Salome HOME
Merge branch 'master' into cgt/devCEA
[modules/shaper.git] / src / PartSet / PartSet_Tools.cpp
1 // Copyright (C) 2014-2017  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
18 // email : webmaster.salome@opencascade.com<mailto:webmaster.salome@opencascade.com>
19 //
20
21 #include <PartSet_Tools.h>
22 #include <PartSet_Module.h>
23 #include <PartSet_SketcherMgr.h>
24
25 #include <ModelAPI_Data.h>
26 #include <ModelAPI_AttributeDouble.h>
27 #include <ModelAPI_AttributeRefList.h>
28 #include <ModelAPI_Document.h>
29 #include <ModelAPI_Session.h>
30 #include <ModelAPI_ResultConstruction.h>
31 #include <ModelAPI_Events.h>
32 #include <ModelAPI_Validator.h>
33 #include <ModelAPI_Tools.h>
34
35 #include <ModuleBase_IViewWindow.h>
36
37 #include <ModelGeomAlgo_Point2D.h>
38
39 #include <Events_Loop.h>
40
41 #include <SketcherPrs_Tools.h>
42
43 #include <XGUI_ModuleConnector.h>
44 #include <XGUI_Displayer.h>
45 #include <XGUI_Workshop.h>
46 #include <XGUI_SelectionMgr.h>
47 #include <XGUI_Selection.h>
48
49 #include <GeomDataAPI_Point.h>
50 #include <GeomDataAPI_Dir.h>
51 #include <GeomDataAPI_Point2D.h>
52 #include <GeomAPI_Pln.h>
53 #include <GeomAPI_Pnt2d.h>
54 #include <GeomAPI_Pnt.h>
55 #include <GeomAPI_Edge.h>
56 #include <GeomAPI_Vertex.h>
57
58 #include <GeomAPI_Dir.h>
59 #include <GeomAPI_XYZ.h>
60
61 #include <SketchPlugin_Feature.h>
62 #include <SketchPlugin_Sketch.h>
63 #include <SketchPlugin_ConstraintCoincidence.h>
64 #include <SketchPlugin_ConstraintDistance.h>
65 #include <SketchPlugin_ConstraintLength.h>
66 #include <SketchPlugin_ConstraintRadius.h>
67 #include <SketchPlugin_ConstraintRigid.h>
68 #include <SketchPlugin_Constraint.h>
69 #include <SketchPlugin_Circle.h>
70 #include <SketchPlugin_Arc.h>
71 #include <SketchPlugin_Line.h>
72 #include <SketchPlugin_Point.h>
73
74 #include <ModuleBase_IWorkshop.h>
75 #include <ModuleBase_ViewerPrs.h>
76 #include <ModuleBase_Tools.h>
77
78 #include <V3d_View.hxx>
79 #include <gp_Pln.hxx>
80 #include <gp_Circ.hxx>
81 #include <ProjLib.hxx>
82 #include <ElSLib.hxx>
83 #include <Geom_Line.hxx>
84 #include <GeomAPI_ProjectPointOnCurve.hxx>
85 #include <BRep_Tool.hxx>
86 #include <TopoDS.hxx>
87 #include <TopoDS_Edge.hxx>
88 #include <TopoDS_Vertex.hxx>
89 #include <AIS_InteractiveObject.hxx>
90 #include <StdSelect_BRepOwner.hxx>
91 #include <SelectMgr_IndexedMapOfOwner.hxx>
92
93 #include <QMouseEvent>
94
95 #ifdef _DEBUG
96 #include <QDebug>
97 #endif
98
99 const double PRECISION_TOLERANCE = 0.000001;
100 const int AIS_DEFAULT_WIDTH = 2;
101
102 int PartSet_Tools::getAISDefaultWidth()
103 {
104   return AIS_DEFAULT_WIDTH;
105 }
106
107 gp_Pnt PartSet_Tools::convertClickToPoint(QPoint thePoint, Handle(V3d_View) theView)
108 {
109   if (theView.IsNull())
110     return gp_Pnt();
111
112   V3d_Coordinate XEye, YEye, ZEye, XAt, YAt, ZAt;
113   theView->Eye(XEye, YEye, ZEye);
114
115   theView->At(XAt, YAt, ZAt);
116   gp_Pnt EyePoint(XEye, YEye, ZEye);
117   gp_Pnt AtPoint(XAt, YAt, ZAt);
118
119   gp_Vec EyeVector(EyePoint, AtPoint);
120   gp_Dir EyeDir(EyeVector);
121
122   gp_Pln PlaneOfTheView = gp_Pln(AtPoint, EyeDir);
123   Standard_Real X, Y, Z;
124   theView->Convert(thePoint.x(), thePoint.y(), X, Y, Z);
125   gp_Pnt ConvertedPoint(X, Y, Z);
126
127   gp_Pnt2d ConvertedPointOnPlane = ProjLib::Project(PlaneOfTheView, ConvertedPoint);
128   gp_Pnt ResultPoint = ElSLib::Value(ConvertedPointOnPlane.X(), ConvertedPointOnPlane.Y(),
129                                      PlaneOfTheView);
130   return ResultPoint;
131 }
132
133 void PartSet_Tools::convertTo2D(const gp_Pnt& thePoint, FeaturePtr theSketch,
134 Handle(V3d_View) theView,
135                                 double& theX, double& theY)
136 {
137   if (!theSketch)
138     return;
139
140   AttributeDoublePtr anAttr;
141   std::shared_ptr<ModelAPI_Data> aData = theSketch->data();
142
143   std::shared_ptr<GeomDataAPI_Point> anOrigin = std::dynamic_pointer_cast<GeomDataAPI_Point>(
144       aData->attribute(SketchPlugin_Sketch::ORIGIN_ID()));
145
146   std::shared_ptr<GeomDataAPI_Dir> aX = std::dynamic_pointer_cast<GeomDataAPI_Dir>(
147       aData->attribute(SketchPlugin_Sketch::DIRX_ID()));
148   std::shared_ptr<GeomDataAPI_Dir> aNorm = std::dynamic_pointer_cast<GeomDataAPI_Dir>(
149       aData->attribute(SketchPlugin_Sketch::NORM_ID()));
150   std::shared_ptr<GeomAPI_XYZ> anY = aNorm->xyz()->cross(aX->xyz());
151
152   gp_Pnt anOriginPnt(anOrigin->x(), anOrigin->y(), anOrigin->z());
153   gp_Vec aVec(anOriginPnt, thePoint);
154
155   if (!theView.IsNull()) {
156     V3d_Coordinate XEye, YEye, ZEye, XAt, YAt, ZAt;
157     theView->Eye(XEye, YEye, ZEye);
158
159     theView->At(XAt, YAt, ZAt);
160     gp_Pnt EyePoint(XEye, YEye, ZEye);
161     gp_Pnt AtPoint(XAt, YAt, ZAt);
162
163     gp_Vec anEyeVec(EyePoint, AtPoint);
164     anEyeVec.Normalize();
165
166     std::shared_ptr<GeomDataAPI_Dir> aNormal = std::dynamic_pointer_cast<GeomDataAPI_Dir>(
167         aData->attribute(SketchPlugin_Sketch::NORM_ID()));
168     gp_Vec aNormalVec(aNormal->x(), aNormal->y(), aNormal->z());
169
170     double aDen = anEyeVec * aNormalVec;
171     double aLVec = aDen != 0 ? aVec * aNormalVec / aDen : DBL_MAX;
172
173     gp_Vec aDeltaVec = anEyeVec * aLVec;
174     aVec = aVec - aDeltaVec;
175   }
176   theX = aVec.X() * aX->x() + aVec.Y() * aX->y() + aVec.Z() * aX->z();
177   theY = aVec.X() * anY->x() + aVec.Y() * anY->y() + aVec.Z() * anY->z();
178 }
179
180 std::shared_ptr<GeomAPI_Pnt2d> PartSet_Tools::convertTo2D(FeaturePtr theSketch,
181                                                     const std::shared_ptr<GeomAPI_Pnt>& thePnt)
182 {
183   std::shared_ptr<GeomAPI_Pnt2d> aRes;
184   if (theSketch->getKind() != SketchPlugin_Sketch::ID())
185     return aRes;
186   std::shared_ptr<GeomDataAPI_Point> aC = std::dynamic_pointer_cast<GeomDataAPI_Point>(
187       theSketch->data()->attribute(SketchPlugin_Sketch::ORIGIN_ID()));
188   std::shared_ptr<GeomDataAPI_Dir> aNorm = std::dynamic_pointer_cast<GeomDataAPI_Dir>(
189       theSketch->data()->attribute(SketchPlugin_Sketch::NORM_ID()));
190   std::shared_ptr<GeomDataAPI_Dir> aX = std::dynamic_pointer_cast<GeomDataAPI_Dir>(
191       theSketch->data()->attribute(SketchPlugin_Sketch::DIRX_ID()));
192   std::shared_ptr<GeomAPI_Dir> aY(new GeomAPI_Dir(aNorm->dir()->cross(aX->dir())));
193   return thePnt->to2D(aC->pnt(), aX->dir(), aY);
194 }
195
196
197 std::shared_ptr<GeomAPI_Pnt> PartSet_Tools::convertTo3D(const double theX, const double theY,
198                                                         FeaturePtr theSketch)
199 {
200   std::shared_ptr<ModelAPI_Data> aData = theSketch->data();
201
202   std::shared_ptr<GeomDataAPI_Point> aC = std::dynamic_pointer_cast<GeomDataAPI_Point>(
203       aData->attribute(SketchPlugin_Sketch::ORIGIN_ID()));
204   std::shared_ptr<GeomDataAPI_Dir> aX = std::dynamic_pointer_cast<GeomDataAPI_Dir>(
205       aData->attribute(SketchPlugin_Sketch::DIRX_ID()));
206   std::shared_ptr<GeomDataAPI_Dir> aNorm = std::dynamic_pointer_cast<GeomDataAPI_Dir>(
207       aData->attribute(SketchPlugin_Sketch::NORM_ID()));
208   std::shared_ptr<GeomAPI_Dir> aY(new GeomAPI_Dir(aNorm->dir()->cross(aX->dir())));
209
210   std::shared_ptr<GeomAPI_Pnt2d> aPnt2d =
211     std::shared_ptr<GeomAPI_Pnt2d>(new GeomAPI_Pnt2d(theX, theY));
212
213   return aPnt2d->to3D(aC->pnt(), aX->dir(), aY);
214 }
215
216 std::shared_ptr<ModelAPI_Document> PartSet_Tools::document()
217 {
218   return ModelAPI_Session::get()->moduleDocument();
219 }
220
221 void PartSet_Tools::setFeatureValue(FeaturePtr theFeature, double theValue,
222                                     const std::string& theAttribute)
223 {
224   if (!theFeature)
225     return;
226   std::shared_ptr<ModelAPI_Data> aData = theFeature->data();
227   AttributeDoublePtr anAttribute = std::dynamic_pointer_cast<ModelAPI_AttributeDouble>(
228       aData->attribute(theAttribute));
229   if (anAttribute)
230     anAttribute->setValue(theValue);
231 }
232
233 double PartSet_Tools::featureValue(FeaturePtr theFeature, const std::string& theAttribute,
234                                    bool& isValid)
235 {
236   isValid = false;
237   double aValue = 0;
238   if (theFeature) {
239     std::shared_ptr<ModelAPI_Data> aData = theFeature->data();
240     AttributeDoublePtr anAttribute = std::dynamic_pointer_cast<ModelAPI_AttributeDouble>(
241         aData->attribute(theAttribute));
242     if (anAttribute) {
243       aValue = anAttribute->value();
244       isValid = true;
245     }
246   }
247   return aValue;
248 }
249
250 FeaturePtr PartSet_Tools::feature(FeaturePtr theFeature, const std::string& theAttribute,
251                                   const std::string& theKind)
252 {
253   FeaturePtr aFeature;
254   if (!theFeature)
255     return aFeature;
256
257   std::shared_ptr<ModelAPI_Data> aData = theFeature->data();
258   std::shared_ptr<ModelAPI_AttributeRefAttr> anAttr = std::dynamic_pointer_cast<
259       ModelAPI_AttributeRefAttr>(aData->attribute(theAttribute));
260   if (anAttr) {
261     aFeature = std::dynamic_pointer_cast<ModelAPI_Feature>(anAttr->object());
262     if (!theKind.empty() && aFeature && aFeature->getKind() != theKind) {
263       aFeature = FeaturePtr();
264     }
265   }
266   return aFeature;
267 }
268
269 void PartSet_Tools::createConstraint(CompositeFeaturePtr theSketch,
270                                      std::shared_ptr<GeomDataAPI_Point2D> thePoint1,
271                                      std::shared_ptr<GeomDataAPI_Point2D> thePoint2)
272 {
273   FeaturePtr aFeature;
274   if (theSketch) {
275     aFeature = theSketch->addFeature(SketchPlugin_ConstraintCoincidence::ID());
276   } else {
277     std::shared_ptr<ModelAPI_Document> aDoc = document();
278     aFeature = aDoc->addFeature(SketchPlugin_ConstraintCoincidence::ID());
279   }
280
281   std::shared_ptr<ModelAPI_Data> aData = aFeature->data();
282
283   std::shared_ptr<ModelAPI_AttributeRefAttr> aRef1 = std::dynamic_pointer_cast<
284       ModelAPI_AttributeRefAttr>(aData->attribute(SketchPlugin_Constraint::ENTITY_A()));
285   aRef1->setAttr(thePoint1);
286
287   std::shared_ptr<ModelAPI_AttributeRefAttr> aRef2 = std::dynamic_pointer_cast<
288       ModelAPI_AttributeRefAttr>(aData->attribute(SketchPlugin_Constraint::ENTITY_B()));
289   aRef2->setAttr(thePoint2);
290
291   // we need to flush created signal in order to coincidence is processed by solver
292   Events_Loop::loop()->flush(Events_Loop::eventByName(EVENT_OBJECT_CREATED));
293 }
294
295 std::shared_ptr<GeomAPI_Pln> PartSet_Tools::sketchPlane(CompositeFeaturePtr theSketch)
296 {
297   std::shared_ptr<GeomAPI_Pln> aPlane;
298
299   std::shared_ptr<GeomDataAPI_Point> anOrigin = std::dynamic_pointer_cast<GeomDataAPI_Point>(
300       theSketch->data()->attribute(SketchPlugin_Sketch::ORIGIN_ID()));
301   std::shared_ptr<GeomDataAPI_Dir> aNormal = std::dynamic_pointer_cast<GeomDataAPI_Dir>(
302       theSketch->data()->attribute(SketchPlugin_Sketch::NORM_ID()));
303
304   if (aNormal.get() && aNormal->isInitialized() &&
305       anOrigin.get() && anOrigin->isInitialized())
306     aPlane = std::shared_ptr<GeomAPI_Pln>(new GeomAPI_Pln(anOrigin->pnt(), aNormal->dir()));
307
308   return aPlane;
309 }
310
311 std::shared_ptr<GeomAPI_Pnt> PartSet_Tools::point3D(std::shared_ptr<GeomAPI_Pnt2d> thePoint2D,
312                                                       CompositeFeaturePtr theSketch)
313 {
314   std::shared_ptr<GeomAPI_Pnt> aPoint;
315   if (!theSketch || !thePoint2D)
316     return aPoint;
317
318   DataPtr aData = theSketch->data();
319   std::shared_ptr<GeomDataAPI_Point> aC = std::dynamic_pointer_cast<GeomDataAPI_Point>(
320       aData->attribute(SketchPlugin_Sketch::ORIGIN_ID()));
321   std::shared_ptr<GeomDataAPI_Dir> aX = std::dynamic_pointer_cast<GeomDataAPI_Dir>(
322       aData->attribute(SketchPlugin_Sketch::DIRX_ID()));
323   std::shared_ptr<GeomDataAPI_Dir> aNorm = std::dynamic_pointer_cast<GeomDataAPI_Dir>(
324       aData->attribute(SketchPlugin_Sketch::NORM_ID()));
325   std::shared_ptr<GeomAPI_Dir> aY(new GeomAPI_Dir(aNorm->dir()->cross(aX->dir())));
326
327   return thePoint2D->to3D(aC->pnt(), aX->dir(), aY);
328 }
329
330 ResultPtr PartSet_Tools::findFixedObjectByExternal(const TopoDS_Shape& theShape,
331                                                    const ObjectPtr& theObject,
332                                                    CompositeFeaturePtr theSketch)
333 {
334   ResultPtr aResult;
335   if (theShape.ShapeType() == TopAbs_EDGE) {
336     // Check that we already have such external edge
337     std::shared_ptr<GeomAPI_Edge> aInEdge = std::shared_ptr<GeomAPI_Edge>(new GeomAPI_Edge());
338     aInEdge->setImpl(new TopoDS_Shape(theShape));
339     aResult = findExternalEdge(theSketch, aInEdge);
340   }
341   if (theShape.ShapeType() == TopAbs_VERTEX) {
342     std::shared_ptr<GeomAPI_Vertex> aInVert = std::shared_ptr<GeomAPI_Vertex>(new GeomAPI_Vertex());
343     aInVert->setImpl(new TopoDS_Shape(theShape));
344     aResult = findExternalVertex(theSketch, aInVert);
345   }
346   return aResult;
347 }
348
349 ResultPtr PartSet_Tools::createFixedObjectByExternal(const TopoDS_Shape& theShape,
350                                                      const ObjectPtr& theObject,
351                                                      CompositeFeaturePtr theSketch,
352                                                      const bool theTemporary)
353 {
354   if (theShape.ShapeType() == TopAbs_EDGE) {
355     Standard_Real aStart, aEnd;
356     Handle(V3d_View) aNullView;
357     FeaturePtr aMyFeature;
358
359     Handle(Geom_Curve) aCurve = BRep_Tool::Curve(TopoDS::Edge(theShape), aStart, aEnd);
360     GeomAdaptor_Curve aAdaptor(aCurve);
361     std::shared_ptr<GeomAPI_Edge> anEdge = std::shared_ptr<GeomAPI_Edge>(new GeomAPI_Edge);
362     anEdge->setImpl(new TopoDS_Shape(theShape));
363     if (aAdaptor.GetType() == GeomAbs_Line) {
364       // Create line
365       aMyFeature = theSketch->addFeature(SketchPlugin_Line::ID());
366       if (!theObject.get()) {
367         // There is no selected result
368         std::shared_ptr<GeomAPI_Pnt> aPnt1 = anEdge->firstPoint();
369         std::shared_ptr<GeomAPI_Pnt> aPnt2 = anEdge->lastPoint();
370         std::shared_ptr<GeomAPI_Pnt2d> aPnt2d1 = convertTo2D(theSketch, aPnt1);
371         std::shared_ptr<GeomAPI_Pnt2d> aPnt2d2 = convertTo2D(theSketch, aPnt2);
372
373         std::shared_ptr<ModelAPI_Data> aData = aMyFeature->data();
374         std::shared_ptr<GeomDataAPI_Point2D> aPoint1 =
375           std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
376           aData->attribute(SketchPlugin_Line::START_ID()));
377         std::shared_ptr<GeomDataAPI_Point2D> aPoint2 =
378           std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
379           aData->attribute(SketchPlugin_Line::END_ID()));
380
381         aPoint1->setValue(aPnt2d1);
382         aPoint2->setValue(aPnt2d2);
383
384         // If this is an axis then its name has to be changed correspondently
385         std::string aSuffix = "";
386         bool aXdir = fabs(aPnt1->x() - aPnt2->x()) > Precision::Confusion();
387         bool aYdir = fabs(aPnt1->y() - aPnt2->y()) > Precision::Confusion();
388         bool aZdir = fabs(aPnt1->z() - aPnt2->z()) > Precision::Confusion();
389         if (aXdir && (!aYdir) && (!aZdir))
390           aSuffix = "X";
391         else if ((!aXdir) && aYdir && (!aZdir))
392           aSuffix = "Y";
393         else if ((!aXdir) && (!aYdir) && aZdir)
394           aSuffix = "Z";
395         if (aSuffix.length() > 0)
396           aData->setName("Axis_" + aSuffix);
397         aMyFeature->execute();
398
399       }
400     } else if (aAdaptor.GetType() == GeomAbs_Circle) {
401       if (anEdge->isArc()) {
402         // Create arc
403         aMyFeature = theSketch->addFeature(SketchPlugin_Arc::ID());
404         if (theShape.Orientation() == TopAbs_REVERSED)
405           aMyFeature->boolean(SketchPlugin_Arc::REVERSED_ID())->setValue(true);
406       }
407       else {
408         // Create circle
409         aMyFeature = theSketch->addFeature(SketchPlugin_Circle::ID());
410       }
411     }
412     if (aMyFeature) {
413       DataPtr aData = aMyFeature->data();
414       AttributeSelectionPtr anAttr =
415         std::dynamic_pointer_cast<ModelAPI_AttributeSelection>
416         (aData->attribute(SketchPlugin_SketchEntity::EXTERNAL_ID()));
417
418       ResultPtr aRes = std::dynamic_pointer_cast<ModelAPI_Result>(theObject);
419       // selection shape has no result owner => the trihedron axis
420       // TODO: make reference to the real axes when
421       // they are implemented in the initialization plugin
422       if (!aRes.get()) {
423         ObjectPtr aPointObj = ModelAPI_Session::get()->moduleDocument()->objectByName(
424           ModelAPI_ResultConstruction::group(), "Origin");
425         if (aPointObj.get()) { // if initialization plugin performed well
426           aRes = std::dynamic_pointer_cast<ModelAPI_Result>(aPointObj);
427         }
428       }
429       if (!aRes.get()) {
430         aRes = aMyFeature->firstResult();
431       }
432       if (anAttr.get() && aRes.get()) {
433         std::shared_ptr<GeomAPI_Shape> anEdge(new GeomAPI_Shape);
434         anEdge->setImpl(new TopoDS_Shape(theShape));
435
436         anAttr->setValue(aRes, anEdge);
437         //if (!theTemporary) {
438           aMyFeature->execute();
439
440         // issue #2125: Naming problem: two edges in Naming for one circle on solid
441         // this is result of boolean and seamedge
442         if (aAdaptor.GetType() == GeomAbs_Circle) {
443           ModelAPI_ValidatorsFactory* aFactory = ModelAPI_Session::get()->validators();
444           if (!aFactory->validate(aMyFeature)) {
445             anAttr->setValue(ResultPtr(), GeomShapePtr());
446             std::set<FeaturePtr> aFeatures;
447             aFeatures.insert(aMyFeature);
448             ModelAPI_Tools::removeFeaturesAndReferences(aFeatures);
449             Events_Loop::loop()->flush(Events_Loop::eventByName(EVENT_OBJECT_CREATED));
450             Events_Loop::loop()->flush(Events_Loop::eventByName(EVENT_OBJECT_DELETED));
451
452             return ResultPtr();
453           }
454         }
455
456         //  // fix this edge
457         //  FeaturePtr aFix = theSketch->addFeature(SketchPlugin_ConstraintRigid::ID());
458         //  aFix->data()->refattr(SketchPlugin_Constraint::ENTITY_A())->
459         //    setObject(aMyFeature->lastResult());
460         //  // we need to flush created signal in order to fixed constraint is processed by solver
461         //  Events_Loop::loop()->flush(Events_Loop::eventByName(EVENT_OBJECT_CREATED));
462         //}
463         return aMyFeature->lastResult();
464       }
465     }
466   }
467   if (theShape.ShapeType() == TopAbs_VERTEX) {
468     FeaturePtr aMyFeature = theSketch->addFeature(SketchPlugin_Point::ID());
469
470     if (aMyFeature) {
471       DataPtr aData = aMyFeature->data();
472       AttributeSelectionPtr anAttr =
473         std::dynamic_pointer_cast<ModelAPI_AttributeSelection>
474         (aData->attribute(SketchPlugin_SketchEntity::EXTERNAL_ID()));
475
476       ResultPtr aRes = std::dynamic_pointer_cast<ModelAPI_Result>(theObject);
477       // if there is no object,
478       // it means that this is the origin point: search it in the module document
479       if (!aRes.get()) {
480         ObjectPtr aPointObj = ModelAPI_Session::get()->moduleDocument()->objectByName(
481           ModelAPI_ResultConstruction::group(), "Origin");
482         if (aPointObj.get()) { // if initialization plugin performed well
483           aRes = std::dynamic_pointer_cast<ModelAPI_Result>(aPointObj);
484         }
485       }
486       // reference to itself with name "Origin" (but this may cause the infinitive cycling)
487       if (!aRes.get()) {
488         // If the point is selected not from Result object
489         std::shared_ptr<GeomAPI_Shape> aShape =
490           std::shared_ptr<GeomAPI_Shape>(new GeomAPI_Shape());
491         aShape->setImpl(new TopoDS_Shape(theShape));
492
493         std::shared_ptr<GeomAPI_Vertex> aVertex =
494           std::shared_ptr<GeomAPI_Vertex>(new GeomAPI_Vertex(aShape));
495         std::shared_ptr<GeomAPI_Pnt> aPnt = aVertex->point();
496
497         std::shared_ptr<GeomAPI_Pnt2d> aPnt2d = convertTo2D(theSketch, aPnt);
498         std::shared_ptr<GeomDataAPI_Point2D> aPoint =
499           std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
500           aData->attribute(SketchPlugin_Point::COORD_ID()));
501         aPoint->setValue(aPnt2d);
502         if ((aPnt->x() < Precision::Confusion()) &&
503             (aPnt->y() < Precision::Confusion()) &&
504             (aPnt->z() < Precision::Confusion()))
505           aData->setName("Origin");
506
507         aMyFeature->execute();
508         aRes = aMyFeature->firstResult();
509       }
510       if (anAttr.get() && aRes.get()) {
511         std::shared_ptr<GeomAPI_Shape> aVert(new GeomAPI_Shape);
512         aVert->setImpl(new TopoDS_Shape(theShape));
513
514         anAttr->setValue(aRes, aVert);
515         //if (theTemporary) {
516           aMyFeature->execute();
517
518         //  // fix this edge
519         //  FeaturePtr aFix = theSketch->addFeature(SketchPlugin_ConstraintRigid::ID());
520         //  aFix->data()->refattr(SketchPlugin_Constraint::ENTITY_A())->
521         //    setObject(aMyFeature->lastResult());
522         //  // we need to flush created signal in order to fixed constraint is processed by solver
523         //  Events_Loop::loop()->flush(Events_Loop::eventByName(EVENT_OBJECT_CREATED));
524         //}
525         return aMyFeature->lastResult();
526       }
527     }
528   }
529   return ResultPtr();
530 }
531
532 bool PartSet_Tools::isContainPresentation(const QList<ModuleBase_ViewerPrsPtr>& theSelected,
533                                           const ModuleBase_ViewerPrsPtr& thePrs)
534 {
535   foreach (ModuleBase_ViewerPrsPtr aPrs, theSelected) {
536     if (aPrs->object() == thePrs->object())
537       return true;
538   }
539   return false;
540 }
541
542 ResultPtr PartSet_Tools::findExternalEdge(CompositeFeaturePtr theSketch,
543                                           std::shared_ptr<GeomAPI_Edge> theEdge)
544 {
545   for (int i = 0; i < theSketch->numberOfSubs(); i++) {
546     FeaturePtr aFeature = theSketch->subFeature(i);
547     std::shared_ptr<SketchPlugin_Feature> aSketchFea =
548       std::dynamic_pointer_cast<SketchPlugin_Feature>(aFeature);
549     // not displayed result of feature projection should not be returned as external edge
550     if (aSketchFea && aSketchFea->canBeDisplayed()) {
551       if (aSketchFea->isExternal()) {
552         std::list<ResultPtr> aResults = aSketchFea->results();
553         std::list<ResultPtr>::const_iterator aIt;
554         for (aIt = aResults.cbegin(); aIt != aResults.cend(); ++aIt) {
555           ResultConstructionPtr aRes =
556             std::dynamic_pointer_cast<ModelAPI_ResultConstruction>(*aIt);
557           if (aRes) {
558             std::shared_ptr<GeomAPI_Shape> aShape = aRes->shape();
559             if (aShape) {
560               if (theEdge->isEqual(aShape))
561                 return aRes;
562             }
563           }
564         }
565       }
566     }
567   }
568   return ResultPtr();
569 }
570
571
572 ResultPtr PartSet_Tools::findExternalVertex(CompositeFeaturePtr theSketch,
573                                             std::shared_ptr<GeomAPI_Vertex> theVert)
574 {
575   for (int i = 0; i < theSketch->numberOfSubs(); i++) {
576     FeaturePtr aFeature = theSketch->subFeature(i);
577     std::shared_ptr<SketchPlugin_Feature> aSketchFea =
578       std::dynamic_pointer_cast<SketchPlugin_Feature>(aFeature);
579     if (aSketchFea) {
580       if (aSketchFea->isExternal()) {
581         std::list<ResultPtr> aResults = aSketchFea->results();
582         std::list<ResultPtr>::const_iterator aIt;
583         for (aIt = aResults.cbegin(); aIt != aResults.cend(); ++aIt) {
584           ResultConstructionPtr aRes =
585             std::dynamic_pointer_cast<ModelAPI_ResultConstruction>(*aIt);
586           if (aRes) {
587             std::shared_ptr<GeomAPI_Shape> aShape = aRes->shape();
588             if (aShape) {
589               if (theVert->isEqual(aShape))
590                 return aRes;
591             }
592           }
593         }
594       }
595     }
596   }
597   return ResultPtr();
598 }
599
600
601 bool PartSet_Tools::hasVertexShape(const ModuleBase_ViewerPrsPtr& thePrs, FeaturePtr theSketch,
602                                    Handle(V3d_View) theView, double& theX, double& theY)
603 {
604   bool aHasVertex = false;
605
606   const GeomShapePtr& aShape = thePrs->shape();
607   if (aShape.get() && !aShape->isNull() && aShape->shapeType() == GeomAPI_Shape::VERTEX)
608   {
609     const TopoDS_Shape& aTDShape = aShape->impl<TopoDS_Shape>();
610     const TopoDS_Vertex& aVertex = TopoDS::Vertex(aTDShape);
611     if (!aVertex.IsNull())
612     {
613       gp_Pnt aPoint = BRep_Tool::Pnt(aVertex);
614       PartSet_Tools::convertTo2D(aPoint, theSketch, theView, theX, theY);
615       aHasVertex = true;
616     }
617   }
618
619   return aHasVertex;
620 }
621
622 GeomShapePtr PartSet_Tools::findShapeBy2DPoint(const AttributePtr& theAttribute,
623                                                        ModuleBase_IWorkshop* theWorkshop)
624 {
625   GeomShapePtr aShape;
626   XGUI_ModuleConnector* aConnector = dynamic_cast<XGUI_ModuleConnector*>(theWorkshop);
627   XGUI_Displayer* aDisplayer = aConnector->workshop()->displayer();
628
629   // 2. find visualized vertices of the attribute and if the attribute of the vertex is
630   // the same, return it
631   FeaturePtr anAttributeFeature = ModelAPI_Feature::feature(theAttribute->owner());
632   // 2.1 get visualized results of the feature
633   const std::list<ResultPtr>& aResList = anAttributeFeature->results();
634   std::list<ResultPtr>::const_iterator anIt = aResList.begin(), aLast = aResList.end();
635   for (; anIt != aLast; anIt++) {
636     AISObjectPtr aAISObj = aDisplayer->getAISObject(*anIt);
637     if (aAISObj.get() != NULL) {
638       Handle(AIS_InteractiveObject) anAISIO = aAISObj->impl<Handle(AIS_InteractiveObject)>();
639       // 2.2 find selected owners of a visualizedd object
640       SelectMgr_IndexedMapOfOwner aSelectedOwners;
641       aConnector->workshop()->selector()->selection()->entityOwners(anAISIO, aSelectedOwners);
642       for (Standard_Integer i = 1, n = aSelectedOwners.Extent(); i <= n; i++) {
643         Handle(SelectMgr_EntityOwner) anOwner = aSelectedOwners(i);
644         if (!anOwner.IsNull()) {
645           Handle(StdSelect_BRepOwner) aBRepOwner = Handle(StdSelect_BRepOwner)::DownCast(anOwner);
646           if (!aBRepOwner.IsNull() && aBRepOwner->HasShape()) {
647             const TopoDS_Shape& aBRepShape = aBRepOwner->Shape();
648             if (aBRepShape.ShapeType() == TopAbs_VERTEX) {
649               // 2.3 if the owner is vertex and an attribute of the vertex is equal to the initial
650               // attribute, returns the shape
651               PartSet_Module* aModule = dynamic_cast<PartSet_Module*>(theWorkshop->module());
652               PartSet_SketcherMgr* aSketchMgr = aModule->sketchMgr();
653               AttributePtr aPntAttr = PartSet_Tools::findAttributeBy2dPoint(anAttributeFeature,
654                                                         aBRepShape, aSketchMgr->activeSketch());
655               if (aPntAttr.get() != NULL && aPntAttr == theAttribute) {
656                 aShape = std::shared_ptr<GeomAPI_Shape>(new GeomAPI_Shape);
657                 aShape->setImpl(new TopoDS_Shape(aBRepShape));
658                 break;
659               }
660             }
661           }
662         }
663       }
664     }
665   }
666   return aShape;
667 }
668
669 std::shared_ptr<GeomAPI_Pnt2d> PartSet_Tools::getPoint(
670                                                   std::shared_ptr<ModelAPI_Feature>& theFeature,
671                                                   const std::string& theAttribute)
672 {
673   std::shared_ptr<GeomDataAPI_Point2D> aPointAttr = ModelGeomAlgo_Point2D::getPointOfRefAttr(
674                                           theFeature.get(), theAttribute, SketchPlugin_Point::ID(),
675                                           SketchPlugin_Point::COORD_ID());
676   if (aPointAttr.get() != NULL)
677     return aPointAttr->pnt();
678   return std::shared_ptr<GeomAPI_Pnt2d>();
679 }
680
681 std::shared_ptr<GeomAPI_Pnt2d> PartSet_Tools::getPnt2d(QMouseEvent* theEvent,
682                                                 ModuleBase_IViewWindow* theWindow,
683                                                 const FeaturePtr& theSketch)
684 {
685   gp_Pnt aPnt = PartSet_Tools::convertClickToPoint(theEvent->pos(), theWindow->v3dView());
686   double aX, anY;
687   Handle(V3d_View) aView = theWindow->v3dView();
688   PartSet_Tools::convertTo2D(aPnt, theSketch, aView, aX, anY);
689
690   return std::shared_ptr<GeomAPI_Pnt2d>(new GeomAPI_Pnt2d(aX, anY));
691 }
692
693 FeaturePtr findFirstCoincidenceByData(const DataPtr& theData,
694                                       std::shared_ptr<GeomAPI_Pnt2d> thePoint)
695 {
696   FeaturePtr aCoincident;
697
698   const std::set<AttributePtr>& aRefsList = theData->refsToMe();
699   std::set<AttributePtr>::const_iterator aIt;
700   for (aIt = aRefsList.cbegin(); aIt != aRefsList.cend(); ++aIt) {
701     std::shared_ptr<ModelAPI_Attribute> aAttr = (*aIt);
702     FeaturePtr aConstrFeature = std::dynamic_pointer_cast<ModelAPI_Feature>(aAttr->owner());
703     if (aConstrFeature->getKind() == SketchPlugin_ConstraintCoincidence::ID()) {
704       std::shared_ptr<GeomAPI_Pnt2d> a2dPnt =
705         PartSet_Tools::getPoint(aConstrFeature, SketchPlugin_ConstraintCoincidence::ENTITY_A());
706       if (a2dPnt.get() && thePoint->isEqual(a2dPnt)) {
707         aCoincident = aConstrFeature;
708         break;
709       } else {
710         a2dPnt = PartSet_Tools::getPoint(aConstrFeature,
711                                           SketchPlugin_ConstraintCoincidence::ENTITY_B());
712         if (a2dPnt.get() && thePoint->isEqual(a2dPnt)) {
713           aCoincident = aConstrFeature;
714           break;
715         }
716       }
717     }
718   }
719   return aCoincident;
720 }
721
722 FeaturePtr PartSet_Tools::findFirstCoincidence(const FeaturePtr& theFeature,
723                                                std::shared_ptr<GeomAPI_Pnt2d> thePoint)
724 {
725   FeaturePtr aCoincident;
726   if (theFeature.get() == NULL)
727     return aCoincident;
728
729   const std::set<AttributePtr>& aRefsList = theFeature->data()->refsToMe();
730   std::set<AttributePtr>::const_iterator aIt;
731   for (aIt = aRefsList.cbegin(); aIt != aRefsList.cend(); ++aIt) {
732     std::shared_ptr<ModelAPI_Attribute> aAttr = (*aIt);
733     FeaturePtr aConstrFeature = std::dynamic_pointer_cast<ModelAPI_Feature>(aAttr->owner());
734     if (aConstrFeature->getKind() == SketchPlugin_ConstraintCoincidence::ID()) {
735       std::shared_ptr<GeomAPI_Pnt2d> a2dPnt =
736         PartSet_Tools::getPoint(aConstrFeature, SketchPlugin_ConstraintCoincidence::ENTITY_A());
737       if (a2dPnt.get() && thePoint->isEqual(a2dPnt)) {
738         aCoincident = aConstrFeature;
739         break;
740       } else {
741         a2dPnt = PartSet_Tools::getPoint(aConstrFeature,
742                                           SketchPlugin_ConstraintCoincidence::ENTITY_B());
743         if (a2dPnt.get() && thePoint->isEqual(a2dPnt)) {
744           aCoincident = aConstrFeature;
745           break;
746         }
747       }
748     }
749   }
750   /// Find by result
751   if (!aCoincident.get()) {
752     std::list<ResultPtr> aResults = theFeature->results();
753     std::list<ResultPtr>::const_iterator aIt;
754     for (aIt = aResults.cbegin(); aIt != aResults.cend(); ++aIt) {
755       ResultPtr aResult = *aIt;
756       aCoincident = findFirstCoincidenceByData(aResult->data(), thePoint);
757       if (aCoincident.get())
758         break;
759     }
760   }
761   return aCoincident;
762 }
763
764 void PartSet_Tools::findCoincidences(FeaturePtr theStartCoin, QList<FeaturePtr>& theList,
765                                      QList<FeaturePtr>& theCoincidencies,
766                                      std::string theAttr, QList<bool>& theIsAttributes)
767 {
768   std::shared_ptr<GeomAPI_Pnt2d> aOrig = getCoincedencePoint(theStartCoin);
769   if (aOrig.get() == NULL)
770     return;
771
772   AttributeRefAttrPtr aPnt = theStartCoin->refattr(theAttr);
773   if (!aPnt)
774     return;
775   ObjectPtr aObj = aPnt->object();
776   FeaturePtr aFeature = std::dynamic_pointer_cast<ModelAPI_Feature>(aObj);
777   if (aFeature.get()) {
778     if (!theList.contains(aFeature)) {
779       theList.append(aFeature);
780       theCoincidencies.append(theStartCoin);
781       theIsAttributes.append(true); // point attribute on a feature
782       const std::set<AttributePtr>& aRefsList = aFeature->data()->refsToMe();
783       std::set<AttributePtr>::const_iterator aIt;
784       for (aIt = aRefsList.cbegin(); aIt != aRefsList.cend(); ++aIt) {
785         std::shared_ptr<ModelAPI_Attribute> aAttr = (*aIt);
786         FeaturePtr aConstrFeature = std::dynamic_pointer_cast<ModelAPI_Feature>(aAttr->owner());
787         if (aConstrFeature->getKind() == SketchPlugin_ConstraintCoincidence::ID()) {
788           if (!theCoincidencies.contains(aConstrFeature)) {
789             std::shared_ptr<GeomAPI_Pnt2d> aPnt = getCoincedencePoint(aConstrFeature);
790             if (aPnt.get() && aOrig->isEqual(aPnt)) {
791               findCoincidences(aConstrFeature, theList, theCoincidencies,
792                 SketchPlugin_ConstraintCoincidence::ENTITY_A(), theIsAttributes);
793               findCoincidences(aConstrFeature, theList, theCoincidencies,
794                 SketchPlugin_ConstraintCoincidence::ENTITY_B(), theIsAttributes);
795             }
796           }
797         }
798       }
799     }
800   } else {
801     // Find by Results
802     ResultConstructionPtr aResult = std::dynamic_pointer_cast<ModelAPI_ResultConstruction>(aObj);
803     if (aResult.get()) {
804       FeaturePtr aFeature = ModelAPI_Feature::feature(aPnt->object());
805       if (!theList.contains(aFeature))
806         theList.append(aFeature);
807       theCoincidencies.append(theStartCoin);
808       theIsAttributes.append(false); // point attribute on a feature
809
810       const std::set<AttributePtr>& aRefsList = aResult->data()->refsToMe();
811       std::set<AttributePtr>::const_iterator aIt;
812       for (aIt = aRefsList.cbegin(); aIt != aRefsList.cend(); ++aIt) {
813         std::shared_ptr<ModelAPI_Attribute> aAttr = (*aIt);
814         FeaturePtr aConstrFeature = std::dynamic_pointer_cast<ModelAPI_Feature>(aAttr->owner());
815         if (aConstrFeature->getKind() == SketchPlugin_ConstraintCoincidence::ID()) {
816           if (!theCoincidencies.contains(aConstrFeature)) {
817             std::shared_ptr<GeomAPI_Pnt2d> aPnt = getCoincedencePoint(aConstrFeature);
818             if (aPnt.get() && aOrig->isEqual(aPnt)) {
819               findCoincidences(aConstrFeature, theList, theCoincidencies,
820                 SketchPlugin_ConstraintCoincidence::ENTITY_A(), theIsAttributes);
821               findCoincidences(aConstrFeature, theList, theCoincidencies,
822                 SketchPlugin_ConstraintCoincidence::ENTITY_B(), theIsAttributes);
823             }
824           }
825         }
826       }
827     }
828   }
829 }
830
831 std::shared_ptr<GeomAPI_Pnt2d> PartSet_Tools::getCoincedencePoint(FeaturePtr theStartCoin)
832 {
833   std::shared_ptr<GeomAPI_Pnt2d> aPnt = SketcherPrs_Tools::getPoint(theStartCoin.get(),
834                                                         SketchPlugin_Constraint::ENTITY_A());
835   if (aPnt.get() == NULL)
836     aPnt = SketcherPrs_Tools::getPoint(theStartCoin.get(), SketchPlugin_Constraint::ENTITY_B());
837   return aPnt;
838 }
839
840 AttributePtr PartSet_Tools::findAttributeBy2dPoint(ObjectPtr theObj,
841                                                    const TopoDS_Shape theShape,
842                                                    FeaturePtr theSketch)
843 {
844
845   AttributePtr anAttribute;
846   FeaturePtr aFeature = ModelAPI_Feature::feature(theObj);
847   if (aFeature) {
848     if (theShape.ShapeType() == TopAbs_VERTEX) {
849       const TopoDS_Vertex& aVertex = TopoDS::Vertex(theShape);
850       if (!aVertex.IsNull())  {
851         gp_Pnt aPoint = BRep_Tool::Pnt(aVertex);
852         std::shared_ptr<GeomAPI_Pnt> aValue = std::shared_ptr<GeomAPI_Pnt>(
853             new GeomAPI_Pnt(aPoint.X(), aPoint.Y(), aPoint.Z()));
854
855         // find the given point in the feature attributes
856         std::list<AttributePtr> anAttiributes =
857           aFeature->data()->attributes(GeomDataAPI_Point2D::typeId());
858         std::list<AttributePtr>::const_iterator anIt = anAttiributes.begin(),
859                                                 aLast = anAttiributes.end();
860         for (; anIt != aLast && !anAttribute; anIt++) {
861           std::shared_ptr<GeomDataAPI_Point2D> aCurPoint =
862             std::dynamic_pointer_cast<GeomDataAPI_Point2D>(*anIt);
863           if (!aCurPoint->isInitialized())
864             continue;
865
866           std::shared_ptr<GeomAPI_Pnt> aPnt =
867             convertTo3D(aCurPoint->x(), aCurPoint->y(), theSketch);
868           if (aPnt && (aPnt->distance(aValue) < Precision::Confusion())) {
869             anAttribute = aCurPoint;
870             break;
871           }
872         }
873       }
874     }
875   }
876   return anAttribute;
877 }
878
879 void PartSet_Tools::sendSubFeaturesEvent(const CompositeFeaturePtr& theComposite,
880                                          const Events_ID theEventId)
881 {
882   if (!theComposite.get())
883     return;
884
885   static Events_Loop* aLoop = Events_Loop::loop();
886   for (int i = 0; i < theComposite->numberOfSubs(); i++) {
887     FeaturePtr aSubFeature = theComposite->subFeature(i);
888     static const ModelAPI_EventCreator* aECreator = ModelAPI_EventCreator::get();
889     aECreator->sendUpdated(aSubFeature, theEventId);
890   }
891   Events_Loop::loop()->flush(theEventId);
892 }
893
894 bool PartSet_Tools::isAuxiliarySketchEntity(const ObjectPtr& theObject)
895 {
896   bool isAuxiliaryFeature = false;
897
898   FeaturePtr anObjectFeature = ModelAPI_Feature::feature(theObject);
899   std::string anAuxiliaryAttribute = SketchPlugin_SketchEntity::AUXILIARY_ID();
900   AttributeBooleanPtr anAuxiliaryAttr = std::dynamic_pointer_cast<ModelAPI_AttributeBoolean>(
901                                     anObjectFeature->data()->attribute(anAuxiliaryAttribute));
902   if (anAuxiliaryAttr.get())
903     isAuxiliaryFeature = anAuxiliaryAttr->value();
904
905
906   return isAuxiliaryFeature;
907 }