/[escript]/trunk/pycad/py_src/primitives.py
ViewVC logotype

Annotation of /trunk/pycad/py_src/primitives.py

Parent Directory Parent Directory | Revision Log Revision Log


Revision 919 - (hide annotations)
Wed Jan 3 22:54:50 2007 UTC (12 years, 8 months ago) by gross
File MIME type: text/x-python
File size: 25709 byte(s)
arc test is passing now. The check for colocation is now invariant of direction


1 gross 898 # $Id:$
2    
3     """
4 gross 899 Geometrical Primitives
5 gross 898
6     the concept is inspired by gmsh and very much focused on the fact that
7     the classes are used to wrk with gmsh.
8    
9     @var __author__: name of author
10     @var __copyright__: copyrights
11     @var __license__: licence agreement
12     @var __url__: url entry point on documentation
13     @var __version__: version
14     @var __date__: date of the version
15     """
16    
17    
18     __author__="Lutz Gross, l.gross@uq.edu.au"
19     __copyright__=""" Copyright (c) 2006 by ACcESS MNRF
20     http://www.access.edu.au
21     Primary Business: Queensland, Australia"""
22     __license__="""Licensed under the Open Software License version 3.0
23     http://www.opensource.org/licenses/osl-3.0.php"""
24     __url__="http://www.iservo.edu.au/esys/escript"
25     __version__="$Revision:$"
26     __date__="$Date:$"
27    
28 gross 899 import numarray
29 gross 915 from transformations import _TYPE, Translation, Dilation, Transformation
30 gross 899
31    
32 gross 915 def resetGlobalPrimitiveIdCounter():
33 gross 917 """
34     initializes the global primitive ID counter
35     """
36 gross 915 global global_primitive_id_counter
37     global_primitive_id_counter=1
38    
39 gross 916 def setToleranceForColocation(tol=1.e-11):
40 gross 917 """
41     set the global tolerance for colocation checks to tol
42     """
43 gross 916 global global_tolerance_for_colocation
44     global_tolerance_for_colocation=tol
45    
46     def getToleranceForColocation():
47 gross 917 """
48     returns the global tolerance for colocation checks
49     """
50 gross 916 return global_tolerance_for_colocation
51    
52 gross 915 resetGlobalPrimitiveIdCounter()
53 gross 916 setToleranceForColocation()
54 gross 915
55 gross 899 class Primitive(object):
56 gross 898 """
57     template for elementary geometrical object
58     """
59     def __init__(self):
60     """
61 gross 915
62 gross 898 """
63 gross 899 global global_primitive_id_counter
64     self.__ID=global_primitive_id_counter
65     global_primitive_id_counter+=1
66 gross 915
67 gross 899 def getID(self):
68     return self.__ID
69 gross 915
70 gross 899 def __repr__(self):
71     return "%s(%s)"%(self.__class__.__name__,self.getID())
72     def __cmp__(self,other):
73     return cmp(self.getID(),other.getID())
74 gross 916
75     def getConstructionPoints(self):
76 gross 912 """
77 gross 916 returns the points used to construct the primitive
78 gross 912 """
79     out=set()
80 gross 916 for i in self.getPrimitives():
81 gross 912 if isinstance(i,Point): out.add(i)
82 gross 916 return list(out)
83 gross 912
84 gross 916 def getPrimitives(self):
85 gross 912 """
86 gross 916 returns primitives used to construct the primitive
87 gross 912 """
88 gross 916 return []
89 gross 912
90 gross 915 def copy(self):
91     """
92 gross 916 returns a deep copy of the object
93 gross 915 """
94     return Primitive()
95 gross 912
96 gross 915
97     def modifyBy(self,transformation):
98 gross 916 """
99     modifies the coordinates by applying a transformation
100     """
101     for p in self.getConstructionPoints(): p.modifyBy(transformation)
102 gross 915
103 gross 916
104 gross 915 def __add__(self,other):
105     """
106     returns a new object shifted by other
107     """
108     return self.apply(Translation(numarray.array(other,_TYPE)))
109    
110     def __sub__(self,other):
111     """
112     returns a new object shifted by other
113     """
114     return self.apply(Translation(-numarray.array(other,_TYPE)))
115    
116     def __iadd__(self,other):
117     """
118     shifts the point by other
119     """
120     self.modifyBy(Translation(numarray.array(other,_TYPE)))
121     return self
122    
123     def __isub__(self,other):
124     """
125     shifts the point by -other
126     """
127     self.modifyBy(Translation(-numarray.array(other,_TYPE)))
128     return self
129    
130     def __imul__(self,other):
131     """
132     modifies object by applying L{Transformation} other. If other is not a L{Transformation} it will try convert it.
133     """
134     if isinstance(other,int) or isinstance(other,float):
135     trafo=Dilation(other)
136     elif isinstance(other,numarray.NumArray):
137     trafo=Translation(other)
138     elif isinstance(other,Transformation):
139     trafo=other
140     else:
141     raise TypeError, "cannot convert argument to Trnsformation class object."
142     self.modifyBy(trafo)
143     return self
144    
145     def __rmul__(self,other):
146     """
147     applies L{Transformation} other to object. If other is not a L{Transformation} it will try convert it.
148     """
149     if isinstance(other,int) or isinstance(other,float):
150     trafo=Dilation(other)
151     elif isinstance(other,numarray.NumArray):
152     trafo=Translation(other)
153     elif isinstance(other,Transformation):
154     trafo=other
155     else:
156 gross 916 raise TypeError, "cannot convert argument to Transformation class object."
157 gross 915 return self.apply(trafo)
158    
159 gross 899 def __neg__(self):
160     return ReversedPrimitive(self)
161 gross 915
162 gross 916 def setLocalScale(self,factor=1.):
163     """
164     sets the local refinement factor
165     """
166     for p in self.getConstructionPoints(): p.setLocalScale(factor)
167    
168     def getGmshCommand(self, local_scaling_factor=1.):
169     """
170     returns the Gmsh command(s) to create the primitive
171     """
172 gross 902 raise NotImplementedError("getGmshCommand is not implemented for this class %s."%self.__class__.__name__)
173 gross 898
174 gross 916 def apply(self,transformation):
175     """
176     returns a new object by applying the transformation
177     """
178     raise NotImplementedError("apply is not implemented for this class %s."%self.__class__.__name__)
179    
180     def isColocated(self,primitive):
181     """
182     returns True is the two primitives are located at the smae position
183     """
184     raise NotImplementedError("isColocated is not implemented for this class %s."%self.__class__.__name__)
185    
186 gross 899 class Point(Primitive):
187 gross 898 """
188     a three dimensional point
189     """
190     def __init__(self,x=0.,y=0.,z=0.,local_scale=1.):
191     """
192 gross 912 creates a point with coorinates x,y,z with the local refinement factor local_scale
193 gross 898 """
194     super(Point, self).__init__()
195 gross 915 self.setCoordinates(numarray.array([x,y,z],_TYPE))
196 gross 899 self.setLocalScale(local_scale)
197 gross 915
198 gross 898 def setLocalScale(self,factor=1.):
199 gross 902 """
200 gross 912 sets the local refinement factor
201 gross 902 """
202 gross 912 if factor<=0.:
203     raise ValueError("scaling factor must be positive.")
204 gross 898 self.__local_scale=factor
205 gross 902 def getLocalScale(self):
206 gross 912 """
207     returns the local refinement factor
208     """
209 gross 902 return self.__local_scale
210 gross 912 def getCoordinates(self):
211     """
212     returns the coodinates of the point as L{numarray.NumArray} object
213     """
214     return self._x
215 gross 915 def setCoordinates(self,x):
216 gross 912 """
217     returns the coodinates of the point as L{numarray.NumArray} object
218     """
219 gross 915 if not isinstance(x, numarray.NumArray):
220     self._x=numarray.array(x,_TYPE)
221     else:
222     self._x=x
223    
224 gross 916 def getPrimitives(self):
225 gross 912 """
226 gross 916 returns primitives used to construct the primitive
227 gross 912 """
228 gross 916 return [self]
229 gross 912
230 gross 916 def isColocated(self,primitive):
231 gross 912 """
232 gross 916 returns True if L{Point} primitive is colocation (same coordinates)
233     that means if |self-primitive| <= tol * max(|self|,|primitive|)
234 gross 912 """
235 gross 916 if isinstance(primitive,Point):
236     primitive=primitive.getCoordinates()
237     c=self.getCoordinates()
238     d=c-primitive
239     return numarray.dot(d,d)<=getToleranceForColocation()**2*max(numarray.dot(c,c),numarray.dot(primitive,primitive))
240     else:
241     return False
242 gross 912
243 gross 902 def copy(self):
244 gross 915 """
245 gross 916 returns a deep copy of the point
246 gross 915 """
247 gross 902 c=self.getCoordinates()
248     return Point(c[0],c[1],c[2],local_scale=self.getLocalScale())
249 gross 915
250     def modifyBy(self,transformation):
251     """
252     modifies the coordinates by applying a transformation
253     """
254     self.setCoordinates(transformation(self.getCoordinates()))
255    
256     def apply(self,transformation):
257     """
258     returns a new L{Point} by applying the transformation
259     """
260     new_p=self.copy()
261     new_p.modifyBy(transformation)
262     return new_p
263    
264     def getGmshCommand(self, local_scaling_factor=1.):
265 gross 916 """
266     returns the Gmsh command(s) to create the primitive
267     """
268 gross 899 c=self.getCoordinates()
269 gross 915 return "Point(%s) = {%s , %s, %s , %s };"%(self.getID(),c[0],c[1],c[2], self.getLocalScale()*local_scaling_factor)
270 gross 898
271 gross 916 class Primitive1D(Primitive):
272 gross 898 """
273 gross 916 general one-dimensional primitive
274 gross 898 """
275     def __init__(self,*args):
276     """
277 gross 916 create a one-dimensional primitive
278 gross 898 """
279 gross 916 super(Primitive1D, self).__init__()
280    
281     class Curve(Primitive1D):
282     """
283     a curve defined through a list of control points.
284     """
285     def __init__(self,*points):
286     """
287     defines a curve form control points
288     """
289     if len(points)<2:
290     raise TypeError("Curve needs at least two points")
291 gross 898 super(Curve, self).__init__()
292 gross 916 i=0
293     for p in points:
294     i+=1
295     if not isinstance(p,Point): raise TypeError("%s-th argument is not a Point object."%i)
296     self.__points=points
297    
298     def __len__(self):
299     """
300     returns the number of control points
301     """
302     return len(self.__points)
303    
304     def getStartPoint(self):
305 gross 898 """
306     returns start point
307     """
308 gross 916 return self.__points[0]
309 gross 898
310 gross 916 def getEndPoint(self):
311 gross 898 """
312     returns end point
313     """
314 gross 916 return self.__points[-1]
315 gross 898
316 gross 916 def getControlPoints(self):
317 gross 898 """
318 gross 916 returns a list of the points
319 gross 898 """
320 gross 916 return self.__points
321    
322     def getPrimitives(self):
323     """
324     returns primitives used to construct the Curve
325     """
326     out=set()
327     for p in self.getControlPoints(): out|=set(p.getPrimitives())
328     out.add(self)
329     return list(out)
330    
331     def copy(self):
332     """
333     returns a deep copy
334     """
335     new_p=[]
336     for p in self.getControlPoints(): new_p.append(p.copy())
337     return self.__class__(*tuple(new_p))
338    
339    
340     def apply(self,transformation):
341     """
342     applies transformation
343     """
344     new_p=[]
345     for p in self.getControlPoints(): new_p.append(p.apply(transformation))
346     return self.__class__(*tuple(new_p))
347    
348     def isColocated(self,primitive):
349     """
350     returns True curves are on the same position
351     """
352     if isinstance(primitive,self.__class__):
353     if len(primitive) == len(self):
354     cp0=self.getControlPoints()
355     cp1=primitive.getControlPoints()
356 gross 919 match=True
357 gross 916 for i in range(len(cp0)):
358     if not cp0[i].isColocated(cp1[i]):
359 gross 919 match=False
360     break
361     if not match:
362     for i in range(len(cp0)):
363     if not cp0[i].isColocated(cp1[len(cp0)-1-i]):
364     return False
365 gross 916 return True
366     else:
367     return False
368     else:
369     return False
370    
371     class Spline(Curve):
372     """
373     a spline curve defined through a list of control points.
374     """
375     def getGmshCommand(self):
376     """
377     returns the Gmsh command(s) to create the Curve
378     """
379 gross 899 out=""
380 gross 916 for i in self.getControlPoints():
381 gross 899 if len(out)>0:
382     out+=", %s"%i.getID()
383     else:
384     out="%s"%i.getID()
385     return "Spline(%s) = {%s};"%(self.getID(),out)
386 gross 916
387 gross 898
388     class BezierCurve(Curve):
389     """
390     a Bezier curve
391     """
392 gross 899 def getGmshCommand(self):
393 gross 916 """
394     returns the Gmsh command(s) to create the Curve
395     """
396 gross 899 out=""
397 gross 916 for i in self.getControlPoints():
398 gross 899 if len(out)>0:
399     out+=", %s"%i.getID()
400     else:
401     out="%s"%i.getID()
402     return "Bezier(%s) = {%s};"%(self.getID(),out)
403 gross 898
404 gross 916 class BSpline(Curve):
405 gross 898 """
406     a BSpline curve. Control points may be repeated.
407     """
408 gross 899 def getGmshCommand(self):
409 gross 916 """
410     returns the Gmsh command(s) to create the Curve
411     """
412 gross 899 out=""
413 gross 916 for i in self.getControlPoints():
414 gross 899 if len(out)>0:
415     out+=", %s"%i.getID()
416     else:
417     out="%s"%i.getID()
418     return "BSpline(%s) = {%s};"%(self.getID(),out)
419 gross 898
420     class Line(Curve):
421     """
422     a line is defined by two L{Point}s
423     """
424 gross 916 def __init__(self,*points):
425 gross 899 """
426 gross 916 defines a line with start and end point
427 gross 899 """
428 gross 916 if len(points)!=2:
429     raise TypeError("Line needs two points")
430     super(Line, self).__init__(*points)
431 gross 899 def getGmshCommand(self):
432 gross 916 """
433     returns the Gmsh command(s) to create the Curve
434     """
435     return "Line(%s) = {%s, %s};"%(self.getID(),self.getStartPoint().getID(),self.getEndPoint().getID())
436 gross 898
437 gross 916
438     class Arc(Primitive1D):
439 gross 898 """
440 gross 917 defines an arc which is strictly, smaller than Pi
441 gross 898 """
442     def __init__(self,center,start,end):
443     """
444     creates an arc by the start point, end point and center
445     """
446 gross 917 if not isinstance(center,Point): raise TypeError("center needs to be a Point object.")
447     if not isinstance(end,Point): raise TypeError("end needs to be a Point object.")
448     if not isinstance(start,Point): raise TypeError("start needs to be a Point object.")
449     # TODO: check length of circle.
450 gross 916 super(Arc, self).__init__()
451 gross 898 self.__center=center
452 gross 916 self.__start=start
453     self.__end=end
454 gross 898
455 gross 916 def getStartPoint(self):
456 gross 898 """
457 gross 916 returns start point
458     """
459     return self.__start
460    
461     def getEndPoint(self):
462     """
463     returns end point
464     """
465     return self.__end
466    
467     def getCenterPoint(self):
468     """
469 gross 898 returns center
470     """
471     return self.__center
472    
473 gross 916 def getPrimitives(self):
474     """
475 gross 917 returns the primitives used to construct the Curve
476 gross 916 """
477     out=set()
478     out|=set(self.getStartPoint().getPrimitives())
479     out|=set(self.getEndPoint().getPrimitives())
480     out|=set(self.getCenterPoint().getPrimitives())
481     out.add(self)
482     return list(out)
483    
484 gross 899 def getGmshCommand(self):
485 gross 916 """
486     returns the Gmsh command(s) to create the primitive
487     """
488     return "Circle(%s) = {%s, %s, %s};"%(self.getID(),self.getStartPoint().getID(),self.getCenterPoint().getID(),self.getEndPoint().getID())
489 gross 899
490 gross 916 def copy(self):
491     """
492     returns a deep copy
493     """
494     return Arc(self.getCenterPoint().copy(),self.getStartPoint().copy(),self.getEndPoint().copy())
495    
496     def apply(self,transformation):
497     """
498     applies transformation
499     """
500     return Arc(self.getCenterPoint().apply(transformation),self.getStartPoint().apply(transformation),self.getEndPoint().apply(transformation))
501    
502     def isColocated(self,primitive):
503     """
504     returns True curves are on the same position
505     """
506     if isinstance(primitive,Arc):
507 gross 919 return (self.getCenterPoint().isColocated(primitive.getCenterPoint())) and ( \
508     (self.getEndPoint().isColocated(primitive.getEndPoint()) and self.getStartPoint().isColocated(primitive.getStartPoint()) ) \
509     or (self.getEndPoint().isColocated(primitive.getStartPoint()) and self.getStartPoint().isColocated(primitive.getEndPoint()) ) )
510 gross 916 else:
511     return False
512    
513 gross 919 class Primitive2D(Primitive):
514     """
515     general two-dimensional primitive
516     """
517     def __init__(self,*args):
518     """
519     create a two-dimensional primitive
520     """
521     super(Primitive2D, self).__init__()
522     class CurveLoop(Primitive2D):
523 gross 898 """
524     An oriented loop of curves.
525    
526     The loop must be closed and the L{Curves}s should be oriented consistently.
527     """
528     def __init__(self,*curves):
529     """
530     creates a polygon from a list of line curves. The curves must form a closed loop.
531     """
532     super(CurveLoop, self).__init__()
533 gross 899 self.__curves=[]
534     self.addCurve(*curves)
535     def addCurve(self,*curves):
536 gross 919 """
537     adds curves to the curves defining the object
538     """
539 gross 899 for i in range(len(curves)):
540 gross 919 if not isinstance(curves[i],Primitive1D):
541     raise TypeError("%s-th argument is not a Primitive1D object."%i)
542 gross 899 self.__curves+=curves
543 gross 898
544     def getCurves(self):
545 gross 919 """
546     returns the curves defining the CurveLoop
547     """
548 gross 898 return self.__curves
549     def __len__(self):
550 gross 919 """
551     return the number of curves in the CurveLoop
552     """
553 gross 898 return len(self.__curves)
554 gross 919
555 gross 916 def getPrimitives(self):
556 gross 919 """
557     returns primitives used to construct the CurveLoop
558     """
559     out=set()
560     for c in self.getCurves(): out|=set(c.getPrimitives())
561     out.add(self)
562     return list(out)
563    
564     def copy(self):
565     """
566     returns a deep copy
567     """
568     new_c=[]
569     for c in self.getCurves(): new_c.append(c.copy())
570     return CurveLoop(*tuple(new_c))
571    
572    
573     def apply(self,transformation):
574     """
575     applies transformation
576     """
577     new_c=[]
578     for c in self.getCurves(): new_c.append(c.apply(transformation))
579     return CurveLoop(*tuple(new_c))
580    
581     def isColocated(self,primitive):
582     """
583     returns True if each curve is collocted with a curve in primitive
584     """
585     if isinstance(primitive,CurveLoop):
586     if len(primitive) == len(self):
587     cp0=self.getCurves()
588     cp1=primitive.getCurves()
589     for c0 in cp0:
590     collocated = False
591     for c1 in cp1: collocated = collocated or c0.isColocated(c1)
592     if not collocated: return False
593     return True
594     else:
595     return False
596     else:
597     return False
598    
599 gross 899 def getGmshCommand(self):
600     out=""
601     for i in self.getCurves():
602     if len(out)>0:
603     out+=", %s"%i.getID()
604     else:
605     out="%s"%i.getID()
606     return "Line Loop(%s) = {%s};"%(self.getID(),out)
607 gross 898
608 gross 919 #=================================================================================================================================
609 gross 899 class Surface(Primitive):
610 gross 898 """
611     a surface
612     """
613     def __init__(self,loop):
614     """
615     creates a surface with boundary loop
616    
617     @param loop: L{CurveLoop} defining the boundary of the surface
618     """
619     super(Surface, self).__init__()
620 gross 899 if not loop.isCurveLoop():
621 gross 898 raise TypeError("argument loop needs to be a CurveLoop object.")
622     self.__loop=loop
623 gross 899 def isSurface(self):
624     return True
625 gross 898 def getBoundaryLoop(self):
626     return self.__loop
627 gross 899 def __add__(self,other):
628     return Surface(self.getBoundaryLoop()+other)
629 gross 916 def getPrimitives(self):
630     out=set([self]) | self.getBoundaryLoop().getPrimitives()
631 gross 899 return out
632 gross 916 def getConstructionPoints(self):
633     return self.getBoundaryLoop().getConstructionPoints()
634 gross 899 def getGmshCommand(self):
635     return "Ruled Surface(%s) = {%s};"%(self.getID(),self.getBoundaryLoop().getID())
636    
637 gross 898 class PlaneSurface(Surface):
638     """
639     a plane surface with holes
640     """
641     def __init__(self,loop,holes=[]):
642     """
643     creates a plane surface.
644    
645     @param loop: L{CurveLoop} defining the boundary of the surface
646     @param holes: list of L{CurveLoop} defining holes in the surface.
647     @note: A CurveLoop defining a hole should not have any lines in common with the exterior CurveLoop.
648     A CurveLoop defining a hole should not have any lines in common with another CurveLoop defining a hole in the same surface.
649     """
650     super(PlaneSurface, self).__init__(loop)
651     for i in range(len(holes)):
652 gross 899 if not holes[i].inCurveLoop():
653 gross 898 raise TypeError("%i th hole needs to be a CurveLoop object.")
654     self.__holes=holes
655     def getHoles(self):
656     return self.__holes
657 gross 899 def __add__(self,other):
658     return PlaneSurface(self.getBoundaryLoop()+other, holes=[h+other for h in self.getHoles()])
659 gross 916 def getPrimitives(self):
660     out=set([self]) | self.getBoundaryLoop().getPrimitives()
661     for i in self.getHoles(): out|=i.getPrimitives()
662 gross 899 return out
663 gross 916 def getConstructionPoints(self):
664     out=self.getBoundaryLoop().getConstructionPoints()
665     for i in self.getHoles(): out|=i.getConstructionPoints()
666 gross 902 return out
667 gross 899 def getGmshCommand(self):
668     out=""
669     for i in self.getHoles():
670     if len(out)>0:
671     out+=", %s"%i.getID()
672     else:
673     out="%s"%i.getID()
674     if len(out)>0:
675     return "Plane Surface(%s) = {%s, %s};"%(self.getID(),self.getBoundaryLoop().getID(), out)
676     else:
677     return "Plane Surface(%s) = {%s};"%(self.getID(),self.getBoundaryLoop().getID())
678 gross 898
679     class RuledSurface(Surface):
680     """
681     A ruled surface, i.e., a surface that can be interpolated using transfinite interpolation
682     """
683     def __init__(self,loop):
684     """
685     creates a ruled surface from a
686    
687     @param loop: L{CurveLoop} defining the boundary of the surface. There is a restriction of composed of either three or four L{Curve} objects.
688     """
689 gross 899 if not loop.isCurveLoop():
690 gross 898 raise TypeError("argument loop needs to be a CurveLoop object.")
691     if len(loop)<3:
692     raise TypeError("the loop must contain at least three Curves.")
693     super(RuledSurface, self).__init__(loop)
694 gross 899 def __add__(self,other):
695     return RuledSurface(self.getBoundaryLoop()+other)
696     def getGmshCommand(self):
697     return "Ruled Surface(%s) = {%s};"%(self.getID(),self.getBoundaryLoop().getID())
698 gross 898
699 gross 899 class SurfaceLoop(Primitive):
700 gross 898 """
701     a surface loop. It defines the shell of a volume.
702    
703     The loop must represent a closed shell, and the L{Surface}s should be oriented consistently.
704     """
705     def __init__(self,*surfaces):
706     """
707     creates a surface loop
708     """
709     super(SurfaceLoop, self).__init__()
710 gross 899 self.__surfaces=[]
711     self.addSurface(*surfaces)
712     def addSurface(self,*surfaces):
713     for i in range(len(surfaces)):
714     if not surfaces[i].isSurface():
715     raise TypeError("%s-th argument is not a Surface object."%i)
716     self.__surfaces+=surfaces
717 gross 898
718 gross 899 def isSurfaceLoop(self):
719     return True
720 gross 898 def getSurfaces(self):
721     return self.__surfaces
722 gross 899 def __add__(self,other):
723     return SurfaceLoop([c+other for c in self.getSurfaces])
724 gross 898 def __len__(self):
725     return len(self.__surfaces)
726 gross 916 def getPrimitives(self):
727 gross 899 out=set([self])
728 gross 916 for i in self.getSurfaces(): out|=i.getPrimitives()
729 gross 899 return out
730 gross 916 def getConstructionPoints(self):
731 gross 902 out=set()
732 gross 916 for i in self.getSurfaces(): out|=i.getConstructionPoints()
733 gross 902 return out
734 gross 899 def getGmshCommand(self):
735     out=""
736     for i in self.getSurfaces():
737     if len(out)>0:
738     out+=", %s"%i.getID()
739     else:
740     out="%s"%i.getID()
741     return "Surface Loop(%s) = {%s};"%(self.getID(),out)
742 gross 898
743 gross 899 class Volume(Primitive):
744 gross 898 """
745     a volume with holes.
746     """
747     def __init__(self,loop,holes=[]):
748     """
749     creates a volume
750    
751     @param loop: L{SurfaceLoop} defining the boundary of the surface
752     @param holes: list of L{SurfaceLoop} defining holes in the surface.
753     @note: A SurfaceLoop defining a hole should not have any surfaces in common with the exterior SurfaceLoop.
754     A SurfaceLoop defining a hole should not have any surfaces in common with another SurfaceLoop defining a hole in the same volume.
755     """
756     super(Volume, self).__init__()
757 gross 899 if not loop.isSurfaceLoop():
758 gross 898 raise TypeError("argument loop needs to be a SurfaceLoop object.")
759     for i in range(len(holes)):
760 gross 899 if not holes[i].isSurfaceLoop():
761 gross 898 raise TypeError("%i th hole needs to be a SurfaceLoop object.")
762     self.__loop=loop
763     self.__holes=holes
764     def getHoles(self):
765     return self.__holes
766     def getSurfaceLoop(self):
767     return self.__loop
768 gross 899 def __add__(self,other):
769     return Volume(self.getSurfaceLoop()+other, holes=[h+other for h in self.getHoles()])
770 gross 916 def getPrimitives(self):
771     out=set([self]) | self.getSurfaceLoop().getPrimitives()
772     for i in self.getHoles(): out|=i.getPrimitives()
773 gross 899 return out
774 gross 916 def getConstructionPoints(self):
775     out=self.getSurfaceLoop().getConstructionPoints()
776 gross 902 for i in self.getHoles(): out|=i.Points()
777     return out
778 gross 899 def getGmshCommand(self):
779     out=""
780     for i in self.getHoles():
781     if len(out)>0:
782     out+=", %s"%i.getID()
783     else:
784     out="%s"%i.getID()
785     if len(out)>0:
786     return "Volume(%s) = {%s, %s};"%(self.getID(),self.getSurfaceLoop().getID(), out)
787     else:
788     return "Volume(%s) = {%s};"%(self.getID(),self.getSurfaceLoop().getID())
789 gross 898
790 gross 912 class ReversedPrimitive(object):
791     def __init__(self,prim):
792     self.__prim=prim
793     def __getattr__(self,name):
794     if name == "getID":
795     return self.getReverseID
796     else:
797     return getattr(self.__prim,name)
798     def getReverseID(self):
799     return -self.__prim.getID()
800    
801 gross 899 class PropertySet(Primitive):
802 gross 898 """
803 gross 899 defines a group L{Primitive} objects.
804 gross 898 """
805     def __init__(self,tag=None,*items):
806     super(PropertySet, self).__init__()
807     self.__items=items
808     self.__tag=tag
809 gross 916 def getPrimitives(self):
810     out=set([self, self.getBoundaryLoop().getPrimitives()])
811     for i in self.getHoles(): out|=i.getPrimitives()
812 gross 899 return out
813    
814     class PrimitiveStack(object):
815     def __init__(self,*items):
816     self.__prims=set()
817     for i in items:
818 gross 916 self.__prims|=i.getPrimitives()
819 gross 899 self.__prims=list(self.__prims)
820     self.__prims.sort()
821    
822     def getGmshCommands(self):
823     out=""
824     for i in self.__prims:
825     out+=i.getGmshCommand()+"\n"
826     return out

  ViewVC Help
Powered by ViewVC 1.1.26