]> SALOME platform Git repositories - modules/shaper.git/blob - src/PartSet/PartSet_SketcherMgr.cpp
Salome HOME
Edit arc by dragging
[modules/shaper.git] / src / PartSet / PartSet_SketcherMgr.cpp
1 // Copyright (C) 2014-20xx CEA/DEN, EDF R&D
2
3 // File:        PartSet_SketcherMgr.cpp
4 // Created:     19 Dec 2014
5 // Author:      Vitaly SMETANNIKOV
6
7 #include "PartSet_SketcherMgr.h"
8 #include "PartSet_Module.h"
9 #include "PartSet_WidgetPoint2D.h"
10 #include "PartSet_Tools.h"
11
12 #include <XGUI_ModuleConnector.h>
13 #include <XGUI_Displayer.h>
14 #include <XGUI_Workshop.h>
15 #include <XGUI_Selection.h>
16 #include <XGUI_SelectionMgr.h>
17
18 #include <ModuleBase_IViewer.h>
19 #include <ModuleBase_IWorkshop.h>
20 #include <ModuleBase_IViewWindow.h>
21 #include <ModuleBase_Operation.h>
22 #include <ModuleBase_ISelection.h>
23 #include <ModuleBase_IPropertyPanel.h>
24 #include <ModuleBase_Operation.h>
25
26 #include <Events_Loop.h>
27
28 #include <SketchPlugin_Line.h>
29 #include <SketchPlugin_Sketch.h>
30 #include <SketchPlugin_Point.h>
31 #include <SketchPlugin_Arc.h>
32 #include <SketchPlugin_Circle.h>
33 #include <SketchPlugin_ConstraintLength.h>
34 #include <SketchPlugin_ConstraintDistance.h>
35 #include <SketchPlugin_ConstraintParallel.h>
36 #include <SketchPlugin_ConstraintPerpendicular.h>
37 #include <SketchPlugin_ConstraintRadius.h>
38 #include <SketchPlugin_ConstraintRigid.h>
39
40 #include <SelectMgr_IndexedMapOfOwner.hxx>
41 #include <StdSelect_BRepOwner.hxx>
42
43 #include <ModelAPI_Events.h>
44
45 #include <QMouseEvent>
46 #include <QApplication>
47
48
49
50
51 /// Returns list of unique objects by sum of objects from List1 and List2
52 QList<ObjectPtr> getSumList(const QList<ModuleBase_ViewerPrs>& theList1,
53                                        const QList<ModuleBase_ViewerPrs>& theList2)
54 {
55   QList<ObjectPtr> aRes;
56   foreach (ModuleBase_ViewerPrs aPrs, theList1) {
57     if (!aRes.contains(aPrs.object()))
58       aRes.append(aPrs.object());
59   }
60   foreach (ModuleBase_ViewerPrs aPrs, theList2) {
61     if (!aRes.contains(aPrs.object()))
62       aRes.append(aPrs.object());
63   }
64   return aRes;
65 }
66
67
68
69
70 PartSet_SketcherMgr::PartSet_SketcherMgr(PartSet_Module* theModule)
71   : QObject(theModule), myModule(theModule), myIsDragging(false), myDragDone(false)
72 {
73   ModuleBase_IWorkshop* aWorkshop = myModule->workshop();
74   ModuleBase_IViewer* aViewer = aWorkshop->viewer();
75
76   connect(aViewer, SIGNAL(mousePress(ModuleBase_IViewWindow*, QMouseEvent*)),
77           this, SLOT(onMousePressed(ModuleBase_IViewWindow*, QMouseEvent*)));
78
79   connect(aViewer, SIGNAL(mouseRelease(ModuleBase_IViewWindow*, QMouseEvent*)),
80           this, SLOT(onMouseReleased(ModuleBase_IViewWindow*, QMouseEvent*)));
81
82   connect(aViewer, SIGNAL(mouseMove(ModuleBase_IViewWindow*, QMouseEvent*)),
83           this, SLOT(onMouseMoved(ModuleBase_IViewWindow*, QMouseEvent*)));
84
85   connect(aViewer, SIGNAL(mouseDoubleClick(ModuleBase_IViewWindow*, QMouseEvent*)),
86           this, SLOT(onMouseDoubleClick(ModuleBase_IViewWindow*, QMouseEvent*)));
87 }
88
89 PartSet_SketcherMgr::~PartSet_SketcherMgr()
90 {
91   if (!myPlaneFilter.IsNull())
92     myPlaneFilter.Nullify();
93 }
94
95 void PartSet_SketcherMgr::onMousePressed(ModuleBase_IViewWindow* theWnd, QMouseEvent* theEvent)
96 {
97   // 
98   if (!(theEvent->buttons() & Qt::LeftButton))
99     return;
100
101   ModuleBase_IWorkshop* aWorkshop = myModule->workshop();
102   ModuleBase_Operation* aOperation = aWorkshop->currentOperation();
103   // Use only for sketch operations
104   if (aOperation && myCurrentSketch) {
105     if (!PartSet_Tools::sketchPlane(myCurrentSketch))
106       return;
107
108     bool isSketcher = (aOperation->id().toStdString() == SketchPlugin_Sketch::ID());
109     bool isSketchOpe = sketchOperationIdList().contains(aOperation->id());
110
111     // Avoid non-sketch operations
112     if ((!isSketchOpe) && (!isSketcher))
113       return;
114
115     bool isEditing = aOperation->isEditOperation();
116
117     // Ignore creation sketch operation
118     if ((!isSketcher) && (!isEditing))
119       return;
120
121     if (theEvent->modifiers()) {
122       // If user performs multiselection
123       if (isSketchOpe /* && (!isSketcher)*/)
124         if (!aOperation->commit())
125           aOperation->abort();
126       return;
127     }
128
129     // MoveTo in order to highlight current object
130     ModuleBase_IViewer* aViewer = aWorkshop->viewer();
131     aViewer->AISContext()->MoveTo(theEvent->x(), theEvent->y(), theWnd->v3dView());
132
133     // Remember highlighted objects for editing
134     ModuleBase_ISelection* aSelect = aWorkshop->selection();
135     QList<ModuleBase_ViewerPrs> aHighlighted = aSelect->getHighlighted();
136     QList<ModuleBase_ViewerPrs> aSelected = aSelect->getSelected();
137     myEditingFeatures.clear();
138     myEditingAttr.clear();
139
140     bool aHasShift = (theEvent->modifiers() & Qt::ShiftModifier);
141     QObjectPtrList aSelObjects;
142     if (aHasShift)
143       aSelObjects = getSumList(aHighlighted, aSelected);
144     else {
145       foreach (ModuleBase_ViewerPrs aPrs, aHighlighted) {
146         aSelObjects.append(aPrs.object());
147       }
148     }
149     if ((aSelObjects.size() == 0)) {
150       if (isSketchOpe && (!isSketcher))
151         // commit previous operation
152         if (!aOperation->commit())
153           aOperation->abort();
154       return;
155     }
156     if (aSelObjects.size() == 1) {
157       // Move by selected shape (vertex). Can be used only for single selection
158       foreach(ModuleBase_ViewerPrs aPrs, aHighlighted) {
159         FeaturePtr aFeature = ModelAPI_Feature::feature(aHighlighted.first().object());
160         if (aFeature) {
161           myEditingFeatures.append(aFeature);
162           TopoDS_Shape aShape = aPrs.shape();
163           if (!aShape.IsNull()) {
164             if (aShape.ShapeType() == TopAbs_VERTEX) {
165               AttributePtr aAttr = PartSet_Tools::findAttributeBy2dPoint(myEditingFeatures.first(), 
166                                                                          aShape, myCurrentSketch);
167               if (aAttr)
168                 myEditingAttr.append(aAttr);
169             }
170           }
171         }
172       }
173     } else {
174       // Provide multi-selection. Can be used only for features
175       foreach (ObjectPtr aObj, aSelObjects) {
176         FeaturePtr aFeature = ModelAPI_Feature::feature(aObj);
177         if (aFeature && (!myEditingFeatures.contains(aFeature)))
178           myEditingFeatures.append(aFeature);
179       }
180
181     }
182     // If nothing highlighted - return
183     if (myEditingFeatures.size() == 0)
184       return;
185
186     if (isSketcher) {
187       myIsDragging = true;
188       get2dPoint(theWnd, theEvent, myCurX, myCurY);
189       myDragDone = false;
190       aWorkshop->viewer()->enableMultiselection(false);
191       launchEditing();
192
193     } else if (isSketchOpe && isEditing) {
194       // If selected another object commit current result
195       aOperation->commit();
196
197       myIsDragging = true;
198       get2dPoint(theWnd, theEvent, myCurX, myCurY);
199       myDragDone = false;
200       aWorkshop->viewer()->enableMultiselection(false);
201
202       // This is necessary in order to finalize previous operation
203       QApplication::processEvents();
204       launchEditing();
205     }
206   }
207 }
208
209 void PartSet_SketcherMgr::onMouseReleased(ModuleBase_IViewWindow* theWnd, QMouseEvent* theEvent)
210 {
211   ModuleBase_IWorkshop* aWorkshop = myModule->workshop();
212   ModuleBase_Operation* aOp = aWorkshop->currentOperation();
213   if (!aOp)
214     return;
215   if (!sketchOperationIdList().contains(aOp->id()))
216     return;
217
218   // Only for sketcher operations
219   ModuleBase_IViewer* aViewer = aWorkshop->viewer();
220   if (myIsDragging) {
221     myIsDragging = false;
222     if (myDragDone) {
223       aViewer->enableMultiselection(true);
224       //aOp->commit();
225       myEditingFeatures.clear();
226       myEditingAttr.clear();
227
228       // Reselect edited object
229       aViewer->AISContext()->MoveTo(theEvent->x(), theEvent->y(), theWnd->v3dView());
230       if (theEvent->modifiers() & Qt::ShiftModifier)
231         aViewer->AISContext()->ShiftSelect();
232       else
233         aViewer->AISContext()->Select();
234       return;
235     }
236   }
237   if (!aViewer->isMultiSelectionEnabled()) {
238     aViewer->enableMultiselection(true);
239   }
240 }
241
242 void PartSet_SketcherMgr::onMouseMoved(ModuleBase_IViewWindow* theWnd, QMouseEvent* theEvent)
243 {
244   if (myIsDragging) {
245     ModuleBase_Operation* aOperation = myModule->workshop()->currentOperation();
246     if (aOperation->id().toStdString() == SketchPlugin_Sketch::ID())
247       return; // No edit operation activated
248
249     static Events_ID anEvent = Events_Loop::eventByName(EVENT_OBJECT_MOVED);
250
251     Handle(V3d_View) aView = theWnd->v3dView();
252     gp_Pnt aPoint = PartSet_Tools::convertClickToPoint(theEvent->pos(), aView);
253     double aX, aY;
254     PartSet_Tools::convertTo2D(aPoint, myCurrentSketch, aView, aX, aY);
255     double dX =  aX - myCurX;
256     double dY =  aY - myCurY;
257
258     if ((myEditingAttr.size() == 1) && myEditingAttr.first()) {
259       // probably we have prehighlighted point
260       AttributePtr aAttr = myEditingAttr.first();
261       std::string aAttrId = aAttr->id();
262       ModuleBase_IPropertyPanel* aPanel = aOperation->propertyPanel();
263       QList<ModuleBase_ModelWidget*> aWidgets = aPanel->modelWidgets();
264       // Find corresponded widget to provide dragging
265       foreach (ModuleBase_ModelWidget* aWgt, aWidgets) {
266         if (aWgt->attributeID() == aAttrId) {
267           PartSet_WidgetPoint2D* aWgt2d = dynamic_cast<PartSet_WidgetPoint2D*>(aWgt);
268           if (aWgt2d) {
269             aWgt2d->setPoint(aWgt2d->x() + dX, aWgt2d->y() + dY);
270             break;
271           }
272         }
273       }
274     } else {
275       ModuleBase_IWorkshop* aWorkshop = myModule->workshop();
276       XGUI_ModuleConnector* aConnector = dynamic_cast<XGUI_ModuleConnector*>(aWorkshop);
277       XGUI_Displayer* aDisplayer = aConnector->workshop()->displayer();
278       bool isEnableUpdateViewer = aDisplayer->enableUpdateViewer(false);
279
280       foreach(FeaturePtr aFeature, myEditingFeatures) {
281         std::shared_ptr<SketchPlugin_Feature> aSketchFeature =
282           std::dynamic_pointer_cast<SketchPlugin_Feature>(aFeature);
283         if (aSketchFeature) {
284           // save the previous selection
285
286           std::list<AttributePtr> aSelectedAttributes;
287           getCurrentSelection(aSketchFeature, myCurrentSketch, aWorkshop, aSelectedAttributes);
288           // save the previous selection: end
289
290           aSketchFeature->move(dX, dY);
291           // TODO: the selection restore should be after the AIS presentation is rebuilt
292           Events_Loop::loop()->flush(Events_Loop::eventByName(EVENT_OBJECT_MOVED));
293           Events_Loop::loop()->flush(Events_Loop::eventByName(EVENT_OBJECT_UPDATED));
294
295           // restore the previous selection
296           SelectMgr_IndexedMapOfOwner anOwnersToSelect;
297           getSelectionOwners(aSketchFeature, myCurrentSketch, aWorkshop, aSelectedAttributes,
298                              anOwnersToSelect);
299           aConnector->workshop()->selector()->setSelectedOwners(anOwnersToSelect, false);
300           // restore the previous selection
301         }
302         ModelAPI_EventCreator::get()->sendUpdated(aSketchFeature, anEvent, true);
303         Events_Loop::loop()->flush(Events_Loop::eventByName(EVENT_OBJECT_UPDATED));
304       }
305       // TODO: set here
306       //Events_Loop::loop()->flush(Events_Loop::eventByName(EVENT_OBJECT_MOVED));
307       //Events_Loop::loop()->flush(Events_Loop::eventByName(EVENT_OBJECT_UPDATED));
308
309       //Events_Loop::loop()->flush(Events_Loop::eventByName(EVENT_OBJECT_TO_REDISPLAY));
310       aDisplayer->enableUpdateViewer(isEnableUpdateViewer);
311       aDisplayer->updateViewer();
312     }
313     myDragDone = true;
314     myCurX = aX;
315     myCurY = aY;
316   }
317 }
318
319 void PartSet_SketcherMgr::onMouseDoubleClick(ModuleBase_IViewWindow* theWnd, QMouseEvent* theEvent)
320 {
321   ModuleBase_Operation* aOperation = myModule->workshop()->currentOperation();
322   if (aOperation && aOperation->isEditOperation()) {
323     std::string aId = aOperation->id().toStdString();
324     if ((aId == SketchPlugin_ConstraintLength::ID()) ||
325       (aId == SketchPlugin_ConstraintDistance::ID()) ||
326       (aId == SketchPlugin_ConstraintRadius::ID())) 
327     {
328       // Activate dimension value editing on double click
329       ModuleBase_IPropertyPanel* aPanel = aOperation->propertyPanel();
330       QList<ModuleBase_ModelWidget*> aWidgets = aPanel->modelWidgets();
331       // Find corresponded widget to activate value editing
332       foreach (ModuleBase_ModelWidget* aWgt, aWidgets) {
333         if (aWgt->attributeID() == "ConstraintValue") {
334           aWgt->focusTo();
335           return;
336         }
337       }
338     }
339   }
340 }
341
342 void PartSet_SketcherMgr::get2dPoint(ModuleBase_IViewWindow* theWnd, QMouseEvent* theEvent, 
343                                 double& theX, double& theY)
344 {
345   Handle(V3d_View) aView = theWnd->v3dView();
346   gp_Pnt aPoint = PartSet_Tools::convertClickToPoint(theEvent->pos(), aView);
347   PartSet_Tools::convertTo2D(aPoint, myCurrentSketch, aView, theX, theY);
348 }
349
350 void PartSet_SketcherMgr::launchEditing()
351 {
352   if (myEditingFeatures.size() > 0) {
353     FeaturePtr aFeature = myEditingFeatures.first();
354     std::shared_ptr<SketchPlugin_Feature> aSPFeature = 
355               std::dynamic_pointer_cast<SketchPlugin_Feature>(aFeature);
356     if (aSPFeature) {
357       myModule->editFeature(aSPFeature);
358     }
359   }
360 }
361
362
363 QStringList PartSet_SketcherMgr::sketchOperationIdList()
364 {
365   static QStringList aIds;
366   if (aIds.size() == 0) {
367     aIds << SketchPlugin_Line::ID().c_str();
368     aIds << SketchPlugin_Point::ID().c_str();
369     aIds << SketchPlugin_Arc::ID().c_str();
370     aIds << SketchPlugin_Circle::ID().c_str();
371     aIds << SketchPlugin_ConstraintLength::ID().c_str();
372     aIds << SketchPlugin_ConstraintDistance::ID().c_str();
373     aIds << SketchPlugin_ConstraintRigid::ID().c_str();
374     aIds << SketchPlugin_ConstraintRadius::ID().c_str();
375     aIds << SketchPlugin_ConstraintPerpendicular::ID().c_str();
376     aIds << SketchPlugin_ConstraintParallel::ID().c_str();
377   }
378   return aIds;
379 }
380
381 void PartSet_SketcherMgr::startSketch(ModuleBase_Operation* theOperation)
382 {
383   // Display all sketcher sub-Objects
384   myCurrentSketch = std::dynamic_pointer_cast<ModelAPI_CompositeFeature>(theOperation->feature());
385   XGUI_ModuleConnector* aConnector = dynamic_cast<XGUI_ModuleConnector*>(myModule->workshop());
386   XGUI_Displayer* aDisplayer = aConnector->workshop()->displayer();
387
388   // Hide sketcher result
389   std::list<ResultPtr> aResults = myCurrentSketch->results();
390   std::list<ResultPtr>::const_iterator aIt;
391   for (aIt = aResults.begin(); aIt != aResults.end(); ++aIt) {
392     aDisplayer->erase((*aIt), false);
393   }
394   aDisplayer->erase(myCurrentSketch, false);
395
396   // Display sketcher objects
397   for (int i = 0; i < myCurrentSketch->numberOfSubs(); i++) {
398     FeaturePtr aFeature = myCurrentSketch->subFeature(i);
399     std::list<ResultPtr> aResults = aFeature->results();
400     std::list<ResultPtr>::const_iterator aIt;
401     for (aIt = aResults.begin(); aIt != aResults.end(); ++aIt) {
402       aDisplayer->display((*aIt), false);
403     }
404     aDisplayer->display(aFeature, false);
405   }
406
407   if (myPlaneFilter.IsNull()) 
408     myPlaneFilter = new ModuleBase_ShapeInPlaneFilter();
409
410   myModule->workshop()->viewer()->addSelectionFilter(myPlaneFilter);
411   if (theOperation->isEditOperation()) {
412     // If it is editing of sketch then it means that plane is already defined
413     std::shared_ptr<GeomAPI_Pln> aPln = PartSet_Tools::sketchPlane(myCurrentSketch);
414     myPlaneFilter->setPlane(aPln->impl<gp_Pln>());
415   }
416   aDisplayer->updateViewer();
417 }
418
419 void PartSet_SketcherMgr::stopSketch(ModuleBase_Operation* theOperation)
420 {
421   DataPtr aData = myCurrentSketch->data();
422   if ((!aData) || (!aData->isValid())) {
423     // The sketch was aborted
424     myCurrentSketch = CompositeFeaturePtr();
425     myModule->workshop()->viewer()->removeSelectionFilter(myPlaneFilter);
426     return; 
427   }
428   // Hide all sketcher sub-Objects
429   XGUI_ModuleConnector* aConnector = dynamic_cast<XGUI_ModuleConnector*>(myModule->workshop());
430   XGUI_Displayer* aDisplayer = aConnector->workshop()->displayer();
431   for (int i = 0; i < myCurrentSketch->numberOfSubs(); i++) {
432     FeaturePtr aFeature = myCurrentSketch->subFeature(i);
433     std::list<ResultPtr> aResults = aFeature->results();
434     std::list<ResultPtr>::const_iterator aIt;
435     for (aIt = aResults.begin(); aIt != aResults.end(); ++aIt) {
436       aDisplayer->erase((*aIt), false);
437     }
438     aDisplayer->erase(aFeature, false);
439   }
440   // Display sketcher result
441   std::list<ResultPtr> aResults = myCurrentSketch->results();
442   std::list<ResultPtr>::const_iterator aIt;
443   for (aIt = aResults.begin(); aIt != aResults.end(); ++aIt) {
444     aDisplayer->display((*aIt), false);
445   }
446   aDisplayer->display(myCurrentSketch);
447     
448   myCurrentSketch = CompositeFeaturePtr();
449   myModule->workshop()->viewer()->removeSelectionFilter(myPlaneFilter);
450   aDisplayer->updateViewer();
451 }
452
453
454 void PartSet_SketcherMgr::onPlaneSelected(const std::shared_ptr<GeomAPI_Pln>& thePln)
455 {
456   myPlaneFilter->setPlane(thePln->impl<gp_Pln>());
457 }
458
459 void PartSet_SketcherMgr::getCurrentSelection(const ObjectPtr& theObject,
460                                               const FeaturePtr& theSketch,
461                                               ModuleBase_IWorkshop* theWorkshop,
462                                               std::list<AttributePtr>& theSelectedAttributes)
463 {
464   FeaturePtr aFeature = ModelAPI_Feature::feature(theObject);
465   if (aFeature.get() == NULL)
466     return;
467
468   ModuleBase_IViewer* aViewer = theWorkshop->viewer();
469   Handle(AIS_InteractiveContext) aContext = aViewer->AISContext();
470   XGUI_ModuleConnector* aConnector = dynamic_cast<XGUI_ModuleConnector*>(theWorkshop);
471   XGUI_Displayer* aDisplayer = aConnector->workshop()->displayer();
472
473   // TODO: check all results and IPresentable feature
474   ResultPtr aResult = aFeature->firstResult();
475
476   bool isVisibleSketch = aDisplayer->isVisible(aResult);
477   AISObjectPtr aAISObj = aDisplayer->getAISObject(aResult);
478
479   if (aAISObj.get() != NULL) {
480     Handle(AIS_InteractiveObject) anAISIO = aAISObj->impl<Handle(AIS_InteractiveObject)>();
481     for (aContext->InitSelected(); aContext->MoreSelected(); aContext->NextSelected())
482     {
483       Handle(StdSelect_BRepOwner) aBRepOwner = Handle(StdSelect_BRepOwner)::DownCast(
484                                                                       aContext->SelectedOwner());
485       if (aBRepOwner.IsNull()) continue;
486
487       Handle(AIS_InteractiveObject) anIO = Handle(AIS_InteractiveObject)::DownCast(
488                                                                        aBRepOwner->Selectable());
489       if (anIO != anAISIO) continue;
490
491       if (aBRepOwner->HasShape()) {
492         const TopoDS_Shape& aShape = aBRepOwner->Shape();
493         TopAbs_ShapeEnum aShapeType = aShape.ShapeType();
494         if (aShapeType == TopAbs_VERTEX) {
495           AttributePtr aPntAttr = PartSet_Tools::findAttributeBy2dPoint(theObject,
496                                                                         aShape, theSketch);
497           if (aPntAttr.get() != NULL)
498             theSelectedAttributes.push_back(aPntAttr);
499         }
500       }
501     }
502   }
503 }
504
505 void PartSet_SketcherMgr::getSelectionOwners(const ObjectPtr& theObject,
506                                              const FeaturePtr& theSketch,
507                                              ModuleBase_IWorkshop* theWorkshop,
508                                              const std::list<AttributePtr>& theSelectedAttributes,
509                                              SelectMgr_IndexedMapOfOwner& anOwnersToSelect)
510 {
511   FeaturePtr aFeature = ModelAPI_Feature::feature(theObject);
512   if (aFeature.get() == NULL)
513     return;
514
515   ModuleBase_IViewer* aViewer = theWorkshop->viewer();
516   Handle(AIS_InteractiveContext) aContext = aViewer->AISContext();
517   XGUI_ModuleConnector* aConnector = dynamic_cast<XGUI_ModuleConnector*>(theWorkshop);
518   XGUI_Displayer* aDisplayer = aConnector->workshop()->displayer();
519
520   // TODO: check all results and IPresentable feature
521   ResultPtr aResult = aFeature->firstResult();
522
523   bool isVisibleSketch = aDisplayer->isVisible(aResult);
524   AISObjectPtr aAISObj = aDisplayer->getAISObject(aResult);
525
526   if (aAISObj.get() != NULL) {
527     Handle(AIS_InteractiveObject) anAISIO = aAISObj->impl<Handle(AIS_InteractiveObject)>();
528
529     SelectMgr_IndexedMapOfOwner aSelectedOwners;
530
531     aConnector->workshop()->selector()->selection()->entityOwners(anAISIO, aSelectedOwners);
532     for  ( Standard_Integer i = 1, n = aSelectedOwners.Extent(); i <= n; i++ ) {
533       Handle(StdSelect_BRepOwner) anOwner = Handle(StdSelect_BRepOwner)::DownCast(aSelectedOwners(i));
534       if ( anOwner.IsNull() || !anOwner->HasShape() )
535         continue;
536       const TopoDS_Shape& aShape = anOwner->Shape();
537       TopAbs_ShapeEnum aShapeType = aShape.ShapeType();
538       if (aShapeType == TopAbs_VERTEX) {
539         AttributePtr aPntAttr = PartSet_Tools::findAttributeBy2dPoint(aFeature, aShape, theSketch);
540         if (aPntAttr.get() != NULL) {
541           std::list<AttributePtr>::const_iterator anIt = theSelectedAttributes.begin(),
542                                                   aLast = theSelectedAttributes.end();
543           for (; anIt != aLast; anIt++) {
544             AttributePtr anAttrIt = *anIt;
545             if (anAttrIt.get() == aPntAttr.get()) {
546               anOwnersToSelect.Add(anOwner);
547             }
548           }
549         }
550       }
551     }
552   }
553 }