0001"""
0002**array of points** with a defined geoemtric relationship
0003"""
0004
0005__Def__ = ['PointArray']
0006
0007__Classes__ = [ 'PointPencil', 'CirclingPencil',
0008 'CirclePoints','GrowthMeasure','Harmonics', 'Conic',
0009 'ArrayIntersect','PlanePoints','CorrelationPoints']
0010
0011__all__= __Classes__+ __Def__
0012
0013__doc_hints__={'m_type':'factory'}
0014
0015
0016import pygeo.base.abstracts._real as Real
0017
0018from pygeo.base.analytics._position3 import Position3
0019
0020from pygeo.base.analytics.pygeomath import arrayrange, sin, cos, transpose, PI, array, matrixmultiply, cross3,eigenvectors, vector, inverse
0023
0024from pygeo.base.support.pygeoopts import MAX, DO_TESTS
0025
0026class PointPencil(Real._PointArray):
0027 __opts__= Real._PointArray.__opts__[:] + ["seg"]
0028 """
0029*array of points* equidistant on given **line**
0030
0031 inherits
0032
0033 `_PointArray`__
0034
0035__ class-base.abstracts._real._PointArray.html
0036
0037 """
0038
0039 __doc_hints__= {'factory':'PointArray',
0040 'args':['line <,seg=Boolean>']}
0041
0042 def __init__(self,line,**kws):
0043 self.line=line
0044 self.seg=kws.get('seg',False)
0045 Real._PointArray.__init__(self,*[line],**kws)
0046 self.init()
0047
0048 def findSelf(self):
0049 line =self.line
0050 p= line.getDirection()
0051 if (self.seg or self.line.seg):
0052 length=self.line.length()
0053 start=line.p1
0054 else:
0055 length=MAX*2
0056 start = (p*-MAX)+(line.p1+line.p2)/2
0057 steps=[length/float(self.density-1)*i for i in range(self.density)]
0058 for point,step in zip(self,steps):
0059 point.set(p*step+start)
0060 return True
0061
0062
0063class CirclingPencil(Real._PointArray):
0064 """
0065*array points* of intersection of the given **array of lines**
0066and **the given line**
0067
0068 inherits
0069
0070 `_PointArray`__
0071
0072__ class-base.abstracts._real._PointArray.html
0073
0074 """
0075 __doc_hints__= {'factory':'PointArray',
0076 'args':['linearray,line'],
0077 'conditions':['line and line array are coplanar'],
0078 'otherwise':'None'}
0079
0080 def __init__(self,linearray,line,**kws):
0081 self.linearray=linearray
0082 self.line=line
0083 self.extend=kws.get("extend",True)
0084 self.density = self.linearray.density
0085 Real._PointArray.__init__(self,*[linearray,line],**kws)
0086 self.init()
0087
0088 def findSelf(self):
0089 if DO_TESTS:
0090 t = self.line.p1.coPlanar(self.line.p2,self.linearray.lines[0].p1,
0091 self.linearray.lines[0].p2)
0092 else:
0093 t =True
0094 if t :
0095 for point,line in zip(self,self.linearray):
0096 point.toInterSection(self.line.p1,self.line.p2,line.p1,line.p2)
0097 return True
0098 else:
0099 print self.__class__.__name__
0100 print """line and line array are not coplanar,
0101 points of intersection undefined,returned False"""
0102 return False
0103
0104 def setext(self):
0105 if self.Not_null:
0106 if self.show:
0107 for point,line in zip(self,self.linearray):
0108 if line.show:
0109 line.get_extension(point)
0110 line._redraw()
0111
0112class CirclePoints(Real._PointArray):
0113 """
0114*array of points* equidistant on given circumference of given **circle**
0115
0116 inherits
0117
0118 `_PointArray`__
0119
0120__ class-base.abstracts._real._PointArray.html
0121
0122 """
0123 __doc_hints__= {'factory':'PointArray',
0124 'args':['circle']}
0125
0126 def __init__(self,circle,**kws):
0127 self.circle=circle
0128 Real._PointArray.__init__(self,*[circle],**kws)
0129 t = arrayrange(0,2*PI,2*PI/self.density)
0130 self.c = transpose((0*t, sin(t), cos(t)))
0131 self.init()
0132
0133 def findSelf(self):
0134 for point,s in zip(self.points,self.c):
0135 t=s*self.circle._radius
0136 n=array([t[0],t[1],t[2],1])
0137 m=matrixmultiply(n,self.circle.rmatrix())
0138 point.to_3d(m)
0139 return True
0140
0141
0142class GrowthMeasure(Real._PointArray):
0143 """
0144*array of points* of line with any sequential 4 points
0145with crossratio equal to that of the **4 given points**
0146
0147 inherits
0148
0149 `_PointArray`__
0150
0151__ class-base.abstracts._real._PointArray.html
0152
0153 """
0154 __doc_hints__= {'factory':'PointArray',
0155 'args':['point1,point2,point3,point4'],
0156 'conditions':['points are coplanar',
0157 'points are distinct'],
0158 'otherwise':'None; None'}
0159
0160 def __init__(self,M,N,a,b,**kws):
0161 self.a=a
0162 self.b=b
0163 self.M=M
0164 self.N=N
0165 self.cd=0
0166 Real._PointArray.__init__(self,*[M,N,a,b],**kws)
0167 self.steps=self.density
0168 self.init()
0169
0170 def findSelf(self):
0171 if DO_TESTS:
0172 t=self.M.coLinear(self.a,self.b) and self.N.coLinear(self.a,self.b)
0173 else:
0174 t= True
0175 if t :
0176 self.cd=self.M.distance(self.N)
0177 mt=self.multiplier()
0178 iter=self.__iter__()
0179 iter.next().set(self.a)
0180 iter.next().set(self.b)
0181 def step(seed):
0182 try:
0183 point=iter.next()
0184 ad=seed.distance(self.N)
0185 ac=seed.distance(self.M)
0186 if ad > self.cd:
0187 ac=-ac
0188 try:
0189 v= mt*ac/ad
0190 point.set((self.M-self.N)/(1+v)+self.N)
0191 except ZeroDivisionError:
0192 print self.__class__.__name__
0193 print """coincident points causing zero division,
0194 returned False """
0195 print "point set to double point 'M'"
0196 v=0
0197 point.set(self.M)
0198 step(point)
0199 except StopIteration:
0200 pass
0201 step(self.a)
0202 return True
0203 else:
0204 print self.__class__.__name__
0205 print """points are not collinear, crossratio undefined,
0206 returning False"""
0207 return False
0208
0209 def multiplier(self):
0210 da=self.N.distance(self.a)
0211 ac=self.a.distance(self.M)
0212 bc=self.b.distance(self.M)
0213 db = self.N.distance(self.b)
0214 if da > self.cd:
0215 ac=-ac
0216 if db > self.cd:
0217 bc=-bc
0218 return (-da/ac)*(bc/-db)
0219
0220
0221class Harmonics(Real._PointArray):
0222 """
0223*array of points* harmonic to the given **point array**,
0224with respect to the given **points**
0225
0226 inherits
0227
0228 `_PointArray`__
0229
0230__ class-base.abstracts._real._PointArray.html
0231
0232 """
0233
0234 __doc_hints__= {'factory':'PointArray',
0235 'args':['pointarray,point1,point2'],
0236 'conditions':['array and points are coplanar ',
0237 'points are distinct'],
0238 'otherwise':'Undefined; Undefined'}
0239
0240 def __init__(self,pa,M,N,**kws):
0241 self.pa=pa
0242 self.M=M
0243 self.N=N
0244 self.density=self.pa.density
0245 Real._PointArray.__init__(self,*[pa,M,N],**kws)
0246 self.init()
0247
0248 def findSelf(self):
0249 for point,hpoint in zip(self,self.pa):
0250 point.toHarmonic(hpoint,self.M,self.N)
0251 return True
0252
0253
0254class Conic(Real._PointArray):
0255 """
0256*array of points* on the conic determined by the given **5 points**
0257
0258 inherits
0259
0260 `_PointArray`__
0261
0262__ class-base.abstracts._real._PointArray.html
0263
0264 """
0265 __doc_hints__= {'factory':'PointArray',
0266 'args':['point1,point2,point3,point4,point5'],
0267 'conditions':['points are coplanar',
0268 'points are distinct',
0269 'no 3 points are collinear'],
0270 'otherwise':'None; None; Undefined'}
0271
0272 def __init__(self,p1,p2,p3,p4,p5,**kws):
0273 self.p1=p1
0274 self.p2=p2
0275 self.p3=p3
0276 self.p4=p4
0277 self.p5=p5
0278 self.m=Position3()
0279 self.a=Position3()
0280 self.t=Position3()
0281 self.c1=Position3()
0282 self.c2=Position3()
0283 self.c3=Position3()
0284 self.c4=Position3()
0285 self.c5=Position3()
0286 Real._PointArray.__init__(self,*[p1,p2,p3,p4,p5],**kws)
0287 self.i=[2*PI/self.density*i for i in range(self.density)]
0288 self.init()
0289
0290 def findSelf(self):
0291 p1=self.p1
0292 p2=self.p2
0293 p3=self.p3
0294 p4=self.p4
0295 p5=self.p5
0296 if DO_TESTS:
0297 t = (p1.coPlanar(p2,p3,p4) and p2.coPlanar(p3,p4,p5))
0298 else:
0299 t= True
0300 if t:
0301 if self.m.toInterSection(p1,p2,p3,p4):
0302 u=cross3(p1,p2,p3).norm()
0303 radius=p1.distance(p2)
0304 cpoint=(p2-p1).norm()*radius
0305 for point,rad in zip(self,self.i):
0306 p=p2 + cpoint.rotate(rad,u)
0307 self.a.toInterSection(p,p2,p3,p5,test=False)
0308 self.t.toInterSection(self.m,self.a,p1,p5,test=False)
0309 point.toInterSection(p,p2,self.t,p4,test=False)
0310 return True
0311 else:
0312 print self.__class__.__name__
0313 print "points are not distinct, conic undfined, returned False"
0314 return False
0315 else:
0316 print self.__class__.__name__
0317 print "points are not coPlanar, conic undefined, returned False"
0318 return False
0319
0320 def getPlane(self):
0321 u= cross3(self.p1,self.p2,self.p3).norm()
0322 d=u.dot(self.p1)
0323 return array([u.x,u.y,u.z,-d])
0324
0325 def getC(self):
0326 self.c1.toXY(self.p1)
0327 self.c2.toXY(self.p2)
0328 self.c3.toXY(self.p3)
0329 self.c4.toXY(self.p4)
0330 self.c5.toXY(self.p5)
0331 c1=self.c1
0332 c2=self.c2
0333 c3=self.c3
0334 c4=self.c4
0335 c5=self.c5
0336 A=array([
0337 [c1.x**2,c1.x*c1.y,c1.y**2,c1.x,c1.y,1],
0338 [c2.x**2,c2.x*c2.y,c2.y**2,c2.x,c2.y,1],
0339 [c3.x**2,c3.x*c3.y,c3.y**2,c3.x,c3.y,1],
0340 [c4.x**2,c4.x*c4.y,c4.y**2,c4.x,c4.y,1],
0341 [c5.x**2,c5.x*c5.y,c5.y**2,c5.x,c5.y,1],
0342 [0,0,0,0,0,0]])
0343 evalues, evectors = eigenvectors(A)
0344 V = evectors[5].real
0345 b2=V[1]/2.
0346 d2=V[3]/2.
0347 e2=V[4]/2
0348 C=array([[V[0],b2,d2],[b2,V[2],e2],[d2,e2,V[5]]])
0349 return C
0350
0351
0352class ArrayIntersect(Real._PointArray):
0353 """
0354*array of points* of intersection of the given **2 arrays of lines**
0355
0356 inherits
0357
0358 `_PointArray`__
0359
0360__ class-base.abstracts._real._PointArray.html
0361
0362 """
0363 __doc_hints__= {'factory':'PointArray',
0364 'args':['line_array1,line_array2'],
0365 'conditions':['linearrays are coplanar'],
0366 'otherwise':'None'}
0367
0368 def __init__(self,lp1,lp2,**kws):
0369 self.lp1=lp1
0370 self.lp2=lp2
0371 self.t=Position3()
0372 self.extend=kws.get("extend",False)
0373 self.density=min(lp1.density,lp2.density)
0374 Real._PointArray.__init__(self,*[lp1,lp2],**kws)
0375 self.init()
0376
0377 def findSelf(self):
0378 if DO_TESTS:
0379 t = self.lp1.lines[0].p1.coPlanar(self.lp1.lines[0].p2,
0380 self.lp2.lines[1].p2,self.lp2.lines[1].p2)
0381 else:
0382 t = True
0383 if t:
0384 for point,line1,line2 in zip(self,self.lp1,self.lp2):
0385 point.toInterSection(line1.p1,line1.p2,line2.p1,line2.p2,test=False)
0386 return True
0387 else:
0388 print self.__class__.__name__
0389 print """line arrays are not coplanar, points of intersections
0390 undefined, returned False"""
0391 return False
0392
0393 def setext(self):
0394 for point,line in zip(self,self.lp1):
0395 line.get_extension(point)
0396 line._redraw()
0397 for point,line in zip(self,self.lp2):
0398 line.get_extension(point)
0399 line._redraw()
0400
0401
0402class CorrelationPoints(Real._PointArray):
0403 """
0404*array of point* as poles of the given **line array** with respect to
0405the given **conic**
0406
0407 inherits
0408
0409 `_PointArray`__
0410
0411__ class-base.abstracts._real._PointArray.html
0412
0413 """
0414 __doc_hints__= {'factory':'PointArray',
0415 'args':['conic, linearray'],
0416 'conditions':['line arrray and conic are coplanar'],
0417 'otherwise':'Undefined'}
0418
0419 def __init__(self,conic,la,**kws):
0420 self.conic=conic
0421 self.line_array=la
0422 self.density=self.line_array.density
0423 Real._PointArray.__init__(self,*[conic,la],**kws)
0424 self.h1=Position3()
0425 self.h2=Position3()
0426 self.tpz=Position3()
0427 self.init()
0428
0429 def findSelf(self):
0430 if DO_TESTS:
0431 t = self.line_array.lines[0].p1.coPlanar(self.line_array.lines[0].p2,
0432 self.conic.p1,self.conic.p2)
0433 else:
0434 t = True
0435 if t:
0436 equat=self.conic.getPlane()
0437 Ci=inverse(self.conic.getC())
0438 for point,line in zip(self,self.line_array):
0439 self.h1.toXY(line.p1)
0440 self.h2.toXY(line.p2)
0441 h=self.h1.cross(self.h2)
0442 tp = matrixmultiply(Ci,h)
0443 self.tpz.set(vector(tp[0]/tp[2],tp[1]/tp[2],0))
0444 point.fromXY(equat,self.tpz)
0445 return True
0446 else:
0447 print self.__class__.__name__
0448 print """line array and conic are not coplanar, correlation points
0449 undefined,returned False"""
0450 return False
0451
0452
0453class PlanePoints(Real._PointArray):
0454 """
0455*array of points* of intersection of the given **line array** with
0456the given **plane**
0457
0458 inherits
0459
0460 `_PointArray`__
0461
0462__ class-base.abstracts._real._PointArray.html
0463
0464 """
0465
0466 __doc_hints__= {'factory':'PointArray',
0467 'args':['plane, linearray'],
0468 'conditions':['line arrray not on plane'],
0469 'otherwise':'Undefined'}
0470
0471 def __init__(self,plane,la,**kws):
0472 self.plane=plane
0473 self.line_array=la
0474 self.density=self.line_array.density
0475 Real._PointArray.__init__(self,*[plane,la],**kws)
0476 self.init()
0477
0478 def findSelf(self):
0479 if DO_TESTS:
0480 t = not (self.line_array.lines[0].p1.onPlane(self.plane)
0481 and self.line_array.lines[0].p2.onPlane(self.plane))
0482 else:
0483 t = True
0484 if t:
0485 for point,line in zip(self,self.line_array):
0486 point.toPlaneIntersection(self.plane,line.p1,
0487 line.p2)
0488 return True
0489 else:
0490 print self.__class__.__name__
0491 print """line array on plane, intersection points undefined,
0492 returned False"""
0493 return False
0494
0495
0496def PointArray(*args,**kws):
0497 """
0498'class factory' function returns instance of object derived from the
0499_PointArray abstract class representing an array of points with a
0500defined geoemtric relationship
0501 """
0502
0503 from pygeo.base.abstracts._element import method_get
0504 from pygeo.base.support.pygeoexceptions import Argument_Type_Error
0505
0506 __sigs__=[[Real._Line],[Real._LineArray,Real._Line],[Real._Circle],
0507 [vector,vector,vector,vector,vector],
0508 [Real._LineArray,Real._LineArray],[vector,vector,vector,vector],
0509 [Real._PointArray,vector,vector],[Conic,Real._LineArray],
0510 [Real._Plane,Real._LineArray]]
0511
0512 t,i = method_get(__sigs__,args)
0513
0514 if t is None:
0515 raise Argument_Type_Error(__sigs__,args)
0516 else:
0517 if i==0:
0518 return PointPencil(t[0],**kws)
0519 elif i==1:
0520 return CirclingPencil(t[0],t[1],**kws)
0521 elif i==2:
0522 return CirclePoints(t[0],**kws)
0523 elif i==3:
0524 return Conic(t[0],t[1],t[2],t[3],t[4],**kws)
0525 elif i==4:
0526 return ArrayIntersect(t[0],t[1],**kws)
0527 elif i==5:
0528 return GrowthMeasure(t[0],t[1],t[2],t[3],**kws)
0529 elif i==6:
0530 return Harmonics(t[0],t[1],t[2],**kws)
0531 elif i==7:
0532 return CorrelationPoints(t[0],t[1],**kws)
0533 elif i==8:
0534 return PlanePoints(t[0],t[1],**kws)
0535 else:
0536 raise Argument_Type_Error(__sigs__,args)