Salome HOME
Task "Make the size of the selection area even bigger, especially for points"
[modules/shaper.git] / src / PartSet / PartSet_OperationPrs.cpp
1 // Copyright (C) 2014-20xx CEA/DEN, EDF R&D
2
3 // File:        PartSet_OperationPrs.cpp
4 // Created:     01 Jul 2015
5 // Author:      Natalia ERMOLAEVA
6
7 #include "PartSet_OperationPrs.h"
8 #include "PartSet_Tools.h"
9
10 #include "XGUI_Workshop.h"
11 #include "XGUI_ModuleConnector.h"
12 #include "XGUI_Displayer.h"
13 #include "XGUI_Tools.h"
14
15 #include "ModuleBase_Tools.h"
16 #include "ModuleBase_IModule.h"
17 #include <ModuleBase_IPropertyPanel.h>
18 #include <ModuleBase_ModelWidget.h>
19 #include <ModuleBase_ViewerPrs.h>
20
21 #include <ModelAPI_Events.h>
22 #include <ModelAPI_Result.h>
23 #include <ModelAPI_Attribute.h>
24 #include <ModelAPI_AttributeRefAttr.h>
25 #include <ModelAPI_AttributeReference.h>
26 #include <ModelAPI_AttributeSelection.h>
27 #include <ModelAPI_AttributeSelectionList.h>
28 #include <ModelAPI_AttributeRefList.h>
29 #include <ModelAPI_Validator.h>
30 #include <ModelAPI_Session.h>
31 #include <ModelAPI_ResultCompSolid.h>
32
33 #include <Events_InfoMessage.h>
34 #include <Events_Loop.h>
35
36 #include <GeomAPI_IPresentable.h>
37
38 #include <StdPrs_WFDeflectionShape.hxx>
39
40 #include <QList>
41
42 #include <gp_Pnt.hxx>
43 #include <TopoDS_Vertex.hxx>
44 #include <BRepBuilderAPI_MakeVertex.hxx>
45 #include <BRep_Builder.hxx>
46 #include <TopoDS_Compound.hxx>
47
48 //#define DEBUG_EMPTY_SHAPE
49 //#define DEBUG_OPERATION_PRS
50
51 // multi-rotation/translation operation
52 //#define DEBUG_HIDE_COPY_ATTRIBUTE
53 #ifdef DEBUG_HIDE_COPY_ATTRIBUTE
54 #include <ModelAPI_AttributeBoolean.h>
55 #include <SketchPlugin_SketchEntity.h>
56 #endif
57
58 IMPLEMENT_STANDARD_HANDLE(PartSet_OperationPrs, ViewerData_AISShape);
59 IMPLEMENT_STANDARD_RTTIEXT(PartSet_OperationPrs, ViewerData_AISShape);
60
61 PartSet_OperationPrs::PartSet_OperationPrs(ModuleBase_IWorkshop* theWorkshop)
62 : ViewerData_AISShape(TopoDS_Shape()), myWorkshop(theWorkshop), myUseAISWidth(false)
63 {
64 #ifdef DEBUG_OPERATION_PRS
65   qDebug("PartSet_OperationPrs::PartSet_OperationPrs");
66 #endif
67   myShapeColor = Quantity_Color(1, 1, 1, Quantity_TOC_RGB);
68
69   // first presentation for having correct Compute until presentation with shapes are set
70   gp_Pnt aPnt(0.0, 0.0, 0.0);
71   BRepBuilderAPI_MakeVertex aMaker(aPnt);
72   TopoDS_Vertex aVertex = aMaker.Vertex();
73   myShapeToPrsMap.Bind(aVertex, NULL);
74 }
75
76 bool PartSet_OperationPrs::hasShapes()
77 {
78   return !myShapeToPrsMap.IsEmpty();
79 }
80
81 void PartSet_OperationPrs::setShapeColor(const Quantity_Color& theColor)
82 {
83   myShapeColor = theColor;
84 }
85
86 void PartSet_OperationPrs::useAISWidth()
87 {
88   myUseAISWidth = true;
89 }
90
91 void PartSet_OperationPrs::Compute(const Handle(PrsMgr_PresentationManager3d)& thePresentationManager,
92                                    const Handle(Prs3d_Presentation)& thePresentation, 
93                                    const Standard_Integer theMode)
94 {
95 #ifdef DEBUG_OPERATION_PRS
96   qDebug("PartSet_OperationPrs::Compute -- begin");
97 #endif
98
99   SetColor(myShapeColor);
100   thePresentation->Clear();
101   bool aReadyToDisplay = !myShapeToPrsMap.IsEmpty();
102
103   XGUI_Displayer* aDisplayer = XGUI_Tools::workshop(myWorkshop)->displayer();
104   Handle(Prs3d_Drawer) aDrawer = Attributes();
105   // create presentations on the base of the shapes
106   BRep_Builder aBuilder;
107   TopoDS_Compound aComp;
108   aBuilder.MakeCompound(aComp);
109   for(NCollection_DataMap<TopoDS_Shape, Handle(AIS_InteractiveObject)>::Iterator anIter(myShapeToPrsMap);
110       anIter.More(); anIter.Next()) {
111     const TopoDS_Shape& aShape = anIter.Key();
112     aBuilder.Add(aComp, aShape);
113     // change deviation coefficient to provide more precise circle
114     // as there is no result, the shape is processed to correct deviation. To be unified
115     ModuleBase_Tools::setDefaultDeviationCoefficient(aShape, aDrawer);
116
117     if (myUseAISWidth) {
118       Handle(AIS_InteractiveObject) anIO = anIter.Value();
119       if (!anIO.IsNull()) {
120         int aWidth = anIO->Width();
121         /// workaround for zero width. Else, there will be a crash
122         if (aWidth == 0) { // width returns of TSolid shape is zero
123           bool isDisplayed = !anIO->GetContext().IsNull();
124           aWidth = PartSet_Tools::getAISDefaultWidth();// default width value
125         }
126         setWidth(aDrawer, aWidth);
127       }
128     }
129     StdPrs_WFDeflectionShape::Add(thePresentation, aShape, aDrawer);
130   }
131   Set(aComp);
132   if (!aReadyToDisplay) {
133     Events_InfoMessage("PartSet_OperationPrs", 
134       "An empty AIS presentation: PartSet_OperationPrs").send();
135     std::shared_ptr<Events_Message> aMsg = std::shared_ptr<Events_Message>(
136                 new Events_Message(Events_Loop::eventByName(EVENT_EMPTY_OPERATION_PRESENTATION)));
137     Events_Loop::loop()->send(aMsg);
138   }
139 #ifdef DEBUG_OPERATION_PRS
140   qDebug("PartSet_OperationPrs::Compute -- end");
141 #endif
142 }
143
144 void PartSet_OperationPrs::ComputeSelection(const Handle(SelectMgr_Selection)& aSelection,
145                                             const Standard_Integer aMode)
146 {
147   // the presentation is not used in the selection
148 }
149
150 NCollection_DataMap<TopoDS_Shape, Handle(AIS_InteractiveObject)>& PartSet_OperationPrs::shapesMap()
151 {
152   return myShapeToPrsMap;
153 }
154
155 bool isSubObject(const ObjectPtr& theObject, const FeaturePtr& theFeature)
156 {
157   bool isSub = false;
158   CompositeFeaturePtr aComposite = std::dynamic_pointer_cast<ModelAPI_CompositeFeature>(theFeature);
159   if (aComposite.get())
160     isSub = aComposite->isSub(theObject);
161
162   return isSub;
163 }
164
165 void PartSet_OperationPrs::addValue(const ObjectPtr& theObject, const GeomShapePtr& theShape,
166                                     const FeaturePtr& theFeature, ModuleBase_IWorkshop* theWorkshop,
167                                     QMap<ObjectPtr, QList<GeomShapePtr> >& theObjectShapes)
168 {
169   if (theObject.get()) {
170     ResultPtr aResult = std::dynamic_pointer_cast<ModelAPI_Result>(theObject);
171     if (aResult.get()) {
172       ResultCompSolidPtr aCompsolidResult = std::dynamic_pointer_cast<ModelAPI_ResultCompSolid>(theObject);
173       if (aCompsolidResult.get()) {
174         if (aCompsolidResult->numberOfSubs() > 0) {
175           for(int i = 0; i < aCompsolidResult->numberOfSubs(); i++) {
176             ResultPtr aSubResult = aCompsolidResult->subResult(i);
177             if (aSubResult.get()) {
178               GeomShapePtr aShape;
179               addValue(aSubResult, aShape, theFeature, theWorkshop, theObjectShapes);
180             }
181           }
182           return;
183         }
184       }
185 #ifdef DEBUG_HIDE_COPY_ATTRIBUTE
186       else {
187         FeaturePtr aFeature = ModelAPI_Feature::feature(theObject);
188         if (aFeature.get()) {
189           AttributeBooleanPtr aCopyAttr = aFeature->data()->boolean(SketchPlugin_SketchEntity::COPY_ID());
190           if (aCopyAttr.get()) {
191             bool isCopy = aCopyAttr->value();
192             if (isCopy)
193               return;
194           }
195         }
196       }
197 #endif
198     }
199
200     GeomShapePtr aShape = theShape;
201     if (!aShape.get()) {
202       ResultPtr aResult = std::dynamic_pointer_cast<ModelAPI_Result>(theObject);
203       if (aResult.get())
204         aShape = aResult->shape();
205     }
206     if (!isSubObject(theObject, theFeature))
207       appendShapeIfVisible(theWorkshop, theObject, aShape, theObjectShapes);
208   }
209 }
210
211 void PartSet_OperationPrs::appendShapeIfVisible(ModuleBase_IWorkshop* theWorkshop,
212                               const ObjectPtr& theObject,
213                               GeomShapePtr theGeomShape,
214                               QMap<ObjectPtr, QList<GeomShapePtr> >& theObjectShapes)
215 {
216   XGUI_Displayer* aDisplayer = XGUI_Tools::workshop(theWorkshop)->displayer();
217   if (XGUI_Displayer::isVisible(aDisplayer, theObject)) {
218     if (theGeomShape.get()) {
219       if (theObjectShapes.contains(theObject))
220         theObjectShapes[theObject].append(theGeomShape);
221       else {
222         QList<GeomShapePtr> aShapes;
223         aShapes.append(theGeomShape);
224         theObjectShapes[theObject] = aShapes;
225       }
226     } else {
227   #ifdef DEBUG_EMPTY_SHAPE
228       qDebug(QString("Empty shape in result, result: %1")
229               .arg(ModuleBase_Tools::objectInfo(theObject)).toStdString().c_str());
230   #endif
231     }
232   }
233 }
234
235 void PartSet_OperationPrs::getFeatureShapes(const FeaturePtr& theFeature,
236                                             ModuleBase_IWorkshop* theWorkshop,
237                                             QMap<ObjectPtr, QList<GeomShapePtr> >& theObjectShapes)
238 {
239   theObjectShapes.clear();
240   if (!theFeature.get())
241     return;
242
243   ModelAPI_ValidatorsFactory* aValidators = ModelAPI_Session::get()->validators();
244
245   QList<GeomShapePtr> aShapes;
246   std::list<AttributePtr> anAttributes = theFeature->data()->attributes("");
247   std::list<AttributePtr>::const_iterator anIt = anAttributes.begin(), aLast = anAttributes.end();
248   for (; anIt != aLast; anIt++) {
249     AttributePtr anAttribute = *anIt;
250     if (!isSelectionAttribute(anAttribute))
251       continue;
252
253     if (!aValidators->isCase(theFeature, anAttribute->id()))
254       continue; // this attribute is not participated in the current case
255
256     std::string anAttrType = anAttribute->attributeType();
257
258     if (anAttrType == ModelAPI_AttributeSelectionList::typeId()) {
259       std::shared_ptr<ModelAPI_AttributeSelectionList> aCurSelList = 
260               std::dynamic_pointer_cast<ModelAPI_AttributeSelectionList>(anAttribute);
261       for(int i = 0; i < aCurSelList->size(); i++) {
262         std::shared_ptr<ModelAPI_AttributeSelection> aSelAttribute = aCurSelList->value(i);
263         ResultPtr aResult = aSelAttribute->context();
264         GeomShapePtr aShape = aSelAttribute->value();
265         addValue(aResult, aShape, theFeature, theWorkshop, theObjectShapes);
266       }
267     }
268     if (anAttrType == ModelAPI_AttributeRefList::typeId()) {
269       std::shared_ptr<ModelAPI_AttributeRefList> aCurSelList =
270         std::dynamic_pointer_cast<ModelAPI_AttributeRefList>(anAttribute);
271       for (int i = 0; i < aCurSelList->size(); i++) {
272         ObjectPtr anObject = aCurSelList->object(i);
273         FeaturePtr aFeature = std::dynamic_pointer_cast<ModelAPI_Feature>(anObject);
274         // if a feature is stored in the attribute, we should obtain the feature results
275         // e.g. feature rectangle uses parameters feature lines in the attribute
276         if (aFeature.get()) {
277           getResultShapes(aFeature, theWorkshop, theObjectShapes, false);
278         }
279         else {
280           ResultPtr aResult = std::dynamic_pointer_cast<ModelAPI_Result>(anObject);
281           if (aResult.get()) {
282             GeomShapePtr aShape = aResult->shape();
283             if (aShape.get())
284               addValue(aResult, aShape, theFeature, theWorkshop, theObjectShapes);
285           }
286         }
287       }
288     }
289     else {
290       ObjectPtr anObject;
291       GeomShapePtr aShape;
292       if (anAttrType == ModelAPI_AttributeRefAttr::typeId()) {
293         AttributeRefAttrPtr anAttr = std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(anAttribute);
294         if (anAttr->isObject()) {
295           anObject = anAttr->object();
296         }
297         else {
298           AttributePtr anAttribute = anAttr->attr();
299           aShape = PartSet_Tools::findShapeBy2DPoint(anAttribute, theWorkshop);
300           // the distance point is not found if the point is selected in the 2nd time
301           // TODO: after debug, this check can be removed
302           if (!aShape.get())
303             continue;
304           anObject = anAttr->attr()->owner();
305         }
306       }
307       if (anAttrType == ModelAPI_AttributeSelection::typeId()) {
308         AttributeSelectionPtr anAttr = std::dynamic_pointer_cast<ModelAPI_AttributeSelection>(anAttribute);
309         anObject = anAttr->context();
310         aShape = anAttr->value();
311       }
312       if (anAttrType == ModelAPI_AttributeReference::typeId()) {
313         AttributeReferencePtr anAttr = std::dynamic_pointer_cast<ModelAPI_AttributeReference>(anAttribute);
314         anObject = anAttr->value();
315       }
316       addValue(anObject, aShape, theFeature, theWorkshop, theObjectShapes);
317     }
318   }
319 }
320
321 void PartSet_OperationPrs::getResultShapes(const FeaturePtr& theFeature,
322                                            ModuleBase_IWorkshop* theWorkshop,
323                                            QMap<ObjectPtr, QList<GeomShapePtr> >& theObjectShapes,
324                                            const bool theListShouldBeCleared)
325 {
326   if (theListShouldBeCleared)
327     theObjectShapes.clear();
328
329   if (!theFeature.get())
330     return;
331
332   XGUI_Displayer* aDisplayer = XGUI_Tools::workshop(theWorkshop)->displayer();
333
334   std::list<ResultPtr> aFeatureResults = theFeature->results();
335   std::list<ResultPtr>::const_iterator aRIt = aFeatureResults.begin(),
336                                        aRLast = aFeatureResults.end();
337   for (; aRIt != aRLast; aRIt++) {
338     ResultPtr aResult = *aRIt;
339     GeomShapePtr aGeomShape = aResult->shape();
340     appendShapeIfVisible(theWorkshop, aResult, aGeomShape, theObjectShapes);
341   }
342 }
343
344 void PartSet_OperationPrs::getHighlightedShapes(ModuleBase_IWorkshop* theWorkshop,
345                                                 QMap<ObjectPtr, QList<GeomShapePtr> >& theObjectShapes)
346 {
347   theObjectShapes.clear();
348
349   QList<ModuleBase_ViewerPrsPtr> aValues;
350   ModuleBase_IPropertyPanel* aPanel = theWorkshop->propertyPanel();
351   if (aPanel) {
352     ModuleBase_ModelWidget* aWidget = aPanel->activeWidget();
353     if (aWidget) {
354       aWidget->getHighlighted(aValues);
355     }
356   }
357
358   QList<GeomShapePtr> aShapes;
359   QList<ModuleBase_ViewerPrsPtr>::const_iterator anIIt = aValues.begin(),
360                                               aILast = aValues.end();
361   for (; anIIt != aILast; anIIt++) {
362     ModuleBase_ViewerPrsPtr aPrs = *anIIt;
363     ObjectPtr anObject = aPrs->object();
364
365     GeomShapePtr aGeomShape = aPrs->shape();
366     if (!aGeomShape.get() || aGeomShape->isNull()) {
367       ResultPtr aResult = std::dynamic_pointer_cast<ModelAPI_Result>(anObject);
368       if (aResult.get()) {
369         aGeomShape = aResult->shape();
370       }
371     }
372     appendShapeIfVisible(theWorkshop, anObject, aGeomShape, theObjectShapes);
373   }
374 }
375
376
377 bool PartSet_OperationPrs::isSelectionAttribute(const AttributePtr& theAttribute)
378 {
379   std::string anAttrType = theAttribute->attributeType();
380
381   return anAttrType == ModelAPI_AttributeSelectionList::typeId() ||
382          anAttrType == ModelAPI_AttributeRefList::typeId() ||
383          anAttrType == ModelAPI_AttributeRefAttr::typeId() ||
384          anAttrType == ModelAPI_AttributeSelection::typeId() ||
385          anAttrType == ModelAPI_AttributeReference::typeId();
386 }
387
388 void PartSet_OperationPrs::fillShapeList(const QMap<ObjectPtr, QList<GeomShapePtr> >& theFeatureShapes,
389                             ModuleBase_IWorkshop* theWorkshop,
390                             NCollection_DataMap<TopoDS_Shape, Handle(AIS_InteractiveObject)>& theShapeToPrsMap)
391 {
392   theShapeToPrsMap.Clear();
393
394   XGUI_Displayer* aDisplayer = XGUI_Tools::workshop(theWorkshop)->displayer();
395
396   // create presentations on the base of the shapes
397   QMap<ObjectPtr, QList<GeomShapePtr> >::const_iterator anIt = theFeatureShapes.begin(),
398                                                         aLast = theFeatureShapes.end();
399   for (; anIt != aLast; anIt++) {
400     ObjectPtr anObject = anIt.key();
401     QList<GeomShapePtr> aShapes = anIt.value();
402     QList<GeomShapePtr>::const_iterator aShIt = aShapes.begin(), aShLast = aShapes.end();
403     for (; aShIt != aShLast; aShIt++) {
404       GeomShapePtr aGeomShape = *aShIt;
405       // the shape should not be checked here on empty value because it should be checked in
406       // appendShapeIfVisible() on the step of filling theFeatureShapes list
407       // the reason is to avoid empty AIS object visualized in the viewer
408       //if (!aGeomShape.get()) continue;
409       TopoDS_Shape aShape = aGeomShape.get() ? aGeomShape->impl<TopoDS_Shape>() : TopoDS_Shape();
410       if (aShape.IsNull())
411         continue;
412
413       // change deviation coefficient to provide more precise circle
414       Handle(AIS_InteractiveObject) anIO;
415       AISObjectPtr anAISPtr = aDisplayer->getAISObject(anObject);
416       if (anAISPtr.get())
417         anIO = anAISPtr->impl<Handle(AIS_InteractiveObject)>();
418       theShapeToPrsMap.Bind(aShape, anIO);
419     }
420   }
421 }