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

revision 1270 by gross, Thu Aug 23 03:13:11 2007 UTC revision 1312 by ksteube, Mon Sep 24 06:18:44 2007 UTC
# Line 1  Line 1
1  # \$Id:\$  #
2    # \$Id\$
3    #
4    #######################################################
5    #
6    #           Copyright 2003-2007 by ACceSS MNRF
7    #       Copyright 2007 by University of Queensland
8    #
9    #                http://esscc.uq.edu.au
10    #        Primary Business: Queensland, Australia
11    #  Licensed under the Open Software License version 3.0
13    #
14    #######################################################
15    #
16
17  """  """
18  Geometrical Primitives  Geometrical Primitives
# Line 27  __date__="\$Date:\$" Line 41  __date__="\$Date:\$"
41
42  import numarray  import numarray
43  from transformations import _TYPE, Translation, Dilation, Transformation  from transformations import _TYPE, Translation, Dilation, Transformation
44    from math import sqrt
45
46
47  def resetGlobalPrimitiveIdCounter():  def resetGlobalPrimitiveIdCounter():
# Line 613  class Arc(ArcBase, Primitive): Line 628  class Arc(ArcBase, Primitive):
628         if not isinstance(center,Point): raise TypeError("center needs to be a Point object.")         if not isinstance(center,Point): raise TypeError("center needs to be a Point object.")
629         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.")
630         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.")
631           if center.isColocated(end): raise TypeError("center and start point are colocated.")
632           if center.isColocated(start): raise TypeError("center end end point are colocated.")
633           if start.isColocated(end): raise TypeError("start and end are colocated.")
634         # TODO: check length of circle.         # TODO: check length of circle.
635         ArcBase.__init__(self)         ArcBase.__init__(self)
636         Primitive.__init__(self)         Primitive.__init__(self)
# Line 696  class ReverseArc(ArcBase, ReversePrimiti Line 714  class ReverseArc(ArcBase, ReversePrimiti
714         """         """
715         return self.getUnderlyingPrimitive().getCenterPoint()         return self.getUnderlyingPrimitive().getCenterPoint()
716
717    class EllipseBase(Manifold1D):
718        def __init__(self):
719              """
720              create ellipse
721              """
722              Manifold1D.__init__(self)
723        def collectPrimitiveBases(self):
724           """
725           returns the primitives used to construct the Curve
726           """
727           out=[self]
728           out+=self.getStartPoint().collectPrimitiveBases()
729           out+=self.getEndPoint().collectPrimitiveBases()
730           out+=self.getCenterPoint().collectPrimitiveBases()
731           out+=self.getPointOnMainAxis().collectPrimitiveBases()
732           return out
733
734
735    class Ellipse(EllipseBase, Primitive):
736        """
737        defines an ellipse which is strictly, smaller than Pi
738        """
739        def __init__(self,center,point_on_main_axis,start,end):
740           """
741           creates an arc by the start point, end point, the center and a point on a main axis.
742           """
743           if not isinstance(center,Point): raise TypeError("center needs to be a Point object.")
744           if not isinstance(end,Point): raise TypeError("end needs to be a Point object.")
745           if not isinstance(start,Point): raise TypeError("start needs to be a Point object.")
746           if not isinstance(point_on_main_axis,Point): raise TypeError("point on main axis needs to be a Point object.")
747           if center.isColocated(end): raise TypeError("center and start point are colocated.")
748           if center.isColocated(start): raise TypeError("center end end point are colocated.")
749           if center.isColocated(point_on_main_axis): raise TypeError("center and point on main axis are colocated.")
750           if start.isColocated(end): raise TypeError("start and end point are colocated.")
751           # TODO: check length of circle.
752           EllipseBase.__init__(self)
753           Primitive.__init__(self)
754           self.__center=center
755           self.__start=start
756           self.__end=end
757           self.__point_on_main_axis=point_on_main_axis
758
759        def __neg__(self):
760              """
761              returns a view onto the curve with reversed ordering
762              """
763              return ReverseEllipse(self)
764
765        def getStartPoint(self):
766           """
767           returns start point
768           """
769           return self.__start
770
771        def getEndPoint(self):
772           """
773           returns end point
774           """
775           return self.__end
776
777        def getCenterPoint(self):
778           """
779           returns center
780           """
781           return self.__center
782
783        def getPointOnMainAxis(self):
784           """
785           returns a point on a main axis
786           """
787           return self.__point_on_main_axis
788
789        def substitute(self,sub_dict):
790            """
791            returns a copy of self with substitutes for the primitives used to construct it given by the dictionary C{sub_dict}.
792            If a substitute for the object is given by C{sub_dict} the value is returned, otherwise a new instance
793            with substituted arguments is returned.
794            """
795            if not sub_dict.has_key(self):
796                sub_dict[self]=Ellipse(self.getCenterPoint().substitute(sub_dict),
797                                       self.getPointOnMainAxis().substitute(sub_dict),
798                                       self.getStartPoint().substitute(sub_dict),
799                                       self.getEndPoint().substitute(sub_dict))
800            return sub_dict[self]
801
802
803        def isColocated(self,primitive):
804           """
805           returns True curves are on the same position
806           """
807           if hasattr(primitive,"getUnderlyingPrimitive"):
808              if isinstance(primitive.getUnderlyingPrimitive(),Ellipse):
809                self_c=self.getCenterPoint().getCoordinates()
810                p=self.getPointOnMainAxis().getCoordinates()-self_c
811                q=primitive.getPointOnMainAxis().getCoordinates()-self_c
812                # are p and q orthogonal or collinear?
813                len_p=sqrt(p[0]**2+p[1]**2+p[2]**2)
814                len_q=sqrt(q[0]**2+q[1]**2+q[2]**2)
815                p_q= abs(p[0]*q[0]+p[1]*q[1]+p[2]*q[2])
816                return ((p_q <= getToleranceForColocation() * len_q * p_q) or \
817                                       (abs(p_q - len_q * p_q) <= getToleranceForColocation())) and \
818                       self.getCenterPoint().isColocated(primitive.getCenterPoint()) and \
819                       (                                                                  \
820                            (self.getEndPoint().isColocated(primitive.getEndPoint()) and \
821                             self.getStartPoint().isColocated(primitive.getStartPoint()) ) \
822                                           or                                              \
823                             (self.getEndPoint().isColocated(primitive.getStartPoint()) and \
824                              self.getStartPoint().isColocated(primitive.getEndPoint()) ) \
825                       )
826           return False
827
828    class ReverseEllipse(EllipseBase, ReversePrimitive):
829        """
830        defines an arc which is strictly, smaller than Pi
831        """
832        def __init__(self,arc):
833           """
834           creates an instance of a reverse view to an ellipse
835           """
836           if not isinstance(arc, Ellipse):
837               raise TypeError("ReverseCurve needs to be an instance of Ellipse")
838           EllipseBase.__init__(self)
839           ReversePrimitive.__init__(self,arc)
840
841        def getStartPoint(self):
842           """
843           returns start point
844           """
845           return self.getUnderlyingPrimitive().getEndPoint()
846
847        def getEndPoint(self):
848           """
849           returns end point
850           """
851           return self.getUnderlyingPrimitive().getStartPoint()
852
853        def getCenterPoint(self):
854           """
855           returns center
856           """
857           return self.getUnderlyingPrimitive().getCenterPoint()
858
859        def getPointOnMainAxis(self):
860           """
861           returns a point on a main axis
862           """
863           return self.getUnderlyingPrimitive().getPointOnMainAxis()
864
865
866  class CurveLoop(Primitive, PrimitiveBase):  class CurveLoop(Primitive, PrimitiveBase):
867      """      """
868      An oriented loop of one-dimensional manifolds (= curves and arcs)      An oriented loop of one-dimensional manifolds (= curves and arcs)
# Line 758  class CurveLoop(Primitive, PrimitiveBase Line 925  class CurveLoop(Primitive, PrimitiveBase
925
926      def isColocated(self,primitive):      def isColocated(self,primitive):
927         """         """
928         returns True if each curve is collocted with a curve in primitive         returns True if each curve is colocted with a curve in primitive
929         """         """
930         if hasattr(primitive,"getUnderlyingPrimitive"):         if hasattr(primitive,"getUnderlyingPrimitive"):
931            if isinstance(primitive.getUnderlyingPrimitive(),CurveLoop):            if isinstance(primitive.getUnderlyingPrimitive(),CurveLoop):
# Line 766  class CurveLoop(Primitive, PrimitiveBase Line 933  class CurveLoop(Primitive, PrimitiveBase
933                  cp0=self.getCurves()                  cp0=self.getCurves()
934                  cp1=primitive.getCurves()                  cp1=primitive.getCurves()
935                  for c0 in cp0:                  for c0 in cp0:
936                      collocated = False                      colocated = False
937                      for c1 in cp1:                      for c1 in cp1:
938                           collocated = collocated or c0.isColocated(c1)                           colocated = colocated or c0.isColocated(c1)
939                      if not collocated: return False                      if not colocated: return False
940                  return True                  return True
941         return False         return False
942
# Line 864  class RuledSurface(Primitive, Manifold2D Line 1031  class RuledSurface(Primitive, Manifold2D
1031
1032      def isColocated(self,primitive):      def isColocated(self,primitive):
1033         """         """
1034         returns True if each curve is collocted with a curve in primitive         returns True if each curve is colocted with a curve in primitive
1035         """         """
1036         if hasattr(primitive,"getUnderlyingPrimitive"):         if hasattr(primitive,"getUnderlyingPrimitive"):
1037            if isinstance(primitive.getUnderlyingPrimitive(),RuledSurface):            if isinstance(primitive.getUnderlyingPrimitive(),RuledSurface):
# Line 924  class PlaneSurface(Primitive, Manifold2D Line 1091  class PlaneSurface(Primitive, Manifold2D
1091         """         """
1092         if not isinstance(loop.getUnderlyingPrimitive(),CurveLoop):         if not isinstance(loop.getUnderlyingPrimitive(),CurveLoop):
1093             raise TypeError("argument loop needs to be a CurveLoop object.")             raise TypeError("argument loop needs to be a CurveLoop object.")
# for l in loop.getCurves():
#     if not isinstance(l.getUnderlyingPrimitive(),Line):
#       raise TypeError("loop may be formed by Lines only.")
1094         for i in range(len(holes)):         for i in range(len(holes)):
1095              if not isinstance(holes[i].getUnderlyingPrimitive(), CurveLoop):              if not isinstance(holes[i].getUnderlyingPrimitive(), CurveLoop):
1096                   raise TypeError("%i-th hole needs to be a CurveLoop object.")                   raise TypeError("%i-th hole needs to be a CurveLoop object.")
#      for l in holes[i].getCurves():
#         if not isinstance(l.getUnderlyingPrimitive(),Line):
#            raise TypeError("holes may be formed by Lines only.")
1097         #TODO: check if lines and holes are in a plane         #TODO: check if lines and holes are in a plane
1098         #TODO: are holes really holes?         #TODO: are holes really holes?
1099         Primitive.__init__(self)         Primitive.__init__(self)
# Line 963  class PlaneSurface(Primitive, Manifold2D Line 1124  class PlaneSurface(Primitive, Manifold2D
1124
1125      def isColocated(self,primitive):      def isColocated(self,primitive):
1126         """         """
1127         returns True if each curve is collocted with a curve in primitive         returns True if each curve is colocted with a curve in primitive
1128         """         """
1129         if hasattr(primitive,"getUnderlyingPrimitive"):         if hasattr(primitive,"getUnderlyingPrimitive"):
1130            if isinstance(primitive.getUnderlyingPrimitive(),PlaneSurface):            if isinstance(primitive.getUnderlyingPrimitive(),PlaneSurface):
# Line 972  class PlaneSurface(Primitive, Manifold2D Line 1133  class PlaneSurface(Primitive, Manifold2D
1133                  hs1=primitive.getHoles()                  hs1=primitive.getHoles()
1134                  if len(hs0) == len(hs1):                  if len(hs0) == len(hs1):
1135                      for h0 in hs0:                      for h0 in hs0:
1136                         collocated = False                         colocated = False
1137                         for h1 in hs1:                         for h1 in hs1:
1138                           collocated = collocated or h0.isColocated(h1)                           colocated = colocated or h0.isColocated(h1)
1139                         if not collocated: return False                         if not colocated: return False
1140                      return True                      return True
1141         return False         return False
1142      def collectPrimitiveBases(self):      def collectPrimitiveBases(self):
# Line 1091  class SurfaceLoop(Primitive, PrimitiveBa Line 1252  class SurfaceLoop(Primitive, PrimitiveBa
1252
1253      def isColocated(self,primitive):      def isColocated(self,primitive):
1254         """         """
1255         returns True if each surface is collocted with a curve in primitive and vice versa.         returns True if each surface is colocted with a curve in primitive and vice versa.
1256         """         """
1257         if hasattr(primitive,"getUnderlyingPrimitive"):         if hasattr(primitive,"getUnderlyingPrimitive"):
1258           if isinstance(primitive.getUnderlyingPrimitive(),SurfaceLoop):           if isinstance(primitive.getUnderlyingPrimitive(),SurfaceLoop):
# Line 1099  class SurfaceLoop(Primitive, PrimitiveBa Line 1260  class SurfaceLoop(Primitive, PrimitiveBa
1260                  sp0=self.getSurfaces()                  sp0=self.getSurfaces()
1261                  sp1=primitive.getSurfaces()                  sp1=primitive.getSurfaces()
1262                  for s0 in sp0:                  for s0 in sp0:
1263                      collocated = False                      colocated = False
1264                      for s1 in sp1:                      for s1 in sp1:
1265                           collocated = collocated or s0.isColocated(s1)                           colocated = colocated or s0.isColocated(s1)
1266                      if not collocated: return False                      if not colocated: return False
1267                  return True                  return True
1268         return False         return False
1269
# Line 1195  class Volume(Manifold3D, Primitive): Line 1356  class Volume(Manifold3D, Primitive):
1356
1357      def isColocated(self,primitive):      def isColocated(self,primitive):
1358         """         """
1359         returns True if each curve is collocted with a curve in primitive         returns True if each curve is colocted with a curve in primitive
1360         """         """
1361         if hasattr(primitive,"getUnderlyingPrimitive"):         if hasattr(primitive,"getUnderlyingPrimitive"):
1362            if isinstance(primitive.getUnderlyingPrimitive(),Volume):            if isinstance(primitive.getUnderlyingPrimitive(),Volume):
# Line 1204  class Volume(Manifold3D, Primitive): Line 1365  class Volume(Manifold3D, Primitive):
1365                  hs1=primitive.getHoles()                  hs1=primitive.getHoles()
1366                  if len(hs0) == len(hs1):                  if len(hs0) == len(hs1):
1367                      for h0 in hs0:                      for h0 in hs0:
1368                         collocated = False                         colocated = False
1369                         for h1 in hs1:                         for h1 in hs1:
1370                           collocated = collocated or h0.isColocated(h1)                           colocated = colocated or h0.isColocated(h1)
1371                         if not collocated: return False                         if not colocated: return False
1372                      return True                      return True
1373         return False         return False
1374      def collectPrimitiveBases(self):      def collectPrimitiveBases(self):

Legend:
 Removed from v.1270 changed lines Added in v.1312