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