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