File feature.py

  1# Copyright (C) 2014-2026  CEA, EDF
  2#
  3# This library is free software; you can redistribute it and/or
  4# modify it under the terms of the GNU Lesser General Public
  5# License as published by the Free Software Foundation; either
  6# version 2.1 of the License, or (at your option) any later version.
  7#
  8# This library is distributed in the hope that it will be useful,
  9# but WITHOUT ANY WARRANTY; without even the implied warranty of
 10# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 11# Lesser General Public License for more details.
 12#
 13# You should have received a copy of the GNU Lesser General Public
 14# License along with this library; if not, write to the Free Software
 15# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
 16#
 17# See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
 18#
 19
 20"""
 21Macro-feature to produce rectangle in the sketcher
 22Author: Artem ZHIDKOV
 23"""
 24
 25from salome.shaper import model
 26import ModelAPI
 27import GeomDataAPI
 28
 29class SketchPlugin_Rectangle(model.Feature):
 30    """
 31    Implementation of rectangle creation.
 32
 33    It produced 2 horizontal lines and 2 vertical lines connected by coincidence constraints
 34    """
 35
 36# Initializations
 37
 38    def __init__(self):
 39        """x.__init__(...) initializes x; see x.__class__.__doc__ for signature"""
 40        model.Feature.__init__(self)
 41
 42    @staticmethod
 43    def ID():
 44        """Rectangle feature kind."""
 45        return "SketchRectangle"
 46
 47    @staticmethod
 48    def START_ID():
 49        """Returns ID of first corner."""
 50        return "RectStartPoint"
 51
 52    @staticmethod
 53    def END_ID():
 54        """Returns ID of second corner."""
 55        return "RectEndPoint"
 56
 57    @staticmethod
 58    def AUXILIARY_ID():
 59        """Returns whether the rectangle is accessory."""
 60        return "Auxiliary"
 61
 62    @staticmethod
 63    def LINES_LIST_ID():
 64        """Returns ID of list containing lines created."""
 65        return "RectangleList"
 66
 67    def getKind(self):
 68        """Override Feature.getKind()"""
 69        return SketchPlugin_Rectangle.ID()
 70
 71
 72# Initialization of the rectangle
 73
 74    def initAttributes(self):
 75        """Override Feature.initAttributes()"""
 76        # Flag whether the rectangle is accessory
 77        self.data().addAttribute(self.AUXILIARY_ID(), ModelAPI.ModelAPI_AttributeBoolean.typeId())
 78        # Creating corners of the rectangle
 79        self.data().addAttribute(self.START_ID(), GeomDataAPI.GeomDataAPI_Point2D.typeId())
 80        self.data().addAttribute(self.END_ID(), GeomDataAPI.GeomDataAPI_Point2D.typeId())
 81        # Creating list to store lines
 82        self.data().addAttribute(self.LINES_LIST_ID(), ModelAPI.ModelAPI_AttributeRefList.typeId())
 83        ModelAPI.ModelAPI_Session.get().validators().registerNotObligatory(self.getKind(), self.LINES_LIST_ID())
 84
 85    def isMacro(self):
 86        """
 87        Override Feature.isMacro().
 88        Rectangle feature is macro: removes itself on the creation transaction finish.
 89        """
 90        return True
 91
 92# Edition of the rectangle
 93
 94    def execute(self):
 95        # Retrieving list of already created lines
 96        aLinesList = self.reflist(self.LINES_LIST_ID())
 97        aNbLines = aLinesList.size()
 98        if aNbLines == 1:
 99            # Create 1-4 lines to compose the rectangle
100            for i in range (0, 3):
101                aLine = self.__sketch.addFeature("SketchLine")
102                aLinesList.append(aLine)
103            self.updateLines()
104            aNbLines = aLinesList.size()
105            # Create constraints to keep the rectangle
106            for i in range (0, aNbLines):
107                aLine = ModelAPI.objectToFeature(aLinesList.object(i))
108                # connect neighbor lines by coincidence
109                iPrev = i - 1
110                if iPrev < 0:
111                    iPrev = aNbLines - 1
112                aPrevLine = ModelAPI.objectToFeature(aLinesList.object(iPrev))
113                aCoincidence = self.__sketch.addFeature("SketchConstraintCoincidence")
114                aRefAttrA = aCoincidence.refattr("ConstraintEntityA")
115                aRefAttrB = aCoincidence.refattr("ConstraintEntityB")
116                aRefAttrA.setAttr(aPrevLine.attribute("EndPoint"))
117                aRefAttrB.setAttr(aLine.attribute("StartPoint"))
118            # Flags which show horizontal or vertical constraint is build for corresponding line
119            self.__isHV = [False, False, False, False]
120            # Update coordinates of created lines
121            self.updateLines()
122        # Add horizontal and vertical constraint for the lines which already have result
123        for i in range (0, aNbLines):
124            if self.__isHV[i]:
125                continue
126            aLine = ModelAPI.objectToFeature(aLinesList.object(i))
127            aLineResult = aLine.lastResult()
128            if aLineResult is None:
129                continue
130            aHVName = "SketchConstraintHorizontal"
131            if i % 2 == 1:
132                aHVName = "SketchConstraintVertical"
133            aHVConstraint = self.__sketch.addFeature(aHVName)
134            aRefAttrA = aHVConstraint.refattr("ConstraintEntityA")
135            aRefAttrA.setObject(aLine.lastResult())
136            self.__isHV[i] = True
137
138    def attributeChanged(self, theID):
139        if theID == self.START_ID() or theID == self.END_ID():
140            # Search the sketch containing this rectangle
141            self.__sketch = None
142            aRefs = self.data().refsToMe();
143            for iter in aRefs:
144                aFeature = ModelAPI.objectToFeature(iter.owner())
145                if aFeature.getKind() == "Sketch":
146                    self.__sketch = ModelAPI.featureToCompositeFeature(aFeature)
147                    break
148
149            aLinesList = self.reflist(self.LINES_LIST_ID())
150            aNbLines = aLinesList.size()
151            if aNbLines == 0:
152                # Create first line to be able to create a coincidence with selected point/feature
153                for i in range (0, 1):
154                    aLine = self.__sketch.addFeature("SketchLine")
155                    aLinesList.append(aLine)
156
157            aStartPoint = GeomDataAPI.geomDataAPI_Point2D(self.attribute(self.START_ID()))
158            aEndPoint = GeomDataAPI.geomDataAPI_Point2D(self.attribute(self.END_ID()))
159            if aStartPoint.isInitialized() and aEndPoint.isInitialized():
160              self.updateLines()
161            else:
162              self.updateStartPoint()
163        if theID == self.AUXILIARY_ID():
164            anAuxiliary = self.data().boolean(self.AUXILIARY_ID()).value()
165            aLinesList = self.reflist(self.LINES_LIST_ID())
166            aNbLines = aLinesList.size()
167            # Update coordinates of rectangle lines
168            for i in range (0, aNbLines):
169                aLine = ModelAPI.objectToFeature(aLinesList.object(i))
170                aLine.data().boolean("Auxiliary").setValue(anAuxiliary)
171
172
173    def updateLines(self):
174        # Retrieving list of already created lines
175        aLinesList = self.reflist(self.LINES_LIST_ID())
176        aNbLines = aLinesList.size()
177        aStartPoint = GeomDataAPI.geomDataAPI_Point2D(self.attribute(self.START_ID()))
178        aEndPoint = GeomDataAPI.geomDataAPI_Point2D(self.attribute(self.END_ID()))
179        aX = [aStartPoint.x(), aStartPoint.x(), aEndPoint.x(), aEndPoint.x()]
180        aY = [aStartPoint.y(), aEndPoint.y(), aEndPoint.y(), aStartPoint.y()]
181        anAuxiliary = self.data().boolean(self.AUXILIARY_ID()).value()
182
183        # Update coordinates of rectangle lines
184        for i in range (0, aNbLines):
185            aLine = ModelAPI.objectToFeature(aLinesList.object(i))
186            aLineStart = GeomDataAPI.geomDataAPI_Point2D(aLine.attribute("StartPoint"))
187            aLineEnd = GeomDataAPI.geomDataAPI_Point2D(aLine.attribute("EndPoint"))
188            aLineStart.setValue(aX[i-1], aY[i-1])
189            aLineEnd.setValue(aX[i], aY[i])
190            aLine.data().boolean("Auxiliary").setValue(anAuxiliary)
191
192    def updateStartPoint(self):
193        # Retrieving list of already created lines
194        aLinesList = self.reflist(self.LINES_LIST_ID())
195        aNbLines = aLinesList.size()
196
197        aStartPoint = GeomDataAPI.geomDataAPI_Point2D(self.attribute(self.START_ID()))
198        aX = aStartPoint.x()
199        aY = aStartPoint.y()
200
201        # Update coordinates of rectangle lines
202        for i in range (0, aNbLines):
203            aLine = ModelAPI.objectToFeature(aLinesList.object(i))
204            aLineStart = GeomDataAPI.geomDataAPI_Point2D(aLine.attribute("EndPoint"))
205            aLineStart.setValue(aX, aY)

Download this script