Salome HOME
8b50a2ad57075d35fbd8993b4303882381964610
[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
20 #include <ModelAPI_Result.h>
21 #include <ModelAPI_Attribute.h>
22 #include <ModelAPI_AttributeRefAttr.h>
23 #include <ModelAPI_AttributeReference.h>
24 #include <ModelAPI_AttributeSelection.h>
25 #include <ModelAPI_AttributeSelectionList.h>
26 #include <ModelAPI_AttributeRefList.h>
27 #include <ModelAPI_Validator.h>
28 #include <ModelAPI_Session.h>
29 #include <ModelAPI_ResultCompSolid.h>
30
31 #include <Events_Error.h>
32
33 #include <GeomAPI_IPresentable.h>
34
35 #include <StdPrs_WFDeflectionShape.hxx>
36
37 #include <QList>
38
39 //#define DEBUG_EMPTY_SHAPE
40
41 // multi-rotation/translation operation
42 //#define DEBUG_HIDE_COPY_ATTRIBUTE
43 #ifdef DEBUG_HIDE_COPY_ATTRIBUTE
44 #include <ModelAPI_AttributeBoolean.h>
45 #include <SketchPlugin_SketchEntity.h>
46 #endif
47
48 IMPLEMENT_STANDARD_HANDLE(PartSet_OperationPrs, ViewerData_AISShape);
49 IMPLEMENT_STANDARD_RTTIEXT(PartSet_OperationPrs, ViewerData_AISShape);
50
51 PartSet_OperationPrs::PartSet_OperationPrs(ModuleBase_IWorkshop* theWorkshop)
52 : ViewerData_AISShape(TopoDS_Shape()), myWorkshop(theWorkshop), myUseAISWidth(false)
53 {
54   myShapeColor = Quantity_Color(1, 1, 1, Quantity_TOC_RGB);
55 }
56
57 bool PartSet_OperationPrs::hasShapes()
58 {
59   return !myFeatureShapes.empty();
60 }
61
62 void PartSet_OperationPrs::setShapeColor(const Quantity_Color& theColor)
63 {
64   myShapeColor = theColor;
65 }
66
67 void PartSet_OperationPrs::useAISWidth()
68 {
69   myUseAISWidth = true;
70 }
71
72 void PartSet_OperationPrs::Compute(const Handle(PrsMgr_PresentationManager3d)& thePresentationManager,
73                                    const Handle(Prs3d_Presentation)& thePresentation, 
74                                    const Standard_Integer theMode)
75 {
76   SetColor(myShapeColor);
77   thePresentation->Clear();
78
79   XGUI_Displayer* aDisplayer = XGUI_Tools::workshop(myWorkshop)->displayer();
80   Handle(Prs3d_Drawer) aDrawer = Attributes();
81
82   // create presentations on the base of the shapes
83   bool anEmptyAIS = true;
84   QMap<ObjectPtr, QList<GeomShapePtr> >::const_iterator anIt = myFeatureShapes.begin(),
85                                                         aLast = myFeatureShapes.end();
86   for (; anIt != aLast; anIt++) {
87     ObjectPtr anObject = anIt.key();
88     QList<GeomShapePtr> aShapes = anIt.value();
89     QList<GeomShapePtr>::const_iterator aShIt = aShapes.begin(), aShLast = aShapes.end();
90     for (; aShIt != aShLast; aShIt++) {
91       GeomShapePtr aGeomShape = *aShIt;
92       // the shape should not be checked here on empty value because it should be checked in
93       // appendShapeIfVisible() on the step of filling myFeatureShapes list
94       // the reason is to avoid empty AIS object visualized in the viewer
95       //if (!aGeomShape.get()) continue;
96       TopoDS_Shape aShape = aGeomShape.get() ? aGeomShape->impl<TopoDS_Shape>() : TopoDS_Shape();
97       // change deviation coefficient to provide more precise circle
98       ModuleBase_Tools::setDefaultDeviationCoefficient(aShape, aDrawer);
99
100       if (myUseAISWidth) {
101         AISObjectPtr anAISPtr = aDisplayer->getAISObject(anObject);
102         if (anAISPtr.get()) {
103           Handle(AIS_InteractiveObject) anIO = anAISPtr->impl<Handle(AIS_InteractiveObject)>();
104           if (!anIO.IsNull()) {
105             int aWidth = anIO->Width();
106             /// workaround for zero width. Else, there will be a crash
107             if (aWidth == 0) { // width returns of TSolid shape is zero
108               bool isDisplayed = !anIO->GetContext().IsNull();
109               aWidth = PartSet_Tools::getAISDefaultWidth();// default width value
110             }
111             setWidth(aDrawer, aWidth);
112           }
113         }
114       }
115       StdPrs_WFDeflectionShape::Add(thePresentation, aShape, aDrawer);
116       if (anEmptyAIS)
117         anEmptyAIS = false;
118     }
119   }
120   if (anEmptyAIS)
121     Events_Error::throwException("An empty AIS presentation: PartSet_OperationPrs");
122 }
123
124 void PartSet_OperationPrs::ComputeSelection(const Handle(SelectMgr_Selection)& aSelection,
125                                             const Standard_Integer aMode)
126 {
127   // the presentation is not used in the selection
128 }
129
130 bool isSubObject(const ObjectPtr& theObject, const FeaturePtr& theFeature)
131 {
132   bool isSub = false;
133   CompositeFeaturePtr aComposite = std::dynamic_pointer_cast<ModelAPI_CompositeFeature>(theFeature);
134   if (aComposite.get())
135     isSub = aComposite->isSub(theObject);
136
137   return isSub;
138 }
139
140 void PartSet_OperationPrs::addValue(const ObjectPtr& theObject, const GeomShapePtr& theShape,
141                                     const FeaturePtr& theFeature, ModuleBase_IWorkshop* theWorkshop,
142                                     QMap<ObjectPtr, QList<GeomShapePtr> >& theObjectShapes)
143 {
144   if (theObject.get()) {
145     ResultPtr aResult = std::dynamic_pointer_cast<ModelAPI_Result>(theObject);
146     if (aResult.get()) {
147       ResultCompSolidPtr aCompsolidResult = std::dynamic_pointer_cast<ModelAPI_ResultCompSolid>(theObject);
148       if (aCompsolidResult.get()) {
149         if (aCompsolidResult->numberOfSubs() > 0) {
150           for(int i = 0; i < aCompsolidResult->numberOfSubs(); i++) {
151             ResultPtr aSubResult = aCompsolidResult->subResult(i);
152             if (aSubResult.get()) {
153               GeomShapePtr aShape;
154               addValue(aSubResult, aShape, theFeature, theWorkshop, theObjectShapes);
155             }
156           }
157           return;
158         }
159       }
160 #ifdef DEBUG_HIDE_COPY_ATTRIBUTE
161       else {
162         FeaturePtr aFeature = ModelAPI_Feature::feature(theObject);
163         if (aFeature.get()) {
164           AttributeBooleanPtr aCopyAttr = aFeature->data()->boolean(SketchPlugin_SketchEntity::COPY_ID());
165           if (aCopyAttr.get()) {
166             bool isCopy = aCopyAttr->value();
167             if (isCopy)
168               return;
169           }
170         }
171       }
172 #endif
173     }
174
175     GeomShapePtr aShape = theShape;
176     if (!aShape.get()) {
177       ResultPtr aResult = std::dynamic_pointer_cast<ModelAPI_Result>(theObject);
178       if (aResult.get())
179         aShape = aResult->shape();
180     }
181     if (!isSubObject(theObject, theFeature))
182       appendShapeIfVisible(theWorkshop, theObject, aShape, theObjectShapes);
183   }
184 }
185
186 void PartSet_OperationPrs::appendShapeIfVisible(ModuleBase_IWorkshop* theWorkshop,
187                               const ObjectPtr& theObject,
188                               GeomShapePtr theGeomShape,
189                               QMap<ObjectPtr, QList<GeomShapePtr> >& theObjectShapes)
190 {
191   XGUI_Displayer* aDisplayer = XGUI_Tools::workshop(theWorkshop)->displayer();
192   if (XGUI_Displayer::isVisible(aDisplayer, theObject)) {
193     if (theGeomShape.get()) {
194       if (theObjectShapes.contains(theObject))
195         theObjectShapes[theObject].append(theGeomShape);
196       else {
197         QList<GeomShapePtr> aShapes;
198         aShapes.append(theGeomShape);
199         theObjectShapes[theObject] = aShapes;
200       }
201     } else {
202   #ifdef DEBUG_EMPTY_SHAPE
203       qDebug(QString("Empty shape in result, result: %1")
204               .arg(ModuleBase_Tools::objectInfo(theObject)).toStdString().c_str());
205   #endif
206     }
207   }
208 }
209
210 void PartSet_OperationPrs::getFeatureShapes(const FeaturePtr& theFeature,
211                                             ModuleBase_IWorkshop* theWorkshop,
212                                             QMap<ObjectPtr, QList<GeomShapePtr> >& theObjectShapes)
213 {
214   theObjectShapes.clear();
215   if (!theFeature.get())
216     return;
217
218   ModelAPI_ValidatorsFactory* aValidators = ModelAPI_Session::get()->validators();
219
220   QList<GeomShapePtr> aShapes;
221   std::list<AttributePtr> anAttributes = theFeature->data()->attributes("");
222   std::list<AttributePtr>::const_iterator anIt = anAttributes.begin(), aLast = anAttributes.end();
223   for (; anIt != aLast; anIt++) {
224     AttributePtr anAttribute = *anIt;
225     if (!isSelectionAttribute(anAttribute))
226       continue;
227
228     if (!aValidators->isCase(theFeature, anAttribute->id()))
229       continue; // this attribute is not participated in the current case
230
231     std::string anAttrType = anAttribute->attributeType();
232
233     if (anAttrType == ModelAPI_AttributeSelectionList::typeId()) {
234       std::shared_ptr<ModelAPI_AttributeSelectionList> aCurSelList = 
235               std::dynamic_pointer_cast<ModelAPI_AttributeSelectionList>(anAttribute);
236       for(int i = 0; i < aCurSelList->size(); i++) {
237         std::shared_ptr<ModelAPI_AttributeSelection> aSelAttribute = aCurSelList->value(i);
238         ResultPtr aResult = aSelAttribute->context();
239         GeomShapePtr aShape = aSelAttribute->value();
240         addValue(aResult, aShape, theFeature, theWorkshop, theObjectShapes);
241       }
242     }
243     if (anAttrType == ModelAPI_AttributeRefList::typeId()) {
244       std::shared_ptr<ModelAPI_AttributeRefList> aCurSelList =
245         std::dynamic_pointer_cast<ModelAPI_AttributeRefList>(anAttribute);
246       for (int i = 0; i < aCurSelList->size(); i++) {
247         ObjectPtr anObject = aCurSelList->object(i);
248         FeaturePtr aFeature = std::dynamic_pointer_cast<ModelAPI_Feature>(anObject);
249         // if a feature is stored in the attribute, we should obtain the feature results
250         // e.g. feature rectangle uses parameters feature lines in the attribute
251         if (aFeature.get()) {
252           getResultShapes(aFeature, theWorkshop, theObjectShapes, false);
253         }
254         else {
255           ResultPtr aResult = std::dynamic_pointer_cast<ModelAPI_Result>(anObject);
256           if (aResult.get()) {
257             GeomShapePtr aShape = aResult->shape();
258             if (aShape.get())
259               addValue(aResult, aShape, theFeature, theWorkshop, theObjectShapes);
260           }
261         }
262       }
263     }
264     else {
265       ObjectPtr anObject;
266       GeomShapePtr aShape;
267       if (anAttrType == ModelAPI_AttributeRefAttr::typeId()) {
268         AttributeRefAttrPtr anAttr = std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(anAttribute);
269         if (anAttr->isObject()) {
270           anObject = anAttr->object();
271         }
272         else {
273           AttributePtr anAttribute = anAttr->attr();
274           aShape = PartSet_Tools::findShapeBy2DPoint(anAttribute, theWorkshop);
275           // the distance point is not found if the point is selected in the 2nd time
276           // TODO: after debug, this check can be removed
277           if (!aShape.get())
278             continue;
279           anObject = anAttr->attr()->owner();
280         }
281       }
282       if (anAttrType == ModelAPI_AttributeSelection::typeId()) {
283         AttributeSelectionPtr anAttr = std::dynamic_pointer_cast<ModelAPI_AttributeSelection>(anAttribute);
284         anObject = anAttr->context();
285         aShape = anAttr->value();
286       }
287       if (anAttrType == ModelAPI_AttributeReference::typeId()) {
288         AttributeReferencePtr anAttr = std::dynamic_pointer_cast<ModelAPI_AttributeReference>(anAttribute);
289         anObject = anAttr->value();
290       }
291       addValue(anObject, aShape, theFeature, theWorkshop, theObjectShapes);
292     }
293   }
294 }
295
296 void PartSet_OperationPrs::getResultShapes(const FeaturePtr& theFeature,
297                                            ModuleBase_IWorkshop* theWorkshop,
298                                            QMap<ObjectPtr, QList<GeomShapePtr> >& theObjectShapes,
299                                            const bool theListShouldBeCleared)
300 {
301   if (theListShouldBeCleared)
302     theObjectShapes.clear();
303
304   if (!theFeature.get())
305     return;
306
307   XGUI_Displayer* aDisplayer = XGUI_Tools::workshop(theWorkshop)->displayer();
308
309   std::list<ResultPtr> aFeatureResults = theFeature->results();
310   std::list<ResultPtr>::const_iterator aRIt = aFeatureResults.begin(),
311                                        aRLast = aFeatureResults.end();
312   for (; aRIt != aRLast; aRIt++) {
313     ResultPtr aResult = *aRIt;
314     GeomShapePtr aGeomShape = aResult->shape();
315     appendShapeIfVisible(theWorkshop, aResult, aGeomShape, theObjectShapes);
316   }
317 }
318
319 void PartSet_OperationPrs::getHighlightedShapes(ModuleBase_IWorkshop* theWorkshop,
320                                                 QMap<ObjectPtr, QList<GeomShapePtr> >& theObjectShapes)
321 {
322   theObjectShapes.clear();
323
324   QList<ModuleBase_ViewerPrs> aValues;
325   ModuleBase_IPropertyPanel* aPanel = theWorkshop->propertyPanel();
326   if (aPanel) {
327     ModuleBase_ModelWidget* aWidget = aPanel->activeWidget();
328     if (aWidget) {
329       aWidget->getHighlighted(aValues);
330     }
331   }
332
333   QList<GeomShapePtr> aShapes;
334   QList<ModuleBase_ViewerPrs>::const_iterator anIIt = aValues.begin(),
335                                               aILast = aValues.end();
336   for (; anIIt != aILast; anIIt++) {
337     ModuleBase_ViewerPrs aPrs = *anIIt;
338     ObjectPtr anObject = aPrs.object();
339
340     GeomShapePtr aGeomShape = aPrs.shape();
341     if (!aGeomShape.get() || aGeomShape->isNull()) {
342       ResultPtr aResult = std::dynamic_pointer_cast<ModelAPI_Result>(anObject);
343       if (aResult.get()) {
344         aGeomShape = aResult->shape();
345       }
346     }
347     appendShapeIfVisible(theWorkshop, anObject, aGeomShape, theObjectShapes);
348   }
349 }
350
351
352 bool PartSet_OperationPrs::isSelectionAttribute(const AttributePtr& theAttribute)
353 {
354   std::string anAttrType = theAttribute->attributeType();
355
356   return anAttrType == ModelAPI_AttributeSelectionList::typeId() ||
357          anAttrType == ModelAPI_AttributeRefList::typeId() ||
358          anAttrType == ModelAPI_AttributeRefAttr::typeId() ||
359          anAttrType == ModelAPI_AttributeSelection::typeId() ||
360          anAttrType == ModelAPI_AttributeReference::typeId();
361 }