I am working on something that can fit a set of Bezier curves through a set of points. I've been able to do this using the curve fitting method from Pomax. The problem with this method is that it cannot fit a low order Bezier curve through a line that has many inflections. Therefore in order to make this work, I need to be able to get a piecewise cubic-bezier by splitting the curve at its inflection points and then running the curve fitting algo from there.
The problem is that I'm not sure how to find the derivative of a set of points that have no clear function. I guess I could always calculate the slope of the secant line instead of the tangent line, but I'm not sure if that would work well.
Does anybody have any better ideas on how to find the inflection points of a set of points?
Inflex point is dividing curve where the curvature winding goes from CW to CCW or vice versa. So first detect the winding.
Assuming 2D case...
If your points are { p0,p1,p2,...,p(n-1) } then winding at p(i) is the sign of z coordinate of 3D cross product of 2 consequent tangents:
w(i) = cross (
( p(i).x-p(i-1).x , p(i).y-p(i-1).y , 0)
( p(i+1).x-p(i).x , p(i+1).y-p(i).y , 0)
).z
So if p(i) is inflex then:
w(i)*w(i-1) < 0
The problem is if w(i) or w(i-1) is zero such winding must be skipped or specially handled.
Related
I am dealing with a reverse-engineering problem regarding road geometry and estimation of design conditions.
Suppose you have a set of points obtained from the measurement of positions of a road. This road has straight sections as well as curve sections. Straight sections are, of course, represented by lines, and curves are represented by circles of unknown center and radius. There are, as well, transition sections, which may be clothoids / Euler spirals or any other usual track transition curve. A representation of the track may look like this:
We know in advance that the road / track was designed taking this transition + circle + transition principle into account for every curve, yet we only have the measurement points, and the goal is to find the parameters describing every curve on the track, this is, the transition parameters as well as the circle's center and radius.
I have written some code using a nonlinear optimization algorithm, where a user can select start and end points and fit a circle that to the arc section between them, as it shows in next figure:
However, I don't find a suitable way to take the transition into account. After giving it some thought I came to think that this s because, given a set of discrete points -with their measurement error- representing a full curve, it is not entirely clear where to consider it "begins" and where it "ends" and, moreover, it is less clear where to consider the transition, the proper circle and the exit transition "begin" and "end".
Is there any work on this subject which I may have missed? is there a proper way to fit the whole transition + curve + transition structure into the set of points?
As far as I know, there's no method to fit a sequence clothoid1-circle-clothoid2 into a given set of points.
Basic facts are that two points define a straight, and three points define a unique circle.
The clothoid is far more complex, because you need: The parameter A, the final radius Rf, an initial point px,py, the radius Ri at that point, and the tangent T (angle with X-axis) at that point.
These are 5 data you may use to find the solution.
Due to clothoid coords are calculated by expanded Fresnel integrals (see https://math.stackexchange.com/a/3359006/688039 a little explanation), and then apply a translation & rotation, there's no an easy way to fit this spiral into a set of given points.
When I've had to deal with your issue, what I've done is:
Calculate the radius for triplets of consecutive points: p1p2p3, p2p3p4, p3p4p5, etc
Observe the sequence of radius. Similar values mean a circle, increasing/decreasing values mean a clothoid; Big values would mean a straight.
For each basic element (line, circle) find the most probably characteristics (angles, vertices, radius) by hand or by some regression method. Many times the common sense is the best.
For a spiral you may start with aproximated values, taken from the adjacent elements. These values may very well be the initial angle and point, and the initial and final radius. Then you need to iterate, playing with Fresnel and 'space change' until you find a "good" parameter A. Then repeat with small differences in the other values, those you took from adjacents.
Make the changes you consider as good. For example, many values (A, radius) use to be integers, without decimals, just because it was easier for the designer to type.
If you can make a small applet to do these steps then it's enough. Using a typical roads software helps, but doesn't avoid you the iteration process.
If the points are dense compared to the effective radii of curvature, estimate the local curvature by least square fitting of a circle on a small number of points, taking into account that the curvature is most of the time zero.
You will obtain a plot with constant values and ramps that connect them. You can use an estimate of the slope at the inflection points to figure out the transition points.
Given two points and a control point, one can easily draw a bezier path between the two points. What I would like to do use a bezier curve to draw a path that with changing width, by a assigning a "weight" to a the points of the curve which will determine its width. For example, if I give weight=0 to the first point of the curve and weight = 1 to the second point of the curve then something like the following path should be generated (the curve in the picture is cubic, but I am working with quadratic bezier curves):
In order to do this I would need to find the control points of the "edge" curves that determine the shape and then fill the shape that is found between the two new curves. However, I am quite unsure on how this can be done. One thing I thought about was to determine the starting and ending points of the new curves by simple drawing perpendicular segments to the line connecting the original control point and the original end points, but this still doesn't solve the problem of finding the new control points for the new curves.
I would use cubics instead of quadratics.
Yes you offset the control points perpendicularly by your weight but not the control points of BEZIER but control points of interpolation cubic (or catmull-rom) and then just convert that into Bezier control points. See related QAs:
How can i produce multi point linear interpolation?
How to create bezier curves for an arc with different start and end tangent slopes
draw outline for some connected lines
However much easier would be to directly render curve using Shaders and (perpendicular) distance. See:
Draw Quadratic Curve on GPU
That way you would not need to offset anything just interpolate the width of your curve ...
Maybe this could help, also there is an example on variable offseting
https://microbians.com/mathcode
I start this thread asking for your help in Excel.
The main goal is to determine the coordinates of the intersection point P=(x,y) between two curves (curve A, curve B) modeled by points.
The curves are non-linear and each defining point is determined using complex equations (equations are dependent by a lot of parameters chosen by user, as well as user will choose the number of points which will define the accuracy of the curves). That is to say that each curve (curve A and curve B) is always changing in the plane XY (Z coordinate is always zero, we are working on the XY plane) according to the input parameters and the number of the defining points is also depending by the user choice.
My first attempt was to determine the intersection point through the trend equations of each curve (I used the LINEST function to determine the coefficients of the polynomial equation) and by solving the solution putting them into a system. The problem is that Excel is not interpolating very well the curves because they are too wide, then the intersection point (the solution of the system) is very far from the real solution.
Then, what I want to do is to shorten the ranges of points to be able to find two defining trend equations for the curves, cutting away the portion of curves where cannot exist the intersection.
Today, in order to find the solution, I plot the curves on Siemens NX cad using multi-segment splines with order 3 and then I can easily find the coordinates of the intersection point. Please notice that I am using the multi-segment splines to be more precise with the approximation of the functions curve A and curve B.
Since I want to avoid the CAD tool and stay always on Excel, is there a way to select a shorter range of the defining points close to the intersection point in order to better approximate curve A and curve B with trend equations (Linest function with 4 points and 3rd order spline) and then find the solution?
I attach a picture to give you an example of Curve A and Curve B on the plane:
https://postimg.cc/MfnKYqtk
At the following link you can find the Excel file with the coordinate points and the curve plot:
https://www.mediafire.com/file/jqph8jrnin0i7g1/intersection.xlsx/file
I hope to solve this problem with your help, thank you in advance!
kalo86
Your question gave me some days of thinking and research.
With the help of https://pomax.github.io/bezierinfo/
§ 27 - Intersections (Line-line intersections)
and
§ 28 - Curve/curve intersection
your problem can be solved in Excel.
About the mystery of Excel smoothed lines you find details here:
https://blog.splitwise.com/2012/01/31/mystery-solved-the-secret-of-excel-curved-line-interpolation/
The author of this fit is Dr. Brian T. Murphy, PhD, PE from www.xlrotor.com. You find details here:
https://www.xlrotor.com/index.php/our-company/about-dr-murphy
https://www.xlrotor.com/index.php/knowledge-center/files
=>see Smooth_curve_bezier_example_file.xls
https://www.xlrotor.com/smooth_curve_bezier_example_file.zip
These knitted together you get the following results for the intersection of your given curves:
for the straight line intersection:
(x = -1,02914127711195 / y = 23,2340949174492)
for the smooth line intersection:
(x = -1,02947493047196 / y = 23,2370611219553)
For a full automation of your task you would need to add more details regarding the needed accuracy and what details you need for further processing (and this is actually not the scope of this website ;-).
Intersection of the straight lines:
Intersection of the smoothed lines:
comparison charts:
solution,
Thank you very much for the anwer, you perfectly centered my goal.
Your solution (for the smoothed lines) is very very close to what I determine in Siemens NX.
I'm going to read the documentation at the provided link https://pomax.github.io/bezierinfo/ in order to better understand the math behind this argument.
Then, to resume my request, you have been able to find the coordinates (x,y) of the intersection point between two curves without passing through an advanced CAD system with a very good precision.
I am starting to study now, best regards!
kalo86
I'm trying to find the inflection points relative to given axis (green line) given a series of (blue) points that form a path. We can see from the diagram below there are two inflection points (pink lines), or places where the path changes direction relative to the task axis.
The tricky part is that the direction of the axis may change, so it has to work going in any direction. My first attempt takes 2 consecutive points along the path, gets the direction between them, and then compares it to the direction of the axis.
Skipping a few boring steps (like recording previous points), the pseudocode looks like this:
foreach point cur_point in path:
direction = prev_point - cur_point
(normalize direction)
relative_direction = dir_towards_axis - direction
(normalize relative direction)
if the sign of either x or y has changed between relative_direction and prev_relative_direction
# we have found an inflection point
Unfortunately this does not work. Any pointers on where I'm going wrong?
To find needed points, you can detect sign change of cross product between axis and current curve direction (orientation/handedness test).
axis_direction = axis_end - axis_start = B - A
....
direction = cur_point - prev_point
cross = cross_product(direction, axis_direction) =
direction.x * axis_direction.y - direction.y * axis_direction.x
Note: If your curve is continuous and analytic, closed-form formula might exist
Have a look at https://pomax.github.io/bezierinfo/#aligning - the idea is to align your baseline with the x or y axis, by moving every point by {-p1.x, -p1.y} and then rotating all the coordinates that define your curve (provided your curve is invariant to affine transforms!) so that your last coordinate lies on the axis (for which you use the atan2 function to find the angle to rotate by, which virtually all programming languages come with).
Once axis-aligned, you can perform whatever analysis "with respect to the axis" you need done.
The curve is in fact the trajectory of a bus, the curve is represented by many (up to a few thousand) discrete points on the curve (the points were recorded by a GPS device installed on the bus).
Input a point P, I need to find the closest point on the curve to the point P. The point P is usually no more than 30m away from the trajectory of the bus. Note, the closest point isn't necessary a point recorded by the GPS device, it could be a point somewhere between two recorded points.
First I need an algorithm to recover the trajectory from those recorded points. It would be great if the interpolated curve could show sharp turns made by the bus. Which curve is best for such task ? Is Bezier curve good enough ? And finally I have to calculate the closest point on the curve, of course the algorithm completely depends on the kind of curve chosen.
I'm doing some research, and don't have much knowledge in curve interpolation, so any suggestions are welcome.
For computing the trajectory from recorded points, I recommended using the centripetal or chord-length Catmull-Rom splines. See link for more details. Catmll-Rom splines are in fact special cubic Hermite curves, which can be easily converted into cubic Bezier curves. Please note that the result from Catmull-Rom spline is a G1 curve only in general. If you want the trajectory to be with higher continuity (such as C2), you can go with natural cubic splines or general B-spline interpolation. Whatever approach you take, it is advised to keep the spline's degree no higher than 5. Degree 3 is a popular choice.
Once you have the mathematical representation for the trajectory, you can compute the minimum distance between a given point P and the trajectory. In general, the squared distance between point P and a curve C(t) is represented as D(t) = |P-C(t)|^2. The minimum of D will happen at where its first derivative is zero, which means we have to find the root for the following equation:
dD/dt = 2*(P-C(t)).C'(t) =0
When C(t) is of degree 3, dD/dt will be of degree 5. This is the reason why it is recommended to use a low degree curve earlier.
There are many literatures or online materials talking about how to find the root of a polynomial (of any degree) efficiently and robustly. Here is another SO post that might be useful.