# with this edition we retire ch.py nee MH and start fixing it
# edited by GF and later by Matt Hoffman with rearrangements
# whose philosophy is reposition 4vertex as being drawn,
# while we usually reassociate and apply rotation after being drawn.
# pyNewTorus.py by Stan Blank, Wayne City, IL
# Credit to George K. Francis for the excellent original program
# continued by GF 18nov12

# om (for angle omega) represents time in the homotopy
global om; om = 0
global dom; dom = .05
global xmult; xmult=1 # rotation angle multiplier
global ymult; ymult=1
global zmult; zmult=2

global dangle; dangle = 15
#compare with dangle=90
global dgap; dgap = dangle

from OpenGL.GL import *
from OpenGL.GLUT import *
from OpenGL.GLU import *
from math import *
import sys, numpy

svn = sqrt(2)/2.
deg = pi/180
def C(u): return cos(u*deg)
def S(u): return sin(u*deg)

global wd
global ht
global mouseX
global mouseY
global aff
global nrange
nrange = 3.0

aff = [1.0, 0.0, 0.0, 0.0,
0.0, 1.0, 0.0, 0.0,
0.0, 0.0, 1.0, 0.0,
0.0, 0.0, 0.0, 1.0]

def drawvert(th,ta, xmat, ymat, zmat):
   #parametric sphere equations
   #n0= svn*C(th+ta)
   #n1= svn*S(th+ta)
   #n2= svn* C(th-ta)
   #n3= svn*S(th-ta)
   n0= .5*(C(th) + S(th))
   n1= .5*(C(th) - S(th))
   n2= .5*(C(ta) + S(ta))
   n3= .5*(C(ta) - S(ta))

   # this is the numpy way of applyig matrix multiplation

   # clifford torus
   denominator = 1-vert[3]
   glVertex3f(vert[0]/denominator, vert[1]/denominator, vert[2]/denominator)

def drawsurf():
   global om #needed because it is changed in the function
   global dom
   matc=C(xmult*om); mats=S(xmult*om)
   matc=C(ymult*om); mats=S(ymult*om)
   matc=C(zmult*om); mats=S(zmult*om)
   om += dom
   glPolygonMode(GL_FRONT_AND_BACK, GL_LINE)
   for th in range(0 ,360+dangle,dangle):
      for ta in range (0,360+dangle, dangle):
         drawvert(th,ta, xmat, ymat, zmat)
         drawvert(th+dgap,ta, xmat, ymat, zmat)
#assign initial window and mouse settings
wd = 800
ht = 800
mouseX = wd/2
mouseY = ht/2

brake = 500.

def display():

#typical keyboard callback
def keyboard(key, x, y):
   if key == chr(27) or key == 'q':

#adjust to resizing of the window
def reshape(width, height):
   global wd
   global ht
    glClearColor(0.0, 0.0, 0.0, 0.0)
   if height == 0:
      height = 1
   wd = width
   ht = height
   if wd<=ht:

#Note that we must declare the globals again
def chaptrack():
   global mouseX
   global mouseY
   global wd
   global ht
   global aff
   dx = (mouseX-wd/2)/brake
   if dx*dx < .1:
      dx =0
   dy = (mouseY-ht/2)/brake;
   if dy*dy < .1:
      dy =0
   aff = glGetFloatv(GL_TEXTURE_MATRIX)

#traditional idle
def idle():

#ditto traditional mousemotion
def mousemotion(x,y):
   global mouseX
   global mouseY
   mouseX = x
   mouseY = y

def init():

#Traditional main subroutine
def main() :
   global wd
   global ht
   glutInitDisplayMode(GLUT_RGB | GLUT_DEPTH | GLUT_DOUBLE)
   glutInitWindowPosition(50, 50)
   glutInitWindowSize(wd, ht)


if __name__=="__main__":