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