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"
25 #include <ModelAPI_Data.h>
26 #include <ModelAPI_ResultConstruction.h>
27 #include <ModelAPI_AttributeSelection.h>
28 #include <ModelAPI_Validator.h>
29 #include <ModelAPI_AttributeString.h>
30 #include <ModelAPI_Session.h>
31 #include <ModelAPI_AttributeRefList.h>
32 #include <ModelAPI_AttributeRefAttr.h>
33 #include <ModelAPI_AttributeReference.h>
34 #include <ModelAPI_Events.h>
36 #include <GeomAlgoAPI_CompoundBuilder.h>
37 #include <GeomAlgoAPI_EdgeBuilder.h>
38 #include <GeomAlgoAPI_PointBuilder.h>
40 #include <GeomAPI_Pnt2d.h>
44 const double tolerance = 1e-7;
47 SketchPlugin_MacroRectangle::SketchPlugin_MacroRectangle()
48 : SketchPlugin_SketchEntity(), myHasCenterPoint(false)
52 void SketchPlugin_MacroRectangle::initAttributes()
54 data()->addAttribute(AUXILIARY_ID(), ModelAPI_AttributeBoolean::typeId());
55 data()->addAttribute(START1_ID(), GeomDataAPI_Point2D::typeId());
56 data()->addAttribute(END1_ID(), GeomDataAPI_Point2D::typeId());
57 data()->addAttribute(END2_ID(), GeomDataAPI_Point2D::typeId());
58 data()->addAttribute(CENTER_ID(), GeomDataAPI_Point2D::typeId());
59 data()->addAttribute(RECTANGLE_TYPE_ID(), ModelAPI_AttributeString::typeId());
60 data()->addAttribute(EDIT_RECTANGLE_TYPE_ID(), ModelAPI_AttributeString::typeId());
61 ModelAPI_Session::get()->validators()->registerNotObligatory(getKind(), EDIT_RECTANGLE_TYPE_ID());
63 string(EDIT_RECTANGLE_TYPE_ID())->setValue("");
66 void SketchPlugin_MacroRectangle::endPoint()
68 std::shared_ptr<GeomDataAPI_Point2D> aEndPoint;
69 if(string(RECTANGLE_TYPE_ID())->value() == START_END_POINT_TYPE_ID())
70 aEndPoint = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(data()->attribute(END1_ID()));
72 aEndPoint = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(data()->attribute(END2_ID()));
73 if(aEndPoint->isInitialized())
74 myEndPoint = std::make_shared<GeomAPI_Pnt2d>(aEndPoint->x(), aEndPoint->y());
79 void SketchPlugin_MacroRectangle::startPoint()
81 if(string(RECTANGLE_TYPE_ID())->value() == START_END_POINT_TYPE_ID())
83 std::shared_ptr<GeomDataAPI_Point2D> aStartPoint =
84 std::dynamic_pointer_cast<GeomDataAPI_Point2D>(data()->attribute(START1_ID()));
85 if(aStartPoint->isInitialized())
86 myStartPoint = std::make_shared<GeomAPI_Pnt2d>(aStartPoint->x(), aStartPoint->y());
92 /// Compute end point as the symmetric of start point w.r.t. center
93 std::shared_ptr<GeomDataAPI_Point2D> aEndPoint =
94 std::dynamic_pointer_cast<GeomDataAPI_Point2D>(data()->attribute(END2_ID()));
95 std::shared_ptr<GeomDataAPI_Point2D> aCenterPoint =
96 std::dynamic_pointer_cast<GeomDataAPI_Point2D>(data()->attribute(CENTER_ID()));
98 if(aCenterPoint->isInitialized())
100 myCenterPoint = std::make_shared<GeomAPI_Pnt2d>(aCenterPoint->x(), aCenterPoint->y());
101 myHasCenterPoint = true;
103 double xStart = 2.0*aCenterPoint->x() - aEndPoint->x();
104 double yStart = 2.0*aCenterPoint->y() - aEndPoint->y();
106 if(aEndPoint->isInitialized() && aCenterPoint->isInitialized())
107 myStartPoint = std::make_shared<GeomAPI_Pnt2d>(xStart, yStart);
109 myStartPoint.reset();
114 void SketchPlugin_MacroRectangle::execute()
116 SketchPlugin_Sketch* aSketch = sketch();
117 if(!myStartPoint || !myEndPoint || !aSketch) {
120 // Wait all constraints being created, then send update events
121 static Events_ID anUpdateEvent = Events_Loop::eventByName(EVENT_OBJECT_UPDATED);
122 bool isUpdateFlushed = Events_Loop::loop()->isFlushed(anUpdateEvent);
124 Events_Loop::loop()->setFlushed(anUpdateEvent, false);
126 /// create a rectangle sketch
127 FeaturePtr myRectangleFeature = aSketch->addFeature(SketchPlugin_Rectangle::ID());
128 if(!myRectangleFeature)
131 if(myHasCenterPoint){
132 std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
133 myRectangleFeature->attribute(SketchPlugin_Rectangle::CENTER_ID()))->setValue(myCenterPoint->x(),
137 std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
138 myRectangleFeature->attribute(SketchPlugin_Rectangle::START_ID()))->setValue(myStartPoint->x(),
140 std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
141 myRectangleFeature->attribute(SketchPlugin_Rectangle::END_ID()))->setValue(myEndPoint->x(),
144 myRectangleFeature->boolean(SketchPlugin_Rectangle::AUXILIARY_ID())
145 ->setValue(boolean(AUXILIARY_ID())->value());
146 myRectangleFeature->execute();
148 /// Send events to update the sub-features by the solver.
150 Events_Loop::loop()->setFlushed(anUpdateEvent, true);
153 void SketchPlugin_MacroRectangle::attributeChanged(const std::string& theID)
155 if(theID == RECTANGLE_TYPE_ID()) {
156 SketchPlugin_Tools::resetAttribute(this, START1_ID());
157 SketchPlugin_Tools::resetAttribute(this, END1_ID());
158 SketchPlugin_Tools::resetAttribute(this, CENTER_ID());
159 SketchPlugin_Tools::resetAttribute(this, END2_ID());
161 else if (theID == START1_ID() || theID == END1_ID() ||
162 theID == END2_ID() || theID == CENTER_ID())
168 bool aWasBlocked = data()->blockSendAttributeUpdated(true);
169 data()->blockSendAttributeUpdated(aWasBlocked, false);
172 AISObjectPtr SketchPlugin_MacroRectangle::getAISObject(AISObjectPtr thePrevious)
174 SketchPlugin_Sketch* aSketch = sketch();
176 if(!aSketch || !myEndPoint || ! myStartPoint)
177 return AISObjectPtr();
179 std::vector<double> aX = {myStartPoint->x(), myStartPoint->x(), myEndPoint->x(), myEndPoint->x()};
180 std::vector<double> aY = {myStartPoint->y(), myEndPoint->y(), myEndPoint->y(), myStartPoint->y()};
182 std::list<std::shared_ptr<GeomAPI_Shape> > aShapes;
183 /// Update coordinates of rectangle lines
185 std::set<int> createdPointIndex;
186 for(unsigned i = 0; i < 4; i++)
188 std::shared_ptr<GeomAPI_Pnt> theStart(aSketch->to3D(aX[(i+3)%4], aY[(i+3)%4]));
189 std::shared_ptr<GeomAPI_Pnt> theEnd(aSketch->to3D(aX[i], aY[i]));
190 GeomShapePtr aLine = GeomAlgoAPI_EdgeBuilder::line(theStart, theEnd);
194 aShapes.push_back(aLine);
195 if(createdPointIndex.insert(i).second){
196 GeomShapePtr aPointShape = GeomAlgoAPI_PointBuilder::vertex(theStart);
197 aShapes.push_back(aPointShape);
199 if(createdPointIndex.insert((i+1)%4).second){
200 GeomShapePtr aPointShape = GeomAlgoAPI_PointBuilder::vertex(theEnd);
201 aShapes.push_back(aPointShape);
206 if(string(RECTANGLE_TYPE_ID())->value() == CENTER_END_POINT_TYPE_ID()){
207 /// draw a line center->end
208 std::shared_ptr<GeomDataAPI_Point2D> aCenterPoint =
209 std::dynamic_pointer_cast<GeomDataAPI_Point2D>(data()->attribute(CENTER_ID()));
211 std::shared_ptr<GeomAPI_Pnt> theEnd(aSketch->to3D(myEndPoint->x(), myEndPoint->y()));
212 std::shared_ptr<GeomAPI_Pnt> theStart(aSketch->to3D(aCenterPoint->x(), aCenterPoint->y()));
213 GeomShapePtr aLine = GeomAlgoAPI_EdgeBuilder::line(theStart, theEnd);
215 aShapes.push_back(aLine);
218 // Compute a rectangle in 3D view.
220 std::shared_ptr<GeomAPI_Shape> aCompound = GeomAlgoAPI_CompoundBuilder::compound(aShapes);
221 AISObjectPtr anAIS = thePrevious;
223 anAIS.reset(new GeomAPI_AISObject());
225 anAIS->createShape(aCompound);
228 SketchPlugin_Tools::customizeFeaturePrs(anAIS, boolean(AUXILIARY_ID())->value());