0001"""
0002**circle** oriented in space
0003"""
0004__Def__ =      ['Circle']
0005
0006__Classes__ =   ['CircleOnPlane','CircumCircle', 'CenterCircle',
0007                'InscribedCircle','ExscribedCircle', 'OrthoCircle',
0008                'SphereCircle', 'SpheresIntersect']
0009
0010__all__= __Classes__ + __Def__
0011
0012__doc_hints__={'m_type':'factory'}
0013
0014import pygeo.base.abstracts._real as Real
0015
0016from pygeo.base.analytics.pygeomath import sqrt, cross3
0017from pygeo.base.support.pygeoopts import DO_TESTS
0018from pygeo.base.analytics._position3 import Position3
0019
0020
0021class CircumCircle(Real._Circle):
0022    """
0023*circle* passing through the **3 given points** 
0024    
0025    inherits
0026    
0027        `_Circle`__
0028
0029__ class-base.abstracts._real._Circle.html        
0030    
0031    """
0032
0033    __doc_hints__=  {'factory':'Circle',
0034                    'args':['point1,point2,point3'],
0035                    'qualifier':'CIRCUM',
0036                    'conditions':['points distinct'],
0037                    'otherwise':'None'}
0038
0039    def __init__(self,p1,p2,p3,**kws):
0040        self.p1=p1
0041        self.p2=p2
0042        self.p3=p3
0043        Real._Circle.__init__(self,*[p1,p2,p3],**kws)
0044        self.deps=[self._center]
0045        self._cpoint=self.p2
0046        self.init()
0047
0048    def findSelf(self):
0049        if self._center.toCircumCenter(self.p1,self.p2,self.p3):
0050            self._radiusSquared=self._center.distanceSquared(self._cpoint)
0051            self._radius=sqrt(self._radiusSquared)
0052            self.set_uds_fromPoints()
0053            return True
0054        else:
0055            self._u=Position3(0,0,1)
0056            self._s=Position3(0,0,1)
0057            self._d=0
0058            return False
0059
0060
0061class CenterCircle(Real._Circle):
0062    """
0063*circle* with first point at center, second on circumference and on the plane 
0064of the **3 points**
0065    
0066    inherits
0067    
0068        `_Circle`__
0069
0070__ class-base.abstracts._real._Circle.html        
0071    
0072    """
0073
0074    __doc_hints__=  {'factory':'Circle',
0075                    'args':['point1,point2,point3'],
0076                    'conditions':['points distinct'],
0077                    'otherwise':'None'}
0078
0079    def __init__(self,p1,p2,p3,**kws):
0080        self.p1=p1
0081        self.p2=p2
0082        self.p3=p3
0083        Real._Circle.__init__(self,*[p1,p2,p3],**kws)
0084        self._cpoint=self.p2
0085        self._center=self.p1
0086        self.init()
0087
0088    def findSelf(self):
0089        self._radiusSquared=self._center.distanceSquared(self._cpoint)
0090        self._radius=sqrt(self._radiusSquared)
0091        try:
0092            self._u=cross3(self.p1,self.p2,self.p3).norm()
0093            self._d=self._u.dot(self.p1)
0094            self._s=(self.p1-self.p2).norm()
0095            return True
0096        except ZeroDivisionError:
0097            print self.__class__.__name__
0098            print "points are not distinct, circle undefined, returned False"
0099            return False
0100
0101
0102class InscribedCircle(Real._Circle):
0103    """
0104*circle* inscribed in the **3 given points'** triangle
0105    
0106    inherits
0107    
0108        `_Circle`__
0109
0110__ class-base.abstracts._real._Circle.html        
0111    
0112    """
0113
0114    __doc_hints__=  {'factory':'Circle',
0115                    'args':['point1,point2,point3'],
0116                    'qualifier':'INSCRIBED',
0117                    'conditions':['points distinct'],
0118                    'otherwise':'None'}
0119
0120    def __init__(self,p1,p2,p3,**kws):
0121        self.p1=p1
0122        self.p2=p2
0123        self.p3=p3
0124        Real._Circle.__init__(self,*[p1,p2,p3],**kws)
0125        self.deps=[self._center,self._cpoint]
0126        self.init()
0127
0128    def findSelf(self):
0129        try:
0130            self._center.toInCenter(self.p1,self.p2,self.p3)
0131            self._cpoint.set(self._center)
0132            self._cpoint.toLine(self.p1,self.p2)
0133            self._radiusSquared=self._center.distanceSquared(self._cpoint)
0134            self._radius=sqrt(self._radiusSquared)
0135            self.set_uds_fromPoints()
0136            return True
0137        except ZeroDivisionError:
0138            print self.__class__.__name__
0139            print "points are not distinct, circle undefined, returned False"
0140            return False
0141
0142
0143class ExscribedCircle(Real._Circle):
0144    """
0145*circle* exscribed in the **3 given points'** triangle, 
0146in the side opp the 1st point
0147    
0148    inherits
0149    
0150        `_Circle`__
0151
0152__ class-base.abstracts._real._Circle.html        
0153    
0154    """
0155
0156    __doc_hints__=  {'factory':'Circle',
0157                    'args':['point1,point2,point3'],
0158                    'qualifier':'EXSCRIBED',
0159                    'conditions':['points distinct'],
0160                    'otherwise':'None'}
0161
0162    def __init__(self,p1,p2,p3,**kws):
0163        self.p1=p1
0164        self.p2=p2
0165        self.p3=p3
0166        Real._Circle.__init__(self,*[p1,p2,p3],**kws)
0167        self.deps=[self._center,self._cpoint]
0168        self.init()
0169
0170    def findSelf(self):
0171        try:
0172            self._center.toExCenter(self.p1,self.p2,self.p3)
0173            self._cpoint.set(self._center)
0174            self._cpoint.toLine(self.p1,self.p2)
0175            self._radiusSquared=self._center.distanceSquared(self._cpoint)
0176            self._radius=sqrt(self._radiusSquared)
0177            self.set_uds_fromPoints()
0178            return True
0179        except ZeroDivisionError:
0180            print self.__class__.__name__
0181            print "points are not distinct, circle undefined, returned False"
0182            return False
0183
0184
0185class OrthoCircle(Real._Circle):
0186    """
0187*circle* with center at the given **point** and orthogonal to the 
0188given **circle**
0189    
0190    inherits
0191    
0192        `_Circle`__
0193
0194__ class-base.abstracts._real._Circle.html        
0195    
0196    """
0197
0198    __doc_hints__=  {'factory':'Circle',
0199                    'args':['circle,point'],
0200                    'conditions':['point and circle are coplanar',
0201                                'point exterior to circle'],
0202                    'otherwise':'None; None'}
0203
0204    def __init__(self,circle,point,**kws):
0205        self.circle=circle
0206        self.point=point
0207        Real._Circle.__init__(self,*[circle,point],**kws)
0208        self.deps=[self._cpoint]
0209        self._center=self.point
0210        self.init()
0211
0212    def findSelf(self):
0213        if DO_TESTS:
0214            t=self.point.onPlane(self.circle)
0215        else:
0216            t =True
0217        if t:
0218            self._d = self.circle._d
0219            self._u.set(self.circle._u)
0220            self._s.set(self.circle._s)
0221            pdist= self.circle._center.distance(self._center)-self.circle._radius
0222            self._radiusSquared=rsqr = pdist*(2*self.circle._radius+pdist)
0223            if rsqr < 0:
0224                print self.__class__.__name__
0225                print """point is interior to circle, orthocircle through point as 
0226                      center is undefined, returned False"""
0227                return False
0228            self._radius=rad=sqrt(rsqr)
0229            self._cpoint.set(self._s*rad+self._center)
0230            return True
0231        else:
0232            print self.__class__.__name__
0233            print "circle and point are not coplanar, orthocircle undefined, returned False"
0234            return False
0235
0236
0237class SphereCircle(Real._Circle):
0238    """
0239*circle* section of the intersection of given **sphere** and given **plane**
0240    
0241     inherits
0242    
0243        `_Circle`__
0244
0245__ class-base.abstracts._real._Circle.html        
0246   
0247    """
0248    __doc_hints__=  {'factory':'Circle',
0249                    'args':['sphere,plane'],
0250                    'conditions':['sphere and plane intersection is real'],
0251                    'otherwise':'None'}
0252
0253    def __init__(self,sphere,plane,**kws):
0254        self.sphere=sphere
0255        self.plane=plane
0256        Real._Circle.__init__(self,*[sphere,plane],**kws)
0257        self.deps=[self._center,self._cpoint]
0258        self.init()
0259
0260    def findSelf(self):
0261        self._d = self.plane._d
0262        self._u.set(self.plane._u)
0263        self._s.set(self.plane._s)
0264        self._center.set(self.sphere._center)
0265        self._center.toPlane(self.plane)
0266        pdist = self._center.distanceSquared(self.sphere._center)
0267        self._radiusSquared = rsqr=self.sphere._radiusSquared-pdist
0268        if rsqr < 0:
0269            print self.__class__.__name__
0270            print "no real plane, sphere intersection, returned false"
0271            return False
0272        self._radius=rad=sqrt(rsqr)
0273        self._cpoint.set(self._s*rad+self._center)
0274        return True
0275
0276
0277class SpheresIntersect(Real._Circle):
0278    """
0279*circle* section determined by the intersection of the **2 given spheres**
0280    
0281    inherits
0282    
0283        `_Circle`__
0284
0285__ class-base.abstracts._real._Circle.html        
0286    
0287    """
0288    __doc_hints__=  {'factory':'Circle',
0289                    'args':['sphere1,sphere2'],
0290                    'conditions':['spheres intersection is real',
0291                                'spheres are not concentric'],
0292                    'otherwise':'None; None'}
0293
0294    def __init__(self,sphere1,sphere2,**kws):
0295        self.sphere1=sphere1
0296        self.sphere2=sphere2
0297        Real._Circle.__init__(self,*[sphere1,sphere2],**kws)
0298        self.deps=[self._center,self._cpoint]
0299        self.init()
0300
0301    def findSelf(self):
0302        sphere1=self.sphere1
0303        sphere2=self.sphere2
0304        tnormal= sphere1._center - sphere2._center
0305        rsum = sphere1._radius+ sphere2._radius
0306        tlen=  tnormal.mag2
0307        if tlen > rsum**2:
0308            print self.__class__.__name__
0309            print "spheres do not intersect, not real intersection, returned false"
0310            return False
0311        try:
0312            t = 0.5*(1.0+(sphere1._radiusSquared-sphere2._radiusSquared)/tlen)
0313        except ZeroDivisionError:
0314            print self.__class__.__name__
0315            print "spheres are concentric, no intersection defined, returned false"
0316            return False
0317        normal=tnormal*t
0318        self._d=normal.mag
0319        self._u.set(normal.norm())
0320        self.set_s_from_u(self._u)
0321        self._center.set(sphere1._center-normal)
0322        self._radiusSquared = rsqr=sphere1._radiusSquared - (t**2)*tlen
0323        if rsqr < 0:
0324            print self.__class__.__name__
0325            print "a sphere is interior to the other, not real intersection, returned false"
0326            return False
0327        self._radius=rad=sqrt(rsqr)
0328        self._cpoint.set(self._s*rad+self._center)
0329        return True
0330
0331class CircleOnPlane(Real._Circle):
0332    """
0333*circle* of the given **plane** with 1st given **point** at center, 2nd **point** on 
0334circumference
0335    
0336    inherits
0337    
0338        `_Circle`__
0339
0340__ class-base.abstracts._real._Circle.html        
0341    
0342    """
0343
0344    __doc_hints__=  {'factory':'Circle',
0345                    'args':['point1,point2,plane'],
0346                    'conditions':['points on plane'],
0347                    'otherwise':'None'}
0348
0349    def __init__(self,p1,p2,plane,**kws):
0350        self.plane=plane
0351        self.p1=p1
0352        self.p2=p2
0353        Real._Circle.__init__(self,*[p1,p2,plane],**kws)
0354        self._cpoint=self.p2
0355        self._center=self.p1
0356        self.init()
0357
0358    def findSelf(self):
0359        if DO_TESTS:
0360            t = (self.p1.onPlane(self.plane) and self.p2.onPlane(self.plane))
0361        else:
0362            t = True
0363        if t:
0364            self._radiusSquared=self._center.distanceSquared(self._cpoint)
0365            self._radius=sqrt(self._radiusSquared)
0366            self._u.set(self.plane._u)
0367            self._d = self.plane._d
0368            self._s.set(self.plane._s)
0369            return True
0370        else:
0371            print self.__class__.__name__
0372            print "points not on plane, circle undefined, returned False"
0373            return False
0374
0375
0376
0377def  Circle(*args,**kws):
0378    """
0379'class factory' function returns instance of object derived from the _Circle 
0380abstract class representing the set of points of a plane equidistant from 
0381a given point of the plane
0382    """
0383
0384    from pygeo.base.abstracts._element import method_get
0385    from pygeo.base.support.pygeoexceptions import Argument_Type_Error
0386    from pygeo.base.analytics.pygeomath import vector
0387    from pygeo.base.support.pygeoconstants import CIRCUM, INSCRIBED, EXSCRIBED
0388
0389    __sigs__=[[vector,vector,Real._Plane],
0390             [vector,vector,vector],[Real._Triangle],
0391             [vector,vector,vector,float],
0392             [Real._Triangle,float],[Real._Circle,vector],[Real._Sphere,Real._Plane],
0393             [Real._Sphere,Real._Sphere]]
0394
0395    t,i = method_get(__sigs__,args)
0396
0397    if t is None:
0398        raise Argument_Type_Error(__sigs__,args)
0399    else:
0400        if i ==0:
0401            return CircleOnPlane(t[0],t[1],t[2],**kws)
0402        elif i == 1:
0403            return CircumCircle(t[0],t[1],t[2],**kws)
0404        elif i == 2:
0405            return CircumCircle(t[0].p1,t[0].p2,t[0].p3,**kws)
0406        elif i==3:
0407            if t[3]== CIRCUM:
0408                return CircumCircle(t[0],t[1],t[2],**kws)
0409            elif t[3] == INSCRIBED:
0410                return InscribedCircle(t[0],t[1],t[2],**kws)
0411            elif t[3] == EXSCRIBED:
0412                return ExscribedCircle(t[0],t[1],t[2],**kws)
0413            else:
0414                raise Argument_Type_Error(__sigs__,args)
0415        elif i==4:
0416            if t[1]== CIRCUM:
0417                return CircumCircle(t[0].p1,t[0].p2,t[0].p3,**kws)
0418            elif t[1] == INSCRIBED:
0419                return InscribedCircle(t[0].p1,t[0].p2,t[0].p3,**kws)
0420            elif t[1] == EXSCRIBED:
0421                return ExscribedCircle(t[0].p1,t[0].p2,t[0].p3,**kws)
0422            else:
0423                raise Argument_Type_Error(__sigs__,args)
0424        elif i==5:
0425            return OrthoCircle(t[0],t[1],**kws)
0426        elif i==6:
0427            return SphereCircle(t[0],t[1],**kws)
0428        elif i==7:
0429            return SpheresIntersect(t[0],t[1],**kws)
0430        else:
0431            raise Argument_Type_Error(__sigs__,args)