How to determine whether a point lies on Quad2DCurve - bezier

I have successfully drawn a Quad2D or Bezier curve in java. I have the equation for the same. But I need to determine whether a particular point(x,y) lies on the curve or not. I tried using Quad2D.contains and a few GeneralPath APIs, I could not get the result accurately.
Can someone help to find out the solution to this?

I think you've meant QuadCurve2D class, which is quadratic Bezier curve.
There seems to be no ready-made method for that, and the problem comes to the distance from the point to the Bezier curve.
Let's P0 will be your point, P1 is a start point, P2 - a control point and P3 is an end point of your curve.
Then point on the curve will be given by
P = B(t)
There is such t, for which distance between P and P0 will be minimal.
F(t) = (B(t)_x - P0_x)^2 + (B(t)_y - P0_y)^2 -> min
If distance is 0 or less than certain error, then P0 is on the curve.
t can be found with Netwon's iterative method by minimizing cost function
t_n = t_n-1 + F'(t) / F''(t)
where F' is first derivative of cost function and F'' is its second derivative.
F'(t) = 2 * (B(t)_x - P0_x) * B'(t)_x + 2 * (B(t)_y - P0_y) * B'(t)_y
F''(t) = 2 * B'(t)_x * B'(t)_x + 2 * (B(t)_x - P0_x) * B''(t)_x +
2 * B'(t)_y * B'(t)_y + 2 * (B(t)_y - P0_x) * B''(t)_y
First derivative of quadratic Bezier curve B'(t) is a line segment with a start point (P2 - P1) and end point (P3 - P2). Second derivative B''(t) is a point P3 - 2 * P2 + P1.
Plugging everything together will give a formula to t for which F(t) is minimal.

Related

Bezier curve, question for the new control point

For a Bezier curve I know the P0,P1 and the
control point P2. (and I can calculate the Q0)
I want to find for a new curve, with Q1(t=0,25) == Q0(t=0,25),
P0==Q0(t=0.25) and P1==Q0(t=0.75),
the new control point P2.
I re-edit my initial post. I've added a picture.
In the picture the blue and red dots are my initial P0 and P1 points and the green dot is the initial control point P2.
Now, I want to find the new control point P2' if I now the purple points P1' and P2'.
In essence I want to draw 2 new curves,
a) from red point to first purple point and
b) from blue point to the second purple point
Any idea?
The question is a bit convoluted but I will give it a shot. To me it seems that OP wants the control points of the segment of the original curve from the parameter value t = 0.25 up to the parameter value t=0.75. This can be achieved using De Casteljau's algorithm twice. Since I haven't found a step-by-step version for quadratic curves on SO, I made one.
Step 0: Take your three control points (note that I name them in a more usual order but I use OP's colour scheme).
Step 1: Use De Casteljau's algorithm for t=0.25. This means that
P_01 = 0.25 * P_0 + (1 - 0.25) * P_1,
P_12 = 0.25 * P_1 + (1 - 0.25) * P_2 and
P_012 = 0.25 * P_01 + (1 - 0.25) * P_12.
Note the purple colour signifying that my P_012 corresponds to the left of OP's purple points.
Step 2: Rename things to simplify writing the second run of the algorithm.
Step 3: Use De Casteljau's algorithm for the second time. But be careful: the parameter value t=0.75 of the original curve corresponds to the parameter value t=2/3 of what is left from it. This means that
P'_01 = 2/3 * P'_0 + (1 - 2/3) * P'_1,
P'_12 = 2/3 * P'_1 + (1 - 2/3) * P'_2 and
P'_012 = 2/3 * P'_01 + (1 - 2/3) * P'_12.
Step 4: Rename things again and pick up the results:
P''_0 is the left of OP's purple points,
P''_1 is the green point OP is looking for and
P''_2 is the right of OP's purple points.

How do I determine the distance between v and PQ when v =[2,1,2] and PQ = [1,0,3]? P = [0,0,0] Q = [1,0,3]

What I have tried already: d = |v||PQ|sin("Theta")
Now, I need to determine what theta is, so I set up a position on a makeshift graph, the graph I made was on the xy plane only as the z plane complicates things needlessly for finding theta. So, I ended up with an acute angle, and if the angle is acute, then I have to find theta which according to dot product facts is greater than 0.
I do not have access to theta, so I used the same princples from cross dots. u * v = |u||v|cos("theta") but in this case, u and v are PQ and v. A vector is a vector, right?
so now I have theta = acos((v*PQ)/(|v||PQ))
with that I get (4sqrt(10))/15 = 32.5125173162 in degrees, so the angle is 32.5125173162 degrees.
So, now that I have theta, I plug it into my distance formula |v||PQ|sin(32.5125173162)
3*sqrt(10)*sin(32.5125173162) = 5.0990195136
or for the sake of simplicity, 5.1
I however want to know if this question is correct.
If it is NOT correct, what can I do to correct it? At what points did I use incorrect information?
This is not a question with a definitive answer in the back of the book, its a question on the side of a page that said: "try this!"
There are a couple of problems with this question.
From the context it looks like you mean for both v and PQ to be vectors. The "distance" between two vectors is an awkward (not well defined) question because vectors are not position bound.
You are using the cross product formula and I have no idea why:
|AxB| = |A||B|Sin(theta)
I think what you are actually trying to do is calculate the distance between the terminal points of the vectors, (2, 1, 2) and (1, 0, 3). Just use the Pythagorean Theorem (extended to 3D) for this.
d = sqrt( (x1 - x2)^2 + (y1 - y2)^2 + (z1 - z2)^2 )
d = sqrt( (2 - 1)^2 + (1 - 2)^2 + (2 - 3)^2 )
d = sqrt( 1^2 + (-1)^2 + (-1)^2 )
d = sqrt(3)
Edit:
If what you need really is the magnitude of the cross product, |AxB| then just find the cross product (using the determinant) and then calculate the magnitude of the result. There is no need for the formula you were using.

How to use improved Euler's method formula to solve an IVP involving population growth?

Hi so I have a problem from my differential equations class that I am having difficulty solving with the improved Euler's method:
The logistic equation for the population (in thousands) of a certain species is given by dP/dt = 2P-2P^2. With t being time variable in years
Given P(0) = .5, with step size h = .2 (so .2 of t), find population at 1 year.
I used the normal Euler's method and got 634 but am not sure how to implement the modified Euler's method on the given differential equation.
The improved Euler method or explicit midpoint method has two stages
Stage one is an Euler step with half the step size
Stage two is the full step with the slope from the point from step one.
So if dP/dt = Q(P) then
k1 = Q(P0)
k2 = Q(P0 + h/2 * k1)
P1 = P0 + h * k2
or
Phalf = P0+h/2*Q(P0)
P1 = P0 + h*Q(Phalf)

orientation of normal surface/vertex vectors

Given a convex 3d polygon (convex hull) How can I determine the correct direction for normal surface/vertex vectors? As the polygon is convex, by correct I mean outward facing (away from the centroid).
def surface_normal(centroid, p1, p2, p3):
a = p2-p1
b = p3-p1
n = np.cross(a,b)
if **test including centroid?** :
return n
else:
return -n # change direction
I actually need the normal vertex vectors as I am exporting as a .obj file, but I am assuming that I would need to calculate the surface vectors before hand and combine them.
This solution should work under the assumption of a convex hull in 3d. You calculate the normal as shown in the question. You can normalize the normal vector with
n /= np.linalg.norm(n) # which should be sqrt(n[0]**2 + n[1]**2 + n[2]**2)
You can then calculate the center point of your input triangle:
pmid = (p1 + p2 + p3) / 3
After that you calculate the distance of the triangle-center to your surface centroid. This is
dist_centroid = np.linalg.norm(pmid - centroid)
The you can calculate the distance of your triangle_center + your normal with the length of the distance to the centroid.
dist_with_normal = np.linalg.norm(pmid + n * dist_centroid - centroid)
If this distance is larger than dist_centroid, then your normal is facing outwards. If it is smaller, it is pointing inwards. If you have a perfect sphere and point towards the centroid, it should almost be zero. This may not be the case for your general surface, but the convexity of the surface should make sure, that this is enough to check for its direction.
if(dist_centroid < dist_with_normal):
n *= -1
Another, nicer option is to use a scalar product.
pmid = (p1 + p2 + p3) / 3
if(np.dot(pmid - centroid, n) < 0):
n *= -1
This checks if your normal and the vector from the mid of your triangle to the centroid have the same direction. If that is not so, change the direction.

How to calculate non-zero dx/dt and dy/dt at t = 0 when P0 == P1 on a cubic Bezier curve?

Before I begin the problem, I use P0, P1, P2, and P3 for the four cubic Bezier points, and 't' since it's parametric. Also, I have searched for a similar problem in this site, as well as Google, and couldn't find one. I apologize if this is a common question.
The problem: I am getting a slope of 0 for both dx/dt and dy/dt for cubic Beziers in these two cases
1: t = 0 and P0 == P1
2: t = 1 and P2 == P3
Here's an example to illustrate (1), where t = 0 and P0 == P1.
Find the tangent (i.e dx/dt and dy/dt) of the following cubic Bezier at t = 0:
(100, 100) (100, 100) (150, 150) (200, 100)
To find the tangent, we'd want the first derivative of the cubic Bezier:
Cubic Bezier definition
B(t) = (1-t)^3P0 + 3t(1-t)^2P1 + 3t^2(1-t)P2 + t^3P3
First derivative of a bezier curve (if you'd like to see the steps I used to get here, let me know)
B'(t) = (-3P0 + 9P1 - 9P2 + 3P3)t^2 + (6P0 - 12P1 + 6P2)t + (-3P0 + 3P1)
Plugging in t = 0 to the first derivative equation, we get
B'(0) = -3P0 + 3P1
And finally, recall that P0 = P1 = (100, 100), so dx/dt and dy/dt are:
dx/dt = dy/dt = -3*(100) + 3*(100) = 0
This tells me...there is no tangent at t = 0 for this cubic Bezier. Which makes no sense if you were to graph and look at it.
What I'm doing to get a non-zero slope is to:
Treat the points P1, P2, and P3 like a quadratic Bezier, convert them into the equivalent cubic Bezier, THEN find the first derivative at t = 0.
Is there any way I can avoid doing that? I'm finding it difficult to accept a tangent that has 0 for dx/dt and dy/dt.
Thanks for your help.
The derivative B'(t) at t = 0 is indeed undefined for case 1 (and at t = 1 for case 2).
To see why this is the case, we can run the de Casteljau algorithm "backwards" on your example to double the parameter range of the curve from t = 0 ... 1 to t = -1 ... 1. This results in the following cubic Bezier curve control points:
(300,400) (0,-100) (100,200) (200,100)
If you plot this curve, you'll see your original curve from t = 0.5 ... 1. You'll also see that there is a cusp at t = 0.5 on this extended curve, right at the beginning of your original. This cusp is why your curve is not differentiable at its starting point.
However, the tangent of the curve is not quite the same thing as the derivative. So if all you need is the tangent, you're in luck. (The derivative is tangent to the curve, but so is any other vector perpendicular to the curve's normal.)
It turns out that the tangents at the ends of the curve are generally equivalent to:
P1 - P0 at t = 0
P3 - P2 at t = 1
However, if (and only if) P0 = P1 and/or P2 = P3, then the tangent at the degenerate point (that is, at t = 0 if P0 = P1 and/or t = 1 if P2 = P3) is equivalent to:
P2 - P1
You can verify that this is the case by evaluating B'(t) as t->0.
In fact, if you split the extended curve in two at t = 0.5 and then apply the P2 - P1 equation to each side, you'll see that there are two different tangents at the cusp. The tangent for each half of the curve point in the exact opposite directions. This is another illustration of why the derivative is undefined at this point.
One final note: your trick of treating the points P1, P2, and P3 like a quadratic Bezier will also give you a correct tangent. However, this will not give you the correct derivative.
This question is already correctly answered but I thought you'd like to know the underlying mathematics:
You are looking to find the end-slopes of a cubic bezier. Since the curve (i.e. its x and y values) is parametric in t, you will differentiate x and y w.r.t. t separately. The pair that you arrive at may be conceived of as the instantaneous "velocity" of a point travelling along the curve. So the point's initial velocity is zero (or more precisely a null-vector) in this case, but (most probably) the acceleration (or failing that, at least the rate of change of acceleration) will be non-zero, and hence the point's velocity will become non-zero (a non-null vector) and hence it will will move from those coordinates and trace out the curve.
But the slope as you visually perceive it is not parametric i.e. it does not depend on the time. I.O.W. what you are looking for is dy/dx, and not the pair (dx/dt, dy/dt), and given that dx/dt and dy/dt both are zero at t=0 for your curve, dy/dx = (dy/dt)/(dx/dt) = 0/0 which is indeterminate. To evaluate this, one must apply L'Hopital's rule. You can get the detailed treatment of the rule from the Wikipedia article but basically it means that to evaluate such indeterminate limits, we can differentiate the numerator f and denominator g separately to get f' and g' and then limit(f/g) is equal to limit(f'/g'). Now if p0, p1, p2 and p3 are the points defining your cubic, then:
dy / dt = ypart ( 3 * ( p1 - p0 ) + 6 * t * ( p2 - 2 * p1 + p0 ) + 3 * t ** 2 * ( p3 - 3 * p2 + 3 * p1 - p0 ) )
dx / dt = xpart ( 3 * ( p1 - p0 ) + 6 * t * ( p2 - 2 * p1 + p0 ) + 3 * t ** 2 * ( p3 - 3 * p2 + 3 * p1 - p0 ) )
-> (dy/dt) / (dx/dt) = ypart ( p1 - p0 ) / xpart ( p1 - p0 )
But this becomes indeterminate when p0 == p1. Now by L'Hopital's rule,
limit(t->0) [ (dy/dt) / (dx/dt) ] = limit(t->0) [ (d2y/dt2) / (d2x/dt2) ]
Now:
d2y/dt2 = ypart ( 6 * ( p2 - 2 * p1 + p0 ) + 6 * t * ( p3 - 3 * p2 + 3 * p1 - p0 ) )
d2x/dt2 = xpart ( 6 * ( p2 - 2 * p1 + p0 ) + 6 * t * ( p3 - 3 * p2 + 3 * p1 - p0 ) )
and at t = 0, (d2y/dt2) / (d2x/dt2) = ypart ( p2 - 2 * p1 + p0 ) / xpart ( p2 - 2 * p1 + p0 )
But since p1 == p0, this becomes: ypart ( p2 - p0 ) / xpart ( p2 - p0 ), which is exactly the result what Naaff told you. Note that if even p2 == p0 (a really degenerate curve, especially if cubic, in which case it will be just a straight line!), then even this will be indeterminate, and you can once more differentiate the numerator and denominator to get:
limit(dy/dx) = limit(t->0) [ (d3y/dt3) / (d3x/dt3) ] = ypart ( p3 - p0 ) / xpart ( p3 - p0 )
I hope it was useful for you... (BTW it doesn't seem as if TeX-like notation works here unlike on math.stackexchange, else I would provide math markup.)