/[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 925 - (show annotations)
Wed Jan 10 22:40:00 2007 UTC (12 years, 8 months ago) by gross
File MIME type: text/x-python
File size: 27354 byte(s)
testing for CurvedLoop 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 self.substitute({})
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 L{Point} by applying the transformation
178 """
179 out=self.copy()
180 out.modifyBy(transformation)
181 return out
182
183 def isColocated(self,primitive):
184 """
185 returns True is the two primitives are located at the smae position
186 """
187 raise NotImplementedError("isColocated is not implemented for this class %s."%self.__class__.__name__)
188
189 def substitute(self,sub_dict):
190 """
191 returns a copy of self with substitutes for the primitives used to construct it given by the dictionary C{sub_dict}.
192 If a substitute for the object is given by C{sub_dict} the value is returned, otherwise a new instance
193 with substituted arguments is returned.
194 """
195 if not sub_dict.has_key(self):
196 sub_dict[self]=self.__class__()
197 return sub_dict[self]
198
199 class Point(Primitive):
200 """
201 a three dimensional point
202 """
203 def __init__(self,x=0.,y=0.,z=0.,local_scale=1.):
204 """
205 creates a point with coorinates x,y,z with the local refinement factor local_scale
206 """
207 super(Point, self).__init__()
208 self.setCoordinates(numarray.array([x,y,z],_TYPE))
209 self.setLocalScale(local_scale)
210
211 def setLocalScale(self,factor=1.):
212 """
213 sets the local refinement factor
214 """
215 if factor<=0.:
216 raise ValueError("scaling factor must be positive.")
217 self.__local_scale=factor
218 def getLocalScale(self):
219 """
220 returns the local refinement factor
221 """
222 return self.__local_scale
223 def getCoordinates(self):
224 """
225 returns the coodinates of the point as L{numarray.NumArray} object
226 """
227 return self._x
228 def setCoordinates(self,x):
229 """
230 returns the coodinates of the point as L{numarray.NumArray} object
231 """
232 if not isinstance(x, numarray.NumArray):
233 self._x=numarray.array(x,_TYPE)
234 else:
235 self._x=x
236
237 def getPrimitives(self):
238 """
239 returns primitives used to construct the primitive
240 """
241 return [self]
242
243 def isColocated(self,primitive):
244 """
245 returns True if L{Point} primitive is colocation (same coordinates)
246 that means if |self-primitive| <= tol * max(|self|,|primitive|)
247 """
248 if isinstance(primitive,Point):
249 primitive=primitive.getCoordinates()
250 c=self.getCoordinates()
251 d=c-primitive
252 return numarray.dot(d,d)<=getToleranceForColocation()**2*max(numarray.dot(c,c),numarray.dot(primitive,primitive))
253 else:
254 return False
255
256 def substitute(self,sub_dict):
257 """
258 returns a copy of self with substitutes for the primitives used to construct it given by the dictionary C{sub_dict}.
259 If a substitute for the object is given by C{sub_dict} the value is returned, otherwise a new instance
260 with substituted arguments is returned.
261 """
262 if not sub_dict.has_key(self):
263 c=self.getCoordinates()
264 sub_dict[self]=Point(c[0],c[1],c[2],local_scale=self.getLocalScale())
265 return sub_dict[self]
266
267 def modifyBy(self,transformation):
268 """
269 modifies the coordinates by applying a transformation
270 """
271 self.setCoordinates(transformation(self.getCoordinates()))
272
273
274 def getGmshCommand(self, local_scaling_factor=1.):
275 """
276 returns the Gmsh command(s) to create the primitive
277 """
278 c=self.getCoordinates()
279 return "Point(%s) = {%s , %s, %s , %s };"%(self.getID(),c[0],c[1],c[2], self.getLocalScale()*local_scaling_factor)
280
281 class Primitive1D(Primitive):
282 """
283 general one-dimensional primitive
284 """
285 def __init__(self,*args):
286 """
287 create a one-dimensional primitive
288 """
289 super(Primitive1D, self).__init__()
290
291 class Curve(Primitive1D):
292 """
293 a curve defined through a list of control points.
294 """
295 def __init__(self,*points):
296 """
297 defines a curve form control points
298 """
299 if len(points)<2:
300 raise TypeError("Curve needs at least two points")
301 super(Curve, self).__init__()
302 i=0
303 for p in points:
304 i+=1
305 if not isinstance(p,Point): raise TypeError("%s-th argument is not a Point object."%i)
306 self.__points=points
307
308 def __len__(self):
309 """
310 returns the number of control points
311 """
312 return len(self.__points)
313
314 def getStartPoint(self):
315 """
316 returns start point
317 """
318 return self.__points[0]
319
320 def getEndPoint(self):
321 """
322 returns end point
323 """
324 return self.__points[-1]
325
326 def getControlPoints(self):
327 """
328 returns a list of the points
329 """
330 return self.__points
331
332 def getPrimitives(self):
333 """
334 returns primitives used to construct the Curve
335 """
336 out=set()
337 for p in self.getControlPoints(): out|=set(p.getPrimitives())
338 out.add(self)
339 return list(out)
340
341 def substitute(self,sub_dict):
342 """
343 returns a copy of self with substitutes for the primitives used to construct it given by the dictionary C{sub_dict}.
344 If a substitute for the object is given by C{sub_dict} the value is returned, otherwise a new instance
345 with substituted arguments is returned.
346 """
347 if not sub_dict.has_key(self):
348 new_p=[]
349 for p in self.getControlPoints(): new_p.append(p.substitute(sub_dict))
350 sub_dict[self]=self.__class__(*tuple(new_p))
351 return sub_dict[self]
352
353 def isColocated(self,primitive):
354 """
355 returns True curves are on the same position
356 """
357 if isinstance(primitive,self.__class__):
358 if len(primitive) == len(self):
359 cp0=self.getControlPoints()
360 cp1=primitive.getControlPoints()
361 match=True
362 for i in range(len(cp0)):
363 if not cp0[i].isColocated(cp1[i]):
364 match=False
365 break
366 if not match:
367 for i in range(len(cp0)):
368 if not cp0[i].isColocated(cp1[len(cp0)-1-i]):
369 return False
370 return True
371 else:
372 return False
373 else:
374 return False
375
376 class Spline(Curve):
377 """
378 a spline curve defined through a list of control points.
379 """
380 def getGmshCommand(self):
381 """
382 returns the Gmsh command(s) to create the Curve
383 """
384 out=""
385 for i in self.getControlPoints():
386 if len(out)>0:
387 out+=", %s"%i.getID()
388 else:
389 out="%s"%i.getID()
390 return "Spline(%s) = {%s};"%(self.getID(),out)
391
392
393 class BezierCurve(Curve):
394 """
395 a Bezier curve
396 """
397 def getGmshCommand(self):
398 """
399 returns the Gmsh command(s) to create the Curve
400 """
401 out=""
402 for i in self.getControlPoints():
403 if len(out)>0:
404 out+=", %s"%i.getID()
405 else:
406 out="%s"%i.getID()
407 return "Bezier(%s) = {%s};"%(self.getID(),out)
408
409 class BSpline(Curve):
410 """
411 a BSpline curve. Control points may be repeated.
412 """
413 def getGmshCommand(self):
414 """
415 returns the Gmsh command(s) to create the Curve
416 """
417 out=""
418 for i in self.getControlPoints():
419 if len(out)>0:
420 out+=", %s"%i.getID()
421 else:
422 out="%s"%i.getID()
423 return "BSpline(%s) = {%s};"%(self.getID(),out)
424
425 class Line(Curve):
426 """
427 a line is defined by two L{Point}s
428 """
429 def __init__(self,*points):
430 """
431 defines a line with start and end point
432 """
433 if len(points)!=2:
434 raise TypeError("Line needs two points")
435 super(Line, self).__init__(*points)
436 def getGmshCommand(self):
437 """
438 returns the Gmsh command(s) to create the Curve
439 """
440 return "Line(%s) = {%s, %s};"%(self.getID(),self.getStartPoint().getID(),self.getEndPoint().getID())
441
442
443 class Arc(Primitive1D):
444 """
445 defines an arc which is strictly, smaller than Pi
446 """
447 def __init__(self,center,start,end):
448 """
449 creates an arc by the start point, end point and center
450 """
451 if not isinstance(center,Point): raise TypeError("center needs to be a Point object.")
452 if not isinstance(end,Point): raise TypeError("end needs to be a Point object.")
453 if not isinstance(start,Point): raise TypeError("start needs to be a Point object.")
454 # TODO: check length of circle.
455 super(Arc, self).__init__()
456 self.__center=center
457 self.__start=start
458 self.__end=end
459
460 def getStartPoint(self):
461 """
462 returns start point
463 """
464 return self.__start
465
466 def getEndPoint(self):
467 """
468 returns end point
469 """
470 return self.__end
471
472 def getCenterPoint(self):
473 """
474 returns center
475 """
476 return self.__center
477
478 def getPrimitives(self):
479 """
480 returns the primitives used to construct the Curve
481 """
482 out=set()
483 out|=set(self.getStartPoint().getPrimitives())
484 out|=set(self.getEndPoint().getPrimitives())
485 out|=set(self.getCenterPoint().getPrimitives())
486 out.add(self)
487 return list(out)
488
489 def getGmshCommand(self):
490 """
491 returns the Gmsh command(s) to create the primitive
492 """
493 return "Circle(%s) = {%s, %s, %s};"%(self.getID(),self.getStartPoint().getID(),self.getCenterPoint().getID(),self.getEndPoint().getID())
494
495 def substitute(self,sub_dict):
496 """
497 returns a copy of self with substitutes for the primitives used to construct it given by the dictionary C{sub_dict}.
498 If a substitute for the object is given by C{sub_dict} the value is returned, otherwise a new instance
499 with substituted arguments is returned.
500 """
501 if not sub_dict.has_key(self):
502 sub_dict[self]=Arc(self.getCenterPoint().substitute(sub_dict),self.getStartPoint().substitute(sub_dict),self.getEndPoint().substitute(sub_dict))
503 return sub_dict[self]
504
505 def isColocated(self,primitive):
506 """
507 returns True curves are on the same position
508 """
509 if isinstance(primitive,Arc):
510 return (self.getCenterPoint().isColocated(primitive.getCenterPoint())) and ( \
511 (self.getEndPoint().isColocated(primitive.getEndPoint()) and self.getStartPoint().isColocated(primitive.getStartPoint()) ) \
512 or (self.getEndPoint().isColocated(primitive.getStartPoint()) and self.getStartPoint().isColocated(primitive.getEndPoint()) ) )
513 else:
514 return False
515
516 class Primitive2D(Primitive):
517 """
518 general two-dimensional primitive
519 """
520 def __init__(self,*args):
521 """
522 create a two-dimensional primitive
523 """
524 super(Primitive2D, self).__init__()
525
526 class CurveLoop(Primitive2D):
527 """
528 An oriented loop of curves.
529
530 The loop must be closed and the L{Curves}s should be oriented consistently.
531 """
532 def __init__(self,*curves):
533 """
534 creates a polygon from a list of line curves. The curves must form a closed loop.
535 """
536 super(CurveLoop, self).__init__()
537 if len(curves)<2:
538 raise TypeError("at least two curves have to be given.")
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 # for the curves a loop:
543 used=[ False for i in curves]
544 self.__curves=[curves[0]]
545 used[0]=True
546 while not min(used):
547 found=False
548 for i in xrange(len(curves)):
549 if not used[i]:
550 if self.__curves[-1].getEndPoint() == curves[i].getStartPoint():
551 self.__curves.append(curves[i])
552 used[i]=True
553 found=True
554 break
555 if not found:
556 raise ValueError("loop is not closed.")
557 if not self.__curves[0].getStartPoint() == self.__curves[-1].getEndPoint():
558 raise ValueError("loop is not closed.")
559
560 def getCurves(self):
561 """
562 returns the curves defining the CurveLoop
563 """
564 return self.__curves
565
566 def __len__(self):
567 """
568 return the number of curves in the CurveLoop
569 """
570 return len(self.__curves)
571
572 def getPrimitives(self):
573 """
574 returns primitives used to construct the CurveLoop
575 """
576 out=set()
577 for c in self.getCurves(): out|=set(c.getPrimitives())
578 out.add(self)
579 return list(out)
580
581 def substitute(self,sub_dict):
582 """
583 returns a copy of self with substitutes for the primitives used to construct it given by the dictionary C{sub_dict}.
584 If a substitute for the object is given by C{sub_dict} the value is returned, otherwise a new instance
585 with substituted arguments is returned.
586 """
587 if not sub_dict.has_key(self):
588 new_c=[]
589 for c in self.getCurves(): new_c.append(c.substitute(sub_dict))
590 sub_dict[self]=CurveLoop(*tuple(new_c))
591 return sub_dict[self]
592
593
594 def isColocated(self,primitive):
595 """
596 returns True if each curve is collocted with a curve in primitive
597 """
598 if isinstance(primitive,CurveLoop):
599 if len(primitive) == len(self):
600 cp0=self.getCurves()
601 cp1=primitive.getCurves()
602 for c0 in cp0:
603 collocated = False
604 for c1 in cp1:
605 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