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_MacroRectangle.h"
21 #include "SketchPlugin_Rectangle.h"
22 #include "SketchPlugin_Sketch.h"
23 #include "SketchPlugin_Tools.h"
24 #include "SketchPlugin_Line.h"
26 #include <ModelAPI_Data.h>
27 #include <ModelAPI_ResultConstruction.h>
28 #include <ModelAPI_AttributeSelection.h>
29 #include <ModelAPI_Validator.h>
30 #include <ModelAPI_AttributeString.h>
31 #include <ModelAPI_Session.h>
32 #include <ModelAPI_AttributeRefList.h>
33 #include <ModelAPI_AttributeRefAttr.h>
34 #include <ModelAPI_AttributeReference.h>
35 #include <ModelAPI_Events.h>
37 #include <GeomAlgoAPI_CompoundBuilder.h>
38 #include <GeomAlgoAPI_EdgeBuilder.h>
39 #include <GeomAlgoAPI_PointBuilder.h>
41 #include <GeomAPI_Pnt2d.h>
45 const double tolerance = 1e-7;
48 SketchPlugin_MacroRectangle::SketchPlugin_MacroRectangle()
49 : SketchPlugin_SketchEntity(), myHasCenterPoint(false)
53 void SketchPlugin_MacroRectangle::initAttributes()
55 data()->addAttribute(AUXILIARY_ID(), ModelAPI_AttributeBoolean::typeId());
56 data()->addAttribute(START1_ID(), GeomDataAPI_Point2D::typeId());
57 data()->addAttribute(START1_REF_ID(), ModelAPI_AttributeRefAttr::typeId());
58 data()->addAttribute(END1_ID(), GeomDataAPI_Point2D::typeId());
59 data()->addAttribute(END1_REF_ID(), ModelAPI_AttributeRefAttr::typeId());
60 data()->addAttribute(END2_ID(), GeomDataAPI_Point2D::typeId());
61 data()->addAttribute(END2_REF_ID(), ModelAPI_AttributeRefAttr::typeId());
62 data()->addAttribute(CENTER_ID(), GeomDataAPI_Point2D::typeId());
63 data()->addAttribute(CENTER_REF_ID(), ModelAPI_AttributeRefAttr::typeId());
64 data()->addAttribute(RECTANGLE_TYPE_ID(), ModelAPI_AttributeString::typeId());
65 data()->addAttribute(EDIT_RECTANGLE_TYPE_ID(), ModelAPI_AttributeString::typeId());
66 ModelAPI_Session::get()->validators()->registerNotObligatory(getKind(), EDIT_RECTANGLE_TYPE_ID());
67 ModelAPI_Session::get()->validators()->registerNotObligatory(getKind(), CENTER_REF_ID());
68 ModelAPI_Session::get()->validators()->registerNotObligatory(getKind(), END2_REF_ID());
69 ModelAPI_Session::get()->validators()->registerNotObligatory(getKind(), END1_REF_ID());
70 ModelAPI_Session::get()->validators()->registerNotObligatory(getKind(), START1_REF_ID());
72 string(EDIT_RECTANGLE_TYPE_ID())->setValue("");
75 void SketchPlugin_MacroRectangle::endPoint()
77 std::shared_ptr<GeomDataAPI_Point2D> aEndPoint;
78 if(string(RECTANGLE_TYPE_ID())->value() == START_END_POINT_TYPE_ID())
79 aEndPoint = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(data()->attribute(END1_ID()));
81 aEndPoint = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(data()->attribute(END2_ID()));
82 if(aEndPoint->isInitialized())
83 myEndPoint = std::make_shared<GeomAPI_Pnt2d>(aEndPoint->x(), aEndPoint->y());
88 void SketchPlugin_MacroRectangle::startPoint()
90 if(string(RECTANGLE_TYPE_ID())->value() == START_END_POINT_TYPE_ID())
92 std::shared_ptr<GeomDataAPI_Point2D> aStartPoint =
93 std::dynamic_pointer_cast<GeomDataAPI_Point2D>(data()->attribute(START1_ID()));
94 if(aStartPoint->isInitialized())
95 myStartPoint = std::make_shared<GeomAPI_Pnt2d>(aStartPoint->x(), aStartPoint->y());
101 /// Compute end point as the symmetric of start point w.r.t. center
102 std::shared_ptr<GeomDataAPI_Point2D> aEndPoint =
103 std::dynamic_pointer_cast<GeomDataAPI_Point2D>(data()->attribute(END2_ID()));
104 std::shared_ptr<GeomDataAPI_Point2D> aCenterPoint =
105 std::dynamic_pointer_cast<GeomDataAPI_Point2D>(data()->attribute(CENTER_ID()));
107 if(aCenterPoint->isInitialized())
109 myCenterPoint = std::make_shared<GeomAPI_Pnt2d>(aCenterPoint->x(), aCenterPoint->y());
110 myHasCenterPoint = true;
112 double xStart = 2.0*aCenterPoint->x() - aEndPoint->x();
113 double yStart = 2.0*aCenterPoint->y() - aEndPoint->y();
115 if(aEndPoint->isInitialized() && aCenterPoint->isInitialized())
116 myStartPoint = std::make_shared<GeomAPI_Pnt2d>(xStart, yStart);
118 myStartPoint.reset();
123 void SketchPlugin_MacroRectangle::execute()
125 SketchPlugin_Sketch* aSketch = sketch();
126 if(!myStartPoint || !myEndPoint || !aSketch) {
129 // Wait all constraints being created, then send update events
130 static Events_ID anUpdateEvent = Events_Loop::eventByName(EVENT_OBJECT_UPDATED);
131 bool isUpdateFlushed = Events_Loop::loop()->isFlushed(anUpdateEvent);
133 Events_Loop::loop()->setFlushed(anUpdateEvent, false);
135 /// create a rectangle sketch
136 FeaturePtr myRectangleFeature = aSketch->addFeature(SketchPlugin_Rectangle::ID());
137 if(!myRectangleFeature)
140 if(myHasCenterPoint){
141 std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
142 myRectangleFeature->attribute(SketchPlugin_Rectangle::CENTER_ID()))->setValue(myCenterPoint->x(),
146 std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
147 myRectangleFeature->attribute(SketchPlugin_Rectangle::START_ID()))->setValue(myStartPoint->x(),
149 std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
150 myRectangleFeature->attribute(SketchPlugin_Rectangle::END_ID()))->setValue(myEndPoint->x(),
153 myRectangleFeature->boolean(SketchPlugin_Rectangle::AUXILIARY_ID())
154 ->setValue(boolean(AUXILIARY_ID())->value());
155 myRectangleFeature->execute();
157 /// create coincidences with rectangle start/center and end points
158 AttributeRefListPtr aLinesList = myRectangleFeature->reflist(SketchPlugin_Rectangle::LINES_LIST_ID());
159 FeaturePtr aRectangleStartLineFeature = std::dynamic_pointer_cast<ModelAPI_Feature>(aLinesList->object(0));
160 FeaturePtr aRectangleEndLineFeature = std::dynamic_pointer_cast<ModelAPI_Feature>(aLinesList->object(2));
161 std::shared_ptr<GeomDataAPI_Point2D> aRectanglePointEndAttr =
162 std::dynamic_pointer_cast<GeomDataAPI_Point2D>(aRectangleEndLineFeature->attribute(SketchPlugin_Line::END_ID()));
163 std::shared_ptr<GeomDataAPI_Point2D> aRectanglePointStartAttr =
164 std::dynamic_pointer_cast<GeomDataAPI_Point2D>(aRectangleStartLineFeature->attribute(SketchPlugin_Line::END_ID()));
166 if(myHasCenterPoint){
167 FeaturePtr aCenterPointFeature = std::dynamic_pointer_cast<ModelAPI_Feature>(myRectangleFeature->refattr(CENTER_REF_ID())->object());
168 SketchPlugin_Tools::createCoincidenceOrTangency(
169 this, CENTER_REF_ID(), AttributePtr(), aCenterPointFeature, false);
170 SketchPlugin_Tools::createCoincidenceOrTangency(
171 this, END2_REF_ID(), aRectanglePointEndAttr, ObjectPtr(), false);
174 SketchPlugin_Tools::createCoincidenceOrTangency(
175 this, START1_REF_ID(), aRectanglePointStartAttr, ObjectPtr(), false);
176 SketchPlugin_Tools::createCoincidenceOrTangency(
177 this, END1_REF_ID(), aRectanglePointEndAttr, ObjectPtr(), false);
180 /// Send events to update the sub-features by the solver.
182 Events_Loop::loop()->setFlushed(anUpdateEvent, true);
185 void SketchPlugin_MacroRectangle::attributeChanged(const std::string& theID)
187 if(theID == RECTANGLE_TYPE_ID()) {
188 SketchPlugin_Tools::resetAttribute(this, START1_ID());
189 SketchPlugin_Tools::resetAttribute(this, END1_ID());
190 SketchPlugin_Tools::resetAttribute(this, CENTER_ID());
191 SketchPlugin_Tools::resetAttribute(this, END2_ID());
192 SketchPlugin_Tools::resetAttribute(this, START1_REF_ID());
193 SketchPlugin_Tools::resetAttribute(this, END1_REF_ID());
194 SketchPlugin_Tools::resetAttribute(this, CENTER_REF_ID());
195 SketchPlugin_Tools::resetAttribute(this, END2_REF_ID());
196 myStartPoint.reset();
198 myCenterPoint.reset();
199 myHasCenterPoint = false;
201 else if (theID == START1_ID() || theID == END1_ID() ||
202 theID == START1_REF_ID() || theID == END1_REF_ID() ||
203 theID == END2_ID() || theID == CENTER_ID() ||
204 theID == END2_REF_ID() || theID == CENTER_REF_ID())
210 bool aWasBlocked = data()->blockSendAttributeUpdated(true);
211 data()->blockSendAttributeUpdated(aWasBlocked, false);
214 AISObjectPtr SketchPlugin_MacroRectangle::getAISObject(AISObjectPtr thePrevious)
216 SketchPlugin_Sketch* aSketch = sketch();
218 if(!aSketch || !myEndPoint || ! myStartPoint)
219 return AISObjectPtr();
221 std::vector<double> aX = {myStartPoint->x(), myStartPoint->x(), myEndPoint->x(), myEndPoint->x()};
222 std::vector<double> aY = {myStartPoint->y(), myEndPoint->y(), myEndPoint->y(), myStartPoint->y()};
224 std::list<std::shared_ptr<GeomAPI_Shape> > aShapes;
225 /// Update coordinates of rectangle lines
227 std::set<int> createdPointIndex;
228 for(unsigned i = 0; i < 4; i++)
230 std::shared_ptr<GeomAPI_Pnt> theStart(aSketch->to3D(aX[(i+3)%4], aY[(i+3)%4]));
231 std::shared_ptr<GeomAPI_Pnt> theEnd(aSketch->to3D(aX[i], aY[i]));
232 GeomShapePtr aLine = GeomAlgoAPI_EdgeBuilder::line(theStart, theEnd);
236 aShapes.push_back(aLine);
237 if(createdPointIndex.insert(i).second){
238 GeomShapePtr aPointShape = GeomAlgoAPI_PointBuilder::vertex(theStart);
239 aShapes.push_back(aPointShape);
241 if(createdPointIndex.insert((i+1)%4).second){
242 GeomShapePtr aPointShape = GeomAlgoAPI_PointBuilder::vertex(theEnd);
243 aShapes.push_back(aPointShape);
248 if(string(RECTANGLE_TYPE_ID())->value() == CENTER_END_POINT_TYPE_ID()){
249 /// draw a line center->end
250 std::shared_ptr<GeomDataAPI_Point2D> aCenterPoint =
251 std::dynamic_pointer_cast<GeomDataAPI_Point2D>(data()->attribute(CENTER_ID()));
253 std::shared_ptr<GeomAPI_Pnt> theEnd(aSketch->to3D(myEndPoint->x(), myEndPoint->y()));
254 std::shared_ptr<GeomAPI_Pnt> theStart(aSketch->to3D(aCenterPoint->x(), aCenterPoint->y()));
255 GeomShapePtr aLine = GeomAlgoAPI_EdgeBuilder::line(theStart, theEnd);
257 aShapes.push_back(aLine);
260 // Compute a rectangle in 3D view.
262 std::shared_ptr<GeomAPI_Shape> aCompound = GeomAlgoAPI_CompoundBuilder::compound(aShapes);
263 AISObjectPtr anAIS = thePrevious;
265 anAIS.reset(new GeomAPI_AISObject());
267 anAIS->createShape(aCompound);
270 SketchPlugin_Tools::customizeFeaturePrs(anAIS, boolean(AUXILIARY_ID())->value());