Salome HOME
Merge remote branch 'remotes/origin/vsr/libxml2_mdv' into Dev_2.1.0
[modules/shaper.git] / src / FeaturesPlugin / FeaturesPlugin_Partition.cpp
1 // Copyright (C) 2014-20xx CEA/DEN, EDF R&D -->
2
3 // File:        FeaturesPlugin_Partition.cpp
4 // Created:     31 Jul 2015
5 // Author:      Natalia ERMOLAEVA
6
7 #include "FeaturesPlugin_Partition.h"
8
9 #include <ModelAPI_Data.h>
10 #include <ModelAPI_Document.h>
11 #include <ModelAPI_AttributeBoolean.h>
12 #include <ModelAPI_AttributeReference.h>
13 #include <ModelAPI_AttributeInteger.h>
14 #include <ModelAPI_BodyBuilder.h>
15 #include <ModelAPI_ResultBody.h>
16 #include <ModelAPI_AttributeSelectionList.h>
17 #include <ModelAPI_Session.h>
18 #include <ModelAPI_Validator.h>
19
20 #include <GeomAlgoAPI_Partition.h>
21 #include <GeomAlgoAPI_MakeShapeCustom.h>
22 #include <GeomAlgoAPI_MakeShapeList.h>
23 #include <GeomAlgoAPI_ShapeTools.h>
24
25 #include <sstream>
26
27 //=================================================================================================
28 FeaturesPlugin_Partition::FeaturesPlugin_Partition()
29 {
30 }
31
32 //=================================================================================================
33 void FeaturesPlugin_Partition::initAttributes()
34 {
35   AttributeSelectionListPtr aSelection =
36     std::dynamic_pointer_cast<ModelAPI_AttributeSelectionList>(data()->addAttribute(
37     FeaturesPlugin_Partition::OBJECT_LIST_ID(), ModelAPI_AttributeSelectionList::typeId()));
38   aSelection->setSelectionType("SOLID");
39
40   aSelection =
41     std::dynamic_pointer_cast<ModelAPI_AttributeSelectionList>(data()->addAttribute(
42     FeaturesPlugin_Partition::TOOL_LIST_ID(), ModelAPI_AttributeSelectionList::typeId()));
43   aSelection->setSelectionType("SOLID");
44
45   ModelAPI_Session::get()->validators()->registerNotObligatory(getKind(), TOOL_LIST_ID());
46
47   data()->addAttribute(COMBINE_ID(), ModelAPI_AttributeBoolean::typeId());
48 }
49
50 //=================================================================================================
51 std::shared_ptr<GeomAPI_Shape> FeaturesPlugin_Partition::getShape(const std::string& theAttrName)
52 {
53   std::shared_ptr<ModelAPI_AttributeReference> aObjRef =
54       std::dynamic_pointer_cast<ModelAPI_AttributeReference>(data()->attribute(theAttrName));
55   if (aObjRef) {
56     std::shared_ptr<ModelAPI_ResultBody> aConstr =
57         std::dynamic_pointer_cast<ModelAPI_ResultBody>(aObjRef->value());
58     if (aConstr)
59       return aConstr->shape();
60   }
61   return std::shared_ptr<GeomAPI_Shape>();
62 }
63
64 //=================================================================================================
65 void FeaturesPlugin_Partition::execute()
66 {
67   ListOfShape anObjects, aTools, aToolsForNaming;
68
69   // Getting objects.
70   AttributeSelectionListPtr anObjectsSelList = selectionList(FeaturesPlugin_Partition::OBJECT_LIST_ID());
71   for (int anObjectsIndex = 0; anObjectsIndex < anObjectsSelList->size(); anObjectsIndex++) {
72     std::shared_ptr<ModelAPI_AttributeSelection> anObjectAttr = anObjectsSelList->value(anObjectsIndex);
73     std::shared_ptr<GeomAPI_Shape> anObject = anObjectAttr->value();
74     if (!anObject.get()) {
75       return;
76     }
77     anObjects.push_back(anObject);
78   }
79
80   GeomAlgoAPI_MakeShapeList aMakeShapeList;
81   std::list<std::shared_ptr<GeomAPI_Pnt> > aBoundingPoints = GeomAlgoAPI_ShapeTools::getBoundingBox(anObjects, 1.0);
82
83   // Getting tools.
84   AttributeSelectionListPtr aToolsSelList = selectionList(FeaturesPlugin_Partition::TOOL_LIST_ID());
85   for (int aToolsIndex = 0; aToolsIndex < aToolsSelList->size(); aToolsIndex++) {
86     std::shared_ptr<ModelAPI_AttributeSelection> aToolAttr = aToolsSelList->value(aToolsIndex);
87     std::shared_ptr<GeomAPI_Shape> aTool = aToolAttr->value();
88     if(!aTool.get()) {
89       // it could be a construction plane
90       ResultPtr aContext = aToolAttr->context();
91       if(aContext.get()) {
92         aTool = GeomAlgoAPI_ShapeTools::fitPlaneToBox(aContext->shape(), aBoundingPoints);
93         std::shared_ptr<GeomAlgoAPI_MakeShapeCustom> aMkShCustom(new GeomAlgoAPI_MakeShapeCustom);
94         aMkShCustom->addModified(aContext->shape(), aTool);
95         aMakeShapeList.append(aMkShCustom);
96         aTools.push_back(aTool);
97         aToolsForNaming.push_back(aContext->shape());
98       }
99     } else {
100       aTools.push_back(aTool);
101       aToolsForNaming.push_back(aTool);
102     }
103   }
104
105   // Getting combine flag.
106   bool isCombine = boolean(COMBINE_ID())->value();
107
108   if(anObjects.empty()/* || aTools.empty()*/) {
109     std::string aFeatureError = "Not enough objects for partition operation";
110     setError(aFeatureError);
111     return;
112   }
113
114   int aResultIndex = 0;
115
116   if(isCombine) {
117     // Create single result.
118     GeomAlgoAPI_Partition aPartitionAlgo(anObjects, aTools);
119
120     // Checking that the algorithm worked properly.
121     if (!aPartitionAlgo.isDone()) {
122       static const std::string aFeatureError = "Partition algorithm failed";
123       setError(aFeatureError);
124       return;
125     }
126     if (aPartitionAlgo.shape()->isNull()) {
127       static const std::string aShapeError = "Resulting shape is Null";
128       setError(aShapeError);
129       return;
130     }
131     if (!aPartitionAlgo.isValid()) {
132       std::string aFeatureError = "Warning: resulting shape is not valid";
133       setError(aFeatureError);
134       return;
135     }
136
137     if (GeomAlgoAPI_ShapeTools::volume(aPartitionAlgo.shape()) > 1.e-7) {
138       std::shared_ptr<ModelAPI_ResultBody> aResultBody = document()->createBody(data(), aResultIndex);
139       aMakeShapeList.append(aPartitionAlgo.makeShape());
140       GeomAPI_DataMapOfShapeShape aMapOfShapes = *aPartitionAlgo.mapOfShapes().get();
141       loadNamingDS(aResultBody, anObjects.front(), aToolsForNaming, aPartitionAlgo.shape(), aMakeShapeList, aMapOfShapes);
142       setResult(aResultBody, aResultIndex);
143       aResultIndex++;
144     }
145   } else {
146     // Create result for each object.
147     for (ListOfShape::iterator anObjectsIt = anObjects.begin(); anObjectsIt != anObjects.end(); anObjectsIt++) {
148       std::shared_ptr<GeomAPI_Shape> anObject = *anObjectsIt;
149       ListOfShape aListWithObject; aListWithObject.push_back(anObject);
150       GeomAlgoAPI_Partition aPartitionAlgo(aListWithObject, aTools);
151
152       // Checking that the algorithm worked properly.
153       if (!aPartitionAlgo.isDone()) {
154         static const std::string aFeatureError = "Partition algorithm failed";
155         setError(aFeatureError);
156         return;
157       }
158       if (aPartitionAlgo.shape()->isNull()) {
159         static const std::string aShapeError = "Resulting shape is Null";
160         setError(aShapeError);
161         return;
162       }
163       if (!aPartitionAlgo.isValid()) {
164         std::string aFeatureError = "Warning: resulting shape is not valid";
165         setError(aFeatureError);
166         return;
167       }
168
169       if (GeomAlgoAPI_ShapeTools::volume(aPartitionAlgo.shape()) > 1.e-7) {
170         std::shared_ptr<ModelAPI_ResultBody> aResultBody = document()->createBody(data(), aResultIndex);
171         aMakeShapeList.append(aPartitionAlgo.makeShape());
172         GeomAPI_DataMapOfShapeShape aMapOfShapes = *aPartitionAlgo.mapOfShapes().get();
173         loadNamingDS(aResultBody, anObject, aToolsForNaming, aPartitionAlgo.shape(), aMakeShapeList, aMapOfShapes);
174         setResult(aResultBody, aResultIndex);
175         aResultIndex++;
176       }
177     }
178   }
179
180   // remove the rest results if there were produced in the previous pass
181   removeResults(aResultIndex);
182 }
183
184 //=================================================================================================
185 void FeaturesPlugin_Partition::loadNamingDS(std::shared_ptr<ModelAPI_ResultBody> theResultBody,
186                                             const std::shared_ptr<GeomAPI_Shape> theBaseShape,
187                                             const ListOfShape& theTools,
188                                             const std::shared_ptr<GeomAPI_Shape> theResultShape,
189                                             GeomAlgoAPI_MakeShape& theMakeShape,
190                                             GeomAPI_DataMapOfShapeShape& theMapOfShapes)
191 {
192   //load result
193   if(theBaseShape->isEqual(theResultShape)) {
194     theResultBody->store(theResultShape);
195   } else {
196     const int aDeletedTag = 1;
197     const int aSubsolidsTag = 2; /// sub solids will be placed at labels 3, 4, etc. if result is compound of solids
198     const int aModifyTag = 100000;
199     int aModifyToolsTag = 200000;
200     std::ostringstream aStream;
201
202     theResultBody->storeModified(theBaseShape, theResultShape, aSubsolidsTag);
203
204     std::string aModName = "Modified";
205     theResultBody->loadAndOrientModifiedShapes(&theMakeShape, theBaseShape, GeomAPI_Shape::FACE,
206                                                aModifyTag, aModName, theMapOfShapes, true);
207     theResultBody->loadDeletedShapes(&theMakeShape, theBaseShape, GeomAPI_Shape::FACE, aDeletedTag);
208
209     int anIndex = 1;
210     for(ListOfShape::const_iterator anIter = theTools.begin(); anIter != theTools.end(); anIter++) {
211       aStream.str(std::string());
212       aStream.clear();
213       aStream << aModName << "_" << anIndex++;
214       theResultBody->loadAndOrientModifiedShapes(&theMakeShape, *anIter, GeomAPI_Shape::FACE,
215                                                  aModifyToolsTag, aStream.str(), theMapOfShapes, true);
216       theResultBody->loadDeletedShapes(&theMakeShape, *anIter, GeomAPI_Shape::FACE, aDeletedTag);
217       aModifyToolsTag += 10000;
218     }
219   }
220 }