]> SALOME platform Git repositories - modules/shaper.git/blob - src/SketchPlugin/SketchPlugin_Circle.cpp
Salome HOME
[GITHUB #2] problem in export dialog - difference in STEP vs BREP
[modules/shaper.git] / src / SketchPlugin / SketchPlugin_Circle.cpp
1 // Copyright (C) 2014-2024  CEA, EDF
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_Circle.h"
21 #include "SketchPlugin_Sketch.h"
22 #include "SketchPlugin_Tools.h"
23 #include <ModelAPI_Data.h>
24 #include <ModelAPI_ResultConstruction.h>
25 #include <ModelAPI_AttributeSelection.h>
26 #include <ModelAPI_AttributeReference.h>
27 #include <ModelAPI_AttributeInteger.h>
28 #include <ModelAPI_AttributeDouble.h>
29 #include <ModelAPI_AttributeString.h>
30 #include <ModelAPI_Events.h>
31 #include <ModelAPI_Session.h>
32 #include <ModelAPI_Tools.h>
33 #include <ModelAPI_Validator.h>
34 #include <SketchPlugin_Point.h>
35 #include <SketchPlugin_ConstraintCoincidenceInternal.h>
36
37 #include <GeomAPI_Pnt2d.h>
38 #include <GeomAPI_Circ.h>
39 #include <GeomAPI_Dir2d.h>
40 #include <GeomAPI_Circ2d.h>
41 #include <GeomAPI_Vertex.h>
42 #include <GeomAPI_XY.h>
43 #include <GeomDataAPI_Point2D.h>
44 #include <GeomDataAPI_Dir.h>
45 #include <GeomAlgoAPI_PointBuilder.h>
46 #include <GeomAlgoAPI_EdgeBuilder.h>
47 #include <GeomAlgoAPI_CompoundBuilder.h>
48
49 #include <Events_Loop.h>
50
51 #include <cmath>
52
53 const double tolerance = 1e-7;
54 const double paramTolerance = 1.e-4;
55 const double PI = 3.141592653589793238463;
56
57 //*************************************************************************************
58 SketchPlugin_Circle::SketchPlugin_Circle()
59 : SketchPlugin_SketchEntity()
60 {
61 }
62
63 //*************************************************************************************
64 void SketchPlugin_Circle::initDerivedClassAttributes()
65 {
66   data()->addAttribute(CENTER_ID(), GeomDataAPI_Point2D::typeId());
67   data()->addAttribute(RADIUS_ID(), ModelAPI_AttributeDouble::typeId());
68   data()->addAttribute(EXTERNAL_ID(), ModelAPI_AttributeSelection::typeId());
69
70   // Attrs for construction point
71   data()->addAttribute(CONSTRUCTION_POINT_REF_ID(), ModelAPI_AttributeReference::typeId());
72   data()->addAttribute(ANGLE_ID(), ModelAPI_AttributeDouble::typeId());
73
74   AttributeDoublePtr anAngleAttr = std::dynamic_pointer_cast<ModelAPI_AttributeDouble>
75      (data()->addAttribute(ANGLE_ID(), ModelAPI_AttributeDouble::typeId()));
76   if(!anAngleAttr->isInitialized())
77   {
78     anAngleAttr->setValue(0.0);
79   }
80
81   AttributeBooleanPtr isAddConstrAttr = std::dynamic_pointer_cast<ModelAPI_AttributeBoolean>
82      (data()->addAttribute(ADD_CONSTRUCTION_POINT_ID(), ModelAPI_AttributeBoolean::typeId()));
83   if (!isAddConstrAttr->isInitialized())
84   {
85     isAddConstrAttr->setValue(false);
86   }
87
88   ModelAPI_Session::get()->validators()->registerNotObligatory(getKind(), EXTERNAL_ID());
89   ModelAPI_Session::get()->validators()->registerNotObligatory(getKind(), ADD_CONSTRUCTION_POINT_ID());
90   ModelAPI_Session::get()->validators()->registerNotObligatory(getKind(), CONSTRUCTION_POINT_REF_ID());
91   ModelAPI_Session::get()->validators()->registerNotObligatory(getKind(), ANGLE_ID());
92 }
93
94 //*************************************************************************************
95 void SketchPlugin_Circle::execute()
96 {
97   SketchPlugin_Sketch* aSketch = sketch();
98   if (!aSketch) {
99     return;
100   }
101
102   //manage construction point movement/deletion
103   bool isToAddPoint = boolean(ADD_CONSTRUCTION_POINT_ID())->value();
104   AttributeReferencePtr aConstrRefAttr = reference((CONSTRUCTION_POINT_REF_ID()));
105   if(aConstrRefAttr->isInitialized())
106     isToAddPoint ? computeAngle(): removeConstructionPoint();
107
108   // Compute a circle in 3D view.
109   std::shared_ptr<GeomDataAPI_Point2D> aCenterAttr =
110     std::dynamic_pointer_cast<GeomDataAPI_Point2D>(data()->attribute(CENTER_ID()));
111   AttributeDoublePtr aRadiusAttr = real(RADIUS_ID());
112   if (!aCenterAttr->isInitialized() || !aRadiusAttr->isInitialized()) {
113     return;
114   }
115
116   double aRadius = aRadiusAttr->value();
117   if (aRadius < tolerance) {
118     return;
119   }
120
121   // Make a visible center point.
122   SketchPlugin_Sketch::createPoint2DResult(this, sketch(), CENTER_ID(), 0);
123
124   // Make a visible circle.
125   std::shared_ptr<GeomAPI_Pnt> aCenter(aSketch->to3D(aCenterAttr->x(), aCenterAttr->y()));
126   std::shared_ptr<GeomDataAPI_Dir> aNDir = std::dynamic_pointer_cast<GeomDataAPI_Dir>(
127     aSketch->data()->attribute(SketchPlugin_Sketch::NORM_ID()));
128   std::shared_ptr<GeomAPI_Dir> aNormal(new GeomAPI_Dir(aNDir->x(), aNDir->y(), aNDir->z()));
129
130   AttributeDoublePtr anAngleAttr = real(ANGLE_ID());
131   if (!anAngleAttr->isInitialized())
132     anAngleAttr->setValue(0);
133   double aValAn = anAngleAttr->value();
134
135   std::shared_ptr<GeomAPI_Edge> aCircleShape = GeomAlgoAPI_EdgeBuilder::lineCircle(aCenter, aNormal, aRadius, aValAn / 180 * PI);
136
137   std::shared_ptr<ModelAPI_ResultConstruction> aResult = document()->createConstruction(data(), 1);
138   aResult->setShape(aCircleShape);
139   aResult->setIsInHistory(false);
140   setResult(aResult, 1);
141
142   if(isToAddPoint && !aConstrRefAttr->isInitialized())
143     setConstructionPoint();
144 }
145
146 //*************************************************************************************
147 std::shared_ptr<GeomAPI_Edge> SketchPlugin_Circle::getCircleShape()
148 {
149   std::shared_ptr<GeomAPI_Shape> aSelection;
150   ResultPtr aCircleRes = lastResult();
151   if (aCircleRes)
152     aSelection = aCircleRes->shape();
153   if (aSelection && !aSelection->isNull() && aSelection->isEdge()) 
154   {
155     return std::shared_ptr<GeomAPI_Edge>(new GeomAPI_Edge(aSelection));
156   }
157   return {};
158 }
159
160 //*************************************************************************************
161 void SketchPlugin_Circle::computeAngle()
162 {
163   if(!boolean(ADD_CONSTRUCTION_POINT_ID())->value()){
164     return;
165   }
166
167   AttributeReferencePtr aConstrRefAttr = reference((CONSTRUCTION_POINT_REF_ID()));
168   std::shared_ptr<GeomAPI_Edge> anCircEdge = getCircleShape();
169   if(anCircEdge && aConstrRefAttr->isInitialized())
170   {
171     std::shared_ptr<GeomAPI_Circ> aCirc = anCircEdge->circle();
172
173     // Get point and project it on line
174     FeaturePtr aPointFeature = ModelAPI_Feature::feature(aConstrRefAttr->value());
175     AttributePoint2DPtr aConstrPoint = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
176            aPointFeature->attribute(SketchPlugin_Point::COORD_ID()));
177     GeomPointPtr aPntRot3D = aCirc->project( sketch()->to3D(aConstrPoint->x(), aConstrPoint->y()));
178
179     // Compute new angle
180     GeomPointPtr aNorm = sketch()->to3D(real(RADIUS_ID())->value(), 0);
181     double aStartParam, anEndParam;
182     aCirc->parameter(aPntRot3D, paramTolerance, anEndParam);
183     aCirc->parameter(aNorm, paramTolerance, aStartParam);
184
185     bool aWasBlocked = data()->blockSendAttributeUpdated(true);
186     real(ANGLE_ID())->setValue((anEndParam - aStartParam) / PI * 180.0);
187     data()->blockSendAttributeUpdated(aWasBlocked, false);
188   }
189 }
190
191 //*************************************************************************************
192 void SketchPlugin_Circle::setConstructionPoint()
193 {
194   if(!boolean(ADD_CONSTRUCTION_POINT_ID())->value()){
195     return;
196   }
197
198   SketchPlugin_Sketch* aSketch = sketch();
199   if (!aSketch) {
200     return;
201   }
202
203   AttributeReferencePtr aConstrRefAttr = reference((CONSTRUCTION_POINT_REF_ID()));
204   if(!aConstrRefAttr->isInitialized())
205   {
206     bool aWasBlocked = data()->blockSendAttributeUpdated(true);
207     std::shared_ptr<GeomAPI_Edge> anCircEdge = getCircleShape();
208     GeomPnt2dPtr aCircleSewPoint = aSketch->to2D(anCircEdge->firstPoint());
209
210     FeaturePtr aPointFeature = aSketch->addFeature(SketchPlugin_Point::ID());
211     auto aCurCircle = this->document()->currentFeature(true);
212     aPointFeature->reference(SketchPlugin_Point::PARENT_ID())->setValue(aCurCircle);
213     AttributePoint2DPtr aCoord = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
214           aPointFeature->attribute(SketchPlugin_Point::COORD_ID()));
215     aCoord->setValue(aCircleSewPoint);
216     aPointFeature->execute();
217     aConstrRefAttr->setValue(aPointFeature);
218
219     SketchPlugin_Tools::createConstraintAttrObject(aSketch,
220            SketchPlugin_ConstraintCoincidence::ID(), aCoord, lastResult());
221     data()->blockSendAttributeUpdated(aWasBlocked, false);
222   }
223 }
224
225 //*************************************************************************************
226 void SketchPlugin_Circle::removeConstructionPoint()
227 {
228   AttributeReferencePtr aConstrRefAttr = reference((CONSTRUCTION_POINT_REF_ID()));
229   FeaturePtr aPointFeature = ModelAPI_Feature::feature(aConstrRefAttr->value());
230   if (aPointFeature)
231   {
232     std::set<FeaturePtr> aDummySet;
233     aDummySet.insert(aPointFeature);
234     std::map<FeaturePtr, std::set<FeaturePtr>> aReferenceMap;
235     ModelAPI_Tools::findAllReferences(aDummySet, aReferenceMap, false, true);
236     std::set<FeaturePtr> aFeaturesRefsTo;
237     ModelAPI_Tools::findRefsToFeatures(aDummySet, aReferenceMap, aFeaturesRefsTo);
238
239     // remove all references to the point except the circle feature(this)
240     for(auto aFeature : aFeaturesRefsTo)
241     {
242       if (aFeature->getKind() != this->ID())
243         document()->removeFeature(aFeature);
244     }
245     document()->removeFeature(aPointFeature);
246     Events_Loop::loop()->flush(Events_Loop::eventByName(EVENT_OBJECT_DELETED));
247   }
248   aConstrRefAttr->setValue(FeaturePtr());
249   aConstrRefAttr->reset();
250   real(ANGLE_ID())->setValue(0.0);
251 }
252
253 //*************************************************************************************
254 bool SketchPlugin_Circle::isFixed() {
255   return data()->selection(EXTERNAL_ID())->context().get() != NULL;
256 }
257
258 //*************************************************************************************
259 void SketchPlugin_Circle::attributeChanged(const std::string& theID) {
260   // the second condition for unability to move external segments anywhere
261   if (theID == EXTERNAL_ID() || isFixed()) {
262     std::shared_ptr<GeomAPI_Shape> aSelection = data()->selection(EXTERNAL_ID())->value();
263     if (!aSelection) {
264       // empty shape in selection shows that the shape is equal to context
265       ResultPtr anExtRes = selection(EXTERNAL_ID())->context();
266       if (anExtRes)
267         aSelection = anExtRes->shape();
268     }
269     // update arguments due to the selection value
270     if (aSelection && !aSelection->isNull() && aSelection->isEdge()) {
271       std::shared_ptr<GeomAPI_Edge> anEdge( new GeomAPI_Edge(aSelection));
272       std::shared_ptr<GeomAPI_Circ> aCirc = anEdge->circle();
273       std::shared_ptr<GeomDataAPI_Point2D> aCenterAttr =
274         std::dynamic_pointer_cast<GeomDataAPI_Point2D>(attribute(CENTER_ID()));
275       aCenterAttr->setValue(sketch()->to2D(aCirc->center()));
276
277       real(RADIUS_ID())->setValue(aCirc->radius());
278       real(ANGLE_ID())->setValue(0.0);
279     }
280   }
281 }