/[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 919 - (show 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 # $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 def __cmp__(self,other):
73 return cmp(self.getID(),other.getID())
74
75 def getConstructionPoints(self):
76 """
77 returns the points used to construct the primitive
78 """
79 out=set()
80 for i in self.getPrimitives():
81 if isinstance(i,Point): out.add(i)
82 return list(out)
83
84 def getPrimitives(self):
85 """
86 returns primitives used to construct the primitive
87 """
88 return []
89
90 def copy(self):
91 """
92 returns a deep copy of the object
93 """
94 return Primitive()
95
96
97 def modifyBy(self,transformation):
98 """
99 modifies the coordinates by applying a transformation
100 """
101 for p in self.getConstructionPoints(): p.modifyBy(transformation)
102
103
104 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 raise TypeError, "cannot convert argument to Transformation class object."
157 return self.apply(trafo)
158
159 def __neg__(self):
160 return ReversedPrimitive(self)
161
162 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 raise NotImplementedError("getGmshCommand is not implemented for this class %s."%self.__class__.__name__)
173
174 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 class Point(Primitive):
187 """
188 a three dimensional point
189 """
190 def __init__(self,x=0.,y=0.,z=0.,local_scale=1.):
191 """
192 creates a point with coorinates x,y,z with the local refinement factor local_scale
193 """
194 super(Point, self).__init__()
195 self.setCoordinates(numarray.array([x,y,z],_TYPE))
196 self.setLocalScale(local_scale)
197
198 def setLocalScale(self,factor=1.):
199 """
200 sets the local refinement factor
201 """
202 if factor<=0.:
203 raise ValueError("scaling factor must be positive.")
204 self.__local_scale=factor
205 def getLocalScale(self):
206 """
207 returns the local refinement factor
208 """
209 return self.__local_scale
210 def getCoordinates(self):
211 """
212 returns the coodinates of the point as L{numarray.NumArray} object
213 """
214 return self._x
215 def setCoordinates(self,x):
216 """
217 returns the coodinates of the point as L{numarray.NumArray} object
218 """
219 if not isinstance(x, numarray.NumArray):
220 self._x=numarray.array(x,_TYPE)
221 else:
222 self._x=x
223
224 def getPrimitives(self):
225 """
226 returns primitives used to construct the primitive
227 """
228 return [self]
229
230 def isColocated(self,primitive):
231 """
232 returns True if L{Point} primitive is colocation (same coordinates)
233 that means if |self-primitive| <= tol * max(|self|,|primitive|)
234 """
235 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
243 def copy(self):
244 """
245 returns a deep copy of the point
246 """
247 c=self.getCoordinates()
248 return Point(c[0],c[1],c[2],local_scale=self.getLocalScale())
249
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 """
266 returns the Gmsh command(s) to create the primitive
267 """
268 c=self.getCoordinates()
269 return "Point(%s) = {%s , %s, %s , %s };"%(self.getID(),c[0],c[1],c[2], self.getLocalScale()*local_scaling_factor)
270
271 class Primitive1D(Primitive):
272 """
273 general one-dimensional primitive
274 """
275 def __init__(self,*args):
276 """
277 create a one-dimensional primitive
278 """
279 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 super(Curve, self).__init__()
292 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 """
306 returns start point
307 """
308 return self.__points[0]
309
310 def getEndPoint(self):
311 """
312 returns end point
313 """
314 return self.__points[-1]
315
316 def getControlPoints(self):
317 """
318 returns a list of the points
319 """
320 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 match=True
357 for i in range(len(cp0)):
358 if not cp0[i].isColocated(cp1[i]):
359 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 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 out=""
380 for i in self.getControlPoints():
381 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
387
388 class BezierCurve(Curve):
389 """
390 a Bezier curve
391 """
392 def getGmshCommand(self):
393 """
394 returns the Gmsh command(s) to create the Curve
395 """
396 out=""
397 for i in self.getControlPoints():
398 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
404 class BSpline(Curve):
405 """
406 a BSpline curve. Control points may be repeated.
407 """
408 def getGmshCommand(self):
409 """
410 returns the Gmsh command(s) to create the Curve
411 """
412 out=""
413 for i in self.getControlPoints():
414 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
420 class Line(Curve):
421 """
422 a line is defined by two L{Point}s
423 """
424 def __init__(self,*points):
425 """
426 defines a line with start and end point
427 """
428 if len(points)!=2:
429 raise TypeError("Line needs two points")
430 super(Line, self).__init__(*points)
431 def getGmshCommand(self):
432 """
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
437
438 class Arc(Primitive1D):
439 """
440 defines an arc which is strictly, smaller than Pi
441 """
442 def __init__(self,center,start,end):
443 """
444 creates an arc by the start point, end point and center
445 """
446 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 super(Arc, self).__init__()
451 self.__center=center
452 self.__start=start
453 self.__end=end
454
455 def getStartPoint(self):
456 """
457 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 returns center
470 """
471 return self.__center
472
473 def getPrimitives(self):
474 """
475 returns the primitives used to construct the Curve
476 """
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 def getGmshCommand(self):
485 """
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
490 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 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 else:
511 return False
512
513 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 """
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 self.__curves=[]
534 self.addCurve(*curves)
535 def addCurve(self,*curves):
536 """
537 adds curves to the curves defining the object
538 """
539 for i in range(len(curves)):
540 if not isinstance(curves[i],Primitive1D):
541 raise TypeError("%s-th argument is not a Primitive1D object."%i)
542 self.__curves+=curves
543
544 def getCurves(self):
545 """
546 returns the curves defining the CurveLoop
547 """
548 return self.__curves
549 def __len__(self):
550 """
551 return the number of curves in the CurveLoop
552 """
553 return len(self.__curves)
554
555 def getPrimitives(self):
556 """
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 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
608 #=================================================================================================================================
609 class Surface(Primitive):
610 """
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 if not loop.isCurveLoop():
621 raise TypeError("argument loop needs to be a CurveLoop object.")
622 self.__loop=loop
623 def isSurface(self):
624 return True
625 def getBoundaryLoop(self):
626 return self.__loop
627 def __add__(self,other):
628 return Surface(self.getBoundaryLoop()+other)
629 def getPrimitives(self):
630 out=set([self]) | self.getBoundaryLoop().getPrimitives()
631 return out
632 def getConstructionPoints(self):
633 return self.getBoundaryLoop().getConstructionPoints()
634 def getGmshCommand(self):
635 return "Ruled Surface(%s) = {%s};"%(self.getID(),self.getBoundaryLoop().getID())
636
637 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 if not holes[i].inCurveLoop():
653 raise TypeError("%i th hole needs to be a CurveLoop object.")
654 self.__holes=holes
655 def getHoles(self):
656 return self.__holes
657 def __add__(self,other):
658 return PlaneSurface(self.getBoundaryLoop()+other, holes=[h+other for h in self.getHoles()])
659 def getPrimitives(self):
660 out=set([self]) | self.getBoundaryLoop().getPrimitives()
661 for i in self.getHoles(): out|=i.getPrimitives()
662 return out
663 def getConstructionPoints(self):
664 out=self.getBoundaryLoop().getConstructionPoints()
665 for i in self.getHoles(): out|=i.getConstructionPoints()
666 return out
667 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
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 if not loop.isCurveLoop():
690 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 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
699 class SurfaceLoop(Primitive):
700 """
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 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
718 def isSurfaceLoop(self):
719 return True
720 def getSurfaces(self):
721 return self.__surfaces
722 def __add__(self,other):
723 return SurfaceLoop([c+other for c in self.getSurfaces])
724 def __len__(self):
725 return len(self.__surfaces)
726 def getPrimitives(self):
727 out=set([self])
728 for i in self.getSurfaces(): out|=i.getPrimitives()
729 return out
730 def getConstructionPoints(self):
731 out=set()
732 for i in self.getSurfaces(): out|=i.getConstructionPoints()
733 return out
734 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
743 class Volume(Primitive):
744 """
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 if not loop.isSurfaceLoop():
758 raise TypeError("argument loop needs to be a SurfaceLoop object.")
759 for i in range(len(holes)):
760 if not holes[i].isSurfaceLoop():
761 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 def __add__(self,other):
769 return Volume(self.getSurfaceLoop()+other, holes=[h+other for h in self.getHoles()])
770 def getPrimitives(self):
771 out=set([self]) | self.getSurfaceLoop().getPrimitives()
772 for i in self.getHoles(): out|=i.getPrimitives()
773 return out
774 def getConstructionPoints(self):
775 out=self.getSurfaceLoop().getConstructionPoints()
776 for i in self.getHoles(): out|=i.Points()
777 return out
778 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
790 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 class PropertySet(Primitive):
802 """
803 defines a group L{Primitive} objects.
804 """
805 def __init__(self,tag=None,*items):
806 super(PropertySet, self).__init__()
807 self.__items=items
808 self.__tag=tag
809 def getPrimitives(self):
810 out=set([self, self.getBoundaryLoop().getPrimitives()])
811 for i in self.getHoles(): out|=i.getPrimitives()
812 return out
813
814 class PrimitiveStack(object):
815 def __init__(self,*items):
816 self.__prims=set()
817 for i in items:
818 self.__prims|=i.getPrimitives()
819 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