/[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 944 - (hide annotations)
Tue Jan 30 08:57:37 2007 UTC (12 years, 8 months ago) by gross
File MIME type: text/x-python
File size: 47864 byte(s)
PropertySet added
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 928
56     class PrimitiveBase(object):
57 gross 898 """
58 gross 929 template for a set of primitives
59 gross 898 """
60 gross 929 def __init__(self):
61 gross 898 """
62 gross 928 initializes PrimitiveBase instance object with id
63 gross 898 """
64 gross 929 pass
65 gross 915
66 gross 899 def __cmp__(self,other):
67 gross 928 """
68     compares object with other by comparing the absolute value of the ID
69     """
70 gross 929 if isinstance(other, PrimitiveBase):
71     return cmp(self.getID(),other.getID())
72 gross 928 else:
73     return False
74 gross 916 def getConstructionPoints(self):
75 gross 912 """
76 gross 916 returns the points used to construct the primitive
77 gross 912 """
78     out=set()
79 gross 916 for i in self.getPrimitives():
80 gross 912 if isinstance(i,Point): out.add(i)
81 gross 916 return list(out)
82 gross 912
83 gross 916 def getPrimitives(self):
84 gross 912 """
85 gross 928 returns a list of primitives used to construct the primitive with no double entries
86 gross 912 """
87 gross 928 out=set()
88 gross 929 return list(set([p for p in self.collectPrimitiveBases()]))
89 gross 912
90 gross 915 def copy(self):
91     """
92 gross 916 returns a deep copy of the object
93 gross 915 """
94 gross 925 return self.substitute({})
95 gross 912
96 gross 915 def modifyBy(self,transformation):
97 gross 916 """
98     modifies the coordinates by applying a transformation
99     """
100     for p in self.getConstructionPoints(): p.modifyBy(transformation)
101 gross 915
102     def __add__(self,other):
103     """
104     returns a new object shifted by other
105     """
106     return self.apply(Translation(numarray.array(other,_TYPE)))
107    
108     def __sub__(self,other):
109     """
110     returns a new object shifted by other
111     """
112     return self.apply(Translation(-numarray.array(other,_TYPE)))
113    
114     def __iadd__(self,other):
115     """
116     shifts the point by other
117     """
118     self.modifyBy(Translation(numarray.array(other,_TYPE)))
119     return self
120    
121     def __isub__(self,other):
122     """
123     shifts the point by -other
124     """
125     self.modifyBy(Translation(-numarray.array(other,_TYPE)))
126     return self
127    
128     def __imul__(self,other):
129     """
130     modifies object by applying L{Transformation} other. If other is not a L{Transformation} it will try convert it.
131     """
132     if isinstance(other,int) or isinstance(other,float):
133     trafo=Dilation(other)
134     elif isinstance(other,numarray.NumArray):
135     trafo=Translation(other)
136     elif isinstance(other,Transformation):
137     trafo=other
138     else:
139     raise TypeError, "cannot convert argument to Trnsformation class object."
140     self.modifyBy(trafo)
141     return self
142    
143     def __rmul__(self,other):
144     """
145     applies L{Transformation} other to object. If other is not a L{Transformation} it will try convert it.
146     """
147     if isinstance(other,int) or isinstance(other,float):
148     trafo=Dilation(other)
149     elif isinstance(other,numarray.NumArray):
150     trafo=Translation(other)
151     elif isinstance(other,Transformation):
152     trafo=other
153     else:
154 gross 916 raise TypeError, "cannot convert argument to Transformation class object."
155 gross 915 return self.apply(trafo)
156    
157    
158 gross 916 def setLocalScale(self,factor=1.):
159     """
160     sets the local refinement factor
161     """
162     for p in self.getConstructionPoints(): p.setLocalScale(factor)
163    
164     def apply(self,transformation):
165     """
166 gross 928 returns a new object by applying the transformation
167 gross 916 """
168 gross 925 out=self.copy()
169     out.modifyBy(transformation)
170     return out
171 gross 916
172 gross 929 class Primitive(object):
173     """
174     A general primitive
175     """
176     def __init__(self):
177     """
178     initializes PrimitiveBase instance object with id
179     """
180     global global_primitive_id_counter
181     self.__ID=global_primitive_id_counter
182     global_primitive_id_counter+=1
183    
184     def getID(self):
185     """
186     returns the primitive ID
187     """
188     return self.__ID
189    
190     def getDirectedID(self):
191 gross 928 """
192 gross 929 returns the primitive ID where a negative signs means that the reversed ordring is used.
193     """
194     return self.getID()
195    
196     def __repr__(self):
197     return "%s(%s)"%(self.__class__.__name__,self.getID())
198    
199     def getUnderlyingPrimitive(self):
200     """
201     returns the underlying primitive
202     """
203     return self
204 gross 930 def hasSameOrientation(self,other):
205     """
206     returns True if other is the same primitive and has the same orientation
207     """
208     return self == other and isinstance(other,Primitive)
209 gross 929
210     def __neg__(self):
211     """
212     returns a view onto the curve with reversed ordering
213    
214 gross 928 @note: this class is overwritten by subclass
215     """
216 gross 929 raise NotImplementedError("__neg__ is not implemented.")
217 gross 928
218     def getGmshCommand(self, local_scaling_factor=1.):
219     """
220     returns the Gmsh command(s) to create the primitive
221    
222     @note: this class is overwritten by subclass
223     """
224 gross 929 raise NotImplementedError("getGmshCommand is not implemented.")
225 gross 928
226 gross 925 def substitute(self,sub_dict):
227     """
228     returns a copy of self with substitutes for the primitives used to construct it given by the dictionary C{sub_dict}.
229     If a substitute for the object is given by C{sub_dict} the value is returned, otherwise a new instance
230     with substituted arguments is returned.
231 gross 928
232     @note: this class is overwritten by subclass
233 gross 925 """
234 gross 929 raise NotImplementedError("substitute is not implemented.")
235 gross 925
236 gross 929 def collectPrimitiveBases(self):
237 gross 928 """
238 gross 929 returns a list of primitives used to construct the primitive. It may contain primitives twice
239    
240     @note: this class is overwritten by subclass
241 gross 928 """
242 gross 929 raise NotImplementedError("collectPrimitiveBases is not implemented.")
243 gross 928
244 gross 929 def isColocated(self,primitive):
245     """
246     returns True is the two primitives are located at the smae position
247    
248     @note: this class is overwritten by subclass
249     """
250     raise NotImplementedError("isColocated is not implemented.")
251    
252    
253     class ReversePrimitive(object):
254 gross 928 """
255     A view onto a primitive creating an reverse orientation
256     """
257     def __init__(self,primitive):
258     """
259     instantiate a view onto primitve
260     """
261 gross 929 if not isinstance(primitive, Primitive):
262     raise ValueError("argument needs to be a Primitive class object.")
263 gross 928 self.__primitive=primitive
264    
265 gross 929 def getID(self):
266     """
267     returns the primitive ID
268     """
269     return self.__primitive.getID()
270    
271 gross 928 def getUnderlyingPrimitive(self):
272     """
273     returns the underlying primitive
274     """
275     return self.__primitive
276    
277 gross 930 def hasSameOrientation(self,other):
278     """
279     returns True if other is the same primitive and has the same orientation
280     """
281     return self == other and isinstance(other,ReversePrimitive)
282    
283 gross 929 def __repr__(self):
284     return "-%s(%s)"%(self.__primitive.__class__.__name__,self.getID())
285    
286     def getDirectedID(self):
287 gross 928 """
288 gross 929 returns the primitive ID where a negative signs means that the reversed ordring is used.
289 gross 928 """
290 gross 929 return -self.__primitive.getID()
291 gross 928
292 gross 929 def substitute(self,sub_dict):
293     """
294     returns a copy of self with substitutes for the primitives used to construct it given by the dictionary C{sub_dict}.
295     If a substitute for the object is given by C{sub_dict} the value is returned, otherwise a new instance
296     with substituted arguments is returned.
297     """
298     if not sub_dict.has_key(self):
299     sub_dict[self]=-self.getUnderlyingPrimitive().substitute(sub_dict)
300     return sub_dict[self]
301    
302     def __neg__(self):
303     """
304     returns a view onto the curve with reversed ordering
305     """
306     return self.__primitive
307    
308     def getGmshCommand(self, local_scaling_factor=1.):
309     """
310     returns the Gmsh command(s) to create the primitive
311     """
312     return self.__primitive.getGmshCommand(local_scaling_factor)
313    
314     def collectPrimitiveBases(self):
315     """
316     returns a list of primitives used to construct the primitive. It may contain primitives twice
317     """
318     return self.__primitive.collectPrimitiveBases()
319    
320     def isColocated(self,primitive):
321     """
322     returns True is the two primitives are located at the smae position
323    
324     @note: this class is overwritten by subclass
325     """
326     return self.__primitive.isColocated(primitive)
327    
328     class Point(Primitive, PrimitiveBase):
329 gross 898 """
330     a three dimensional point
331     """
332     def __init__(self,x=0.,y=0.,z=0.,local_scale=1.):
333     """
334 gross 912 creates a point with coorinates x,y,z with the local refinement factor local_scale
335 gross 898 """
336 gross 929 PrimitiveBase.__init__(self)
337 gross 928 Primitive.__init__(self)
338 gross 915 self.setCoordinates(numarray.array([x,y,z],_TYPE))
339 gross 899 self.setLocalScale(local_scale)
340 gross 915
341 gross 898 def setLocalScale(self,factor=1.):
342 gross 902 """
343 gross 912 sets the local refinement factor
344 gross 902 """
345 gross 912 if factor<=0.:
346     raise ValueError("scaling factor must be positive.")
347 gross 898 self.__local_scale=factor
348 gross 929
349 gross 902 def getLocalScale(self):
350 gross 912 """
351     returns the local refinement factor
352     """
353 gross 902 return self.__local_scale
354 gross 912 def getCoordinates(self):
355     """
356     returns the coodinates of the point as L{numarray.NumArray} object
357     """
358     return self._x
359 gross 915 def setCoordinates(self,x):
360 gross 912 """
361     returns the coodinates of the point as L{numarray.NumArray} object
362     """
363 gross 915 if not isinstance(x, numarray.NumArray):
364     self._x=numarray.array(x,_TYPE)
365     else:
366     self._x=x
367    
368 gross 929 def collectPrimitiveBases(self):
369 gross 912 """
370 gross 916 returns primitives used to construct the primitive
371 gross 912 """
372 gross 916 return [self]
373 gross 912
374 gross 916 def isColocated(self,primitive):
375 gross 912 """
376 gross 916 returns True if L{Point} primitive is colocation (same coordinates)
377     that means if |self-primitive| <= tol * max(|self|,|primitive|)
378 gross 912 """
379 gross 916 if isinstance(primitive,Point):
380     primitive=primitive.getCoordinates()
381     c=self.getCoordinates()
382     d=c-primitive
383     return numarray.dot(d,d)<=getToleranceForColocation()**2*max(numarray.dot(c,c),numarray.dot(primitive,primitive))
384     else:
385     return False
386 gross 912
387 gross 925 def substitute(self,sub_dict):
388     """
389     returns a copy of self with substitutes for the primitives used to construct it given by the dictionary C{sub_dict}.
390     If a substitute for the object is given by C{sub_dict} the value is returned, otherwise a new instance
391     with substituted arguments is returned.
392     """
393     if not sub_dict.has_key(self):
394     c=self.getCoordinates()
395     sub_dict[self]=Point(c[0],c[1],c[2],local_scale=self.getLocalScale())
396     return sub_dict[self]
397 gross 915
398     def modifyBy(self,transformation):
399     """
400     modifies the coordinates by applying a transformation
401     """
402     self.setCoordinates(transformation(self.getCoordinates()))
403    
404    
405     def getGmshCommand(self, local_scaling_factor=1.):
406 gross 916 """
407     returns the Gmsh command(s) to create the primitive
408     """
409 gross 899 c=self.getCoordinates()
410 gross 915 return "Point(%s) = {%s , %s, %s , %s };"%(self.getID(),c[0],c[1],c[2], self.getLocalScale()*local_scaling_factor)
411 gross 898
412 gross 928 def __neg__(self):
413     """
414     returns a view of the object with reverse orientiention. As a point has no direction the object itself is returned.
415     """
416     return self
417    
418     class Manifold1D(PrimitiveBase):
419 gross 916 """
420 gross 928 general one-dimensional minifold in 3D defined by a start and end point.
421 gross 916 """
422 gross 928 def __init__(self):
423     """
424     create a one-dimensional manifold
425     """
426 gross 929 PrimitiveBase.__init__(self)
427 gross 928
428     def getStartPoint(self):
429     """
430     returns start point
431     """
432     raise NotImplementedError()
433    
434     def getEndPoint(self):
435     """
436     returns end point
437     """
438     raise NotImplementedError()
439 gross 931 def getBoundary(self):
440     """
441     returns a list of the zero-dimensional manifolds forming the boundary of the curve
442     """
443     return [ self.getStartPoint(), self.getEndPoint()]
444 gross 928
445     class CurveBase(Manifold1D):
446 gross 929 """
447     A Curve is defined by a set of control points
448     """
449 gross 928 def __init__(self):
450 gross 916 """
451 gross 929 create curve
452 gross 916 """
453 gross 928 Manifold1D.__init__(self)
454 gross 916
455     def __len__(self):
456     """
457     returns the number of control points
458     """
459 gross 928 return len(self.getControlPoints())
460 gross 916
461     def getStartPoint(self):
462 gross 898 """
463     returns start point
464     """
465 gross 929 return self.getControlPoints()[0]
466 gross 898
467 gross 916 def getEndPoint(self):
468 gross 898 """
469     returns end point
470     """
471 gross 929 return self.getControlPoints()[-1]
472 gross 898
473 gross 929 def getControlPoints(self):
474     """
475     returns a list of the points
476     """
477     raise NotImplementedError()
478    
479     class Curve(CurveBase, Primitive):
480     """
481     a curve defined through a list of control points.
482     """
483     def __init__(self,*points):
484 gross 916 """
485 gross 929 defines a curve form control points
486 gross 916 """
487 gross 929 if len(points)<2:
488 gross 931 raise ValueError("Curve needs at least two points")
489 gross 929 i=0
490     for p in points:
491     i+=1
492     if not isinstance(p,Point): raise TypeError("%s-th argument is not a Point object."%i)
493     self.__points=points
494     CurveBase.__init__(self)
495     Primitive.__init__(self)
496 gross 916
497 gross 929 def getControlPoints(self):
498     """
499     returns a list of the points
500     """
501     return self.__points
502    
503     def __neg__(self):
504     """
505     returns a view onto the curve with reversed ordering
506     """
507     return ReverseCurve(self)
508    
509 gross 925 def substitute(self,sub_dict):
510 gross 916 """
511 gross 925 returns a copy of self with substitutes for the primitives used to construct it given by the dictionary C{sub_dict}.
512     If a substitute for the object is given by C{sub_dict} the value is returned, otherwise a new instance
513     with substituted arguments is returned.
514 gross 916 """
515 gross 925 if not sub_dict.has_key(self):
516     new_p=[]
517     for p in self.getControlPoints(): new_p.append(p.substitute(sub_dict))
518 gross 929 sub_dict[self]=self.__class__(*tuple(new_p))
519 gross 925 return sub_dict[self]
520 gross 916
521 gross 929 def collectPrimitiveBases(self):
522     """
523     returns primitives used to construct the Curve
524     """
525     out=[self]
526     for p in self.getControlPoints(): out+=p.collectPrimitiveBases()
527     return out
528    
529 gross 916 def isColocated(self,primitive):
530     """
531     returns True curves are on the same position
532     """
533 gross 930 if hasattr(primitive,"getUnderlyingPrimitive"):
534     if isinstance(primitive.getUnderlyingPrimitive(),self.__class__):
535     if len(primitive) == len(self):
536 gross 916 cp0=self.getControlPoints()
537     cp1=primitive.getControlPoints()
538 gross 919 match=True
539 gross 916 for i in range(len(cp0)):
540     if not cp0[i].isColocated(cp1[i]):
541 gross 919 match=False
542     break
543     if not match:
544     for i in range(len(cp0)):
545     if not cp0[i].isColocated(cp1[len(cp0)-1-i]):
546     return False
547 gross 916 return True
548 gross 930 return False
549 gross 916
550 gross 929 class ReverseCurve(CurveBase, ReversePrimitive):
551 gross 928 """
552     a curve defined through a list of control points.
553     """
554     def __init__(self,curve):
555     """
556     defines a curve form control points
557     """
558 gross 929 if not isinstance(curve, Curve):
559     raise TypeError("ReverseCurve needs to be an instance of Curve")
560 gross 928 CurveBase.__init__(self)
561 gross 929 ReversePrimitive.__init__(self,curve)
562 gross 928
563     def getControlPoints(self):
564     """
565     returns a list of the points
566     """
567 gross 929 out=[p for p in self.getUnderlyingPrimitive().getControlPoints()]
568 gross 928 out.reverse()
569     return out
570    
571 gross 916 class Spline(Curve):
572     """
573     a spline curve defined through a list of control points.
574     """
575 gross 929 def getGmshCommand(self,scaling_factor=1.):
576 gross 916 """
577     returns the Gmsh command(s) to create the Curve
578     """
579 gross 899 out=""
580 gross 916 for i in self.getControlPoints():
581 gross 899 if len(out)>0:
582 gross 929 out+=", %s"%i.getDirectedID()
583 gross 899 else:
584 gross 929 out="%s"%i.getDirectedID()
585 gross 899 return "Spline(%s) = {%s};"%(self.getID(),out)
586 gross 916
587 gross 898
588     class BezierCurve(Curve):
589     """
590     a Bezier curve
591     """
592 gross 929 def getGmshCommand(self,scaling_factor=1.):
593 gross 916 """
594     returns the Gmsh command(s) to create the Curve
595     """
596 gross 899 out=""
597 gross 916 for i in self.getControlPoints():
598 gross 899 if len(out)>0:
599 gross 929 out+=", %s"%i.getDirectedID()
600 gross 899 else:
601 gross 929 out="%s"%i.getDirectedID()
602 gross 899 return "Bezier(%s) = {%s};"%(self.getID(),out)
603 gross 898
604 gross 916 class BSpline(Curve):
605 gross 898 """
606     a BSpline curve. Control points may be repeated.
607     """
608 gross 929 def getGmshCommand(self,scaling_factor=1.):
609 gross 916 """
610     returns the Gmsh command(s) to create the Curve
611     """
612 gross 899 out=""
613 gross 916 for i in self.getControlPoints():
614 gross 899 if len(out)>0:
615 gross 929 out+=", %s"%i.getDirectedID()
616 gross 899 else:
617 gross 929 out="%s"%i.getDirectedID()
618 gross 899 return "BSpline(%s) = {%s};"%(self.getID(),out)
619 gross 898
620     class Line(Curve):
621     """
622 gross 929 a line is defined by two pointDirecteds
623 gross 898 """
624 gross 916 def __init__(self,*points):
625 gross 899 """
626 gross 916 defines a line with start and end point
627 gross 899 """
628 gross 916 if len(points)!=2:
629     raise TypeError("Line needs two points")
630 gross 929 Curve.__init__(self,*points)
631     def getGmshCommand(self,scaling_factor=1.):
632 gross 916 """
633     returns the Gmsh command(s) to create the Curve
634     """
635 gross 929 return "Line(%s) = {%s, %s};"%(self.getID(),self.getStartPoint().getDirectedID(),self.getEndPoint().getDirectedID())
636 gross 898
637 gross 916
638 gross 928 class ArcBase(Manifold1D):
639 gross 929 def __init__(self):
640     """
641     create curve
642     """
643     Manifold1D.__init__(self)
644     def collectPrimitiveBases(self):
645 gross 928 """
646     returns the primitives used to construct the Curve
647     """
648     out=[self]
649 gross 929 out+=self.getStartPoint().collectPrimitiveBases()
650     out+=self.getEndPoint().collectPrimitiveBases()
651     out+=self.getCenterPoint().collectPrimitiveBases()
652 gross 928 return out
653    
654    
655 gross 929 def getCenterPoint(self):
656     """
657     returns center
658     """
659     raise NotImplementedError()
660 gross 928
661 gross 929 class Arc(ArcBase, Primitive):
662 gross 898 """
663 gross 917 defines an arc which is strictly, smaller than Pi
664 gross 898 """
665     def __init__(self,center,start,end):
666     """
667     creates an arc by the start point, end point and center
668     """
669 gross 917 if not isinstance(center,Point): raise TypeError("center needs to be a Point object.")
670     if not isinstance(end,Point): raise TypeError("end needs to be a Point object.")
671     if not isinstance(start,Point): raise TypeError("start needs to be a Point object.")
672     # TODO: check length of circle.
673 gross 928 ArcBase.__init__(self)
674 gross 929 Primitive.__init__(self)
675 gross 898 self.__center=center
676 gross 916 self.__start=start
677     self.__end=end
678 gross 928 def __neg__(self):
679 gross 929 """
680     returns a view onto the curve with reversed ordering
681     """
682     return ReverseArc(self)
683 gross 898
684 gross 916 def getStartPoint(self):
685 gross 898 """
686 gross 916 returns start point
687     """
688     return self.__start
689    
690     def getEndPoint(self):
691     """
692     returns end point
693     """
694     return self.__end
695    
696     def getCenterPoint(self):
697     """
698 gross 898 returns center
699     """
700     return self.__center
701    
702 gross 929 def substitute(self,sub_dict):
703     """
704     returns a copy of self with substitutes for the primitives used to construct it given by the dictionary C{sub_dict}.
705     If a substitute for the object is given by C{sub_dict} the value is returned, otherwise a new instance
706     with substituted arguments is returned.
707     """
708     if not sub_dict.has_key(self):
709     sub_dict[self]=Arc(self.getCenterPoint().substitute(sub_dict),self.getStartPoint().substitute(sub_dict),self.getEndPoint().substitute(sub_dict))
710     return sub_dict[self]
711    
712     def getGmshCommand(self,scaling_factor=1.):
713     """
714     returns the Gmsh command(s) to create the primitive
715     """
716     return "Circle(%s) = {%s, %s, %s};"%(self.getID(),self.getStartPoint().getDirectedID(),self.getCenterPoint().getDirectedID(),self.getEndPoint().getDirectedID())
717    
718     def isColocated(self,primitive):
719     """
720     returns True curves are on the same position
721     """
722 gross 930 if hasattr(primitive,"getUnderlyingPrimitive"):
723     if isinstance(primitive.getUnderlyingPrimitive(),Arc):
724 gross 929 return (self.getCenterPoint().isColocated(primitive.getCenterPoint())) and ( \
725     (self.getEndPoint().isColocated(primitive.getEndPoint()) and self.getStartPoint().isColocated(primitive.getStartPoint()) ) \
726     or (self.getEndPoint().isColocated(primitive.getStartPoint()) and self.getStartPoint().isColocated(primitive.getEndPoint()) ) )
727 gross 930 return False
728 gross 929
729     class ReverseArc(ArcBase, ReversePrimitive):
730 gross 928 """
731     defines an arc which is strictly, smaller than Pi
732     """
733     def __init__(self,arc):
734 gross 916 """
735 gross 928 creates an arc by the start point, end point and center
736 gross 916 """
737 gross 929 if not isinstance(arc, Arc):
738     raise TypeError("ReverseCurve needs to be an instance of Arc")
739 gross 928 ArcBase.__init__(self)
740 gross 929 ReversePrimitive.__init__(self,arc)
741 gross 916
742 gross 928 def getStartPoint(self):
743 gross 916 """
744 gross 928 returns start point
745 gross 916 """
746 gross 929 return self.getUnderlyingPrimitive().getEndPoint()
747 gross 899
748 gross 928 def getEndPoint(self):
749     """
750     returns end point
751     """
752 gross 929 return self.getUnderlyingPrimitive().getStartPoint()
753 gross 916
754 gross 928 def getCenterPoint(self):
755 gross 916 """
756 gross 928 returns center
757 gross 916 """
758 gross 929 return self.getUnderlyingPrimitive().getCenterPoint()
759 gross 916
760 gross 929 class CurveLoop(Primitive, PrimitiveBase):
761 gross 898 """
762 gross 930 An oriented loop of one-dimensional manifolds (= curves and arcs)
763 gross 898
764 gross 928 The loop must be closed and the L{Manifold1D}s should be oriented consistently.
765 gross 898 """
766     def __init__(self,*curves):
767     """
768     creates a polygon from a list of line curves. The curves must form a closed loop.
769     """
770 gross 923 if len(curves)<2:
771 gross 931 raise ValueError("at least two curves have to be given.")
772 gross 899 for i in range(len(curves)):
773 gross 928 if not isinstance(curves[i],Manifold1D):
774     raise TypeError("%s-th argument is not a Manifold1D object."%i)
775 gross 923 # for the curves a loop:
776     used=[ False for i in curves]
777 gross 932 self.__curves=list(curves)
778 gross 930 Primitive.__init__(self)
779     PrimitiveBase.__init__(self)
780 gross 898
781     def getCurves(self):
782 gross 919 """
783     returns the curves defining the CurveLoop
784     """
785 gross 898 return self.__curves
786 gross 925
787 gross 929 def __neg__(self):
788     """
789     returns a view onto the curve with reversed ordering
790     """
791     return ReverseCurveLoop(self)
792    
793 gross 898 def __len__(self):
794 gross 919 """
795     return the number of curves in the CurveLoop
796     """
797 gross 928 return len(self.getCurves())
798 gross 919
799 gross 929
800     def collectPrimitiveBases(self):
801 gross 919 """
802     returns primitives used to construct the CurveLoop
803     """
804 gross 928 out=[self]
805 gross 929 for c in self.getCurves(): out+=c.collectPrimitiveBases()
806 gross 928 return out
807 gross 919
808 gross 925 def substitute(self,sub_dict):
809 gross 919 """
810 gross 925 returns a copy of self with substitutes for the primitives used to construct it given by the dictionary C{sub_dict}.
811     If a substitute for the object is given by C{sub_dict} the value is returned, otherwise a new instance
812     with substituted arguments is returned.
813 gross 919 """
814 gross 925 if not sub_dict.has_key(self):
815     new_c=[]
816     for c in self.getCurves(): new_c.append(c.substitute(sub_dict))
817     sub_dict[self]=CurveLoop(*tuple(new_c))
818     return sub_dict[self]
819 gross 919
820     def isColocated(self,primitive):
821     """
822     returns True if each curve is collocted with a curve in primitive
823     """
824 gross 930 if hasattr(primitive,"getUnderlyingPrimitive"):
825     if isinstance(primitive.getUnderlyingPrimitive(),CurveLoop):
826     if len(primitive) == len(self):
827     cp0=self.getCurves()
828     cp1=primitive.getCurves()
829     for c0 in cp0:
830     collocated = False
831     for c1 in cp1:
832     collocated = collocated or c0.isColocated(c1)
833     if not collocated: return False
834     return True
835     return False
836 gross 919
837 gross 929 def getGmshCommand(self,scaling_factor=1.):
838 gross 928 """
839     returns the Gmsh command(s) to create the primitive
840     """
841 gross 899 out=""
842     for i in self.getCurves():
843     if len(out)>0:
844 gross 929 out+=", %s"%i.getDirectedID()
845 gross 899 else:
846 gross 929 out="%s"%i.getDirectedID()
847 gross 899 return "Line Loop(%s) = {%s};"%(self.getID(),out)
848 gross 898
849 gross 929 class ReverseCurveLoop(ReversePrimitive, PrimitiveBase):
850 gross 898 """
851 gross 930 An oriented loop of one-dimensional manifolds (= curves and arcs)
852 gross 929
853 gross 930 The loop must be closed and the one-dimensional manifolds should be oriented consistently.
854 gross 929 """
855     def __init__(self,curve_loop):
856     """
857     creates a polygon from a list of line curves. The curves must form a closed loop.
858     """
859     if not isinstance(curve_loop, CurveLoop):
860 gross 931 raise TypeError("arguments need to be an instance of CurveLoop.")
861 gross 929 ReversePrimitive.__init__(self, curve_loop)
862     PrimitiveBase.__init__(self)
863    
864     def getCurves(self):
865     """
866     returns the curves defining the CurveLoop
867     """
868     return [ -c for c in self.getUnderlyingPrimitive().getCurves() ]
869    
870     def __len__(self):
871     return len(self.getUnderlyingPrimitive())
872    
873 gross 930 #=
874     class Manifold2D(PrimitiveBase):
875 gross 929 """
876 gross 930 general two-dimensional manifold
877 gross 898 """
878 gross 928 def __init__(self):
879     """
880 gross 930 create a two-dimensional manifold
881 gross 928 """
882 gross 930 PrimitiveBase.__init__(self)
883 gross 928
884 gross 930 def getBoundary(self):
885 gross 928 """
886 gross 930 returns a list of the one-dimensional manifolds forming the boundary of the Surface (including holes)
887 gross 928 """
888 gross 930 raise NotImplementedError()
889 gross 928
890 gross 930 class RuledSurface(Primitive, Manifold2D):
891 gross 927 """
892     A ruled surface, i.e., a surface that can be interpolated using transfinite interpolation
893     """
894 gross 898 def __init__(self,loop):
895     """
896 gross 927 creates a ruled surface with boundary loop
897 gross 898
898 gross 927 @param loop: L{CurveLoop} defining the boundary of the surface.
899 gross 898 """
900 gross 930 if not isinstance(loop.getUnderlyingPrimitive(),CurveLoop):
901 gross 898 raise TypeError("argument loop needs to be a CurveLoop object.")
902 gross 927 if len(loop)<2:
903 gross 931 raise ValueError("the loop must contain at least two Curves.")
904 gross 927 if len(loop)>4:
905 gross 931 raise ValueError("the loop must contain at least three Curves.")
906 gross 930 Primitive.__init__(self)
907     Manifold2D.__init__(self)
908 gross 898 self.__loop=loop
909 gross 927
910 gross 930 def __neg__(self):
911     """
912     returns a view onto the suface with reversed ordering
913     """
914     return ReverseRuledSurface(self)
915    
916 gross 898 def getBoundaryLoop(self):
917 gross 927 """
918 gross 928 returns the loop defining the outer boundary
919 gross 927 """
920     return self.__loop
921    
922 gross 930 def getBoundary(self):
923 gross 928 """
924 gross 930 returns a list of the one-dimensional manifolds forming the boundary of the Surface (including holes)
925 gross 928 """
926 gross 930 return self.getBoundaryLoop().getCurves()
927 gross 927
928 gross 929 def getGmshCommand(self,scaling_factor=1.):
929 gross 928 """
930     returns the Gmsh command(s) to create the primitive
931     """
932 gross 929 return "Ruled Surface(%s) = {%s};"%(self.getID(),self.getBoundaryLoop().getDirectedID())
933 gross 899
934 gross 927 def substitute(self,sub_dict):
935     """
936     returns a copy of self with substitutes for the primitives used to construct it given by the dictionary C{sub_dict}.
937     If a substitute for the object is given by C{sub_dict} the value is returned, otherwise a new instance
938     with substituted arguments is returned.
939     """
940     if not sub_dict.has_key(self):
941 gross 928 sub_dict[self]=RuledSurface(self.getBoundaryLoop().substitute(sub_dict))
942 gross 927 return sub_dict[self]
943    
944     def isColocated(self,primitive):
945     """
946     returns True if each curve is collocted with a curve in primitive
947     """
948 gross 930 if hasattr(primitive,"getUnderlyingPrimitive"):
949     if isinstance(primitive.getUnderlyingPrimitive(),RuledSurface):
950     return self.getBoundaryLoop().isColocated(primitive.getBoundaryLoop())
951     return False
952 gross 927
953 gross 930 def collectPrimitiveBases(self):
954     """
955     returns primitives used to construct the Surface
956     """
957     return [self] + self.getBoundaryLoop().collectPrimitiveBases()
958    
959 gross 927 def createRuledSurface(*curves):
960     """
961     an easier way to create a L{RuledSurface} from given curves.
962     """
963     return RuledSurface(CurveLoop(*curves))
964    
965 gross 930
966     class ReverseRuledSurface(ReversePrimitive, Manifold2D):
967 gross 898 """
968 gross 930 creates a view onto a L{RuledSurface} but with the reverse orientation
969     """
970     def __init__(self,surface):
971     """
972     creates a polygon from a list of line curves. The curves must form a closed loop.
973     """
974     if not isinstance(surface, RuledSurface):
975 gross 931 raise TypeError("arguments need to be an instance of CurveLoop.")
976 gross 930 ReversePrimitive.__init__(self, surface)
977     Manifold2D.__init__(self)
978    
979     def getBoundaryLoop(self):
980     """
981     returns the CurveLoop defining the RuledSurface
982     """
983     return -self.getUnderlyingPrimitive().getBoundaryLoop()
984    
985     def getBoundary(self):
986     """
987     returns a list of the one-dimensional manifolds forming the boundary of the Surface (including holes)
988     """
989     return self.getBoundaryLoop().getCurves()
990     #==============================
991     class PlaneSurface(Primitive, Manifold2D):
992     """
993 gross 898 a plane surface with holes
994     """
995     def __init__(self,loop,holes=[]):
996     """
997 gross 927 creates a plane surface with a hole
998 gross 898
999     @param loop: L{CurveLoop} defining the boundary of the surface
1000     @param holes: list of L{CurveLoop} defining holes in the surface.
1001     @note: A CurveLoop defining a hole should not have any lines in common with the exterior CurveLoop.
1002     A CurveLoop defining a hole should not have any lines in common with another CurveLoop defining a hole in the same surface.
1003     """
1004 gross 930 if not isinstance(loop.getUnderlyingPrimitive(),CurveLoop):
1005 gross 927 raise TypeError("argument loop needs to be a CurveLoop object.")
1006 gross 928 for l in loop.getCurves():
1007 gross 930 if not isinstance(l.getUnderlyingPrimitive(),Line):
1008 gross 928 raise TypeError("loop may be formed by Lines only.")
1009 gross 898 for i in range(len(holes)):
1010 gross 930 if not isinstance(holes[i].getUnderlyingPrimitive(), CurveLoop):
1011 gross 928 raise TypeError("%i-th hole needs to be a CurveLoop object.")
1012     for l in holes[i].getCurves():
1013 gross 930 if not isinstance(l.getUnderlyingPrimitive(),Line):
1014 gross 928 raise TypeError("holes may be formed by Lines only.")
1015     #TODO: check if lines and holes are in a plane
1016     #TODO: are holes really holes?
1017 gross 930 Primitive.__init__(self)
1018     Manifold2D.__init__(self)
1019 gross 928 self.__loop=loop
1020 gross 898 self.__holes=holes
1021     def getHoles(self):
1022 gross 927 """
1023     returns the holes
1024     """
1025 gross 898 return self.__holes
1026 gross 930
1027 gross 927 def getBoundaryLoop(self):
1028     """
1029     returns the loop defining the boundary
1030     """
1031     return self.__loop
1032    
1033 gross 929 def getGmshCommand(self,scaling_factor=1.):
1034 gross 928 """
1035     returns the Gmsh command(s) to create the primitive
1036     """
1037 gross 899 out=""
1038     for i in self.getHoles():
1039     if len(out)>0:
1040 gross 929 out+=", %s"%i.getDirectedID()
1041 gross 899 else:
1042 gross 929 out="%s"%i.getDirectedID()
1043 gross 899 if len(out)>0:
1044 gross 929 return "Plane Surface(%s) = {%s, %s};"%(self.getID(),self.getBoundaryLoop().getDirectedID(), out)
1045 gross 899 else:
1046 gross 929 return "Plane Surface(%s) = {%s};"%(self.getID(),self.getBoundaryLoop().getDirectedID())
1047 gross 898
1048 gross 927 def substitute(self,sub_dict):
1049     """
1050     returns a copy of self with substitutes for the primitives used to construct it given by the dictionary C{sub_dict}.
1051     If a substitute for the object is given by C{sub_dict} the value is returned, otherwise a new instance
1052     with substituted arguments is returned.
1053     """
1054     if not sub_dict.has_key(self):
1055 gross 928 sub_dict[self]=PlaneSurface(self.getBoundaryLoop().substitute(sub_dict),[ h.substitute(sub_dict) for h in self.getHoles()])
1056 gross 927 return sub_dict[self]
1057 gross 898
1058 gross 927 def isColocated(self,primitive):
1059 gross 898 """
1060 gross 927 returns True if each curve is collocted with a curve in primitive
1061     """
1062 gross 930 if hasattr(primitive,"getUnderlyingPrimitive"):
1063     if isinstance(primitive.getUnderlyingPrimitive(),PlaneSurface):
1064     if self.getBoundaryLoop().isColocated(primitive.getBoundaryLoop()):
1065     hs0=self.getHoles()
1066     hs1=primitive.getHoles()
1067     if len(hs0) == len(hs1):
1068     for h0 in hs0:
1069     collocated = False
1070     for h1 in hs1:
1071     collocated = collocated or h0.isColocated(h1)
1072     if not collocated: return False
1073     return True
1074     return False
1075     def collectPrimitiveBases(self):
1076     """
1077     returns primitives used to construct the Surface
1078     """
1079     out=[self] + self.getBoundaryLoop().collectPrimitiveBases()
1080     for i in self.getHoles(): out+=i.collectPrimitiveBases()
1081     return out
1082     def __neg__(self):
1083     """
1084     returns a view onto the curve with reversed ordering
1085     """
1086     return ReversePlaneSurface(self)
1087     def getBoundary(self):
1088     """
1089     returns a list of the one-dimensional manifolds forming the boundary of the Surface (including holes)
1090     """
1091     out = []+ self.getBoundaryLoop().getCurves()
1092     for h in self.getHoles(): out+=h.getCurves()
1093     return out
1094 gross 898
1095 gross 930 class ReversePlaneSurface(ReversePrimitive, Manifold2D):
1096 gross 898 """
1097 gross 930 creates a view onto a L{PlaneSurface} but with the reverse orientation
1098     """
1099     def __init__(self,surface):
1100     """
1101     creates a polygon from a list of line curves. The curves must form a closed loop.
1102     """
1103     if not isinstance(surface, PlaneSurface):
1104 gross 931 raise TypeError("arguments need to be an instance of PlaneSurface.")
1105 gross 930 ReversePrimitive.__init__(self, surface)
1106     Manifold2D.__init__(self)
1107    
1108     def getBoundaryLoop(self):
1109     """
1110     returns the CurveLoop defining the RuledSurface
1111     """
1112     return -self.getUnderlyingPrimitive().getBoundaryLoop()
1113    
1114     def getHoles(self):
1115     """
1116     returns a list of the one-dimensional manifolds forming the boundary of the Surface (including holes)
1117     """
1118     return [ -h for h in self.getUnderlyingPrimitive().getHoles() ]
1119    
1120     def getBoundary(self):
1121     """
1122     returns a list of the one-dimensional manifolds forming the boundary of the Surface (including holes)
1123     """
1124     out = [] + self.getBoundaryLoop().getCurves()
1125     for h in self.getHoles(): out+=h.getCurves()
1126     return out
1127    
1128    
1129     #=========================================================================
1130     class SurfaceLoop(Primitive, PrimitiveBase):
1131     """
1132 gross 928 a loop of 2D primitives. It defines the shell of a volume.
1133 gross 898
1134 gross 928 The loop must represent a closed shell, and the primitives should be oriented consistently.
1135 gross 898 """
1136     def __init__(self,*surfaces):
1137     """
1138     creates a surface loop
1139     """
1140 gross 928 if len(surfaces)<2:
1141 gross 931 raise ValueError("at least two surfaces have to be given.")
1142 gross 899 for i in range(len(surfaces)):
1143 gross 930 if not isinstance(surfaces[i].getUnderlyingPrimitive(),Manifold2D):
1144     raise TypeError("%s-th argument is not a Manifold2D object."%i)
1145 gross 932 self.__surfaces=list(surfaces)
1146 gross 930 Primitive.__init__(self)
1147     PrimitiveBase.__init__(self)
1148 gross 928 def __len__(self):
1149     """
1150     return the number of curves in the SurfaceLoop
1151     """
1152     return len(self.__surfaces)
1153 gross 898
1154 gross 930 def __neg__(self):
1155     """
1156     returns a view onto the curve with reversed ordering
1157     """
1158     return ReverseSurfaceLoop(self)
1159    
1160 gross 898 def getSurfaces(self):
1161 gross 928 """
1162     returns the surfaces defining the SurfaceLoop
1163     """
1164 gross 930 return self.__surfaces
1165 gross 928
1166 gross 929 def collectPrimitiveBases(self):
1167 gross 928 """
1168     returns primitives used to construct the SurfaceLoop
1169     """
1170     out=[self]
1171 gross 929 for c in self.getSurfaces(): out+=c.collectPrimitiveBases()
1172 gross 928 return out
1173 gross 930
1174 gross 929 def getGmshCommand(self,scaling_factor=1.):
1175 gross 928 """
1176     returns the Gmsh command(s) to create the primitive
1177     """
1178 gross 899 out=""
1179     for i in self.getSurfaces():
1180     if len(out)>0:
1181 gross 929 out+=", %s"%i.getDirectedID()
1182 gross 899 else:
1183 gross 929 out="%s"%i.getDirectedID()
1184 gross 899 return "Surface Loop(%s) = {%s};"%(self.getID(),out)
1185 gross 931
1186 gross 928 def substitute(self,sub_dict):
1187     """
1188     returns a copy of self with substitutes for the primitives used to construct it given by the dictionary C{sub_dict}.
1189     If a substitute for the object is given by C{sub_dict} the value is returned, otherwise a new instance
1190     with substituted arguments is returned.
1191     """
1192     if not sub_dict.has_key(self):
1193     new_s=[]
1194 gross 931 for s in self.getSurfaces(): new_s.append(s.substitute(sub_dict))
1195 gross 928 sub_dict[self]=SurfaceLoop(*tuple(new_s))
1196     return sub_dict[self]
1197 gross 898
1198 gross 928 def isColocated(self,primitive):
1199     """
1200     returns True if each surface is collocted with a curve in primitive and vice versa.
1201     """
1202 gross 930 if hasattr(primitive,"getUnderlyingPrimitive"):
1203     if isinstance(primitive.getUnderlyingPrimitive(),SurfaceLoop):
1204     if len(primitive) == len(self):
1205     sp0=self.getSurfaces()
1206 gross 931 sp1=primitive.getSurfaces()
1207 gross 930 for s0 in sp0:
1208     collocated = False
1209     for s1 in sp1:
1210     collocated = collocated or s0.isColocated(s1)
1211     if not collocated: return False
1212     return True
1213     return False
1214 gross 928
1215 gross 930 class ReverseSurfaceLoop(ReversePrimitive, PrimitiveBase):
1216     """
1217     a view to SurfaceLoop with reverse orientaion
1218    
1219     The loop must represent a closed shell, and the primitives should be oriented consistently.
1220     An oriented loop of 2-dimensional manifolds (= RuledSurface, PlaneSurface)
1221    
1222     The loop must be closed and the one-dimensional manifolds should be oriented consistently.
1223     """
1224     def __init__(self,surface_loop):
1225     """
1226     creates a polygon from a list of line surfaces. The curves must form a closed loop.
1227     """
1228     if not isinstance(surface_loop, SurfaceLoop):
1229 gross 931 raise TypeError("arguments need to be an instance of SurfaceLoop.")
1230 gross 930 ReversePrimitive.__init__(self, surface_loop)
1231     PrimitiveBase.__init__(self)
1232    
1233     def getSurfaces(self):
1234     """
1235     returns the surfaces defining the SurfaceLoop
1236     """
1237     return [ -s for s in self.getUnderlyingPrimitive().getSurfaces() ]
1238    
1239     def __len__(self):
1240     return len(self.getUnderlyingPrimitive())
1241 gross 931
1242     #==============================
1243     class Manifold3D(PrimitiveBase):
1244 gross 898 """
1245 gross 931 general three-dimensional manifold
1246     """
1247     def __init__(self):
1248     """
1249     create a three-dimensional manifold
1250     """
1251     PrimitiveBase.__init__(self)
1252    
1253     def getBoundary(self):
1254     """
1255     returns a list of the one-dimensional manifolds forming the boundary of the volume (including holes)
1256     """
1257     raise NotImplementedError()
1258    
1259     class Volume(Manifold3D, Primitive):
1260     """
1261 gross 898 a volume with holes.
1262     """
1263     def __init__(self,loop,holes=[]):
1264     """
1265     creates a volume
1266    
1267     @param loop: L{SurfaceLoop} defining the boundary of the surface
1268     @param holes: list of L{SurfaceLoop} defining holes in the surface.
1269     @note: A SurfaceLoop defining a hole should not have any surfaces in common with the exterior SurfaceLoop.
1270     A SurfaceLoop defining a hole should not have any surfaces in common with another SurfaceLoop defining a hole in the same volume.
1271     """
1272 gross 931 if not isinstance(loop.getUnderlyingPrimitive(), SurfaceLoop):
1273 gross 898 raise TypeError("argument loop needs to be a SurfaceLoop object.")
1274     for i in range(len(holes)):
1275 gross 931 if not isinstance(holes[i].getUnderlyingPrimitive(), SurfaceLoop):
1276 gross 898 raise TypeError("%i th hole needs to be a SurfaceLoop object.")
1277 gross 931 Primitive.__init__(self)
1278     Manifold3D.__init__(self)
1279 gross 898 self.__loop=loop
1280     self.__holes=holes
1281     def getHoles(self):
1282 gross 931 """
1283     returns the hole in the volume
1284     """
1285 gross 898 return self.__holes
1286     def getSurfaceLoop(self):
1287 gross 931 """
1288     returns the loop forming the surface
1289     """
1290 gross 898 return self.__loop
1291 gross 931
1292 gross 929 def getGmshCommand(self,scaling_factor=1.):
1293 gross 928 """
1294     returns the Gmsh command(s) to create the primitive
1295     """
1296 gross 899 out=""
1297     for i in self.getHoles():
1298     if len(out)>0:
1299 gross 929 out+=", %s"%i.getDirectedID()
1300 gross 899 else:
1301 gross 929 out="%s"%i.getDirectedID()
1302 gross 899 if len(out)>0:
1303 gross 929 return "Volume(%s) = {%s, %s};"%(self.getID(),self.getSurfaceLoop().getDirectedID(), out)
1304 gross 899 else:
1305 gross 929 return "Volume(%s) = {%s};"%(self.getID(),self.getSurfaceLoop().getDirectedID())
1306 gross 898
1307 gross 931 def substitute(self,sub_dict):
1308     """
1309     returns a copy of self with substitutes for the primitives used to construct it given by the dictionary C{sub_dict}.
1310     If a substitute for the object is given by C{sub_dict} the value is returned, otherwise a new instance
1311     with substituted arguments is returned.
1312     """
1313     if not sub_dict.has_key(self):
1314     sub_dict[self]=Volume(self.getSurfaceLoop().substitute(sub_dict),[ h.substitute(sub_dict) for h in self.getHoles()])
1315     return sub_dict[self]
1316    
1317     def isColocated(self,primitive):
1318     """
1319     returns True if each curve is collocted with a curve in primitive
1320     """
1321     if hasattr(primitive,"getUnderlyingPrimitive"):
1322     if isinstance(primitive.getUnderlyingPrimitive(),Volume):
1323     if self.getSurfaceLoop().isColocated(primitive.getSurfaceLoop()):
1324     hs0=self.getHoles()
1325     hs1=primitive.getHoles()
1326     if len(hs0) == len(hs1):
1327     for h0 in hs0:
1328     collocated = False
1329     for h1 in hs1:
1330     collocated = collocated or h0.isColocated(h1)
1331     if not collocated: return False
1332     return True
1333     return False
1334     def collectPrimitiveBases(self):
1335     """
1336     returns primitives used to construct the Surface
1337     """
1338     out=[self] + self.getSurfaceLoop().collectPrimitiveBases()
1339     for i in self.getHoles(): out+=i.collectPrimitiveBases()
1340     return out
1341     def getBoundary(self):
1342     """
1343     returns a list of the one-dimensional manifolds forming the boundary of the Surface (including holes)
1344     """
1345     out = []+ self.getSurfaceLoop().getSurfaces()
1346     for h in self.getHoles(): out+=h.getSurfaces()
1347     return out
1348    
1349 gross 944 class PropertySet(Primitive, PrimitiveBase):
1350 gross 898 """
1351 gross 944 defines a group L{Primitive} which can be accessed through a name
1352 gross 898 """
1353 gross 944 def __init__(self,name,*items):
1354     Primitive.__init__(self)
1355     if len(items)==0:
1356     raise ValueError("at least one item must be give.")
1357     if isinstance(items[0] ,Manifold1D):
1358     dim=1
1359     elif isinstance(items[0] ,Manifold2D):
1360     dim=2
1361     elif isinstance(items[0] ,Manifold3D):
1362     dim=3
1363     else:
1364     dim=0
1365     self.__dim=dim
1366     self.clearItems()
1367     self.addItem(*items)
1368     self.setName(name)
1369     def __repr__(self):
1370     """
1371     returns a string representation
1372     """
1373     return "%s(%s)"%(self.getName(),self.getID())
1374     def getManifoldClass(self):
1375     """
1376     returns the manifold class expected from items
1377     """
1378     d=self.getDim()
1379     if d==0:
1380     return Point
1381     elif d==1:
1382     return Manifold1D
1383     elif d==2:
1384     return Manifold2D
1385     else:
1386     return Manifold3D
1387     def getDim(self):
1388     """
1389     returns the dimension of the
1390     """
1391     return self.__dim
1392     def getName(self):
1393     """
1394     returns the name of the set
1395     """
1396     return self.__name
1397     def setName(self,name=None):
1398     """
1399     sets the name. If no name is given the id is used.
1400     """
1401     self.__name=str(name)
1402     def addItem(self,*items):
1403     """
1404     adds items. An item my be any L{Primitive} but no L{PropertySet}
1405     """
1406     m=self.getManifoldClass()
1407     for i in items:
1408     if not i in self.__items:
1409     if not isinstance(i, m):
1410     raise TypeError("argument %s is not a %s class object."%(i, m.__name__))
1411     self.__items.append(i)
1412     def getItems(self):
1413     """
1414     returns the list of items
1415     """
1416     return self.__items
1417    
1418     def clearItems(self):
1419     """
1420     clears the list of items
1421     """
1422     self.__items=[]
1423 gross 929 def collectPrimitiveBases(self):
1424 gross 944 """
1425     returns primitives used to construct the PropertySet
1426     """
1427     out=[self]
1428     for i in self.getItems(): out+=i.collectPrimitiveBases()
1429 gross 899 return out
1430 gross 944
1431     def getGmshCommand(self,scaling_factor=1.):
1432     """
1433     returns the Gmsh command(s) to create the primitive
1434     """
1435     k=self.getDim()
1436     out="Physical "
1437     if k==0:
1438     out+="Point"
1439     elif k==1:
1440     out+="Line"
1441     elif k==2:
1442     out+="Surface"
1443     else:
1444     out+="Volume"
1445     out2=""
1446     for i in self.getItems():
1447     if len(out2)>0:
1448     out2+=", %s"%i.getDirectedID()
1449     else:
1450     out2="%s"%i.getDirectedID()
1451     out+="(" + str(self.getID()) + ") = {"+out2+"};"
1452     return out
1453    
1454     def getTag(self):
1455     """
1456     returns the tag used for this
1457     """
1458     return self.getID()

  ViewVC Help
Powered by ViewVC 1.1.26