Salome HOME
fd4301b1a7713db0d6c10eca50fad6426389c06c
[modules/shaper.git] / src / PythonAddons / doc / examples / rectangle / feature.py
1 # Copyright (C) 2014-2023  CEA/DEN, EDF R&D
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 """
21 Macro-feature to produce rectangle in the sketcher
22 Author: Artem ZHIDKOV
23 """
24
25 from salome.shaper import model
26 import ModelAPI
27 import GeomDataAPI
28
29 class 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 correponding 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)