Bezier curve fitting with known end points - curve-fitting

I want to fit a bezier curve with known end points (p0 and p3) to noisy 2d data. This seems like an easier problem than traditional 4-point bezier curve fitting but still too hard for me to figure out.
Can someone point me to existing code or an algorithm to find the best values for the control points p1 and p2?
edit: The points that I'm trying to fit with a bezier curve comes from curves drawn with a mouse (imagine drawing something with a brush in Paint, there could be hundreds of recorded points in one long stroke). The anchor points p0 and p3 are created in advance but the control points p1 and p2 should be calculated so that the bezier fits the shape of the curve sketched out with the mouse.

I stumbled on a paper called "Approximation of data using cubic Bezier curve least square fitting" by "M.Khan" which describes an algorithm to calculate the exact thing I'm looking for.
Implementation in javascript was easy. It works quite good and is fast but the resulting bezier curves are not perfect. Could be a bug in my code but I suspect that better curves could be obtained by iteratively adjusting the matching points on the bezier curve to better fit the data .
edit: It turns out you can use newton-raphson to optimize each individual t-value for the bezier curve. After doing that the curve fits great, atleast for curves with only few points that don't self intersect but I have to do some more testing.

Related

Fitting elliptical arcs to points or other curves

I'm struggling to fit an elliptical arc to some points. The points are either from line segments or all part of the same polyline or they are generated from a bezier curve. I basically have two issues:
I would like to fit an elliptical arc to the points if it is reasonable and i straight line if that is a better fit. I'm thinking about starting at the first point and then constructing a line and a ellip_arc to the next points. The one with the lowest error wins. Or something like that at least. The problem is that an ellipse has many free parameters as opposed to a straight line. So how could I fit an ellipse arc to the points? It also has to start and stop at the points.
Fitting seems to be easiest when the ellipse arc is parameterized. Even though I find it hard to define where to start and stop the arc. But, as output, I need to have the ellipse described like in SVG format (Center Point, Minor and Major Axis, rotation to x-axis etc. https://www.w3.org/TR/SVG2/paths.html#PathDataEllipticalArcCommands). I'm not sure how to convert to this representation, or maybe I can fit it like that?
see:
Circular approximation of polygon (or its part)
If you compute this for your curve samples from local change of radius and center you could group and estimate parts of curve that belongs to the same ellipse and also its eccentricity and or a,b semiaxises sizes , center and orientation to ease up your fitting... Even if not get the precise value it will be a start point and range for ellipse parameter fitting hugely improving speed and stability of fitting
Some of the ellipse parameters might be obtained directly if your data has enough large chunks of ellipses see:
Algorithms: Ellipse matching
Fitting SVG like parameters fully will be very slow easier would be to fit just the ellipses first (center,a,b,rotation) and then convert/fit to SVG form elliptic arc. See:
Converting an svg arc to lines
Express SVG arc as series of curves
And finally you can use any fitting algorithm my favorite is this one:
approximation search
I do not code in C# so I have no idea about any existing packages for tasks like this.

Creating a circular arc tangent to two curves with specified radius

The operation mentioned in the title is common in many Computer Aided Design (CAD) softwares such as AutoCAD, where it is called fillet. However, I found it is really difficult to implement this function in my own program.
The method I thought of is to use the condition that the distances of the arc center to the tangent lines of the curves are equal to the specified radius. Considering that actual curves are defined with piece-wise nonlinear functions, and the contact points could be anywhere on the curves, it is not easy to get the solution. Anyone good ideas?
Given that you don't describe in enough details the characteristics of the curves, it's hard to come with a specific/specified algo, but let's try a descriptive approach:
take a circle of the given radius and roll it on one curve until the circle touches the other one.
I assume you can parametrize you curves.
To "roll the circle" along the curve you need the tangent (or better said the normal, which of course is normal to the tangent) in the point "rolling track curve"-to-circle tangent point. You have this normal, you know the radius, you can compute your circle. You have the circle, you can see if/where it intersects the other curve.
The idea of "rolling" is to bracket your solution (parameter of the tangent-point on one curve) between a point when the circle does not intersect the other curve and another point where it intersects (possible in more than 1 point).
Once you have the bracket, go with a bisection method (binary search) between the two positions until your circle becomes "tangent enough" to the other curve (i.e the intersection points with the other curve are so close that they fall below your acceptable epsilon).
You will now have two points (one on each curves) and the circle that realizes the solution: just keep the arc on this circle corresponding what make sense (based on the convergence or divergence of the two tangents).
To find the arc center you need two robust and strategic algorithms:
Curve offset
Curve intersection
What AutoCAD does to find the arc center is to offset the two curves of the arc radius distance and intersect them. Depending on the curve offset direction you can easily switch between all possible solutions to the problem.
At this point, trimming the curves at tangent points will be trivial.

How do I calculate pairs of Bezier S-curves such that the space between them has constant thickness?

Using SVG and cubic beziers, I'm attempting to generate the outline of S-curve shapes of various thicknesses, widths and heights, such as these:
I'm stuck on figuring out where the Bezier handle for each of the four corner nodes should be positioned in order to give the curve formed by their in-between area a constant thickness (or at least approximately).
I can see that the horizontal distance between the inner and outer handle at each end is dependent on the thickness of the curve and the overall curve width and height, but I'm stumped trying to get something that links them all together.
Is there a formula that would give me the horizontal position for each of the handles?
(I'm using d3js, so if there's a plugin or function I've missed that would help with this, that'd be even better).
I recommend the Tiller-Hanson algorithm used in FreeType's ftstroke module. It is normally used for converting a zero-width line into a stroke with some finite width; you can use the way it creates one of the two envelope lines (one on either side of the original line) to get your parallel curve. It handles any line made from straight segments and quadratic and cubic Bézier splines.
For more information see my answer to this question: How to get the outline of a stroke?.
Unfortunately, unless your curve has a uniform curvature, you can't get a fixed distance offset curve simply by linear scaling the original curve.
In order to get an offset curve for a Bezier, you have to do a bit of calculus to figure out how to split up the curve into "safe" segments, which can be offset by scaling, and then scale each piece.
More details over on http://pomax.github.io/bezierinfo/#offsetting, but basically what you want is something that usually you have someone else implement for you because it's a chore to get right.
You can actually offset the control polygon of one cubic Bezier curve to generate the control polygon for the "offset" curve, which will still be a cubic Bezier curve.
The following picture shall make it clear about what does "offset control polygon" mean. Given the cubic Bezier curve defined by P0, P1, P2 and P3, we can offset the 3 infinite lines L01 (defined by P0 and P1), L12 (defined by P1 and P2) and L23 (defined by P2 and P3). The resulting lines are denoted as L01*, L12* and L23*. The intersection points of L01* and L12* will be Q1 and that between L12* and L23* will be Q2. Q0 and Q3 will be the direct projected point of P0 and P3 onto L01* and L23*. The offset curve will be the cubic Bezier curve defined by Q0, Q1, Q2 and Q3.
Of course, the "offset" curve created in this way is not the exact offset but just an approximation. But as long as the offset distance is not too big and you are not too picky about the accuracy, the result is generally good enough. There are two advantages of this approach (besides its simplicity):
the approximate offset curve will honor the true offset curve's tangent direction at the start and end of the curve.
if you offset the offset curve in the opposite direction by the same distance, you will get back the original cubic Bezier curve.

How can I simulate a Bezier curve out of an image?

If I have a set of points from a black-white image I scanned.
It looks like a curve and I want to simulate a smooth curve using cubic Bezier curve from those points.
How can I figure out the start point, 2 control points and the end point?
From the image, there are several cubic Bezier curves that can be simulated but I don't know how to figure out the control points.
I have found the solution for my problems and I want to share it.
First, I write a python program to trace the curve and tell me all x,y of the points on the line.
Now, I have one curve.
I then create a line from start to end point and compare the distance between the perpendicular points on those 2 lines. If the distance is not low enough I will move the control point up, down, left, right and find which direction has the least distance. Do this multiple time and I will get a curve that is similar to the curve I have.

What is the best algorithm for bezier path clipping

I know two common algorithms by Greiner-Hormann and Vatti. They work with polygons. I want to implement boolean operations on bezier paths. I want to extend these algorithms to work with bezier paths. But this is numerical problem. What is the best way to bezier path clipping? ( and what is the best modification of Greiner-Hormann algorithm for arbitrary polygons (with self intersections) )
Here is a suggested algorithm.
use the four control points to determine a polygon enclosing the bezier curve.
test polygon overlapping to see if two bezier curves may have an intersection point. If not overlapping, we are done, no clipping required.
if polygon overlap, split the two bezier curve in two using one casteljau iteration. Stop the recursion if the size of the bezier curve is too small regarding the required precision. Otherwise resume recursively with step 2.
In the process of dividing the bezier curve, keep track of where you are (value t) so that you can easily determine the 4 control point of the clipped bezier curve.
Note that at some point a bezier curve may be approximated to a straight line. In this case the overlapping test and splitting will be faster.
With this process you should end with a bezier curve cut in pieces by the clipping bezier curve. You still need to determine which piece is on which side of the clipping.

Resources