Salome HOME
ModuleBase_ViewerPrs should contain GeomShapePtr instead of TopoDS_Shape.
[modules/shaper.git] / src / XGUI / XGUI_Selection.cpp
1 // Copyright (C) 2014-20xx CEA/DEN, EDF R&D -->
2
3 // File:        XGUI_Selection.cpp
4 // Created:     8 July 2014
5 // Author:      Vitaly SMETANNIKOV
6
7 #include "XGUI_Selection.h"
8 #include "XGUI_Workshop.h"
9 #include "XGUI_Displayer.h"
10 #include "XGUI_ViewerProxy.h"
11 #include "XGUI_ObjectsBrowser.h"
12
13 #include "ModuleBase_ResultPrs.h"
14
15 #include <ModelAPI_Feature.h>
16 #include <ModelAPI_Tools.h>
17
18 #include <AIS_InteractiveContext.hxx>
19 #include <AIS_Axis.hxx>
20 #include <AIS_Point.hxx>
21 #include <Geom_Line.hxx>
22 #include <BRep_Builder.hxx>
23 #include <TopoDS_Edge.hxx>
24 #include <Geom_Point.hxx>
25 #include <Geom_TrimmedCurve.hxx>
26 #include <Prs3d_DatumAspect.hxx>
27
28 #include <TColStd_ListIteratorOfListOfInteger.hxx>
29 #include <StdSelect_BRepOwner.hxx>
30
31 #include <set>
32
33 #define DEBUG_DELIVERY
34
35 XGUI_Selection::XGUI_Selection(XGUI_Workshop* theWorkshop)
36     : myWorkshop(theWorkshop)
37 {
38 }
39
40 QList<ModuleBase_ViewerPrs> XGUI_Selection::getSelected(const SelectionPlace& thePlace) const
41 {
42   QList<ModuleBase_ViewerPrs> aPresentations;
43
44   switch (thePlace) {
45     case Browser:
46       getSelectedInBrowser(aPresentations);
47     break;
48     case Viewer:
49       getSelectedInViewer(aPresentations);
50     break;
51   case AllControls:
52       getSelectedInViewer(aPresentations);
53       getSelectedInBrowser(aPresentations);
54     break;
55   }
56   return aPresentations;
57 }
58
59 Handle(AIS_InteractiveObject) XGUI_Selection::getIO(const ModuleBase_ViewerPrs& thePrs)
60 {
61   Handle(AIS_InteractiveObject) anIO = thePrs.interactive();
62   if (anIO.IsNull()) {
63     Handle(SelectMgr_EntityOwner) anOwner = thePrs.owner();
64     if (!anOwner.IsNull())
65       anIO = Handle(AIS_InteractiveObject)::DownCast(anOwner->Selectable());
66
67     if (anIO.IsNull() && thePrs.object()) {
68       XGUI_Displayer* aDisplayer = myWorkshop->displayer();
69       AISObjectPtr anAISObject = aDisplayer->getAISObject(thePrs.object());
70       if (anAISObject.get())
71         anIO = anAISObject->impl<Handle(AIS_InteractiveObject)>();
72     }
73   }
74   return anIO;
75 }
76
77 void XGUI_Selection::getSelectedInViewer(QList<ModuleBase_ViewerPrs>& thePresentations) const
78 {
79   Handle(AIS_InteractiveContext) aContext = myWorkshop->viewer()->AISContext();
80   if (!aContext.IsNull() && aContext->HasOpenedContext()) {
81     QList<long> aSelectedIds; // Remember of selected address in order to avoid duplicates
82     for (aContext->InitSelected(); aContext->MoreSelected(); aContext->NextSelected()) {
83       ModuleBase_ViewerPrs aPrs;
84       Handle(SelectMgr_EntityOwner) anOwner = aContext->SelectedOwner();
85
86       if (aSelectedIds.contains((long)anOwner.Access()))
87         continue;
88       aSelectedIds.append((long)anOwner.Access());
89
90       fillPresentation(aPrs, anOwner);
91
92       if (!thePresentations.contains(aPrs)) // TODO: check whether the presentation in a list
93         thePresentations.append(aPrs);
94     }
95   }
96 }
97
98 void XGUI_Selection::getSelectedInBrowser(QList<ModuleBase_ViewerPrs>& thePresentations) const
99 {
100   // collect the objects  of the parameter presentation to avoid a repeted objects in the result
101   QObjectPtrList aPresentationObjects;
102   QList<ModuleBase_ViewerPrs>::const_iterator aPrsIt = thePresentations.begin(),
103                                               aPrsLast = thePresentations.end();
104   for (; aPrsIt != aPrsLast; aPrsIt++) {
105     aPresentationObjects.push_back((*aPrsIt).object());
106   }
107
108   QObjectPtrList anObjects = selectedObjects();
109   QObjectPtrList::const_iterator anIt = anObjects.begin(), aLast = anObjects.end();
110   for (; anIt != aLast; anIt++) {
111     ObjectPtr anObject = *anIt;
112     if (anObject.get() != NULL && !aPresentationObjects.contains(anObject)) {
113       thePresentations.append(ModuleBase_ViewerPrs(anObject, GeomShapePtr(), NULL));
114     }
115   }
116 }
117
118 void XGUI_Selection::fillPresentation(ModuleBase_ViewerPrs& thePrs,
119                                       const Handle(SelectMgr_EntityOwner)& theOwner) const
120 {
121   thePrs.setOwner(theOwner);
122
123   Handle(AIS_InteractiveObject) anIO = 
124                            Handle(AIS_InteractiveObject)::DownCast(theOwner->Selectable());
125   thePrs.setInteractive(anIO);
126
127   // we should not check the appearance of this feature because there can be some selected shapes
128   // for one feature
129   Handle(StdSelect_BRepOwner) aBRO = Handle(StdSelect_BRepOwner)::DownCast(theOwner);
130   if( !aBRO.IsNull() && aBRO->HasShape() ) {
131     // the located method is called in the context to obtain the shape by the SelectedShape() method,
132     // so the shape is located by the same rules
133     TopoDS_Shape aShape = aBRO->Shape().Located (aBRO->Location() * aBRO->Shape().Location());
134 #ifndef DEBUG_DELIVERY
135     if (aShape.IsNull())
136       aShape = findAxisShape(anIO);
137 #endif
138     if (!aShape.IsNull()) {
139       std::shared_ptr<GeomAPI_Shape> aGeomShape = std::shared_ptr<GeomAPI_Shape>(new GeomAPI_Shape());
140       aGeomShape->setImpl(new TopoDS_Shape(aShape));
141       thePrs.setShape(aGeomShape);
142     }
143   } else {
144 #ifdef DEBUG_DELIVERY
145     // Fill by trihedron shapes
146     Handle(AIS_Axis) aAxis = Handle(AIS_Axis)::DownCast(anIO);
147     if (!aAxis.IsNull()) {
148       // an Axis from Trihedron
149       Handle(Geom_Line) aLine = aAxis->Component();
150       Handle(Prs3d_DatumAspect) DA = aAxis->Attributes()->DatumAspect();
151       Handle(Geom_TrimmedCurve) aTLine = new Geom_TrimmedCurve(aLine, 0, DA->FirstAxisLength());
152
153       BRep_Builder aBuilder;      
154       TopoDS_Edge aEdge;
155       aBuilder.MakeEdge(aEdge, aTLine, Precision::Confusion());
156       if (!aEdge.IsNull()) {
157         std::shared_ptr<GeomAPI_Shape> aGeomShape = std::shared_ptr<GeomAPI_Shape>(new GeomAPI_Shape());
158         aGeomShape->setImpl(new TopoDS_Shape(aEdge));
159         thePrs.setShape(aGeomShape);
160       }
161     } else {
162       Handle(AIS_Point) aPoint = Handle(AIS_Point)::DownCast(anIO);
163       if (!aPoint.IsNull()) {
164         // A point from trihedron
165         Handle(Geom_Point) aPnt = aPoint->Component();
166         BRep_Builder aBuilder;
167         TopoDS_Vertex aVertex;
168         aBuilder.MakeVertex(aVertex, aPnt->Pnt(), Precision::Confusion());
169         if (!aVertex.IsNull()) {
170           std::shared_ptr<GeomAPI_Shape> aGeomShape = std::shared_ptr<GeomAPI_Shape>(new GeomAPI_Shape());
171           aGeomShape->setImpl(new TopoDS_Shape(aVertex));
172           thePrs.setShape(aGeomShape);
173         }
174       }
175     }
176 #endif
177   }
178      
179   XGUI_Displayer* aDisplayer = myWorkshop->displayer();
180   ObjectPtr aFeature = aDisplayer->getObject(anIO);
181
182   Handle(ModuleBase_BRepOwner) aCompSolidBRO = Handle(ModuleBase_BRepOwner)::DownCast(theOwner);
183   if (!aCompSolidBRO.IsNull()) {
184     // If ModuleBase_BRepOwner object is created then it means that TopAbs_COMPSOLID selection mode
185     // is On and we have to use parent result which corresponds to the CompSolid shape
186     ResultPtr aResult = std::dynamic_pointer_cast<ModelAPI_Result>(aFeature);
187     if (aResult.get()) {
188       ResultCompSolidPtr aCompSolid = ModelAPI_Tools::compSolidOwner(aResult);
189       if (aCompSolid.get()) {
190         GeomShapePtr aShape = aCompSolid->shape();
191         if (aShape.get() && aShape->isEqual(thePrs.shape())) {
192           thePrs.setObject(aCompSolid);
193           return;
194         }
195       }
196     }
197   }
198   thePrs.setObject(aFeature);
199 }
200
201 QList<ModuleBase_ViewerPrs> XGUI_Selection::getHighlighted() const
202 {
203   QList<ModuleBase_ViewerPrs> aPresentations;
204   Handle(AIS_InteractiveContext) aContext = myWorkshop->viewer()->AISContext();
205   if (aContext.IsNull())
206     return aPresentations;
207
208   QList<long> aSelectedIds; // Remember of selected address in order to avoid duplicates
209   XGUI_Displayer* aDisplayer = myWorkshop->displayer();
210   for (aContext->InitDetected(); aContext->MoreDetected(); aContext->NextDetected()) {
211     ModuleBase_ViewerPrs aPrs;
212     Handle(AIS_InteractiveObject) anIO = aContext->DetectedInteractive();
213     if (aSelectedIds.contains((long)anIO.Access()))
214       continue;
215     
216     aSelectedIds.append((long)anIO.Access());
217     aPrs.setInteractive(anIO);
218
219     ObjectPtr aResult = aDisplayer->getObject(anIO);
220     // we should not check the appearance of this feature because there can be some selected shapes
221     // for one feature
222     aPrs.setObject(aResult);
223     if (aContext->HasOpenedContext()) {
224       TopoDS_Shape aShape = aContext->DetectedShape();
225       if (!aShape.IsNull()) {
226         std::shared_ptr<GeomAPI_Shape> aGeomShape = std::shared_ptr<GeomAPI_Shape>(new GeomAPI_Shape());
227         aGeomShape->setImpl(new TopoDS_Shape(aShape));
228         aPrs.setShape(aGeomShape);
229       }
230     }
231     aPresentations.push_back(aPrs);
232   }
233   return aPresentations;
234 }
235
236 QObjectPtrList XGUI_Selection::selectedObjects() const
237 {
238   return myWorkshop->objectBrowser()->selectedObjects();
239 }
240
241 void XGUI_Selection::setSelectedObjects( const QObjectPtrList& theObjects ) const
242 {
243   return myWorkshop->objectBrowser()->setObjectsSelected( theObjects );
244 }
245
246 QObjectPtrList XGUI_Selection::selectedPresentations() const
247 {
248   QObjectPtrList aSelectedList;
249
250   Handle(AIS_InteractiveContext) aContext = myWorkshop->viewer()->AISContext();
251   if (!aContext.IsNull()) {
252     for (aContext->InitSelected(); aContext->MoreSelected(); aContext->NextSelected()) {
253       Handle(AIS_InteractiveObject) anIO = aContext->SelectedInteractive();
254       ObjectPtr aResult = myWorkshop->displayer()->getObject(anIO);
255       if (aResult)
256         aSelectedList.append(aResult);
257     }
258   }
259   return aSelectedList;
260 }
261
262 //**************************************************************
263 QModelIndexList XGUI_Selection::selectedIndexes() const
264 {
265   return myWorkshop->objectBrowser()->selectedIndexes();
266 }
267
268 //**************************************************************
269 void XGUI_Selection::selectedAISObjects(AIS_ListOfInteractive& theList) const
270 {
271   theList.Clear();
272
273   Handle(AIS_InteractiveContext) aContext = myWorkshop->viewer()->AISContext();
274   if (!aContext.IsNull()) {
275     for (aContext->InitSelected(); aContext->MoreSelected(); aContext->NextSelected())
276       theList.Append(aContext->SelectedInteractive());
277   }
278 }
279
280 //**************************************************************
281 ObjectPtr XGUI_Selection::getSelectableObject(const Handle(SelectMgr_EntityOwner)& theOwner) const
282 {
283   ObjectPtr anObject;
284
285   Handle(SelectMgr_EntityOwner) aEO = theOwner;
286   if (!aEO.IsNull()) {
287     Handle(AIS_InteractiveObject) anObj = 
288       Handle(AIS_InteractiveObject)::DownCast(aEO->Selectable());
289     anObject = myWorkshop->displayer()->getObject(anObj);
290   }
291   return anObject;
292 }
293
294 //**************************************************************
295 void XGUI_Selection::selectedShapes(NCollection_List<TopoDS_Shape>& theList, 
296                                     std::list<ObjectPtr>& theOwners) const
297 {
298   theList.Clear();
299   Handle(AIS_InteractiveContext) aContext = myWorkshop->viewer()->AISContext();
300   if (aContext.IsNull())
301     return;
302
303   for (aContext->InitSelected(); aContext->MoreSelected(); aContext->NextSelected()) {
304     TopoDS_Shape aShape = aContext->SelectedShape();
305     if (aShape.IsNull()) {
306       aShape = findAxisShape(aContext->SelectedInteractive());
307     }
308     if (!aShape.IsNull()) {
309       theList.Append(aShape);
310       Handle(SelectMgr_EntityOwner) aEO = aContext->SelectedOwner();
311       if (!aEO.IsNull()) {
312         Handle(AIS_InteractiveObject) anObj = 
313           Handle(AIS_InteractiveObject)::DownCast(aEO->Selectable());
314         ObjectPtr anObject = myWorkshop->displayer()->getObject(anObj);
315         theOwners.push_back(anObject);
316       }
317     }
318   }
319 }
320
321 //**************************************************************
322 void XGUI_Selection::selectedOwners(SelectMgr_IndexedMapOfOwner& theSelectedOwners) const
323 {
324   Handle(AIS_InteractiveContext) aContext = myWorkshop->viewer()->AISContext();
325   if (!aContext.IsNull()) {
326     for (aContext->InitSelected(); aContext->MoreSelected(); aContext->NextSelected()) {
327       theSelectedOwners.Add(aContext->SelectedOwner());
328     }
329   }
330 }
331
332 //**************************************************************
333 void XGUI_Selection::entityOwners(const Handle(AIS_InteractiveObject)& theObject,
334                                   SelectMgr_IndexedMapOfOwner& theOwners) const
335 {
336   Handle(AIS_InteractiveContext) aContext = myWorkshop->viewer()->AISContext();
337   if (aContext.IsNull() || theObject.IsNull())
338     return;
339
340   TColStd_ListOfInteger aModes;
341   aContext->ActivatedModes(theObject, aModes);
342
343   TColStd_ListIteratorOfListOfInteger anIt(aModes);
344   for (; anIt.More(); anIt.Next()) {
345     int aMode = anIt.Value();
346     if (!theObject->HasSelection(aMode))
347       continue;
348
349     Handle(SelectMgr_Selection) aSelection = theObject->Selection(aMode);
350     for (aSelection->Init(); aSelection->More(); aSelection->Next()) {
351       Handle(SelectMgr_SensitiveEntity) anEntity = aSelection->Sensitive();
352       if (anEntity.IsNull())
353         continue;
354       Handle(SelectMgr_EntityOwner) anOwner =
355         Handle(SelectMgr_EntityOwner)::DownCast(anEntity->BaseSensitive()->OwnerId());
356       if (!anOwner.IsNull())
357         theOwners.Add(anOwner);
358     }
359   }
360 }
361
362 //**************************************************************
363 TopoDS_Shape XGUI_Selection::findAxisShape(Handle(AIS_InteractiveObject) theIO) const
364 {
365   TopoDS_Shape aShape;
366   // Fill by trihedron shapes
367   Handle(AIS_Axis) aAxis = Handle(AIS_Axis)::DownCast(theIO);
368   if (!aAxis.IsNull()) {
369     // an Axis from Trihedron
370     Handle(Geom_Line) aLine = aAxis->Component();
371     Handle(Prs3d_DatumAspect) DA = aAxis->Attributes()->DatumAspect();
372     Handle(Geom_TrimmedCurve) aTLine = new Geom_TrimmedCurve(aLine, 0, DA->FirstAxisLength());
373
374     BRep_Builder aBuilder;      
375     TopoDS_Edge aEdge;
376     aBuilder.MakeEdge(aEdge, aTLine, Precision::Confusion());
377     if (!aEdge.IsNull())
378       aShape = aEdge;
379   } else {
380     Handle(AIS_Point) aPoint = Handle(AIS_Point)::DownCast(theIO);
381     if (!aPoint.IsNull()) {
382       // A point from trihedron
383       Handle(Geom_Point) aPnt = aPoint->Component();
384       BRep_Builder aBuilder;
385       TopoDS_Vertex aVertex;
386       aBuilder.MakeVertex(aVertex, aPnt->Pnt(), Precision::Confusion());
387       if (!aVertex.IsNull())
388         aShape = aVertex;
389     }
390   }
391   return aShape;
392 }