Salome HOME
Unit tests:
[modules/shaper.git] / src / PythonAPI / model / sketcher / sketch.py
index a47759071958424249545130b616a119e324fbe4..5303f7df5c335e67554367d39c8ebc4241666953 100644 (file)
@@ -1,6 +1,28 @@
-"""Sketch Feature Interface
-Author: Daniel Brunier-Coulin with contribution by Mikhail Ponikarov
-Copyright (C) 2014-20xx CEA/DEN, EDF R&D
+# Author: Daniel Brunier-Coulin with contribution by Mikhail Ponikarov
+#         finalized by Renaud Nedelec and Sergey Pokhodenko
+# Copyright (C) 2014-20xx CEA/DEN, EDF R&D
+
+"""Sketcher interface.
+This interface allows to add a sketch
+in a part or partset.
+The created sketch object provides all the needed methods
+for sketch modification and constraint edition.
+
+Example of code:
+
+.. doctest::
+
+   >>> import model
+   >>> model.begin()
+   >>> partset = model.moduleDocument()
+   >>> part = model.addPart(partset).document()
+   >>> plane = model.defaultPlane("XOY")
+   >>> sketch = model.addSketch(part, plane)
+   >>> line = sketch.addLine(0, 0, 0, 1)
+   >>> line.endPoint().x()
+   0.0
+   >>> line.endPoint().y()
+   1.0
 """
 
 from ModelAPI import modelAPI_ResultConstruction, featureToCompositeFeature
@@ -11,23 +33,26 @@ from model.sketcher.point import Point
 from model.sketcher.line import Line
 from model.sketcher.circle import Circle
 from model.sketcher.arc import Arc
+from model.sketcher.mirror import Mirror
 from model.roots import Interface
 from model.tools import Selection
 
 
-def addSketch(doc, plane):
-    """Add a Sketch feature to the Part or PartSet and return an interface
-    on it.
+def addSketch(document, plane):
+    """Add a sketch to a Part or PartSet.
 
-    A Sketch object is instanciated with a feature as input parameter
-    it provides an interface for manipulation of the feature data.
-    :return: interface on the feature
-    :rtype: Sketch"""
-    feature = featureToCompositeFeature(doc.addFeature("Sketch"))
+    Arguments:
+       document(ModelAPI_Document): part or partset document
+       plane(geom.Ax3): plane on wich the sketch is built
+
+    Returns:
+       Sketch: sketch object
+    """
+    feature = featureToCompositeFeature(document.addFeature("Sketch"))
     return Sketch(feature, plane)
 
 class Sketch(Interface):
-    """Interface on a Sketch feature."""
+    """Interface class for Sketch feature."""
     def __init__(self, feature, *args):
         """Initialize a 2D Sketch on the given plane.
 
@@ -49,22 +74,14 @@ class Sketch(Interface):
             )
         self._external = self._feature.data().selection("External")
 
-        assert(self._origin)
-        assert(self._dir_x)
-        assert(self._norm)
-        assert(self._external)
-
-        if not args:
-            return
-
-        plane = args[0]
-
-        #   self.resultype ="Face" # Type of Sketch result
-        if isinstance(plane, str):
-            self.__sketchOnFace(plane)
-        else:
-            self.__sketchOnPlane(plane)
-        pass
+        # If no arguments are given the attributes of the feature
+        # are not Initialized
+        if args is not None:
+            plane = args[0]
+            if isinstance(plane, str):
+                self.__sketchOnFace(plane)
+            else:
+                self.__sketchOnPlane(plane)
 
     def __sketchOnPlane(self, plane):
         """Create the sketch on a plane."""
@@ -86,12 +103,37 @@ class Sketch(Interface):
     #-------------------------------------------------------------
 
     def addPoint(self, *args):
-        """Add a point to this Sketch."""
+        """Add a point to the sketch."""
+        if not args:
+            raise TypeError("No arguments given")
         point_feature = self._feature.addFeature("SketchPoint")
         return Point(point_feature, *args)
 
     def addLine(self, *args):
-        """Add a line to this Sketch."""
+        """Add a line to the sketch.
+
+        .. function:: addLine(name)
+        Select an existing line. The line is added to the sketch with a rigid
+        constraint (it cannot be modified by the sketch)
+
+        Arguments:
+            name(str): name of an existing line
+
+        .. function:: addLine(start, end)
+        Create a line by points
+
+        Arguments:
+           start(point): start point of the line
+           end(point): end point of the line
+
+        .. function:: addLine(start_x, start_y, end_x, end_y)
+        Create a line by coordinates
+
+        Arguments:
+           start_x(double): start point x coordinate
+        """
+        if not args:
+            raise TypeError("No arguments given")
         line_feature = self._feature.addFeature("SketchLine")
         line_interface = Line(line_feature, *args)
         # if the line is created by name add a rigid constraint
@@ -105,13 +147,36 @@ class Sketch(Interface):
 
     def addCircle(self, *args):
         """Add a circle to this Sketch."""
+        if not args:
+            raise TypeError("No arguments given")
         circle_feature = self._feature.addFeature("SketchCircle")
         return Circle(circle_feature, *args)
 
-    def addArc(self, *args):
-        """Add an arc to this Sketch."""
+    def addArc(self, *args, **kwargs):
+        """Add an arc of circle to the sketch and return an arc object.
+
+        Two different syntaxes are allowed:
+
+        .. function:: addArc(center, start, end)
+
+        Arguments:
+            center (point): center of the arc
+            start (point): start point of the arc
+            end (point): end point of the arc
+
+        .. function:: addArc(center_x, center_y, start_x, start_y, end_x, end_y)
+
+        Same as above but with coordinates
+
+        Returns:
+            Arc: arc object
+        Raises:
+            TypeError: if no argument is provided
+        """
+        if not args:
+            raise TypeError("No arguments given")
         arc_feature = self._feature.addFeature("SketchArc")
-        return Arc(arc_feature, *args)
+        return Arc(arc_feature, *args, **kwargs)
 
     #-------------------------------------------------------------
     #
@@ -122,82 +187,94 @@ class Sketch(Interface):
     def setCoincident(self, p1, p2):
         """Set coincident the two given points and add the corresponding
         constraint to this Sketch."""
-        assert(p1 and p2)
+        # assert(p1 and p2) NOTE : if an argument is missing python
+        # will raise TypeError by itself.
+        # It seems better to check only that provided arguments are not
+        # None
+        if p1 is None or p2 is None:
+            raise TypeError("NoneType argument given")
         constraint = self._feature.addFeature("SketchConstraintCoincidence")
-        constraint.data().refattr("ConstraintEntityA").setAttr(p1)
-        constraint.data().refattr("ConstraintEntityB").setAttr(p2)
-        self._execute()
+        self._fillAttribute(constraint.refattr("ConstraintEntityA"), p1)
+        self._fillAttribute(constraint.refattr("ConstraintEntityB"), p2)
+        self.execute()
         return constraint
 
     def setParallel(self, l1, l2):
         """Set parallel the two given lines and add the corresponding
         constraint to this Sketch."""
-        assert(l1 and l2)
+        if l1 is None or l2 is None:
+            raise TypeError("NoneType argument given")
         constraint = self._feature.addFeature("SketchConstraintParallel")
         constraint.data().refattr("ConstraintEntityA").setObject(l1)
         constraint.data().refattr("ConstraintEntityB").setObject(l2)
-        self._execute()
+        self.execute()
         return constraint
 
     def setPerpendicular(self, l1, l2):
         """Set perpendicular the two given lines and add the corresponding
         constraint to this Sketch."""
-        assert(l1 and l2)
+        if l1 is None or l2 is None:
+            raise TypeError("NoneType argument given")
         constraint = self._feature.addFeature("SketchConstraintPerpendicular")
         constraint.data().refattr("ConstraintEntityA").setObject(l1)
         constraint.data().refattr("ConstraintEntityB").setObject(l2)
-        self._execute()
+        self.execute()
         return constraint
 
     def setHorizontal(self, line):
         """Set horizontal the given line and add the corresponding
         constraint to this Sketch."""
+        if line is None:
+            raise TypeError("NoneType argument given")
         constraint = self._feature.addFeature("SketchConstraintHorizontal")
         constraint.data().refattr("ConstraintEntityA").setObject(line)
-        self._execute()
+        self.execute()
         return constraint
 
     def setVertical(self, line):
         """Set vertical the given line and add the corresponding
         constraint to this Sketch."""
+        if line is None:
+            raise TypeError("NoneType argument given")
         constraint = self._feature.addFeature("SketchConstraintVertical")
         constraint.data().refattr("ConstraintEntityA").setObject(line)
-        self._execute()
+        self.execute()
         return constraint
 
     def setDistance(self, point, line, length):
         """Set the distance between the given point and line, and add
         the corresponding constraint to this Sketch."""
-        assert(point and line)
+        if point is None or line is None:
+            raise TypeError("NoneType argument given")
         constraint = self._feature.addFeature("SketchConstraintDistance")
         if isinstance(line, basestring):
             # Add the edge identified by the given topological name
             # to this Sketch
             line = self.addLine(line).result()
-            assert(line)
         constraint.data().refattr("ConstraintEntityA").setAttr(point)
         constraint.data().refattr("ConstraintEntityB").setObject(line)
         constraint.data().real("ConstraintValue").setValue(length)
-        self._execute()
+        self.execute()
         return constraint
 
     def setLength(self, line, length):
         """Set the length of the given line and add the corresponding
         constraint to this Sketch."""
-        assert(line)
+        if line is None:
+            raise TypeError("NoneType argument given")
         constraint = self._feature.addFeature("SketchConstraintLength")
         constraint.data().refattr("ConstraintEntityA").setObject(line)
-        constraint.data().real("ConstraintValue").setValue(length)
-        self._execute()
+        self._fillAttribute(constraint.real("ConstraintValue"), length)
+        self.execute()
         return constraint
 
     def setRadius(self, circle, radius):
         """Set the radius of the given circle and add the corresponding
         constraint to this Sketch."""
         constraint = self._feature.addFeature("SketchConstraintRadius")
-        constraint.data().refattr("ConstraintEntityA").setObject(circle)
-        constraint.data().real("ConstraintValue").setValue(radius)
-        self._execute()
+        self._fillAttribute(constraint.refattr("ConstraintEntityA"), circle)
+        self._fillAttribute(constraint.real("ConstraintValue"), radius)
+        self.execute()
         return constraint
 
     def setEqual(self, object_1, object_2):
@@ -207,7 +284,7 @@ class Sketch(Interface):
         constraint = self._feature.addFeature("SketchConstraintEqual")
         constraint.data().refattr("ConstraintEntityA").setObject(object_1)
         constraint.data().refattr("ConstraintEntityB").setObject(object_2)
-        self._execute()
+        self.execute()
         return constraint
 
     def setAngle(self, line_1, line_2, angle):
@@ -217,28 +294,64 @@ class Sketch(Interface):
         constraint.data().refattr("ConstraintEntityA").setObject(line_1)
         constraint.data().refattr("ConstraintEntityB").setObject(line_2)
         constraint.data().real("ConstraintValue").setValue(angle)
-        self._execute()
+        self.execute()
         return constraint
 
     def setTangent(self, object_1, object_2):
         """Set a tangential continuity between two objects
         at their coincidence point."""
+        if object_1 is None or object_2 is None:
+            raise TypeError("NoneType argument given")
         constraint = self._feature.addFeature("SketchConstraintTangent")
         constraint.data().refattr("ConstraintEntityA").setObject(object_1)
         constraint.data().refattr("ConstraintEntityB").setObject(object_2)
-        self._execute()
+        self.execute()
         return constraint
 
-    def setFillet(self, line_1, line_2, radius):
-        """Set a fillet constraint between the 3 given lines with the given
+    def setFillet(self, *args):
+        """Set a fillet constraint between the 2 given lines with the given
         filleting radius."""
+        assert(args)
         constraint = self._feature.addFeature("SketchConstraintFillet")
-        constraint.data().refattr("ConstraintEntityA").setObject(line_1)
-        constraint.data().refattr("ConstraintEntityB").setObject(line_2)
-        constraint.data().real("ConstraintValue").setValue(radius)
-        self._execute()
+        if len(args) == 3:
+            line_1, line_2, radius = args
+            constraint.data().refattr("ConstraintEntityA").setObject(line_1)
+            constraint.data().reflist("ConstraintEntityB").clear()
+            constraint.data().reflist("ConstraintEntityB").append(line_2)
+        elif len(args) == 2:
+            point, radius = args
+            self._fillAttribute(constraint.data().refattrlist("ConstraintEntityA"), [point])
+            self._fillAttribute(constraint.real("ConstraintValue"), radius)
+        self.execute()
         return constraint
 
+    def setRigid(self, object_):
+        """Set a rigid constraint on a given object."""
+        constraint = self._feature.addFeature("SketchConstraintRigid")
+        self._fillAttribute(constraint.refattr("ConstraintEntityA"), object_)
+        self.execute()
+        return constraint
+
+    #-------------------------------------------------------------
+    #
+    # Transformation constraints
+    #
+    #-------------------------------------------------------------
+
+    def addMirror(self, mirror_line, sketch_objects):
+        """Add a mirror transformation of the given objects to the sketch.
+
+        This transformation is a constraint.
+
+        :return: interface to the constraint
+        :rtype: Mirror object
+        """
+        mirror_constraint = self._feature.addFeature("SketchConstraintMirror")
+        mirror_interface = Mirror(mirror_constraint, mirror_line, sketch_objects)
+        self.execute()
+        return mirror_interface
+
+
     #-------------------------------------------------------------
     #
     # Edition of Dimensional Constraints
@@ -268,7 +381,7 @@ class Sketch(Interface):
         # Adding and connecting next lines
         for c2 in coords[2:]:
             line_2 = self.addLine(c1, c2)
-            self.setCoincident(line_1.endPointData(), line_2.startPointData())
+            self.setCoincident(line_1.endPoint(), line_2.startPoint())
             polyline.append(line_2)
             c1 = c2
             line_1 = line_2
@@ -285,10 +398,10 @@ class Sketch(Interface):
         cn = coords[len(coords) - 1]
         ln = self.addLine(cn, c0)
         self.setCoincident(
-            pg[len(coords) - 2].endPointData(), ln.startPointData()
+            pg[len(coords) - 2].endPoint(), ln.startPoint()
             )
         self.setCoincident(
-            ln.endPointData(), pg[0].startPointData()
+            ln.endPoint(), pg[0].startPoint()
             )
         pg.append(ln)
         return pg