/[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

trunk/pycad/py_src/elementries.py revision 898 by gross, Sun Nov 12 23:56:26 2006 UTC trunk/pycad/py_src/primitives.py revision 902 by gross, Thu Nov 16 07:22:08 2006 UTC
# Line 1  Line 1 
1  # $Id:$  # $Id:$
2    
3  """  """
4  Geometrical Elementries  Geometrical Primitives
5    
6  the concept is inspired by gmsh and very much focused on the fact that  the concept is inspired by gmsh and very much focused on the fact that
7  the classes are used to wrk with gmsh.  the classes are used to wrk with gmsh.
# Line 25  __url__="http://www.iservo.edu.au/esys/e Line 25  __url__="http://www.iservo.edu.au/esys/e
25  __version__="$Revision:$"  __version__="$Revision:$"
26  __date__="$Date:$"  __date__="$Date:$"
27    
28  class Elementary(object):  import numarray
29    
30    global global_primitive_id_counter
31    global_primitive_id_counter=0
32    
33    class Primitive(object):
34      """      """
35      template for elementary geometrical object      template for elementary geometrical object
36      """      """
37      def __init__(self):      def __init__(self):
38         """         """
39         """         """
40         pass         global global_primitive_id_counter
41           self.__ID=global_primitive_id_counter
42           global_primitive_id_counter+=1
43        def getID(self):
44           return self.__ID
45        def __repr__(self):
46           return "%s(%s)"%(self.__class__.__name__,self.getID())
47        def __cmp__(self,other):
48           return cmp(self.getID(),other.getID())
49        def isPoint(self):
50            return False
51        def isCurve(self):
52            return False
53        def isSurface(self):
54            return False
55        def isCurveLoop(self):
56            return False
57        def isSurfaceLoop(self):
58            return False
59        def __neg__(self):
60            return ReversedPrimitive(self)
61        def __pos__(self):
62            return self.copy()
63        def __add__(self,other):
64           out=self.copy()
65           out+=other
66           return out
67        def __iadd__(self,other):
68           self.shift()
69        def setLocalLength(self,factor=1.):
70            for p in self.getPoints(): p.setLocalLength(factor)
71        def shift(self,shift):
72            for p in self.getPoints(): p+=shift
73        def copy(self):
74            return Primitive()
75        def getGmshCommand(self):
76            raise NotImplementedError("getGmshCommand is not implemented for this class %s."%self.__class__.__name__)
77        def getHistory(self):
78            return set()
79        def getPoints(self):
80            return set()
81        def translate(self,shift):
82            raise NotImplementedError("translate is not implemented for this class %s."%self.__class__.__name__)
83    
84    class ReversedPrimitive(object):
85        def __init__(self,prim):
86           self.__prim=prim
87        def __getattr__(self,name):
88           if name == "getID":
89              return self.getReverseID
90           else:
91              return getattr(self.__prim,name)
92        def getReverseID(self):
93            return -self.__prim.getID()
94    
95  class Point(Elementary):  class Point(Primitive):
96      """      """
97      a three dimensional point      a three dimensional point
98      """      """
# Line 46  class Point(Elementary): Line 104  class Point(Elementary):
104         if not local_scale > 0.:         if not local_scale > 0.:
105             raise ValueError("local_scale needs to be positive.")             raise ValueError("local_scale needs to be positive.")
106         self._x=numarray.array([x,y,z],numarray.Float64)         self._x=numarray.array([x,y,z],numarray.Float64)
107         self.setLocalScale(0.,local_scale)         self.setLocalScale(local_scale)
     def __str__(self):  
        return str(self._x)  
108      def setLocalScale(self,factor=1.):      def setLocalScale(self,factor=1.):
109           """
110           sets the local relative length scale
111           """
112         self.__local_scale=factor         self.__local_scale=factor
113        def getLocalScale(self):
114           return self.__local_scale
115        def copy(self):
116           c=self.getCoordinates()
117           return Point(c[0],c[1],c[2],local_scale=self.getLocalScale())
118        def isPoint(self):
119            return True
120        def getCoordinates(self):
121           return self._x
122        def getGmshCommand(self):
123            c=self.getCoordinates()
124            return "Point(%s) = {%e , %e, %e , %e * scale};"%(self.getID(),c[0],c[1],c[2], self.getLocalScale())
125        def getHistory(self):
126            return set([self])
127        def getPoints(self):
128            return set([self])
129        def shift(self,shift):
130           """
131           shifts the point by a given shift
132           """
133           self._x+=numarray.array(shift,numarray.Float64)
134        def translate(self,shift):
135           """
136           returns the point shifted by shift
137           """
138           out=self.copy()
139           out+=other
140           return out
141    
142  class Curve(Elementary):  
143    class Curve(Primitive):
144        """        """
145        a curve        a curve
146        """        """
# Line 64  class Curve(Elementary): Line 151  class Curve(Elementary):
151            super(Curve, self).__init__()            super(Curve, self).__init__()
152            l=len(args)            l=len(args)
153            for i in range(l):            for i in range(l):
154                if not isinstance(args[i],Point):                if not args[i].isPoint():
155                   raise TypeError("%s-th argument is not a Point object.")                   raise TypeError("%s-th argument is not a Point object."%i)
156            super(Curve, self).__init__(args[0],args[l-1])            self.__nodes=args
           self.__nodes=list(args)  
157        def __len__(self):        def __len__(self):
158            return len(self.__nodes)            return len(self.__nodes)
159          def isCurve(self):
160            return True
161        def getStart(self):        def getStart(self):
162           """           """
163           returns start point           returns start point
# Line 88  class Curve(Elementary): Line 175  class Curve(Elementary):
175           returns a list of the nodes           returns a list of the nodes
176           """           """
177           return self.__nodes           return self.__nodes
178          def getGmshCommand(self):
179            out=""
180            for i in self.getNodes():
181                if len(out)>0:
182                    out+=", %s"%i.getID()
183                else:
184                    out="%s"%i.getID()
185            return "Spline(%s) = {%s};"%(self.getID(),out)
186          def getHistory(self):
187              out=set([self])
188              for i in self.getNodes(): out|=i.getHistory()
189              return out
190          def getPoints(self):
191            out=set()
192            for i in self.getNodes(): out|=i.getPoints()
193            return out
194    
       def __neg__(self):  
          """  
          returns the line segment with swapped start and end points  
          """  
          return Curve(self.__nodes[::-1])  
195    
196  class BezierCurve(Curve):  class BezierCurve(Curve):
197      """      """
198      a Bezier curve      a Bezier curve
199      """      """
200      def __neg__(self):      def __neg__(self):
201         """           """
202         returns the line segment with swapped start and end points           returns the line segment with swapped start and end points
203         """           """
204         return BezierCurve(self.getNodesInReversedOrder())           return BezierCurve(self.getNodes()[::-1])
205        def __add__(self,other):
206             return BezierCurve([p+other for p in self.getNodes()])
207        def getGmshCommand(self):
208            out=""
209            for i in self.getNodes():
210                if len(out)>0:
211                    out+=", %s"%i.getID()
212                else:
213                    out="%s"%i.getID()
214            return "Bezier(%s) = {%s};"%(self.getID(),out)
215    
216  class BSplineCurve(Curve):  class BSplineCurve(Curve):
217      """      """
218      a BSpline curve. Control points may be repeated.      a BSpline curve. Control points may be repeated.
219      """      """
220      def __neg__(self):      def __neg__(self):
221         """           """
222         returns the line segment with swapped start and end points           returns the line segment with swapped start and end points
223         """           """
224         return BSplineCurve(self.getNodesInReversedOrder())           return BSplineCurve(self.getNodes()[::-1])
225        def __add__(self,other):
226             return BSplineCurve([p+other for p in self.getNodes()])
227        def getGmshCommand(self):
228            out=""
229            for i in self.getNodes():
230                if len(out)>0:
231                    out+=", %s"%i.getID()
232                else:
233                    out="%s"%i.getID()
234            return "BSpline(%s) = {%s};"%(self.getID(),out)
235    
236  class Line(Curve):  class Line(Curve):
237      """      """
238      a line is defined by two L{Point}s      a line is defined by two L{Point}s
239      """      """
240        def __init__(self,start,end):
241            """
242            defines a curve form a set of control points
243            """
244            super(Line, self).__init__(start,end)
245      def __neg__(self):      def __neg__(self):
246         """         return ReversedPrimitive(self)
247         returns the line segment with swapped start and end points      def __add__(self,other):
248         """         return Line(self.getEnd()+other,self.getStart()+other)
249         return Line(self.getEnd(),self.getStart())      def getGmshCommand(self):
250            return "Line(%s) = {%s, %s};"%(self.getID(),self.getStart().getID(),self.getEnd().getID())
251    
252  class Arc(Curve):  class Arc(Curve):
253      """      """
# Line 134  class Arc(Curve): Line 257  class Arc(Curve):
257         """         """
258         creates an arc by the start point, end point and center         creates an arc by the start point, end point and center
259         """         """
260         if not isinstance(center,Point):         if center.isPoint():
261             raise TypeError("center needs to be a Point object.")             raise TypeError("center needs to be a Point object.")
262         super(Arc, self).__init__(start,end)         super(Arc, self).__init__(start,end)
263         self.__center=center         self.__center=center
# Line 144  class Arc(Curve): Line 267  class Arc(Curve):
267         returns center         returns center
268         """         """
269         return self.__center         return self.__center
270      def __neg__(self):      def __add__(self,other):
271         """         return Arc(self.getCenter()+other,self.getStart()+other,self.getEnd()+other)
272         returns the line segment with swapped start and end points  
273         """      def getHistory(self):
274         return Arc(self.getCenter(),self.getEnd(),self.getStart())            out=set([self])
275              out|=self.getCenter().getHistory()
276              for i in self.getNodes(): out|=i.getHistory()
277              return out
278        def getPoints(self):
279              out=self.getCenter().getPoints()
280              for i in self.getNodes(): out|=i.getPoints()
281              return out
282        def getGmshCommand(self):
283            return "Circle(%s) = {%s, %s, %s};"%(self.getID(),self.getStart().getID(),self.getCenter().getID(),self.getEnd().getID())
284    
285  class CurveLoop(Elementary):  class CurveLoop(Primitive):
286      """      """
287      An oriented loop of curves.      An oriented loop of curves.
288    
# Line 161  class CurveLoop(Elementary): Line 293  class CurveLoop(Elementary):
293         creates a polygon from a list of line curves. The curves must form a closed loop.         creates a polygon from a list of line curves. The curves must form a closed loop.
294         """         """
295         super(CurveLoop, self).__init__()         super(CurveLoop, self).__init__()
296         for i in curves:         self.__curves=[]
297             if not isinstance(curves[i],Curve):         self.addCurve(*curves)
298                raise TypeError("%s-th argument is not a Curve object.")      def addCurve(self,*curves):
299         if length(curves)>0:         for i in range(len(curves)):
300            for i in range(len(curves)-1):             if not curves[i].isCurve():
301               if not curves[i].getEnd() == curves[i+1].getStart():                raise TypeError("%s-th argument is not a Curve object."%i)
302                   raise ValueError("start point of %s-th curve does not match end point of %s-th curve."%(i,i+1))         self.__curves+=curves
           if curves[0].getStart() == curves[len(curves)-1].getEnd():  
                  raise ValueError("loop is not closed.")  
        self.__curves=curves  
303    
304        def isCurveLoop(self):
305            return True
306      def getCurves(self):      def getCurves(self):
307         return self.__curves         return self.__curves
308        def __add__(self,other):
309      def __neg__(self):         return CurveLoop(*tuple([c+other for c in self.getCurves()[::-1]]))
        return CurveLoop([-c for c in self.__curves[::-1]])  
   
310      def __len__(self):      def __len__(self):
311         return len(self.__curves)         return len(self.__curves)
312        def getHistory(self):
313              out=set([self])
314              for i in self.getCurves(): out|=i.getHistory()
315              return out
316        def getPoints(self):
317              out=set()
318              for i in self.getCurves(): out|=i.getPoints()
319              return out
320        def getGmshCommand(self):
321            out=""
322            for i in self.getCurves():
323                if len(out)>0:
324                    out+=", %s"%i.getID()
325                else:
326                    out="%s"%i.getID()
327            return "Line Loop(%s) = {%s};"%(self.getID(),out)
328    
329  class Surface(Elementary):  class Surface(Primitive):
330      """      """
331      a surface      a surface
332      """      """
# Line 192  class Surface(Elementary): Line 337  class Surface(Elementary):
337         @param loop: L{CurveLoop} defining the boundary of the surface         @param loop: L{CurveLoop} defining the boundary of the surface
338         """         """
339         super(Surface, self).__init__()         super(Surface, self).__init__()
340         if not isinstance(loop,CurveLoop):         if not loop.isCurveLoop():
341             raise TypeError("argument loop needs to be a CurveLoop object.")             raise TypeError("argument loop needs to be a CurveLoop object.")
342         self.__loop=loop         self.__loop=loop
343        def isSurface(self):
344            return True
345      def getBoundaryLoop(self):      def getBoundaryLoop(self):
346         return self.__loop         return self.__loop
347      def __neg__(self):      def __add__(self,other):
348         return Surface(-self.getBoundaryLoop())         return Surface(self.getBoundaryLoop()+other)
349              def getHistory(self):
350            out=set([self]) | self.getBoundaryLoop().getHistory()
351            return out
352        def getPoints(self):
353            return self.getBoundaryLoop().getPoints()
354        def getGmshCommand(self):
355            return "Ruled Surface(%s) = {%s};"%(self.getID(),self.getBoundaryLoop().getID())
356    
357  class PlaneSurface(Surface):  class PlaneSurface(Surface):
358      """      """
359      a plane surface with holes      a plane surface with holes
# Line 215  class PlaneSurface(Surface): Line 369  class PlaneSurface(Surface):
369         """         """
370         super(PlaneSurface, self).__init__(loop)         super(PlaneSurface, self).__init__(loop)
371         for i in range(len(holes)):         for i in range(len(holes)):
372              if not isinstance(holes[i],CurveLoop):              if not holes[i].inCurveLoop():
373                   raise TypeError("%i th hole needs to be a CurveLoop object.")                   raise TypeError("%i th hole needs to be a CurveLoop object.")
374         self.__holes=holes         self.__holes=holes
375      def getHoles(self):      def getHoles(self):
376         return self.__holes         return self.__holes
377      def __neg__(self):      def __add__(self,other):
378         return PlaneSurface(-self.getBoundaryLoop(),holes=[-h for h in self.getHoles()] )         return PlaneSurface(self.getBoundaryLoop()+other, holes=[h+other for h in self.getHoles()])
379        def getHistory(self):
380            out=set([self]) | self.getBoundaryLoop().getHistory()
381            for i in self.getHoles(): out|=i.getHistory()
382            return out
383        def getPoints(self):
384            out=self.getBoundaryLoop().getPoints()
385            for i in self.getHoles(): out|=i.getPoints()
386            return out
387        def getGmshCommand(self):
388            out=""
389            for i in self.getHoles():
390                if len(out)>0:
391                    out+=", %s"%i.getID()
392                else:
393                    out="%s"%i.getID()
394            if len(out)>0:
395              return "Plane Surface(%s) = {%s, %s};"%(self.getID(),self.getBoundaryLoop().getID(), out)
396            else:
397              return "Plane Surface(%s) = {%s};"%(self.getID(),self.getBoundaryLoop().getID())
398    
399  class RuledSurface(Surface):  class RuledSurface(Surface):
400      """      """
# Line 233  class RuledSurface(Surface): Line 406  class RuledSurface(Surface):
406    
407         @param loop: L{CurveLoop} defining the boundary of the surface. There is a restriction of composed of either three or four L{Curve} objects.         @param loop: L{CurveLoop} defining the boundary of the surface. There is a restriction of composed of either three or four L{Curve} objects.
408         """         """
409         if not isinstance(loop,CurveLoop):         if not loop.isCurveLoop():
410             raise TypeError("argument loop needs to be a CurveLoop object.")             raise TypeError("argument loop needs to be a CurveLoop object.")
411         if len(loop)<3:         if len(loop)<3:
412             raise TypeError("the loop must contain at least three Curves.")             raise TypeError("the loop must contain at least three Curves.")
413         super(RuledSurface, self).__init__(loop)         super(RuledSurface, self).__init__(loop)
414      def __neg__(self):      def __add__(self,other):
415         return RuledSurface(-self.getBoundaryLoop())         return RuledSurface(self.getBoundaryLoop()+other)
416        def getGmshCommand(self):
417            return "Ruled Surface(%s) = {%s};"%(self.getID(),self.getBoundaryLoop().getID())
418    
419  class SurfaceLoop(Elementary):  class SurfaceLoop(Primitive):
420      """      """
421      a surface loop. It defines the shell of a volume.      a surface loop. It defines the shell of a volume.
422    
# Line 252  class SurfaceLoop(Elementary): Line 427  class SurfaceLoop(Elementary):
427         creates a surface loop         creates a surface loop
428         """         """
429         super(SurfaceLoop, self).__init__()         super(SurfaceLoop, self).__init__()
430         for i in surfaces:         self.__surfaces=[]
431             if not isinstance(surfaces[i],Curve):         self.addSurface(*surfaces)
432                raise TypeError("%s-th argument is not a Curve object.")      def addSurface(self,*surfaces):
433         self.__surfaces=surfaces         for i in range(len(surfaces)):
434               if not surfaces[i].isSurface():
435                  raise TypeError("%s-th argument is not a Surface object."%i)
436           self.__surfaces+=surfaces
437    
438        def isSurfaceLoop(self):
439            return True
440      def getSurfaces(self):      def getSurfaces(self):
441         return self.__surfaces         return self.__surfaces
442        def __add__(self,other):
443      def __neg__(self):         return SurfaceLoop([c+other for c in self.getSurfaces])
        return SurfaceLoop(-c for c in self.__surfaces[::-1])  
   
444      def __len__(self):      def __len__(self):
445         return len(self.__surfaces)         return len(self.__surfaces)
446        def getHistory(self):
447              out=set([self])
448              for i in self.getSurfaces(): out|=i.getHistory()
449              return out
450        def getPoints(self):
451              out=set()
452              for i in self.getSurfaces(): out|=i.getPoints()
453              return out
454        def getGmshCommand(self):
455            out=""
456            for i in self.getSurfaces():
457                if len(out)>0:
458                    out+=", %s"%i.getID()
459                else:
460                    out="%s"%i.getID()
461            return "Surface Loop(%s) = {%s};"%(self.getID(),out)
462    
463  class Volume(Elementary):  class Volume(Primitive):
464      """      """
465      a volume with holes.      a volume with holes.
466      """      """
# Line 280  class Volume(Elementary): Line 474  class Volume(Elementary):
474                A SurfaceLoop defining a hole should not have any surfaces in common with another SurfaceLoop defining a hole in the same volume.                A SurfaceLoop defining a hole should not have any surfaces in common with another SurfaceLoop defining a hole in the same volume.
475         """         """
476         super(Volume, self).__init__()         super(Volume, self).__init__()
477         if not isinstance(loop,SurfaceLoop):         if not loop.isSurfaceLoop():
478             raise TypeError("argument loop needs to be a SurfaceLoop object.")             raise TypeError("argument loop needs to be a SurfaceLoop object.")
479         for i in range(len(holes)):         for i in range(len(holes)):
480              if not isinstance(holes[i],SurfaceLoop):              if not holes[i].isSurfaceLoop():
481                   raise TypeError("%i th hole needs to be a SurfaceLoop object.")                   raise TypeError("%i th hole needs to be a SurfaceLoop object.")
482         self.__loop=loop         self.__loop=loop
483         self.__holes=holes         self.__holes=holes
# Line 291  class Volume(Elementary): Line 485  class Volume(Elementary):
485         return self.__holes         return self.__holes
486      def getSurfaceLoop(self):      def getSurfaceLoop(self):
487         return self.__loop         return self.__loop
488      def __neg__(self):      def __add__(self,other):
489         return PlaneSurface(-self.getSurfaceLoop(),holes=[-h for h in self.getHoles()] )         return Volume(self.getSurfaceLoop()+other, holes=[h+other for h in self.getHoles()])
490        def getHistory(self):
491            out=set([self]) | self.getSurfaceLoop().getHistory()
492            for i in self.getHoles(): out|=i.getHistory()
493            return out
494        def getPoints(self):
495            out=self.getSurfaceLoop().getPoints()
496            for i in self.getHoles(): out|=i.Points()
497            return out
498        def getGmshCommand(self):
499            out=""
500            for i in self.getHoles():
501                if len(out)>0:
502                    out+=", %s"%i.getID()
503                else:
504                    out="%s"%i.getID()
505            if len(out)>0:
506              return "Volume(%s) = {%s, %s};"%(self.getID(),self.getSurfaceLoop().getID(), out)
507            else:
508              return "Volume(%s) = {%s};"%(self.getID(),self.getSurfaceLoop().getID())
509    
510  class PropertySet(Elementary):  class PropertySet(Primitive):
511      """      """
512      defines a group L{Elementary} objects.      defines a group L{Primitive} objects.
513      """      """
514      def __init__(self,tag=None,*items):      def __init__(self,tag=None,*items):
515         super(PropertySet, self).__init__()         super(PropertySet, self).__init__()
516         self.__items=items         self.__items=items
517         self.__tag=tag         self.__tag=tag
518        def getHistory(self):
519            out=set([self, self.getBoundaryLoop().getHistory()])
520            for i in self.getHoles(): out|=i.getHistory()
521            return out
522    
523    class PrimitiveStack(object):
524          def __init__(self,*items):
525            self.__prims=set()
526            for i in items:
527                self.__prims|=i.getHistory()
528            self.__prims=list(self.__prims)
529            self.__prims.sort()
530    
531          def getGmshCommands(self):
532            out=""
533            for i in self.__prims:
534               out+=i.getGmshCommand()+"\n"
535            return out

Legend:
Removed from v.898  
changed lines
  Added in v.902

  ViewVC Help
Powered by ViewVC 1.1.26