0001"""
0002**plane** oriented in space 
0003"""
0004
0005__Defs__ =      ['Plane']
0006
0007__Classes__ =   ['PlaneFromPoints', 'ParaPointPlane', 'ParaLinesPlane',
0008                'PerpPlane', 'PlaneFromNormal', 'PolarPlane', 'Triangle']
0009
0010__all__= __Classes__+ __Defs__
0011
0012__doc_hints__={'m_type':'factory'}
0013
0014import pygeo.base.abstracts._real as Real
0015
0016from pygeo.base.analytics.pygeomath import cross3
0017from pygeo.base.support.pygeoconstants import CYAN, LINES
0018
0019
0020class PlaneFromPoints(Real._Plane):
0021    """
0022*plane* through the **3 given points**    
0023    
0024    inherits
0025    
0026        `_Plane`__
0027
0028__ class-base.abstracts._real._Plane.html       
0029    
0030    """
0031
0032    __doc_hints__=  {'factory':'Plane',
0033                    'args':['point1,point2,point3'],
0034                    'conditions':['points distinct','points not collinear'],
0035                    'otherwise':'None; None'}
0036
0037    def __init__(self,p1,p2,p3,**kws):
0038        self.p1=p1
0039        self.p2=p2
0040        self.p3=p3
0041        Real._Plane.__init__(self,*[p1,p2,p3],**kws)
0042        self.init()
0043
0044    def findSelf(self):
0045        if self.set_uds_fromPoints():
0046            return True
0047        else:
0048            return False
0049
0050
0051class ParaPointPlane(Real._Plane):
0052    """
0053*plane* through the given **point** and parallel to the given **plane**
0054    
0055    inherits
0056    
0057        `_Plane`__
0058
0059__ class-base.abstracts._real._Plane.html       
0060    
0061    """
0062
0063    __doc_hints__=  {'factory':'Plane',
0064                    'args':['plane,point']}
0065
0066    def __init__(self,plane,p1,**kws):
0067        self.plane=plane
0068        self.p1=p1
0069        Real._Plane.__init__(self,*[plane,p1],**kws)
0070        self.init()
0071
0072    def findSelf(self):
0073        self._u.set(self.plane._u)
0074        self._d=self._u.dot(self.p1)
0075        self._s.set(self.plane._s)
0076        return True
0077
0078class ParaLinesPlane(Real._Plane):
0079    """
0080*plane* through the given **point** and parallel to the given **2 lines**.
0081    
0082    inherits
0083    
0084        `_Plane`__
0085
0086__ class-base.abstracts._real._Plane.html       
0087    
0088    """
0089
0090    __doc_hints__=  {'factory':'Plane',
0091                    'args':['line1,line2,point'],
0092                    'conditions':['lines are distinct'],
0093                    'otherwise':'None'}
0094
0095    def __init__(self,line1,line2,point,**kws):
0096        self.line1=line1
0097        self.line2=line2
0098        self.point=point
0099        Real._Plane.__init__(self,*[line1,line2,point],**kws)
0100        self.init()
0101
0102    def findSelf(self):
0103        try:
0104            self._s.set(self.line1.getDirection())
0105            self._u.set((self._s.cross(self.line2.getDirection())).norm())
0106            self._d=self._u.dot(self.point)
0107            return True
0108        except ZeroDivisionError:
0109            print self.__class__.__name__
0110            print """lines are not distinct, no parallel plane defined, 
0111                  returned False"""
0112            return False
0113
0114
0115class PerpPlane(Real._Plane):
0116    """
0117*plane* through the given **2 points** and perpendicular to the given **plane**
0118    
0119    inherits
0120    
0121        `_Plane`__
0122
0123__ class-base.abstracts._real._Plane.html       
0124    
0125    """
0126
0127    __doc_hints__=  {'factory':'Plane',
0128                    'args':['plane,point1,point2'],
0129                    'conditions':['points are distinct'],
0130                    'otherwise':'None'}
0131
0132    def __init__(self,plane,p1,p2,**kws):
0133        self.plane=plane
0134        self.p1=p1
0135        self.p2=p2
0136        Real._Plane.__init__(self,*[plane,p1,p2],**kws)
0137        self.init()
0138
0139    def findSelf(self):
0140        try:
0141            self._s.set((self.p2-self.p1).norm())
0142            self._u.set((self._s.cross(self.plane._u)).norm())
0143            self._d=self._u.dot(self.p1)
0144            return True
0145        except ZeroDivisionError:
0146            print self.__class__.__name__
0147            print """points are not distinct, not perpendicular plane defined, 
0148                  returned False"""
0149            return False
0150
0151
0152class PlaneFromNormal(Real._Plane):
0153    """
0154*plane* normal to the line connecting given **2 points** and on the 2nd 
0155given point
0156    
0157    inherits
0158    
0159        `_Plane`__
0160
0161__ class-base.abstracts._real._Plane.html       
0162    
0163    """
0164
0165    __doc_hints__=  {'factory':'Plane',
0166                    'args':['point1,point2'],
0167                    'conditions':['points are distinct'],
0168                    'otherwise':'None'}
0169
0170    def __init__(self,p1,p2,**kws):
0171        self.p1=p1
0172        self.p2=p2
0173        Real._Plane.__init__(self,*[p1,p2],**kws)
0174        self.args=[self.p1,self.p2]
0175        self.init()
0176
0177    def findSelf(self):
0178       try:
0179           self._u.set((self.p2-self.p1).norm())
0180           self._d = self._u.dot(self.p2)
0181           self.set_s_from_u(self._u)
0182           return True
0183       except ZeroDivisionError:
0184           print self.__class__.__name__
0185           print """points are not distinct, plane from normal undefined, 
0186                 returned False"""
0187           return False
0188
0189
0190class PolarPlane(Real._Plane):
0191    """
0192*plane* polar to the given **point** with respect to the given **sphere**
0193    
0194    inherits
0195    
0196        `_Plane`__
0197
0198__ class-base.abstracts._real._Plane.html       
0199    
0200    """
0201
0202    __doc_hints__=  {'factory':'Plane',
0203                    'args':['sphere,point'],
0204                    'conditions':['point not at sphere center'],
0205                    'otherwise':'None'}
0206
0207    def __init__(self,sphere,pole,**kws):
0208        self.sphere=sphere
0209        self.pole=pole
0210        Real._Plane.__init__(self,*[sphere,pole],**kws)
0211        self.init()
0212
0213    def findSelf(self):
0214        pole=self.pole
0215        sphere=self.sphere
0216        try:
0217            self._u.set((pole-sphere._center).norm())
0218            factor = float(sphere._radiusSquared)/pole.distance(sphere._center)
0219            t=self._u*factor+self.sphere._center
0220            self._d =  self._u.dot(t)
0221            self.set_s_from_u(self._u)
0222            return True
0223        except ZeroDivisionError:
0224            print self.__class__.__name__
0225            print """point at sphere center, polar plane at infinity, 
0226                  returned False"""
0227            return False
0228
0229
0230class Triangle(Real._Triangle):
0231    """
0232*triangle* connecting the given **3 points**
0233    
0234    inherits
0235    
0236        `_Triangle`__
0237
0238__ class-base.abstracts._real._Triangle       
0239    
0240    """
0241
0242    __doc_hints__=  {'factory':'Plane',
0243                    'args':['oint1,point2,point3'],
0244                    'qualifier':'TRIANGLE',
0245                    'conditions':['points distinct','points not collinear'],
0246                    'otherwise':'None; None'}
0247
0248    def __init__(self,p1,p2,p3,**kws):
0249        Real._Triangle.__init__(self,*[p1,p2,p3],**kws)
0250        self.p1=p1
0251        self.p2=p2
0252        self.p3=p3
0253        self.color = (kws.get("color",CYAN))
0254        self.style=kws.get('style',LINES)
0255        self.linewidth = (kws.get("linewidth",.3))
0256        self.init()
0257
0258    def findSelf(self):
0259        try:
0260            self._u.set(cross3(self.p1,self.p2,self.p3).norm())
0261            self._d=self._u.dot(self.p1)
0262            self._s.set((self.p1-self.p2).norm())
0263            return True
0264        except ZeroDivisionError:
0265            print self.__class__.__name__
0266            print """points are not distinct or collinear, triangle from points 
0267                  undefined, returned False"""
0268            return False
0269
0270def  Plane(*args,**kws):
0271    """
0272'class factory' function returns instance of object derived from the 
0273_Plane abstract class,  a 2 dimensional surface spanned by two linearly 
0274independent vectors
0275    """
0276
0277    from pygeo.base.abstracts._element import method_get
0278    from pygeo.base.support.pygeoexceptions import Argument_Type_Error
0279    from pygeo.base.analytics.pygeomath import vector
0280    from pygeo.base.support.pygeoconstants import PLANE, TRIANGLE
0281
0282    __sigs__=[  [vector,vector,vector],[Real._Plane,vector],
0283                [Real._Line,Real._Line,vector], [Real._Plane,vector,vector],
0284                [vector,vector], [Real._Sphere,vector],
0285                [vector,vector,vector,float]]
0286
0287    t,i = method_get(__sigs__,args)
0288
0289    if t is None:
0290        raise Argument_Type_Error(__sigs__,args)
0291    else:
0292        if i == 0:
0293            return PlaneFromPoints(t[0],t[1],t[2],**kws)
0294        elif i == 1:
0295            return ParaPointPlane(t[0],t[1],**kws)
0296        elif i == 2:
0297            return ParaLinesPlane(t[0],t[1],t[2],**kws)
0298        elif i == 3:
0299            return PerpPlane(t[0],t[1],t[2],**kws)
0300        elif i==4:
0301            return PlaneFromNormal(t[0],t[1],**kws)
0302        elif i==5:
0303            return PolarPlane(t[0],t[1],**kws)
0304        elif i==6:
0305            if t[3] == PLANE:
0306                return PlaneFromPoints(t[0],t[1],t[2],**kws)
0307            elif t[3] ==TRIANGLE:
0308                return Triangle(t[0],t[1],t[2],**kws)
0309            else:
0310                raise Argument_Type_Error(__sigs__,args)
0311        else:
0312            raise Argument_Type_Error(__sigs__,args)