--- /dev/null
+
+import numpy as np
+
+tau = np.pi * 2
+
+origin = (0,0,0)
+unit_x = (1,0,0)
+unit_y = (0,1,0)
+unit_z = (0,0,1)
+
+def ParametricCircle:
+ def __init__(pc, c, r0, r1):
+ ''' circle centred on c
+ with theta=0 point at c+r0
+ and with theta=tau/4 point at c+r1 '''
+ pc._c = c
+ pc._r0 = r0
+ pc._r1 = r1
+ pc._axis = np.cross(r0, r1)
+ def point(pc, theta):
+ return pc._c + pc._r0 * cos(theta) + pc._r1 * sin(theta)
+
+def Twirler(ParametricCircle):
+ def __init__(tw, c, r0, r1, cycles, begin):
+ ''' circle centred on c, etc.
+ but with an orientation at each point, orthogonal to
+ the circle
+'''
+ ParametricCircle.__init__(tw, c, r0, r1)
+ tw._cycles = cycles
+ def
+
+class Moebius:
+ def __init__(m, n_u):
+ m._edge = ParametricCircle(origin, unit_z, unit_x)
+ m._midline = ParametricCircle(-unit_z, unit_z, unit_y)
+ m._beziers = [ self._bezier(u) for u in np.linspace(0, 1, n_u) ]
+ def _bezier(u):
+ theta = u * tau
+ cp0 = m._edge.point(theta)
+ cp3 = m._midline.point(theta*2)
+