chiark / gitweb /
moebius before point
authorIan Jackson <ijackson@chiark.greenend.org.uk>
Sat, 4 Nov 2017 20:21:57 +0000 (20:21 +0000)
committerIan Jackson <ijackson@chiark.greenend.org.uk>
Sat, 4 Nov 2017 20:21:57 +0000 (20:21 +0000)
Signed-off-by: Ian Jackson <ijackson@chiark.greenend.org.uk>
moebius.py

index 4b4f3a0c6342a4340aac49b8c740a02861012b2d..38e3cb8d9e7d3c75f04c4f140004915f54e42dc9 100644 (file)
@@ -16,27 +16,41 @@ def ParametricCircle:
     pc._c  = c
     pc._r0 = r0
     pc._r1 = r1
-    pc._axis = np.cross(r0, r1)
+  def radius(pc, theta):
+    return pc._r0 * cos(theta) + pc._r1 * sin(theta)
   def point(pc, theta):
-    return pc._c + pc._r0 * cos(theta) + pc._r1 * sin(theta)
+    return pc._c + pc.radius(theta)
 
 def Twirler(ParametricCircle):
-  def __init__(tw, c, r0, r1, cycles, begin):
+  def __init__(tw, c, r0, r1, cycles, begin_zeta):
     ''' circle centred on c, etc.
         but with an orientation at each point, orthogonal to
-        the circle
-'''
+          the circle
+        the orientation circles round cycles times during the
+          whole cycle
+        begin_zeta is the angle from outwards at theta==0
+          positive meaning in the direction of r0 x r1
+    '''
     ParametricCircle.__init__(tw, c, r0, r1)
     tw._cycles = cycles
-  def 
+    tw._begin_zeta = begin_zeta
+    tw._axis = np.cross(r0, r1)
+  def dirn(tw, theta):
+    zeta = tw._begin_zeta + theta * tw._cycles
+    r = radius(tw, theta)
+    return cos(zeta) * r + sin(zeta) * pc._axis
 
 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._edge    = Twirler(origin,  unit_z, unit_x, 2, 0)
+    m._midline = Twirler(-unit_z, unit_z, unit_y, 1, 0)
     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)
+    cp = [None] * 4
+    cp[0] =               m._edge   .point(theta)
+    cp[1] = cp[0] + 0.5 * m._edge   .dirn (theta)
+    cp[3] =               m._midline.point(theta*2)
+    cp[2] = cp[3] + 0.5 * m._midline.dirn (theta*2)
+    return BezierSegmentcp)