1 // Copyright (C) 2014-2020 CEA/DEN, EDF R&D
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.
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.
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
17 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
20 #include "SketchPlugin_Rectangle.h"
21 #include "SketchPlugin_Sketch.h"
22 #include <ModelAPI_ResultConstruction.h>
23 #include <ModelAPI_AttributeSelection.h>
24 #include <ModelAPI_Validator.h>
25 #include <ModelAPI_AttributeRefList.h>
26 #include <ModelAPI_AttributeRefAttr.h>
27 #include <GeomDataAPI_Point2D.h>
28 #include <GeomAlgoAPI_CompoundBuilder.h>
30 #include <SketchPlugin_Line.h>
31 #include <SketchPlugin_Point.h>
32 #include <SketchPlugin_Tools.h>
33 #include <SketchPlugin_ConstraintCoincidence.h>
34 #include <SketchPlugin_ConstraintHorizontal.h>
35 #include <SketchPlugin_ConstraintVertical.h>
36 #include <SketchPlugin_ConstraintCoincidenceInternal.h>
41 const double tolerance = 1e-7;
44 SketchPlugin_Rectangle::SketchPlugin_Rectangle()
45 : SketchPlugin_SketchEntity()
50 void SketchPlugin_Rectangle::initDerivedClassAttributes()
52 data()->addAttribute(AUXILIARY_ID(), ModelAPI_AttributeBoolean::typeId());
53 data()->addAttribute(START_ID(), GeomDataAPI_Point2D::typeId());
54 data()->addAttribute(END_ID(), GeomDataAPI_Point2D::typeId());
55 data()->addAttribute(CENTER_ID(), GeomDataAPI_Point2D::typeId());
56 ModelAPI_Session::get()->validators()->registerNotObligatory(getKind(), CENTER_ID());
57 data()->addAttribute(CENTER_REF_ID(), ModelAPI_AttributeRefAttr::typeId());
58 ModelAPI_Session::get()->validators()->registerNotObligatory(getKind(), CENTER_REF_ID());
59 data()->addAttribute(LINES_LIST_ID(), ModelAPI_AttributeRefList::typeId());
60 ModelAPI_Session::get()->validators()->registerNotObligatory(getKind(), LINES_LIST_ID());
61 data()->addAttribute(DIAGONAL_LIST_ID(), ModelAPI_AttributeRefList::typeId());
62 ModelAPI_Session::get()->validators()->registerNotObligatory(getKind(), DIAGONAL_LIST_ID());
63 data()->addAttribute(ISHV_LIST_ID(), ModelAPI_AttributeIntArray::typeId());
64 ModelAPI_Session::get()->validators()->registerNotObligatory(getKind(), ISHV_LIST_ID());
65 data()->addAttribute(NOT_TO_DUMP_LIST_ID(), ModelAPI_AttributeRefList::typeId());
66 ModelAPI_Session::get()->validators()->registerNotObligatory(getKind(), NOT_TO_DUMP_LIST_ID());
70 static const std::pair<unsigned, std::string> cornerToDiagonalLinePoints[4]
72 {0, SketchPlugin_Line::START_ID()},
73 {1, SketchPlugin_Line::START_ID()},
74 {0, SketchPlugin_Line::END_ID()},
75 {1, SketchPlugin_Line::END_ID()}
79 void SketchPlugin_Rectangle::updateLines()
81 // Retrieving list of already created lines
82 AttributeRefListPtr aLinesList = reflist(LINES_LIST_ID());
83 unsigned aNbLines = aLinesList->size();
84 std::shared_ptr<GeomDataAPI_Point2D> aStartPoint =
85 std::dynamic_pointer_cast<GeomDataAPI_Point2D>(data()->attribute(START_ID()));
86 std::shared_ptr<GeomDataAPI_Point2D> aEndPoint =
87 std::dynamic_pointer_cast<GeomDataAPI_Point2D>(data()->attribute(END_ID()));
89 double aXStart = aStartPoint->x();
90 double aYStart = aStartPoint->y();
91 double aXEnd = aEndPoint->x();
92 double aYEnd = aEndPoint->y();
94 std::vector<double> aX = {aXStart, aXStart, aXEnd, aXEnd};
95 std::vector<double> aY = {aYStart, aYEnd, aYEnd, aYStart};
97 bool anAuxiliary = data()->boolean(AUXILIARY_ID())->value();
98 AttributeRefListPtr aDiagonalList = reflist(DIAGONAL_LIST_ID());
101 /// Update coordinates of rectangle lines
102 for(unsigned i = 0; i < aNbLines; i++)
104 FeaturePtr aLine = std::dynamic_pointer_cast<ModelAPI_Feature>(aLinesList->object(i));
105 std::shared_ptr<GeomDataAPI_Point2D> aLineStart =
106 std::dynamic_pointer_cast<GeomDataAPI_Point2D>(aLine->attribute(SketchPlugin_Line::START_ID()));
107 std::shared_ptr<GeomDataAPI_Point2D> aLineEnd =
108 std::dynamic_pointer_cast<GeomDataAPI_Point2D>(aLine->attribute(SketchPlugin_Line::END_ID()));
109 aLineStart->setValue(aX[(i+3)%4], aY[(i+3)%4]);
110 aLineEnd->setValue(aX[i], aY[i]);
111 aLine->data()->boolean(AUXILIARY_ID())->setValue(anAuxiliary);
112 /// Cooordinates of diagonals
113 if(aDiagonalList->size())
115 auto aDiagonalPoint = cornerToDiagonalLinePoints[i];
116 FeaturePtr aDiagonal = std::dynamic_pointer_cast<ModelAPI_Feature>(aDiagonalList->object(aDiagonalPoint.first));
117 std::dynamic_pointer_cast<GeomDataAPI_Point2D>(aDiagonal->attribute(aDiagonalPoint.second))->setValue(aX[(i+3)%4], aY[(i+3)%4]);
122 void SketchPlugin_Rectangle::updateStartPoint()
124 /// Retrieving list of already created lines
125 AttributeRefListPtr aLinesList = reflist(LINES_LIST_ID());
126 unsigned aNbLines = aLinesList->size();
127 std::shared_ptr<GeomDataAPI_Point2D> aStartPoint =
128 std::dynamic_pointer_cast<GeomDataAPI_Point2D>(data()->attribute(START_ID()));
130 double aXStart = aStartPoint->x();
131 double aYStart = aStartPoint->y();
133 /// Update coordinates of rectangle lines
134 for(unsigned i = 0; i < aNbLines; i++)
136 FeaturePtr aLine = std::dynamic_pointer_cast<ModelAPI_Feature>(aLinesList->object(i));
137 std::shared_ptr<GeomDataAPI_Point2D> aLineStart =
138 std::dynamic_pointer_cast<GeomDataAPI_Point2D>(aLine->attribute(SketchPlugin_Line::END_ID()));
139 aLineStart->setValue(aXStart, aYStart);
143 void SketchPlugin_Rectangle::execute()
145 SketchPlugin_Sketch* aSketch = sketch();
150 // Compute a Rectangle in 3D view.
151 std::shared_ptr<GeomDataAPI_Point2D> aStartAttr =
152 std::dynamic_pointer_cast<GeomDataAPI_Point2D>(data()->attribute(START_ID()));
154 std::shared_ptr<GeomDataAPI_Point2D> aEndAttr =
155 std::dynamic_pointer_cast<GeomDataAPI_Point2D>(data()->attribute(END_ID()));
157 if(!aStartAttr->isInitialized() || !aEndAttr->isInitialized()) {
161 AttributeRefListPtr aLinesList = reflist(LINES_LIST_ID());
162 unsigned aNbLines = aLinesList->size();
163 AttributeIntArrayPtr isHVList = intArray(ISHV_LIST_ID());
164 AttributeRefListPtr aNotToDumpList = reflist(NOT_TO_DUMP_LIST_ID());
165 AttributeRefListPtr aDiagonalList = reflist(DIAGONAL_LIST_ID());
169 /// Create 1-4 lines to compose the rectangle
170 for( unsigned i = 0; i < 3; i++)
172 FeaturePtr aLine = aSketch->addFeature(SketchPlugin_Line::ID());
173 aLinesList->append(aLine);
174 aNotToDumpList->append(aLine);
179 aNbLines = aLinesList->size();
180 FeaturePtr aCenterPointFeature;
182 if(aDiagonalList->size())
184 /// compute diagonals intersection point
185 std::shared_ptr<GeomDataAPI_Point2D> aCenterAttr =
186 std::dynamic_pointer_cast<GeomDataAPI_Point2D>(data()->attribute(CENTER_ID()));
188 aCenterPointFeature = aSketch->addFeature(SketchPlugin_Point::ID());
189 aNotToDumpList->append(aCenterPointFeature);
190 AttributePoint2DPtr aCoord = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
191 aCenterPointFeature->attribute(SketchPlugin_Point::COORD_ID()));
192 aCoord->setValue(aCenterAttr->x(), aCenterAttr->y());
193 aCenterPointFeature->boolean(SketchPlugin_Point::AUXILIARY_ID())->setValue(true);
194 refattr(CENTER_REF_ID())->setObject(aCenterPointFeature);
196 for(int i = 0; i < 2; i++)
198 FeaturePtr aDiagonal = std::dynamic_pointer_cast<ModelAPI_Feature>(aDiagonalList->object(i));
199 FeaturePtr aConstraint = SketchPlugin_Tools::createConstraintAttrObject(aSketch, SketchPlugin_ConstraintCoincidenceInternal::ID(),
201 aNotToDumpList->append(aConstraint);
205 /// Create constraints to keep the rectangle
206 for( unsigned i = 0; i < aNbLines; i++)
208 FeaturePtr aLine = std::dynamic_pointer_cast<ModelAPI_Feature>(aLinesList->object(i));
209 /// connect neighbor lines by coincidence
210 unsigned iPrev = (i+3)%4;
211 FeaturePtr aPrevLine = std::dynamic_pointer_cast<ModelAPI_Feature>(aLinesList->object(iPrev));
212 FeaturePtr aConstraint = SketchPlugin_Tools::createConstraintAttrAttr(aSketch, SketchPlugin_ConstraintCoincidence::ID(),
213 aPrevLine->attribute(SketchPlugin_Line::END_ID()),
214 aLine->attribute(SketchPlugin_Line::START_ID()));
215 aNotToDumpList->append(aConstraint);
217 /// case of rectangle created from its center
218 if(aDiagonalList->size())
220 auto aDiagonalPoint = cornerToDiagonalLinePoints[i];
221 FeaturePtr aDiagonal = std::dynamic_pointer_cast<ModelAPI_Feature>(aDiagonalList->object(aDiagonalPoint.first));
222 FeaturePtr aConstraint = SketchPlugin_Tools::createConstraintAttrAttr(aSketch, SketchPlugin_ConstraintCoincidenceInternal::ID(),
223 aDiagonal->attribute(aDiagonalPoint.second),
224 aLine->attribute(SketchPlugin_Line::START_ID()));
225 aNotToDumpList->append(aConstraint);
228 /// Update coordinates of created lines
232 /// Add horizontal and vertical constraint for the lines which already have result
233 if(isHVList->size() == 0)
235 isHVList->setSize(4, false);
236 for(int i = 0; i< 4;)
237 isHVList->setValue(i++, 0, false);
240 for(unsigned i = 0; i< aNbLines; i++)
242 if(isHVList->value(i))
244 FeaturePtr aLine = std::dynamic_pointer_cast<ModelAPI_Feature>(aLinesList->object(i));
245 ResultPtr aLineResult = aLine->lastResult();
246 if(!aLineResult.get())
248 std::string aHVName = SketchPlugin_ConstraintHorizontal::ID();
250 aHVName = SketchPlugin_ConstraintVertical::ID();
251 FeaturePtr aHVConstraint = aSketch->addFeature(aHVName);
252 aNotToDumpList->append(aHVConstraint);
253 AttributeRefAttrPtr aRefAttrA = aHVConstraint->refattr(SketchPlugin_Constraint::ENTITY_A());
254 aRefAttrA->setObject(aLine->lastResult());
255 isHVList->setValue(i, 1, false);
258 double aDiag = std::pow(aStartAttr->x() - aEndAttr->x(), 2.0);
259 aDiag += std::pow(aStartAttr->y() - aEndAttr->y(), 2.0);
260 aDiag = std::sqrt(aDiag);
261 if(aDiag < tolerance) {
266 GeomShapePtr aRectangleShape;
269 for(unsigned i = 0; i< aNbLines; i++)
271 FeaturePtr aLine = std::dynamic_pointer_cast<ModelAPI_Feature>(aLinesList->object(i));
272 ResultPtr aLineResult = aLine->lastResult();
273 if(!aLineResult.get())
275 aSubs.push_back(aLineResult->shape());
278 for(int i = 0; i< aDiagonalList->size(); i++)
280 FeaturePtr aDiagonal = std::dynamic_pointer_cast<ModelAPI_Feature>(aDiagonalList->object(i));
281 ResultPtr aDiagonalResult = aDiagonal->lastResult();
282 if(!aDiagonalResult.get())
284 aSubs.push_back(aDiagonalResult->shape());
287 FeaturePtr aCenterPointFeature = std::dynamic_pointer_cast<ModelAPI_Feature>(refattr(CENTER_REF_ID())->object());
288 if(aCenterPointFeature)
290 ResultPtr aCenterResult = aCenterPointFeature->lastResult();
291 if(aCenterResult.get())
292 aSubs.push_back(aCenterResult->shape());
295 aRectangleShape = aSubs.empty() ? GeomShapePtr() : GeomAlgoAPI_CompoundBuilder::compound(aSubs);
296 std::shared_ptr<ModelAPI_ResultConstruction> aResult = document()->createConstruction(data(), 0);
297 aResult->setShape(aRectangleShape);
298 aResult->setIsInHistory(false);
299 setResult(aResult, 1);
302 void SketchPlugin_Rectangle::attributeChanged(const std::string& theID)
304 if (theID == START_ID() || theID == END_ID())
306 AttributeRefListPtr aLinesList = reflist(LINES_LIST_ID());
307 AttributeRefListPtr aNotToDumpList = reflist(NOT_TO_DUMP_LIST_ID());
308 unsigned aNbLines = aLinesList->size();
311 SketchPlugin_Sketch* aSketch = sketch();
315 /// Create first line to be able to create a coincidence with selected point/feature
316 FeaturePtr aLine = aSketch->addFeature(SketchPlugin_Line::ID());
317 aLinesList->append(aLine);
318 aNotToDumpList->append(aLine);
320 /// if rectangle has center, add 2 iagonals
321 std::shared_ptr<GeomDataAPI_Point2D> aCenterAttr =
322 std::dynamic_pointer_cast<GeomDataAPI_Point2D>(data()->attribute(CENTER_ID()));
323 if(aCenterAttr->isInitialized())
325 AttributeRefListPtr aDiagonalList = reflist(DIAGONAL_LIST_ID());
326 for(int i = 0; i < 2; i++)
328 FeaturePtr aDiagonalLine = aSketch->addFeature(SketchPlugin_Line::ID());
329 aDiagonalLine->boolean(SketchPlugin_Point::AUXILIARY_ID())->setValue(true);
330 aDiagonalList->append(aDiagonalLine);
331 aNotToDumpList->append(aDiagonalLine);
335 std::shared_ptr<GeomDataAPI_Point2D> aStartPoint =
336 std::dynamic_pointer_cast<GeomDataAPI_Point2D>(data()->attribute(START_ID()));
337 std::shared_ptr<GeomDataAPI_Point2D> aEndPoint =
338 std::dynamic_pointer_cast<GeomDataAPI_Point2D>(data()->attribute(END_ID()));
340 if (aStartPoint->isInitialized() && aEndPoint->isInitialized())
346 if (theID == AUXILIARY_ID())
348 bool anAuxiliary = data()->boolean(AUXILIARY_ID())->value();
349 AttributeRefListPtr aLinesList = reflist(LINES_LIST_ID());
350 unsigned aNbLines = aLinesList->size();
352 /// Update coordinates of rectangle lines
353 for(unsigned i = 0; i < aNbLines; i++)
355 FeaturePtr aLine = std::dynamic_pointer_cast<ModelAPI_Feature>(aLinesList->object(i));
356 aLine->data()->boolean(AUXILIARY_ID())->setValue(anAuxiliary);