0001"""
0002**array of lines** with a defined geometric relationship
0003"""
0004
0005__Def__ =       ['LineArray']
0006
0007__Classes__ =   ['LinePencil', 'Regulus', 'PointMap', 'ArrayMap',
0008                'PlanesPencilIntersect', 'LineMap', 'CorrelationLines']
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._position3 import Position3
0017from pygeo.base.analytics.pygeomath import vector, cross3, array, solve, matrixmultiply,                                   quadratic, transpose, PI, AlgebraError
0019from pygeo.base.support.pygeoopts import DO_TESTS
0020
0021
0022class LinePencil(Real._LineArray):
0023    """
0024*array of equidistant lines* on given **plane** and through given **point**
0025    
0026    inherits
0027    
0028        `_LineArray`__
0029
0030__ class-base.abstracts._real._LineArray.html       
0031     
0032    """
0033
0034    __doc_hints__=  {'factory':'LineArray',
0035                    'args':['point,plane'],
0036                    'conditions':['point on the plane'],
0037                    'otherwise':'None'}
0038
0039    __opts__ = Real._LineArray.__opts__ + ["start"]
0040
0041    def __init__(self,point,plane,**kws):
0042        self.point=point
0043        self.plane=plane
0044        Real._LineArray.__init__(self,*[point,plane],**kws)
0045        self.v=2*PI/self.density
0046        self.start=kws.get("start",0)
0047        self.init()
0048
0049    def findSelf(self):
0050        if DO_TESTS:
0051            t = self.point.onPlane(self.plane)
0052        else:
0053            t = True
0054        if t:
0055            cpoint = self.plane._s*self.drawradius
0056            for i,line in enumerate(self.lines):
0057                rad=i*self.v/2
0058                line.p1.set(cpoint.rotate(rad+self.start,self.plane._u)
0059                            + self.point)
0060                line.p2.set(self.point)
0061            return True
0062        else:
0063            print self.__class__.__name__
0064            print "point not on plane, line array undefined, returned false"
0065            return False
0066
0067
0068class Regulus(Real._LineArray):
0069    """
0070*array of lines* transverse to the given **lines** through given **array of points**
0071    
0072    inherits
0073    
0074        `_LineArray`__
0075
0076__ class-base.abstracts._real._LineArray.html     
0077    
0078    """
0079    __doc_hints__=  {'factory':'LineArray',
0080                    'args':['pointarray,line1,line2'],
0081                    'conditions':['lines distinct'],
0082                    'otherwise':'None'}
0083
0084    def __init__(self,pointpencil,line1,line2,**kws):
0085        self.pointpencil=pointpencil
0086        self.line1=line1
0087        self.line2=line2
0088        Real._LineArray.__init__(self,*[pointpencil,line1,line2],**kws)
0089        self.extend=kws.get("extend",False)
0090        self.density=self.pointpencil.density
0091        self.init()
0092
0093    def findSelf(self):
0094        for line,point in zip(self,self.pointpencil):
0095            l1=self.line1
0096            l2=self.line2
0097            u1=cross3(l1.p1,l1.p2,point)
0098            d1=u1.dot(l1.p1)
0099            u2=cross3(l2.p1,l2.p2,point)
0100            d2=u2.dot(l2.p1)
0101            dir=u1.cross(u2)
0102            try:
0103                ip1 = vector(solve(
0104                            array([u1,u2,dir]),
0105                            array([d1,d2,0.])))
0106
0107            except AlgebraError:
0108                print self.__class__.__name__
0109                print """lines are not distinct, quadric undefined, 
0110                      returned False"""
0111                return False
0112            ip2= dir + ip1
0113            line.p1.toInterSection(ip1,ip2,self.line1.p1,self.line1.p2,
0114                                test=False)
0115            line.p2.toInterSection(ip1,ip2,self.line2.p1,self.line2.p2,
0116                                test=False)
0117        return True
0118
0119
0120class PointMap(Real._LineArray):
0121    """
0122*array of lines* connecting points of the projective correspondance
0123defined by the **1st list of 3 points** and the **2nd list of 3 points**
0124    
0125    inherits
0126    
0127        `_LineArray`__
0128
0129__ class-base.abstracts._real._LineArray.html     
0130    
0131    """
0132    __doc_hints__=  {'factory':'LineArray',
0133                    'args':['[point1,point2,point3],[point1a,point2a,point3a]']}
0134
0135    def __init__(self,points1,points2,**kws):
0136        self.p1a=points1[0]
0137        self.p1b=points1[1]
0138        self.s1=points1[2]
0139        self.p2a=points2[0]
0140        self.p2b=points2[1]
0141        self.s2=points2[2]
0142        args=points1 + points2
0143        Real._LineArray.__init__(self,*args,**kws)
0144        self.init()
0145
0146    def findSelf(self):
0147        for i, line in enumerate(self.lines):
0148            step=(1/float(len(self.lines)))*i
0149            line.p1.toInterpolated(self.p1a,self.p1b,step)
0150            line.p2.toCrossPoint(self.p1a,self.s1,self.p1b,
0151                                line.p1,
0152                                self.p2a,self.s2,self.p2b)
0153        return True
0154
0155
0156class ArrayMap(Real._LineArray):
0157    """
0158**array of lines** connecting the points of the **2 given point arrays**
0159    
0160    inherits
0161    
0162        `_LineArray`__
0163
0164__ class-base.abstracts._real._LineArray.html     
0165    
0166    """
0167    __doc_hints__=  {'factory':'LineArray',
0168                    'args':['pointarray1,pointarray2']}
0169
0170    def __init__(self,pointarray1,pointarray2,**kws):
0171        self.pa1=pointarray1
0172        self.pa2=pointarray2
0173        Real._LineArray.__init__(self,*[pointarray1,pointarray2],**kws)
0174        self.density=min(self.pa1.density,self.pa2.density)
0175        self.init()
0176
0177    def findSelf(self):
0178        for line,p1,p2 in zip(self.lines,self.pa1,self.pa2):
0179            line.p1.set(p1)
0180            line.p2.set(p2)
0181        return True
0182
0183
0184class PlanesPencilIntersect(Real._LineArray):
0185    """
0186**array of lines** of intersection of **2 given plane sheaves**
0187    
0188    inherits
0189    
0190        `_LineArray`__
0191
0192__ class-base.abstracts._real._LineArray.html     
0193    
0194    """
0195    __doc_hints__=  {'factory':'LineArray',
0196                    'args':['planepencil1,planepencil2'],
0197                    'conditions':['plane pencils distinct'],
0198                    'otherwise':'None'}
0199
0200    def __init__(self,planes1,planes2,**kws):
0201        self.planes1=planes1
0202        self.planes2=planes2
0203        Real._LineArray.__init__(self,*[planes1,planes2],**kws)
0204        self.drawlen=kws.get("drawlen",40)
0205        self.density=min(self.planes1.density,self.planes2.density)
0206        self.init()
0207
0208    def findSelf(self):
0209        planes1 =self.planes1
0210        planes2 = self.planes2
0211        for p1,p2,line in zip(planes1,planes2,self.lines):
0212            try:
0213                dir=p1._u.cross(p2._u)
0214            except IndexError:
0215                print self.__class__.__name__
0216                print """plane pencil empty, intersection array undefined, 
0217                    returned False"""
0218                return False
0219            try:
0220                line.p1.set(vector(solve(
0221                            array([p1._u,p2._u,dir]),
0222                            array([p1._d,p2._d,0.]))))
0223            except AlgebraError:
0224                print self.__class__.__name__
0225                print """plane pencils not distinct, intersection array 
0226                        undefined, returned False"""
0227                return False
0228            line.p2.set(dir*self.drawlen+line.p1)
0229        return True
0230
0231
0232class LineMap(Real._LineArray):
0233    """
0234*array of lines* through the points of the **point array** and the **given point**
0235    
0236    inherits
0237    
0238        `_LineArray`__
0239
0240__ class-base.abstracts._real._LineArray.html     
0241    
0242    """
0243    __doc_hints__=  {'factory':'LineArray',
0244                    'args':['pointarray,point']}
0245
0246    def __init__(self,pointarray,point,**kws):
0247        self.pa=pointarray
0248        self.point=point
0249        Real._LineArray.__init__(self,*[pointarray,point],**kws)
0250        self.density=self.pa.density
0251        self.init()
0252
0253    def findSelf(self):
0254        for point,line in zip(self.pa,self.lines):
0255            line.p1.set(point)
0256            line.p2.set(self.point)
0257        return True
0258
0259
0260class CorrelationLines(Real._LineArray):
0261    """
0262*array of lines* polar to the points of the given **point array** with respect 
0263to the **given conic**
0264    
0265    inherits
0266    
0267        `_LineArray`__
0268
0269__ class-base.abstracts._real._LineArray.html     
0270    
0271    """
0272    __doc_hints__=  {'factory':'LineArray',
0273                    'args':['conic,pointarray']}
0274
0275    def __init__(self,conic,pointarray,**kws):
0276        self.conic=conic
0277        self.pa=pointarray
0278        self.x1z=Position3()
0279        self.x2z=Position3()
0280        Real._LineArray.__init__(self,*[conic,pointarray],**kws)
0281        self.density=self.pa.density
0282        self.init()
0283
0284    def findSelf(self):
0285        equat=self.conic.getPlane()
0286        C=self.conic.getC()
0287        for point,line in zip(self.pa,self.lines):
0288            L= matrixmultiply(C*2,point)
0289            tp1=array([0.,-L[2]/L[1],1.])
0290            tp2=array([-L[2]/L[0],0.,1.])
0291            cx = matrixmultiply(matrixmultiply(C,tp1),transpose(tp1))
0292            ax = matrixmultiply(matrixmultiply(C,tp2),transpose(tp2))
0293            bx =2*matrixmultiply(matrixmultiply(C,tp2),transpose(tp1))
0294            h=quadratic(ax,bx,cx)
0295            if h[0]:
0296                x1=tp1+tp2*h[0]
0297                x2=tp1+tp2*h[1]
0298            else:
0299                x1=tp1
0300                x2=tp2
0301            self.x1z.set(vector([x1[0]/x1[2],x1[1]/x1[2],0]))
0302            self.x2z.set(vector([x2[0]/x2[2],x2[1]/x2[2],0]))
0303            line.p1.fromXY(equat,self.x1z)
0304            line.p2.fromXY(equat,self.x2z)
0305        return True
0306
0307def  LineArray(*args,**kws):
0308    """
0309'class factory' function returns instance of object derived from the  _LineArray 
0310abstract class representing an array of lines with a defined geoemtric relationship
0311    """
0312
0313    from pygeo.base.abstracts._element import method_get
0314    from pygeo.base.support.pygeoexceptions import Argument_Type_Error
0315    from pygeo.base.geometry_real.pointarrays import Conic
0316
0317    __sigs__=[[Real._PointArray,vector],[vector,Real._Plane],
0318              [vector,Real._Circle],[Real._PointArray,Real._Line,Real._Line],
0319              [list,list],
0320              [Real._PointArray,Real._PointArray],[Real._PlaneArray,Real._PlaneArray],
0321              [Conic,Real._PointArray]]
0322
0323    t,i = method_get(__sigs__,args)
0324
0325    if t is None:
0326        raise Argument_Type_Error(__sigs__,args)
0327    else:
0328        if i ==0:
0329            return LineMap(t[0],t[1],**kws)
0330        elif i==1 or i==2:
0331            return LinePencil(t[0],t[1],**kws)
0332        elif i==3:
0333            return Regulus(t[0],t[1],t[2],**kws)
0334        elif i==4:
0335            return PointMap(t[0],t[1],**kws)
0336        elif i==5:
0337            return ArrayMap(t[0],t[1],**kws)
0338        elif i==6:
0339            return PlanesPencilIntersect(t[0],t[1],**kws)
0340        elif i==7:
0341            return CorrelationLines(t[0],t[1],**kws)
0342        else:
0343            raise Argument_Type_Error(__sigs__,args)