Salome HOME
Add copyright header according to request of CEA from 06.06.2017
[modules/shaper.git] / src / FeaturesPlugin / FeaturesPlugin_Partition.cpp
1 // Copyright (C) 2014-2017  CEA/DEN, EDF R&D
2 //
3 // This library is free software; you can redistribute it and/or
4 // modify it under the terms of the GNU Lesser General Public
5 // License as published by the Free Software Foundation; either
6 // version 2.1 of the License, or (at your option) any later version.
7 //
8 // This library is distributed in the hope that it will be useful,
9 // but WITHOUT ANY WARRANTY; without even the implied warranty of
10 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
11 // Lesser General Public License for more details.
12 //
13 // You should have received a copy of the GNU Lesser General Public
14 // License along with this library; if not, write to the Free Software
15 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
16 //
17 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com<mailto:webmaster.salome@opencascade.com>
18 //
19
20 #include "FeaturesPlugin_Partition.h"
21
22 #include <ModelAPI_Data.h>
23 #include <ModelAPI_Document.h>
24 #include <ModelAPI_AttributeBoolean.h>
25 #include <ModelAPI_AttributeReference.h>
26 #include <ModelAPI_AttributeInteger.h>
27 #include <ModelAPI_BodyBuilder.h>
28 #include <ModelAPI_ResultBody.h>
29 #include <ModelAPI_AttributeSelectionList.h>
30 #include <ModelAPI_Session.h>
31 #include <ModelAPI_Validator.h>
32
33 #include <GeomAlgoAPI_CompoundBuilder.h>
34 #include <GeomAlgoAPI_Partition.h>
35 #include <GeomAlgoAPI_MakeShapeCustom.h>
36 #include <GeomAlgoAPI_MakeShapeList.h>
37 #include <GeomAlgoAPI_ShapeTools.h>
38
39 #include <GeomAPI_Face.h>
40 #include <GeomAPI_ShapeExplorer.h>
41 #include <GeomAPI_ShapeIterator.h>
42
43 #include <iostream>
44 #include <sstream>
45
46 static GeomShapePtr findBase(const GeomShapePtr theObjectShape,
47                              const GeomShapePtr theResultShape,
48                              const GeomAPI_Shape::ShapeType theShapeType,
49                              const std::shared_ptr<GeomAlgoAPI_MakeShape> theMakeShape);
50
51 //=================================================================================================
52 FeaturesPlugin_Partition::FeaturesPlugin_Partition()
53 {
54 }
55
56 //=================================================================================================
57 void FeaturesPlugin_Partition::initAttributes()
58 {
59   data()->addAttribute(BASE_OBJECTS_ID(), ModelAPI_AttributeSelectionList::typeId());
60 }
61
62 //=================================================================================================
63 void FeaturesPlugin_Partition::execute()
64 {
65   ListOfShape anObjects, aPlanes;
66
67   // Getting objects.
68   AttributeSelectionListPtr anObjectsSelList = selectionList(BASE_OBJECTS_ID());
69   for(int anIndex = 0; anIndex < anObjectsSelList->size(); ++anIndex) {
70     AttributeSelectionPtr anObjectAttr = anObjectsSelList->value(anIndex);
71     GeomShapePtr anObject = anObjectAttr->value();
72     if(!anObject.get()) {
73       // It could be a construction plane.
74       ResultPtr aContext = anObjectAttr->context();
75       aPlanes.push_back(anObjectAttr->context()->shape());
76     } else {
77       anObjects.push_back(anObject);
78     }
79   }
80
81   if(anObjects.empty()) {
82     static const std::string aFeatureError = "Error: No objects for partition.";
83     setError(aFeatureError);
84     return;
85   }
86
87   std::list<std::shared_ptr<GeomAPI_Pnt> > aBoundingPoints =
88     GeomAlgoAPI_ShapeTools::getBoundingBox(anObjects, 1.0);
89
90   // Resize planes.
91   ListOfShape aTools;
92   std::shared_ptr<GeomAlgoAPI_MakeShapeList> aMakeShapeList(new GeomAlgoAPI_MakeShapeList());
93   for(ListOfShape::const_iterator anIt = aPlanes.cbegin(); anIt != aPlanes.cend(); ++anIt) {
94     GeomShapePtr aPlane = *anIt;
95     GeomShapePtr aTool = GeomAlgoAPI_ShapeTools::fitPlaneToBox(aPlane, aBoundingPoints);
96     std::shared_ptr<GeomAlgoAPI_MakeShapeCustom> aMkShCustom(new GeomAlgoAPI_MakeShapeCustom);
97     aMkShCustom->addModified(aPlane, aTool);
98     aMakeShapeList->appendAlgo(aMkShCustom);
99     aTools.push_back(aTool);
100   }
101
102   // Create single result.
103   std::shared_ptr<GeomAlgoAPI_Partition> aPartitionAlgo(
104     new GeomAlgoAPI_Partition(anObjects, aTools));
105
106   // Checking that the algorithm worked properly.
107   if (!aPartitionAlgo->isDone()) {
108     static const std::string aFeatureError = "Error: Partition algorithm failed.";
109     setError(aFeatureError);
110     return;
111   }
112   if (aPartitionAlgo->shape()->isNull()) {
113     static const std::string aShapeError = "Error: Resulting shape is Null.";
114     setError(aShapeError);
115     return;
116   }
117   if (!aPartitionAlgo->isValid()) {
118     std::string aFeatureError = "Error: Resulting shape is not valid.";
119     setError(aFeatureError);
120     return;
121   }
122   aMakeShapeList->appendAlgo(aPartitionAlgo);
123   GeomShapePtr aResultShape = aPartitionAlgo->shape();
124
125   int aResultIndex = 0;
126   if(aResultShape->shapeType() == GeomAPI_Shape::COMPOUND) {
127     for(GeomAPI_ShapeIterator anIt(aResultShape); anIt.more(); anIt.next()) {
128       storeResult(anObjects, aPlanes, anIt.current(), aMakeShapeList, aResultIndex);
129       ++aResultIndex;
130     }
131   } else {
132     storeResult(anObjects, aPlanes, aResultShape, aMakeShapeList, aResultIndex);
133     ++aResultIndex;
134   }
135
136   // Remove the rest results if there were produced in the previous pass.
137   removeResults(aResultIndex);
138 }
139
140 //=================================================================================================
141 void FeaturesPlugin_Partition::storeResult(
142   ListOfShape& theObjects, ListOfShape& thePlanes,
143   const GeomShapePtr theResultShape,
144   const std::shared_ptr<GeomAlgoAPI_MakeShape> theMakeShape,
145   const int theIndex)
146 {
147   // Find base. The most complicated is the real modified object (#1799 if box is partitioned by
148   // two planes the box is the base, not planes, independently on the order in the list).
149   GeomShapePtr aBaseShape;
150   for(ListOfShape::const_iterator anIt = theObjects.cbegin(); anIt != theObjects.cend(); ++anIt) {
151     GeomShapePtr anObjectShape = *anIt;
152     GeomShapePtr aCandidate =
153       findBase(anObjectShape, theResultShape, GeomAPI_Shape::VERTEX, theMakeShape);
154     if(!aCandidate.get()) {
155       aCandidate = findBase(anObjectShape, theResultShape, GeomAPI_Shape::EDGE, theMakeShape);
156     }
157     if (!aCandidate.get())
158       aCandidate = findBase(anObjectShape, theResultShape, GeomAPI_Shape::FACE, theMakeShape);
159
160     if(aCandidate.get()) {
161       if (!aBaseShape.get() || aBaseShape->shapeType() > aCandidate->shapeType()) {
162         aBaseShape = aCandidate;
163       }
164     }
165   }
166
167   // Create result body.
168   ResultBodyPtr aResultBody = document()->createBody(data(), theIndex);
169
170   // Store modified shape.
171   if(!aBaseShape.get() || aBaseShape->isEqual(theResultShape)) {
172     aResultBody->store(theResultShape);
173     setResult(aResultBody, theIndex);
174     return;
175   }
176
177   const int aDelTag = 1;
178   /// sub solids will be placed at labels 3, 4, etc. if result is compound of solids
179   const int aSubTag = 2;
180   int aModTag = aSubTag + 10000;
181   const std::string aModName = "Modified";
182
183   aResultBody->storeModified(aBaseShape, theResultShape, aSubTag);
184
185   std::shared_ptr<GeomAPI_DataMapOfShapeShape> aMapOfSubShapes = theMakeShape->mapOfSubShapes();
186   theObjects.insert(theObjects.end(), thePlanes.begin(), thePlanes.end());
187   int anIndex = 1;
188   for(ListOfShape::const_iterator anIt = theObjects.cbegin(); anIt != theObjects.cend(); ++anIt) {
189     GeomShapePtr aShape = *anIt;
190     std::string aModEdgeName = aModName + "_Edge_" + std::to_string((long long)anIndex);
191     std::string aModFaceName = aModName + "_Face_" + std::to_string((long long)anIndex++);
192     aResultBody->loadAndOrientModifiedShapes(theMakeShape.get(), aShape, GeomAPI_Shape::EDGE,
193                                              aModTag, aModEdgeName, *aMapOfSubShapes.get(), true);
194     aModTag += 10000;
195     aResultBody->loadAndOrientModifiedShapes(theMakeShape.get(), aShape, GeomAPI_Shape::FACE,
196                                              aModTag, aModFaceName, *aMapOfSubShapes.get(), true);
197     aModTag += 10000;
198     aResultBody->loadDeletedShapes(theMakeShape.get(), aShape, GeomAPI_Shape::EDGE, aDelTag);
199     aResultBody->loadDeletedShapes(theMakeShape.get(), aShape, GeomAPI_Shape::FACE, aDelTag);
200   }
201
202   setResult(aResultBody, theIndex);
203 }
204
205
206 //=================================================================================================
207 GeomShapePtr findBase(const GeomShapePtr theObjectShape,
208                       const GeomShapePtr theResultShape,
209                       const GeomAPI_Shape::ShapeType theShapeType,
210                       const std::shared_ptr<GeomAlgoAPI_MakeShape> theMakeShape)
211 {
212   GeomShapePtr aBaseShape;
213   std::shared_ptr<GeomAPI_DataMapOfShapeShape> aMapOfSubShapes = theMakeShape->mapOfSubShapes();
214   for(GeomAPI_ShapeExplorer anObjectSubShapesExp(theObjectShape, theShapeType);
215       anObjectSubShapesExp.more();
216       anObjectSubShapesExp.next()) {
217     GeomShapePtr anObjectSubShape = anObjectSubShapesExp.current();
218     ListOfShape aModifiedShapes;
219     theMakeShape->modified(anObjectSubShape, aModifiedShapes);
220     for(ListOfShape::const_iterator
221         aModIt = aModifiedShapes.cbegin(); aModIt != aModifiedShapes.cend(); ++aModIt) {
222       GeomShapePtr aModShape = *aModIt;
223       if(aMapOfSubShapes->isBound(aModShape)) {
224         aModShape = aMapOfSubShapes->find(aModShape);
225       }
226       if(theResultShape->isSubShape(aModShape)) {
227         aBaseShape = theObjectShape;
228         break;
229       }
230     }
231     if(aBaseShape.get()) {
232       break;
233     }
234   }
235
236   return aBaseShape;
237 }