diff --git a/basicShapes.py b/basicShapes.py index 3c6a18f..42dc1da 100644 --- a/basicShapes.py +++ b/basicShapes.py @@ -1,19 +1,24 @@ import numpy as np import wireframe as wf -def Cuboid((x,y,z), (w,h,d)): + +def Cuboid(X, size): """ Return a wireframe cuboid starting at (x,y,z) with width, w, height, h, and depth, d. """ + x,y,z = X + w,h,d = size cuboid = wf.Wireframe() cuboid.addNodes(np.array([[nx,ny,nz] for nx in (x,x+w) for ny in (y,y+h) for nz in (z,z+d)])) cuboid.addFaces([(0,1,3,2), (7,5,4,6), (4,5,1,0), (2,3,7,6), (0,2,6,4), (5,7,3,1)]) return cuboid -def Spheroid((x,y,z), (rx, ry, rz), resolution=10): +def Spheroid(X, R, resolution=10): """ Returns a wireframe spheroid centred on (x,y,z) with a radii of (rx,ry,rz) in the respective axes. """ + x,y,z = X + rx, ry, rz = R spheroid = wf.Wireframe() latitudes = [n*np.pi/resolution for n in range(1,resolution)] @@ -34,9 +39,14 @@ def Spheroid((x,y,z), (rx, ry, rz), resolution=10): return spheroid -def HorizontalGrid((x,y,z), (dx,dz), (nx,nz)): +def HorizontalGrid(X, D, N): """ Returns a nx by nz wireframe grid that starts at (x,y,z) with width dx.nx and depth dz.nz. """ + x,y,z = X + dx,dz = D + nx,nz = N + print('x', x, 'y', y, 'z', z, 'dx', dx, 'dy', dy, 'nx', nx, 'nz', nz) + asdfsdf grid = wf.Wireframe() grid.addNodes([[x+n1*dx, y, z+n2*dz] for n1 in range(nx+1) for n2 in range(nz+1)]) grid.addEdges([(n1*(nz+1)+n2,n1*(nz+1)+n2+1) for n1 in range(nx+1) for n2 in range(nz)]) diff --git a/examples.py b/examples.py index 0bdcaa5..9388692 100644 --- a/examples.py +++ b/examples.py @@ -1,63 +1,69 @@ +from __future__ import print_function import math import numpy as np import wireframe as wf import wireframeDisplay as wd import basicShapes as shape + def testWireframe(): """ Example of how to create wireframes node by node, and by using the basicShape module. Creates a triangle and cuboid wireframe and outputs their node, edge and face values. """ - + # Create a triangle by explictly passing the nodes and edges - print "\nTriangle" - triangle = wf.Wireframe([[100,200,10], [200,200,10], [125,100,500]]) - triangle.addEdges([(0,1), (1,2), (2,0)]) + print("\nTriangle") + triangle = wf.Wireframe([[100, 200, 10], [200, 200, 10], [125, 100, 500]]) + triangle.addEdges([(0, 1), (1, 2), (2, 0)]) triangle.output() - + # Create a cuboid using the basicShape module - print "\nCuboid" + print("\nCuboid") cuboid = shape.Cuboid((100,100,10), (20,30,40)) cuboid.output() + def testTranslate(): """ Example of how to translate a wireframe. Creates a cuboid and translates it by vector (4,3,1). """ - + cuboid = shape.Cuboid((100,100,10), (20,30,40)) cuboid.outputNodes() - - print "\n> Translate cuboid along vector [4 3 1]" + + print("\n> Translate cuboid along vector [4 3 1]") cuboid.transform(wf.translationMatrix(4, 3, 1)) cuboid.outputNodes() - + + def testScale(): """ Example of how to scale a wireframe. Creates a cuboid and scales it by 2, centred on (100,150,200). """ - + cuboid = shape.Cuboid((100,100,10), (20,30,40)) cuboid.outputNodes() - print "\n> Scale cuboid by 2, centred at (100,150,200)" + print("\n> Scale cuboid by 2, centred at (100,150,200)") cuboid.transform(wf.scaleMatrix(2, 100, 150, 200)) cuboid.outputNodes() - + + def testRotate(): """ Example of how to rotate a wireframe. Creates a cuboid and rotates about its centre by pi/2 radians. """ - + cuboid = shape.Cuboid((100,100,10), (20,30,40)) cuboid.outputNodes() - + # Find rotation matrix (x,y,z) = cuboid.findCentre() translation_matrix = wf.translationMatrix(-x, -y, -z) rotation_matrix = np.dot(translation_matrix, wf.rotateXMatrix(math.pi/2)) rotation_matrix = np.dot(rotation_matrix, -translation_matrix) - print "\n> Rotate cuboid around its centre and the x-axis" + print("\n> Rotate cuboid around its centre and the x-axis") cuboid.transform(rotation_matrix) cuboid.outputNodes() + def testWireframeGroup(): """ Example of how to create a group of named wireframes. """ @@ -66,6 +72,7 @@ def testWireframeGroup(): g.addWireframe('cube2', shape.Cuboid(( 10,200,10), (10,40,20))) g.output() + def testWireframeDisplay(): """ Create and display a wireframe cube. """ @@ -74,6 +81,7 @@ def testWireframeDisplay(): viewer.displayFaces = False viewer.run() + def testSurfaceDisplayWithCube(): """ Create and display a cube with surfaces. """ @@ -81,7 +89,8 @@ def testSurfaceDisplayWithCube(): viewer.addWireframe('cube', shape.Cuboid((225,100,0), (200,200,200))) viewer.displayEdges = False viewer.run() - + + def testSurfaceDisplayWithSphere(): """ Create and display a cube with surfaces. """ @@ -102,10 +111,11 @@ def testSurfaceDisplayWithSphere(): # colour[1] = 0 # colour[2] = 0 - print "Create a sphere with %d faces." % len(viewer.wireframes['sphere'].faces) + print("Create a sphere with %d faces." % len(viewer.wireframes['sphere'].faces)) viewer.displayEdges = False viewer.run() - + + def testWireframeDisplay3(): """ Create display with two cuboids, a plane and spheroid. """ @@ -116,6 +126,7 @@ def testWireframeDisplay3(): viewer.addWireframe('sphere', shape.Spheroid((250,300, 100), (20,30,40))) viewer.run() + def chooseExample(): examples = ['testWireframe', 'testTranslate', @@ -129,18 +140,18 @@ def chooseExample(): makingChoice = True while makingChoice: - print "\nOptions:" + print("\nOptions:") for i, e in enumerate(examples, 1): - print " %d. %s" % (i, e) - choice = input("\nChoose an option: ") + print(" %d. %s" % (i, e)) + choice = int(input("\nChoose an option: ")) if choice > len(examples)-1: - print '> exit' + print('> exit') makingChoice = False else: - print "> %s" % examples[choice-1] + print("> %s" % examples[choice-1]) exec("%s()" % examples[choice-1]) - + if __name__ == '__main__': chooseExample() diff --git a/wireframe.py b/wireframe.py index 6572d0b..680fbf9 100644 --- a/wireframe.py +++ b/wireframe.py @@ -1,5 +1,7 @@ +from __future__ import print_function import numpy as np + def translationMatrix(dx=0, dy=0, dz=0): """ Return matrix for translation along vector (dx, dy, dz). """ @@ -8,12 +10,14 @@ def translationMatrix(dx=0, dy=0, dz=0): [0,0,1,0], [dx,dy,dz,1]]) + def translateAlongVectorMatrix(vector, distance): """ Return matrix for translation along a vector for a given distance. """ unit_vector = np.hstack([unitVector(vector) * distance, 1]) return np.array([[1,0,0,0],[0,1,0,0],[0,0,1,0], unit_vector]) + def scaleMatrix(s, cx=0, cy=0, cz=0): """ Return matrix for scaling equally along all axes centred on the point (cx,cy,cz). """ @@ -22,6 +26,7 @@ def scaleMatrix(s, cx=0, cy=0, cz=0): [0,0,s,0], [cx*(1-s), cy*(1-s), cz*(1-s), 1]]) + def rotateXMatrix(radians): """ Return matrix for rotating about the x-axis by 'radians' radians """ @@ -32,6 +37,7 @@ def rotateXMatrix(radians): [0,s, c,0], [0,0, 0,1]]) + def rotateYMatrix(radians): """ Return matrix for rotating about the y-axis by 'radians' radians """ @@ -42,6 +48,7 @@ def rotateYMatrix(radians): [-s,0,c,0], [ 0,0,0,1]]) + def rotateZMatrix(radians): """ Return matrix for rotating about the z-axis by 'radians' radians """ @@ -52,9 +59,12 @@ def rotateZMatrix(radians): [0, 0,1,0], [0, 0,0,1]]) -def rotateAboutVector((cx,cy,cz), (x,y,z), radians): + +def rotateAboutVector(C, X, radians): """ Rotate wireframe about given vector by 'radians' radians. """ + cx,cy,cz = C + x,y,z = X # Find angle and matrix needed to rotate vector about the z-axis such that its y-component is 0 rotZ = np.arctan2(y, x) rotZ_matrix = rotateZMatrix(rotZ) @@ -73,7 +83,8 @@ def rotateAboutVector((cx,cy,cz), (x,y,z), radians): return matrix -class Wireframe: + +class Wireframe(object): """ An array of vectors in R3 and list of edges connecting them. """ def __init__(self, nodes=None): @@ -114,19 +125,20 @@ def output(self): self.outputFaces() def outputNodes(self): - print "\n --- Nodes --- " + print("\n --- Nodes --- ") for i, (x, y, z, _) in enumerate(self.nodes): - print " %d: (%d, %d, %d)" % (i, x, y, z) + print(" %d: (%d, %d, %d)" % (i, x, y, z)) def outputEdges(self): - print "\n --- Edges --- " + print("\n --- Edges --- ") for i, (node1, node2) in enumerate(self.edges): - print " %d: %d -> %d" % (i, node1, node2) + print(" %d: %d -> %d" % (i, node1, node2)) def outputFaces(self): - print "\n --- Faces --- " + print("\n --- Faces --- ") for i, nodes in enumerate(self.faces): - print " %d: (%s)" % (i, ", ".join(['%d' % n for n in nodes])) + print('nodes', nodes) + print(" %d: (%s)" % (i, ", ".join(['%d' % n for n in nodes[0]]))) def transform(self, transformation_matrix): """ Apply a transformation defined by a transformation matrix. """ @@ -147,7 +159,8 @@ def update(self): """ Override this function to control wireframe behaviour. """ pass -class WireframeGroup: + +class WireframeGroup(object): """ A dictionary of wireframes and methods to manipulate them all together. """ def __init__(self): @@ -158,17 +171,17 @@ def addWireframe(self, name, wireframe): def output(self): for name, wireframe in self.wireframes.items(): - print name + print(name) wireframe.output() def outputNodes(self): for name, wireframe in self.wireframes.items(): - print name + print(name) wireframe.outputNodes() def outputEdges(self): for name, wireframe in self.wireframes.items(): - print name + print(name) wireframe.outputEdges() def findCentre(self): @@ -185,4 +198,4 @@ def transform(self, matrix): def update(self): for wireframe in self.wireframes.values(): - wireframe.update() \ No newline at end of file + wireframe.update()