/[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 929 by gross, Wed Jan 17 07:41:13 2007 UTC revision 931 by gross, Fri Jan 19 03:06:33 2007 UTC
# Line 169  class PrimitiveBase(object): Line 169  class PrimitiveBase(object):
169          out.modifyBy(transformation)          out.modifyBy(transformation)
170          return out          return out
171    
   
   
172  class Primitive(object):  class Primitive(object):
173      """      """
174      A general primitive      A general primitive
# Line 203  class Primitive(object): Line 201  class Primitive(object):
201          returns the underlying primitive          returns the underlying primitive
202          """          """
203          return self          return self
204        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    
210      def __neg__(self):      def __neg__(self):
211          """          """
# Line 271  class ReversePrimitive(object): Line 274  class ReversePrimitive(object):
274          """          """
275          return self.__primitive          return self.__primitive
276    
277        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      def __repr__(self):      def __repr__(self):
284         return "-%s(%s)"%(self.__primitive.__class__.__name__,self.getID())         return "-%s(%s)"%(self.__primitive.__class__.__name__,self.getID())
285    
# Line 427  class Manifold1D(PrimitiveBase): Line 436  class Manifold1D(PrimitiveBase):
436           returns end point           returns end point
437           """           """
438           raise NotImplementedError()           raise NotImplementedError()
439        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    
445  class CurveBase(Manifold1D):  class CurveBase(Manifold1D):
446      """      """
# Line 471  class Curve(CurveBase, Primitive): Line 485  class Curve(CurveBase, Primitive):
485         defines a curve form control points         defines a curve form control points
486         """         """
487         if len(points)<2:         if len(points)<2:
488             raise TypeError("Curve needs at least two points")             raise ValueError("Curve needs at least two points")
489         i=0         i=0
490         for p in points:         for p in points:
491                i+=1                i+=1
# Line 516  class Curve(CurveBase, Primitive): Line 530  class Curve(CurveBase, Primitive):
530         """         """
531         returns True curves are on the same position         returns True curves are on the same position
532         """         """
533         if isinstance(primitive.getUnderlyingPrimitive(),self.__class__):         if hasattr(primitive,"getUnderlyingPrimitive"):
534            if len(primitive) == len(self):           if isinstance(primitive.getUnderlyingPrimitive(),self.__class__):
535               if len(primitive) == len(self):
536               cp0=self.getControlPoints()               cp0=self.getControlPoints()
537               cp1=primitive.getControlPoints()               cp1=primitive.getControlPoints()
538               match=True               match=True
# Line 530  class Curve(CurveBase, Primitive): Line 545  class Curve(CurveBase, Primitive):
545                     if not cp0[i].isColocated(cp1[len(cp0)-1-i]):                     if not cp0[i].isColocated(cp1[len(cp0)-1-i]):
546                        return False                        return False
547               return True               return True
548            else:         return False
              return False  
        else:  
           return False  
549    
550  class ReverseCurve(CurveBase, ReversePrimitive):  class ReverseCurve(CurveBase, ReversePrimitive):
551      """      """
# Line 707  class Arc(ArcBase, Primitive): Line 719  class Arc(ArcBase, Primitive):
719         """         """
720         returns True curves are on the same position         returns True curves are on the same position
721         """         """
722         if isinstance(primitive.getUnderlyingPrimitive(),Arc):         if hasattr(primitive,"getUnderlyingPrimitive"):
723              if isinstance(primitive.getUnderlyingPrimitive(),Arc):
724              return (self.getCenterPoint().isColocated(primitive.getCenterPoint())) and ( \              return (self.getCenterPoint().isColocated(primitive.getCenterPoint())) and ( \
725                     (self.getEndPoint().isColocated(primitive.getEndPoint()) and self.getStartPoint().isColocated(primitive.getStartPoint()) ) \                     (self.getEndPoint().isColocated(primitive.getEndPoint()) and self.getStartPoint().isColocated(primitive.getStartPoint()) ) \
726                  or (self.getEndPoint().isColocated(primitive.getStartPoint()) and self.getStartPoint().isColocated(primitive.getEndPoint()) ) )                  or (self.getEndPoint().isColocated(primitive.getStartPoint()) and self.getStartPoint().isColocated(primitive.getEndPoint()) ) )
727         else:         return False
           return False  
728    
729  class ReverseArc(ArcBase, ReversePrimitive):  class ReverseArc(ArcBase, ReversePrimitive):
730      """      """
# Line 747  class ReverseArc(ArcBase, ReversePrimiti Line 759  class ReverseArc(ArcBase, ReversePrimiti
759    
760  class CurveLoop(Primitive, PrimitiveBase):  class CurveLoop(Primitive, PrimitiveBase):
761      """      """
762      An oriented loop of 1D primitives (= curves and arcs)      An oriented loop of one-dimensional manifolds (= curves and arcs)
763    
764      The loop must be closed and the L{Manifold1D}s should be oriented consistently.      The loop must be closed and the L{Manifold1D}s should be oriented consistently.
765      """      """
# Line 755  class CurveLoop(Primitive, PrimitiveBase Line 767  class CurveLoop(Primitive, PrimitiveBase
767         """         """
768         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.
769         """         """
        Primitive.__init__(self)  
        PrimitiveBase.__init__(self)  
770         if len(curves)<2:         if len(curves)<2:
771              raise TypeError("at least two curves have to be given.")              raise ValueError("at least two curves have to be given.")
772         for i in range(len(curves)):         for i in range(len(curves)):
773             if not isinstance(curves[i],Manifold1D):             if not isinstance(curves[i],Manifold1D):
774                raise TypeError("%s-th argument is not a Manifold1D object."%i)                raise TypeError("%s-th argument is not a Manifold1D object."%i)
# Line 779  class CurveLoop(Primitive, PrimitiveBase Line 789  class CurveLoop(Primitive, PrimitiveBase
789               raise ValueError("loop is not closed.")               raise ValueError("loop is not closed.")
790         if not self.__curves[0].getStartPoint() == self.__curves[-1].getEndPoint():         if not self.__curves[0].getStartPoint() == self.__curves[-1].getEndPoint():
791            raise ValueError("loop is not closed.")            raise ValueError("loop is not closed.")
792           Primitive.__init__(self)
793           PrimitiveBase.__init__(self)
794    
795      def getCurves(self):      def getCurves(self):
796         """         """
# Line 823  class CurveLoop(Primitive, PrimitiveBase Line 835  class CurveLoop(Primitive, PrimitiveBase
835         """         """
836         returns True if each curve is collocted with a curve in primitive         returns True if each curve is collocted with a curve in primitive
837         """         """
838         if isinstance(primitive,CurveLoop):         if hasattr(primitive,"getUnderlyingPrimitive"):
839            if len(primitive) == len(self):            if isinstance(primitive.getUnderlyingPrimitive(),CurveLoop):
840               cp0=self.getCurves()               if len(primitive) == len(self):
841               cp1=primitive.getCurves()                  cp0=self.getCurves()
842               for c0 in cp0:                  cp1=primitive.getCurves()
843                   collocated = False                  for c0 in cp0:
844                   for c1 in cp1:                      collocated = False
845                        collocated = collocated or c0.isColocated(c1)                      for c1 in cp1:
846                   if not collocated: return False                           collocated = collocated or c0.isColocated(c1)
847               return True                      if not collocated: return False
848            else:                  return True
849               return False         return False
        else:  
           return False  
850    
851      def getGmshCommand(self,scaling_factor=1.):      def getGmshCommand(self,scaling_factor=1.):
852          """          """
# Line 852  class CurveLoop(Primitive, PrimitiveBase Line 862  class CurveLoop(Primitive, PrimitiveBase
862    
863  class ReverseCurveLoop(ReversePrimitive, PrimitiveBase):  class ReverseCurveLoop(ReversePrimitive, PrimitiveBase):
864      """      """
865      An oriented loop of 1D primitives (= curves and arcs)      An oriented loop of one-dimensional manifolds (= curves and arcs)
866    
867      The loop must be closed and the L{Manifold1D}s should be oriented consistently.      The loop must be closed and the one-dimensional manifolds should be oriented consistently.
868      """      """
869      def __init__(self,curve_loop):      def __init__(self,curve_loop):
870         """         """
871         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.
872         """         """
873         if not isinstance(curve_loop, CurveLoop):         if not isinstance(curve_loop, CurveLoop):
874             raise ValueError("arguments need to be an instance of CurveLoop.")             raise TypeError("arguments need to be an instance of CurveLoop.")
875         ReversePrimitive.__init__(self, curve_loop)         ReversePrimitive.__init__(self, curve_loop)
876         PrimitiveBase.__init__(self)         PrimitiveBase.__init__(self)
877    
# Line 874  class ReverseCurveLoop(ReversePrimitive, Line 884  class ReverseCurveLoop(ReversePrimitive,
884      def __len__(self):      def __len__(self):
885          return len(self.getUnderlyingPrimitive())          return len(self.getUnderlyingPrimitive())
886    
887  class PrimitiveBase2D(PrimitiveBase):  #=
888    class Manifold2D(PrimitiveBase):
889      """      """
890      general two-dimensional primitive      general two-dimensional manifold
891      """      """
892      def __init__(self):      def __init__(self):
           """  
           create a two-dimensional primitive  
           """  
           super(PrimitiveBase2D, self).__init__()  
   
     def getBoundary(self):  
         """  
         returns a list of the 1D primitives forming the boundary of the Surface (including holes)  
         """  
         out=[]  
         for i in self.getPrimitives():  
              if isinstance(i, Manifold1D): out.append(i)  
         return out  
   
     def getBoundary(self):  
         """  
         returns a list of the 1D primitives forming the boundary of the Surface (including holes)  
         """  
         out=[]  
         for i in self.getPrimitives():  
              if isinstance(i, Manifold1D): out.append(i)  
         return out  
   
     def getBoundaryLoop(self):  
         """  
         returns the loop defining the outer boundary  
         """  
         raise NotImplementedError("getBoundaryLoop is not implemented for this class %s."%self.__class__.__name__)  
   
     def getHoles(self):  
893         """         """
894         returns the holes         create a two-dimensional manifold
895         """         """
896         raise NotImplementedError("getHoles is not implemented for this class %s."%self.__class__.__name__)         PrimitiveBase.__init__(self)
897    
898      def collectPrimitiveBases(self):      def getBoundary(self):
899          """          """
900          returns primitives used to construct the Surface          returns a list of the one-dimensional manifolds forming the boundary of the Surface (including holes)
901          """          """
902          out=[self] + self.getBoundaryLoop().collectPrimitiveBases()          raise NotImplementedError()
         for i in self.getHoles(): out+=i.collectPrimitiveBases()  
         return out  
903    
904  class RuledSurface(PrimitiveBase2D):  class RuledSurface(Primitive, Manifold2D):
905      """      """
906      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
907      """      """
# Line 932  class RuledSurface(PrimitiveBase2D): Line 911  class RuledSurface(PrimitiveBase2D):
911    
912         @param loop: L{CurveLoop} defining the boundary of the surface.         @param loop: L{CurveLoop} defining the boundary of the surface.
913         """         """
914         super(RuledSurface, self).__init__()         if not isinstance(loop.getUnderlyingPrimitive(),CurveLoop):
        if not isinstance(loop,CurveLoop):  
915             raise TypeError("argument loop needs to be a CurveLoop object.")             raise TypeError("argument loop needs to be a CurveLoop object.")
916         if len(loop)<2:         if len(loop)<2:
917             raise TypeError("the loop must contain at least two Curves.")             raise ValueError("the loop must contain at least two Curves.")
918         if len(loop)>4:         if len(loop)>4:
919             raise TypeError("the loop must contain at least three Curves.")             raise ValueError("the loop must contain at least three Curves.")
920           Primitive.__init__(self)
921           Manifold2D.__init__(self)
922         self.__loop=loop         self.__loop=loop
923    
924        def __neg__(self):
925              """
926              returns a view onto the suface with reversed ordering
927              """
928              return ReverseRuledSurface(self)
929    
930      def getBoundaryLoop(self):      def getBoundaryLoop(self):
931          """          """
932          returns the loop defining the outer boundary          returns the loop defining the outer boundary
933          """          """
934          return self.__loop          return self.__loop
935    
936      def getHoles(self):      def getBoundary(self):
937          """          """
938          returns the holes          returns a list of the one-dimensional manifolds forming the boundary of the Surface (including holes)
939          """          """
940          return []          return self.getBoundaryLoop().getCurves()
941    
942      def getGmshCommand(self,scaling_factor=1.):      def getGmshCommand(self,scaling_factor=1.):
943          """          """
# Line 974  class RuledSurface(PrimitiveBase2D): Line 959  class RuledSurface(PrimitiveBase2D):
959         """         """
960         returns True if each curve is collocted with a curve in primitive         returns True if each curve is collocted with a curve in primitive
961         """         """
962         if isinstance(primitive,RuledSurface):         if hasattr(primitive,"getUnderlyingPrimitive"):
963            return self.getBoundaryLoop().isColocated(primitive.getBoundaryLoop())            if isinstance(primitive.getUnderlyingPrimitive(),RuledSurface):
964         else:               return self.getBoundaryLoop().isColocated(primitive.getBoundaryLoop())
965            return False         return False
966    
967        def collectPrimitiveBases(self):
968            """
969            returns primitives used to construct the Surface
970            """
971            return [self] + self.getBoundaryLoop().collectPrimitiveBases()
972    
973  def createRuledSurface(*curves):  def createRuledSurface(*curves):
974        """        """
# Line 985  def createRuledSurface(*curves): Line 976  def createRuledSurface(*curves):
976        """        """
977        return RuledSurface(CurveLoop(*curves))        return RuledSurface(CurveLoop(*curves))
978    
979  class PlaneSurface(PrimitiveBase2D):  
980    class ReverseRuledSurface(ReversePrimitive, Manifold2D):
981        """
982        creates a view onto a L{RuledSurface} but with the reverse orientation
983        """
984        def __init__(self,surface):
985           """
986           creates a polygon from a list of line curves. The curves must form a closed loop.
987           """
988           if not isinstance(surface, RuledSurface):
989               raise TypeError("arguments need to be an instance of CurveLoop.")
990           ReversePrimitive.__init__(self, surface)
991           Manifold2D.__init__(self)
992    
993        def getBoundaryLoop(self):
994           """
995           returns the CurveLoop defining the RuledSurface
996           """
997           return -self.getUnderlyingPrimitive().getBoundaryLoop()
998    
999        def getBoundary(self):
1000            """
1001            returns a list of the one-dimensional manifolds forming the boundary of the Surface (including holes)
1002            """
1003            return self.getBoundaryLoop().getCurves()
1004    #==============================
1005    class PlaneSurface(Primitive, Manifold2D):
1006      """      """
1007      a plane surface with holes      a plane surface with holes
1008      """      """
# Line 998  class PlaneSurface(PrimitiveBase2D): Line 1015  class PlaneSurface(PrimitiveBase2D):
1015         @note: A CurveLoop defining a hole should not have any lines in common with the exterior CurveLoop.           @note: A CurveLoop defining a hole should not have any lines in common with the exterior CurveLoop.  
1016                A CurveLoop defining a hole should not have any lines in common with another CurveLoop defining a hole in the same surface.                A CurveLoop defining a hole should not have any lines in common with another CurveLoop defining a hole in the same surface.
1017         """         """
1018         super(PlaneSurface, self).__init__()         if not isinstance(loop.getUnderlyingPrimitive(),CurveLoop):
        if not isinstance(loop,CurveLoop):  
1019             raise TypeError("argument loop needs to be a CurveLoop object.")             raise TypeError("argument loop needs to be a CurveLoop object.")
1020         for l in loop.getCurves():         for l in loop.getCurves():
1021             if not isinstance(l,Line):             if not isinstance(l.getUnderlyingPrimitive(),Line):
1022               raise TypeError("loop may be formed by Lines only.")               raise TypeError("loop may be formed by Lines only.")
1023         for i in range(len(holes)):         for i in range(len(holes)):
1024              if not isinstance(holes[i], CurveLoop):              if not isinstance(holes[i].getUnderlyingPrimitive(), CurveLoop):
1025                   raise TypeError("%i-th hole needs to be a CurveLoop object.")                   raise TypeError("%i-th hole needs to be a CurveLoop object.")
1026              for l in holes[i].getCurves():              for l in holes[i].getCurves():
1027                 if not isinstance(l,Line):                 if not isinstance(l.getUnderlyingPrimitive(),Line):
1028                    raise TypeError("holes may be formed by Lines only.")                    raise TypeError("holes may be formed by Lines only.")
1029         #TODO: check if lines and holes are in a plane         #TODO: check if lines and holes are in a plane
1030         #TODO: are holes really holes?         #TODO: are holes really holes?
1031           Primitive.__init__(self)
1032           Manifold2D.__init__(self)
1033         self.__loop=loop         self.__loop=loop
1034         self.__holes=holes         self.__holes=holes
1035      def getHoles(self):      def getHoles(self):
# Line 1019  class PlaneSurface(PrimitiveBase2D): Line 1037  class PlaneSurface(PrimitiveBase2D):
1037         returns the holes         returns the holes
1038         """         """
1039         return self.__holes         return self.__holes
1040    
1041      def getBoundaryLoop(self):      def getBoundaryLoop(self):
1042          """          """
1043          returns the loop defining the boundary          returns the loop defining the boundary
# Line 1054  class PlaneSurface(PrimitiveBase2D): Line 1073  class PlaneSurface(PrimitiveBase2D):
1073         """         """
1074         returns True if each curve is collocted with a curve in primitive         returns True if each curve is collocted with a curve in primitive
1075         """         """
1076         if isinstance(primitive,PlaneSurface):         if hasattr(primitive,"getUnderlyingPrimitive"):
1077            if self.getBoundaryLoop().isColocated(primitive.getBoundaryLoop()):            if isinstance(primitive.getUnderlyingPrimitive(),PlaneSurface):
1078               hs0=self.getHoles()               if self.getBoundaryLoop().isColocated(primitive.getBoundaryLoop()):
1079               hs1=primitive.getHoles()                  hs0=self.getHoles()
1080               if len(hs0) == len(hs1):                  hs1=primitive.getHoles()
1081                   for h0 in hs0:                  if len(hs0) == len(hs1):
1082                      collocated = False                      for h0 in hs0:
1083                      for h1 in hs1:                         collocated = False
1084                        collocated = collocated or h0.isColocated(h1)                         for h1 in hs1:
1085                      if not collocated: return False                           collocated = collocated or h0.isColocated(h1)
1086                   return True                         if not collocated: return False
1087               return False                      return True
1088            else:         return False
1089               return False      def collectPrimitiveBases(self):
1090         else:          """
1091            return False          returns primitives used to construct the Surface
1092            """
1093            out=[self] + self.getBoundaryLoop().collectPrimitiveBases()
1094            for i in self.getHoles(): out+=i.collectPrimitiveBases()
1095            return out
1096        def __neg__(self):
1097              """
1098              returns a view onto the curve with reversed ordering
1099              """
1100              return ReversePlaneSurface(self)
1101        def getBoundary(self):
1102            """
1103            returns a list of the one-dimensional manifolds forming the boundary of the Surface (including holes)
1104            """
1105            out = []+ self.getBoundaryLoop().getCurves()
1106            for h in self.getHoles(): out+=h.getCurves()
1107            return out
1108    
1109  class SurfaceLoop(PrimitiveBase):  class ReversePlaneSurface(ReversePrimitive, Manifold2D):
1110        """
1111        creates a view onto a L{PlaneSurface} but with the reverse orientation
1112        """
1113        def __init__(self,surface):
1114           """
1115           creates a polygon from a list of line curves. The curves must form a closed loop.
1116           """
1117           if not isinstance(surface, PlaneSurface):
1118               raise TypeError("arguments need to be an instance of PlaneSurface.")
1119           ReversePrimitive.__init__(self, surface)
1120           Manifold2D.__init__(self)
1121    
1122        def getBoundaryLoop(self):
1123           """
1124           returns the CurveLoop defining the RuledSurface
1125           """
1126           return -self.getUnderlyingPrimitive().getBoundaryLoop()
1127    
1128        def getHoles(self):
1129            """
1130            returns a list of the one-dimensional manifolds forming the boundary of the Surface (including holes)
1131            """
1132            return [ -h for h in self.getUnderlyingPrimitive().getHoles() ]
1133    
1134        def getBoundary(self):
1135            """
1136            returns a list of the one-dimensional manifolds forming the boundary of the Surface (including holes)
1137            """
1138            out = [] + self.getBoundaryLoop().getCurves()
1139            for h in self.getHoles(): out+=h.getCurves()
1140            return out
1141    
1142    
1143    #=========================================================================
1144    class SurfaceLoop(Primitive, PrimitiveBase):
1145      """      """
1146      a loop of 2D primitives. It defines the shell of a volume.      a loop of 2D primitives. It defines the shell of a volume.
1147    
# Line 1081  class SurfaceLoop(PrimitiveBase): Line 1151  class SurfaceLoop(PrimitiveBase):
1151         """         """
1152         creates a surface loop         creates a surface loop
1153         """         """
        super(SurfaceLoop, self).__init__()  
1154         if len(surfaces)<2:         if len(surfaces)<2:
1155              raise TypeError("at least two surfaces have to be given.")              raise ValueError("at least two surfaces have to be given.")
1156         for i in range(len(surfaces)):         for i in range(len(surfaces)):
1157             if not isinstance(surfaces[i],PrimitiveBase2D):             if not isinstance(surfaces[i].getUnderlyingPrimitive(),Manifold2D):
1158                raise TypeError("%s-th argument is not a PrimitiveBase2D object."%i)                raise TypeError("%s-th argument is not a Manifold2D object."%i)
1159           Primitive.__init__(self)
1160           PrimitiveBase.__init__(self)
1161         # for the curves a loop:         # for the curves a loop:
1162         used=[ True for s in surfaces]         used=[ False for s in surfaces]
1163         self.__surfaces=[surfaces[0]]         self.__surfaces=[surfaces[0]]
1164         edges=[ e in surfaces[0].getBoundary() ]         used[0]= True
1165         used_edges=[ False in surfaces[0].getBoundary() ]         edges=[ e for e in surfaces[0].getBoundary() ]
1166         while min(used):         used_edges=[ False for e in surfaces[0].getBoundary() ]
1167           while not min(used):
1168            found=False            found=False
1169            for i in xrange(len(surfaces)):            for i in xrange(len(surfaces)):
1170               if not used[i]:               if not used[i]:
1171                  i_boundary=surfaces[i].getBoundary()                  i_boundary=surfaces[i].getBoundary()
1172                  for ib in xrange(i_boundary):                    for ib in xrange(len(i_boundary)):  
1173                      if i_boundary[ib] in edges:                      if i_boundary[ib] in edges:
                          if used_edges[edges.index(i_boundary[ib])]:  
                             raise TypeError("boundary segment %s is shared by more than one surface."%str(i_boundary[ib]))  
                          used_edges[edges.index(i_boundary[ib])]=True  
                          self.__surfaces.append(surfaces[i])  
                          for b in i_boundary:  
                             if not b in edges:  
                                 edges.append(b)  
                                 used_edges.append(False)  
1174                           found=True                           found=True
                          used[i]=True  
1175                           break                           break
1176               if found: break                  if found:
1177                        used[i]=True
1178                        self.__surfaces.append(surfaces[i])
1179                        for ib in xrange(len(i_boundary)):  
1180                           if i_boundary[ib] in edges:
1181                             if used_edges[edges.index(i_boundary[ib])]:
1182                                raise ValueError("boundary segment %s is shared by more than one surface."%str(i_boundary[ib].getUnderlyingPrimitive()))
1183                             used_edges[edges.index(i_boundary[ib])]=True
1184                           else:
1185                             edges.append(i_boundary[ib])
1186                             used_edges.append(False)
1187                        break
1188            if not found:            if not found:
1189               raise ValueError("loop is not closed.")                 raise ValueError("loop is not closed.")
1190         if min(used_edges):         if not min(used_edges):
1191            raise ValueError("loop is not closed. Surface is missing.")            raise ValueError("loop is not closed. Surface is missing.")
1192      def __len__(self):      def __len__(self):
1193         """         """
# Line 1121  class SurfaceLoop(PrimitiveBase): Line 1195  class SurfaceLoop(PrimitiveBase):
1195         """         """
1196         return len(self.__surfaces)         return len(self.__surfaces)
1197    
1198        def __neg__(self):
1199           """
1200           returns a view onto the curve with reversed ordering
1201           """
1202           return ReverseSurfaceLoop(self)
1203    
1204      def getSurfaces(self):      def getSurfaces(self):
1205         """         """
1206         returns the surfaces defining the SurfaceLoop         returns the surfaces defining the SurfaceLoop
1207         """         """
1208         return self.__curves         return self.__surfaces
1209    
1210      def collectPrimitiveBases(self):      def collectPrimitiveBases(self):
1211         """         """
# Line 1134  class SurfaceLoop(PrimitiveBase): Line 1214  class SurfaceLoop(PrimitiveBase):
1214         out=[self]         out=[self]
1215         for c in self.getSurfaces(): out+=c.collectPrimitiveBases()         for c in self.getSurfaces(): out+=c.collectPrimitiveBases()
1216         return out         return out
1217    
1218      def getGmshCommand(self,scaling_factor=1.):      def getGmshCommand(self,scaling_factor=1.):
1219          """          """
1220          returns the Gmsh command(s) to create the primitive          returns the Gmsh command(s) to create the primitive
# Line 1145  class SurfaceLoop(PrimitiveBase): Line 1226  class SurfaceLoop(PrimitiveBase):
1226              else:              else:
1227                  out="%s"%i.getDirectedID()                  out="%s"%i.getDirectedID()
1228          return "Surface Loop(%s) = {%s};"%(self.getID(),out)          return "Surface Loop(%s) = {%s};"%(self.getID(),out)
1229    
1230      def substitute(self,sub_dict):      def substitute(self,sub_dict):
1231          """          """
1232          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 1153  class SurfaceLoop(PrimitiveBase): Line 1235  class SurfaceLoop(PrimitiveBase):
1235          """          """
1236          if not sub_dict.has_key(self):          if not sub_dict.has_key(self):
1237              new_s=[]              new_s=[]
1238              for s in self.getCurves(): new_s.append(s.substitute(sub_dict))              for s in self.getSurfaces(): new_s.append(s.substitute(sub_dict))
1239              sub_dict[self]=SurfaceLoop(*tuple(new_s))              sub_dict[self]=SurfaceLoop(*tuple(new_s))
1240          return sub_dict[self]          return sub_dict[self]
1241    
# Line 1161  class SurfaceLoop(PrimitiveBase): Line 1243  class SurfaceLoop(PrimitiveBase):
1243         """         """
1244         returns True if each surface is collocted with a curve in primitive and vice versa.         returns True if each surface is collocted with a curve in primitive and vice versa.
1245         """         """
1246         if isinstance(primitive,SurfaceLoop):         if hasattr(primitive,"getUnderlyingPrimitive"):
1247           if len(primitive) == len(self):           if isinstance(primitive.getUnderlyingPrimitive(),SurfaceLoop):
1248               sp0=self.getSurfaces()              if len(primitive) == len(self):
1249               sp1=primitive.getCurves()                  sp0=self.getSurfaces()
1250               for s0 in sp0:                  sp1=primitive.getSurfaces()
1251                   collocated = False                  for s0 in sp0:
1252                   for s1 in sp1:                      collocated = False
1253                        collocated = collocated or s0.isColocated(s1)                      for s1 in sp1:
1254                   if not collocated: return False                           collocated = collocated or s0.isColocated(s1)
1255               return True                      if not collocated: return False
1256           else:                  return True
1257               return False         return False
1258         else:  
1259           return False  class ReverseSurfaceLoop(ReversePrimitive, PrimitiveBase):
1260        """
1261        a view to SurfaceLoop with reverse orientaion
1262    
1263        The loop must represent a closed shell, and the primitives should be oriented consistently.
1264        An oriented loop of 2-dimensional manifolds (= RuledSurface, PlaneSurface)
1265    
1266        The loop must be closed and the one-dimensional manifolds should be oriented consistently.
1267        """
1268        def __init__(self,surface_loop):
1269           """
1270           creates a polygon from a list of line surfaces. The curves must form a closed loop.
1271           """
1272           if not isinstance(surface_loop, SurfaceLoop):
1273               raise TypeError("arguments need to be an instance of SurfaceLoop.")
1274           ReversePrimitive.__init__(self, surface_loop)
1275           PrimitiveBase.__init__(self)
1276    
1277        def getSurfaces(self):
1278           """
1279           returns the surfaces defining the SurfaceLoop
1280           """
1281           return [ -s for s in  self.getUnderlyingPrimitive().getSurfaces() ]
1282    
1283        def __len__(self):
1284            return len(self.getUnderlyingPrimitive())
1285    
1286  #==========================  #==============================
1287  class Volume(PrimitiveBase):  class Manifold3D(PrimitiveBase):
1288        """
1289        general three-dimensional manifold
1290        """
1291        def __init__(self):
1292           """
1293           create a three-dimensional manifold
1294           """
1295           PrimitiveBase.__init__(self)
1296    
1297        def getBoundary(self):
1298            """
1299            returns a list of the one-dimensional manifolds forming the boundary of the volume (including holes)
1300            """
1301            raise NotImplementedError()
1302    
1303    class Volume(Manifold3D, Primitive):
1304      """      """
1305      a volume with holes.      a volume with holes.
1306      """      """
# Line 1190  class Volume(PrimitiveBase): Line 1313  class Volume(PrimitiveBase):
1313         @note: A SurfaceLoop defining a hole should not have any surfaces in common with the exterior SurfaceLoop.           @note: A SurfaceLoop defining a hole should not have any surfaces in common with the exterior SurfaceLoop.  
1314                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.
1315         """         """
1316         super(Volume, self).__init__()         if not isinstance(loop.getUnderlyingPrimitive(), SurfaceLoop):
        if not loop.isSurfaceLoop():  
1317             raise TypeError("argument loop needs to be a SurfaceLoop object.")             raise TypeError("argument loop needs to be a SurfaceLoop object.")
1318         for i in range(len(holes)):         for i in range(len(holes)):
1319              if not holes[i].isSurfaceLoop():              if not isinstance(holes[i].getUnderlyingPrimitive(), SurfaceLoop):
1320                   raise TypeError("%i th hole needs to be a SurfaceLoop object.")                   raise TypeError("%i th hole needs to be a SurfaceLoop object.")
1321           Primitive.__init__(self)
1322           Manifold3D.__init__(self)
1323         self.__loop=loop         self.__loop=loop
1324         self.__holes=holes         self.__holes=holes
1325      def getHoles(self):      def getHoles(self):
1326           """
1327           returns the hole in the volume
1328           """
1329         return self.__holes         return self.__holes
1330      def getSurfaceLoop(self):      def getSurfaceLoop(self):
1331           """
1332           returns the loop forming the surface
1333           """
1334         return self.__loop         return self.__loop
1335      def __add__(self,other):  
        return Volume(self.getSurfaceLoop()+other, holes=[h+other for h in self.getHoles()])  
     def collectPrimitiveBases(self):  
         out=[self] + self.getSurfaceLoop().collectPrimitiveBases()  
         for i in self.getHoles(): out+=i.collectPrimitiveBases()  
         return out  
     def getConstructionPoints(self):  
         out=self.getSurfaceLoop().getConstructionPoints()  
         for i in self.getHoles(): out|=i.Points()  
         return out  
1336      def getGmshCommand(self,scaling_factor=1.):      def getGmshCommand(self,scaling_factor=1.):
1337          """          """
1338          returns the Gmsh command(s) to create the primitive          returns the Gmsh command(s) to create the primitive
# Line 1227  class Volume(PrimitiveBase): Line 1348  class Volume(PrimitiveBase):
1348          else:          else:
1349            return "Volume(%s) = {%s};"%(self.getID(),self.getSurfaceLoop().getDirectedID())            return "Volume(%s) = {%s};"%(self.getID(),self.getSurfaceLoop().getDirectedID())
1350    
1351        def substitute(self,sub_dict):
1352            """
1353            returns a copy of self with substitutes for the primitives used to construct it given by the dictionary C{sub_dict}.
1354            If a substitute for the object is given by C{sub_dict} the value is returned, otherwise a new instance
1355            with substituted arguments is returned.
1356            """
1357            if not sub_dict.has_key(self):
1358                sub_dict[self]=Volume(self.getSurfaceLoop().substitute(sub_dict),[ h.substitute(sub_dict) for h in self.getHoles()])
1359            return sub_dict[self]
1360    
1361        def isColocated(self,primitive):
1362           """
1363           returns True if each curve is collocted with a curve in primitive
1364           """
1365           if hasattr(primitive,"getUnderlyingPrimitive"):
1366              if isinstance(primitive.getUnderlyingPrimitive(),Volume):
1367                 if self.getSurfaceLoop().isColocated(primitive.getSurfaceLoop()):
1368                    hs0=self.getHoles()
1369                    hs1=primitive.getHoles()
1370                    if len(hs0) == len(hs1):
1371                        for h0 in hs0:
1372                           collocated = False
1373                           for h1 in hs1:
1374                             collocated = collocated or h0.isColocated(h1)
1375                           if not collocated: return False
1376                        return True
1377           return False
1378        def collectPrimitiveBases(self):
1379            """
1380            returns primitives used to construct the Surface
1381            """
1382            out=[self] + self.getSurfaceLoop().collectPrimitiveBases()
1383            for i in self.getHoles(): out+=i.collectPrimitiveBases()
1384            return out
1385        def getBoundary(self):
1386            """
1387            returns a list of the one-dimensional manifolds forming the boundary of the Surface (including holes)
1388            """
1389            out = []+ self.getSurfaceLoop().getSurfaces()
1390            for h in self.getHoles(): out+=h.getSurfaces()
1391            return out
1392    
1393  class PropertySet(PrimitiveBase):  class PropertySet(PrimitiveBase):
1394      """      """
1395      defines a group L{PrimitiveBase} objects.      defines a group L{PrimitiveBase} objects.
# Line 1239  class PropertySet(PrimitiveBase): Line 1402  class PropertySet(PrimitiveBase):
1402          out=[self]+self.getBoundaryLoop().collectPrimitiveBases()          out=[self]+self.getBoundaryLoop().collectPrimitiveBases()
1403          for i in self.getHoles(): out+=i.collectPrimitiveBases()          for i in self.getHoles(): out+=i.collectPrimitiveBases()
1404          return out          return out
   
 class PrimitiveBaseStack(object):  
       def __init__(self,*items):  
         self.__prims=set()  
         for i in items:  
             self.__prims|=i.getPrimitives()  
         self.__prims=list(self.__prims)  
         self.__prims.sort()  
   
       def getGmshCommands(self,scaling_factor=1.):  
         out=""  
         for i in self.__prims:  
            out+=i.getGmshCommand(scaling_factor)+"\n"  
         return out  

Legend:
Removed from v.929  
changed lines
  Added in v.931

  ViewVC Help
Powered by ViewVC 1.1.26