point2.py

'''\
Python 2D Point Class.

A two-dimensional point is implemented as an intelligent tuple.
The value is stored as an X,Y coordinate, but the object can also
return the polar coordinates (Radius and Angle).

Note that, since Python class members are public, the class state
is readable and writeable.  It should be, at the least, read-only, 
but ideally, private to the class.

Developer@Sonnack.com
April 2010
'''
####################################################################################################
from sys import stdoutstderrargv
import math
####################################################################################################


##~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~##
## 2D POINT
##~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~##
class point2 (object):
    '''Your basic 2D Point Class!'''
    tiny = 0.000001

    def __init__ (selfx=0y=0):
        self.x = x
        self.y = y

    def reset (self):
        ''' Move the Point to 0,0. '''
        self.x = 0
        self.y = 0
        return self

    def set (selfx=0y=0):
        ''' Move the Point to an absolute coordinate (x,y). '''
        self.x = x
        self.y = y
        return self

    def move (selfx=0y=0):
        ''' Move the Point relative to itself (+x,+y). '''
        self.x += x
        self.y += y
        return self


    def radius (self):
        ''' Radius: x^2 + y^2 = r^2. '''
        return math.hypot(self.xself.y)

    def angle (self):
        ''' Angle: arc tangent of y/x. '''
        return math.degrees(math.atan2(self.yself.x))

    def distance (selfother):
        ''' Distance from one point to another. '''
        dx = math.fabs(self.x - other.x)
        dy = math.fabs(self.y - other.y)
        return math.hypot(dxdy)


    def getList (self):
        ''' Return Point as a List object. '''
        return [self.xself.y]

    def getTuple (self):
        ''' Return Point as a Tuple object. '''
        return (self.xself.y)


    def coord (self):
        ''' Return pretty coordinate version. '''
        return "(%.3f,%.3f)" % (self.xself.y)

    def polar (self):
        ''' Return pretty polar version. '''
        return "[%.3f@%.3f]" % (self.radius(), self.angle())

    def __str__ (self):
        ''' Return pretty version. '''
        s = "%.4f,%.4f"
        t = (self.xself.y)
        return s % t

    def __repr__ (self):
        ''' Return Point as a serializable object (JSON). '''
        s = "{point2:{x:%f, y:%f}}"
        t = (self.xself.y)
        return s % t

    def __len__ (self):
        ''' A point's length is the radius as an integer. '''
        return int(self.radius())


    def __cmp__ (selfother):
        ''' Points compare equal if they are really close. '''
        diff = self.angle() - other.angle()
        # if angles are nearly the same, compare based on radius...
        if math.fabs(diff) < self.tiny:
            diff = self.radius() - other.radius()
            # if the radii are also nearly the same, just consider the points equal...
            if math.fabs(diff) < self.tiny:
                return 0
        # if the difference sub-integer, use "hysteresis"...
        if int(diff) == 0:
            return -1 if (diff < 0else +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

##~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~##
## POINT
##~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~##
class point (point2):
    '''A generic alias.'''
    pass



##================================================================================================##
def demo1 ():
    ''' Just shows the Point in action.
        (And proves the class works.)
    '''
    p1 = point()
    p2 = point(4,3)
    print p1p2
    print "repr: "repr(p1), repr(p2)
    print "str:"str(p1), str(p2)
    print "len: "len(p1), len(p2)
    list_point2("P0"p1)
    list_point2("P2"p2)
    compare_points(p1p2)

    p2.reset()
    print "p2.reset(): %s" % p2
    list_point2("P2"p2)
    compare_points(p1p2)

    p1.set5,5)
    p2.set(-8,6)
    print "p1.set( 5, 5): %s" % p1
    print "p2.set(-8, 6): %s" % p2
    list_point2("P0"p1)
    list_point2("P2"p2)
    compare_points(p1p2)

    p1.move(-10,-10)
    print "p1.move(-10,-10): %s" % p1
    list_point2("P0"p1)
    compare_points(p1p2)

    return [p1p2]

##================================================================================================##
def compare_points (papb):
    print "p1.compare(p2): %d" % cmp(papb)
    print "p1.distance(p2): %f" % pa.distance(pb)
    print

##================================================================================================##
def list_point2 (sp):
    print "%s.coord: %.3f,%.3f" % (sp.xp.y)
    print "%s.polar: %.3f,%.3f" % (sp.angle(), p.radius())

####################################################################################################
if __name__ == "__main__":
    print 'autorun:',argv[0]
    obj = demo1()

####################################################################################################
'''eof'''