I have a problem. Suppose we have a single cubic bezier curve defined by four control points. Now suppose, the curve is cut from a point and each segment is again represented using cubic bezier curves. So, now if we are given two such beziers B1 and B2, is there a way to know if they can be joined to form another bezier curve B? This is to simplify the geometry by joining two curves and reduce the number of control points.
2 Answers
Some thoughts about this problem.
I suggest there was initial Bezier curve P0
-P3
with control points P1
and P2
Let's make two subdivisions at parameters ta and tb.
We have now two subcurves (in yellow) - P0
-PA3
and PB0
-P3
.
Blue interval is lost.
PA1
and PB2
- known control points. We have to find unknown P1
and P2
.
Some equations
Initial curve:
C = P0*(1-t)^3+3*P1(1-t)^2*t+3*P2*(1-t)*t^2+P3*t^3
Endpoints:
PA3 = P0*(1-ta)^3+3*P1*(1-ta)^2*ta+3*P2*(1-ta)*ta^2+P3*ta^3
PB0 = P0*(1-tb)^3+3*P1*(1-tb)^2*tb+3*P2*(1-tb)*tb^2+P3*tb^3
Control points of small curves
PA1 = P0*(1-ta)+P1*ta => P1*ta = PA1 – P0*(1-ta)
PB2 = P2*(1-tb)+P3*tb => P2(1-tb) = PB2 – P3*tb
Now substitute unknown points in PA3 equation:
**PA3***(1-tb) = **P0***(1-ta)^3*(1-tb)+3*(1-ta)^2*(1-tb)*(**PA1** – **P0***(1-ta))+3*(1-ta)*ta^2*( **PB2** – **P3***tb)+**P3***ta^3*(1-tb)
(some multiplication signs have been lost due to SO formatting)
This is vector equation, it contains two scalar equations for two unknowns ta
and tb
PA3X*(1-tb) = P0X*(1-ta)^3*(1-tb)+3*(1-ta)^2*(1-tb)*(PA1X – P0X*(1-ta))+3*(1-ta)*ta^2*( PB2X – P3X*tb)+P3X*ta^3*(1-tb)
PA3Y*(1-tb) = P0Y*(1-ta)^3*(1-tb)+3*(1-ta)^2*(1-tb)*(PA1Y – P0Y*(1-ta))+3*(1-ta)*ta^2*( PB2Y – P3Y*tb)+P3Y*ta^3*(1-tb)
This system might be solved both numerically and analytically (indeed Maple solves it with very-very big cubic formula :( )
If we have points with some error, that makes sense to build overdetermined equation system for some points (PA3
, PB0
, PA2
, PB1
) and solve it numerically to minimize deviations.
You will find a quite simple solution here: https://math.stackexchange.com/a/879213/65203.
When you split a Bezier, the vectors formed by the last two control points of the first section and the first two control points of the second section are collinear and the ratio of their lengths leads to the value of the parameter at the split. Verifying that the common control point matches that value of the parameter is an easy matter (to avoid the case of accidental collinearity).
bool match(const ControlPoint B1[4], const ControlPoint B2[4], ControlPoint B[4]) { Approx(B1,B2,B); return (Compare(B1,B2,B) }
with values for B1,B2 and B for an example where you want this to return true and explaining in words whatApprox
andCompare
should do. – user786653