Salome HOME
Debug : use plane for symmetry.
[modules/shaper.git] / src / FeaturesPlugin / FeaturesPlugin_Union.cpp
1 // Copyright (C) 2014-20xx CEA/DEN, EDF R&D -->
2
3 // File:        FeaturesPlugin_Union.cpp
4 // Created:     17 June 2016
5 // Author:      Dmitry Bobylev
6
7 #include "FeaturesPlugin_Union.h"
8
9 #include <GeomAlgoAPI_Boolean.h>
10 #include <GeomAlgoAPI_MakeShapeList.h>
11 #include <GeomAlgoAPI_PaveFiller.h>
12
13 #include <GeomAPI_ShapeExplorer.h>
14
15 #include <ModelAPI_AttributeSelectionList.h>
16 #include <ModelAPI_ResultCompSolid.h>
17 #include <ModelAPI_Tools.h>
18
19 //=================================================================================================
20 FeaturesPlugin_Union::FeaturesPlugin_Union()
21 {
22 }
23
24 //=================================================================================================
25 void FeaturesPlugin_Union::initAttributes()
26 {
27   data()->addAttribute(BASE_OBJECTS_ID(), ModelAPI_AttributeSelectionList::typeId());
28 }
29
30 //=================================================================================================
31 void FeaturesPlugin_Union::execute()
32 {
33   ListOfShape anObjects;
34   std::map<std::shared_ptr<GeomAPI_Shape>, ListOfShape> aCompSolidsObjects;
35
36   // Getting objects.
37   AttributeSelectionListPtr anObjectsSelList =
38     selectionList(FeaturesPlugin_Union::BASE_OBJECTS_ID());
39   for(int anObjectsIndex = 0; anObjectsIndex < anObjectsSelList->size(); anObjectsIndex++) {
40     AttributeSelectionPtr anObjectAttr = anObjectsSelList->value(anObjectsIndex);
41     std::shared_ptr<GeomAPI_Shape> anObject = anObjectAttr->value();
42     if(!anObject.get()) {
43       return;
44     }
45     ResultPtr aContext = anObjectAttr->context();
46     ResultCompSolidPtr aResCompSolidPtr = ModelAPI_Tools::compSolidOwner(aContext);
47     if(aResCompSolidPtr.get()) {
48       std::shared_ptr<GeomAPI_Shape> aContextShape = aResCompSolidPtr->shape();
49       std::map<std::shared_ptr<GeomAPI_Shape>, ListOfShape>::iterator
50         anIt = aCompSolidsObjects.begin();
51       for(; anIt != aCompSolidsObjects.end(); anIt++) {
52         if(anIt->first->isEqual(aContextShape)) {
53           aCompSolidsObjects[anIt->first].push_back(anObject);
54           break;
55         }
56       }
57       if(anIt == aCompSolidsObjects.end()) {
58         aCompSolidsObjects[aContextShape].push_back(anObject);
59       }
60     } else {
61       anObjects.push_back(anObject);
62     }
63   }
64
65   // Collecting solids from compsolids which will not be modified in
66   // boolean operation and will be added to result.
67   ListOfShape aShapesToAdd;
68   for(std::map<std::shared_ptr<GeomAPI_Shape>, ListOfShape>::iterator
69     anIt = aCompSolidsObjects.begin();
70     anIt != aCompSolidsObjects.end(); anIt++) {
71     std::shared_ptr<GeomAPI_Shape> aCompSolid = anIt->first;
72     ListOfShape& aUsedInOperationSolids = anIt->second;
73     anObjects.insert(anObjects.end(), aUsedInOperationSolids.begin(), aUsedInOperationSolids.end());
74
75     // Collect solids from compsolid which will not be modified in boolean operation.
76     for(GeomAPI_ShapeExplorer anExp(aCompSolid, GeomAPI_Shape::SOLID); anExp.more(); anExp.next()) {
77       std::shared_ptr<GeomAPI_Shape> aSolidInCompSolid = anExp.current();
78       ListOfShape::iterator anIt = aUsedInOperationSolids.begin();
79       for(; anIt != aUsedInOperationSolids.end(); anIt++) {
80         if(aSolidInCompSolid->isEqual(*anIt)) {
81           break;
82         }
83       }
84       if(anIt == aUsedInOperationSolids.end()) {
85         aShapesToAdd.push_back(aSolidInCompSolid);
86       }
87     }
88   }
89
90   if(anObjects.size() < 2) {
91     setError("Error: Not enough objects for operation. Should be at least 2.");
92     return;
93   }
94
95   // Fuse objects.
96   ListOfShape aTools;
97   aTools.splice(aTools.begin(), anObjects, anObjects.begin());
98   std::shared_ptr<GeomAlgoAPI_Boolean> aFuseAlgo(new GeomAlgoAPI_Boolean(anObjects,
99                                                             aTools,
100                                                             GeomAlgoAPI_Boolean::BOOL_FUSE));
101
102   // Checking that the algorithm worked properly.
103   GeomAlgoAPI_MakeShapeList aMakeShapeList;
104   GeomAPI_DataMapOfShapeShape aMapOfShapes;
105   if(!aFuseAlgo->isDone()) {
106     setError("Error: Boolean algorithm failed.");
107     return;
108   }
109   if(aFuseAlgo->shape()->isNull()) {
110     setError("Error: Resulting shape is Null.");
111     return;
112   }
113   if(!aFuseAlgo->isValid()) {
114     setError("Error: Resulting shape is not valid.");
115     return;
116   }
117
118   GeomShapePtr aShape = aFuseAlgo->shape();
119   aMakeShapeList.appendAlgo(aFuseAlgo);
120   aMapOfShapes.merge(aFuseAlgo->mapOfSubShapes());
121
122   // Store original shapes for naming.
123   anObjects.splice(anObjects.begin(), aTools);
124   anObjects.insert(anObjects.end(), aShapesToAdd.begin(), aShapesToAdd.end());
125
126   // Combine result with not used solids from compsolid.
127   if(aShapesToAdd.size() > 0) {
128     aShapesToAdd.push_back(aShape);
129     std::shared_ptr<GeomAlgoAPI_PaveFiller> aFillerAlgo(
130       new GeomAlgoAPI_PaveFiller(aShapesToAdd, true));
131     if(!aFillerAlgo->isDone()) {
132       setError("Error: PaveFiller algorithm failed.");
133       return;
134     }
135     if(aFillerAlgo->shape()->isNull()) {
136       setError("Error: Resulting shape is Null.");
137       return;
138     }
139     if(!aFillerAlgo->isValid()) {
140       setError("Error: Resulting shape is not valid.");
141       return;
142     }
143
144     aShape = aFillerAlgo->shape();
145     aMakeShapeList.appendAlgo(aFillerAlgo);
146     aMapOfShapes.merge(aFillerAlgo->mapOfSubShapes());
147   }
148
149   // Store result and naming.
150   const int aModifyTag = 1;
151   const int aDeletedTag = 2;
152   /// sub solids will be placed at labels 3, 4, etc. if result is compound of solids
153   const int aSubsolidsTag = 3;
154   const std::string aModName = "Modified";
155
156   std::shared_ptr<ModelAPI_ResultBody> aResultBody = document()->createBody(data());
157   aResultBody->storeModified(anObjects.front(), aShape, aSubsolidsTag);
158
159   for(ListOfShape::const_iterator anIter = anObjects.begin(); anIter != anObjects.end(); ++anIter) {
160     aResultBody->loadAndOrientModifiedShapes(&aMakeShapeList, *anIter, GeomAPI_Shape::FACE,
161                                              aModifyTag, aModName, aMapOfShapes);
162     aResultBody->loadDeletedShapes(&aMakeShapeList, *anIter, GeomAPI_Shape::FACE, aDeletedTag);
163   }
164
165   setResult(aResultBody);
166 }