Salome HOME
d7c4812d02a6325b3b57d505225b89c74c6647bb
[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 const bool SKETCH_PROJECTION_INCLUDE_INTO_RESULT = false; // by default, it is not presented
103
104 int PartSet_Tools::getAISDefaultWidth()
105 {
106   return AIS_DEFAULT_WIDTH;
107 }
108
109 gp_Pnt PartSet_Tools::convertClickToPoint(QPoint thePoint, Handle(V3d_View) theView)
110 {
111   if (theView.IsNull())
112     return gp_Pnt();
113
114   V3d_Coordinate XEye, YEye, ZEye, XAt, YAt, ZAt;
115   theView->Eye(XEye, YEye, ZEye);
116
117   theView->At(XAt, YAt, ZAt);
118   gp_Pnt EyePoint(XEye, YEye, ZEye);
119   gp_Pnt AtPoint(XAt, YAt, ZAt);
120
121   gp_Vec EyeVector(EyePoint, AtPoint);
122   gp_Dir EyeDir(EyeVector);
123
124   gp_Pln PlaneOfTheView = gp_Pln(AtPoint, EyeDir);
125   Standard_Real X, Y, Z;
126   theView->Convert(thePoint.x(), thePoint.y(), X, Y, Z);
127   gp_Pnt ConvertedPoint(X, Y, Z);
128
129   gp_Pnt2d ConvertedPointOnPlane = ProjLib::Project(PlaneOfTheView, ConvertedPoint);
130   gp_Pnt ResultPoint = ElSLib::Value(ConvertedPointOnPlane.X(), ConvertedPointOnPlane.Y(),
131                                      PlaneOfTheView);
132   return ResultPoint;
133 }
134
135 void PartSet_Tools::convertTo2D(const gp_Pnt& thePoint, FeaturePtr theSketch,
136 Handle(V3d_View) theView,
137                                 double& theX, double& theY)
138 {
139   if (!theSketch)
140     return;
141
142   AttributeDoublePtr anAttr;
143   std::shared_ptr<ModelAPI_Data> aData = theSketch->data();
144
145   std::shared_ptr<GeomDataAPI_Point> anOrigin = std::dynamic_pointer_cast<GeomDataAPI_Point>(
146       aData->attribute(SketchPlugin_Sketch::ORIGIN_ID()));
147
148   std::shared_ptr<GeomDataAPI_Dir> aX = std::dynamic_pointer_cast<GeomDataAPI_Dir>(
149       aData->attribute(SketchPlugin_Sketch::DIRX_ID()));
150   std::shared_ptr<GeomDataAPI_Dir> aNorm = std::dynamic_pointer_cast<GeomDataAPI_Dir>(
151       aData->attribute(SketchPlugin_Sketch::NORM_ID()));
152   std::shared_ptr<GeomAPI_XYZ> anY = aNorm->xyz()->cross(aX->xyz());
153
154   gp_Pnt anOriginPnt(anOrigin->x(), anOrigin->y(), anOrigin->z());
155   gp_Vec aVec(anOriginPnt, thePoint);
156
157   if (!theView.IsNull()) {
158     V3d_Coordinate XEye, YEye, ZEye, XAt, YAt, ZAt;
159     theView->Eye(XEye, YEye, ZEye);
160
161     theView->At(XAt, YAt, ZAt);
162     gp_Pnt EyePoint(XEye, YEye, ZEye);
163     gp_Pnt AtPoint(XAt, YAt, ZAt);
164
165     gp_Vec anEyeVec(EyePoint, AtPoint);
166     anEyeVec.Normalize();
167
168     std::shared_ptr<GeomDataAPI_Dir> aNormal = std::dynamic_pointer_cast<GeomDataAPI_Dir>(
169         aData->attribute(SketchPlugin_Sketch::NORM_ID()));
170     gp_Vec aNormalVec(aNormal->x(), aNormal->y(), aNormal->z());
171
172     double aDen = anEyeVec * aNormalVec;
173     double aLVec = aDen != 0 ? aVec * aNormalVec / aDen : DBL_MAX;
174
175     gp_Vec aDeltaVec = anEyeVec * aLVec;
176     aVec = aVec - aDeltaVec;
177   }
178   theX = aVec.X() * aX->x() + aVec.Y() * aX->y() + aVec.Z() * aX->z();
179   theY = aVec.X() * anY->x() + aVec.Y() * anY->y() + aVec.Z() * anY->z();
180 }
181
182 std::shared_ptr<GeomAPI_Pnt2d> PartSet_Tools::convertTo2D(FeaturePtr theSketch,
183                                                     const std::shared_ptr<GeomAPI_Pnt>& thePnt)
184 {
185   std::shared_ptr<GeomAPI_Pnt2d> aRes;
186   if (theSketch->getKind() != SketchPlugin_Sketch::ID())
187     return aRes;
188   std::shared_ptr<GeomDataAPI_Point> aC = std::dynamic_pointer_cast<GeomDataAPI_Point>(
189       theSketch->data()->attribute(SketchPlugin_Sketch::ORIGIN_ID()));
190   std::shared_ptr<GeomDataAPI_Dir> aNorm = std::dynamic_pointer_cast<GeomDataAPI_Dir>(
191       theSketch->data()->attribute(SketchPlugin_Sketch::NORM_ID()));
192   std::shared_ptr<GeomDataAPI_Dir> aX = std::dynamic_pointer_cast<GeomDataAPI_Dir>(
193       theSketch->data()->attribute(SketchPlugin_Sketch::DIRX_ID()));
194   std::shared_ptr<GeomAPI_Dir> aY(new GeomAPI_Dir(aNorm->dir()->cross(aX->dir())));
195   return thePnt->to2D(aC->pnt(), aX->dir(), aY);
196 }
197
198
199 std::shared_ptr<GeomAPI_Pnt> PartSet_Tools::convertTo3D(const double theX, const double theY,
200                                                         FeaturePtr theSketch)
201 {
202   std::shared_ptr<ModelAPI_Data> aData = theSketch->data();
203
204   std::shared_ptr<GeomDataAPI_Point> aC = std::dynamic_pointer_cast<GeomDataAPI_Point>(
205       aData->attribute(SketchPlugin_Sketch::ORIGIN_ID()));
206   std::shared_ptr<GeomDataAPI_Dir> aX = std::dynamic_pointer_cast<GeomDataAPI_Dir>(
207       aData->attribute(SketchPlugin_Sketch::DIRX_ID()));
208   std::shared_ptr<GeomDataAPI_Dir> aNorm = std::dynamic_pointer_cast<GeomDataAPI_Dir>(
209       aData->attribute(SketchPlugin_Sketch::NORM_ID()));
210   std::shared_ptr<GeomAPI_Dir> aY(new GeomAPI_Dir(aNorm->dir()->cross(aX->dir())));
211
212   std::shared_ptr<GeomAPI_Pnt2d> aPnt2d =
213     std::shared_ptr<GeomAPI_Pnt2d>(new GeomAPI_Pnt2d(theX, theY));
214
215   return aPnt2d->to3D(aC->pnt(), aX->dir(), aY);
216 }
217
218 std::shared_ptr<ModelAPI_Document> PartSet_Tools::document()
219 {
220   return ModelAPI_Session::get()->moduleDocument();
221 }
222
223 void PartSet_Tools::setFeatureValue(FeaturePtr theFeature, double theValue,
224                                     const std::string& theAttribute)
225 {
226   if (!theFeature)
227     return;
228   std::shared_ptr<ModelAPI_Data> aData = theFeature->data();
229   AttributeDoublePtr anAttribute = std::dynamic_pointer_cast<ModelAPI_AttributeDouble>(
230       aData->attribute(theAttribute));
231   if (anAttribute)
232     anAttribute->setValue(theValue);
233 }
234
235 double PartSet_Tools::featureValue(FeaturePtr theFeature, const std::string& theAttribute,
236                                    bool& isValid)
237 {
238   isValid = false;
239   double aValue = 0;
240   if (theFeature) {
241     std::shared_ptr<ModelAPI_Data> aData = theFeature->data();
242     AttributeDoublePtr anAttribute = std::dynamic_pointer_cast<ModelAPI_AttributeDouble>(
243         aData->attribute(theAttribute));
244     if (anAttribute) {
245       aValue = anAttribute->value();
246       isValid = true;
247     }
248   }
249   return aValue;
250 }
251
252 FeaturePtr PartSet_Tools::feature(FeaturePtr theFeature, const std::string& theAttribute,
253                                   const std::string& theKind)
254 {
255   FeaturePtr aFeature;
256   if (!theFeature)
257     return aFeature;
258
259   std::shared_ptr<ModelAPI_Data> aData = theFeature->data();
260   std::shared_ptr<ModelAPI_AttributeRefAttr> anAttr = std::dynamic_pointer_cast<
261       ModelAPI_AttributeRefAttr>(aData->attribute(theAttribute));
262   if (anAttr) {
263     aFeature = std::dynamic_pointer_cast<ModelAPI_Feature>(anAttr->object());
264     if (!theKind.empty() && aFeature && aFeature->getKind() != theKind) {
265       aFeature = FeaturePtr();
266     }
267   }
268   return aFeature;
269 }
270
271 void PartSet_Tools::createConstraint(CompositeFeaturePtr theSketch,
272                                      std::shared_ptr<GeomDataAPI_Point2D> thePoint1,
273                                      std::shared_ptr<GeomDataAPI_Point2D> thePoint2)
274 {
275   FeaturePtr aFeature;
276   if (theSketch) {
277     aFeature = theSketch->addFeature(SketchPlugin_ConstraintCoincidence::ID());
278   } else {
279     std::shared_ptr<ModelAPI_Document> aDoc = document();
280     aFeature = aDoc->addFeature(SketchPlugin_ConstraintCoincidence::ID());
281   }
282
283   std::shared_ptr<ModelAPI_Data> aData = aFeature->data();
284
285   std::shared_ptr<ModelAPI_AttributeRefAttr> aRef1 = std::dynamic_pointer_cast<
286       ModelAPI_AttributeRefAttr>(aData->attribute(SketchPlugin_Constraint::ENTITY_A()));
287   aRef1->setAttr(thePoint1);
288
289   std::shared_ptr<ModelAPI_AttributeRefAttr> aRef2 = std::dynamic_pointer_cast<
290       ModelAPI_AttributeRefAttr>(aData->attribute(SketchPlugin_Constraint::ENTITY_B()));
291   aRef2->setAttr(thePoint2);
292
293   // we need to flush created signal in order to coincidence is processed by solver
294   Events_Loop::loop()->flush(Events_Loop::eventByName(EVENT_OBJECT_CREATED));
295 }
296
297 std::shared_ptr<GeomAPI_Pln> PartSet_Tools::sketchPlane(CompositeFeaturePtr theSketch)
298 {
299   std::shared_ptr<GeomAPI_Pln> aPlane;
300
301   std::shared_ptr<GeomDataAPI_Point> anOrigin = std::dynamic_pointer_cast<GeomDataAPI_Point>(
302       theSketch->data()->attribute(SketchPlugin_Sketch::ORIGIN_ID()));
303   std::shared_ptr<GeomDataAPI_Dir> aNormal = std::dynamic_pointer_cast<GeomDataAPI_Dir>(
304       theSketch->data()->attribute(SketchPlugin_Sketch::NORM_ID()));
305
306   if (aNormal.get() && aNormal->isInitialized() &&
307       anOrigin.get() && anOrigin->isInitialized())
308     aPlane = std::shared_ptr<GeomAPI_Pln>(new GeomAPI_Pln(anOrigin->pnt(), aNormal->dir()));
309
310   return aPlane;
311 }
312
313 std::shared_ptr<GeomAPI_Pnt> PartSet_Tools::point3D(std::shared_ptr<GeomAPI_Pnt2d> thePoint2D,
314                                                       CompositeFeaturePtr theSketch)
315 {
316   std::shared_ptr<GeomAPI_Pnt> aPoint;
317   if (!theSketch || !thePoint2D)
318     return aPoint;
319
320   DataPtr aData = theSketch->data();
321   std::shared_ptr<GeomDataAPI_Point> aC = std::dynamic_pointer_cast<GeomDataAPI_Point>(
322       aData->attribute(SketchPlugin_Sketch::ORIGIN_ID()));
323   std::shared_ptr<GeomDataAPI_Dir> aX = std::dynamic_pointer_cast<GeomDataAPI_Dir>(
324       aData->attribute(SketchPlugin_Sketch::DIRX_ID()));
325   std::shared_ptr<GeomDataAPI_Dir> aNorm = std::dynamic_pointer_cast<GeomDataAPI_Dir>(
326       aData->attribute(SketchPlugin_Sketch::NORM_ID()));
327   std::shared_ptr<GeomAPI_Dir> aY(new GeomAPI_Dir(aNorm->dir()->cross(aX->dir())));
328
329   return thePoint2D->to3D(aC->pnt(), aX->dir(), aY);
330 }
331
332 ResultPtr PartSet_Tools::findFixedObjectByExternal(const TopoDS_Shape& theShape,
333                                                    const ObjectPtr& theObject,
334                                                    CompositeFeaturePtr theSketch)
335 {
336   ResultPtr aResult = std::dynamic_pointer_cast<ModelAPI_Result>(theObject);
337   if (!aResult.get())
338     return ResultPtr();
339
340   for (int i = 0, aNbSubs = theSketch->numberOfSubs(); i < aNbSubs; i++) {
341     FeaturePtr aFeature = theSketch->subFeature(i);
342     if (aFeature->getKind() != SketchPlugin_Projection::PROJECTED_FEATURE_ID())
343       continue;
344     if (aFeature->lastResult() == aResult)
345       return aResult;
346   }
347   return ResultPtr();
348 }
349
350 ResultPtr PartSet_Tools::createFixedObjectByExternal(
351                                    const std::shared_ptr<GeomAPI_Shape>& theShape,
352                                    const ObjectPtr& theObject,
353                                    CompositeFeaturePtr theSketch,
354                                    const bool theTemporary,
355                                    FeaturePtr& theCreatedFeature)
356 {
357   ResultPtr aResult = std::dynamic_pointer_cast<ModelAPI_Result>(theObject);
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
367   AttributeBooleanPtr anIntoResult = std::dynamic_pointer_cast<ModelAPI_AttributeBoolean>
368     (aProjectionFeature->data()->attribute(SketchPlugin_Projection::INCLUDE_INTO_RESULT()));
369   anIntoResult->setValue(SKETCH_PROJECTION_INCLUDE_INTO_RESULT);
370   aProjectionFeature->execute();
371
372   // if projection feature has not been created, exit
373   AttributeRefAttrPtr aRefAttr = aProjectionFeature->data()->refattr(
374     SketchPlugin_Projection::PROJECTED_FEATURE_ID());
375   if (!aRefAttr || !aRefAttr->isInitialized())
376     return ResultPtr();
377
378   FeaturePtr aProjection = ModelAPI_Feature::feature(aRefAttr->object());
379   if (aProjection.get() && aProjection->lastResult().get())
380     return aProjection->lastResult();
381
382   return ResultPtr();
383 }
384
385 bool PartSet_Tools::isContainPresentation(const QList<ModuleBase_ViewerPrsPtr>& theSelected,
386                                           const ModuleBase_ViewerPrsPtr& thePrs)
387 {
388   foreach (ModuleBase_ViewerPrsPtr aPrs, theSelected) {
389     if (aPrs->object() == thePrs->object())
390       return true;
391   }
392   return false;
393 }
394
395 GeomShapePtr PartSet_Tools::findShapeBy2DPoint(const AttributePtr& theAttribute,
396                                                        ModuleBase_IWorkshop* theWorkshop)
397 {
398   GeomShapePtr aShape;
399   XGUI_ModuleConnector* aConnector = dynamic_cast<XGUI_ModuleConnector*>(theWorkshop);
400   XGUI_Displayer* aDisplayer = aConnector->workshop()->displayer();
401
402   // 2. find visualized vertices of the attribute and if the attribute of the vertex is
403   // the same, return it
404   FeaturePtr anAttributeFeature = ModelAPI_Feature::feature(theAttribute->owner());
405   // 2.1 get visualized results of the feature
406   const std::list<ResultPtr>& aResList = anAttributeFeature->results();
407   std::list<ResultPtr>::const_iterator anIt = aResList.begin(), aLast = aResList.end();
408   for (; anIt != aLast; anIt++) {
409     AISObjectPtr aAISObj = aDisplayer->getAISObject(*anIt);
410     if (aAISObj.get() != NULL) {
411       Handle(AIS_InteractiveObject) anAISIO = aAISObj->impl<Handle(AIS_InteractiveObject)>();
412       // 2.2 find selected owners of a visualizedd object
413       SelectMgr_IndexedMapOfOwner aSelectedOwners;
414       aConnector->workshop()->selector()->selection()->entityOwners(anAISIO, aSelectedOwners);
415       for (Standard_Integer i = 1, n = aSelectedOwners.Extent(); i <= n; i++) {
416         Handle(SelectMgr_EntityOwner) anOwner = aSelectedOwners(i);
417         if (!anOwner.IsNull()) {
418           Handle(StdSelect_BRepOwner) aBRepOwner = Handle(StdSelect_BRepOwner)::DownCast(anOwner);
419           if (!aBRepOwner.IsNull() && aBRepOwner->HasShape()) {
420             const TopoDS_Shape& aBRepShape = aBRepOwner->Shape();
421             if (aBRepShape.ShapeType() == TopAbs_VERTEX) {
422               // 2.3 if the owner is vertex and an attribute of the vertex is equal to the initial
423               // attribute, returns the shape
424               PartSet_Module* aModule = dynamic_cast<PartSet_Module*>(theWorkshop->module());
425               PartSet_SketcherMgr* aSketchMgr = aModule->sketchMgr();
426               AttributePtr aPntAttr = PartSet_Tools::findAttributeBy2dPoint(anAttributeFeature,
427                                                         aBRepShape, aSketchMgr->activeSketch());
428               if (aPntAttr.get() != NULL && aPntAttr == theAttribute) {
429                 aShape = std::shared_ptr<GeomAPI_Shape>(new GeomAPI_Shape);
430                 aShape->setImpl(new TopoDS_Shape(aBRepShape));
431                 break;
432               }
433             }
434           }
435         }
436       }
437     }
438   }
439   return aShape;
440 }
441
442 std::shared_ptr<GeomAPI_Pnt2d> PartSet_Tools::getPoint(
443                                                   std::shared_ptr<ModelAPI_Feature>& theFeature,
444                                                   const std::string& theAttribute)
445 {
446   std::shared_ptr<GeomDataAPI_Point2D> aPointAttr = ModelGeomAlgo_Point2D::getPointOfRefAttr(
447                                           theFeature.get(), theAttribute, SketchPlugin_Point::ID(),
448                                           SketchPlugin_Point::COORD_ID());
449   if (aPointAttr.get() != NULL)
450     return aPointAttr->pnt();
451   return std::shared_ptr<GeomAPI_Pnt2d>();
452 }
453
454 std::shared_ptr<GeomAPI_Pnt2d> PartSet_Tools::getPnt2d(QMouseEvent* theEvent,
455                                                 ModuleBase_IViewWindow* theWindow,
456                                                 const FeaturePtr& theSketch)
457 {
458   gp_Pnt aPnt = PartSet_Tools::convertClickToPoint(theEvent->pos(), theWindow->v3dView());
459   double aX, anY;
460   Handle(V3d_View) aView = theWindow->v3dView();
461   PartSet_Tools::convertTo2D(aPnt, theSketch, aView, aX, anY);
462
463   return std::shared_ptr<GeomAPI_Pnt2d>(new GeomAPI_Pnt2d(aX, anY));
464 }
465
466 FeaturePtr findFirstCoincidenceByData(const DataPtr& theData,
467                                       std::shared_ptr<GeomAPI_Pnt2d> thePoint)
468 {
469   FeaturePtr aCoincident;
470
471   const std::set<AttributePtr>& aRefsList = theData->refsToMe();
472   std::set<AttributePtr>::const_iterator aIt;
473   for (aIt = aRefsList.cbegin(); aIt != aRefsList.cend(); ++aIt) {
474     std::shared_ptr<ModelAPI_Attribute> aAttr = (*aIt);
475     FeaturePtr aConstrFeature = std::dynamic_pointer_cast<ModelAPI_Feature>(aAttr->owner());
476     if (aConstrFeature->getKind() == SketchPlugin_ConstraintCoincidence::ID()) {
477       std::shared_ptr<GeomAPI_Pnt2d> a2dPnt =
478         PartSet_Tools::getPoint(aConstrFeature, SketchPlugin_ConstraintCoincidence::ENTITY_A());
479       if (a2dPnt.get() && thePoint->isEqual(a2dPnt)) {
480         aCoincident = aConstrFeature;
481         break;
482       } else {
483         a2dPnt = PartSet_Tools::getPoint(aConstrFeature,
484                                           SketchPlugin_ConstraintCoincidence::ENTITY_B());
485         if (a2dPnt.get() && thePoint->isEqual(a2dPnt)) {
486           aCoincident = aConstrFeature;
487           break;
488         }
489       }
490     }
491   }
492   return aCoincident;
493 }
494
495 FeaturePtr PartSet_Tools::findFirstCoincidence(const FeaturePtr& theFeature,
496                                                std::shared_ptr<GeomAPI_Pnt2d> thePoint)
497 {
498   FeaturePtr aCoincident;
499   if (theFeature.get() == NULL)
500     return aCoincident;
501
502   const std::set<AttributePtr>& aRefsList = theFeature->data()->refsToMe();
503   std::set<AttributePtr>::const_iterator aIt;
504   for (aIt = aRefsList.cbegin(); aIt != aRefsList.cend(); ++aIt) {
505     std::shared_ptr<ModelAPI_Attribute> aAttr = (*aIt);
506     FeaturePtr aConstrFeature = std::dynamic_pointer_cast<ModelAPI_Feature>(aAttr->owner());
507     if (aConstrFeature->getKind() == SketchPlugin_ConstraintCoincidence::ID()) {
508       std::shared_ptr<GeomAPI_Pnt2d> a2dPnt =
509         PartSet_Tools::getPoint(aConstrFeature, SketchPlugin_ConstraintCoincidence::ENTITY_A());
510       if (a2dPnt.get() && thePoint->isEqual(a2dPnt)) {
511         aCoincident = aConstrFeature;
512         break;
513       } else {
514         a2dPnt = PartSet_Tools::getPoint(aConstrFeature,
515                                           SketchPlugin_ConstraintCoincidence::ENTITY_B());
516         if (a2dPnt.get() && thePoint->isEqual(a2dPnt)) {
517           aCoincident = aConstrFeature;
518           break;
519         }
520       }
521     }
522   }
523   /// Find by result
524   if (!aCoincident.get()) {
525     std::list<ResultPtr> aResults = theFeature->results();
526     std::list<ResultPtr>::const_iterator aIt;
527     for (aIt = aResults.cbegin(); aIt != aResults.cend(); ++aIt) {
528       ResultPtr aResult = *aIt;
529       aCoincident = findFirstCoincidenceByData(aResult->data(), thePoint);
530       if (aCoincident.get())
531         break;
532     }
533   }
534   return aCoincident;
535 }
536
537 void PartSet_Tools::findCoincidences(FeaturePtr theStartCoin, QList<FeaturePtr>& theList,
538                                      QList<FeaturePtr>& theCoincidencies,
539                                      std::string theAttr, QList<bool>& theIsAttributes)
540 {
541   std::shared_ptr<GeomAPI_Pnt2d> aOrig = getCoincedencePoint(theStartCoin);
542   if (aOrig.get() == NULL)
543     return;
544
545   AttributeRefAttrPtr aPnt = theStartCoin->refattr(theAttr);
546   if (!aPnt)
547     return;
548   ObjectPtr aObj = aPnt->object();
549   FeaturePtr aFeature = std::dynamic_pointer_cast<ModelAPI_Feature>(aObj);
550   if (aFeature.get()) {
551     if (!theList.contains(aFeature)) {
552       theList.append(aFeature);
553       theCoincidencies.append(theStartCoin);
554       theIsAttributes.append(true); // point attribute on a feature
555       const std::set<AttributePtr>& aRefsList = aFeature->data()->refsToMe();
556       std::set<AttributePtr>::const_iterator aIt;
557       for (aIt = aRefsList.cbegin(); aIt != aRefsList.cend(); ++aIt) {
558         std::shared_ptr<ModelAPI_Attribute> aAttr = (*aIt);
559         FeaturePtr aConstrFeature = std::dynamic_pointer_cast<ModelAPI_Feature>(aAttr->owner());
560         if (aConstrFeature->getKind() == SketchPlugin_ConstraintCoincidence::ID()) {
561           if (!theCoincidencies.contains(aConstrFeature)) {
562             std::shared_ptr<GeomAPI_Pnt2d> aPnt = getCoincedencePoint(aConstrFeature);
563             if (aPnt.get() && aOrig->isEqual(aPnt)) {
564               findCoincidences(aConstrFeature, theList, theCoincidencies,
565                 SketchPlugin_ConstraintCoincidence::ENTITY_A(), theIsAttributes);
566               findCoincidences(aConstrFeature, theList, theCoincidencies,
567                 SketchPlugin_ConstraintCoincidence::ENTITY_B(), theIsAttributes);
568             }
569           }
570         }
571       }
572     }
573   } else {
574     // Find by Results
575     ResultConstructionPtr aResult = std::dynamic_pointer_cast<ModelAPI_ResultConstruction>(aObj);
576     if (aResult.get()) {
577       FeaturePtr aFeature = ModelAPI_Feature::feature(aPnt->object());
578       if (!theList.contains(aFeature))
579         theList.append(aFeature);
580       theCoincidencies.append(theStartCoin);
581       theIsAttributes.append(false); // point attribute on a feature
582
583       const std::set<AttributePtr>& aRefsList = aResult->data()->refsToMe();
584       std::set<AttributePtr>::const_iterator aIt;
585       for (aIt = aRefsList.cbegin(); aIt != aRefsList.cend(); ++aIt) {
586         std::shared_ptr<ModelAPI_Attribute> aAttr = (*aIt);
587         FeaturePtr aConstrFeature = std::dynamic_pointer_cast<ModelAPI_Feature>(aAttr->owner());
588         if (aConstrFeature->getKind() == SketchPlugin_ConstraintCoincidence::ID()) {
589           if (!theCoincidencies.contains(aConstrFeature)) {
590             std::shared_ptr<GeomAPI_Pnt2d> aPnt = getCoincedencePoint(aConstrFeature);
591             if (aPnt.get() && aOrig->isEqual(aPnt)) {
592               findCoincidences(aConstrFeature, theList, theCoincidencies,
593                 SketchPlugin_ConstraintCoincidence::ENTITY_A(), theIsAttributes);
594               findCoincidences(aConstrFeature, theList, theCoincidencies,
595                 SketchPlugin_ConstraintCoincidence::ENTITY_B(), theIsAttributes);
596             }
597           }
598         }
599       }
600     }
601   }
602 }
603
604 std::shared_ptr<GeomAPI_Pnt2d> PartSet_Tools::getCoincedencePoint(FeaturePtr theStartCoin)
605 {
606   std::shared_ptr<GeomAPI_Pnt2d> aPnt = SketcherPrs_Tools::getPoint(theStartCoin.get(),
607                                                         SketchPlugin_Constraint::ENTITY_A());
608   if (aPnt.get() == NULL)
609     aPnt = SketcherPrs_Tools::getPoint(theStartCoin.get(), SketchPlugin_Constraint::ENTITY_B());
610   return aPnt;
611 }
612
613 AttributePtr PartSet_Tools::findAttributeBy2dPoint(ObjectPtr theObj,
614                                                    const TopoDS_Shape theShape,
615                                                    FeaturePtr theSketch)
616 {
617
618   AttributePtr anAttribute;
619   FeaturePtr aFeature = ModelAPI_Feature::feature(theObj);
620   if (aFeature) {
621     if (theShape.ShapeType() == TopAbs_VERTEX) {
622       const TopoDS_Vertex& aVertex = TopoDS::Vertex(theShape);
623       if (!aVertex.IsNull())  {
624         gp_Pnt aPoint = BRep_Tool::Pnt(aVertex);
625         std::shared_ptr<GeomAPI_Pnt> aValue = std::shared_ptr<GeomAPI_Pnt>(
626             new GeomAPI_Pnt(aPoint.X(), aPoint.Y(), aPoint.Z()));
627
628         // find the given point in the feature attributes
629         std::list<AttributePtr> anAttiributes =
630           aFeature->data()->attributes(GeomDataAPI_Point2D::typeId());
631         std::list<AttributePtr>::const_iterator anIt = anAttiributes.begin(),
632                                                 aLast = anAttiributes.end();
633         for (; anIt != aLast && !anAttribute; anIt++) {
634           std::shared_ptr<GeomDataAPI_Point2D> aCurPoint =
635             std::dynamic_pointer_cast<GeomDataAPI_Point2D>(*anIt);
636           if (!aCurPoint->isInitialized())
637             continue;
638
639           std::shared_ptr<GeomAPI_Pnt> aPnt =
640             convertTo3D(aCurPoint->x(), aCurPoint->y(), theSketch);
641           if (aPnt && (aPnt->distance(aValue) < Precision::Confusion())) {
642             anAttribute = aCurPoint;
643             break;
644           }
645         }
646       }
647     }
648   }
649   return anAttribute;
650 }
651
652 void PartSet_Tools::sendSubFeaturesEvent(const CompositeFeaturePtr& theComposite,
653                                          const Events_ID theEventId)
654 {
655   if (!theComposite.get())
656     return;
657
658   static Events_Loop* aLoop = Events_Loop::loop();
659   for (int i = 0; i < theComposite->numberOfSubs(); i++) {
660     FeaturePtr aSubFeature = theComposite->subFeature(i);
661     static const ModelAPI_EventCreator* aECreator = ModelAPI_EventCreator::get();
662     aECreator->sendUpdated(aSubFeature, theEventId);
663   }
664   Events_Loop::loop()->flush(theEventId);
665 }
666
667 bool PartSet_Tools::isAuxiliarySketchEntity(const ObjectPtr& theObject)
668 {
669   bool isAuxiliaryFeature = false;
670
671   FeaturePtr anObjectFeature = ModelAPI_Feature::feature(theObject);
672   std::string anAuxiliaryAttribute = SketchPlugin_SketchEntity::AUXILIARY_ID();
673   AttributeBooleanPtr anAuxiliaryAttr = std::dynamic_pointer_cast<ModelAPI_AttributeBoolean>(
674                                     anObjectFeature->data()->attribute(anAuxiliaryAttribute));
675   if (anAuxiliaryAttr.get())
676     isAuxiliaryFeature = anAuxiliaryAttr->value();
677
678
679   return isAuxiliaryFeature;
680 }
681
682
683 ResultPtr PartSet_Tools::createFixedByExternalCenter(
684     const ObjectPtr& theObject,
685     const std::shared_ptr<GeomAPI_Edge>& theEdge,
686     ModelAPI_AttributeSelection::CenterType theType,
687     const CompositeFeaturePtr& theSketch,
688     bool theTemporary)
689 {
690   ResultPtr aResult = std::dynamic_pointer_cast<ModelAPI_Result>(theObject);
691   if (!aResult.get())
692     return ResultPtr();
693
694   FeaturePtr aProjectionFeature = theSketch->addFeature(SketchPlugin_Projection::ID());
695   AttributeSelectionPtr anExternalAttr = std::dynamic_pointer_cast<ModelAPI_AttributeSelection>(
696                  aProjectionFeature->attribute(SketchPlugin_Projection::EXTERNAL_FEATURE_ID()));
697   anExternalAttr->setValueCenter(aResult, theEdge, theType, theTemporary);
698
699   AttributeBooleanPtr anIntoResult = std::dynamic_pointer_cast<ModelAPI_AttributeBoolean>
700     (aProjectionFeature->data()->attribute(SketchPlugin_Projection::INCLUDE_INTO_RESULT()));
701   anIntoResult->setValue(SKETCH_PROJECTION_INCLUDE_INTO_RESULT);
702   aProjectionFeature->execute();
703
704   // if projection feature has not been created, exit
705   AttributeRefAttrPtr aRefAttr = aProjectionFeature->data()->refattr(
706     SketchPlugin_Projection::PROJECTED_FEATURE_ID());
707   if (!aRefAttr || !aRefAttr->isInitialized())
708     return ResultPtr();
709
710   FeaturePtr aProjection = ModelAPI_Feature::feature(aRefAttr->object());
711   if (aProjection.get() && aProjection->lastResult().get())
712     return aProjection->lastResult();
713
714   return ResultPtr();
715 }