0001"""
0002**line segment** connecting the points of a line on a given
0003geometric object
0004"""
0005__Def__ = ['Chord']
0006
0007__Classes__ = ['CircleChord', 'SphereChord','BiChord','ConicChord']
0008
0009__all__= __Classes__+__Def__
0010
0011__doc_hints__={'m_type':'factory'}
0012
0013import pygeo.base.abstracts._real as Real
0014
0015from pygeo.base.analytics._position3 import Position3
0016from pygeo.base.analytics.pygeomath import sqrt, arccos, array, matrixmultiply, transpose, toXY, quadratic, cross3
0018from pygeo.base.support.pygeoopts import DO_TESTS, EPS
0019
0020
0021class CircleChord(Real._Line):
0022 """
0023*line segment* joining the points of intersection of the given **circle**
0024and **line**
0025
0026 inherits
0027
0028 `_Line`__
0029
0030__ class-base.abstracts._real._Line.html
0031
0032 """
0033
0034 __doc_hints__= {'factory':'Chord',
0035 'args':['circle,line'],
0036 'conditions':['circle and line are coplanar',
0037 'circle and line intersection is real'],
0038 'otherwise':'None; None'}
0039
0040 def __init__(self,circle,line,**kws):
0041 self.tp=Position3()
0042 self.circle=circle
0043 self.line=line
0044 Real._Line.__init__(self,*[circle,line],**kws)
0045 self.seg=True
0046 self.deps=[self.p1,self.p2]
0047 self.init()
0048
0049 def findSelf(self):
0050 if DO_TESTS:
0051 t=(self.line.p1.onPlane(self.circle)
0052 and self.line.p2.onPlane(self.circle))
0053 else:
0054 t=True
0055 if t:
0056 self.tp.set(self.circle._center)
0057 if self.tp.toLine(self.line.p1,self.line.p2):
0058 d=self.tp.distanceSquared(self.circle._center)
0059 if sqrt(d) > self.circle._radius:
0060 print self.__class__.__name__
0061 print """no real point of intersection for circle
0062 and line returned False"""
0063 return False
0064 if not d < EPS:
0065 r=self.circle._radiusSquared
0066 factor=sqrt(r-d)/self.tp.distance(self.line.p1)
0067 self.p1.set((self.line.p1-self.tp)*factor+self.tp)
0068 self.p2.set(self.tp*2-self.p1)
0069 else:
0070
0071 self.p1.set(self.line.getDirection()*self.circle._radius
0072 +self.tp)
0073 self.p2.set(self.line.getDirection()*-self.circle._radius
0074 +self.tp)
0075 return True
0076 else:
0077 print self.__class__.__name__
0078 print """line segment points not distinct, toLine opreation
0079 returned False"""
0080 return False
0081 else:
0082 print self.__class__.__name__
0083 print """circle and line are not coplanar, no intersection
0084 chord defined, returned False"""
0085 return False
0086
0087
0088class SphereChord(Real._Line):
0089 """
0090*line segment* joining the points of intersection of the given **sphere**
0091and **line**
0092
0093 inherits
0094
0095 `_Line`__
0096
0097__ class-base.abstracts._real._Line.html
0098
0099 """
0100
0101 __doc_hints__= {'factory':'Chord',
0102 'args':['sphere,line'],
0103 'conditions':['sphere and line intersection is real'],
0104 'otherwise':'None'}
0105
0106 def __init__(self,sphere,line,**kws):
0107 self.sphere=sphere
0108 self.line=line
0109 self.t=Real._Point()
0110 Real._Line.__init__(self,*[sphere,line],**kws)
0111 self.seg=True
0112 self.deps=[self.p1,self.p2]
0113 self.init()
0114
0115 def findSelf(self):
0116 line=self.line
0117 sphere=self.sphere
0118 self.t.set(sphere._center)
0119 self.t.toLine(line.p1,line.p2)
0120 self.t-=sphere._center
0121 t2=self.t.mag2
0122 r2 = sphere._radiusSquared
0123 if t2 > r2:
0124 self.t*=.5
0125 d = 0.50*(1.0+(r2-t2)/t2)
0126 self.t*=d
0127 crad = sqrt(r2 - d**2*t2)
0128 self.p1.set(cross3(line.p1,line.p2,sphere._center).norm())
0129 self.p1*=crad
0130 self.p2.set(self.p1*-1)
0131 self.t+=sphere._center
0132 self.p1+=self.t
0133 self.p2+=self.t
0134 else:
0135 self.p1.set((line.p2-line.p1).norm())
0136 crad=sqrt(r2-t2)
0137 self.p1*=crad
0138 self.p2.set(self.p1*-1)
0139 self.t += sphere._center
0140 self.p1 += self.t
0141 self.p2 += self.t
0142 return True
0143
0144
0145class BiChord(Real._Line):
0146 """
0147*line segment* joining the points of intersection of the given **2 circles**
0148
0149 inherits
0150
0151 `_Line`__
0152
0153__ class-base.abstracts._real._Line.html
0154
0155 """
0156
0157 __doc_hints__= {'factory':'Chord',
0158 'args':['circle1,circle2'],
0159 'conditions':['the circles are coplanar',
0160 'the circles intersection is real'],
0161 'otherwise':'None; None'}
0162
0163 def __init__(self,circle1,circle2,**kws):
0164 self.circle1=circle1
0165 self.circle2=circle2
0166 Real._Line.__init__(self,*[circle1,circle2],**kws)
0167 self.seg=True
0168 self.deps=[self.p1,self.p2]
0169 self.init()
0170
0171 def findSelf(self):
0172 circle1=self.circle1
0173 circle2=self.circle2
0174 if DO_TESTS:
0175 t=(circle1._center.onPlane(circle2)
0176 and circle1._cpoint.onPlane(circle2))
0177 else:
0178 t=True
0179 if t:
0180 dcenters=circle1._center.distance(circle2._center)
0181 if dcenters < EPS:
0182 print self.__class__.__name__
0183 print """circles are concentric, no intersection defined,
0184 return False"""
0185 return False
0186 try:
0187 angle=arccos((circle1._center.distanceSquared(circle2._center)+
0188 circle1._radiusSquared-circle2._radiusSquared)/
0189 (2*dcenters*circle1._radius))
0190 except ValueError:
0191 print self.__class__.__name__
0192 print """circles do not intersect in real points,
0193 returning False"""
0194 return False
0195 self.p1.set(circle2._center)
0196 self.p1.toCircle(circle1)
0197 self.p2.set(self.p1)
0198 self.p1.toCircumPoint(self.circle1,angle)
0199 self.p2.toCircumPoint(self.circle1,-angle)
0200 return True
0201 else:
0202 print self.__class__.__name__
0203 print """circles are not coplanar, no intersection defined,
0204 returning false"""
0205 return False
0206
0207
0208class ConicChord(Real._Line):
0209 """
0210*line segment* joining the points of intersection of the given **conic** and **line**
0211
0212 inherits
0213
0214 `_Line`__
0215
0216__ class-base.abstracts._real._Line.html
0217
0218 """
0219
0220 __doc_hints__= {'factory':'Chord',
0221 'args':['conic,line'],
0222 'conditions':[' conic and line are coplanar',
0223 'conic and line intersection is real'],
0224 'otherwise':'None; None'}
0225
0226 def __init__(self,conic,line,**kws):
0227 self.conic=conic
0228 self.line=line
0229 self.pt=array([0.,0.,-1.,1.])
0230 Real._Line.__init__(self,*[self.conic,self.line],**kws)
0231 self.seg=True
0232 self.deps=[self.p1,self.p2]
0233 self.init()
0234
0235 def __repr__(self):
0236 return self.__class__.__name__ + "(" + str(self.p1) +"," + str(self.p2) + ")"
0238
0239 def findSelf(self):
0240 equat=self.conic.getPlane()
0241 tp1= toXY(self.line.p1)
0242 tp2= toXY(self.line.p2)
0243 C=self.conic.getC()
0244 cx = matrixmultiply(matrixmultiply(C,tp1),transpose(tp1))
0245 ax = matrixmultiply(matrixmultiply(C,tp2),transpose(tp2))
0246 bx =2*matrixmultiply(matrixmultiply(C,tp2),transpose(tp1))
0247 h= quadratic(ax,bx,cx)
0248 if h[0]:
0249 x1=tp1+tp2*h[0]
0250 x2=tp1+tp2*h[1]
0251 x1z=array([x1[0]/x1[2],x1[1]/x1[2],0])
0252 x2z=array([x2[0]/x2[2],x2[1]/x2[2],0])
0253 self.p1.fromXY(equat,x1z)
0254 self.p2.fromXY(equat,x2z)
0255 return True
0256 else:
0257 print self.__class__.__name__
0258 print """No real intersections between conic and line,
0259 returning False"""
0260 return False
0261
0262def Chord(*args,**kws):
0263 """
0264'class factory' function returns instance of object derived from the _Line
0265abstract class, representing the segment connecting the points of the line on
0266a given geometric object
0267 """
0268
0269 from pygeo.base.abstracts._element import method_get
0270 from pygeo.base.support.pygeoexceptions import Argument_Type_Error
0271 from pygeo.base.geometry_real.pointarrays import Conic
0272
0273 __sigs__=[[Real._Circle,Real._Line],[Real._Sphere,Real._Line],
0274 [Real._Circle,Real._Circle],[Conic,Real._Line]]
0275
0276 t,i = method_get(__sigs__,args)
0277
0278 if t is None:
0279 raise Argument_Type_Error(__sigs__,args)
0280 else:
0281 if i==0:
0282 return CircleChord(t[0],t[1],**kws)
0283 elif i==1:
0284 return SphereChord(t[0],t[1],**kws)
0285 elif i==2:
0286 return BiChord(t[0],t[1],**kws)
0287 elif i==3:
0288 return ConicChord(t[0],t[1],**kws)
0289 else:
0290 raise Argument_Type_Error(__sigs__,args)