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