Algorithm for inserting points in a piecewise-cubic Bézier path - algorithm

I'm looking for an algorithm to insert a new control point on a Bézier curve, without deforming.
Does anybody know a library or reference for Bézier algorithms (insertion, optimize, de Casteljau ...)?

This is called the "knot insertion problem". For Bézier curves, the de Casteljau algorithm will give you the right answer. Here is the simple algorithm for a degree 3 Bézier.
Say you want to insert a knot at a fraction t of the parameter space inside the Bézier curve defined by P0, P1, P2, P3. Here's what you do:
P0_1 = (1-t)*P0 + t*P1
P1_2 = (1-t)*P1 + t*P2
P2_3 = (1-t)*P2 + t*P3
P01_12 = (1-t)*P0_1 + t*P1_2
P12_23 = (1-t)*P1_2 + t*P2_3
P0112_1223 = (1-t)*P01_12 + t*P12_23
Then your first Bézier will be defined by: P_0, P0_1, P01_12, P0112_1223; your second Bézier is defined by: P0112_1223, P12_23, P2_3, P3.
The geometrical interpretation is simple: you split each segment of the Bézier polygon at fraction t, then connect these split points in a new polygon and iterate. When you're left with 1 point, this point lies on the curve and the previous/next split points form the previous/next Bézier polygon. The same algorithm also works for higher degree Bézier curves.
Now it can get trickier if you want to insert the control point not at a specific value of t but at a specific location in space. Personally, what I would do here is simply a binary search for a value of t that falls close to the desired split point... But if performance is critical, you can probably find a faster analytic solution.

You could also take the mathematical approach.
A qubic Bézier curve with control points can be written as:
Its derivative w.r.t. is
To limit the curve from to , you get new control points :
Proof
Substituting
We get
The first and last points of the sub-curve are the first and last new control points
And the tangent at those points is
So

Adding this for completeness.
An open-source implementation of many Bézier path operations can be found inside GIMP source code, in gimpbezierstroke.c. For reference on inserting a new anchor, search for gimp_bezier_stroke_anchor_insert.

Related

How to find the intersection point of a 3D curve and a 3D surface?

I am trying to find the intersection point of a curve and a 3D surface with no luck. The surface is in the shape of a cone, and the curve is hyperbolic, as are shown in the figure.
CONE AND THE CURVE
This simulates a ray hits a certain surface. I tried to use bisection method, but it doesn't seem to work. then I tried newton's algorithm, but the results are still not good.
Is there any other good algorithms out there which are suitable for solving this kind of problem?
With the curve given in parametric form
x = fx(t)
y = fy(t)
z = fz(t)
and the surface by one equation of the form
g(x,y,z) = 0
just plug in the curve functions and bisection should work:
g(fx(t), fy(t), fz(t)) = 0
The only problem is to find suitable starting points t1 and t2 where g has opposite sign.
Problem
You are searching for a curve-surface intersection algorithm. Note that both curves and surfaces can be represented in either implicit form or in parametric form. Surface in implicit form is defined by equation F(x, y, z) = 0, which is a quadratic polynomial of x, y, z in case of conic surface. Surface in parametric form is defined by point-valued function S(u, v) of its parameters (e.g. you can use distance along cone axis and polar angle as parameters of conical surface). Curve is usually described only in parametric form, as a function C(t) with parameter t, which could be quadratic for a hyperbolic curve.
Implicit surface
The simplest cases of all is to treat your problem as an intersection of parametric curve against implicit surface. In this case you can write down a single equation q(t) = F(C(t)) = 0 with single variable t. Of course, Newton's iteration is not guaranteed to find all solutions in general case, bisection can only surely find one solution if you find two points with different sign of q(t).
In your case q(t) is a quartic polynomial (after putting quadratic curve parametrization into quadratic surface equation). It can be theoretically solved with Ferrari's analytic formula, but I strongly advise against it, because it is quite unstable numerically. You can apply any popular polynomial solver here, like Jenkins-Traub algorithm or eigenvalues algorithm for companion matrix (also see this question). You can also use methods of interval mathematics: for example, you can recursively subdivide the domain interval of parameter t into smaller pieces, while pruning all the pieces that surely do not contain zeros (interval arithmetic would help you to detect such pieces).
Parametric surface
Now we can move on to the case when both the curve and the surface are represented parametrically. I do not know any solutions that could benefit from the fact the your surface is conical and your curve is hyperbolic, so you have to apply the general curve-surface intersection algorithm. Alternatively, you can fit an implicitly-defined cone into your parametric surface, then use the solution above for quartic polynomial roots.
A lot of reliable general intersection algorithms are based on the subdivision method (which is actually interval mathematics again). The general idea is to continiously divide the curve and the surface into smaller and smaller pieces. The pairs of pieces which surely do not intersect are dropped as soon as possible. At the end you'll have a set of small piece pairs, tightly bounding your intersection points. Yoy might want to run Newton's iteration from them in order to make intersection points precise.
Here is the outline of a sample algorithm:
Start with a single curve piece (the whole input curve) and a single surface
piece (whole surface), and one potentially intersection pair (PIP) of these pieces.
Subdivide each curve piece into two halves (by parameter), subdivide each surface piece into four quadrants (by both parameters).
For each old PIP check all 8 pairs of curve half vs surface quadrant. If they surely do not intersect, forget them. If they can intersect, save them as a new PIP.
Unless all pieces are small enough, repeat from step 2 with new pieces and PIP-s.
For each pair of curve piece and surface piece, you have to check whether they can potentially intersect, which can be easily done by checking their axis-aligned bounding boxes. Also, you can represent your curves and surfaces as NURBS, in which case you can use convex hulls as tighter bounding volumes.
Generally, there are tons of variations and improvements of this algorithms. I advise the following literature for deeper knowledge:
Shape interrogation for computer-aided design and manufacturing.
chapter 4: for root solvers
section 5.7: for curve-surface intersection
PhD of Michael Hohmeyer.
section 4.5: for curve-surface intersection
sections 4.1 and 4.2: for convex hulls intersection (if you are brave enough).
Bottom line
If you are seeking for a simple and working solution, and you are sure that hyperbolas and cones are the only things you have to worry about, then you'd better use implicit definition of cone and solve quartic equation with some standard numerical algorithm from a good library available to you.

deCasteljau algorithm on bezier surfaces

Hi people i have 2 question related to Decasteljau algorithm,they are more of a general questions,but if im right it could help solving many problems.Here it is:
We have some sufrace: Ʃ(i=0,n) Ʃ(j=o,m) Bi,n(U),Bi,m(v) Pi,j analysis that i have found says that first we take some value for one parameter u=uo,then we itterate other parametar v -> 1 get a set of points,then increment u by one etc....for loop inside for loop in code language.My question is can we fix one parameter U=Uo for what ever value,and then just compute points on for parameter v?Because all points that are on one curve are also on the surface,and if distance between curves approaches to zero (which itteration really is) we can apply DeCasteljau algorithm only to one set of curves itterating only one parameter.Or i got something wrong?:)
Second question is i havent really figured out what do we really need DeCasteljau algorithm for,unless we are drawing curves by hand?If we know order of the curve we can easily form Bernstain polynoms for that curve order and compute point for given value of parametar.Because when you unwrap Decasteljau what you get is Bernstain polynom?
So like i said,please help have i got i wrong?
Yes you can fix one parameter (say U) and change the other (V) to generate an iso-U curve.
You can see the things as if you had an NxM array of control points. If you perform a first interpolation on U (actually M interpolations involving N control points), you get M new control points that define a Bezier curve. and by varying U, the curve moves in space.
The De Casteljau's algorithm is used for convenience: it computes the interpolant by using a cascade of linear interpolations between the control points. Direct evaluation of the Bernstein polynomials would require the precomputation of the coefficients, and would not be faster, even when implemented by Horner's scheme, and can be numerically less stable.
The De Casteljau's algorithm is also appreciated for its geometrical interpretation, and for its connection with the subdivision process: if you want to build the control points for just a part of a Bezier curve, De Calsteljau's provides them.

Parabola fitting with two given points and a cost function

Suppose that there is a parabola Y = aX^2 + bX + c, and it might be rotated as follow:
X = x.sin(phi) + y.cos(phi)
Y = x.cos(phi) - y.sin(phi)
phi = rotation angle
We wish to fit it on a border (e.g. inner border of an eyelid, figure below). The problem is that how we can change the parabola in each iteration such that it minimizes a cost function. We know that the parabola can be in different rotation and its origin may vary in the search region. Note that the there are two given points which the fitted parabola should passes through them (e.g. the white squares in fig below). So, In each iteration we can compute a, b and c by the two given points and the origin point (three equations and three variables).
The question is how we can reach the goal in minimum iteration (not to test all the possibilities, i.e. all angles and all positions in the search region).
Any idea will be appreciated.
#woodchips: I think this is a programming problem, and he asked a solution for the implementation.I definitely disagree with you.
A possible solution would be to first search along the vertical line which is orthogonal to the line between the two given points. And also you can vary the angle in this interval. As the nature of your problem (the border of eyelid), you can limit the angle variation between -pi/4 and pi/4. After you find the minimum cost for a position in this vertical line, you can search along the horizontal line and do similar tasks.
Why not use regression to fit a parabola to several points in the target shape? Then you could use which ever algorithm you wanted to get an approximate solution. Newton's method converges pretty fast. The optimization here is on the coefficients in the approximate parabolas.

Reverse engineering a bezier curve

Given a few sample points on a bézier curve, is it possible to work out the set of possible curves these points may lie on?
In my specific application there is a limited set of endpoints the curve may have, so I want to generate the set of possible curves, enumerate all of them and pick out all the ones which may end on a valid end point.
Some people have asked for more detail.
I have a set of points which I know are on a quadratic bezier curve, I want to calculate the formula of the curve and be able to extrapolate new points on the curve.
Bezier curves will always go through starting and ending control points.
If the degree of the curve is equal to the number of sample points then there will be only one curve that will pass through all your points (in a normal case, where all points are different and they don't lie on a bezier curve of a lesser degree).
If the degree of a curve is less then the number of the sample points then, in general case, you will not be able to make the curve go through all the points (in a normal case).
If the degree of a curve is higher then the number of the sample points then, in general case, you will be able to draw infinite number of curves.
In the wiki article you will find references to control points only, but still I believe that I remember the above properties correctly and that they hold for the points on the curves as well.
I think you need to redefine your question and exactly define what type of curves (and of which degree) do you need. Also as Georg pointed out you might be looking for paths - a combination of curves.
EDIT:
First a correction - curve is defined with degree plus one number of control points points (quadratic need three). Control points are not the same as points on the curve - and for three points on the curve and quadratic curve you could have infinite number of solutions (see this for quadratic curve and four points)
As for the solution (but still under assumption that you are looking at a single curve):
For an equation for single quadratic curve you have
B(t) = (1-t)^2*P0 + 2*(1-t)*t*P1 + t^2*P2
Capital letters above are vectors, and P0 corresponds to starting control point (first point), P2 corresponds to ending control point (last point), so you still need to find P1. The variable t is scalar that ranges from 0 to 1.
If working with 2D curves the above vector equation gives two scalar equations for each point on the curve.
Still there is t as an unknown, so you should take 2 more points (4 in total) which will give you 4 unknowns (t for first point, t for second point, x and y of the P1, middle control point) and 4 equation to solve (2 from each sample point).
Solve that with your favourite numerical method and you will get the original curve on which the points came from.
If you still think that you can get more curves and that you will have to choose something then you are not working with bezier curves, but with bezier splines (in a sense of multiple curves joined together). Still the same principle applies and if you work out a way to solve a single curve from the above equations (and if you have enough points) then you can divide the problem into n-segments of actual bezier curves and solve each as outlined above.
If it turns out that you don't have enough points then look at the linked article again - you are probably looking for the smoothest curve and there are some suggestions in the article on how to get there as looking for the exact solution (shortest curve/smoothest curve) seems to be rather complex.

How to convert closed bezier curves to Bitmaps?

I need an algorithm to convert a closed bezier curve (perhaps self-crossing) to a binary bitmap: 0 for inside pixels and 1 for outside. I'm writing a code that needs to implement some operations on bezier curves, could anybody give me some resources or tutorials about beziere? Wikipedia and others didn't say anything about optimization, subtracting, union, knot insertion and deletion and other operations :-)
alt text http://www.imagechicken.com/uploads/1271001073057545100.jpg
This paper by Charles Loop and Jim Blinn goes into lots of detail on your question.
Another option is to tessellate the Bezier curve into line segments and then use your favorite polygon fill algorithm.
I'd like to add that the tessellation option is very efficient and gives excellent results. It sounds wrong to approximate a Bezier curve by line segments, because you think the output will look like a polygon. The trick is to make the line segments short enough so that the error is very small (say, less than 1/10 of a pixel).
Here is a formula that I have used to compute the step size, to ensure that the maximum error (i.e., deviation of line segments from true curve) is less than delta:
Let (x1,y1), (x2,y2), (x3,y3), (x4,y4) be the control points of the Bezier curve, in pixel coordinates.j
dd0 = square(x1-2*x2+x3) + square(y1-2*y2+y3);
dd1 = square(x2-2*x3+x4) + square(y2-2*y3+y4);
dd = 6*sqrt(max(dd0, dd1));
Then dd is the maximal value of the 2nd derivative over the curve - because the 2nd derivative of a cubic is a linear function, this maximum must occur at an endpoint. Here I have used square(x) as an abbreviation for x*x.
if (8*delta > dd) {
epsilon = 1;
} else {
epsilon = sqrt(8*delta/dd);
}
Then epsilon is your step size: if you choose the endpoints of your line segments at t=0, t=epsilon, t=2*epsilon, ..., (and the last endpoint at t=1), then the line segments will be within delta of the original curve.
Choose delta = 0.1 and you get bitmap output that is visually indistinguishable from the original curve.

Resources