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
18 // email : webmaster.salome@opencascade.com<mailto:webmaster.salome@opencascade.com>
21 #include "FeaturesPlugin_RemoveSubShapes.h"
23 #include <ModelAPI_AttributeSelectionList.h>
24 #include <ModelAPI_AttributeString.h>
25 #include <ModelAPI_ResultBody.h>
26 #include <ModelAPI_ResultConstruction.h>
27 #include <ModelAPI_Session.h>
28 #include <ModelAPI_Tools.h>
29 #include <ModelAPI_Validator.h>
31 #include <GeomAPI_ShapeIterator.h>
32 #include <GeomAPI_ShapeExplorer.h>
34 #include <GeomAlgoAPI_Copy.h>
35 #include <GeomAlgoAPI_ShapeBuilder.h>
36 #include <GeomAlgoAPI_ShapeTools.h>
37 #include <GeomAlgoAPI_MakeShapeCustom.h>
40 //==================================================================================================
41 FeaturesPlugin_RemoveSubShapes::FeaturesPlugin_RemoveSubShapes()
42 : myChangedInCode(false)
46 //==================================================================================================
47 void FeaturesPlugin_RemoveSubShapes::initAttributes()
49 data()->addAttribute(BASE_SHAPE_ID(), ModelAPI_AttributeSelection::typeId());
51 data()->addAttribute(CREATION_METHOD(), ModelAPI_AttributeString::typeId());
53 data()->addAttribute(SUBSHAPES_TO_KEEP_ID(), ModelAPI_AttributeSelectionList::typeId());
55 data()->addAttribute(SUBSHAPES_TO_REMOVE_ID(), ModelAPI_AttributeSelectionList::typeId());
58 void FeaturesPlugin_RemoveSubShapes::attributeChanged(const std::string& theID)
60 ModelAPI_Feature::attributeChanged(theID);
62 if (myChangedInCode) return;
64 AttributeSelectionPtr aShapeAttrSelection = selection(BASE_SHAPE_ID());
65 AttributeSelectionListPtr aSubShapesToKeepAttrList = selectionList(SUBSHAPES_TO_KEEP_ID());
66 AttributeSelectionListPtr aSubShapesToRemoveAttrList = selectionList(SUBSHAPES_TO_REMOVE_ID());
67 if (!aShapeAttrSelection.get()
68 || !aSubShapesToKeepAttrList.get()
69 || !aSubShapesToRemoveAttrList.get())
74 ResultPtr aContext = aShapeAttrSelection->context();
75 ResultBodyPtr aResultBody =
76 std::dynamic_pointer_cast<ModelAPI_ResultBody>(aContext);
77 if (!aResultBody.get()) {
78 aSubShapesToKeepAttrList->clear();
79 aSubShapesToRemoveAttrList->clear();
82 const bool isHasSubs = ModelAPI_Tools::hasSubResults(aResultBody);
84 GeomShapePtr aBaseShape = aShapeAttrSelection->value();
85 if(!aBaseShape.get()) {
86 aBaseShape = aContext->shape();
89 myChangedInCode = true;
91 if(theID == BASE_SHAPE_ID()) {
92 aSubShapesToKeepAttrList->clear();
93 aSubShapesToRemoveAttrList->clear();
95 if (!aBaseShape.get()) {
99 std::list<GeomShapePtr> aSubShapes = GeomAlgoAPI_ShapeTools::getLowLevelSubShapes(aBaseShape);
100 for (ListOfShape::const_iterator anIt = aSubShapes.cbegin(); anIt != aSubShapes.cend(); ++anIt)
102 GeomShapePtr aSubShape = *anIt;
104 aSubShapesToKeepAttrList->append(aContext, aSubShape);
106 std::list<ResultPtr> anAllSubs;
107 ModelAPI_Tools::allSubs(aResultBody, anAllSubs);
108 std::list<ResultPtr>::iterator aSubsIt = anAllSubs.begin();
109 for(; aSubsIt != anAllSubs.end(); aSubsIt++) {
110 ResultBodyPtr aSub = std::dynamic_pointer_cast<ModelAPI_ResultBody>(*aSubsIt);
111 if (aSub && aSub->shape().get() && aSub->shape()->isSubShape(aSubShape)) {
112 aSubShapesToKeepAttrList->append(aSub, aSubShape);
119 else if (theID == SUBSHAPES_TO_KEEP_ID())
121 aSubShapesToRemoveAttrList->clear();
123 if (!aBaseShape.get()) {
128 const int aSubsToKeepNb = aSubShapesToKeepAttrList->size();
129 std::list<GeomShapePtr> aSubShapes = GeomAlgoAPI_ShapeTools::getLowLevelSubShapes(aBaseShape);
130 for (ListOfShape::const_iterator anIt = aSubShapes.cbegin(); anIt != aSubShapes.cend(); ++anIt)
132 GeomShapePtr aSubShape = *anIt;
133 for(anIndex = 0; anIndex < aSubsToKeepNb; ++anIndex) {
134 AttributeSelectionPtr anAttrSelectionInList = aSubShapesToKeepAttrList->value(anIndex);
135 GeomShapePtr aSubShapeToKeep = anAttrSelectionInList->value();
136 if (aSubShapeToKeep.get() &&
137 (aSubShapeToKeep->isEqual(aSubShape) || aSubShapeToKeep->isSubShape(aSubShape))) {
142 if (anIndex == aSubsToKeepNb) {
144 aSubShapesToRemoveAttrList->append(aContext, aSubShape);
146 std::list<ResultPtr> anAllSubs;
147 ModelAPI_Tools::allSubs(aResultBody, anAllSubs);
148 std::list<ResultPtr>::iterator aSubsIt = anAllSubs.begin();
149 for(; aSubsIt != anAllSubs.end(); aSubsIt++) {
150 ResultBodyPtr aSub = std::dynamic_pointer_cast<ModelAPI_ResultBody>(*aSubsIt);
151 if (aSub && aSub->shape().get() && aSub->shape()->isSubShape(aSubShape)) {
152 aSubShapesToRemoveAttrList->append(aSub, aSubShape);
160 else if (theID == SUBSHAPES_TO_REMOVE_ID())
162 aSubShapesToKeepAttrList->clear();
164 if (!aBaseShape.get()) {
169 const int aSubsToRemoveNb = aSubShapesToRemoveAttrList->size();
170 std::list<GeomShapePtr> aSubShapes = GeomAlgoAPI_ShapeTools::getLowLevelSubShapes(aBaseShape);
171 for (ListOfShape::const_iterator anIt = aSubShapes.cbegin(); anIt != aSubShapes.cend(); ++anIt)
173 GeomShapePtr aSubShape = *anIt;
174 for(anIndex = 0; anIndex < aSubsToRemoveNb; ++anIndex) {
175 AttributeSelectionPtr anAttrSelectionInList = aSubShapesToRemoveAttrList->value(anIndex);
176 GeomShapePtr aSubShapeToRemove = anAttrSelectionInList->value();
177 if (aSubShapeToRemove.get() &&
178 (aSubShapeToRemove->isEqual(aSubShape) || aSubShapeToRemove->isSubShape(aSubShape))) {
183 if (anIndex == aSubsToRemoveNb) {
185 aSubShapesToKeepAttrList->append(aContext, aSubShape);
187 std::list<ResultPtr> anAllSubs;
188 ModelAPI_Tools::allSubs(aResultBody, anAllSubs);
189 std::list<ResultPtr>::iterator aSubsIt = anAllSubs.begin();
190 for(; aSubsIt != anAllSubs.end(); aSubsIt++) {
191 ResultBodyPtr aSub = std::dynamic_pointer_cast<ModelAPI_ResultBody>(*aSubsIt);
192 if (aSub && aSub->shape().get() && aSub->shape()->isSubShape(aSubShape)) {
193 aSubShapesToKeepAttrList->append(aSub, aSubShape);
202 myChangedInCode = false;
205 //==================================================================================================
206 void FeaturesPlugin_RemoveSubShapes::execute()
208 // Get base shape and sub-shapes list.
209 AttributeSelectionPtr aShapeAttrSelection = selection(BASE_SHAPE_ID());
210 AttributeSelectionListPtr aSubShapesAttrList = selectionList(SUBSHAPES_TO_KEEP_ID());
211 if(!aShapeAttrSelection.get() || !aSubShapesAttrList.get()) {
216 GeomShapePtr aBaseShape = aShapeAttrSelection->value();
218 GeomShapePtr aResultShape;
219 int aSubsNb = aSubShapesAttrList->size();
221 if(!aBaseShape.get()) {
224 aResultShape = aBaseShape->emptyCopied();
226 // Copy sub-shapes from list to new shape.
227 for(int anIndex = 0; anIndex < aSubsNb; ++anIndex) {
228 AttributeSelectionPtr anAttrSelectionInList = aSubShapesAttrList->value(anIndex);
229 GeomShapePtr aShapeToAdd = anAttrSelectionInList->value();
230 GeomAlgoAPI_ShapeBuilder::add(aResultShape, aShapeToAdd);
232 } else if(aSubsNb == 1) {
233 AttributeSelectionPtr anAttrSelectionInList = aSubShapesAttrList->value(0);
234 aResultShape = anAttrSelectionInList->value();
236 // deleted and copied must be jointed to one list which keeps all the history
237 GeomAlgoAPI_MakeShapeList aMakeShapeList;
239 // find all removed shapes
240 std::shared_ptr<GeomAlgoAPI_MakeShapeCustom> aDeletedSubs(new GeomAlgoAPI_MakeShapeCustom);
241 std::set<GeomAPI_Shape::ShapeType> aTypes; // types that where removed
242 aTypes.insert(GeomAPI_Shape::FACE);
244 std::list<GeomShapePtr> aSubShapes = GeomAlgoAPI_ShapeTools::getLowLevelSubShapes(aBaseShape);
245 for (ListOfShape::const_iterator anIt = aSubShapes.cbegin(); anIt != aSubShapes.cend(); ++anIt) {
246 GeomShapePtr aSubShape = *anIt;
247 if (!aSubShape.get() || aSubShape->isNull())
251 for(anIndex = 0; anIndex < aSubsNb; ++anIndex) {
252 AttributeSelectionPtr anAttrSelectionInList = aSubShapesAttrList->value(anIndex);
253 GeomShapePtr aLeftShape = anAttrSelectionInList->value();
254 if (aSubShape->isEqual(aLeftShape)) {
255 break; // found in a left-list
258 if (anIndex == aSubsNb) { // not found in left
259 aDeletedSubs->addDeleted(aSubShape);
260 aTypes.insert(aSubShape->shapeType());
261 if (aSubShape->shapeType() != GeomAPI_Shape::FACE) {
262 GeomAPI_ShapeExplorer aFaces(aSubShape, GeomAPI_Shape::FACE);
263 for(; aFaces.more(); aFaces.next())
264 aDeletedSubs->addDeleted(aFaces.current());
268 aMakeShapeList.appendAlgo(aDeletedSubs);
270 std::shared_ptr<GeomAlgoAPI_Copy> aCopy(new GeomAlgoAPI_Copy(aResultShape));
271 aResultShape = aCopy->shape();
272 aMakeShapeList.appendAlgo(aCopy);
274 if (aResultShape->shapeType() == GeomAPI_Shape::COMPOUND) {
275 aResultShape = GeomAlgoAPI_ShapeTools::groupSharedTopology(aResultShape);
276 if (aResultShape->shapeType() == GeomAPI_Shape::COMPOUND) {
277 // if the result has only one sub-shape, discard the compound
278 GeomAPI_ShapeIterator aSubIt(aResultShape);
279 GeomShapePtr aSub = aSubIt.current();
287 ResultBodyPtr aResultBody = document()->createBody(data());
288 aResultBody->storeModified(aBaseShape, aResultShape, 1);
289 std::set<GeomAPI_Shape::ShapeType>::iterator aTypeIter = aTypes.begin();
290 for(; aTypeIter != aTypes.end(); aTypeIter++)
291 aResultBody->loadDeletedShapes(&aMakeShapeList, aBaseShape, *aTypeIter, 1);
292 aResultBody->loadAndOrientModifiedShapes(&aMakeShapeList, aBaseShape, GeomAPI_Shape::FACE,
293 2, "Modified_Face", *aMakeShapeList.mapOfSubShapes().get(), true, false, true);
294 aResultBody->loadAndOrientModifiedShapes(&aMakeShapeList, aBaseShape, GeomAPI_Shape::EDGE,
295 3, "Modified_Edge", *aMakeShapeList.mapOfSubShapes().get(), false, false, true);
296 aResultBody->loadAndOrientModifiedShapes(&aMakeShapeList, aBaseShape, GeomAPI_Shape::VERTEX,
297 4, "Modified_Vertex", *aMakeShapeList.mapOfSubShapes().get());
298 setResult(aResultBody);