Continuing from this post, this is the last in the deconstruction of the basic algorithm for distributing text along an arc-length parameterized spline. The final case to consider is when the amount of text to distribute excedes the physical boundary of the spline curve. A simple way to handle this caase is to estimate the slope towards the end of the curve and continue the text in a straight line in the direction of that estimate. This is the idea behind the else block,

else { // text extends beyond end of spline - slope estimate towards // end of spline to continue along in a straight line if( cacheRotation ) { dX = endX - __spline.getX(0.92); dY = endY - __spline.getY(0.92); d = Math.sqrt(dX*dX + dY*dY); uX = dX/d; uY = dY/d; rotation = Math.atan2(dY, dX)*Consts.RAD_TO_DEG; cacheRotation = false; } tf.rotation = rotation; myWidth = tf.textWidth; myHeight = tf.textHeight; // distance along line from end of of spline to current // text starting position d = (s-1)*arcLength; myX = endX + d*uX; myY = endY + d*uY; tf.x = myX + uY*myHeight; tf.y = myY - uX*myHeight; }

which handles the case when the current s-parameter is greater than 1 (meaning the next letter is placed beyond the physical boundary of the spline). The advantage of extrapolating along a straight line is that the rotation value can be computed once and re-used for each letter. There is also a constant normal vector. All these values can be computed once (the first time through the else block) and continually re-used. This is the idea behind the cacheRotation value that is initialized to true.

The Δx and Δy values are estimated by,

dX = endX – __spline.getX(0.92);

dY = endY – __spline.getY(0.92);

The 0.92 value is arbitrary. A more sophisticated algorithm might use the mean of two or more estimates. The exact slope at s=1 sounds reasonable, but visually the text often flows better when using some sort of average estimate.

Notice that every time through the else block, the current TextField’s rotation property is set to the same value,

tf.rotation = rotation; myWidth = tf.textWidth; myHeight = tf.textHeight;

The amount by which the current s-parameter exceeds 1.0 provides an indication of how far along the line to place the text,

d = (s-1)*arcLength; myX = endX + d*uX; myY = endY + d*uY; tf.x = myX + uY*myHeight; tf.y = myY - uX*myHeight;

The computations are the same as before, except that the unit and normal vectors have constant orientation. They are ‘shifted’ along the straight line using the spline endpoint plus the distance along the straight line. After that, TextField positioning is the same as before.

I hope this series of posts provides a good high-level deconstruction of the simple algorithm. Understanding the algorithm at this level is necessary before adding numerous adjustments and refinements to take font metrics, punctuation, and other issues into account.

thanks again for singularity lib. I used parametrized ellipse to build text on ellipse algorithm. it’s not finished though (it has to be capable of placing letters in both directions and I also will have to consider the case when ellipse height is greater then its width). I had to read a bit on trigonometry and definition of tangent to an ellipse, but your lib was a great help

here is the screensnap of the results I’ve got http://echopic.com/16zu.jpg