]> SALOME platform Git repositories - modules/shaper.git/blob - src/PartSet/PartSet_Tools.cpp
Salome HOME
Issue #273: Add copyright string
[modules/shaper.git] / src / PartSet / PartSet_Tools.cpp
1 // Copyright (C) 2014-20xx CEA/DEN, EDF R&D
2
3 // File:        PartSet_Tools.h
4 // Created:     28 Apr 2014
5 // Author:      Natalia ERMOLAEVA
6
7 #include <PartSet_Tools.h>
8
9 #include <ModelAPI_Data.h>
10 #include <ModelAPI_AttributeDouble.h>
11 #include <ModelAPI_AttributeRefList.h>
12 #include <ModelAPI_Document.h>
13 #include <ModelAPI_Session.h>
14 #include <ModelAPI_ResultConstruction.h>
15
16 #include <GeomDataAPI_Point.h>
17 #include <GeomDataAPI_Dir.h>
18 #include <GeomDataAPI_Point2D.h>
19 #include <GeomAPI_Pln.h>
20 #include <GeomAPI_Pnt2d.h>
21 #include <GeomAPI_Pnt.h>
22 #include <GeomAPI_Edge.h>
23
24 #include <GeomAPI_Dir.h>
25 #include <GeomAPI_XYZ.h>
26
27 #include <SketchPlugin_Feature.h>
28 #include <SketchPlugin_Sketch.h>
29 #include <SketchPlugin_ConstraintCoincidence.h>
30 #include <SketchPlugin_ConstraintDistance.h>
31 #include <SketchPlugin_ConstraintLength.h>
32 #include <SketchPlugin_ConstraintRadius.h>
33 #include <SketchPlugin_ConstraintRigid.h>
34 #include <SketchPlugin_Constraint.h>
35 #include <SketchPlugin_Circle.h>
36 #include <SketchPlugin_Arc.h>
37 #include <SketchPlugin_Line.h>
38
39 #include <ModuleBase_ViewerPrs.h>
40
41 #include <V3d_View.hxx>
42 #include <gp_Pln.hxx>
43 #include <gp_Circ.hxx>
44 #include <ProjLib.hxx>
45 #include <ElSLib.hxx>
46 #include <Geom_Line.hxx>
47 #include <GeomAPI_ProjectPointOnCurve.hxx>
48 #include <BRep_Tool.hxx>
49 #include <TopoDS.hxx>
50 #include <TopoDS_Edge.hxx>
51 #include <TopoDS_Vertex.hxx>
52
53 #ifdef _DEBUG
54 #include <QDebug>
55 #endif
56
57 const double PRECISION_TOLERANCE = 0.000001;
58
59 gp_Pnt PartSet_Tools::convertClickToPoint(QPoint thePoint, Handle(V3d_View) theView)
60 {
61   if (theView.IsNull())
62     return gp_Pnt();
63
64   V3d_Coordinate XEye, YEye, ZEye, XAt, YAt, ZAt;
65   theView->Eye(XEye, YEye, ZEye);
66
67   theView->At(XAt, YAt, ZAt);
68   gp_Pnt EyePoint(XEye, YEye, ZEye);
69   gp_Pnt AtPoint(XAt, YAt, ZAt);
70
71   gp_Vec EyeVector(EyePoint, AtPoint);
72   gp_Dir EyeDir(EyeVector);
73
74   gp_Pln PlaneOfTheView = gp_Pln(AtPoint, EyeDir);
75   Standard_Real X, Y, Z;
76   theView->Convert(thePoint.x(), thePoint.y(), X, Y, Z);
77   gp_Pnt ConvertedPoint(X, Y, Z);
78
79   gp_Pnt2d ConvertedPointOnPlane = ProjLib::Project(PlaneOfTheView, ConvertedPoint);
80   gp_Pnt ResultPoint = ElSLib::Value(ConvertedPointOnPlane.X(), ConvertedPointOnPlane.Y(),
81                                      PlaneOfTheView);
82   return ResultPoint;
83 }
84
85 void PartSet_Tools::convertTo2D(const gp_Pnt& thePoint, FeaturePtr theSketch,
86 Handle(V3d_View) theView,
87                                 double& theX, double& theY)
88 {
89   if (!theSketch)
90     return;
91
92   AttributeDoublePtr anAttr;
93   std::shared_ptr<ModelAPI_Data> aData = theSketch->data();
94
95   std::shared_ptr<GeomDataAPI_Point> anOrigin = std::dynamic_pointer_cast<GeomDataAPI_Point>(
96       aData->attribute(SketchPlugin_Sketch::ORIGIN_ID()));
97
98   std::shared_ptr<GeomDataAPI_Dir> aX = std::dynamic_pointer_cast<GeomDataAPI_Dir>(
99       aData->attribute(SketchPlugin_Sketch::DIRX_ID()));
100   std::shared_ptr<GeomDataAPI_Dir> anY = std::dynamic_pointer_cast<GeomDataAPI_Dir>(
101       aData->attribute(SketchPlugin_Sketch::DIRY_ID()));
102
103   gp_Pnt anOriginPnt(anOrigin->x(), anOrigin->y(), anOrigin->z());
104   gp_Vec aVec(anOriginPnt, thePoint);
105
106   if (!theView.IsNull()) {
107     V3d_Coordinate XEye, YEye, ZEye, XAt, YAt, ZAt;
108     theView->Eye(XEye, YEye, ZEye);
109
110     theView->At(XAt, YAt, ZAt);
111     gp_Pnt EyePoint(XEye, YEye, ZEye);
112     gp_Pnt AtPoint(XAt, YAt, ZAt);
113
114     gp_Vec anEyeVec(EyePoint, AtPoint);
115     anEyeVec.Normalize();
116
117     std::shared_ptr<GeomDataAPI_Dir> aNormal = std::dynamic_pointer_cast<GeomDataAPI_Dir>(
118         aData->attribute(SketchPlugin_Sketch::NORM_ID()));
119     gp_Vec aNormalVec(aNormal->x(), aNormal->y(), aNormal->z());
120
121     double aDen = anEyeVec * aNormalVec;
122     double aLVec = aDen != 0 ? aVec * aNormalVec / aDen : DBL_MAX;
123
124     gp_Vec aDeltaVec = anEyeVec * aLVec;
125     aVec = aVec - aDeltaVec;
126   }
127   theX = aVec.X() * aX->x() + aVec.Y() * aX->y() + aVec.Z() * aX->z();
128   theY = aVec.X() * anY->x() + aVec.Y() * anY->y() + aVec.Z() * anY->z();
129 }
130
131 std::shared_ptr<GeomAPI_Pnt> PartSet_Tools::convertTo3D(const double theX, const double theY, FeaturePtr theSketch)
132 {
133   std::shared_ptr<ModelAPI_Data> aData = theSketch->data();
134
135   std::shared_ptr<GeomDataAPI_Point> aC = std::dynamic_pointer_cast<GeomDataAPI_Point>(
136       aData->attribute(SketchPlugin_Sketch::ORIGIN_ID()));
137   std::shared_ptr<GeomDataAPI_Dir> aX = std::dynamic_pointer_cast<GeomDataAPI_Dir>(
138       aData->attribute(SketchPlugin_Sketch::DIRX_ID()));
139   std::shared_ptr<GeomDataAPI_Dir> aY = std::dynamic_pointer_cast<GeomDataAPI_Dir>(
140       aData->attribute(SketchPlugin_Sketch::DIRY_ID()));
141
142   std::shared_ptr<GeomAPI_Pnt2d> aPnt2d = 
143     std::shared_ptr<GeomAPI_Pnt2d>(new GeomAPI_Pnt2d(theX, theY));
144
145   return aPnt2d->to3D(aC->pnt(), aX->dir(), aY->dir());
146 }
147
148 ObjectPtr PartSet_Tools::nearestFeature(QPoint thePoint, Handle_V3d_View theView,
149                                         FeaturePtr theSketch,
150                                         const QList<ModuleBase_ViewerPrs>& theSelected,
151                                         const QList<ModuleBase_ViewerPrs>& theHighlighted)
152 {
153   // firstly it finds the feature in the list of highlight
154   ObjectPtr aDeltaObject  = nearestFeature(thePoint, theView, theSketch, theHighlighted);
155   if (!aDeltaObject)
156     // secondly it finds the feature in the list of selected objects
157     aDeltaObject  = nearestFeature(thePoint, theView, theSketch, theSelected);
158
159   return aDeltaObject;
160 }
161
162 ObjectPtr PartSet_Tools::nearestFeature(QPoint thePoint, Handle_V3d_View theView,
163                                         FeaturePtr theSketch,
164                                         const QList<ModuleBase_ViewerPrs>& thePresentations)
165 {
166   ObjectPtr aDeltaObject;
167
168   CompositeFeaturePtr aSketch = 
169       std::dynamic_pointer_cast<ModelAPI_CompositeFeature>(theSketch);
170   // 1. find it in the selected list by the selected point
171   if (!aDeltaObject) {
172     double aX, anY;
173     gp_Pnt aPoint = PartSet_Tools::convertClickToPoint(thePoint, theView);
174     PartSet_Tools::convertTo2D(aPoint, theSketch, theView, aX, anY);
175
176     FeaturePtr aFeature;
177     double aMinDelta = -1;
178     ModuleBase_ViewerPrs aPrs;
179     foreach (ModuleBase_ViewerPrs aPrs, thePresentations) {
180       if (!aPrs.object())
181         continue;
182       FeaturePtr aFeature = ModelAPI_Feature::feature(aPrs.object());
183       std::shared_ptr<SketchPlugin_Feature> aSketchFeature = std::dynamic_pointer_cast<
184           SketchPlugin_Feature>(aFeature);
185       if (!aSketchFeature || !aSketch->isSub(aSketchFeature))
186         continue;
187
188       double aDelta = aSketchFeature->distanceToPoint(
189           std::shared_ptr<GeomAPI_Pnt2d>(new GeomAPI_Pnt2d(aX, anY)));
190       if (aMinDelta < 0 || aMinDelta > aDelta) {
191         aMinDelta = aDelta;
192         // TODO aDeltaObject = aPrs.result();
193       }
194     }
195   }
196   // 2. if the object is not found, returns the first selected sketch feature
197   if (!aDeltaObject && thePresentations.size() > 0) {
198     // there can be some highlighted objects, e.g. a result of boolean operation and a sketch point
199     foreach (ModuleBase_ViewerPrs aPrs, thePresentations) {
200       if (!aPrs.object())
201         continue;
202       FeaturePtr aFeature = ModelAPI_Feature::feature(aPrs.object());
203       if (aFeature && aSketch->isSub(aFeature))
204         aDeltaObject = aPrs.object();
205     }
206   }
207   return aDeltaObject;
208 }
209
210 std::shared_ptr<ModelAPI_Document> PartSet_Tools::document()
211 {
212   return ModelAPI_Session::get()->moduleDocument();
213 }
214
215 std::shared_ptr<GeomDataAPI_Point2D> PartSet_Tools::getFeaturePoint(FeaturePtr theFeature,
216                                                                       double theX, double theY)
217 {
218   std::shared_ptr<GeomAPI_Pnt2d> aClickedPoint = std::shared_ptr<GeomAPI_Pnt2d>(
219                                                                  new GeomAPI_Pnt2d(theX, theY));
220   std::list<std::shared_ptr<ModelAPI_Attribute> > anAttiributes =
221                                     theFeature->data()->attributes(GeomDataAPI_Point2D::type());
222   std::list<std::shared_ptr<ModelAPI_Attribute> >::const_iterator anIt = anAttiributes.begin(),
223                                                                     aLast = anAttiributes.end();
224   std::shared_ptr<GeomDataAPI_Point2D> aFPoint;
225   for (; anIt != aLast && !aFPoint; anIt++) {
226     std::shared_ptr<GeomDataAPI_Point2D> aCurPoint = std::dynamic_pointer_cast<
227         GeomDataAPI_Point2D>(*anIt);
228     if (aCurPoint && aCurPoint->pnt()->distance(aClickedPoint) < Precision::Confusion())
229       aFPoint = aCurPoint;
230   }
231
232   return aFPoint;
233 }
234
235 void PartSet_Tools::setFeatureValue(FeaturePtr theFeature, double theValue,
236                                     const std::string& theAttribute)
237 {
238   if (!theFeature)
239     return;
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     anAttribute->setValue(theValue);
245 }
246
247 double PartSet_Tools::featureValue(FeaturePtr theFeature, const std::string& theAttribute,
248                                    bool& isValid)
249 {
250   isValid = false;
251   double aValue = 0;
252   if (theFeature) {
253     std::shared_ptr<ModelAPI_Data> aData = theFeature->data();
254     AttributeDoublePtr anAttribute = std::dynamic_pointer_cast<ModelAPI_AttributeDouble>(
255         aData->attribute(theAttribute));
256     if (anAttribute) {
257       aValue = anAttribute->value();
258       isValid = true;
259     }
260   }
261   return aValue;
262 }
263
264 FeaturePtr PartSet_Tools::feature(FeaturePtr theFeature, const std::string& theAttribute,
265                                   const std::string& theKind)
266 {
267   FeaturePtr aFeature;
268   if (!theFeature)
269     return aFeature;
270
271   std::shared_ptr<ModelAPI_Data> aData = theFeature->data();
272   std::shared_ptr<ModelAPI_AttributeRefAttr> anAttr = std::dynamic_pointer_cast<
273       ModelAPI_AttributeRefAttr>(aData->attribute(theAttribute));
274   if (anAttr) {
275     aFeature = std::dynamic_pointer_cast<ModelAPI_Feature>(anAttr->object());
276     if (!theKind.empty() && aFeature && aFeature->getKind() != theKind) {
277       aFeature = FeaturePtr();
278     }
279   }
280   return aFeature;
281 }
282
283 void PartSet_Tools::createConstraint(CompositeFeaturePtr theSketch,
284                                      std::shared_ptr<GeomDataAPI_Point2D> thePoint1,
285                                      std::shared_ptr<GeomDataAPI_Point2D> thePoint2)
286 {
287   FeaturePtr aFeature;
288   if (theSketch) {
289     aFeature = theSketch->addFeature(SketchPlugin_ConstraintCoincidence::ID());
290   } else {
291     std::shared_ptr<ModelAPI_Document> aDoc = document();
292     aFeature = aDoc->addFeature(SketchPlugin_ConstraintCoincidence::ID());
293   }
294
295   std::shared_ptr<ModelAPI_Data> aData = aFeature->data();
296
297   std::shared_ptr<ModelAPI_AttributeRefAttr> aRef1 = std::dynamic_pointer_cast<
298       ModelAPI_AttributeRefAttr>(aData->attribute(SketchPlugin_Constraint::ENTITY_A()));
299   aRef1->setAttr(thePoint1);
300
301   std::shared_ptr<ModelAPI_AttributeRefAttr> aRef2 = std::dynamic_pointer_cast<
302       ModelAPI_AttributeRefAttr>(aData->attribute(SketchPlugin_Constraint::ENTITY_B()));
303   aRef2->setAttr(thePoint2);
304
305   if (aFeature)  // TODO: generate an error if feature was not created
306     aFeature->execute();
307 }
308
309 void PartSet_Tools::setConstraints(CompositeFeaturePtr theSketch, FeaturePtr theFeature,
310                                    const std::string& theAttribute, double theClickedX,
311                                    double theClickedY)
312 {
313   // find a feature point by the selection mode
314   //std::shared_ptr<GeomDataAPI_Point2D> aPoint = featurePoint(theMode);
315   std::shared_ptr<GeomDataAPI_Point2D> aFeaturePoint = std::dynamic_pointer_cast<
316       GeomDataAPI_Point2D>(theFeature->data()->attribute(theAttribute));
317   if (!aFeaturePoint)
318     return;
319
320   // get all sketch features. If the point with the given coordinates belong to any sketch feature,
321   // the constraint is created between the feature point and the found sketch point
322   std::shared_ptr<ModelAPI_Data> aData = theSketch->data();
323   std::shared_ptr<ModelAPI_AttributeRefList> aRefList = std::dynamic_pointer_cast<
324       ModelAPI_AttributeRefList>(aData->attribute(SketchPlugin_Sketch::FEATURES_ID()));
325
326   std::list<ObjectPtr> aFeatures = aRefList->list();
327   std::list<ObjectPtr>::const_iterator anIt = aFeatures.begin(), aLast = aFeatures.end();
328   std::list<std::shared_ptr<ModelAPI_Attribute> > anAttiributes;
329   std::shared_ptr<GeomAPI_Pnt2d> aClickedPoint = std::shared_ptr<GeomAPI_Pnt2d>(
330       new GeomAPI_Pnt2d(theClickedX, theClickedY));
331   for (; anIt != aLast; anIt++) {
332     FeaturePtr aFeature = std::dynamic_pointer_cast<ModelAPI_Feature>(*anIt);
333     // find the given point in the feature attributes
334     anAttiributes = aFeature->data()->attributes(GeomDataAPI_Point2D::type());
335     std::list<std::shared_ptr<ModelAPI_Attribute> >::const_iterator anIt = anAttiributes.begin(),
336         aLast = anAttiributes.end();
337     std::shared_ptr<GeomDataAPI_Point2D> aFPoint;
338     for (; anIt != aLast && !aFPoint; anIt++) {
339       std::shared_ptr<GeomDataAPI_Point2D> aCurPoint = std::dynamic_pointer_cast<
340           GeomDataAPI_Point2D>(*anIt);
341       if (aCurPoint && aCurPoint->pnt()->distance(aClickedPoint) < Precision::Confusion())
342         aFPoint = aCurPoint;
343     }
344     if (aFPoint)
345       PartSet_Tools::createConstraint(theSketch, aFPoint, aFeaturePoint);
346   }
347 }
348
349 std::shared_ptr<GeomAPI_Pln> PartSet_Tools::sketchPlane(CompositeFeaturePtr theSketch)
350 {
351   std::shared_ptr<GeomAPI_Pln> aPlane;
352
353   std::shared_ptr<ModelAPI_Data> aData = theSketch->data();
354   std::shared_ptr<GeomDataAPI_Point> anOrigin = std::dynamic_pointer_cast<GeomDataAPI_Point>(
355       aData->attribute(SketchPlugin_Sketch::ORIGIN_ID()));
356   std::shared_ptr<GeomDataAPI_Dir> aNormal = std::dynamic_pointer_cast<GeomDataAPI_Dir>(
357       aData->attribute(SketchPlugin_Sketch::NORM_ID()));
358   if (aNormal && anOrigin) {
359     double adX = aNormal->x();
360     double adY = aNormal->y();
361     double adZ = aNormal->z();
362
363     if ( (adX != 0) || (adY != 0) || (adZ != 0) ) { // Plane is valid
364       double aX = anOrigin->x();
365       double aY = anOrigin->y();
366       double aZ = anOrigin->z();
367       gp_Pln aPln(gp_Pnt(aX, aY, aZ), gp_Dir(adX, adY, adZ));
368       double aA, aB, aC, aD;
369       aPln.Coefficients(aA, aB, aC, aD);
370       aPlane = std::shared_ptr<GeomAPI_Pln>(new GeomAPI_Pln(aA, aB, aC, aD));
371     }
372   }
373   return aPlane;
374 }
375
376 std::shared_ptr<GeomAPI_Pnt> PartSet_Tools::point3D(std::shared_ptr<GeomAPI_Pnt2d> thePoint2D,
377                                                       CompositeFeaturePtr theSketch)
378 {
379   std::shared_ptr<GeomAPI_Pnt> aPoint;
380   if (!theSketch || !thePoint2D)
381     return aPoint;
382
383   std::shared_ptr<GeomDataAPI_Point> aC = std::dynamic_pointer_cast<GeomDataAPI_Point>(
384       theSketch->data()->attribute(SketchPlugin_Sketch::ORIGIN_ID()));
385   std::shared_ptr<GeomDataAPI_Dir> aX = std::dynamic_pointer_cast<GeomDataAPI_Dir>(
386       theSketch->data()->attribute(SketchPlugin_Sketch::DIRX_ID()));
387   std::shared_ptr<GeomDataAPI_Dir> aY = std::dynamic_pointer_cast<GeomDataAPI_Dir>(
388       theSketch->data()->attribute(SketchPlugin_Sketch::DIRY_ID()));
389
390   return thePoint2D->to3D(aC->pnt(), aX->dir(), aY->dir());
391 }
392
393 bool PartSet_Tools::isConstraintFeature(const std::string& theKind)
394 {
395   return theKind == SketchPlugin_ConstraintDistance::ID()
396       || theKind == SketchPlugin_ConstraintLength::ID()
397       || theKind == SketchPlugin_ConstraintRadius::ID()
398       || theKind == SketchPlugin_ConstraintRigid::ID();
399 }
400
401 ResultPtr PartSet_Tools::createFixedObjectByEdge(const TopoDS_Shape& theShape, 
402                                                  const ObjectPtr& theObject, 
403                                                  CompositeFeaturePtr theSketch)
404 {
405   if (theShape.ShapeType() != TopAbs_EDGE)
406     return ResultPtr();
407
408   // Check that we already have such external edge
409   std::shared_ptr<GeomAPI_Edge> aInEdge = std::shared_ptr<GeomAPI_Edge>(new GeomAPI_Edge());
410   aInEdge->setImpl(new TopoDS_Shape(theShape));
411   ResultPtr aResult = findExternalEdge(theSketch, aInEdge);
412   if (aResult)
413     return aResult;
414
415   // If not found then we have to create new
416   Standard_Real aStart, aEnd;
417   Handle(V3d_View) aNullView;
418   FeaturePtr aMyFeature;
419
420   Handle(Geom_Curve) aCurve = BRep_Tool::Curve(TopoDS::Edge(theShape), aStart, aEnd);
421   GeomAdaptor_Curve aAdaptor(aCurve);
422   if (aAdaptor.GetType() == GeomAbs_Line) {
423     // Create line
424     aMyFeature = theSketch->addFeature(SketchPlugin_Line::ID());
425   } else if (aAdaptor.GetType() == GeomAbs_Circle) {
426     if (aAdaptor.IsClosed()) {
427       // Create circle
428       aMyFeature = theSketch->addFeature(SketchPlugin_Circle::ID());
429     } else {
430       // Create arc
431       aMyFeature = theSketch->addFeature(SketchPlugin_Arc::ID());
432     }
433   }
434   if (aMyFeature) {
435     DataPtr aData = aMyFeature->data();
436     AttributeSelectionPtr anAttr = 
437       std::dynamic_pointer_cast<ModelAPI_AttributeSelection>
438       (aData->attribute(SketchPlugin_Feature::EXTERNAL_ID()));
439
440     ResultPtr aRes = std::dynamic_pointer_cast<ModelAPI_Result>(theObject);
441     if (anAttr && aRes) {
442       std::shared_ptr<GeomAPI_Shape> anEdge(new GeomAPI_Shape);
443       anEdge->setImpl(new TopoDS_Shape(theShape));
444
445       anAttr->setValue(aRes, anEdge);
446
447       aMyFeature->execute();
448
449       // fix this edge
450       FeaturePtr aFix = theSketch->addFeature(SketchPlugin_ConstraintRigid::ID());
451       aFix->data()->refattr(SketchPlugin_Constraint::ENTITY_A())->
452         setObject(aMyFeature->lastResult());
453
454       return aMyFeature->lastResult();
455     }
456   }
457   return ResultPtr();
458 }
459
460 bool PartSet_Tools::isContainPresentation(const QList<ModuleBase_ViewerPrs>& theSelected,
461                                           const ModuleBase_ViewerPrs& thePrs)
462 {
463   foreach (ModuleBase_ViewerPrs aPrs, theSelected) {
464     if (aPrs.object() == thePrs.object())
465       return true;
466   }
467   return false;
468 }
469
470 ResultPtr PartSet_Tools::findExternalEdge(CompositeFeaturePtr theSketch, std::shared_ptr<GeomAPI_Edge> theEdge)
471 {
472   for (int i = 0; i < theSketch->numberOfSubs(); i++) {
473     FeaturePtr aFeature = theSketch->subFeature(i);
474     std::shared_ptr<SketchPlugin_Feature> aSketchFea = 
475       std::dynamic_pointer_cast<SketchPlugin_Feature>(aFeature);
476     if (aSketchFea) {
477       if (aSketchFea->isExternal()) {
478         std::list<ResultPtr> aResults = aSketchFea->results();
479         std::list<ResultPtr>::const_iterator aIt;
480         for (aIt = aResults.cbegin(); aIt != aResults.cend(); ++aIt) {
481           ResultConstructionPtr aRes = 
482             std::dynamic_pointer_cast<ModelAPI_ResultConstruction>(*aIt);
483           if (aRes) {
484             std::shared_ptr<GeomAPI_Shape> aShape = aRes->shape();
485             if (aShape) {
486               if (theEdge->isEqual(aShape))
487                 return aRes;
488             }
489           }
490         }
491       }
492     }
493   }
494   return ResultPtr();
495 }
496
497 bool PartSet_Tools::hasVertexShape(const ModuleBase_ViewerPrs& thePrs, FeaturePtr theSketch,
498                                    Handle_V3d_View theView, double& theX, double& theY)
499 {
500   bool aHasVertex = false;
501
502   const TopoDS_Shape& aShape = thePrs.shape();
503   if (!aShape.IsNull() && aShape.ShapeType() == TopAbs_VERTEX)
504   {
505     const TopoDS_Vertex& aVertex = TopoDS::Vertex(aShape);
506     if (!aVertex.IsNull())
507     {
508       gp_Pnt aPoint = BRep_Tool::Pnt(aVertex);
509       PartSet_Tools::convertTo2D(aPoint, theSketch, theView, theX, theY);
510       aHasVertex = true;
511     }
512   }
513
514   return aHasVertex;
515 }
516
517 AttributePtr PartSet_Tools::findAttributeBy2dPoint(ObjectPtr theObj, 
518                                                    const TopoDS_Shape theShape, 
519                                                    FeaturePtr theSketch)
520 {
521
522   AttributePtr anAttribute;
523   FeaturePtr aFeature = ModelAPI_Feature::feature(theObj);
524   if (aFeature) {
525     if (theShape.ShapeType() == TopAbs_VERTEX) {
526       const TopoDS_Vertex& aVertex = TopoDS::Vertex(theShape);
527       if (!aVertex.IsNull())  {
528         gp_Pnt aPoint = BRep_Tool::Pnt(aVertex);
529         std::shared_ptr<GeomAPI_Pnt> aValue = std::shared_ptr<GeomAPI_Pnt>(
530             new GeomAPI_Pnt(aPoint.X(), aPoint.Y(), aPoint.Z()));
531
532         // find the given point in the feature attributes
533         std::list<AttributePtr> anAttiributes = 
534           aFeature->data()->attributes(GeomDataAPI_Point2D::type());
535         std::list<AttributePtr>::const_iterator anIt = anAttiributes.begin(), 
536                                                 aLast = anAttiributes.end();
537         for (; anIt != aLast && !anAttribute; anIt++) {
538           std::shared_ptr<GeomDataAPI_Point2D> aCurPoint = 
539             std::dynamic_pointer_cast<GeomDataAPI_Point2D>(*anIt);
540
541           std::shared_ptr<GeomAPI_Pnt> aPnt = convertTo3D(aCurPoint->x(), aCurPoint->y(), theSketch);
542           if (aPnt && (aPnt->distance(aValue) < Precision::Confusion())) {
543             anAttribute = aCurPoint;
544             break;
545           }
546         }
547       }
548     }
549   }
550   return anAttribute;
551 }