0001"""
0002**sphere** in space
0003"""
0004
0005__Defs__ =      ['Sphere']
0006
0007__Classes__ =   ['CenterSphere', 'OrthoSphere', 'CircumSphere']
0008
0009__all__= __Classes__ + __Defs__
0010
0011__doc_hints__={'m_type':'factory'}
0012
0013import pygeo.base.abstracts._real as Real
0014
0015from pygeo.base.analytics.pygeomath import sqrt
0016
0017
0018class CenterSphere(Real._Sphere):
0019    """
0020*sphere* with center at 1st given **point** and through 2nd given **point**
0021    
0022    inherits
0023    
0024        `_Sphere`__
0025
0026__ class-base.abstracts._real._Sphere.html        
0027    
0028    """
0029    __doc_hints__=  {'factory':'Sphere',
0030                    'args':['point1,point2']}
0031
0032    def __init__(self,center,cpoint,**kws):
0033        self.linewidth=kws.get('linewidth',.2)
0034        Real._Sphere.__init__(self,*[center,cpoint],**kws)
0035        self._cpoint=cpoint
0036        self._center=center
0037        self.init()
0038
0039    def findSelf(self):
0040        self._radiusSquared = self._center.distanceSquared(self._cpoint)
0041        self._radius=sqrt(self._radiusSquared)
0042        return True
0043
0044
0045class OrthoSphere(Real._Sphere):
0046    """
0047*sphere* with center at given **point** and orthogonal to given **sphere**
0048    
0049    inherits
0050    
0051        `_Sphere`__
0052
0053__ class-base.abstracts._real._Sphere.html        
0054    
0055    """
0056    __doc_hints__=  {'factory':'Sphere',
0057                    'args':['sphere,point'],
0058                    'conditions':['point exterior to sphere'],
0059                    'otherwise':'None'}
0060
0061    def __init__(self,sphere,center,**kws):
0062        Real._Sphere.__init__(self,*[sphere,center],**kws)
0063        self.sphere=sphere
0064        self._center=center
0065        self.deps=[self._cpoint]
0066        self.init()
0067
0068    def findSelf(self):
0069        s_radius=self.sphere._radius
0070        pdist = self.sphere._center.distance(self._center)-s_radius
0071        rsqr =pdist*(2*s_radius+pdist)
0072        if rsqr <= 0:
0073            print self.__class__.__name__
0074            print """point is interior to sphere, othogonal sphere undefined, 
0075                    returned False"""
0076            return False
0077        self._cpoint.set(self._center.norm()*sqrt(rsqr)+self._center)
0078        self._radiusSquared = self._center.distanceSquared(self._cpoint)
0079        self._radius=sqrt(self._radiusSquared)
0080        return True
0081
0082
0083class CircumSphere(Real._Sphere):
0084    """
0085*sphere* through the **4 given points**
0086    
0087    inherits
0088    
0089        `_Sphere`__
0090
0091__ class-base.abstracts._real._Sphere.html        
0092    
0093    """
0094    __doc_hints__=  {'factory':'Sphere',
0095                    'args':['point1,point2,point3,point4'],
0096                    'conditions':['points distinct'],
0097                    'otherwise':'None'}
0098
0099    def __init__(self,p1,p2,p3,p4,**kws):
0100        self.p1=p1
0101        self.p2=p2
0102        self.p3=p3
0103        self.p4=p4
0104        Real._Sphere.__init__(self,*[p1,p2,p3,p4],**kws)
0105        self._cpoint=self.p1
0106        self.deps=[self._center]
0107        self.init()
0108
0109    def findSelf(self):
0110        if self._center.toSphereCenter(self.p1,self.p2,self.p3,self.p4):
0111            self._radiusSquared = self._center.distanceSquared(self._cpoint)
0112            self._radius=sqrt(self._radiusSquared)
0113            return True
0114        else:
0115            return False
0116
0117def  Sphere(*args,**kws):
0118    """
0119'class factory' function returns instance of object derived from 
0120the _Sphere abstract class
0121    """
0122
0123    from pygeo.base.abstracts._element import method_get
0124    from pygeo.base.support.pygeoexceptions import Argument_Type_Error
0125    from pygeo.base.analytics.pygeomath import vector
0126
0127    __sigs__=[[vector,vector],[Real._Sphere,vector],
0128             [vector,vector,vector,vector]]
0129    t,i = method_get(__sigs__,args)
0130
0131    if t is None:
0132        raise Argument_Type_Error(__sigs__,args)
0133    else:
0134        if i == 0:
0135            return CenterSphere(t[0],t[1],**kws)
0136        elif i == 1:
0137            return OrthoSphere(t[0],t[1],**kws)
0138        elif i==2:
0139            return CircumSphere(t[0],t[1],t[2],t[3],**kws)
0140        else:
0141            raise Argument_Type_Error(__sigs__,args)