1 # -*- coding: utf-8 -*-
2 # Copyright (C) 2014-2021 CEA/DEN, EDF R&D
4 # This library is free software; you can redistribute it and/or
5 # modify it under the terms of the GNU Lesser General Public
6 # License as published by the Free Software Foundation; either
7 # version 2.1 of the License, or (at your option) any later version.
9 # This library is distributed in the hope that it will be useful,
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 # Lesser General Public License for more details.
14 # You should have received a copy of the GNU Lesser General Public
15 # License along with this library; if not, write to the Free Software
16 # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18 # See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
22 Macro-feature to produce rectangle in the sketcher
26 from salome.shaper import model
30 class SketchPlugin_Rectangle(model.Feature):
32 Implementation of rectangle creation.
34 It produced 2 horizontal lines and 2 vertical lines connected by coincidence constraints
43 """x.__init__(...) initializes x; see x.__class__.__doc__ for signature"""
44 model.Feature.__init__(self)
48 """Rectangle feature kind."""
49 return "SketchRectangle"
53 """Returns ID of first corner."""
54 return "RectStartPoint"
58 """Returns ID of second corner."""
63 """Returns whether the rectangle is accessory."""
68 """Returns ID of list containing lines created."""
69 return "RectangleList"
72 def RECTANGLE_TYPE_ID():
73 """Returns ID of type of rectangle creation (by corners or by center and corner)."""
74 return "RectangleType"
77 def RECTANGLE_BY_CORNERS_ID():
78 """Returns ID of creation type by opposite corners."""
79 return "RectangleTypeByCorners"
82 def RECTANGLE_CENTERED_ID():
83 """Returns ID of creation type by center point and a corner."""
84 return "RectangleTypeCentered"
88 """Returns ID of center point."""
89 return "RectCenterPoint"
93 """Returns ID of the reference to the center point."""
94 return "RectCenterPointRef"
98 """Returns ID of a corner."""
99 return "RectCornerPoint"
103 """Override Feature.getKind()"""
104 return SketchPlugin_Rectangle.ID()
107 # Initialization of the rectangle
109 def initAttributes(self):
110 """Override Feature.initAttributes()"""
111 # Flag whether the rectangle is accessory
112 self.data().addAttribute(self.AUXILIARY_ID(), ModelAPI.ModelAPI_AttributeBoolean_typeId())
113 # Creating corners of the rectangle
114 self.data().addAttribute(self.START_ID(), GeomDataAPI.GeomDataAPI_Point2D_typeId())
115 self.data().addAttribute(self.END_ID(), GeomDataAPI.GeomDataAPI_Point2D_typeId())
116 # Creating list to store lines
117 self.data().addAttribute(self.LINES_LIST_ID(), ModelAPI.ModelAPI_AttributeRefList_typeId())
118 ModelAPI.ModelAPI_Session.get().validators().registerNotObligatory(self.getKind(), self.LINES_LIST_ID())
120 self.data().addAttribute(self.RECTANGLE_TYPE_ID(), ModelAPI.ModelAPI_AttributeString_typeId())
121 # Center and corner of the rectangle
122 self.data().addAttribute(self.CENTER_ID(), GeomDataAPI.GeomDataAPI_Point2D_typeId())
123 self.data().addAttribute(self.CORNER_ID(), GeomDataAPI.GeomDataAPI_Point2D_typeId())
125 self.data().addAttribute(self.CENTER_REF_ID(), ModelAPI.ModelAPI_AttributeRefAttr_typeId())
126 ModelAPI.ModelAPI_Session.get().validators().registerNotObligatory(self.getKind(), self.CENTER_REF_ID())
130 Override Feature.isMacro().
131 Rectangle feature is macro: removes itself on the creation transaction finish.
135 # Edition of the rectangle
138 """F.execute() -- execute the Feature"""
139 # Retrieving list of already created lines
140 aLinesList = self.reflist(self.LINES_LIST_ID())
141 aNbLines = aLinesList.size()
143 # Create 1-4 lines to compose the rectangle
144 for i in range (0, 3):
145 aLine = self.__sketch.addFeature("SketchLine")
146 aLinesList.append(aLine)
148 aNbLines = aLinesList.size()
150 # Create constraints to keep the rectangle
151 for i in range (0, aNbLines):
152 aLine = ModelAPI.objectToFeature(aLinesList.object(i))
153 # connect neighbor lines by coincidence
157 aPrevLine = ModelAPI.objectToFeature(aLinesList.object(iPrev))
158 aCoincidence = self.__sketch.addFeature("SketchConstraintCoincidence")
159 aRefAttrA = aCoincidence.refattr("ConstraintEntityA")
160 aRefAttrB = aCoincidence.refattr("ConstraintEntityB")
161 aRefAttrA.setAttr(aPrevLine.attribute("EndPoint"))
162 aRefAttrB.setAttr(aLine.attribute("StartPoint"))
163 aStartPoints.append(aLine.attribute("StartPoint"))
164 # Flags which show horizontal or vertical constraint is build for corresponding line
165 self.__isHV = [False, False, False, False]
166 # Update coordinates of created lines
168 # Create auxiliary diagonals in case of centered rectangle
169 if self.string(self.RECTANGLE_TYPE_ID()).value() == self.RECTANGLE_CENTERED_ID():
170 aDiag1 = self.__sketch.addFeature("SketchLine")
171 aLinesList.append(aDiag1)
172 aDiag2 = self.__sketch.addFeature("SketchLine")
173 aLinesList.append(aDiag2)
174 # coincidences in corners
175 aPoints = [aDiag1.attribute("StartPoint"), aDiag2.attribute("StartPoint"),
176 aDiag1.attribute("EndPoint"), aDiag2.attribute("EndPoint")]
177 for i in range (0, len(aPoints)):
178 aCoincidence = self.__sketch.addFeature("SketchConstraintCoincidence")
179 aRefAttrA = aCoincidence.refattr("ConstraintEntityA")
180 aRefAttrB = aCoincidence.refattr("ConstraintEntityB")
181 aRefAttrA.setAttr(aStartPoints[i])
182 aRefAttrB.setAttr(aPoints[i])
183 # Update coordinates of created lines
187 # coincidences between center point and diagonals
188 refPnt = self.getReferencePoint(self.refattr(self.CENTER_REF_ID()))
189 if refPnt is not None:
190 for line in [aDiag1.lastResult(), aDiag2.lastResult()]:
191 aCoincidence = self.__sketch.addFeature("SketchConstraintCoincidence")
192 aCoincidence.refattr("ConstraintEntityA").setAttr(refPnt)
193 aCoincidence.refattr("ConstraintEntityB").setObject(line)
194 # Add horizontal and vertical constraint for the lines which already have result
195 for i in range (0, 4):
198 aLine = ModelAPI.objectToFeature(aLinesList.object(i))
199 aLineResult = aLine.lastResult()
200 if aLineResult is None:
202 aHVName = "SketchConstraintHorizontal"
204 aHVName = "SketchConstraintVertical"
205 aHVConstraint = self.__sketch.addFeature(aHVName)
206 aRefAttrA = aHVConstraint.refattr("ConstraintEntityA")
207 aRefAttrA.setObject(aLine.lastResult())
208 self.__isHV[i] = True
210 def attributeChanged(self, theID):
211 """attributeChanged"""
212 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():
213 # Search the sketch containing this rectangle
214 aRefs = self.data().refsToMe()
216 aFeature = ModelAPI.objectToFeature(itera.owner())
217 if aFeature.getKind() == "Sketch":
218 self.__sketch = ModelAPI.featureToCompositeFeature(aFeature)
221 aLinesList = self.reflist(self.LINES_LIST_ID())
222 aNbLines = aLinesList.size()
224 # Create first line to be able to create a coincidence with selected point/feature
225 for i in range (0, 1):
226 aLine = self.__sketch.addFeature("SketchLine")
227 aLinesList.append(aLine)
229 aStartPoint = GeomDataAPI.geomDataAPI_Point2D(self.attribute(self.START_ID()))
230 aEndPoint = GeomDataAPI.geomDataAPI_Point2D(self.attribute(self.END_ID()))
231 aCenter = self.getPointByRef(self.attribute(self.CENTER_ID()), self.refattr(self.CENTER_REF_ID()))
232 aCorner = GeomDataAPI.geomDataAPI_Point2D(self.attribute(self.CORNER_ID()))
233 if (aStartPoint.isInitialized() and aEndPoint.isInitialized()) or (aCenter is not None and aCorner.isInitialized()):
236 self.updateStartPoint()
237 if theID == self.AUXILIARY_ID():
238 anAuxiliary = self.data().boolean(self.AUXILIARY_ID()).value()
239 aLinesList = self.reflist(self.LINES_LIST_ID())
240 aNbLines = aLinesList.size()
241 # Update coordinates of rectangle lines
242 for i in range (0, aNbLines):
243 aLine = ModelAPI.objectToFeature(aLinesList.object(i))
244 aLine.data().boolean("Auxiliary").setValue(anAuxiliary)
246 def getReferencePoint(self, theRef):
247 """getReferencePoint"""
248 if theRef.isObject() and theRef.object() is not None:
249 feature = ModelAPI.ModelAPI_Feature.feature(theRef.object())
250 if feature.getKind() == "SketchPoint":
251 return feature.attribute("PointCoordinates")
256 def getPointByRef(self, thePoint, theRef):
259 if theRef.isInitialized():
260 refPnt = self.getReferencePoint(theRef)
261 if refPnt is not None:
263 if attr is None or not attr.isInitialized():
265 return GeomDataAPI.geomDataAPI_Point2D(attr).pnt()
267 def updateLines(self):
269 # Retrieving list of already created lines
270 aLinesList = self.reflist(self.LINES_LIST_ID())
271 aNbLines = min(aLinesList.size(), 4)
272 if self.string(self.RECTANGLE_TYPE_ID()).value() == self.RECTANGLE_CENTERED_ID():
273 aCenter = self.getPointByRef(self.attribute(self.CENTER_ID()), self.refattr(self.CENTER_REF_ID()))
274 aCorner = GeomDataAPI.geomDataAPI_Point2D(self.attribute(self.CORNER_ID()))
275 aStartX = 2.0 * aCenter.x() - aCorner.x()
276 aStartY = 2.0 * aCenter.y() - aCorner.y()
277 aX = [aStartX, aStartX, aCorner.x(), aCorner.x()]
278 aY = [aStartY, aCorner.y(), aCorner.y(), aStartY]
280 aStartPoint = GeomDataAPI.geomDataAPI_Point2D(self.attribute(self.START_ID()))
281 aEndPoint = GeomDataAPI.geomDataAPI_Point2D(self.attribute(self.END_ID()))
282 aX = [aStartPoint.x(), aStartPoint.x(), aEndPoint.x(), aEndPoint.x()]
283 aY = [aStartPoint.y(), aEndPoint.y(), aEndPoint.y(), aStartPoint.y()]
284 anAuxiliary = self.data().boolean(self.AUXILIARY_ID()).value()
286 # do not recalculate the rectrangle after each update
288 for i in range (0, aLinesList.size()):
289 wasBlocked.append(aLinesList.object(i).data().blockSendAttributeUpdated(True))
291 # Update coordinates of rectangle lines
292 for i in range (0, aNbLines):
293 aLine = ModelAPI.objectToFeature(aLinesList.object(i))
294 aLineStart = GeomDataAPI.geomDataAPI_Point2D(aLine.attribute("StartPoint"))
295 aLineEnd = GeomDataAPI.geomDataAPI_Point2D(aLine.attribute("EndPoint"))
296 aLineStart.setValue(aX[i-1], aY[i-1])
297 aLineEnd.setValue(aX[i], aY[i])
298 aLine.data().boolean("Auxiliary").setValue(anAuxiliary)
300 # Update auxiliary diagonals
301 if self.string(self.RECTANGLE_TYPE_ID()).value() == self.RECTANGLE_CENTERED_ID():
302 for i in range (aNbLines, aLinesList.size()):
303 aLine = ModelAPI.objectToFeature(aLinesList.object(i))
304 aLineStart = GeomDataAPI.geomDataAPI_Point2D(aLine.attribute("StartPoint"))
305 aLineEnd = GeomDataAPI.geomDataAPI_Point2D(aLine.attribute("EndPoint"))
306 aLineStart.setValue(aX[i-aNbLines-1], aY[i-aNbLines-1])
307 aLineEnd.setValue(aX[i-aNbLines+1], aY[i-aNbLines+1])
308 aLine.data().boolean("Auxiliary").setValue(True)
310 # update the rectangle
311 for i in range (0, aLinesList.size()):
312 aLinesList.object(i).data().blockSendAttributeUpdated(wasBlocked[i], True)
314 def updateStartPoint(self):
315 """updateStartPoint"""
316 # Retrieving list of already created lines
317 aLinesList = self.reflist(self.LINES_LIST_ID())
318 aNbLines = aLinesList.size()
320 aStartPoint = GeomDataAPI.geomDataAPI_Point2D(self.attribute(self.START_ID()))
321 if aStartPoint.isInitialized:
325 aCenter = self.getPointByRef(self.attribute(self.CENTER_ID()), self.refattr(self.CENTER_REF_ID()))
329 # Update coordinates of rectangle lines
330 for i in range (0, aNbLines):
331 aLine = ModelAPI.objectToFeature(aLinesList.object(i))
332 aLineStart = GeomDataAPI.geomDataAPI_Point2D(aLine.attribute("EndPoint"))
333 aLineStart.setValue(aX, aY)