Salome HOME
Issue #1535 crash when mirror: debug information
[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_Error.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     ModuleBase_Tools::setDefaultDeviationCoefficient(aShape, aDrawer);
115
116     if (myUseAISWidth) {
117       Handle(AIS_InteractiveObject) anIO = anIter.Value();
118       if (!anIO.IsNull()) {
119         int aWidth = anIO->Width();
120         /// workaround for zero width. Else, there will be a crash
121         if (aWidth == 0) { // width returns of TSolid shape is zero
122           bool isDisplayed = !anIO->GetContext().IsNull();
123           aWidth = PartSet_Tools::getAISDefaultWidth();// default width value
124         }
125         setWidth(aDrawer, aWidth);
126       }
127     }
128     StdPrs_WFDeflectionShape::Add(thePresentation, aShape, aDrawer);
129   }
130   Set(aComp);
131   if (!aReadyToDisplay) {
132     Events_Error::throwException("An empty AIS presentation: PartSet_OperationPrs");
133     std::shared_ptr<Events_Message> aMsg = std::shared_ptr<Events_Message>(
134                 new Events_Message(Events_Loop::eventByName(EVENT_EMPTY_OPERATION_PRESENTATION)));
135     Events_Loop::loop()->send(aMsg);
136   }
137 #ifdef DEBUG_OPERATION_PRS
138   qDebug("PartSet_OperationPrs::Compute -- end");
139 #endif
140 }
141
142 void PartSet_OperationPrs::ComputeSelection(const Handle(SelectMgr_Selection)& aSelection,
143                                             const Standard_Integer aMode)
144 {
145   // the presentation is not used in the selection
146 }
147
148 NCollection_DataMap<TopoDS_Shape, Handle(AIS_InteractiveObject)>& PartSet_OperationPrs::shapesMap()
149 {
150   return myShapeToPrsMap;
151 }
152
153 bool isSubObject(const ObjectPtr& theObject, const FeaturePtr& theFeature)
154 {
155   bool isSub = false;
156   CompositeFeaturePtr aComposite = std::dynamic_pointer_cast<ModelAPI_CompositeFeature>(theFeature);
157   if (aComposite.get())
158     isSub = aComposite->isSub(theObject);
159
160   return isSub;
161 }
162
163 void PartSet_OperationPrs::addValue(const ObjectPtr& theObject, const GeomShapePtr& theShape,
164                                     const FeaturePtr& theFeature, ModuleBase_IWorkshop* theWorkshop,
165                                     QMap<ObjectPtr, QList<GeomShapePtr> >& theObjectShapes)
166 {
167   if (theObject.get()) {
168     ResultPtr aResult = std::dynamic_pointer_cast<ModelAPI_Result>(theObject);
169     if (aResult.get()) {
170       ResultCompSolidPtr aCompsolidResult = std::dynamic_pointer_cast<ModelAPI_ResultCompSolid>(theObject);
171       if (aCompsolidResult.get()) {
172         if (aCompsolidResult->numberOfSubs() > 0) {
173           for(int i = 0; i < aCompsolidResult->numberOfSubs(); i++) {
174             ResultPtr aSubResult = aCompsolidResult->subResult(i);
175             if (aSubResult.get()) {
176               GeomShapePtr aShape;
177               addValue(aSubResult, aShape, theFeature, theWorkshop, theObjectShapes);
178             }
179           }
180           return;
181         }
182       }
183 #ifdef DEBUG_HIDE_COPY_ATTRIBUTE
184       else {
185         FeaturePtr aFeature = ModelAPI_Feature::feature(theObject);
186         if (aFeature.get()) {
187           AttributeBooleanPtr aCopyAttr = aFeature->data()->boolean(SketchPlugin_SketchEntity::COPY_ID());
188           if (aCopyAttr.get()) {
189             bool isCopy = aCopyAttr->value();
190             if (isCopy)
191               return;
192           }
193         }
194       }
195 #endif
196     }
197
198     GeomShapePtr aShape = theShape;
199     if (!aShape.get()) {
200       ResultPtr aResult = std::dynamic_pointer_cast<ModelAPI_Result>(theObject);
201       if (aResult.get())
202         aShape = aResult->shape();
203     }
204     if (!isSubObject(theObject, theFeature))
205       appendShapeIfVisible(theWorkshop, theObject, aShape, theObjectShapes);
206   }
207 }
208
209 void PartSet_OperationPrs::appendShapeIfVisible(ModuleBase_IWorkshop* theWorkshop,
210                               const ObjectPtr& theObject,
211                               GeomShapePtr theGeomShape,
212                               QMap<ObjectPtr, QList<GeomShapePtr> >& theObjectShapes)
213 {
214   XGUI_Displayer* aDisplayer = XGUI_Tools::workshop(theWorkshop)->displayer();
215   if (XGUI_Displayer::isVisible(aDisplayer, theObject)) {
216     if (theGeomShape.get()) {
217       if (theObjectShapes.contains(theObject))
218         theObjectShapes[theObject].append(theGeomShape);
219       else {
220         QList<GeomShapePtr> aShapes;
221         aShapes.append(theGeomShape);
222         theObjectShapes[theObject] = aShapes;
223       }
224     } else {
225   #ifdef DEBUG_EMPTY_SHAPE
226       qDebug(QString("Empty shape in result, result: %1")
227               .arg(ModuleBase_Tools::objectInfo(theObject)).toStdString().c_str());
228   #endif
229     }
230   }
231 }
232
233 void PartSet_OperationPrs::getFeatureShapes(const FeaturePtr& theFeature,
234                                             ModuleBase_IWorkshop* theWorkshop,
235                                             QMap<ObjectPtr, QList<GeomShapePtr> >& theObjectShapes)
236 {
237   theObjectShapes.clear();
238   if (!theFeature.get())
239     return;
240
241   ModelAPI_ValidatorsFactory* aValidators = ModelAPI_Session::get()->validators();
242
243   QList<GeomShapePtr> aShapes;
244   std::list<AttributePtr> anAttributes = theFeature->data()->attributes("");
245   std::list<AttributePtr>::const_iterator anIt = anAttributes.begin(), aLast = anAttributes.end();
246   for (; anIt != aLast; anIt++) {
247     AttributePtr anAttribute = *anIt;
248     if (!isSelectionAttribute(anAttribute))
249       continue;
250
251     if (!aValidators->isCase(theFeature, anAttribute->id()))
252       continue; // this attribute is not participated in the current case
253
254     std::string anAttrType = anAttribute->attributeType();
255
256     if (anAttrType == ModelAPI_AttributeSelectionList::typeId()) {
257       std::shared_ptr<ModelAPI_AttributeSelectionList> aCurSelList = 
258               std::dynamic_pointer_cast<ModelAPI_AttributeSelectionList>(anAttribute);
259       for(int i = 0; i < aCurSelList->size(); i++) {
260         std::shared_ptr<ModelAPI_AttributeSelection> aSelAttribute = aCurSelList->value(i);
261         ResultPtr aResult = aSelAttribute->context();
262         GeomShapePtr aShape = aSelAttribute->value();
263         addValue(aResult, aShape, theFeature, theWorkshop, theObjectShapes);
264       }
265     }
266     if (anAttrType == ModelAPI_AttributeRefList::typeId()) {
267       std::shared_ptr<ModelAPI_AttributeRefList> aCurSelList =
268         std::dynamic_pointer_cast<ModelAPI_AttributeRefList>(anAttribute);
269       for (int i = 0; i < aCurSelList->size(); i++) {
270         ObjectPtr anObject = aCurSelList->object(i);
271         FeaturePtr aFeature = std::dynamic_pointer_cast<ModelAPI_Feature>(anObject);
272         // if a feature is stored in the attribute, we should obtain the feature results
273         // e.g. feature rectangle uses parameters feature lines in the attribute
274         if (aFeature.get()) {
275           getResultShapes(aFeature, theWorkshop, theObjectShapes, false);
276         }
277         else {
278           ResultPtr aResult = std::dynamic_pointer_cast<ModelAPI_Result>(anObject);
279           if (aResult.get()) {
280             GeomShapePtr aShape = aResult->shape();
281             if (aShape.get())
282               addValue(aResult, aShape, theFeature, theWorkshop, theObjectShapes);
283           }
284         }
285       }
286     }
287     else {
288       ObjectPtr anObject;
289       GeomShapePtr aShape;
290       if (anAttrType == ModelAPI_AttributeRefAttr::typeId()) {
291         AttributeRefAttrPtr anAttr = std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(anAttribute);
292         if (anAttr->isObject()) {
293           anObject = anAttr->object();
294         }
295         else {
296           AttributePtr anAttribute = anAttr->attr();
297           aShape = PartSet_Tools::findShapeBy2DPoint(anAttribute, theWorkshop);
298           // the distance point is not found if the point is selected in the 2nd time
299           // TODO: after debug, this check can be removed
300           if (!aShape.get())
301             continue;
302           anObject = anAttr->attr()->owner();
303         }
304       }
305       if (anAttrType == ModelAPI_AttributeSelection::typeId()) {
306         AttributeSelectionPtr anAttr = std::dynamic_pointer_cast<ModelAPI_AttributeSelection>(anAttribute);
307         anObject = anAttr->context();
308         aShape = anAttr->value();
309       }
310       if (anAttrType == ModelAPI_AttributeReference::typeId()) {
311         AttributeReferencePtr anAttr = std::dynamic_pointer_cast<ModelAPI_AttributeReference>(anAttribute);
312         anObject = anAttr->value();
313       }
314       addValue(anObject, aShape, theFeature, theWorkshop, theObjectShapes);
315     }
316   }
317 }
318
319 void PartSet_OperationPrs::getResultShapes(const FeaturePtr& theFeature,
320                                            ModuleBase_IWorkshop* theWorkshop,
321                                            QMap<ObjectPtr, QList<GeomShapePtr> >& theObjectShapes,
322                                            const bool theListShouldBeCleared)
323 {
324   if (theListShouldBeCleared)
325     theObjectShapes.clear();
326
327   if (!theFeature.get())
328     return;
329
330   XGUI_Displayer* aDisplayer = XGUI_Tools::workshop(theWorkshop)->displayer();
331
332   std::list<ResultPtr> aFeatureResults = theFeature->results();
333   std::list<ResultPtr>::const_iterator aRIt = aFeatureResults.begin(),
334                                        aRLast = aFeatureResults.end();
335   for (; aRIt != aRLast; aRIt++) {
336     ResultPtr aResult = *aRIt;
337     GeomShapePtr aGeomShape = aResult->shape();
338     appendShapeIfVisible(theWorkshop, aResult, aGeomShape, theObjectShapes);
339   }
340 }
341
342 void PartSet_OperationPrs::getHighlightedShapes(ModuleBase_IWorkshop* theWorkshop,
343                                                 QMap<ObjectPtr, QList<GeomShapePtr> >& theObjectShapes)
344 {
345   theObjectShapes.clear();
346
347   QList<ModuleBase_ViewerPrsPtr> aValues;
348   ModuleBase_IPropertyPanel* aPanel = theWorkshop->propertyPanel();
349   if (aPanel) {
350     ModuleBase_ModelWidget* aWidget = aPanel->activeWidget();
351     if (aWidget) {
352       aWidget->getHighlighted(aValues);
353     }
354   }
355
356   QList<GeomShapePtr> aShapes;
357   QList<ModuleBase_ViewerPrsPtr>::const_iterator anIIt = aValues.begin(),
358                                               aILast = aValues.end();
359   for (; anIIt != aILast; anIIt++) {
360     ModuleBase_ViewerPrsPtr aPrs = *anIIt;
361     ObjectPtr anObject = aPrs->object();
362
363     GeomShapePtr aGeomShape = aPrs->shape();
364     if (!aGeomShape.get() || aGeomShape->isNull()) {
365       ResultPtr aResult = std::dynamic_pointer_cast<ModelAPI_Result>(anObject);
366       if (aResult.get()) {
367         aGeomShape = aResult->shape();
368       }
369     }
370     appendShapeIfVisible(theWorkshop, anObject, aGeomShape, theObjectShapes);
371   }
372 }
373
374
375 bool PartSet_OperationPrs::isSelectionAttribute(const AttributePtr& theAttribute)
376 {
377   std::string anAttrType = theAttribute->attributeType();
378
379   return anAttrType == ModelAPI_AttributeSelectionList::typeId() ||
380          anAttrType == ModelAPI_AttributeRefList::typeId() ||
381          anAttrType == ModelAPI_AttributeRefAttr::typeId() ||
382          anAttrType == ModelAPI_AttributeSelection::typeId() ||
383          anAttrType == ModelAPI_AttributeReference::typeId();
384 }
385
386 void PartSet_OperationPrs::fillShapeList(const QMap<ObjectPtr, QList<GeomShapePtr> >& theFeatureShapes,
387                             ModuleBase_IWorkshop* theWorkshop,
388                             NCollection_DataMap<TopoDS_Shape, Handle(AIS_InteractiveObject)>& theShapeToPrsMap)
389 {
390   theShapeToPrsMap.Clear();
391
392   XGUI_Displayer* aDisplayer = XGUI_Tools::workshop(theWorkshop)->displayer();
393
394   // create presentations on the base of the shapes
395   QMap<ObjectPtr, QList<GeomShapePtr> >::const_iterator anIt = theFeatureShapes.begin(),
396                                                         aLast = theFeatureShapes.end();
397   for (; anIt != aLast; anIt++) {
398     ObjectPtr anObject = anIt.key();
399     QList<GeomShapePtr> aShapes = anIt.value();
400     QList<GeomShapePtr>::const_iterator aShIt = aShapes.begin(), aShLast = aShapes.end();
401     for (; aShIt != aShLast; aShIt++) {
402       GeomShapePtr aGeomShape = *aShIt;
403       // the shape should not be checked here on empty value because it should be checked in
404       // appendShapeIfVisible() on the step of filling theFeatureShapes list
405       // the reason is to avoid empty AIS object visualized in the viewer
406       //if (!aGeomShape.get()) continue;
407       TopoDS_Shape aShape = aGeomShape.get() ? aGeomShape->impl<TopoDS_Shape>() : TopoDS_Shape();
408       if (aShape.IsNull())
409         continue;
410
411       // change deviation coefficient to provide more precise circle
412       Handle(AIS_InteractiveObject) anIO;
413       AISObjectPtr anAISPtr = aDisplayer->getAISObject(anObject);
414       if (anAISPtr.get())
415         anIO = anAISPtr->impl<Handle(AIS_InteractiveObject)>();
416       theShapeToPrsMap.Bind(aShape, anIO);
417     }
418   }
419 }