Yes, I’m familiar. I had implemented the rubber-band thing about one and half years ago now, after seeing **Armin Hoffmann**’s (Swiss graphic designer) experimental font in a book that they derived with similar principals, but - I guess - analogously by hand.

I first did a prototype in GHPython and later ported the whole thing to C++, because I wanted to compute all possible shapes for a given set of points, which in hindsight was a little naive, given that for the standard set that Hoffmann used, namely 9 points/circles in a grid, already yields a lot of non-intersecting, Hamiltonian paths.

It also was a deep, deep, deep rabbit hole to descent into, because I basically implemented everything from scratch (e.g. points, lines, circles, intersections between them, graph, Hamiltion path finder, permutations generator, etc.), a whole fricking mini geometry library that I still use parts of for creative coding projects.

It works for a reasonable amount of points, but I still need to perfect the SVG export, which I also did from scratch, and which made me lose interest in the whole thing.

Anyway, here’s what I came up with for circle to circle tangents in GHPython back then, if you’re intereseted:

```
import Rhino.Geometry as rg
def tangent_lines(from_circle, to_circle, interior=False):
"""Creates two interior or exterior tangent lines to two circles.
Tangent lines can only be constructed, if neither circle is inscribed
within the other. Interior tangent lines additionally require the two
circles to not intersect at any point.
Args:
from_circle (Rhino.Geometry.Circle): first circle
to_circle (Rhino.Geometry.Circle): second circle
interior
Raises:
RuntimeError: Unable to create interior tangent lines,
from_circle/to_circle is inscribed within to_circle/from_circle
RuntimeError: Unable to create interior tangent lines,
from_circle and to_circle intersect
Returns:
The two tangent lines from the first circle to the second.
"""
circles = [from_circle, to_circle]
indices = [0, 1]
if from_circle.Radius != to_circle.Radius:
indices.sort(key=lambda i: circles[i].Radius)
circles.sort(key=lambda c: c.Radius)
min_circle, max_circle = circles
distance = min_circle.Center.DistanceTo(max_circle.Center)
if distance <= max_circle.Radius - min_circle.Radius:
e = "from_circle is inscribed within to_circle"
if indices[0] == 1:
e = "to_circle is inscribed within from_circle"
raise RuntimeError("Unable to create tangent lines, " + e)
if interior and distance <= max_circle.Radius + min_circle.Radius:
e = "from_circle and to_circle intersect"
raise RuntimeError("Unable to create interior tangent lines, " + e)
circles_tan_pts = [[], []]
if min_circle.Radius != max_circle.Radius or interior:
radius_x = max_circle.Radius - min_circle.Radius
if interior:
radius_x = max_circle.Radius + min_circle.Radius
circle_x = rg.Circle(max_circle.Center, radius_x)
mid_pt = (min_circle.Center + max_circle.Center) / 2
mid_circle = rg.Circle(mid_pt, mid_pt.DistanceTo(max_circle.Center))
rc, pt1, pt2 = rg.Intersect.Intersection.CircleCircle(mid_circle, circle_x)
for pt in [pt1, pt2]:
vec = pt - max_circle.Center
vec.Unitize()
min_vec = vec * min_circle.Radius * -1 if interior else vec * min_circle.Radius
min_tan_pt = min_circle.Center + min_vec
circles_tan_pts[0].append(min_tan_pt)
max_vec = vec * max_circle.Radius if interior else vec * (circle_x.Radius + min_circle.Radius)
max_tan_pt = max_circle.Center + max_vec
circles_tan_pts[1].append(max_tan_pt)
else:
vec = max_circle.Center - min_circle.Center
xvec = rg.Vector3d.CrossProduct(vec, max_circle.Normal)
xvec.Unitize()
xvec *= max_circle.Radius
min_tan_pt_a = min_circle.Center + xvec
min_tan_pt_b = min_circle.Center - xvec
circles_tan_pts[0] = [min_tan_pt_a, min_tan_pt_b]
max_tan_pt_a= max_circle.Center + xvec
max_tan_pt_b = max_circle.Center - xvec
circles_tan_pts[1] = [max_tan_pt_a, max_tan_pt_b]
sorted_cir_tan_pts = [p for _, p in sorted(zip(indices, circles_tan_pts))]
tan_line_1 = rg.Line(sorted_cir_tan_pts[0][0], sorted_cir_tan_pts[1][0])
tan_line_2 = rg.Line(sorted_cir_tan_pts[0][1], sorted_cir_tan_pts[1][1])
return tan_line_1, tan_line_2
if __name__ == "__main__":
tan_lines = tangent_lines(C1, C2, I)
```