Salome HOME
Rework Sketch Rectangle feature.
[modules/shaper.git] / src / PythonAddons / macros / rectangle / feature.py
index 116c22dbaca09ba9c633bdd106830e4b7cd4d695..9e09564083fae67d6afacc1fce0708c904924629 100644 (file)
@@ -64,6 +64,37 @@ class SketchPlugin_Rectangle(model.Feature):
         """Returns ID of list containing lines created."""
         return "RectangleList"
 
+    @staticmethod
+    def RECTANGLE_TYPE_ID():
+        """Returns ID of type of rectangle creation (by corners or by center and corner)."""
+        return "RectangleType"
+
+    @staticmethod
+    def RECTANGLE_BY_CORNERS_ID():
+        """Returns ID of creation type by opposite corners."""
+        return "RectangleTypeByCorners"
+
+    @staticmethod
+    def RECTANGLE_CENTERED_ID():
+        """Returns ID of creation type by center point and a corner."""
+        return "RectangleTypeCentered"
+
+    @staticmethod
+    def CENTER_ID():
+        """Returns ID of center point."""
+        return "RectCenterPoint"
+
+    @staticmethod
+    def CENTER_REF_ID():
+        """Returns ID of the reference to the center point."""
+        return "RectCenterPointRef"
+
+    @staticmethod
+    def CORNER_ID():
+        """Returns ID of a corner."""
+        return "RectCornerPoint"
+
+
     def getKind(self):
         """Override Feature.getKind()"""
         return SketchPlugin_Rectangle.ID()
@@ -81,6 +112,14 @@ class SketchPlugin_Rectangle(model.Feature):
         # Creating list to store lines
         self.data().addAttribute(self.LINES_LIST_ID(), ModelAPI.ModelAPI_AttributeRefList_typeId())
         ModelAPI.ModelAPI_Session.get().validators().registerNotObligatory(self.getKind(), self.LINES_LIST_ID())
+        # Type of rectangle
+        self.data().addAttribute(self.RECTANGLE_TYPE_ID(), ModelAPI.ModelAPI_AttributeString_typeId())
+        # Center and corner of the rectangle
+        self.data().addAttribute(self.CENTER_ID(), GeomDataAPI.GeomDataAPI_Point2D_typeId())
+        self.data().addAttribute(self.CORNER_ID(), GeomDataAPI.GeomDataAPI_Point2D_typeId())
+
+        self.data().addAttribute(self.CENTER_REF_ID(), ModelAPI.ModelAPI_AttributeRefAttr_typeId())
+        ModelAPI.ModelAPI_Session.get().validators().registerNotObligatory(self.getKind(), self.CENTER_REF_ID())
 
     def isMacro(self):
         """
@@ -102,6 +141,7 @@ class SketchPlugin_Rectangle(model.Feature):
                 aLinesList.append(aLine)
             self.updateLines()
             aNbLines = aLinesList.size()
+            aStartPoints = []
             # Create constraints to keep the rectangle
             for i in range (0, aNbLines):
                 aLine = ModelAPI.objectToFeature(aLinesList.object(i))
@@ -115,12 +155,39 @@ class SketchPlugin_Rectangle(model.Feature):
                 aRefAttrB = aCoincidence.refattr("ConstraintEntityB")
                 aRefAttrA.setAttr(aPrevLine.attribute("EndPoint"))
                 aRefAttrB.setAttr(aLine.attribute("StartPoint"))
+                aStartPoints.append(aLine.attribute("StartPoint"))
             # Flags which show horizontal or vertical constraint is build for correponding line
             self.__isHV = [False, False, False, False]
             # Update coordinates of created lines
             self.updateLines()
+            # Create auxiliary diagonals in case of centered rectangle
+            if self.string(self.RECTANGLE_TYPE_ID()).value() == self.RECTANGLE_CENTERED_ID():
+                aDiag1 = self.__sketch.addFeature("SketchLine")
+                aLinesList.append(aDiag1)
+                aDiag2 = self.__sketch.addFeature("SketchLine")
+                aLinesList.append(aDiag2)
+                # coincidences in corners
+                aPoints = [aDiag1.attribute("StartPoint"), aDiag2.attribute("StartPoint"),
+                           aDiag1.attribute("EndPoint"), aDiag2.attribute("EndPoint")]
+                for i in range (0, len(aPoints)):
+                    aCoincidence = self.__sketch.addFeature("SketchConstraintCoincidence")
+                    aRefAttrA = aCoincidence.refattr("ConstraintEntityA")
+                    aRefAttrB = aCoincidence.refattr("ConstraintEntityB")
+                    aRefAttrA.setAttr(aStartPoints[i])
+                    aRefAttrB.setAttr(aPoints[i])
+                # Update coordinates of created lines
+                self.updateLines()
+                aDiag1.execute()
+                aDiag2.execute()
+                # coincidences between center point and diagonals
+                refPnt = self.getReferencePoint(self.refattr(self.CENTER_REF_ID()))
+                if refPnt is not None:
+                    for line in [aDiag1.lastResult(), aDiag2.lastResult()]:
+                        aCoincidence = self.__sketch.addFeature("SketchConstraintCoincidence")
+                        aCoincidence.refattr("ConstraintEntityA").setAttr(refPnt)
+                        aCoincidence.refattr("ConstraintEntityB").setObject(line)
         # Add horizontal and vertical constraint for the lines which already have result
-        for i in range (0, aNbLines):
+        for i in range (0, 4):
             if self.__isHV[i]:
                 continue
             aLine = ModelAPI.objectToFeature(aLinesList.object(i))
@@ -136,7 +203,7 @@ class SketchPlugin_Rectangle(model.Feature):
             self.__isHV[i] = True
 
     def attributeChanged(self, theID):
-        if theID == self.START_ID() or theID == self.END_ID():
+        if theID == self.START_ID() or theID == self.END_ID() or theID == self.CENTER_ID() or theID == self.CENTER_REF_ID() or theID == self.CORNER_ID():
             # Search the sketch containing this rectangle
             self.__sketch = None
             aRefs = self.data().refsToMe();
@@ -156,7 +223,9 @@ class SketchPlugin_Rectangle(model.Feature):
 
             aStartPoint = GeomDataAPI.geomDataAPI_Point2D(self.attribute(self.START_ID()))
             aEndPoint = GeomDataAPI.geomDataAPI_Point2D(self.attribute(self.END_ID()))
-            if aStartPoint.isInitialized() and aEndPoint.isInitialized():
+            aCenter = self.getPointByRef(self.attribute(self.CENTER_ID()), self.refattr(self.CENTER_REF_ID()))
+            aCorner = GeomDataAPI.geomDataAPI_Point2D(self.attribute(self.CORNER_ID()))
+            if (aStartPoint.isInitialized() and aEndPoint.isInitialized()) or (aCenter is not None and aCorner.isInitialized()):
               self.updateLines()
             else:
               self.updateStartPoint()
@@ -169,17 +238,48 @@ class SketchPlugin_Rectangle(model.Feature):
                 aLine = ModelAPI.objectToFeature(aLinesList.object(i))
                 aLine.data().boolean("Auxiliary").setValue(anAuxiliary)
 
+    def getReferencePoint(self, theRef):
+        if theRef.isObject() and theRef.object() is not None:
+            feature = ModelAPI.ModelAPI_Feature.feature(theRef.object())
+            if feature.getKind() == "SketchPoint":
+                return feature.attribute("PointCoordinates")
+        else:
+            return theRef.attr()
+        return None
+
+    def getPointByRef(self, thePoint, theRef):
+        attr = thePoint
+        if theRef.isInitialized():
+            refPnt = self.getReferencePoint(theRef)
+            if refPnt is not None:
+                attr = refPnt
+        if attr is None or not attr.isInitialized():
+            return None
+        return GeomDataAPI.geomDataAPI_Point2D(attr).pnt()
 
     def updateLines(self):
         # Retrieving list of already created lines
         aLinesList = self.reflist(self.LINES_LIST_ID())
-        aNbLines = aLinesList.size()
-        aStartPoint = GeomDataAPI.geomDataAPI_Point2D(self.attribute(self.START_ID()))
-        aEndPoint = GeomDataAPI.geomDataAPI_Point2D(self.attribute(self.END_ID()))
-        aX = [aStartPoint.x(), aStartPoint.x(), aEndPoint.x(), aEndPoint.x()]
-        aY = [aStartPoint.y(), aEndPoint.y(), aEndPoint.y(), aStartPoint.y()]
+        aNbLines = min(aLinesList.size(), 4)
+        if self.string(self.RECTANGLE_TYPE_ID()).value() == self.RECTANGLE_CENTERED_ID():
+            aCenter = self.getPointByRef(self.attribute(self.CENTER_ID()), self.refattr(self.CENTER_REF_ID()))
+            aCorner = GeomDataAPI.geomDataAPI_Point2D(self.attribute(self.CORNER_ID()))
+            aStartX = 2.0 * aCenter.x() - aCorner.x()
+            aStartY = 2.0 * aCenter.y() - aCorner.y()
+            aX = [aStartX, aStartX, aCorner.x(), aCorner.x()]
+            aY = [aStartY, aCorner.y(), aCorner.y(), aStartY]
+        else:
+            aStartPoint = GeomDataAPI.geomDataAPI_Point2D(self.attribute(self.START_ID()))
+            aEndPoint = GeomDataAPI.geomDataAPI_Point2D(self.attribute(self.END_ID()))
+            aX = [aStartPoint.x(), aStartPoint.x(), aEndPoint.x(), aEndPoint.x()]
+            aY = [aStartPoint.y(), aEndPoint.y(), aEndPoint.y(), aStartPoint.y()]
         anAuxiliary = self.data().boolean(self.AUXILIARY_ID()).value()
 
+        # do not recalculate the rectrangle after each update
+        wasBlocked = []
+        for i in range (0, aLinesList.size()):
+            wasBlocked.append(aLinesList.object(i).data().blockSendAttributeUpdated(True))
+
         # Update coordinates of rectangle lines
         for i in range (0, aNbLines):
             aLine = ModelAPI.objectToFeature(aLinesList.object(i))
@@ -189,14 +289,33 @@ class SketchPlugin_Rectangle(model.Feature):
             aLineEnd.setValue(aX[i], aY[i])
             aLine.data().boolean("Auxiliary").setValue(anAuxiliary)
 
+        # Update auxiliary diagonals
+        if self.string(self.RECTANGLE_TYPE_ID()).value() == self.RECTANGLE_CENTERED_ID():
+            for i in range (aNbLines, aLinesList.size()):
+                aLine = ModelAPI.objectToFeature(aLinesList.object(i))
+                aLineStart = GeomDataAPI.geomDataAPI_Point2D(aLine.attribute("StartPoint"))
+                aLineEnd = GeomDataAPI.geomDataAPI_Point2D(aLine.attribute("EndPoint"))
+                aLineStart.setValue(aX[i-aNbLines-1], aY[i-aNbLines-1])
+                aLineEnd.setValue(aX[i-aNbLines+1], aY[i-aNbLines+1])
+                aLine.data().boolean("Auxiliary").setValue(True)
+
+        # update the rectangle
+        for i in range (0, aLinesList.size()):
+            aLinesList.object(i).data().blockSendAttributeUpdated(wasBlocked[i], True)
+
     def updateStartPoint(self):
         # Retrieving list of already created lines
         aLinesList = self.reflist(self.LINES_LIST_ID())
         aNbLines = aLinesList.size()
 
         aStartPoint = GeomDataAPI.geomDataAPI_Point2D(self.attribute(self.START_ID()))
-        aX = aStartPoint.x()
-        aY = aStartPoint.y()
+        if aStartPoint.isInitialized:
+            aX = aStartPoint.x()
+            aY = aStartPoint.y()
+        else:
+            aCenter = self.getPointByRef(self.attribute(self.CENTER_ID()), self.refattr(self.CENTER_REF_ID()))
+            aX = aCenter.x()
+            aY = aCenter.y()
 
         # Update coordinates of rectangle lines
         for i in range (0, aNbLines):