c++mathgeometrysplinecubic-spline

Finding Perpendicular Points Given An Angle With Piece-wise Hermite Splines


I am given a Hermite spline from which I want to create another spline with every point on that spline being exactly x distance away.

Here's an example of what I want to do:

.

I can find every derivative and point on the original spline. I also know all the coefficients of each polynomial.

Here's the code that I've came up with that does this for every control point of the original spline. Where controlPath[i] is a vector of control points that makeup the spline, and Point is a struct representing a 2D point with its facing angle.

double x, y, a;
a = controlPath[i].Angle + 90;
x = x * cosf(a * (PI / 180)) + controlPath[i].X;
y = x * sinf(a * (PI / 180)) + controlPath[i].Y;
Point l(x, y, a - 90);

a = controlPath[i].Angle - 90;
x = x * cosf(a * (PI / 180)) + controlPath[i].X;
y = x * sinf(a * (PI / 180)) + controlPath[i].Y;
Point r(x, y, a + 90);

This method work to an extent, but its results are subpar.

Result of this method using input:

The inaccuracy is not good. How do I confront this issue?


Solution

  • If you build normals of given length in every point of Hermite spline and connect endpoint of these normals, resulting curve (so-called parallel curve) is not Hermit spline in general case. The same is true for Bezier curve and the most of pther curve (only circle arc generates self-similar curve and some exotic curves).

    So to generate reliable result, it is worth to subdivide curve into small pieces, build normals in all intermediate points and generate smooth piecewise splines through "parallel points"

    Also note doubtful using x in the right part of formulas - should be some distance.

    Also you don't need to calculate sin/cos twice

    double x, y, a, d, c, s;
    a = controlPath[i].Angle + 90;
    c = d * cosf(a * (PI / 180));
    s = d * sinf(a * (PI / 180))
    x = c + controlPath[i].X;
    y = s + controlPath[i].Y;
    Point l(x, y, controlPath[i].Angle);
    x = -c + controlPath[i].X;
    y = -s + controlPath[i].Y;
    Point l(x, y, controlPath[i].Angle);