1 // Copyright (C) 2014-2017 CEA/DEN, EDF R&D
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.
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.
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
17 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com<mailto:webmaster.salome@opencascade.com>
20 #include "FeaturesPlugin_Partition.h"
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>
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>
39 #include <GeomAPI_Face.h>
40 #include <GeomAPI_ShapeExplorer.h>
41 #include <GeomAPI_ShapeIterator.h>
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);
51 //=================================================================================================
52 FeaturesPlugin_Partition::FeaturesPlugin_Partition()
56 //=================================================================================================
57 void FeaturesPlugin_Partition::initAttributes()
59 data()->addAttribute(BASE_OBJECTS_ID(), ModelAPI_AttributeSelectionList::typeId());
62 //=================================================================================================
63 void FeaturesPlugin_Partition::execute()
65 ListOfShape anObjects, aPlanes;
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();
73 // It could be a construction plane.
74 ResultPtr aContext = anObjectAttr->context();
75 aPlanes.push_back(anObjectAttr->context()->shape());
77 anObjects.push_back(anObject);
81 if(anObjects.empty()) {
82 static const std::string aFeatureError = "Error: No objects for partition.";
83 setError(aFeatureError);
87 std::list<std::shared_ptr<GeomAPI_Pnt> > aBoundingPoints =
88 GeomAlgoAPI_ShapeTools::getBoundingBox(anObjects, 1.0);
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);
102 // Create single result.
103 std::shared_ptr<GeomAlgoAPI_Partition> aPartitionAlgo(
104 new GeomAlgoAPI_Partition(anObjects, aTools));
106 // Checking that the algorithm worked properly.
107 if (!aPartitionAlgo->isDone()) {
108 static const std::string aFeatureError = "Error: Partition algorithm failed.";
109 setError(aFeatureError);
112 if (aPartitionAlgo->shape()->isNull()) {
113 static const std::string aShapeError = "Error: Resulting shape is Null.";
114 setError(aShapeError);
117 if (!aPartitionAlgo->isValid()) {
118 std::string aFeatureError = "Error: Resulting shape is not valid.";
119 setError(aFeatureError);
122 aMakeShapeList->appendAlgo(aPartitionAlgo);
123 GeomShapePtr aResultShape = aPartitionAlgo->shape();
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);
132 storeResult(anObjects, aPlanes, aResultShape, aMakeShapeList, aResultIndex);
136 // Remove the rest results if there were produced in the previous pass.
137 removeResults(aResultIndex);
140 //=================================================================================================
141 void FeaturesPlugin_Partition::storeResult(
142 ListOfShape& theObjects, ListOfShape& thePlanes,
143 const GeomShapePtr theResultShape,
144 const std::shared_ptr<GeomAlgoAPI_MakeShape> theMakeShape,
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);
157 if (!aCandidate.get())
158 aCandidate = findBase(anObjectShape, theResultShape, GeomAPI_Shape::FACE, theMakeShape);
160 if(aCandidate.get()) {
161 if (!aBaseShape.get() || aBaseShape->shapeType() > aCandidate->shapeType()) {
162 aBaseShape = aCandidate;
167 // Create result body.
168 ResultBodyPtr aResultBody = document()->createBody(data(), theIndex);
170 // Store modified shape.
171 if(!aBaseShape.get() || aBaseShape->isEqual(theResultShape)) {
172 aResultBody->store(theResultShape);
173 setResult(aResultBody, theIndex);
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";
183 aResultBody->storeModified(aBaseShape, theResultShape, aSubTag);
185 std::shared_ptr<GeomAPI_DataMapOfShapeShape> aMapOfSubShapes = theMakeShape->mapOfSubShapes();
186 theObjects.insert(theObjects.end(), thePlanes.begin(), thePlanes.end());
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);
195 aResultBody->loadAndOrientModifiedShapes(theMakeShape.get(), aShape, GeomAPI_Shape::FACE,
196 aModTag, aModFaceName, *aMapOfSubShapes.get(), true);
198 aResultBody->loadDeletedShapes(theMakeShape.get(), aShape, GeomAPI_Shape::EDGE, aDelTag);
199 aResultBody->loadDeletedShapes(theMakeShape.get(), aShape, GeomAPI_Shape::FACE, aDelTag);
202 setResult(aResultBody, theIndex);
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)
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);
226 if(theResultShape->isSubShape(aModShape)) {
227 aBaseShape = theObjectShape;
231 if(aBaseShape.get()) {