manipulatorMath.py

#-
# ==========================================================================
# Copyright (C) 1995 - 2006 Autodesk, Inc. and/or its licensors.  All 
# rights reserved.
#
# The coded instructions, statements, computer programs, and/or related 
# material (collectively the "Data") in these files contain unpublished 
# information proprietary to Autodesk, Inc. ("Autodesk") and/or its 
# licensors, which is protected by U.S. and Canadian federal copyright 
# law and by international treaties.
#
# The Data is provided for use exclusively by You. You have the right 
# to use, modify, and incorporate this Data into other products for 
# purposes authorized by the Autodesk software license agreement, 
# without fee.
#
# The copyright notices in the Software and this entire statement, 
# including the above license grant, this restriction and the 
# following disclaimer, must be included in all copies of the 
# Software, in whole or in part, and all derivative works of 
# the Software, unless such copies or derivative works are solely 
# in the form of machine-executable object code generated by a 
# source language processor.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND. 
# AUTODESK DOES NOT MAKE AND HEREBY DISCLAIMS ANY EXPRESS OR IMPLIED 
# WARRANTIES INCLUDING, BUT NOT LIMITED TO, THE WARRANTIES OF 
# NON-INFRINGEMENT, MERCHANTABILITY OR FITNESS FOR A PARTICULAR 
# PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE, OR 
# TRADE PRACTICE. IN NO EVENT WILL AUTODESK AND/OR ITS LICENSORS 
# BE LIABLE FOR ANY LOST REVENUES, DATA, OR PROFITS, OR SPECIAL, 
# DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES, EVEN IF AUTODESK 
# AND/OR ITS LICENSORS HAS BEEN ADVISED OF THE POSSIBILITY 
# OR PROBABILITY OF SUCH DAMAGES.
#
# ==========================================================================
#+

import maya.OpenMaya as OpenMaya

# 
# simple plane math class
#
class planeMath:
    a = None
    b = None
    c = None
    d = None

    def __init__(self):
        a = 0
        b = 0
        c = 0
        d = 0

    def setPlane(self,pointOnPlane,normalToPlane):
        _normalToPlane = normalToPlane
        _normalToPlane.normalize()

        # Calculate a,b,c,d based on input
        self.a = _normalToPlane.x
        self.b = _normalToPlane.y
        self.c = _normalToPlane.z
        self.d = -(self.a*pointOnPlane.x + self.b*pointOnPlane.y + self.c*pointOnPlane.z)

    def intersect(self,linePoint,lineDirection):
        intersectionPoint = OpenMaya.MPoint()
        denominator = self.a*lineDirection.x + self.b*lineDirection.y + self.c*lineDirection.z
        # Verify that the vector and the plane are not parallel.
        if denominator < .00001:
            return (False,intersectionPoint)

        t = -(self.d + self.a*linePoint.x + self.b*linePoint.y + self.c*linePoint.z) / denominator

        # Calculate the intersection point.
        scaledLineDirection = OpenMaya.MVector(lineDirection.x*t,lineDirection.y*t,lineDirection.z*t)
        intersectionPoint = linePoint + scaledLineDirection

        return (True,intersectionPoint)


#
# simple line math class
#
class lineMath:

    point = None
    direction = None

    def setLine(self,linePoint,lineDirection):
        self.point = linePoint
        self.direction = lineDirection
        self.direction.normalize()
            
    def closestPoint(self,toPoint):
        t = self.direction * ( toPoint - self.point )
        closest = self.point + ( self.direction * t )
        return (True,closest)
        

#
# simple degree radian converted
class degreeRadianConverter:
    M_PI = 3.14159265358979323846
    def degreesToRadians(self,degrees):
        return degrees * ( self.M_PI / 180.0 )
    def radiansToDegrees(self,radians):
        return radians * ( 180.0  / self.M_PI)

#
# utility function to return the
# value which has the max abs
# -10,3,4 returns -10
def maxOfAbsThree(a,b,c):
    aa = abs(a)
    ab = abs(b)
    ac = abs(c)
    if aa > ab and aa > ac:
        return a
    if ab > aa and ab > ac:
        return b
    return c

#
# tests for the math classes
#
def testModule():
    # degreeRadianConverter
    drc = degreeRadianConverter()
    r = drc.degreesToRadians( 45 )
    print r, " ", r*4

    d = drc.radiansToDegrees( drc.M_PI/4.0 )
    print d

    # lineMath
    lm = lineMath()
    point = OpenMaya.MPoint(0,1,0)
    direction = OpenMaya.MVector( 1,1,0)
    lm.setLine( point, direction )
    toPoint = OpenMaya.MPoint(3,0,0)
    (worked,closestPoint) = lm.closestPoint(toPoint)
    if worked:
        print "closest point to line: %g %g %g" % (closestPoint.x,closestPoint.y,closestPoint.z)
    else:
        print "Failed to find closest point to line"

#
# invoke test if  run from the 
# command line
#
if __name__ == "__main__":
    testModule()