drawing the tangent to the curve knowing the point and gradient - math

I writing a computer program to back up my knowledge of calculus. You can see the web page here
The next thing I want to do is display a tangent to the curve when the user hovers the mouse over the curve.
When that happens, I know exactly the coordinates of the mouse and I can get the derivative which in this case is 2x -2 so if the point is at (1, 1) then the gradient would be 0.
If I was drawing this with pen and paper then I would rearrange the equation into y2-y1 = m(x2 -x1).
I am not entirely sure how to do this with code though.
I tried getting the y intercept and x intercept but the tangent looked wrong:
function getYIntercept(vertex, slope) {
return vertex.y - (slope * vertex.x);
}
const yIntercept = getYIntercept(point, gradient);
const xIntercept = - yIntercept / (gradient);
g.append('line')
.style('stroke', 'red')
.attr('class', 'tangent')
.attr('x1', xScale(point.x))
.attr('y1', yScale(point.y))
.attr('x2', xScale(xIntercept))
.attr('y2', yScale(yIntercept));
};
How better can I plot this line with the information I have?

Finding the Tangent
Let us start with a function f(x).
Calculate f '(x) (the derivative) for future reference.
Then the user indicates some point (x1, y1).
Using f '(x), the slope at this point is m = f '(x1).
Utilizing the Point-Slope formula, the equation for tangent is y-y1 = m(x-x1)
Solve for y:
y = m(x-x1)+y1
Finding the Intercepts
For the x and y intercepts [denoted here as x0 and y0 respectively], simply use the tangent equation. It may be useful to note that the intercepts are (x0,0) and (0,y0) so plugging in zero for the correct variable allows you to find a intercept.
Find the y intercept, so x=0
Thus y = m(0-x1)+y1
Distributing the m leaves y = -m*x1+y1
So y0 = -m*x1+y1 and the y intercept is ( 0, -m*x1+y1 )
This is all that is needed to graph the tangent. But in case you're are curious about the x intercept as well.
Find the x intercept, so y=0
Thus 0 = m(x-x1)+y1
Distributing the m leaves 0 = m*x - m*x1 + y1
Subtracting the x1 and y1 terms yields m*x1-y1 = m*x
Now divide by m so that [ m*x1-y1 ]/m = x
So x0 = [ m*x1-y1 ]/m and the x intercept is ( [ m*x1-y1 ]/m, 0 )
Specifics for this Case
Here are some issues:
(1, 1) is not a point on the function f(x) = x^2 - 2*x + 1
To solve this, you could simply use only the x-value of the point the user hovers over
Alternatively, you could consider graphing the slope field
The x intercept and y intercept are two distinct points, not the x and y value of one point
Once these issues are resolved, you will be able to properly graph the tangent of any function for which you know the first derivative!

Related

Connecting two points with a 3D logarithmic spiral (Julia)

I am calculating points along a three-dimensional logarithmic spiral between two points. I seem to be close, but I think I'm missing a conditional sign flip somewhere.
This code works relatively well:
using PlotlyJS
using LinearAlgebra
# Points to connect (`p2` spirals into `p1`)
p1 = [1,1,1]
p2 = [3,10,2]
# Number of curve revolutions
rev = 3
# Number of points defining the curve
rez = 500 # Number of points defining the line
r = norm(p1-p2)
t = range(0,r,rez)
theta_offset = atan((p1[2]-p2[2])/(p1[1]-p2[1]))
theta = range(0, 2*pi*rev, rez) .+ theta_offset
x = cos.(theta).*exp.(-t).*r.+p1[1];
y = sin.(theta).*exp.(-t).*r.+p1[2];
z = exp.(-t).*log.(r).+p1[3]
# Plot curve points
plot(scatter(x=x, y=y, z=z, marker=attr(size=2,color="red"),type="scatter3d"))
and produces the following plot. Values of the endpoints are shown on the plot, with an arrow from the coordinate to its respective marker. The first point is off, but it's close enough for my liking.
The problem comes when I flip p2 and p1 such that
p1 = [3,10,2]
p2 = [1,1,1]
In this case, I still get a spiral from p2 to p1, and the end point (p1) is highly accurate. However, the other endpoint (p2) is wildly off:
I think this is due to me changing the relative Z position of the two points, but I'm not sure, and I haven't been able to solve this riddle. Any help would be greatly appreciated. (Bonus points if you can help figure out why the Z value on p2 is off in the first example!)
Assuming this is a follow-up of your other question: Drawing an equiangular spiral between two known points in Julia
I assume you just want to add a third dimension to your previous 2D problem using cylindric coordinate system. This means that you need to separate the treatment of x and y coordinate on one side, and the z coordinate on the other side.
First you need to calculate your r on the first two coordinate:
r = norm(p1[1:2]-p2[1:2])
Then, when calculating z, you need to take only the third dimension in your formula (not sure why you used a log function there in the first place):
z = exp.(-t).*(p1[3]-p2[3]).+p2[3]
That will fix your z-axis.
Finally for your x and y coordinate, use the two argument atan function:
julia>?atan
help?> atan
atan(y)
atan(y, x)
Compute the inverse tangent of y or y/x, respectively.
For one argument, this is the angle in radians between the positive x-axis and the point (1, y), returning a value in the interval [-\pi/2, \pi/2].
For two arguments, this is the angle in radians between the positive x-axis and the point (x, y), returning a value in the interval [-\pi, \pi]. This corresponds to a standard atan2
(https://en.wikipedia.org/wiki/Atan2) function. Note that by convention atan(0.0,x) is defined as \pi and atan(-0.0,x) is defined as -\pi when x < 0.
like this:
theta_offset = atan( p1[2]-p2[2], p1[1]-p2[1] )
And finally, like in your previous question, add the p2 point instead of the p1 point at the end of x, y, and z:
x = cos.(theta).*exp.(-t).*r.+p2[1];
y = sin.(theta).*exp.(-t).*r.+p2[2];
z = exp.(-t).*(p1[3]-p2[3]).+p2[3]
In the end, I have this:
using PlotlyJS
using LinearAlgebra
# Points to connect (`p2` spirals into `p1`)
p2 = [1,1,1]
p1 = [3,10,2]
# Number of curve revolutions
rev = 3
# Number of points defining the curve
rez = 500 # Number of points defining the line
r = norm(p1[1:2]-p2[1:2])
t = range(0.,norm(p1-p2), length=rez)
theta_offset = atan( p1[2]-p2[2], p1[1]-p2[1] )
theta = range(0., 2*pi*rev, length=rez) .+ theta_offset
x = cos.(theta).*exp.(-t).*r.+p2[1];
y = sin.(theta).*exp.(-t).*r.+p2[2];
z = exp.(-t).*(p1[3]-p2[3]).+p2[3]
#show (x[begin], y[begin], z[begin])
#show (x[end], y[end], z[end]);
# Plot curve points
plot(scatter(x=x, y=y, z=z, marker=attr(size=2,color="red"),type="scatter3d"))
Which give the expected results:
p2 = [1,1,1]
p1 = [3,10,2]
(x[begin], y[begin], z[begin]) = (3.0, 10.0, 2.0)
(x[end], y[end], z[end]) = (1.0001877364735474, 1.0008448141309634, 1.0000938682367737)
and:
p1 = [1,1,1]
p2 = [3,10,2]
(x[begin], y[begin], z[begin]) = (0.9999999999999987, 1.0, 1.0)
(x[end], y[end], z[end]) = (2.9998122635264526, 9.999155185869036, 1.9999061317632263)
In 2D, let us assume the pole at the point C, and the spiral from P to Q, corresponding to a variation of the parameter in the interval [0, 1].
We have
X = Cx + cos(at+b).e^(ct+d)
Y = Cy + sin(at+b).e^(ct+d)
Using the known points,
Px - Cx = cos(b).e^d
Py - Cy = sin(b).e^d
Qx - Cx = cos(a+b).e^(c+d)
Qy - Cy = sin(a+b).e^(c+d)
From the first two, by a Cartesian to polar transformation (and logarithm), you can obtain b and d. From the last two, you similarly obtain a+b and c+d, and the spiral is now defined.
For the Z coordinate, I cannot answer precisely as you don't describe how you generalize the spiral to 3D. Anyway, we can assume a certain function Z(t), that you can map to [Pz, Qz] by the linear transformation
(Qz - Pz) . (Z(t) - Z(0)) / (Z(1) - Z(0)) + Pz.

Understanding & Deriving Jacobian Determinant Scaling Factor

I have been trying to understand Jacobian Determinant.
I hope someone is able to give me a pointer.
Most material that I found on Internet didn't provide
derivation of Jacobian Determinant.
One such web site is:
http://tutorial.math.lamar.edu
(Which I find quite good, otherwise.)
I spent a lot of time trying to deepen my understanding of
Jacobian Determinant.
I played with Transformations that define uv-axes and
how integration of a function over a Region/area would work
with the Transformations.
For example, when I started with simple Transformations of:
u = ( x - y )/√2
v = ( x + y )/2√2
which is uv-axes rotated -45° from Cartesian xy-axes,
and with v-axis at 2 times the scale,
that is, v = 1 maps to 2 units length in xy-coords.
So, I say that uscale = 1, vscale = 2,
for the above transformations.
With this uv-axes, I can simplify a 10x20 rectangle Region
which is rotated at 45° from x-axis,
such that the longer dimension points at 45° from x-axis.
With such examples, I begin to develop intuition
how Jacobian Determinant works.
I understand Jacobian Determinant to be a Scaling Factor
to convert area measurement in uv-axes to xy-dimensions.
Area measurement in uv-axes is given simply by formula
Δu x Δv, where Δu = 10, Δv = 10, because vscale = 2).
Jacobian Determinant Scaling Factor = uscale x vscale
(quite intuitively).
Area in xy-dimensions = Δu x Δv x (uscale x vscale)
= 10 x 10 x 1 x 2 = 200.
Integration of volume over such a simpler uv Square,
could be easier than over the same xy Region,
appearing at an angle.
With the above initial understanding,
I am trying to work out how Jacobian Determinant is derived.
Deriving from the above Transformations formula:
dx/du = √2 / 2
dx/dv = √2
dy/du = -√2 / 2
dy/dv = √2
I can also derive from Geometry that:
dx/du = uscale cos Θ
dy/du = uscale sin Θ
dx/dv = vscale cos (90° - Θ)
dy/dv = vscale sin (90° - Θ)
I could get:
areaInXY / areaInUV = uscale x vscale
which matches my understanding.
However, Jacobian Determinant formula is:
∂(x, y) / ∂(u, v) = ∂x/∂u ∂y/∂v - ∂x/∂v ∂y/∂u
= uscale * vscale * cos 2Θ
This leaves me quite puzzled why I have the extra cos 2Θ factor
which isn't making intuitive sense -- why would the
area Scaling Factor depends on how the rectangle is rotated
and thus how uv-axes are rotated?!
Anybody can see where my reasoning went wrong above?
Let me try to explain what basically the Jacobian determinant does. This is true in general for smooth functions mapping from R^n to R^n, but for the sake of simplicity, assume we are working on R^2. Let F(x,y) a smooth R^2 to R^2 function. Then we can say that F(x,y) sends the x coordinate to f1(x,y) and the y coordiate to f2(x,y) at point (x,y). Then think about an infinitesimal rectangular area, defined by the points (x,y),(x+dx,y),(x,y+dy) and (x+dx,y+dy). Now, the area of this infinitesimal rectangle is dxdy. What happens to this rectangle when it goes through the F(x,y) transformation? We apply F(x,y) to each of the four coordinates and obtain the following points:
A:(x,y)->(f1(x,y),f2(x,y))
B:(x+dx,y) -> (f1(x+dx,y),f2(x+dx,y)) (approx.)= (f1(x,y) + (∂f1/∂x)dx,f2(x,y) + (∂f2/∂x)dx)
C:(x,y+dy) -> (f1(x,y+dy),f2(x,y+dy)) (approx.)= (f1(x,y) + (∂f1/∂y)dy,f2(x,y) + (∂f2/∂y)dy)
D:(x+dx,y+dy) -> (f1(x+dx,y+dy),f2(x+dx,y+dy)) (approx.)=(f1(x,y) + (∂f1/∂x)dx + (∂f1/∂y)dy,f2(x,y) + (∂f2/∂x)dx + (∂f2/∂y)dy)
The equalities are approximately equal and exactly hold in the limit where dx and dy goes to 0, they are the best linear approximation to the function F at new points. (We obtain these from the first order parts of the Taylor approximation of the functions f1 and f2).
If we look to the new (approximated) area under the transformation F(x,y), we see the new distance vectors between the transformed points a:
B-A:((∂f1/∂x)dx,(∂f2/∂x)dx)
C-A:((∂f1/∂y)dy,(∂f2/∂y)dy)
D-C:((∂f1/∂x)dx,(∂f2/∂x)dx)
D-B:((∂f1/∂y)dy,(∂f2/∂y)dy)
As you can see, the newly transformed infinitesimal area is a parallelogram. Let:
u=((∂f1/∂x)dx,(∂f2/∂x)dx)
v=((∂f1/∂y)dy,(∂f2/∂y)dy)
These vectors constitute the edges of our parallelogram. It can be shown with the help of the cross product between u and v, that the area of the parallelogram is:
area^2 = (u1v2 - u2v1)^2 = ((∂f1/∂x)(∂f2/∂y)dxdy - (∂f2/∂x)(∂f1/∂y)dxdy)^2
area^2 = ((∂f1/∂x)(∂f2/∂y) - (∂f2/∂x)(∂f1/∂y))^2 (dxdy)^2
area = |(∂f1/∂x)(∂f2/∂y) - (∂f2/∂x)(∂f1/∂y)|dxdy (dx and dy are positive)
area = |det([∂f1/∂x, ∂f1/∂y],[∂f2/∂x, ∂f2/∂y])|dxdy
So, the matrix we are going to take the determinant of is simply the Jacobian matrix. Like I said in the beginning, this derivation can be extended to arbitrary dimensions of n,given the coordinate transformation function F is smooth and the Jacobian matrix is hence invertible, with non-zero determinant.
A good visual explanation of this is given at: http://mathinsight.org/double_integral_change_variables_introduction

Standard form of ellipse

I'm getting ellipses as level curves of a fit dataset. After selecting a particular ellipse, I would like to report it as a center point, semi-major and minor axes lengths, and a rotation angle. In other words, I would like to transform (using mathematica) my ellipse equation from the form:
Ax^2 + By^2 + Cx + Dy + Exy + F = 0
to a more standard form:
((xCos[alpha] - ySin[alpha] - h)^2)/(r^2) + ((xSin[alpha] + yCos[alpha] - k)^2)/(s^2) = 1
where (h,k) is the center, alpha is the rotation angle, and r and s are the semi-axes
The actual equation I'm attempting to transform is
1.68052 x - 9.83173 x^2 + 4.89519 y - 1.19133 x y - 9.70891 y^2 + 6.09234 = 0
I know the center point is the fitted maximum, which is:
{0.0704526, 0.247775}
I posted a version of this answer on Math SE since it benefits a lot from proper mathematical typesetting. The example there is simpler as well, and there are some extra details.
The following description follows the German Wikipedia article Hauptachsentransformation. Its English counterpart, according to inter-wiki links, is principal component analysis. I find the former article a lot more geometric than the latter. The latter has a strong focus on statistical data, though, so it might be useful for you nevertheless.
Rotation
Your ellipse is described as
[A E/2] [x] [x]
[x y] * [E/2 B] * [y] + [C D] * [y] + F = 0
First you identify the rotation. You do this by identifying the eigenvalues and eigenvectors of this 2×2 matrix. These eigenvectors will form an orthogonal matrix describing your rotation: its entries are the Sin[alpha] and Cos[alpha] from your formula.
With your numbers, you get
[A E/2] [-0.74248 0.66987] [-10.369 0 ] [-0.74248 -0.66987]
[E/2 B] = [-0.66987 -0.74248] * [ 0 -9.1715] * [ 0.66987 -0.74248]
The first of the three factors is the matrix formed by the eigenvectors, each normalized to unit length. The central matrix has the eigenvalues on the diagonal, and the last one is the transpose of the first. If you multiply the vector (x,y) with that last matrix, then you will change the coordinate system in such a way that the mixed term vanishes, i.e. the x and y axes are parallel to the main axes of your ellipse. This is just what happens in your desired formula, so now you know that
Cos[alpha] = -0.74248 (-0.742479398678 with more accuracy)
Sin[alpha] = 0.66987 ( 0.669868899516)
Translation
If you multiply the row vector [C D] in the above formula with the first of the three matrices, then this effect will exactly cancel the multiplication of (x, y) by the third matrix. Therefore in that changed coordinate system, you use the central diagonal matrix for the quadratic term, and this product for the linear term.
[-0.74248 0.66987]
[1.68052, 4.89519] * [-0.66987 -0.74248] = [-4.5269 -2.5089]
Now you have to complete the square independently for x and y, and you end up with a form from which you can read the center coordinates.
-10.369x² -4.5269x = -10.369(x + 0.21829)² + 0.49408
-9.1715y² -2.5089y = -9.1715(y + 0.13677)² + 0.17157
h = -0.21829 (-0.218286476695)
k = -0.13677 (-0.136774259156)
Note that h and k describe the center in the already rotated coordinate system; to obtain the original center you'd multiply again with the first matrix:
[-0.74248 0.66987] [-0.21829] [0.07045]
[-0.66987 -0.74248] * [-0.13677] = [0.24778]
which fits your description.
Scaling
The completed squares above contributed some more terms to the constant factor F:
6.09234 + 0.49408 + 0.17157 = 6.7580
Now you move this to the right side of the equation, then divide the whole equation by this number so that you get the = 1 from your desired form. Then you can deduce the radii.
1 -10.369
-- = ------- = 1.5344
r² -6.7580
1 -9.1715
-- = ------- = 1.3571
s² -6.7580
r = 0.80730 (0.807304599162099)
s = 0.85840 (0.858398019487315)
Verifying the result
Now let's check that we didn't make any mistakes. With the parameters we found, you can piece together the equation
((-0.74248*x - 0.66987*y + 0.21829)^2)/(0.80730^2)
+ (( 0.66987*x - 0.74248*y + 0.13677)^2)/(0.85840^2) = 1
Move the 1 to the left side, and multiply by -6.7580, and you should end up with the original equation. Expanding that (with the extra precision versions printed in parentheses), you'll get
-9.8317300000 x^2
-1.1913300000 x y
+1.6805200000 x
-9.7089100000 y^2
+4.8951900000 y
+6.0923400000
which is a perfect match for your input.
If you have h and k, you can use Lagrange Multipliers to maximize / minimize the function (x-h)^2+(y-k)^2 subject to the constraint of being on the ellipse. The maximum distance will be the major radius, the minimum distance the minor radius, and alpha will be how much they are rotated from horizontal.

How to get a vector field that maps the slopes of an equation

Hey so I'm reading this article by Chris Hecker where he has an image of a Parabola surrounded by the a vector field of it's derivative:
However he never mentions how exactly he got the vector field equation, and never even states it. He does say he overlayed the vector field of the slopes in Figure 1, by drawing the solution to the slope equation, dy/dx = 2x, as a short vector at each coordinate on the grid.
How do you create a vector field of the slopes of an equation in the vector field syntax of
V = xi + yj
The Figure title would be clearer if it read:
The curve y = x^2, and the vector field dy/dx = 2x for the general case y = x^2 + C
There are three equations at work in the graph above:
y = x^2 - The equation for the parabola drawn - This is the one long solid curve
y = x^2 + C -The equation for all parabolas that fit on the vector field - C is a constant. This is the equation for all parabolas that fit on that vector field
dy/dx = 2x The equation for the slope field. - This is the slope or derivative of the both the curve drawn and all the possible curves that can be drawn with y = x^2 + C for all constant Cs.
Note that C is a constant, since the derivative of y = x^2 + C with any C is 2x. So the vector field shows how to draw all the different parabolas with different Cs.
So there are two ways to calculate the vector field:
Iterate over your desired range of x and y and calculate the slope, dy/dx- 2x independent of y in this case - at each point. This is how the author did it.
Draw a bunch of parabolas by slowly varying C in y = x^2 + C over a desired range of - let's say - x calculating y.
For a differential equation dy/dx = f(x,y) (e.g., dy/dx = 2x in this case, with f(x,y) = 2x), the vector field (F) will be F = i + f(x,y)j (so in your case, F = i + 2x j )

Simulating movement in 2D

I need assistance in simulating movement between 2 points in a plane. Consider two points P1:(x,y1) and P2:(x2,y2). I compute the distance between P1 and P2, say D, and I choose a random velocity, say V. Next, I compute the time required to move from P1 to P2, say T. Finally, I compute the equation of the straight line between P1 and P2 as y = mx + b.
For example, let T = 10 seconds. For the first 9 seconds, I would like to generate points per second on the straight line until I reach point P2 at the 10th second. Could you please assist me in doing so.
The best approach is to use parametric equations
x = x1 + t*(x2 - x1)
y = y1 + t*(y2 - y1)
where t is the "time" parameter going from 0 to 1 (0.5 means for example halfway).
If you also like your movement to be "soft" (starting from zero velocity, then accelerating then slowing down and stopping on the arrival point) you can use this modified equation
w = 3*t*t - 2*t*t*t
x = x1 + w*(x2 - x1)
y = y1 + w*(y2 - y1)
The following is a plot of the w curve compared to a linear distribution t with 11 points (t=0.0, 0.1, ... 0.9, 1.0):

Resources