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

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

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

revision 927 by gross, Fri Jan 12 06:32:08 2007 UTC revision 928 by gross, Tue Jan 16 08:36:03 2007 UTC
# Line 52  def getToleranceForColocation(): Line 52  def getToleranceForColocation():
52  resetGlobalPrimitiveIdCounter()  resetGlobalPrimitiveIdCounter()
53  setToleranceForColocation()  setToleranceForColocation()
54    
55  class Primitive(object):  
56    class PrimitiveBase(object):
57      """      """
58      template for elementary geometrical object      template for elementary geometrical object
59      """      """
60      def __init__(self):      def __init__(self,id):
61         """         """
62                 initializes PrimitiveBase instance object with id
63         """         """
64         global global_primitive_id_counter         self.__ID=id
        self.__ID=global_primitive_id_counter  
        global_primitive_id_counter+=1  
65    
66      def getID(self):      def getID(self):
67           """
68           returns the primitive ID
69           """
70         return self.__ID         return self.__ID
71    
72      def __repr__(self):      def __repr__(self):
73         return "%s(%s)"%(self.__class__.__name__,self.getID())         return "%s(%s)"%(self.getClass().__name__,self.getID())
74    
75      def __cmp__(self,other):      def __cmp__(self,other):
76         return cmp(self.getID(),other.getID())         """
77           compares object with other by comparing the absolute value of the ID
78           """
79           if isinstance(self, PrimitiveBase):
80               return cmp(abs(self.getID()),abs(other.getID()))
81           else:
82               return False
83    
84      def getConstructionPoints(self):      def getConstructionPoints(self):
85          """          """
# Line 84  class Primitive(object): Line 92  class Primitive(object):
92    
93      def getPrimitives(self):      def getPrimitives(self):
94          """          """
95          returns primitives used to construct the primitive          returns a list of primitives used to construct the primitive with no double entries
96          """          """
97          return []          out=set()
98            for p in self.collectPrimitives():
99               if isintance(p,ReversePrimitive):
100                  out.add(-p)
101               elif isintance(p,Primitive):
102                  out.add(p)
103            return list(set(self.collectPrimitives()))
104    
105      def copy(self):      def copy(self):
106         """         """
# Line 94  class Primitive(object): Line 108  class Primitive(object):
108         """         """
109         return self.substitute({})         return self.substitute({})
110    
   
111      def modifyBy(self,transformation):      def modifyBy(self,transformation):
112         """         """
113         modifies the coordinates by applying a transformation         modifies the coordinates by applying a transformation
114         """         """
115         for p in self.getConstructionPoints(): p.modifyBy(transformation)         for p in self.getConstructionPoints(): p.modifyBy(transformation)
116    
   
117      def __add__(self,other):      def __add__(self,other):
118          """          """
119          returns a new object shifted by other          returns a new object shifted by other
# Line 157  class Primitive(object): Line 169  class Primitive(object):
169              raise TypeError, "cannot convert argument to Transformation class object."              raise TypeError, "cannot convert argument to Transformation class object."
170          return self.apply(trafo)          return self.apply(trafo)
171    
     def __neg__(self):  
         return ReversedPrimitive(self)  
172    
173      def setLocalScale(self,factor=1.):      def setLocalScale(self,factor=1.):
174         """         """
# Line 166  class Primitive(object): Line 176  class Primitive(object):
176         """         """
177         for p in self.getConstructionPoints(): p.setLocalScale(factor)         for p in self.getConstructionPoints(): p.setLocalScale(factor)
178    
179      def getGmshCommand(self, local_scaling_factor=1.):      def __neg__(self):
180          """          """
181          returns the Gmsh command(s) to create the primitive          returns a view of the object with reverse orientiention
182          """          """
183          raise NotImplementedError("getGmshCommand is not implemented for this class %s."%self.__class__.__name__)          if isinstance(self,ReversePrimitive):
184                return self.getUnderlyingPrimitive()
185            else:
186                return ReversedPrimitive(self)
187    
188      def apply(self,transformation):      def apply(self,transformation):
189          """          """
190          returns a new L{Point} by applying the transformation          returns a new object by applying the transformation
191          """          """
192          out=self.copy()          out=self.copy()
193          out.modifyBy(transformation)          out.modifyBy(transformation)
194          return out          return out
195    
196        def collectPrimitives(self):
197            """
198            returns a list of primitives used to construct the primitive. It may contain primitives twice
199            
200            @note: this class is overwritten by subclass
201            """
202            return [self]
203    
204        def getGmshCommand(self, local_scaling_factor=1.):
205            """
206            returns the Gmsh command(s) to create the primitive
207    
208            @note: this class is overwritten by subclass
209            """
210            raise NotImplementedError("getGmshCommand is not implemented for this class %s."%self.__class__.__name__)
211    
212      def isColocated(self,primitive):      def isColocated(self,primitive):
213         """         """
214         returns True is the two primitives are located at the smae position         returns True is the two primitives are located at the smae position
215    
216           @note: this class is overwritten by subclass
217         """         """
218         raise NotImplementedError("isColocated is not implemented for this class %s."%self.__class__.__name__)         raise NotImplementedError("isColocated is not implemented for this class %s."%self.__class__.__name__)
219    
# Line 191  class Primitive(object): Line 222  class Primitive(object):
222          returns a copy of self with substitutes for the primitives used to construct it given by the dictionary C{sub_dict}.          returns a copy of self with substitutes for the primitives used to construct it given by the dictionary C{sub_dict}.
223          If a substitute for the object is given by C{sub_dict} the value is returned, otherwise a new instance          If a substitute for the object is given by C{sub_dict} the value is returned, otherwise a new instance
224          with substituted arguments is returned.          with substituted arguments is returned.
225    
226            @note: this class is overwritten by subclass
227          """          """
228          if not sub_dict.has_key(self):          if not sub_dict.has_key(self):
229             sub_dict[self]=self.__class__()             sub_dict[self]=self.getClass()
230          return sub_dict[self]          return sub_dict[self]
231    
232    class Primitive(PrimitiveBase):
233        """
234        A general primitive
235        """
236        def __init__(self):
237           """
238           instantiate a primitve
239           """
240           global global_primitive_id_counter
241           self.__ID=global_primitive_id_counter
242           PrimitiveBase.__init__(self,global_primitive_id_counter)
243    
244        def getClass(self):
245            """
246            returns the class of the object
247            """
248            return self.__class__
249    
250    class ReversePrimitive(PrimitiveBase):
251        """
252        A view onto a primitive creating an reverse orientation
253        """
254        def __init__(self,primitive):
255           """
256           instantiate a view onto primitve
257           """
258           PrimitiveBase.__init__(self,-primitive.getID())
259           self.__primitive=primitive
260    
261        def getUnderlyingPrimitive(self):
262            """
263            returns the underlying primitive
264            """
265            return self.__primitive
266    
267        def getClass(self):
268            """
269            returns the class of the underlying object
270            """
271            return self.getUnderlyingPrimitive().__class__()
272    
273  class Point(Primitive):  class Point(Primitive):
274      """      """
275      a three dimensional point      a three dimensional point
# Line 204  class Point(Primitive): Line 278  class Point(Primitive):
278         """         """
279         creates a point with coorinates x,y,z with the local refinement factor local_scale         creates a point with coorinates x,y,z with the local refinement factor local_scale
280         """         """
281         super(Point, self).__init__()         Primitive.__init__(self)
282         self.setCoordinates(numarray.array([x,y,z],_TYPE))         self.setCoordinates(numarray.array([x,y,z],_TYPE))
283         self.setLocalScale(local_scale)         self.setLocalScale(local_scale)
284    
# Line 234  class Point(Primitive): Line 308  class Point(Primitive):
308         else:         else:
309            self._x=x            self._x=x
310    
311      def getPrimitives(self):      def collectPrimitives(self):
312         """         """
313         returns primitives used to construct the primitive         returns primitives used to construct the primitive
314         """         """
# Line 278  class Point(Primitive): Line 352  class Point(Primitive):
352          c=self.getCoordinates()          c=self.getCoordinates()
353          return "Point(%s) = {%s , %s, %s , %s };"%(self.getID(),c[0],c[1],c[2], self.getLocalScale()*local_scaling_factor)          return "Point(%s) = {%s , %s, %s , %s };"%(self.getID(),c[0],c[1],c[2], self.getLocalScale()*local_scaling_factor)
354    
355  class Primitive1D(Primitive):      def __neg__(self):
356        """          """
357        general one-dimensional primitive          returns a view of the object with reverse orientiention. As a point has no direction the object itself is returned.
358        """          """
359        def __init__(self,*args):          return self
360            """        
361            create a one-dimensional primitive  class Manifold1D(PrimitiveBase):
           """  
           super(Primitive1D, self).__init__()  
         
 class Curve(Primitive1D):  
362      """      """
363      a curve defined through a list of control points.      general one-dimensional minifold in 3D defined by a start and end point.
364      """      """
365      def __init__(self,*points):      def __init__(self):
366            """
367            create a one-dimensional manifold
368            """
369            PrimitiveBass.__init__(self)
370    
371        def getStartPoint(self):
372             """
373             returns start point
374             """
375             raise NotImplementedError()
376    
377        def getEndPoint(self):
378             """
379             returns end point
380             """
381             raise NotImplementedError()
382    
383    class CurveBase(Manifold1D):
384        def __init__(self):
385            """            """
386            defines a curve form control points            create a one-dimensional primitive
387            """            """
388            if len(points)<2:            Manifold1D.__init__(self)
              raise TypeError("Curve needs at least two points")  
           super(Curve, self).__init__()  
           i=0  
           for p in points:  
               i+=1  
               if not isinstance(p,Point): raise TypeError("%s-th argument is not a Point object."%i)  
           self.__points=points  
389    
390      def __len__(self):      def __len__(self):
391            """            """
392            returns the number of control points            returns the number of control points
393            """            """
394            return len(self.__points)            return len(self.getControlPoints())
395    
396      def getStartPoint(self):      def getStartPoint(self):
397           """           """
398           returns start point           returns start point
399           """           """
400           return self.__points[0]           return self.getControlPoints[0]
401    
402      def getEndPoint(self):      def getEndPoint(self):
403           """           """
404           returns end point           returns end point
405           """           """
406           return self.__points[-1]           return self.getControlPoints[-1]
407    
408      def getControlPoints(self):      def collectPrimitives(self):
          """  
          returns a list of the points  
          """  
          return self.__points  
   
     def getPrimitives(self):  
409         """         """
410         returns primitives used to construct the Curve         returns primitives used to construct the Curve
411         """         """
412         out=set()         out=[self]
413         for p in self.getControlPoints(): out|=set(p.getPrimitives())         for p in self.getControlPoints(): out+=p.collectPrimitives()
414         out.add(self)         return out
        return list(out)  
415    
416      def substitute(self,sub_dict):      def substitute(self,sub_dict):
417          """          """
# Line 347  class Curve(Primitive1D): Line 422  class Curve(Primitive1D):
422          if not sub_dict.has_key(self):          if not sub_dict.has_key(self):
423              new_p=[]              new_p=[]
424              for p in self.getControlPoints(): new_p.append(p.substitute(sub_dict))              for p in self.getControlPoints(): new_p.append(p.substitute(sub_dict))
425              sub_dict[self]=self.__class__(*tuple(new_p))              sub_dict[self]=self.getGeneratingClass()(*tuple(new_p))
426          return sub_dict[self]          return sub_dict[self]
427    
428      def isColocated(self,primitive):      def isColocated(self,primitive):
# Line 373  class Curve(Primitive1D): Line 448  class Curve(Primitive1D):
448         else:         else:
449            return False            return False
450    
451          
452    class Curve(CurveBase):
453        """
454        a curve defined through a list of control points.
455        """
456        def __init__(self,*points):
457           """
458           defines a curve form control points
459           """
460           CurveBase.__init__(self)
461           if len(points)<2:
462               raise TypeError("Curve needs at least two points")
463           super(Curve, self).__init__()
464           i=0
465           for p in points:
466                  i+=1
467                  if not isinstance(p,Point): raise TypeError("%s-th argument is not a Point object."%i)
468           self.__points=points
469    
470        def __neg__(self):
471              """
472              returns a view onto the curce with reversed ordering
473              """
474              return ReverseCurve(self)
475        def getControlPoints(self):
476             """
477             returns a list of the points
478             """
479             return self.__points
480    
481        def getGeneratingClass(self):
482             return self.__class__
483    
484    class ReverseCurve(CurveBase):
485        """
486        a curve defined through a list of control points.
487        """
488        def __init__(self,curve):
489           """
490           defines a curve form control points
491           """
492           CurveBase.__init__(self)
493           if not isinstance(curve, CurveBase):
494               raise TypeError("curve needs to be an instance of Curve")
495           self.__curve=curve
496    
497        def __neg__(self):
498              """
499              returns a view onto the curce with reversed ordering
500              """
501              return self.__curve
502        def getControlPoints(self):
503             """
504             returns a list of the points
505             """
506             out=[p for p in self.__curve.getControlPoints()]
507             out.reverse()
508             return out
509        def getGeneratingClass(self):
510             return self.__curve.getGeneratingClass()
511    
512  class Spline(Curve):  class Spline(Curve):
513      """      """
514      a spline curve defined through a list of control points.      a spline curve defined through a list of control points.
# Line 440  class Line(Curve): Line 576  class Line(Curve):
576          return "Line(%s) = {%s, %s};"%(self.getID(),self.getStartPoint().getID(),self.getEndPoint().getID())          return "Line(%s) = {%s, %s};"%(self.getID(),self.getStartPoint().getID(),self.getEndPoint().getID())
577    
578    
579  class Arc(Primitive1D):  class ArcBase(Manifold1D):
580        def collectPrimitives(self):
581           """
582           returns the primitives used to construct the Curve
583           """
584           out=[self]
585           out+=self.getStartPoint().collectPrimitives()
586           out+=self.getEndPoint().collectPrimitives()
587           out+=self.getCenterPoint().collectPrimitives()
588           return out
589    
590        def getGmshCommand(self):
591           """
592           returns the Gmsh command(s) to create the primitive
593           """
594           return "Circle(%s) = {%s, %s, %s};"%(self.getID(),self.getStartPoint().getID(),self.getCenterPoint().getID(),self.getEndPoint().getID())
595    
596        def substitute(self,sub_dict):
597            """
598            returns a copy of self with substitutes for the primitives used to construct it given by the dictionary C{sub_dict}.
599            If a substitute for the object is given by C{sub_dict} the value is returned, otherwise a new instance
600            with substituted arguments is returned.
601            """
602            if not sub_dict.has_key(self):
603                sub_dict[self]=Arc(self.getCenterPoint().substitute(sub_dict),self.getStartPoint().substitute(sub_dict),self.getEndPoint().substitute(sub_dict))
604            return sub_dict[self]
605    
606        def isColocated(self,primitive):
607           """
608           returns True curves are on the same position
609           """
610           if isinstance(primitive,Arc):
611                return (self.getCenterPoint().isColocated(primitive.getCenterPoint())) and ( \
612                       (self.getEndPoint().isColocated(primitive.getEndPoint()) and self.getStartPoint().isColocated(primitive.getStartPoint()) ) \
613                    or (self.getEndPoint().isColocated(primitive.getStartPoint()) and self.getStartPoint().isColocated(primitive.getEndPoint()) ) )
614           else:
615              return False
616    
617    class Arc(ArcBase):
618      """      """
619      defines an arc which is strictly, smaller than Pi      defines an arc which is strictly, smaller than Pi
620      """      """
# Line 452  class Arc(Primitive1D): Line 626  class Arc(Primitive1D):
626         if not isinstance(end,Point): raise TypeError("end needs to be a Point object.")         if not isinstance(end,Point): raise TypeError("end needs to be a Point object.")
627         if not isinstance(start,Point): raise TypeError("start needs to be a Point object.")         if not isinstance(start,Point): raise TypeError("start needs to be a Point object.")
628         # TODO: check length of circle.         # TODO: check length of circle.
629         super(Arc, self).__init__()         ArcBase.__init__(self)
630         self.__center=center         self.__center=center
631         self.__start=start         self.__start=start
632         self.__end=end         self.__end=end
633        def __neg__(self):
634           return ReverseArc(self)
635    
636      def getStartPoint(self):      def getStartPoint(self):
637         """         """
# Line 475  class Arc(Primitive1D): Line 651  class Arc(Primitive1D):
651         """         """
652         return self.__center         return self.__center
653    
654      def getPrimitives(self):  class ReverseArc(_ArcBase):
655        """
656        defines an arc which is strictly, smaller than Pi
657        """
658        def __init__(self,arc):
659         """         """
660         returns the primitives used to construct the Curve         creates an arc by the start point, end point and center
661         """         """
662         out=set()         if not isinstance(arc,Arc): raise TypeError("arc needs to be an instance of Arc.")
663         out|=set(self.getStartPoint().getPrimitives())         ArcBase.__init__(self)
664         out|=set(self.getEndPoint().getPrimitives())         self.__arc=arc
        out|=set(self.getCenterPoint().getPrimitives())  
        out.add(self)  
        return list(out)  
665    
666      def getGmshCommand(self):      def getStartPoint(self):
667         """         """
668         returns the Gmsh command(s) to create the primitive         returns start point
669         """         """
670         return "Circle(%s) = {%s, %s, %s};"%(self.getID(),self.getStartPoint().getID(),self.getCenterPoint().getID(),self.getEndPoint().getID())         return self.__arc.getEndPoint()
671    
672      def substitute(self,sub_dict):      def getEndPoint(self):
673          """         """
674          returns a copy of self with substitutes for the primitives used to construct it given by the dictionary C{sub_dict}.         returns end point
675          If a substitute for the object is given by C{sub_dict} the value is returned, otherwise a new instance         """
676          with substituted arguments is returned.         return self.__arc.getStartPoint()
         """  
         if not sub_dict.has_key(self):  
             sub_dict[self]=Arc(self.getCenterPoint().substitute(sub_dict),self.getStartPoint().substitute(sub_dict),self.getEndPoint().substitute(sub_dict))  
         return sub_dict[self]  
677    
678      def isColocated(self,primitive):      def getCenterPoint(self):
679         """         """
680         returns True curves are on the same position         returns center
681         """         """
682         if isinstance(primitive,Arc):         return self.__arc.getCenterPoint()
             return (self.getCenterPoint().isColocated(primitive.getCenterPoint())) and ( \  
                    (self.getEndPoint().isColocated(primitive.getEndPoint()) and self.getStartPoint().isColocated(primitive.getStartPoint()) ) \  
                 or (self.getEndPoint().isColocated(primitive.getStartPoint()) and self.getStartPoint().isColocated(primitive.getEndPoint()) ) )  
        else:  
           return False  
683    
684  class Primitive2D(Primitive):      def __neg__(self):
685        """         return self.__arc
       general two-dimensional primitive  
       """  
       def __init__(self,*args):  
           """  
           create a two-dimensional primitive  
           """  
           super(Primitive2D, self).__init__()  
686    
687  class CurveLoop(Primitive2D):  #====================================
688    class CurveLoop(Primitive):
689      """      """
690      An oriented loop of curves.      An oriented loop of 1D primitives (= curves and arcs)
691    
692      The loop must be closed and the L{Curves}s should be oriented consistently.      The loop must be closed and the L{Manifold1D}s should be oriented consistently.
693      """      """
694      def __init__(self,*curves):      def __init__(self,*curves):
695         """         """
# Line 537  class CurveLoop(Primitive2D): Line 699  class CurveLoop(Primitive2D):
699         if len(curves)<2:         if len(curves)<2:
700              raise TypeError("at least two curves have to be given.")              raise TypeError("at least two curves have to be given.")
701         for i in range(len(curves)):         for i in range(len(curves)):
702             if not isinstance(curves[i],Primitive1D):             if not isinstance(curves[i],Manifold1D):
703                raise TypeError("%s-th argument is not a Primitive1D object."%i)                raise TypeError("%s-th argument is not a Manifold1D object."%i)
704         # for the curves a loop:         # for the curves a loop:
705         used=[ False for i in curves]         used=[ False for i in curves]
706         self.__curves=[curves[0]]         self.__curves=[curves[0]]
# Line 567  class CurveLoop(Primitive2D): Line 729  class CurveLoop(Primitive2D):
729         """         """
730         return the number of curves in the CurveLoop         return the number of curves in the CurveLoop
731         """         """
732         return len(self.__curves)         return len(self.getCurves())
733    
734      def getPrimitives(self):      def collectPrimitives(self):
735         """         """
736         returns primitives used to construct the CurveLoop         returns primitives used to construct the CurveLoop
737         """         """
738         out=set()         out=[self]
739         for c in self.getCurves(): out|=set(c.getPrimitives())         for c in self.getCurves(): out+=c.collectPrimitives()
740         out.add(self)         return out
        return list(out)  
741    
742      def substitute(self,sub_dict):      def substitute(self,sub_dict):
743          """          """
# Line 590  class CurveLoop(Primitive2D): Line 751  class CurveLoop(Primitive2D):
751              sub_dict[self]=CurveLoop(*tuple(new_c))              sub_dict[self]=CurveLoop(*tuple(new_c))
752          return sub_dict[self]          return sub_dict[self]
753    
   
754      def isColocated(self,primitive):      def isColocated(self,primitive):
755         """         """
756         returns True if each curve is collocted with a curve in primitive         returns True if each curve is collocted with a curve in primitive
# Line 611  class CurveLoop(Primitive2D): Line 771  class CurveLoop(Primitive2D):
771            return False            return False
772    
773      def getGmshCommand(self):      def getGmshCommand(self):
774            """
775            returns the Gmsh command(s) to create the primitive
776            """
777          out=""          out=""
778          for i in self.getCurves():          for i in self.getCurves():
779              if len(out)>0:              if len(out)>0:
# Line 619  class CurveLoop(Primitive2D): Line 782  class CurveLoop(Primitive2D):
782                  out="%s"%i.getID()                  out="%s"%i.getID()
783          return "Line Loop(%s) = {%s};"%(self.getID(),out)          return "Line Loop(%s) = {%s};"%(self.getID(),out)
784    
785  class Surface(Primitive2D):  class Primitive2D(Primitive):
786      """      """
787      a surface      general two-dimensional primitive
788      """      """
789      pass      def __init__(self):
790              """
791              create a two-dimensional primitive
792              """
793              super(Primitive2D, self).__init__()
794    
795        def getBoundary(self):
796            """
797            returns a list of the 1D primitives forming the boundary of the Surface (including holes)
798            """
799            out=[]
800            for i in self.getPrimitives():
801                 if isinstance(i, Manifold1D): out.append(i)
802            return out
803    
804        def getBoundary(self):
805            """
806            returns a list of the 1D primitives forming the boundary of the Surface (including holes)
807            """
808            out=[]
809            for i in self.getPrimitives():
810                 if isinstance(i, Manifold1D): out.append(i)
811            return out
812    
813  class RuledSurface(Surface):      def getBoundaryLoop(self):
814            """
815            returns the loop defining the outer boundary
816            """
817            raise NotImplementedError("getBoundaryLoop is not implemented for this class %s."%self.__class__.__name__)
818    
819        def getHoles(self):
820           """
821           returns the holes
822           """
823           raise NotImplementedError("getHoles is not implemented for this class %s."%self.__class__.__name__)
824    
825        def collectPrimitives(self):
826            """
827            returns primitives used to construct the Surface
828            """
829            out=[self] + self.getBoundaryLoop().collectPrimitives()
830            for i in self.getHoles(): out+=i.collectPrimitives()
831            return out
832    
833    class RuledSurface(Primitive2D):
834      """      """
835      A ruled surface, i.e., a surface that can be interpolated using transfinite interpolation      A ruled surface, i.e., a surface that can be interpolated using transfinite interpolation
836      """      """
# Line 636  class RuledSurface(Surface): Line 841  class RuledSurface(Surface):
841         @param loop: L{CurveLoop} defining the boundary of the surface.         @param loop: L{CurveLoop} defining the boundary of the surface.
842         """         """
843         super(RuledSurface, self).__init__()         super(RuledSurface, self).__init__()
844         if not isinstance(CurveLoop):         if not isinstance(loop,CurveLoop):
845             raise TypeError("argument loop needs to be a CurveLoop object.")             raise TypeError("argument loop needs to be a CurveLoop object.")
846         if len(loop)<2:         if len(loop)<2:
847             raise TypeError("the loop must contain at least two Curves.")             raise TypeError("the loop must contain at least two Curves.")
# Line 647  class RuledSurface(Surface): Line 852  class RuledSurface(Surface):
852    
853      def getBoundaryLoop(self):      def getBoundaryLoop(self):
854          """          """
855          returns the loop defining the boundary          returns the loop defining the outer boundary
856          """          """
857          return self.__loop          return self.__loop
858    
859      def getPrimitives(self):      def getHoles(self):
860          out=set([self]) | self.getBoundaryLoop().getPrimitives()          """
861            returns the holes
862            """
863            return []
864    
865      def getGmshCommand(self):      def getGmshCommand(self):
866            """
867            returns the Gmsh command(s) to create the primitive
868            """
869          return "Ruled Surface(%s) = {%s};"%(self.getID(),self.getBoundaryLoop().getID())          return "Ruled Surface(%s) = {%s};"%(self.getID(),self.getBoundaryLoop().getID())
870    
     def getPrimitives(self):  
        """  
        returns primitives used to construct the CurveLoop  
        """  
        out=list(set([self]) | self.getBoundaryLoop().getPrimitives())  
   
871      def substitute(self,sub_dict):      def substitute(self,sub_dict):
872          """          """
873          returns a copy of self with substitutes for the primitives used to construct it given by the dictionary C{sub_dict}.          returns a copy of self with substitutes for the primitives used to construct it given by the dictionary C{sub_dict}.
# Line 670  class RuledSurface(Surface): Line 875  class RuledSurface(Surface):
875          with substituted arguments is returned.          with substituted arguments is returned.
876          """          """
877          if not sub_dict.has_key(self):          if not sub_dict.has_key(self):
878              sub_dict[self]=CurveLoop(self.getBoundaryLoop().substitute(sub_dict))              sub_dict[self]=RuledSurface(self.getBoundaryLoop().substitute(sub_dict))
879          return sub_dict[self]          return sub_dict[self]
880    
881      def isColocated(self,primitive):      def isColocated(self,primitive):
# Line 678  class RuledSurface(Surface): Line 883  class RuledSurface(Surface):
883         returns True if each curve is collocted with a curve in primitive         returns True if each curve is collocted with a curve in primitive
884         """         """
885         if isinstance(primitive,RuledSurface):         if isinstance(primitive,RuledSurface):
886            return self.getBoundaryLoop().colocated(primitive.getBoundaryLoop())            return self.getBoundaryLoop().isColocated(primitive.getBoundaryLoop())
887         else:         else:
888            return False            return False
889    
# Line 688  def createRuledSurface(*curves): Line 893  def createRuledSurface(*curves):
893        """        """
894        return RuledSurface(CurveLoop(*curves))        return RuledSurface(CurveLoop(*curves))
895    
896  class PlaneSurface(Surface):  class PlaneSurface(Primitive2D):
897      """      """
898      a plane surface with holes      a plane surface with holes
899      """      """
# Line 704  class PlaneSurface(Surface): Line 909  class PlaneSurface(Surface):
909         super(PlaneSurface, self).__init__()         super(PlaneSurface, self).__init__()
910         if not isinstance(loop,CurveLoop):         if not isinstance(loop,CurveLoop):
911             raise TypeError("argument loop needs to be a CurveLoop object.")             raise TypeError("argument loop needs to be a CurveLoop object.")
912           for l in loop.getCurves():
913               if not isinstance(l,Line):
914                 raise TypeError("loop may be formed by Lines only.")
915         for i in range(len(holes)):         for i in range(len(holes)):
916              if not holes[i].inCurveLoop():              if not isinstance(holes[i], CurveLoop):
917                   raise TypeError("%i th hole needs to be a CurveLoop object.")                   raise TypeError("%i-th hole needs to be a CurveLoop object.")
918         #TODO: check if lines are in a plane              for l in holes[i].getCurves():
919                   if not isinstance(l,Line):
920                      raise TypeError("holes may be formed by Lines only.")
921           #TODO: check if lines and holes are in a plane
922           #TODO: are holes really holes?
923           self.__loop=loop
924         self.__holes=holes         self.__holes=holes
925      def getHoles(self):      def getHoles(self):
926         """         """
# Line 719  class PlaneSurface(Surface): Line 932  class PlaneSurface(Surface):
932          returns the loop defining the boundary          returns the loop defining the boundary
933          """          """
934          return self.__loop          return self.__loop
     def getPrimitives(self):  
         out=set([self]) | self.getBoundaryLoop().getPrimitives()  
         for i in self.getHoles(): out|=i.getPrimitives()  
         return out  
935    
936      def getGmshCommand(self):      def getGmshCommand(self):
937            """
938            returns the Gmsh command(s) to create the primitive
939            """
940          out=""          out=""
941          for i in self.getHoles():          for i in self.getHoles():
942              if len(out)>0:              if len(out)>0:
# Line 743  class PlaneSurface(Surface): Line 955  class PlaneSurface(Surface):
955          with substituted arguments is returned.          with substituted arguments is returned.
956          """          """
957          if not sub_dict.has_key(self):          if not sub_dict.has_key(self):
958              sub_dict[self]=CurveLoop(self.getBoundaryLoop().substitute(sub_dict),[ h.substitute(sub_dict) for h in self.getHoles()])              sub_dict[self]=PlaneSurface(self.getBoundaryLoop().substitute(sub_dict),[ h.substitute(sub_dict) for h in self.getHoles()])
959          return sub_dict[self]          return sub_dict[self]
960    
961      def isColocated(self,primitive):      def isColocated(self,primitive):
# Line 751  class PlaneSurface(Surface): Line 963  class PlaneSurface(Surface):
963         returns True if each curve is collocted with a curve in primitive         returns True if each curve is collocted with a curve in primitive
964         """         """
965         if isinstance(primitive,PlaneSurface):         if isinstance(primitive,PlaneSurface):
966            if self.getBoundaryLoop().colocated(primitive.getBoundaryLoop()):            if self.getBoundaryLoop().isColocated(primitive.getBoundaryLoop()):
967               my_h=self.getHoles()               hs0=self.getHoles()
968               h=primitive.getHoles()               hs1=primitive.getHoles()
969                 if len(hs0) == len(hs1):
970                     for h0 in hs0:
971                        collocated = False
972                        for h1 in hs1:
973                          collocated = collocated or h0.isColocated(h1)
974                        if not collocated: return False
975                     return True
976                 return False
977            else:            else:
978               return False               return False
979         else:         else:
980            return False            return False
981    
   
 #=================================================================================================================================  
982  class SurfaceLoop(Primitive):  class SurfaceLoop(Primitive):
983      """      """
984      a surface loop. It defines the shell of a volume.      a loop of 2D primitives. It defines the shell of a volume.
985    
986      The loop must represent a closed shell, and the L{Surface}s should be oriented consistently.      The loop must represent a closed shell, and the primitives should be oriented consistently.
987      """      """
988      def __init__(self,*surfaces):      def __init__(self,*surfaces):
989         """         """
990         creates a surface loop         creates a surface loop
991         """         """
992         super(SurfaceLoop, self).__init__()         super(SurfaceLoop, self).__init__()
993         self.__surfaces=[]         if len(surfaces)<2:
994         self.addSurface(*surfaces)              raise TypeError("at least two surfaces have to be given.")
     def addSurface(self,*surfaces):  
995         for i in range(len(surfaces)):         for i in range(len(surfaces)):
996             if not surfaces[i].isSurface():             if not isinstance(surfaces[i],Primitive2D):
997                raise TypeError("%s-th argument is not a Surface object."%i)                raise TypeError("%s-th argument is not a Primitive2D object."%i)
998         self.__surfaces+=surfaces         # for the curves a loop:
999           used=[ True for s in surfaces]
1000      def isSurfaceLoop(self):         self.__surfaces=[surfaces[0]]
1001          return True         edges=[ e in surfaces[0].getBoundary() ]
1002      def getSurfaces(self):         used_edges=[ False in surfaces[0].getBoundary() ]
1003         return self.__surfaces         while min(used):
1004      def __add__(self,other):            found=False
1005         return SurfaceLoop([c+other for c in self.getSurfaces])            for i in xrange(len(surfaces)):
1006                 if not used[i]:
1007                    i_boundary=surfaces[i].getBoundary()
1008                    for ib in xrange(i_boundary):  
1009                        if i_boundary[ib] in edges:
1010                             if used_edges[edges.index(i_boundary[ib])]:
1011                                raise TypeError("boundary segment %s is shared by more than one surface."%str(i_boundary[ib]))
1012                             used_edges[edges.index(i_boundary[ib])]=True
1013                             self.__surfaces.append(surfaces[i])
1014                             for b in i_boundary:
1015                                if not b in edges:
1016                                    edges.append(b)
1017                                    used_edges.append(False)
1018                             found=True
1019                             used[i]=True
1020                             break
1021                 if found: break
1022              if not found:
1023                 raise ValueError("loop is not closed.")
1024           if min(used_edges):
1025              raise ValueError("loop is not closed. Surface is missing.")
1026      def __len__(self):      def __len__(self):
1027           """
1028           return the number of curves in the SurfaceLoop
1029           """
1030         return len(self.__surfaces)         return len(self.__surfaces)
1031      def getPrimitives(self):  
1032            out=set([self])      def getSurfaces(self):
1033            for i in self.getSurfaces(): out|=i.getPrimitives()         """
1034            return out         returns the surfaces defining the SurfaceLoop
1035      def getConstructionPoints(self):         """
1036            out=set()         return self.__curves
1037            for i in self.getSurfaces(): out|=i.getConstructionPoints()  
1038            return out      def collectPrimitives(self):
1039           """
1040           returns primitives used to construct the SurfaceLoop
1041           """
1042           out=[self]
1043           for c in self.getSurfaces(): out+=c.collectPrimitives()
1044           return out
1045      def getGmshCommand(self):      def getGmshCommand(self):
1046            """
1047            returns the Gmsh command(s) to create the primitive
1048            """
1049          out=""          out=""
1050          for i in self.getSurfaces():          for i in self.getSurfaces():
1051              if len(out)>0:              if len(out)>0:
# Line 804  class SurfaceLoop(Primitive): Line 1053  class SurfaceLoop(Primitive):
1053              else:              else:
1054                  out="%s"%i.getID()                  out="%s"%i.getID()
1055          return "Surface Loop(%s) = {%s};"%(self.getID(),out)          return "Surface Loop(%s) = {%s};"%(self.getID(),out)
1056        def substitute(self,sub_dict):
1057            """
1058            returns a copy of self with substitutes for the primitives used to construct it given by the dictionary C{sub_dict}.
1059            If a substitute for the object is given by C{sub_dict} the value is returned, otherwise a new instance
1060            with substituted arguments is returned.
1061            """
1062            if not sub_dict.has_key(self):
1063                new_s=[]
1064                for s in self.getCurves(): new_s.append(s.substitute(sub_dict))
1065                sub_dict[self]=SurfaceLoop(*tuple(new_s))
1066            return sub_dict[self]
1067    
1068        def isColocated(self,primitive):
1069           """
1070           returns True if each surface is collocted with a curve in primitive and vice versa.
1071           """
1072           if isinstance(primitive,SurfaceLoop):
1073             if len(primitive) == len(self):
1074                 sp0=self.getSurfaces()
1075                 sp1=primitive.getCurves()
1076                 for s0 in sp0:
1077                     collocated = False
1078                     for s1 in sp1:
1079                          collocated = collocated or s0.isColocated(s1)
1080                     if not collocated: return False
1081                 return True
1082             else:
1083                 return False
1084           else:
1085             return False
1086    
1087    #==========================
1088  class Volume(Primitive):  class Volume(Primitive):
1089      """      """
1090      a volume with holes.      a volume with holes.
# Line 832  class Volume(Primitive): Line 1112  class Volume(Primitive):
1112         return self.__loop         return self.__loop
1113      def __add__(self,other):      def __add__(self,other):
1114         return Volume(self.getSurfaceLoop()+other, holes=[h+other for h in self.getHoles()])         return Volume(self.getSurfaceLoop()+other, holes=[h+other for h in self.getHoles()])
1115      def getPrimitives(self):      def collectPrimitives(self):
1116          out=set([self]) | self.getSurfaceLoop().getPrimitives()          out=[self] + self.getSurfaceLoop().collectPrimitives()
1117          for i in self.getHoles(): out|=i.getPrimitives()          for i in self.getHoles(): out+=i.collectPrimitives()
1118          return out          return out
1119      def getConstructionPoints(self):      def getConstructionPoints(self):
1120          out=self.getSurfaceLoop().getConstructionPoints()          out=self.getSurfaceLoop().getConstructionPoints()
1121          for i in self.getHoles(): out|=i.Points()          for i in self.getHoles(): out|=i.Points()
1122          return out          return out
1123      def getGmshCommand(self):      def getGmshCommand(self):
1124            """
1125            returns the Gmsh command(s) to create the primitive
1126            """
1127          out=""          out=""
1128          for i in self.getHoles():          for i in self.getHoles():
1129              if len(out)>0:              if len(out)>0:
# Line 871  class PropertySet(Primitive): Line 1154  class PropertySet(Primitive):
1154         super(PropertySet, self).__init__()         super(PropertySet, self).__init__()
1155         self.__items=items         self.__items=items
1156         self.__tag=tag         self.__tag=tag
1157      def getPrimitives(self):      def collectPrimitives(self):
1158          out=set([self, self.getBoundaryLoop().getPrimitives()])          out=[self]+self.getBoundaryLoop().collectPrimitives()
1159          for i in self.getHoles(): out|=i.getPrimitives()          for i in self.getHoles(): out+=i.collectPrimitives()
1160          return out          return out
1161    
1162  class PrimitiveStack(object):  class PrimitiveStack(object):

Legend:
Removed from v.927  
changed lines
  Added in v.928

  ViewVC Help
Powered by ViewVC 1.1.26