Once again, there were a few questions regarding this post; namely, how to draw the normal vector to the spline. One person suggested using the fact that slopes of perpendicular lines are negative reciprocals. Since we already know the slope of the tangent line, we know the slope of the normal line (although there are numerical issues with near or exactly vertical tangents).
That’s a good suggestion for a starting point. An alternative is to use the fact that we have unit vectors in the tangent direction both ‘away’ and ‘toward’ the direction the curve moves with increasing parameter value. The 2D rotation matrix corresponding to rotations of +/- PI/2 is particularly simple. We can rotate the already computed unit vectors and then determine a point along the normal the same distance as along the tangent line. This is illustrated below,
The issue here is that the normal will flip when passing through a parameter value corresponding to a vertical tangent. The reason is a subject for another post at another time. You are welcome to download the updated code from the Downloads section and experiment with both approaches. In the mean time, I’m hoping that the demo that created this series in the first place will be completed by the weekend or early next week.
I received a couple questions regarding this post relative to computing the angle of the tangent line relative to the horizontal. It’s a matter of a little trig once you recall the geometric interpretation of a curve’s derivative at a point. Our old friend, Math.atan2() is just what the doctor ordered. To illustrate, I modified the demo code to use the Singularity Wedge class to show the angle relative to the horizontal as shown below.
The wedge is redrawn dynamically as the slider moves. Once you know the tangent orientation, you also know the normal orientation. Along with arc-length parameterization, this means that sprites can be precisely distributed along and aligned to the spline. Stay tuned for more …
In calculus, we are taught that the slope of the tangent to a curve, y = f(x) at some point x=c is f'(c). What about a parameteric curve? The curve is parameterized on t, not on x. We do have derivative information, but the derivatives are with respect to the curve’s parameter.
Fortunately, the chain rule provides the necessary result; dy/dx = [dy/dt]/[dx/dt]. All Singularity parametric curves (including composite curves) return position and derivative at a parameter value. This information can be used to compute the slope of a tangent to a spline such as Catmull-Rom, as shown below.
If dx/dt is sufficiently small, the tangent slope approaches infinity and this should be tested and compensated for in application code. The demo from which the above screenshot was taken allows an arbitrary number of points to be defined in the drawing area. A Catmull-Rom spline is fit to those points. Move the slider to watch a 40px segment drawn tangent to the curve as the parameter varies from 0 to 1.
To compute the tangent segment, the slope of the spline at the specified parameter along with a small positive and negative perturbation in x is used to generate two points on the tangent in opposite directions. Unit vectors in each direction are created. Two points, each 20px along each unit vector, are generated to create the line segment.
The demo is contained in a single MXML file and may be obtained from the Downloads section in this blog. Or, you can download the .zip file here along with Singularity here. You need to have Singularity on your computer in order to build a Flex project from the supplied MXML file.
If we have a well-defined tangent to a curve at a point, not only can we orient sprites along the curve, we know the angle the tangent makes with horizontal. That information, combined with arc-length parameterization allows sprites to be distributed uniformly along the curve with orientation control. Stay tuned for a new demo in a few days illustrating these observations.