Conditions for smooth cubic bezier curve - bezier

I have the start and end points and the values of the slope of the curve at those points.
Now I have to draw a "smooth 2D bezier curve" through the two given points.
Now how to locate the two control points to achieve this. Is there any way for it? I know that the control points must lie on the tangents at the respective start and end points.
Note:By "smooth curve", I meant that there should be no steep curves or turnings in the final plot.

It sounds like you have catmull-rom curve coordinates (two points, and their departure and arrival tangents), in which case https://pomax.github.io/bezierinfo/#catmullconv covers all the math necessary to convert those to Bezier coordinates. And if you don't care about the "how", just skip to the end of the section for the straight up conversion rules.
tl;dr version: rewrite your coordinates to Catmull form:
[P1, v1, v2, P2] -> [P1 - v1, P1, P2, P2 + v2]
Then we convert that to Bezier coordinates:
P1 <= P1
p2 <= P1 - (P2 - P1 - v1) / 6 * f
p3 <= P2 + (P2 + v2 - P1) / 6 * f
p4 <= P2
the f is a tension constant. Play around with that. It's usually 1, but it might not be depending on how strong those tangents were.

For a cubic Bezier curve defined by P0, P1, P2 and P3 where P0 and P3 are the start point and end point, its first derivative vector at t=0 and t=1 are
C'(t=0) = 3*(P1-P0)
C'(t=1) = 3*(P3-P2)
So, if you already know the slope at the start and end point, you can easily convert that to tangent vectors and find the control points P1 and P2. You do need to assign a proper magnitude for the first derivative vectors so that the final resulting curve does not have inflection point. But as long as you make sure the resulting control polygon formed by P0, P1, P2 and P3 are convex, then your cubic Bezier curve should be smooth and has no turnnings.

Related

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.

finding a minimum distance

I need to find a point or points on the given circle (or curve) which minimizes d0+d1? the radius and center of the curve are (0,0) and 'r' respectively and the coordinates of points A and B are known. Let say A=(x1,y1) and B=(x1,-y1) and r> sqrt(x1^2+y1^2) . C is unknown point of the circle which should minimize the length d0+d1
d0 - the distance between A to C on the circle
d1- the distance between B to C on the circle
point C moves along the circle. I need to find a point or points on the given circle (or curve) which minimizes d0+d1?
If the line AB intersects the circle, then C is that intersection point (note that there can be two intersection points and both give an equal distance d0+d1 !).
If AB does not intersect the circle, then C is the point on the circle intersecting an imaginary line from the point on the line AB closest to the circle center.
There are many articles online about how to find the point on a line closest to another point, and how to find the intersection between two lines, which would solve the second case. For the first case you can google "line circle intersection"
The general case is very complicated, but the special situation
A=(x1,y1) and B=(x1,-y1) and r > sqrt(x1^2+y1^2)
with a circle whose centre is the origin has enough symmetries to make the solution at least in some circumstances accessible. I'm assuming A ≠ B, (equivalently y1 ≠ 0), otherwise the problem is trivial for a circle.
Let dist(P,Q) be the Euclidean distance between the points P and Q. The (closed) line segment connecting A and B is the locus of points P with
dist(P,A) + dist(P,B) = dist(A,B)
For D > dist(A,B), the locus of points with
f(P) = dist(P,A) + dist(P,B) = D
is an ellipse E(D) whose foci are A and B. Let P be a point on the circle and D = f(P).
If the tangents to the circle and to the ellipse E(D) in the point P don't coincide, P is neither a local minimum nor a local maximum of f restricted to the circle.
If the tangents coincide, and the curvature of the circle is larger than the curvature of E(D) in P, then P is an isolated local maximum of f restricted to the circle.
If the tangents coincide, and the curvature of the circle is smaller than the curvature of E(D) in P, then P is an isolated local minimum of f restricted to the circle.
If the tangents coincide and the curvature of the circle is equal to the curvature of E(D) in P, then
P is an isolated local minimum of f restricted to the circle if dist(P,A) = dist(P,B),
P is neither a local maximum nor a local minimum of f restricted to the circle otherwise.
First, if x1 = 0, it is easily seen (in case it is not geometrically obvious) that the points on the circle minimising f are the points with x-coordinate 0, i.e. P1 = (0,r) and P2 = (0,-r). [That would even be true if r² ≤ x1² + y1².]
Now, suppose x1 ≠ 0, without loss of generality x1 > 0. Then it is obvious that a point P = (x,y) on the circle minimising f must have x > x1. By the symmetry of the situation, the point R = (r,0) must either be a local minimum or a local maximum of f restricted to the circle.
Computing the behaviour of f near R, one finds that R is a local minimum if and only if
r ≥ (x1² + y1²) / x1
Since R is a point of smallest curvature of E(f(R)) (and the tangents in R to E(f(R)) and the circle coincide), R is then also the global minimum.
If r < (x1² + y1²) / x1, then R is a local maximum of f restricted to the circle. Then f has two global minima on the circle, with the same x-coordinate. Unfortunately, I don't have a nice formula to compute them, so I can't offer a better way than an iterative search.

joining two bezier curves

i have two bezier curves placed at a distance apart in space.
curve 1 has control points A0, A1,A2, A3. A0 and A3 lie on curve and are its end points
Curve 2 has control points C0,C1, C2, C3 . C0 and C3 lie on curve.and are its end points
i want to join the two curves A and C with an intermediate bezier curve B. the intermediate Curve B has control points A3 and C0 which lie on the curve and are its end points. the intermediate control points B1 and B2 are unknown to me. also the joining should be smooth enough. please help as to how to proceed. have read alot about beziers but dont know how to do this.
thanks and regards,
Gauri
B1 will be: B1x = 2 * A3x - A2x; B1y = 2 * A3y - A2y;
B2 will be: B2x = 2 * C0x - C1x; B2y = 2 * C0y - C1y;
This should give you perfectly smooth join.
#Arty
You are correct but this will only assure a "smooth enough" join.
To achieve a better looking join of those 2 curves you must also have 2nd derivative equals at the junction points. I place this here for those that might need this piece of information.

Cubic bezier curves - get Y for given X

I have a cubic bezier curve where the first and last points are given (namely P0(0,0) and P3(1,1)).
The other two points are defined like this: cubic-bezier(0.25, 0.1, 0.25, 1.0) (X1, Y1, X2, Y2, also those values must not be smaller or larger than 0 or 1, respectively)
Now what would I have to do to get the Y coordinate for a given X, assuming there's only one? (I know that under certain circumstances there can be multiple values, but let's just put them aside. I'm not doing rocket science over here, I just want to be able to get Y multiple times per second to do transitions)
I managed to dig up this: y coordinate for a given x cubic bezier, but I don't understand what xTarget stands for.
Oh, also this is no homework whatsoever, I'm just a bit annoyed at the fact that there's no comprehensible stuff about cubic bezier curves on the internet.
If you have
P0 = (X0,Y0)
P1 = (X1,Y1)
P2 = (X2,Y2)
P3 = (X3,Y3)
Then for any t in [0,1] you get a point on the curve given by the coordinates
X(t) = (1-t)^3 * X0 + 3*(1-t)^2 * t * X1 + 3*(1-t) * t^2 * X2 + t^3 * X3
Y(t) = (1-t)^3 * Y0 + 3*(1-t)^2 * t * Y1 + 3*(1-t) * t^2 * Y2 + t^3 * Y3
If you are given an x value, then you need to find which t values in [0,1] correspond to that point on the curve, then use those t values to find the y coordinate.
In the X(t) equation above, set the left side to your x value and plug in X0, X1, X2, X3. This leaves you with a cubic polynomial with variable t. You solve this for t, then plug that t value into the Y(t) equation to get the y coordinate.
Solving the cubic polynomial is tricky but can be done by carefully using one of the methods to solve a cubic polynomial.
P0 is your first point in the curve where t=0
P3 is your last point in the curve where t=1
P1 and P2 are your control points.

How to determine whether a point lies on Quad2DCurve

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.