point3.py
'''\
Python 3D Point Class.
Extending the 2D Point class to three dimensions.
The sub-class adds a Z coordinate to the implementation
and an Elevation angle to the polar coordinates.
Developer@Sonnack.com
April 2010
'''
from sys import stdout, stderr, argv
import math
from point2 import point2
class point3 (point2):
'''A 3D Point Class based on the 2D Point Class.'''
def __init__ (self, x=0, y=0, z=0):
super(point3,self).__init__(x,y)
self.z = z
def reset (self):
''' Move the Point to 0,0,0. '''
super(point3,self).reset()
self.z = 0
return self
def set (self, x=0, y=0, z=0):
''' Move the Point to an absolute coordinate (x,y,z). '''
super(point3,self).set(x,y)
self.z = z
return self
def move (self, x=0, y=0, z=0):
''' Move the Point relative to itself (+x,+y,+z). '''
super(point3,self).move(x,y)
self.z += z
return self
def radius (self):
''' Radius: x^2 + y^2 + z^2 = r^2. '''
return math.sqrt((self.x ** 2)+(self.y ** 2)+(self.z ** 2))
def elevation (self):
''' Elevation: arc tangent of z/xy. '''
xy = math.hypot(self.x, self.y)
return math.degrees(math.atan2(self.z, xy))
def distance (self, other):
''' Distance from one point to another. '''
dx = math.fabs(self.x - other.x)
dy = math.fabs(self.y - other.y)
dz = math.fabs(self.z - other.z)
return math.sqrt((dx*dx)+(dy*dy)+(dz*dz))
def getList (self):
''' Return Point as a List object. '''
return [self.x, self.y, self.z]
def getTuple (self):
''' Return Point as a Tuple object. '''
return (self.x, self.y, self.z)
def coord (self):
''' Return pretty coordinate version. '''
return "(%.3f,%.3f,%.3f)" % (self.x, self.y, self.z)
def polar (self):
''' Return pretty polar version. '''
return "[%.3f@%.3f@%.3f]" % (self.radius(), self.angle(), self.elevation())
def __str__ (self):
''' Return pretty version. '''
s = "%.4f,%.4f,%.4f"
t = (self.x, self.y, self.z)
return s % t
def __repr__ (self):
''' Return Point as a serializable object (JSON). '''
s = "{point3:{x:%f, y:%f, z:%f}}"
t = (self.x, self.y, self.z)
return s % t
def __len__ (self):
''' A point's length is its radius as an integer. '''
return int(self.radius())
def __cmp__ (self, other):
''' Points compare equal if they are really close. '''
diff = self.angle() - other.angle()
if math.fabs(diff) < self.tiny:
diff = self.elevation() - other.elevation()
if math.fabs(diff) < self.tiny:
diff = self.radius() - other.radius()
if math.fabs(diff) < self.tiny:
return 0
if int(diff) == 0:
return -1 if (diff < 0) else +1
return int(diff)
def __nonzero__ (self):
''' Point is non-zero if outside a tiny radius. '''
offset = self.radius()
if math.fabs(offset) < self.tiny:
return True
return False
class point (point3):
'''A generic alias.'''
pass
def demo1 ():
''' Just shows the Point in action.
(And proves the class works.)
'''
p0 = point()
p1 = point(10, 10, 10)
p2 = point(10, 20)
p3 = point(10, -20, 8)
p4 = point(0, 5, 7)
p5 = point(-10, 20, 9)
print p0, p1, p2, p3, p4, p5
print
list_point3("P0", p0)
list_point3("P1", p1)
list_point3("P2", p2)
list_point3("P3", p3)
list_point3("P4", p4)
list_point3("P5", p5)
p1.reset()
list_point3("P1.reset", p1)
p1.set(-10,10,-5)
list_point3("P1.set", p1)
p1.move(1,1,1)
list_point3("P1.move", p1)
p1.move(1,1,1)
list_point3("P1.move", p1)
ps = [p0, p1, p2, p3, p4, p5]
print ps
print
print sorted(ps)
return ps
def list_point3 (s, p):
print "%s.coord: %.3f,%.3f,%.3f" % (s, p.x, p.y, p.z)
print "%s.polar: %.3f,%.3f,%.3f" % (s, p.angle(), p.radius(), p.elevation())
if __name__ == "__main__":
print 'autorun:',argv[0]
obj = demo1()
'''eof'''