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

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

Parent Directory Parent Directory | Revision Log Revision Log


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

  ViewVC Help
Powered by ViewVC 1.1.26