Saturday, August 22, 2015

Polylines: Radius-Bulge Turnaround

The dxf representation of LWPOLYLINEs represents arcs using the end points of the arc and a bulge factor which is the tangent of a quarter of the central angle of the arc (see this previous post). We want to interchange between the radius and the bulge factor (both ways). Let's pull up the earlier diagram.

Looking at the diagram, we can produce several useful formulas. Taking the bulge factor as \(b\), observe that
\[b = \tan {\theta \over 4} = {i \over u/2} = {2 i \over u}\tag{1},\]
where we are temporarily ignoring the issue of sign.
The distance \(u\) is simply the distance from \(A\) to \(B\) and these point are always given to us in the context of a polyline whether we are given the bulge factor or the radius. We write this as 
\[u = ||B-A||.\tag{2}\]
Using the Pythagorean theorem we have
\[r^2 = {u^2 \over 4} + a^2 .\tag{3}\]
Using the substitution \(a=r-i\), we obtain
\[r^2= {u^2 \over 4} + (r-i)^2 = {u^2 \over 4} + r^2 - 2 r i + i^2\]
and so
\[2 r i = {u^2 \over 4} + i^2.\tag{4}\]

Radius/bulge direction => Bulge factor

Using equation (3), we can solve for \(a\)
\[a = \sqrt{r^2 - \frac{u^2}{4}}.\]
From this we can obtain \(i = r - a\) which allows us to calculate \(b\) according to equation 1. Additionally, set the sign of \(b\) to be positive for a CCW arc and negative for a CW arc. Alternatively stated, \(b\) is positive if the peak of the arc is a right offset from ray \(\overrightarrow{AB}\) and negative if the peak is a left offset from ray \(\overrightarrow{AB}\). In our diagram above, if point A comes before point B in the order they occur in the polyline, then we have a CW arc (P offset to the left of \(\overrightarrow{AB}\)) and so \(b\) should be negative. A negative bulge value indicates bulging to the left and a positive value indicates bulging to the right.

Bulge factor => Radius/bulge direction

We calculate \(u\) from \(A\) and \(B\) and then substitute equation 1 (solved for \(i\)) into equation 4 to get
\[2 r \frac{b u}{2} = \frac{u^2}{4} + \frac{b^2 u^2}{4}\]
\[4 r b =  u + b^2 u\]
\[r = u \left(\frac{1 + b^2}{4 b}\right).\]
Note that we would actually use the absolute value of \(b\) to obtain a positive radius. We can use the same logic as above for determining CW versus CCW (it's "iff" logic).

Locating the Center Point

Whether we are given the radius or bulge factor, we may want to find the center point. From above, we know we have \(u\), \(i\), \(b\), \(r\), and \(a\) all easily available to us if we need them.

We take our unit vector for the direction of the line segment taken from \(A\) to \(B\) as \(d = (B-A)/u\). Then the normal direction (90° right turn for offsetting) is given by
\[N = (d_y, -d_x).\]
Taking \(\sigma = {\rm signum}(b)\),
\[C = \frac{A+B}{2} - \sigma a N\]
\[P = \frac{A+B}{2} + \sigma i N.\]

In my next post, I show a way to implement this in Maxima.