Snap tangent means, start with some point and try to find a point on the destination object (circle, sphere, ellipse, anything) that causes the line segment between the first point and the second point to be tangent to the object selected. My post about snap tangent, showed the result for a circle and worked in 2D. If you get the concept in 2D and are ready to take the concept to 3D for a sphere, you probably recognize without proof that the set of possible points on the sphere which will result in a tangential point, forms a circle. You can pretty much mentally extrapolate from the following picture which a repeat from the previous post.

Fig. 1 - Can you imagine the snap tangent circle on this if we allow the figure to represent a sphere? The snap tangent circle has center \(E\) and radius \(a\). |

So, now we need a way to describe this circle which is not too onerous. A parametric vector equation is the simplest expression of it. We take our inspiration from the classic representation of circles in parametric form, which is

\[ p(\theta) = (x(\theta), y(\theta)) \] \[ x(\theta) = r \cos{\theta} \] \[ y(\theta) = r \sin{\theta}. \]

We have a normal from which to work from, but we need to have an entire coordinate system to work with. The classic parametric equations have everything in a neat coordinate system, but to describe a circle that's oriented any which way, we need to cook up a coordinate system to describe it with. Observe a change to the foregoing presentation that we can make:

\[ p(\theta) = r \cos{\theta} (1, 0) + r \sin{\theta} (0, 1) = r \cos{\theta} \vec{x} + r \sin{\theta} \vec{y}\]

The normal vector we have is basically the z-axis of the impromptu coordinate system we require, but we don't have a natural x-axis or y-axis. The trouble is there are an infinite number of x-axes that we could choose, we just need something perpendicular to \(N = (n_x, n_y, n_z).\) So, let's just pick one. If I take the cross product between \(N\) and any other vector that isn't parallel to \(N\), I will obtain a value which is perpendicular to \(N\) and it can serve as my impromptu x-axis. To ensure I don't have a vector which is close to the direction of \(N\), I will grab the basis vector, which is the most "out of line" with the direction of \(N\). So, for example (F# style),

let b = if abs(normal.[0]) <= abs(normal.[1]) then

if abs(normal.[0]) <= abs(normal.[2]) then

DenseVector([| 1.0; 0.0; 0.0 |])

else

DenseVector([| 0.0; 0.0; 1.0 |])

else

if abs(normal.[1]) <= abs(normal.[2]) then

DenseVector([| 0.0; 1.0; 0.0 |])

else

DenseVector([| 0.0; 0.0; 1.0 |])

In this case, I have

\[\vec{x} = b \times N\] \[\vec{y} = N \times \vec{x}.\]

Using this impromptu coordinate system, I can express an arbitrary circle in parametric form, having center \(C\) and radius \(r\) as

\[ p(\theta) = C + \vec{x} r \cos{\theta} + \vec{y} r \sin{\theta}.\]

Thus, our snap tangent circle is given from above as

\[ p(\theta) = E + \vec{x} a \cos{\theta} + \vec{y} a \sin{\theta},\]

where we would use \(N = A - C\) (normalized) to be the beginning of our coordinate system.