0001"""
0002**point** defined in relation to the the division of a given geoemtric object
0003in a given ratio or metric
0004"""
0005
0006__Def__ =       ['Divider']
0007
0008__Classes__ =   ['LineDivider', 'LineCut', 'CrossPoint', 'Harmonic',
0009                'CircumPoint']
0010
0011__all__= __Classes__ + __Def__
0012
0013__doc_hints__=  {'m_type':'factory'}
0014
0015import pygeo.base.abstracts._real as Real
0016
0017from pygeo.base.support.pygeoopts import DO_TESTS
0018from pygeo.base.analytics.pygeomath import PI
0019
0020
0021class LineDivider(Real._Point):
0022    """
0023*point* dividing the given **line** segment in the given **ratio**
0024
0025    inherits
0026    
0027        `_Point`__
0028
0029__ base.abstracts._real._Point.html        
0030
0031    """
0032    __doc_hints__=  {'factory':'Divider',
0033                    'args':['line, ratio=<numeric>'],
0034                    'default':'midpoint of segment (i.e., ratio=.5)'}
0035
0036    __opts__= Real._Point.__opts__[:] + ["ratio"]
0037
0038    def __init__(self,line,**kws):
0039        self.line=line
0040        self.ratio=kws.get('ratio',.5)
0041        Real._Point.__init__(self,*[line],**kws)
0042        self.extend=kws.get("extend",True)
0043        self.lines=[self.line]
0044        self.init()
0045
0046    def findSelf(self):
0047        self.toInterpolated(self.line.p1,self.line.p2,self.ratio)
0048        return True
0049
0050
0051class LineCut(Real._Point):
0052    """
0053*point* of given **line** dividing it so the segment equals distance between 
0054given **2 points** <or 2nd given **line segments** endpoints>. 
0055    
0056    inherits
0057    
0058        `_Point`__
0059
0060__ base.abstracts._real._Point.html        
0061    
0062    """
0063    __doc_hints__=  {'factory':'Divider',
0064                    'args':['line, point1, point2','line1,line2']}
0065
0066    def __init__(self,line,p1,p2,**kws):
0067        self.line=line
0068        self.p1=p1
0069        self.p2=p2
0070        Real._Point.__init__(self,*[line,p1,p2],**kws)
0071        self.extend=kws.get("extend",True)
0072        self.lines=[self.line]
0073        self.init()
0074
0075    def findSelf(self):
0076        v=(self.line.p2-self.line.p1).norm()
0077        d=self.p1.distance(self.p2)
0078        self.set(v*d + self.line.p1)
0079        return True
0080
0081
0082class CrossPoint(Real._Point):
0083    """
0084point equalizing cross ratio of second **3 point list** to first **4 point list**
0085
0086    inherits
0087    
0088        `_Point`__
0089
0090__ base.abstracts._real._Point.html        
0091
0092    """
0093    __doc_hints__=  {'factory':'Divider',
0094                    'args':['[p1a,p1b,p1c,p1d],[p2a,p2a,p2b,p2c]'],
0095                    'conditions': ['4 point set collinear and 3 point set collinear'],
0096                    'otherwise': 'undefined'}
0097
0098    def __init__(self,list1,list2,**kws):
0099        self.p1=list1[0]
0100        self.p2=list1[1]
0101        self.p3=list1[2]
0102        self.p4=list1[3]
0103        self.p1a=list2[0]
0104        self.p2a=list2[1]
0105        self.p3a=list2[2]
0106        args=list1+list2
0107        Real._Point.__init__(self, *args,**kws)
0108        self.init()
0109
0110    def findSelf(self):
0111        if DO_TESTS:
0112            t= (self.p1.coLinear(self.p2,self.p3)
0113                and self.p1.coLinear(self.p3,self.p4)
0114                and self.p1a.coLinear(self.p2a,self.p3a))
0115        else:
0116            t=True
0117        if t:
0118            return self.toCrossPoint(self.p1,self.p2,self.p3,
0119                                        self.p4,self.p1a,self.p2a,self.p3a)
0120        else:
0121            print self.__class__.__name__
0122            print """reference or target points are not collinear, crosspoint 
0123                    undefined, returned False"""
0124            return False
0125
0126class Harmonic(Real._Point):
0127    """
0128*point* that is harmonic conjugate of 1st given **point** with respect 
0129to succeeding given **2 points**
0130
0131    inherits
0132    
0133        `_Point`__
0134
0135__ base.abstracts._real._Point.html        
0136
0137    """
0138
0139    __doc_hints__=  {'factory':'Divider',
0140                    'args':['point1, point2, point3'],
0141                    'conditions': ['points collinear'],
0142                    'otherwise': 'undefined'}
0143
0144    def __init__(self,p1,p2,p3,**kws):
0145        self.p1=p1
0146        self.p2=p2
0147        self.p3=p3
0148        Real._Point.__init__(self,*[p1,p2,p3],**kws)
0149        self.init()
0150
0151    def findSelf(self):
0152        if DO_TESTS:
0153            t = self.p1.coLinear(self.p2,self.p3)
0154        else:
0155            t =True
0156        if t:
0157            self.toHarmonic(self.p1,self.p2,self.p3)
0158            return True
0159        else:
0160            print self.__class__.__name__
0161            print """points are not collinear, harmonic not defined, 
0162                    returned False"""
0163            return False
0164
0165class CircumPoint(Real._Point):
0166    """
0167*point* on **circle** circumference rotated by the given **angle**
0168
0169    inherits
0170    
0171        `_Point`__
0172
0173__ base.abstracts._real._Point.html        
0174
0175    """
0176    __doc_hints__=  {'factory':'Divider',
0177                    'args':['circle, <angle = numeric>'],
0178                    'default':'angle=PI'}
0179
0180    __opts__= Real._Point.__opts__[:] + ["angle"]
0181
0182    def __init__(self,circle,**kws):
0183        self.circle=circle
0184        self.angle=kws.get('angle',PI)
0185        Real._Point.__init__(self,*[circle],**kws)
0186        self.init()
0187
0188    def findSelf(self):
0189        self.set(self.circle._cpoint)
0190        return self.toCircumPoint(self.circle,self.angle)
0191
0192def Divider(*args,**kws):
0193    """
0194'class factory' function returns instance of object derived from the 
0195*_Point* abstract class defined in relation to the the division of 
0196a given geoemtric object in a given ratio or metric
0197    """
0198
0199    from pygeo.base.abstracts._element import method_get
0200    from pygeo.base.support.pygeoexceptions import Argument_Type_Error
0201    from pygeo.base.analytics.pygeomath import vector
0202
0203    __sigs__ = [[Real._Line],[Real._Line,float],[Real._Line,vector,vector],
0204               [Real._Line,Real._Line], [vector, vector,vector],
0205               [list,list], [Real._Circle]]
0206
0207    t,i = method_get(__sigs__,args)
0208
0209    if t is None:
0210        raise Argument_Type_Error(__sigs__,args)
0211    else:
0212        if i == 0:
0213            return LineDivider(t[0],**kws)
0214        elif i == 1:
0215            return LineDivider(t[0],t[1],**kws)
0216        elif i == 2:
0217            return LineCut(t[0],t[1],t[2],**kws)
0218        elif i == 3:
0219            return LineCut(t[0],t[1].p1,t[1].p2,**kws)
0220        elif i == 4:
0221            return Harmonic(t[0],t[1],t[2],**kws)
0222        elif i == 5:
0223             if (len(t[0])==4 and len(t[1])==3):
0224                return CrossPoint(t[0],t[1],**kws)
0225             else:
0226                raise Argument_Type_Error(__sigs__,args)
0227        elif i == 6:
0228            return CircumPoint(t[0],**kws)
0229        else:
0230            raise Argument_Type_Error(__sigs__,args)