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