Salome HOME
rectangle feature: complete rectangle type by center and end points
[modules/shaper.git] / src / SketchPlugin / SketchPlugin_MacroRectangle.cpp
1 // Copyright (C) 2014-2020  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 #include "SketchPlugin_MacroRectangle.h"
21 #include "SketchPlugin_Rectangle.h"
22 #include "SketchPlugin_Sketch.h"
23 #include "SketchPlugin_Tools.h"
24
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>
35
36 #include <GeomAlgoAPI_CompoundBuilder.h>
37 #include <GeomAlgoAPI_EdgeBuilder.h>
38 #include <GeomAlgoAPI_PointBuilder.h>
39
40 #include <GeomAPI_Pnt2d.h>
41
42 #include <cmath>
43
44 const double tolerance = 1e-7;
45
46
47 SketchPlugin_MacroRectangle::SketchPlugin_MacroRectangle()
48   : SketchPlugin_SketchEntity(), myHasCenterPoint(false)
49 {  
50 }
51
52 void SketchPlugin_MacroRectangle::initAttributes()
53 {
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());
62
63   string(EDIT_RECTANGLE_TYPE_ID())->setValue("");
64 }
65
66 void SketchPlugin_MacroRectangle::endPoint()
67 {
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()));
71   else
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());
75   else
76     myEndPoint.reset();
77 }
78
79 void SketchPlugin_MacroRectangle::startPoint()
80 {
81   if(string(RECTANGLE_TYPE_ID())->value() == START_END_POINT_TYPE_ID())
82   {
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());
87     else
88       myStartPoint.reset();
89   }
90   else
91   {
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()));
97
98     if(aCenterPoint->isInitialized())
99     {
100       myCenterPoint = std::make_shared<GeomAPI_Pnt2d>(aCenterPoint->x(), aCenterPoint->y());
101       myHasCenterPoint = true;
102     }
103     double xStart = 2.0*aCenterPoint->x() - aEndPoint->x();
104     double yStart = 2.0*aCenterPoint->y() - aEndPoint->y();
105
106     if(aEndPoint->isInitialized() && aCenterPoint->isInitialized())
107       myStartPoint =  std::make_shared<GeomAPI_Pnt2d>(xStart, yStart);
108     else
109       myStartPoint.reset();
110   }
111 }
112
113
114 void SketchPlugin_MacroRectangle::execute()
115 {
116   SketchPlugin_Sketch* aSketch = sketch();
117   if(!myStartPoint || !myEndPoint || !aSketch) {
118     return ;
119   }
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);
123   if (isUpdateFlushed)
124     Events_Loop::loop()->setFlushed(anUpdateEvent, false);
125
126   /// create a rectangle sketch
127   FeaturePtr myRectangleFeature = aSketch->addFeature(SketchPlugin_Rectangle::ID());
128   if(!myRectangleFeature)
129     return;
130
131   if(myHasCenterPoint){
132     std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
133           myRectangleFeature->attribute(SketchPlugin_Rectangle::CENTER_ID()))->setValue(myCenterPoint->x(),
134                                                                                        myCenterPoint->y());
135   }
136
137   std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
138         myRectangleFeature->attribute(SketchPlugin_Rectangle::START_ID()))->setValue(myStartPoint->x(),
139                                                                                      myStartPoint->y());
140   std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
141         myRectangleFeature->attribute(SketchPlugin_Rectangle::END_ID()))->setValue(myEndPoint->x(),
142                                                                                    myEndPoint->y());
143
144   myRectangleFeature->boolean(SketchPlugin_Rectangle::AUXILIARY_ID())
145       ->setValue(boolean(AUXILIARY_ID())->value());
146   myRectangleFeature->execute();
147
148   /// Send events to update the sub-features by the solver.
149   if (isUpdateFlushed)
150     Events_Loop::loop()->setFlushed(anUpdateEvent, true);  
151 }
152
153 void SketchPlugin_MacroRectangle::attributeChanged(const std::string& theID)
154 {
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());
160   }
161   else if (theID == START1_ID() || theID == END1_ID() ||
162            theID == END2_ID() || theID == CENTER_ID())
163   {
164     // update points
165     startPoint();
166     endPoint();
167   }
168   bool aWasBlocked = data()->blockSendAttributeUpdated(true);
169   data()->blockSendAttributeUpdated(aWasBlocked, false);
170 }
171
172 AISObjectPtr SketchPlugin_MacroRectangle::getAISObject(AISObjectPtr thePrevious)
173 {
174   SketchPlugin_Sketch* aSketch = sketch();
175
176   if(!aSketch || !myEndPoint || ! myStartPoint)
177     return AISObjectPtr();
178
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()};
181
182   std::list<std::shared_ptr<GeomAPI_Shape> > aShapes;
183   /// Update coordinates of rectangle lines
184
185   std::set<int> createdPointIndex;
186   for(unsigned  i = 0; i < 4; i++)
187   {
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);
191
192     if(aLine)
193     {
194       aShapes.push_back(aLine);
195       if(createdPointIndex.insert(i).second){
196         GeomShapePtr aPointShape = GeomAlgoAPI_PointBuilder::vertex(theStart);
197         aShapes.push_back(aPointShape);
198       }
199       if(createdPointIndex.insert((i+1)%4).second){
200         GeomShapePtr aPointShape = GeomAlgoAPI_PointBuilder::vertex(theEnd);
201         aShapes.push_back(aPointShape);
202       }
203     }
204   }
205
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()));
210
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);
214     if(aLine)
215       aShapes.push_back(aLine);
216   }
217
218   // Compute a rectangle in 3D view.
219
220   std::shared_ptr<GeomAPI_Shape> aCompound = GeomAlgoAPI_CompoundBuilder::compound(aShapes);
221   AISObjectPtr anAIS = thePrevious;
222   if(!anAIS.get()) {
223     anAIS.reset(new GeomAPI_AISObject());
224   }
225   anAIS->createShape(aCompound);
226
227   // Modify attributes
228   SketchPlugin_Tools::customizeFeaturePrs(anAIS, boolean(AUXILIARY_ID())->value());
229
230   return anAIS;
231 }
232