Splitted Bezier curve - bezier

Suppose I splitted a cubic bezier curve at the point corresponding to the parameter t=0.5. Call the splitted parts C and D. Then I connect ends of C by a straight line segment. Can we say that this straight line segment never touches C apart from the endpoints?

No. This is because the split portion C and D are also a cubic Bezier curve, which can be of any shape (that a cubic polynomial curve can be). A straight line connecting two ends of a cubic Bezier curve could have intersected the curve at the interior if the cubic Bezier curve is not convex.
If you want to produce an example, you will have to make the control points going up and down drastically as shown in the following example (where the green dots are control points and the yellow dot is where t=0.5).
A close-up on where t=0.5 shows

No, because as I understand it, a straight line is a degenerate case of a Bezier curve.
So you would need to ensure, for example, that the control points are not on the line.
If the also happens to be that both points are on the same side of the line (e.g. either both above, both below, both to the left or both to the right), then that would do it.
If you don't have the control points, but have two points near the endpoints of the line, you can do the same test.
Or in other words the case where you might need to worry about is when either the control points or points near the endpoints are on in different side of the line between the endpoints.

Related

How to find a point on a b-spline that is on the normal plane of a point on another b-spline using goemdl / nurbs

So the first problem will be explaining what I am after clearly.
I have two non-rational 3D b-splines. The first b-spline it the guiding spline. The second b-spline is a reference and it is essentially 'inside' of the first spline. ( the splines were generated in Solidworks )
Imagine a circular playground slide. The first spline is the center line of the slide. The second spline is the inside edge of the slide.
The inside spline will tend to be shorter than the center spline. The inside will also tend to have more curvature at any given point than the center.
The path of the slide is not perfectly circular. But the inside spline is always 'parallel' to the outside. ( very liberal use of the word parallel here )
What I am after:
Given a point along the center curve, I would like to find the point on the inside curve that is on the plane that is defined by the normal to the tangent of the center spline at that point.
Where I am at:
I am using the geomdl library in python to manipulate the splines.
I can choose a distance along the center spline and from geomdl I get the 3D point and the tangent vector (A,B,C) of that point and therefore the plane at that point that is normal to the spline at that point.
What I am doing:
From the tangent vector and the point I compute the equation of the plane in the form of:
Ax + By + Cz = D.
From there I guess at the point at the same distance on the inside spline and plug it into the equation for the plane that I already have. I use the error in D to guess at which way I should bump my guess on where the point on the inside curve might really be.
[ I understand that over the entire length of the two splines there may be more than one solution. i.e. if the curve wraps more than 180° there would be more than one point on the inside curve that lands on the plane defined by the center curve. In the local area that i am interested in this will not be a problem. Any second point would also be a long ways away from the center line. i.e. the correct point will be no more than 25 mm from the center point. A non-local point will be at least 3000 mm away. ]
This mostly works. But from time to time it fails. i.e. if D is very near 0 my guesses will diverge from the answer.
Currently I make 10 guesses, each guess having a smaller delta guess than the last.
I have a great number of these points to evaluate. My solution requires 10 X the number of calculations so it is not terribly efficient.
From my Google searches I believe that using the error in D in the equation of a plane may not be correct. I 'think' that D is the distance of the plane to the origin.(yes /no?) Therefore I am really comparing the distance of the two planes from the origin and not really from each other. If my guess happens to be on the "other side" of the origin then the distance's may be the same but opposite.
My Question:
What is the correct way to go about this?
Is my assumption that D is the distance from the plane to the origin?
Is driving the error in D between the two points valid?
What is the correct way to do this?
Restate my question in different terms
Given a plane (Ax + By + Cz = D) how do I find the point on a given b-spline that pierces ( or is coincident to ) that plane (using geomdl.bcurve)?
( I am very much in over my head here so please forgive if this does not make sense )

How to choose control point distance for 3D cubic Bézier curves to optimize 'roundness'?

Say I want to construct a 3D cubic Bézier curve, and I already have both end-points, and the direction (normal vector) for both control points. How can I choose the distance of both control points to their respective end-points in order to make the curve as 'nicely rounded' as possible?
To formalize 'nicely rounded': I think that means maximizing the smallest angle between any two segments in the curve. For example, having end-points (10, 0, 0) and (0, 10, 0) with respective normal vectors (0, 1, 0) and (1, 0, 0) should result in a 90° circular arc. For the specific case of 2D circular arcs, I've found articles like this one. But I haven't been able to find anything for my more general case.
(Note that these images are just to illustrate the 'roundness' concept. My curves are not guaranteed to be plane-aligned. I may replace the images later to better illustrate that point.)
This is a question of aesthetics, and if the real solution is unknown or too complicated, I would be happy with a reasonable approximation. My current approximation is too simplistic: choosing half the distance between the two end-points for both control point distances. Someone more familiar with the math will probably be able to come up with something better.
(PS: This is for open-source software, and I would be happy to give credit on GitHub.)
Edit: Here are some other images to illustrate a 3D case (jsfiddle):
Edit 2: Here's a screenshot of an unstable version of ApiNATOMY to give you an idea of what I'm trying to do. I'm creating 3D tubes to represent blood-vessels, connecting different parts of an anatomical schematic:
(They won't let me put in a jsfiddle link if I don't include code...)
What you are basically asking is to have curvature over the spline as constant as possible.
A curve with constant curvature is just a circular arc, so it makes sense to try to fit such an arc to your input parameters. In 2D, this is easy: construct the line which goes through your starting point and is orthogonal to the desired direction vector. Do the same for the ending point. Now intersect these two lines: the result is the center of the circle which passes through the two points with the desired direction vectors.
In your example, this intersection point would just be (0,0), and the desired circular arc lies on the unit circle.
So this gives you a circular arc, which you can either use directly or use the approximation algorithm which you have already cited.
This breaks down when the two direction vectors are collinear, so you'd have to fudge it a bit if this ever comes up. If they point at each other, you can simply use a straight line.
In 3D, the same construction gives you two planes passing through the end points. Intersect these, and you get a line; on this line, choose the point which minimizes the sum of squared distances to the two points. This gives you the center of a sphere which touches both end points, and now you can simply work in the plane spanned by these three points and proceed as in 2D.
For the special case where your two end points and the two known normal vector for the control points happen to make the Bezier curve a planar one, then basically you are looking for a cubic Bezier curve that can well approximate a circular arc. For this special case, you can set the distance (denoted as L) between the control point and their respective end point as L = (4/3)*tan(A/4) where A is the angle of the circular arc.
For the general 3D case, perhaps you can apply the same formula as:
compute the angle between the two normal vectors.
use L=(4/3)*tan(A/4) to decide the location of your control points.
if your normals are aligned in a plane
What you're basically doing here is creating an elliptical arc, in 3D, where the "it's in 3D" part is completely irrelevant, since it's just a 2D curve, rotated/translated to sit in your 3D space. So let's just solve the 2D case, and then the RT is entirely up to you.
Creating the "perfect" cubic Bezier between two points on an arc comes with limitations. You basically can't create good looking arcs that span more than a quarter circle. So, with that said: your start and end point normals give you a 2D angle between your normal vectors, which is the same angle as between your start and end tangents (since normals are perpendicular to tangents). So, let's:
align our curve so that the tangent at the start is 0
plug the angle between tangents into the formula given in the section on Circle approximation in the Primer on Bezier curves. This is basically just dumb "implementing the formula for c1x/c1y/c2x/c2y as a function that takes an angle as argument, and spits out four values as c1(x,y) and c2(x,y) coordinats".
There is no step 3, we're done.
After step 2, you have your control points in 2D to create the most circular arc between a start and end point. Now you just need to scale/rotate/translate it in 3D so that it lines up with where you needed your start and end point to begin with.
if your normals are not aligned in a plane
Now we have a problem, although one that we can deal with by treating the dimensions as separate things entirely. Instead of creating a single 2D curve, we're going to create three: one that's the X/Y projection, one that's the X/Z projection, and one that's the Y/Z projection. For all three of these, we're going to abstract the control points in exactly the same way as before, and then we simply take the projective control points (three for each control point), and then go "okay, we now have X, Y, and Z projective coordinates. That means we have (X,Y,Z) coordinates", and done again.

ccBezierConfig as a quadratic, not cubic.

So I'm trying to animate a sprite, and I just found the CCBezierBy/CCBezierTo methods, which are saving me a lot of trouble, but they only work as cubic functions.
HOw can I make them quadratics? (I need s-curves)
Having only 3 controlpoints limits severely what you can do.
Thank you.
I don't think you understand Bezier curves here: S curves cannot be modeled by quadratic Beziers, they can only do curves with a single inflection point. Cubic curves can have two inflection points, so quadratic curves can only model curves that look like | or C, and cubic curves can model anything that looks like |, C or S
Cubic functions have a starting on-curve point, two control points, and an ending on-curve point, for a total of four control points; Quadratic functions have a starting on-curve point, one control point, and an ending on-curve point, for a total of three control points.
So what you want is a cubic curve, and that's exactly what the CCBezierBy/CCBezierTo methods offer. They let you specify a bezier curve as the two control points and end point, because you'll already have the starting point.

Find bezier control-points for curve passing through N points

Considering the following nice solution for finding cubic Bézier control points for a curve passing through 4 points:
How to find control points for a BezierSegment given Start, End, and 2 Intersection Pts in C# - AKA Cubic Bezier 4-point Interpolation
I wonder, if there is a straightforward extension to this for making the Bézier curve pass through N points, for N > 2 and maybe N ≤ 20?
This is a really old question, but I'm leaving this here for people who have the same question in the future.
#divanov has mentioned that there's no Bezier curve passing through N arbitrary points for N >4.
I think the OP was asking how to compute the control points to join multiple bezier curves to produce a single curve that looks smooth.
This pdf will show you how to compute the control points: http://www.math.ucla.edu/~baker/149.1.02w/handouts/dd_splines.pdf
which I found on this writeup https://developer.squareup.com/blog/smoother-signatures/ from Square about how they render a smooth curve that passes through all the sampled points of a mouse drawn signature.
In general, there is no Bezier curve passing through N arbitrary points, where N > 4. One should consider curve fitting to minimize least square error between computed Bezier curve and given N data points. Which is discussed, for example, here.

The intersection point between a spline and a line

I'm trying to find a way to calculate the intersection between a b-spline and a straight line. So far Google hasn't been much help.
A pure mathematical approach:
Transform the spline and the line so that the line lies on the X axis.
Calculate the points on the spline where Y = 0 (depends on the order of the spline).
Transform these points back to your original cordinate system.
If this is the way you are going I can work out the necessary formulas.
The most efficient algorithm that I've heard of is called Bezier clipping.
Here's a book chapter on curve and spline intersection (pdf).
Your best approach might be to break down your spline into individual line segments and test each line segment for intersection with the line. The spline may intersect the line in more than one point, so you'll also have to decide which one you're interested in.