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