From 87b74a6fd4660ebfa71a40f0be84e44535f84798 Mon Sep 17 00:00:00 2001 From: dbv Date: Fri, 1 Apr 2016 15:46:56 +0300 Subject: [PATCH] Issue #1343: Architecture changes. Composite features now derived from extrusion, revolution features. --- src/FeaturesPlugin/CMakeLists.txt | 8 - .../FeaturesPlugin_CompositeBoolean.cpp | 573 +++++++----------- .../FeaturesPlugin_CompositeBoolean.h | 133 ++-- .../FeaturesPlugin_CompositeSketch.cpp | 369 +++++++---- .../FeaturesPlugin_CompositeSketch.h | 92 +-- .../FeaturesPlugin_Extrusion.cpp | 206 ++----- src/FeaturesPlugin/FeaturesPlugin_Extrusion.h | 94 ++- .../FeaturesPlugin_ExtrusionBoolean.cpp | 88 +-- .../FeaturesPlugin_ExtrusionBoolean.h | 82 +-- .../FeaturesPlugin_ExtrusionCut.cpp | 4 +- .../FeaturesPlugin_ExtrusionCut.h | 21 +- .../FeaturesPlugin_ExtrusionFuse.cpp | 4 +- .../FeaturesPlugin_ExtrusionFuse.h | 21 +- .../FeaturesPlugin_ExtrusionSketch.cpp | 87 --- .../FeaturesPlugin_ExtrusionSketch.h | 96 --- src/FeaturesPlugin/FeaturesPlugin_Plugin.cpp | 8 +- .../FeaturesPlugin_Revolution.cpp | 226 +++---- .../FeaturesPlugin_Revolution.h | 67 +- .../FeaturesPlugin_RevolutionBoolean.cpp | 105 +--- .../FeaturesPlugin_RevolutionBoolean.h | 86 +-- .../FeaturesPlugin_RevolutionCut.cpp | 4 +- .../FeaturesPlugin_RevolutionCut.h | 19 +- .../FeaturesPlugin_RevolutionFuse.cpp | 4 +- .../FeaturesPlugin_RevolutionFuse.h | 19 +- .../FeaturesPlugin_RevolutionSketch.cpp | 104 ---- .../FeaturesPlugin_RevolutionSketch.h | 103 ---- .../FeaturesPlugin_Validators.cpp | 105 +++- .../FeaturesPlugin_Validators.h | 21 + .../Test/TestExtrusionSketch.py | 126 ---- .../Test/TestRevolutionSketch.py | 153 ----- src/FeaturesPlugin/extrusion_widget.xml | 85 +-- src/FeaturesPlugin/extrusioncut_widget.xml | 10 +- src/FeaturesPlugin/extrusionfuse_widget.xml | 10 +- src/FeaturesPlugin/extrusionsketch_widget.xml | 68 --- src/FeaturesPlugin/pipe_widget.xml | 51 +- src/FeaturesPlugin/revolution_widget.xml | 101 ++- src/FeaturesPlugin/revolutioncut_widget.xml | 26 +- src/FeaturesPlugin/revolutionfuse_widget.xml | 26 +- .../revolutionsketch_widget.xml | 84 --- src/GeomAlgoAPI/GeomAlgoAPI_MakeShape.h | 4 +- src/GeomAlgoAPI/GeomAlgoAPI_MakeShapeList.cpp | 15 + .../GeomValidators_ShapeType.cpp | 6 +- src/PartSet/PartSet_WidgetSketchCreator.cpp | 2 +- 43 files changed, 1165 insertions(+), 2351 deletions(-) delete mode 100644 src/FeaturesPlugin/FeaturesPlugin_ExtrusionSketch.cpp delete mode 100644 src/FeaturesPlugin/FeaturesPlugin_ExtrusionSketch.h delete mode 100644 src/FeaturesPlugin/FeaturesPlugin_RevolutionSketch.cpp delete mode 100644 src/FeaturesPlugin/FeaturesPlugin_RevolutionSketch.h delete mode 100644 src/FeaturesPlugin/Test/TestExtrusionSketch.py delete mode 100644 src/FeaturesPlugin/Test/TestRevolutionSketch.py delete mode 100644 src/FeaturesPlugin/extrusionsketch_widget.xml delete mode 100644 src/FeaturesPlugin/revolutionsketch_widget.xml diff --git a/src/FeaturesPlugin/CMakeLists.txt b/src/FeaturesPlugin/CMakeLists.txt index 86530f164..0ae589cc7 100644 --- a/src/FeaturesPlugin/CMakeLists.txt +++ b/src/FeaturesPlugin/CMakeLists.txt @@ -19,10 +19,8 @@ SET(PROJECT_HEADERS FeaturesPlugin_CompositeBoolean.h FeaturesPlugin_CompositeSketch.h FeaturesPlugin_ExtrusionBoolean.h - FeaturesPlugin_ExtrusionSketch.h FeaturesPlugin_ExtrusionCut.h FeaturesPlugin_ExtrusionFuse.h - FeaturesPlugin_RevolutionSketch.h FeaturesPlugin_RevolutionBoolean.h FeaturesPlugin_RevolutionCut.h FeaturesPlugin_RevolutionFuse.h @@ -45,11 +43,9 @@ SET(PROJECT_SOURCES FeaturesPlugin_Placement.cpp FeaturesPlugin_CompositeBoolean.cpp FeaturesPlugin_CompositeSketch.cpp - FeaturesPlugin_ExtrusionSketch.cpp FeaturesPlugin_ExtrusionBoolean.cpp FeaturesPlugin_ExtrusionCut.cpp FeaturesPlugin_ExtrusionFuse.cpp - FeaturesPlugin_RevolutionSketch.cpp FeaturesPlugin_RevolutionBoolean.cpp FeaturesPlugin_RevolutionCut.cpp FeaturesPlugin_RevolutionFuse.cpp @@ -61,11 +57,9 @@ SET(PROJECT_SOURCES SET(XML_RESOURCES plugin-Features.xml extrusion_widget.xml - extrusionsketch_widget.xml extrusioncut_widget.xml extrusionfuse_widget.xml revolution_widget.xml - revolutionsketch_widget.xml revolutioncut_widget.xml revolutionfuse_widget.xml rotation_widget.xml @@ -102,11 +96,9 @@ INSTALL(TARGETS FeaturesPlugin DESTINATION ${SHAPER_INSTALL_PLUGIN_FILES}) INSTALL(FILES ${XML_RESOURCES} DESTINATION ${SHAPER_INSTALL_XML_RESOURCES}) ADD_UNIT_TESTS(TestExtrusion.py - TestExtrusionSketch.py TestExtrusionCut.py TestExtrusionFuse.py TestRevolution.py - TestRevolutionSketch.py TestRevolutionCut.py TestRevolutionFuse.py TestCompositeFeaturesOnCompSolids.py diff --git a/src/FeaturesPlugin/FeaturesPlugin_CompositeBoolean.cpp b/src/FeaturesPlugin/FeaturesPlugin_CompositeBoolean.cpp index 65a6c6a8d..5c86e7eb7 100644 --- a/src/FeaturesPlugin/FeaturesPlugin_CompositeBoolean.cpp +++ b/src/FeaturesPlugin/FeaturesPlugin_CompositeBoolean.cpp @@ -7,186 +7,99 @@ #include "FeaturesPlugin_CompositeBoolean.h" #include -#include -#include -#include -#include #include -#include -#include +#include #include -#include #include -#include -#include #include + #include #include -#include //================================================================================================= -void FeaturesPlugin_CompositeBoolean::initAttributes() +void FeaturesPlugin_CompositeBoolean::initBooleanAttributes() { - AttributeSelectionListPtr aSelection = - std::dynamic_pointer_cast(data()->addAttribute( - LIST_ID(), ModelAPI_AttributeSelectionList::typeId())); - - data()->addAttribute(SKETCH_OBJECT_ID(), ModelAPI_AttributeReference::typeId()); - ModelAPI_Session::get()->validators()->registerNotObligatory(getKind(), - SKETCH_OBJECT_ID()); - - // Boolean works with solids always. - data()->addAttribute(BOOLEAN_OBJECTS_ID(), ModelAPI_AttributeSelectionList::typeId()); - aSelection = data()->selectionList(BOOLEAN_OBJECTS_ID()); - aSelection->setSelectionType("SOLID"); - - initMakeSolidsAttributes(); - - data()->addAttribute(SKETCH_SELECTION_ID(), ModelAPI_AttributeSelection::typeId()); - ModelAPI_Session::get()->validators()->registerNotObligatory(getKind(), SKETCH_SELECTION_ID()); + myFeature->data()->addAttribute(OBJECTS_ID(), ModelAPI_AttributeSelectionList::typeId()); } //================================================================================================= -std::shared_ptr FeaturesPlugin_CompositeBoolean::addFeature(std::string theID) +void FeaturesPlugin_CompositeBoolean::execute() { - std::shared_ptr aNew = document()->addFeature(theID, false); - if (aNew) { - data()->reference(SKETCH_OBJECT_ID())->setValue(aNew); + // Make generation. + ListOfShape aGenBaseShapes; + ListOfMakeShape aGenMakeShapes; + if(!makeGeneration(aGenBaseShapes, aGenMakeShapes)) { + return; } - // set as current also after it becomes sub to set correctly enabled for other sketch subs - document()->setCurrentFeature(aNew, false); - return aNew; -} -//================================================================================================= -int FeaturesPlugin_CompositeBoolean::numberOfSubs(bool forTree) const -{ - ObjectPtr aObj = data()->reference(SKETCH_OBJECT_ID())->value(); - return aObj.get()? 1 : 0; -} + // Getting tools. + ListOfShape aTools; + for(ListOfMakeShape::const_iterator anIt = aGenMakeShapes.cbegin(); anIt != aGenMakeShapes.cend(); ++anIt) { + aTools.push_back((*anIt)->shape()); + } -//================================================================================================= -std::shared_ptr FeaturesPlugin_CompositeBoolean::subFeature(const int theIndex, bool forTree) -{ - if (theIndex == 0) - return std::dynamic_pointer_cast(data()->reference(SKETCH_OBJECT_ID())->value()); - return std::shared_ptr(); -} + // Make boolean. + ListOfShape aBooleanObjects; + ListOfMakeShape aBooleanMakeShapes; + if(!makeBoolean(aTools, aBooleanObjects, aBooleanMakeShapes)) { + return; + } -//================================================================================================= -int FeaturesPlugin_CompositeBoolean::subFeatureId(const int theIndex) const -{ - if (theIndex == 0) { - FeaturePtr aFeature = - std::dynamic_pointer_cast(data()->reference(SKETCH_OBJECT_ID())->value()); - if (aFeature.get()) - return aFeature->data()->featureId(); + if(myOperationType == BOOL_FUSE) { + aTools.splice(aTools.begin(), aBooleanObjects); + aBooleanObjects.splice(aBooleanObjects.begin(), aTools, aTools.begin()); } - return -1; -} -//================================================================================================= -bool FeaturesPlugin_CompositeBoolean::isSub(ObjectPtr theObject) const -{ - // check is this feature of result - FeaturePtr aFeature = std::dynamic_pointer_cast(theObject); - if (!aFeature) - return false; - - ObjectPtr aSub = data()->reference(SKETCH_OBJECT_ID())->value(); - return aSub == theObject; -} + // Store result. + int aResultIndex = 0; + ListOfShape::const_iterator aBoolObjIt = aBooleanObjects.cbegin(); + ListOfMakeShape::const_iterator aBoolMSIt = aBooleanMakeShapes.cbegin(); + for(; aBoolObjIt != aBooleanObjects.cend() && aBoolMSIt != aBooleanMakeShapes.cend(); + ++aBoolObjIt, ++aBoolMSIt) { -//================================================================================================= -void FeaturesPlugin_CompositeBoolean::removeFeature(std::shared_ptr theFeature) -{ - AttributeSelectionListPtr aFacesSelectionList = selectionList(LIST_ID()); - if (aFacesSelectionList.get() && aFacesSelectionList->size() > 0) - aFacesSelectionList->clear(); -} + int aTag = 1; -//================================================================================================= -void FeaturesPlugin_CompositeBoolean::erase() -{ - if (data().get() && data()->isValid()) { // on abort of sketch of this composite it may be invalid - FeaturePtr aSketch = - std::dynamic_pointer_cast(data()->reference(SKETCH_OBJECT_ID())->value()); - if (aSketch.get() && aSketch->data()->isValid()) { - document()->removeFeature(aSketch); + ResultBodyPtr aResultBody = myFeature->document()->createBody(myFeature->data(), aResultIndex); + aResultBody->storeModified(*aBoolObjIt, (*aBoolMSIt)->shape(), aTag); + + aTag += 5000; + + // Store generation history. + ListOfShape::const_iterator aGenBaseIt = aGenBaseShapes.cbegin(); + ListOfMakeShape::const_iterator aGenMSIt = aGenMakeShapes.cbegin(); + for(; aGenBaseIt != aGenBaseShapes.cend() && aGenMSIt != aGenMakeShapes.cend(); + ++aGenBaseIt, ++aGenMSIt) { + storeGenerationHistory(aResultBody, *aGenBaseIt, *aGenMSIt, aTag); } + + int aModTag = aTag; + storeModificationHistory(aResultBody, *aBoolObjIt, aTools, *aBoolMSIt, aModTag); } - ModelAPI_CompositeFeature::erase(); } - //================================================================================================= -void FeaturesPlugin_CompositeBoolean::execute() +bool FeaturesPlugin_CompositeBoolean::makeBoolean(const ListOfShape& theTools, + ListOfShape& theObjects, + ListOfMakeShape& theMakeShapes) { - /// feature extrusion does not have the next attribute - AttributeSelectionListPtr aFacesSelectionList = selectionList(LIST_ID()); - if (aFacesSelectionList.get() && !aFacesSelectionList->isInitialized()) { - AttributeReferencePtr aSketchAttr = reference(SKETCH_OBJECT_ID()); - if (aSketchAttr.get() && aSketchAttr->isInitialized()) - setSketchObjectToList(); - } - - // Getting faces to create solids. - std::shared_ptr aSketchFeature = std::dynamic_pointer_cast( - reference(SKETCH_OBJECT_ID())->value()); - if(!aSketchFeature || aSketchFeature->results().empty()) { - return; - } - ResultPtr aSketchRes = aSketchFeature->results().front(); - ResultConstructionPtr aConstruction = std::dynamic_pointer_cast(aSketchRes); - if(!aConstruction.get()) { - return; - } - selection(SKETCH_SELECTION_ID())->setValue(aSketchRes, std::shared_ptr()); - int aSketchFacesNum = aConstruction->facesNum(); - if(aSketchFacesNum == 0) { - return; - } - ListOfShape aFacesList; - for(int aFaceIndex = 0; aFaceIndex < aSketchFacesNum; aFaceIndex++) { - std::shared_ptr aFace = std::dynamic_pointer_cast(aConstruction->face(aFaceIndex)); - aFacesList.push_back(aFace); - } - - // Searching faces with common edges. - ListOfShape aShells; - ListOfShape aFreeFaces; - std::shared_ptr aFacesCompound = GeomAlgoAPI_CompoundBuilder::compound(aFacesList); - GeomAlgoAPI_ShapeTools::combineShapes(aFacesCompound, GeomAPI_Shape::SHELL, aShells, aFreeFaces); - aShells.insert(aShells.end(), aFreeFaces.begin(), aFreeFaces.end()); - - // Pass shells/faces to solids creation function. - ListOfShape aTools; - ListOfMakeShape aSolidsAlgos; - makeSolids(aShells, aTools, aSolidsAlgos); - if(aTools.empty()) { - return; - } - - // Getting objects for boolean operation. - ListOfShape anObjects; - std::map, ListOfShape> aCompSolidsObjects; - AttributeSelectionListPtr anObjectsSelList = selectionList(BOOLEAN_OBJECTS_ID()); - if(anObjectsSelList->size() == 0) { - return; - } + // Getting objects. + ListOfShape anObjects, anEdgesAndFaces, aCompSolids; + std::map aCompSolidsObjects; + AttributeSelectionListPtr anObjectsSelList = myFeature->selectionList(OBJECTS_ID()); for(int anObjectsIndex = 0; anObjectsIndex < anObjectsSelList->size(); anObjectsIndex++) { AttributeSelectionPtr anObjectAttr = anObjectsSelList->value(anObjectsIndex); - std::shared_ptr anObject = anObjectAttr->value(); + GeomShapePtr anObject = anObjectAttr->value(); if(!anObject.get()) { - return; + myFeature->setError("Error: Could not get object."); + return false; } ResultPtr aContext = anObjectAttr->context(); ResultCompSolidPtr aResCompSolidPtr = ModelAPI_Tools::compSolidOwner(aContext); if(aResCompSolidPtr.get()) { - std::shared_ptr aContextShape = aResCompSolidPtr->shape(); - std::map, ListOfShape>::iterator anIt = aCompSolidsObjects.begin(); + GeomShapePtr aContextShape = aResCompSolidPtr->shape(); + std::map::iterator anIt = aCompSolidsObjects.begin(); for(; anIt != aCompSolidsObjects.end(); anIt++) { if(anIt->first->isEqual(aContextShape)) { aCompSolidsObjects[anIt->first].push_back(anObject); @@ -195,302 +108,258 @@ void FeaturesPlugin_CompositeBoolean::execute() } if(anIt == aCompSolidsObjects.end()) { aCompSolidsObjects[aContextShape].push_back(anObject); + aCompSolids.push_back(aContextShape); } } else { - anObjects.push_back(anObject); + if(anObject->shapeType() == GeomAPI_Shape::EDGE || + anObject->shapeType() == GeomAPI_Shape::FACE) { + anEdgesAndFaces.push_back(anObject); + } else { + anObjects.push_back(anObject); + } } } - // Cut from each object solids. - int aResultIndex = 0; + switch(myOperationType) { + case BOOL_CUT: { + if((anObjects.empty() && aCompSolidsObjects.empty()) || theTools.empty()) { + myFeature->setError("Error: Not enough objects for boolean operation."); + return false; + } - switch(myBooleanOperationType) { - case GeomAlgoAPI_Boolean::BOOL_CUT: - case GeomAlgoAPI_Boolean::BOOL_COMMON:{ - // Cut each object with all tools - for(ListOfShape::iterator anObjectsIt = anObjects.begin(); anObjectsIt != anObjects.end(); anObjectsIt++) { - std::shared_ptr anObject = *anObjectsIt; + // For solids cut each object with all tools. + for(ListOfShape::const_iterator anIt = anObjects.cbegin(); anIt != anObjects.cend(); ++anIt) { + GeomShapePtr anObject = *anIt; ListOfShape aListWithObject; aListWithObject.push_back(anObject); - GeomAlgoAPI_Boolean aBoolAlgo(aListWithObject, aTools, myBooleanOperationType); + std::shared_ptr aBoolAlgo(new GeomAlgoAPI_Boolean(aListWithObject, + theTools, + GeomAlgoAPI_Boolean::BOOL_CUT)); // Checking that the algorithm worked properly. - if(!aBoolAlgo.isDone() || aBoolAlgo.shape()->isNull() || !aBoolAlgo.isValid()) { - setError("Error: Boolean algorithm failed."); - return; + if(!aBoolAlgo->isDone() || aBoolAlgo->shape()->isNull() || !aBoolAlgo->isValid()) { + myFeature->setError("Error: Boolean algorithm failed."); + return false; } - if(GeomAlgoAPI_ShapeTools::volume(aBoolAlgo.shape()) > 1.e-7) { - std::shared_ptr aResultBody = document()->createBody(data(), aResultIndex); - loadNamingDS(aResultBody, aShells, aSolidsAlgos, anObject, aTools, aBoolAlgo.shape(), - aBoolAlgo, *aBoolAlgo.mapOfSubShapes().get()); - setResult(aResultBody, aResultIndex); - aResultIndex++; + if(GeomAlgoAPI_ShapeTools::volume(aBoolAlgo->shape()) > 1.e-7) { + theObjects.push_back(anObject); + theMakeShapes.push_back(aBoolAlgo); } } // Compsolids handling - for(std::map, ListOfShape>::iterator anIt = aCompSolidsObjects.begin(); - anIt != aCompSolidsObjects.end(); anIt++) { - std::shared_ptr aCompSolid = anIt->first; - ListOfShape& aUsedInOperationSolids = anIt->second; + for(std::map::const_iterator anIt = aCompSolidsObjects.cbegin(); + anIt != aCompSolidsObjects.cend(); ++anIt) { + GeomShapePtr aCompSolid = anIt->first; + const ListOfShape& aUsedShapes = anIt->second; // Collecting solids from compsolids which will not be modified in boolean operation. - ListOfShape aNotUsedSolids; + ListOfShape aShapesToAdd; for(GeomAPI_ShapeExplorer anExp(aCompSolid, GeomAPI_Shape::SOLID); anExp.more(); anExp.next()) { - std::shared_ptr aSolidInCompSolid = anExp.current(); - ListOfShape::iterator anIt = aUsedInOperationSolids.begin(); - for(; anIt != aUsedInOperationSolids.end(); anIt++) { - if(aSolidInCompSolid->isEqual(*anIt)) { + GeomShapePtr aSolidInCompSolid = anExp.current(); + ListOfShape::const_iterator aUsedShapesIt = aUsedShapes.cbegin(); + for(; aUsedShapesIt != aUsedShapes.cend(); ++aUsedShapesIt) { + if(aSolidInCompSolid->isEqual(*aUsedShapesIt)) { break; } } - if(anIt == aUsedInOperationSolids.end()) { - aNotUsedSolids.push_back(aSolidInCompSolid); + if(aUsedShapesIt == aUsedShapes.end()) { + aShapesToAdd.push_back(aSolidInCompSolid); } } - std::shared_ptr aBoolAlgo(new GeomAlgoAPI_Boolean(aUsedInOperationSolids, aTools, myBooleanOperationType)); + std::shared_ptr aBoolAlgo(new GeomAlgoAPI_Boolean(aUsedShapes, + theTools, + GeomAlgoAPI_Boolean::BOOL_CUT)); // Checking that the algorithm worked properly. if(!aBoolAlgo->isDone() || aBoolAlgo->shape()->isNull() || !aBoolAlgo->isValid()) { - setError("Error: Boolean algorithm failed."); - return; + myFeature->setError("Error: Boolean algorithm failed."); + return false; } GeomAlgoAPI_MakeShapeList aMakeShapeList; aMakeShapeList.appendAlgo(aBoolAlgo); - GeomAPI_DataMapOfShapeShape aMapOfShapes; - aMapOfShapes.merge(aBoolAlgo->mapOfSubShapes()); // Add result to not used solids from compsolid. - ListOfShape aShapesToAdd = aNotUsedSolids; aShapesToAdd.push_back(aBoolAlgo->shape()); std::shared_ptr aFillerAlgo(new GeomAlgoAPI_PaveFiller(aShapesToAdd, true)); - if(!aFillerAlgo->isDone()) { - std::string aFeatureError = "Error: PaveFiller algorithm failed."; - setError(aFeatureError); - return; + if(!aFillerAlgo->isDone() || aFillerAlgo->shape()->isNull() || !aFillerAlgo->isValid()) { + myFeature->setError("Error: PaveFiller algorithm failed."); + return false; } aMakeShapeList.appendAlgo(aFillerAlgo); - aMapOfShapes.merge(aFillerAlgo->mapOfSubShapes()); if(GeomAlgoAPI_ShapeTools::volume(aFillerAlgo->shape()) > 1.e-7) { - std::shared_ptr aResultBody = document()->createBody(data(), aResultIndex); - loadNamingDS(aResultBody, aShells, aSolidsAlgos, aCompSolid, aTools, aFillerAlgo->shape(), aMakeShapeList, aMapOfShapes); - setResult(aResultBody, aResultIndex); - aResultIndex++; + theObjects.push_back(aCompSolid); + theMakeShapes.push_back(aBoolAlgo); } } break; } - case GeomAlgoAPI_Boolean::BOOL_FUSE: { + case BOOL_FUSE: { + // Set objects. + theObjects.insert(theObjects.end(), anEdgesAndFaces.begin(), anEdgesAndFaces.end()); + theObjects.insert(theObjects.end(), anObjects.begin(), anObjects.end()); + theObjects.insert(theObjects.end(), aCompSolids.begin(), aCompSolids.end()); + + // Filter edges and faces in tools. + ListOfShape aTools; + for(ListOfShape::const_iterator anIt = aTools.cbegin(); anIt != aTools.cend(); ++anIt) { + if((*anIt)->shapeType() == GeomAPI_Shape::EDGE || + (*anIt)->shapeType() == GeomAPI_Shape::FACE) { + anEdgesAndFaces.push_back(*anIt); + } else { + aTools.push_back(*anIt); + } + } + + if((anObjects.size() + aTools.size() + aCompSolidsObjects.size() + anEdgesAndFaces.size()) < 2) { + myFeature->setError("Error: Not enough objects for boolean operation."); + return false; + } + // Collecting all solids which will be fused. ListOfShape aSolidsToFuse; aSolidsToFuse.insert(aSolidsToFuse.end(), anObjects.begin(), anObjects.end()); aSolidsToFuse.insert(aSolidsToFuse.end(), aTools.begin(), aTools.end()); - // Collecting solids from compsolids which will not be modified in boolean operation. - ListOfShape aNotUsedSolids; - for(std::map, ListOfShape>::iterator anIt = aCompSolidsObjects.begin(); - anIt != aCompSolidsObjects.end(); anIt++) { - std::shared_ptr aCompSolid = anIt->first; - ListOfShape& aUsedInOperationSolids = anIt->second; - aSolidsToFuse.insert(aSolidsToFuse.end(), aUsedInOperationSolids.begin(), aUsedInOperationSolids.end()); + // Collecting solids from compsolids which will not be modified in boolean operation and will be added to result. + ListOfShape aShapesToAdd; + for(std::map::iterator anIt = aCompSolidsObjects.begin(); + anIt != aCompSolidsObjects.end(); anIt++) { + GeomShapePtr aCompSolid = anIt->first; + ListOfShape& aUsedShapes = anIt->second; + aSolidsToFuse.insert(aSolidsToFuse.end(), aUsedShapes.begin(), aUsedShapes.end()); // Collect solids from compsolid which will not be modified in boolean operation. for(GeomAPI_ShapeExplorer anExp(aCompSolid, GeomAPI_Shape::SOLID); anExp.more(); anExp.next()) { - std::shared_ptr aSolidInCompSolid = anExp.current(); - ListOfShape::iterator anIt = aUsedInOperationSolids.begin(); - for(; anIt != aUsedInOperationSolids.end(); anIt++) { + GeomShapePtr aSolidInCompSolid = anExp.current(); + ListOfShape::iterator anIt = aUsedShapes.begin(); + for(; anIt != aUsedShapes.end(); anIt++) { if(aSolidInCompSolid->isEqual(*anIt)) { break; } } - if(anIt == aUsedInOperationSolids.end()) { - aNotUsedSolids.push_back(aSolidInCompSolid); + if(anIt == aUsedShapes.end()) { + aShapesToAdd.push_back(aSolidInCompSolid); } } } - ListOfShape anOriginalSolids = aSolidsToFuse; - anOriginalSolids.insert(anOriginalSolids.end(), aNotUsedSolids.begin(), aNotUsedSolids.end()); + // Cut edges and faces(if we have any) with solids. + ListOfShape aCutTools; + aCutTools.insert(aCutTools.end(), anObjects.begin(), anObjects.end()); + aCutTools.insert(aCutTools.end(), aCompSolids.begin(), aCompSolids.end()); + aCutTools.insert(aCutTools.end(), aTools.begin(), aTools.end()); + GeomAlgoAPI_MakeShapeList aMakeShapeList; - GeomAPI_DataMapOfShapeShape aMapOfShapes; + if(!anEdgesAndFaces.empty() && !aCutTools.empty()) { + std::shared_ptr aCutAlgo(new GeomAlgoAPI_Boolean(anEdgesAndFaces, + aCutTools, + GeomAlgoAPI_Boolean::BOOL_CUT)); + if(aCutAlgo->isDone() && !aCutAlgo->shape()->isNull() && aCutAlgo->isValid()) { + anEdgesAndFaces.clear(); + anEdgesAndFaces.push_back(aCutAlgo->shape()); + aMakeShapeList.appendAlgo(aCutAlgo); + } + } // If we have compsolids then cut with not used solids all others. - if(!aNotUsedSolids.empty()) { - aSolidsToFuse.clear(); - for(ListOfShape::iterator anIt = anOriginalSolids.begin(); anIt != anOriginalSolids.end(); anIt++) { - ListOfShape aOneObjectList; - aOneObjectList.push_back(*anIt); - std::shared_ptr aCutAlgo(new GeomAlgoAPI_Boolean(aOneObjectList, aNotUsedSolids, GeomAlgoAPI_Boolean::BOOL_CUT)); - - if(GeomAlgoAPI_ShapeTools::volume(aCutAlgo->shape()) > 1.e-7) { - aSolidsToFuse.push_back(aCutAlgo->shape()); - aMakeShapeList.appendAlgo(aCutAlgo); - aMapOfShapes.merge(aCutAlgo->mapOfSubShapes()); - } + if(!aShapesToAdd.empty()) { + std::shared_ptr aCutAlgo(new GeomAlgoAPI_Boolean(aSolidsToFuse, + aShapesToAdd, + GeomAlgoAPI_Boolean::BOOL_CUT)); + if(aCutAlgo->isDone() && GeomAlgoAPI_ShapeTools::volume(aCutAlgo->shape()) > 1.e-7) { + aSolidsToFuse.clear(); + aSolidsToFuse.push_back(aCutAlgo->shape()); + aMakeShapeList.appendAlgo(aCutAlgo); } } - anObjects.clear(); - anObjects.push_back(aSolidsToFuse.back()); - aSolidsToFuse.pop_back(); - aTools = aSolidsToFuse; - // Fuse all objects and all tools. - std::shared_ptr aFuseAlgo(new GeomAlgoAPI_Boolean(anObjects, aTools, myBooleanOperationType)); + GeomShapePtr aFusedShape; + if(aSolidsToFuse.size() == 1) { + aFusedShape = aSolidsToFuse.front(); + } else if(aSolidsToFuse.size() > 1){ + anObjects.clear(); + anObjects.push_back(aSolidsToFuse.front()); + aSolidsToFuse.pop_front(); + aTools = aSolidsToFuse; + + std::shared_ptr aFuseAlgo(new GeomAlgoAPI_Boolean(anObjects, + aTools, + GeomAlgoAPI_Boolean::BOOL_FUSE)); - // Checking that the algorithm worked properly. - if(!aFuseAlgo->isDone() || aFuseAlgo->shape()->isNull() || !aFuseAlgo->isValid()) { - static const std::string aFeatureError = "Error: Boolean algorithm failed."; - setError(aFeatureError); - return; + // Checking that the algorithm worked properly. + if(!aFuseAlgo->isDone() || aFuseAlgo->shape()->isNull() || !aFuseAlgo->isValid()) { + myFeature->setError("Error: Boolean algorithm failed."); + return false; + } + + aFusedShape = aFuseAlgo->shape(); + aMakeShapeList.appendAlgo(aFuseAlgo); } - std::shared_ptr aShape = aFuseAlgo->shape(); - aMakeShapeList.appendAlgo(aFuseAlgo); - aMapOfShapes.merge(aFuseAlgo->mapOfSubShapes()); - - // Add result to not used solids from compsolid (if we have any). - if(!aNotUsedSolids.empty()) { - aNotUsedSolids.push_back(aShape); - std::shared_ptr aFillerAlgo(new GeomAlgoAPI_PaveFiller(aNotUsedSolids, true)); - if(!aFillerAlgo->isDone()) { - std::string aFeatureError = "Error: PaveFiller algorithm failed."; - setError(aFeatureError); - return; + // Combine result with not used solids from compsolid and edges and faces (if we have any). + aShapesToAdd.insert(aShapesToAdd.end(), anEdgesAndFaces.begin(), anEdgesAndFaces.end()); + if(!aShapesToAdd.empty()) { + if(aFusedShape.get()) { + aShapesToAdd.push_back(aFusedShape); } - if(aFillerAlgo->shape()->isNull()) { - static const std::string aShapeError = "Error: Resulting shape is Null."; - setError(aShapeError); - return; - } - if(!aFillerAlgo->isValid()) { - std::string aFeatureError = "Error: Resulting shape is not valid."; - setError(aFeatureError); - return; + + std::shared_ptr aFillerAlgo(new GeomAlgoAPI_PaveFiller(aShapesToAdd, true)); + if(!aFillerAlgo->isDone() || aFillerAlgo->shape()->isNull() || !aFillerAlgo->isValid()) { + myFeature->setError("Error: PaveFiller algorithm failed."); + return false; } - aShape = aFillerAlgo->shape(); aMakeShapeList.appendAlgo(aFillerAlgo); - aMapOfShapes.merge(aFillerAlgo->mapOfSubShapes()); } - - std::shared_ptr aResultBody = document()->createBody(data(), aResultIndex); - loadNamingDS(aResultBody, aShells, aSolidsAlgos, anOriginalSolids.front(), anOriginalSolids, aShape, aMakeShapeList, aMapOfShapes); - setResult(aResultBody, aResultIndex); - aResultIndex++; break; } - default: { - setError("Error: Wrong type of boolean operation."); - return; - } } - // Remove the rest results if there were produced in the previous pass. - removeResults(aResultIndex); + return true; } //================================================================================================= -void FeaturesPlugin_CompositeBoolean::loadNamingDS(std::shared_ptr theResultBody, - const ListOfShape& theShells, - ListOfMakeShape& theSolidsAlgos, - const std::shared_ptr theBaseShape, - const ListOfShape& theTools, - const std::shared_ptr theResultShape, - GeomAlgoAPI_MakeShape& theMakeShape, - GeomAPI_DataMapOfShapeShape& theMapOfShapes) +void FeaturesPlugin_CompositeBoolean::storeModificationHistory(ResultBodyPtr theResultBody, + const GeomShapePtr theObject, + const ListOfShape& theTools, + const std::shared_ptr theMakeShape, + int& theTag) { - //load result - if(theBaseShape->isEqual(theResultShape)) { - theResultBody->store(theResultShape); - } else { - const int aGenTag = 1; - const int aModTag = 2; - const int aDelTag = 3; - const int aSubsolidsTag=4; /// sub solids will be placed at labels 6, 7, etc. if result is compound of solids - int aToTag = 5000; // may be many labels, starting from this index - int aFromTag = 10000; // may be many labels, starting from this index or last aToTag index - const std::string aGenName = "Generated"; - const std::string aModName = "Modified"; - const std::string aLatName = "LateralFace"; - const std::string aFromName = "FromFace"; - const std::string aToName = "ToFace"; - - theResultBody->storeModified(theBaseShape, theResultShape, aSubsolidsTag); - - ListOfShape::const_iterator aShellsIter = theShells.begin(); - ListOfMakeShape::const_iterator aSolidsAlgosIter = theSolidsAlgos.begin(); - for(; aShellsIter != theShells.end() && aSolidsAlgosIter != theSolidsAlgos.end(); aShellsIter++, aSolidsAlgosIter++) { - //Insert lateral face : Face from Edge - std::shared_ptr aSolidAlgo = std::dynamic_pointer_cast(*aSolidsAlgosIter); - if(aSolidAlgo.get()) { - std::shared_ptr aSubShapes = aSolidAlgo->mapOfSubShapes(); - theResultBody->loadAndOrientGeneratedShapes(aSolidAlgo.get(), *aShellsIter, GeomAPI_Shape::EDGE, aGenTag, - aLatName, *aSubShapes.get()); - - - std::shared_ptr aSweepAlgo = std::dynamic_pointer_cast(aSolidAlgo); - if(aSweepAlgo.get()) { - //Insert to faces - int aToFaceIndex = 1; - const ListOfShape& aToFaces = aSweepAlgo->toShapes(); - for(ListOfShape::const_iterator anIt = aToFaces.cbegin(); anIt != aToFaces.cend(); anIt++) { - std::shared_ptr aToFace = *anIt; - if(aSubShapes->isBound(aToFace)) { - aToFace = aSubShapes->find(aToFace); - } - std::ostringstream aStr; - aStr << aToName << "_" << aToFaceIndex++; - theResultBody->generated(aToFace, aStr.str(), aToTag++); - } + int aModTag = theTag; + int anEdgesAndFacesTag = ++aModTag; + int aDelTag = ++anEdgesAndFacesTag; + theTag = aDelTag; - //Insert from faces - int aFromFaceIndex = 1; - const ListOfShape& aFromFaces = aSweepAlgo->fromShapes(); - if (aFromTag < aToTag) aFromTag = aToTag; - for(ListOfShape::const_iterator anIt = aFromFaces.cbegin(); anIt != aFromFaces.cend(); anIt++) { - std::shared_ptr aFromFace = *anIt; - if(aSubShapes->isBound(aFromFace)) { - aFromFace = aSubShapes->find(aFromFace); - } - std::ostringstream aStr; - aStr << aFromName << "_" << aFromFaceIndex++; - theResultBody->generated(aFromFace, aStr.str(), aFromTag++); - } - } - } - } + const std::string aModName = "Modfied"; - theResultBody->loadAndOrientModifiedShapes(&theMakeShape, theBaseShape, GeomAPI_Shape::FACE, - aModTag, aModName, theMapOfShapes); - theResultBody->loadDeletedShapes(&theMakeShape, theBaseShape, GeomAPI_Shape::FACE, aDelTag); + ListOfShape aTools = theTools; + aTools.push_back(theObject); - for(ListOfShape::const_iterator anIter = theTools.begin(); anIter != theTools.end(); anIter++) { - theResultBody->loadAndOrientModifiedShapes(&theMakeShape, *anIter, GeomAPI_Shape::FACE, - aModTag, aModName, theMapOfShapes); - theResultBody->loadDeletedShapes(&theMakeShape, *anIter, GeomAPI_Shape::FACE, aDelTag); - } - } -} + std::shared_ptr aMap = theMakeShape->mapOfSubShapes(); -//================================================================================================= -void FeaturesPlugin_CompositeBoolean::setSketchObjectToList() -{ - std::shared_ptr aSketchFeature = std::dynamic_pointer_cast( - reference(SKETCH_OBJECT_ID())->value()); - - if(aSketchFeature.get() && !aSketchFeature->results().empty()) { - ResultPtr aSketchRes = aSketchFeature->results().front(); - ResultConstructionPtr aConstruction = std::dynamic_pointer_cast(aSketchRes); - if(aConstruction.get()) { - AttributeSelectionListPtr aFacesSelectionList = selectionList(LIST_ID()); - if (aFacesSelectionList.get() && aFacesSelectionList->size() == 0) - aFacesSelectionList->append(aSketchRes, std::shared_ptr()); + int aTag; + std::string aName; + for(ListOfShape::const_iterator anIt = aTools.begin(); anIt != aTools.end(); anIt++) { + if((*anIt)->shapeType() == GeomAPI_Shape::EDGE) { + aTag = anEdgesAndFacesTag; + aName = aModName + "_Edge"; + } + else if((*anIt)->shapeType() == GeomAPI_Shape::FACE) { + aTag = anEdgesAndFacesTag; + aName = aModName + "_Face"; + } else { + aTag = aModTag; + aName = aModName; } + theResultBody->loadAndOrientModifiedShapes(theMakeShape.get(), *anIt, (*anIt)->shapeType() == GeomAPI_Shape::EDGE ? + GeomAPI_Shape::EDGE : GeomAPI_Shape::FACE, aTag, aName, *aMap.get()); + theResultBody->loadDeletedShapes(theMakeShape.get(), *anIt, GeomAPI_Shape::FACE, aDelTag); } } diff --git a/src/FeaturesPlugin/FeaturesPlugin_CompositeBoolean.h b/src/FeaturesPlugin/FeaturesPlugin_CompositeBoolean.h index 7cae61fd9..daa2e060d 100644 --- a/src/FeaturesPlugin/FeaturesPlugin_CompositeBoolean.h +++ b/src/FeaturesPlugin/FeaturesPlugin_CompositeBoolean.h @@ -7,103 +7,70 @@ #ifndef FeaturesPlugin_CompositeBoolean_H_ #define FeaturesPlugin_CompositeBoolean_H_ -#include +#include "FeaturesPlugin.h" -#include +#include +#include +#include -#include - -/** \class FeaturesPlugin_CompositeBoolean - * \ingroup Plugins - * \brief Interface for the composite boolean feature. - */ -class FeaturesPlugin_CompositeBoolean : public ModelAPI_CompositeFeature +/// \class FeaturesPlugin_CompositeBoolean +/// \ingroup Plugins +/// \brief Interface for the composite boolean feature. +class FeaturesPlugin_CompositeBoolean { - public: - /// Attribute name of sketch feature. - inline static const std::string& SKETCH_OBJECT_ID() - { - static const std::string MY_SKETCH_OBJECT_ID("sketch"); - return MY_SKETCH_OBJECT_ID; - } - - /// attribute name of references sketch entities list, it should contain a sketch result or - /// a pair a sketch result to sketch face - inline static const std::string& LIST_ID() +public: + enum OperationType { + BOOL_CUT, + BOOL_FUSE, + BOOL_COMMON, + BOOL_SMASH + }; + + /// Attribute name of main objects. + inline static const std::string& OBJECTS_ID() { - static const std::string MY_GROUP_LIST_ID("base"); - return MY_GROUP_LIST_ID; - } - - /// Attribute name of sketch feature. - inline static const std::string& SKETCH_SELECTION_ID() - { - static const std::string MY_SKETCH_SELECTION_ID("sketch_selection"); - return MY_SKETCH_SELECTION_ID; - } - - /// Attribute name of objects for boolean operation. - inline static const std::string& BOOLEAN_OBJECTS_ID() - { - static const std::string MY_BOOLEAN_OBJECTS_ID("boolean_objects"); - return MY_BOOLEAN_OBJECTS_ID; + static const std::string MY_OBJECTS_ID("main_objects"); + return MY_OBJECTS_ID; } /// Creates a new part document if needed. FEATURESPLUGIN_EXPORT virtual void execute(); - /// Request for initialization of data model of the feature: adding all attributes. - FEATURESPLUGIN_EXPORT virtual void initAttributes(); - - /// Appends a feature to the sketch sub-elements container. - FEATURESPLUGIN_EXPORT virtual std::shared_ptr addFeature(std::string theID); - - /// \return the number of sub-elements. - FEATURESPLUGIN_EXPORT virtual int numberOfSubs(bool forTree = false) const; - - /// \return the sub-feature by zero-base index. - FEATURESPLUGIN_EXPORT virtual std::shared_ptr subFeature(const int theIndex, bool forTree = false); - - /// \return the sub-feature unique identifier in this composite feature by zero-base index. - FEATURESPLUGIN_EXPORT virtual int subFeatureId(const int theIndex) const; - - /// \return true if feature or reuslt belong to this composite feature as subs. - FEATURESPLUGIN_EXPORT virtual bool isSub(ObjectPtr theObject) const; - - /// This method to inform that sub-feature is removed and must be removed from the internal data - /// structures of the owner (the remove from the document will be done outside just after) - FEATURESPLUGIN_EXPORT virtual void removeFeature(std::shared_ptr theFeature); - - /// removes also all sub-sketch - FEATURESPLUGIN_EXPORT virtual void erase(); - protected: FeaturesPlugin_CompositeBoolean(){}; - /// Define this function to init attributes for extrusion/revolution. - virtual void initMakeSolidsAttributes() = 0; - - /// Define this function to create solids from faces with extrusion/revolution. - virtual void makeSolids(const ListOfShape& theFaces, - ListOfShape& theResults, - ListOfMakeShape& theAlgos) = 0; - - /// Results naming. - void loadNamingDS(std::shared_ptr theResultBody, - const ListOfShape& theShells, - ListOfMakeShape& theSolidsAlgos, - const std::shared_ptr theBaseShape, - const ListOfShape& theTools, - const std::shared_ptr theResultShape, - GeomAlgoAPI_MakeShape& theMakeShape, - GeomAPI_DataMapOfShapeShape& theMapOfShapes); - - /// Set the sub-object to list of exturusion base. - void setSketchObjectToList(); + /// Initializes boolean attributes. + void initBooleanAttributes(); + + /// This function need to be defined for extrusion/revolution generation. + virtual bool makeGeneration(ListOfShape& theBaseShapes, + ListOfMakeShape& theMakeShapes) = 0; + + /// Makes boolean operation. + /// \param[in] theTools list of tools. + /// \param[out] theObjects list of objects. + /// \param[out] theMakeShapes list of according algos. + /// \return false in failed. + bool makeBoolean(const ListOfShape& theTools, + ListOfShape& theObjects, + ListOfMakeShape& theMakeShapes); + + /// Stores generation history. + virtual void storeGenerationHistory(ResultBodyPtr theResultBody, + const GeomShapePtr theBaseShape, + const std::shared_ptr theMakeShape, + int& theTag) = 0; + + /// Stores modification history. + void storeModificationHistory(ResultBodyPtr theResultBody, + const GeomShapePtr theObject, + const ListOfShape& theTools, + const std::shared_ptr theMakeShape, + int& theTag); protected: - /// Type of boolean operation. - GeomAlgoAPI_Boolean::OperationType myBooleanOperationType; + ModelAPI_Feature* myFeature; + OperationType myOperationType; }; #endif diff --git a/src/FeaturesPlugin/FeaturesPlugin_CompositeSketch.cpp b/src/FeaturesPlugin/FeaturesPlugin_CompositeSketch.cpp index 57a711e0c..0b5a103ce 100644 --- a/src/FeaturesPlugin/FeaturesPlugin_CompositeSketch.cpp +++ b/src/FeaturesPlugin/FeaturesPlugin_CompositeSketch.cpp @@ -9,7 +9,6 @@ #include #include #include -#include #include #include #include @@ -18,27 +17,34 @@ #include #include #include +#include #include //================================================================================================= -void FeaturesPlugin_CompositeSketch::initAttributes() +void FeaturesPlugin_CompositeSketch::initCompositeSketchAttribtues(const int theInitFlags) { - data()->addAttribute(SKETCH_OBJECT_ID(), ModelAPI_AttributeReference::typeId()); - data()->addAttribute(SKETCH_SELECTION_ID(), ModelAPI_AttributeSelection::typeId()); - ModelAPI_Session::get()->validators()->registerNotObligatory(getKind(), SKETCH_SELECTION_ID()); + // Initialize sketch launcher. + if(theInitFlags & InitSketchLauncher) { + data()->addAttribute(SKETCH_ID(), ModelAPI_AttributeReference::typeId()); + ModelAPI_Session::get()->validators()->registerNotObligatory(getKind(), SKETCH_ID()); + } - //initMakeSolidsAttributes(); + // Initialize selection list. + if(theInitFlags & InitBaseObjectsList) { + data()->addAttribute(BASE_OBJECTS_ID(), ModelAPI_AttributeSelectionList::typeId()); + } } //================================================================================================= std::shared_ptr FeaturesPlugin_CompositeSketch::addFeature(std::string theID) { - std::shared_ptr aNew = document()->addFeature(theID, false); - if (aNew) { - data()->reference(SKETCH_OBJECT_ID())->setValue(aNew); + FeaturePtr aNew = document()->addFeature(theID, false); + if(aNew) { + data()->reference(SKETCH_ID())->setValue(aNew); } - // set as current also after it becomes sub to set correctly enabled for other sketch subs + + // Set as current also after it becomes sub to set correctly enabled for other sketch subs. document()->setCurrentFeature(aNew, false); return aNew; } @@ -46,194 +52,301 @@ std::shared_ptr FeaturesPlugin_CompositeSketch::addFeature(std //================================================================================================= int FeaturesPlugin_CompositeSketch::numberOfSubs(bool forTree) const { - ObjectPtr aObj = data()->reference(SKETCH_OBJECT_ID())->value(); - return aObj.get()? 1 : 0; + ObjectPtr aObj = data()->reference(SKETCH_ID())->value(); + return aObj.get() ? 1 : 0; } //================================================================================================= std::shared_ptr FeaturesPlugin_CompositeSketch::subFeature(const int theIndex, bool forTree) { - if (theIndex == 0) - return std::dynamic_pointer_cast(data()->reference(SKETCH_OBJECT_ID())->value()); + if(theIndex == 0) { + return std::dynamic_pointer_cast(data()->reference(SKETCH_ID())->value()); + } + return std::shared_ptr(); } //================================================================================================= int FeaturesPlugin_CompositeSketch::subFeatureId(const int theIndex) const { - if (theIndex == 0) { - FeaturePtr aFeature = - std::dynamic_pointer_cast(data()->reference(SKETCH_OBJECT_ID())->value()); - if (aFeature.get()) + if(theIndex == 0) { + FeaturePtr aFeature = + std::dynamic_pointer_cast(data()->reference(SKETCH_ID())->value()); + if(aFeature.get()) { return aFeature->data()->featureId(); + } } + return -1; } //================================================================================================= bool FeaturesPlugin_CompositeSketch::isSub(ObjectPtr theObject) const { - // check is this feature of result + // Check is this feature of result FeaturePtr aFeature = std::dynamic_pointer_cast(theObject); - if (!aFeature) + if(!aFeature.get()) { return false; - - ObjectPtr aSub = data()->reference(SKETCH_OBJECT_ID())->value(); + } + + ObjectPtr aSub = data()->reference(SKETCH_ID())->value(); return aSub == theObject; } //================================================================================================= void FeaturesPlugin_CompositeSketch::removeFeature(std::shared_ptr theFeature) { - AttributeSelectionListPtr aFacesSelectionList = selectionList(LIST_ID()); - if (aFacesSelectionList.get() && aFacesSelectionList->size() > 0) - aFacesSelectionList->clear(); + AttributeSelectionListPtr aBaseObjectsSelectionList = selectionList(BASE_OBJECTS_ID()); + if(aBaseObjectsSelectionList.get() && aBaseObjectsSelectionList->size() > 0) { + aBaseObjectsSelectionList->clear(); + } - data()->reference(SKETCH_OBJECT_ID())->setValue(ObjectPtr()); + reference(SKETCH_ID())->setValue(ObjectPtr()); } //================================================================================================= void FeaturesPlugin_CompositeSketch::erase() { - if (data().get() && data()->isValid()) { // on abort of sketch of this composite it may be invalid - FeaturePtr aSketch = - std::dynamic_pointer_cast(data()->reference(SKETCH_OBJECT_ID())->value()); - if (aSketch.get() && aSketch->data()->isValid()) { + if(data().get() && data()->isValid()) { // on abort of sketch of this composite it may be invalid + FeaturePtr aSketch = std::dynamic_pointer_cast(reference(SKETCH_ID())->value()); + if(aSketch.get() && aSketch->data()->isValid()) { document()->removeFeature(aSketch); } } + ModelAPI_CompositeFeature::erase(); } - //================================================================================================= -void FeaturesPlugin_CompositeSketch::execute() +void FeaturesPlugin_CompositeSketch::setSketchObjectToList() { - // Getting faces to create solids. - std::shared_ptr aSketchFeature = std::dynamic_pointer_cast( - reference(SKETCH_OBJECT_ID())->value()); - if(!aSketchFeature || aSketchFeature->results().empty()) { + AttributeSelectionListPtr aBaseObjectsSelectionList = selectionList(BASE_OBJECTS_ID()); + if(!aBaseObjectsSelectionList.get() || aBaseObjectsSelectionList->isInitialized()) { return; } + + AttributeReferencePtr aSketchLauncherRef = reference(SKETCH_ID()); + if(!aSketchLauncherRef.get() || !aSketchLauncherRef->isInitialized()) { + return; + } + + FeaturePtr aSketchFeature = std::dynamic_pointer_cast(aSketchLauncherRef->value()); + + if(!aSketchFeature.get() || aSketchFeature->results().empty()) { + return; + } + ResultPtr aSketchRes = aSketchFeature->results().front(); ResultConstructionPtr aConstruction = std::dynamic_pointer_cast(aSketchRes); if(!aConstruction.get()) { return; } - /// feature extrusion does not have the next attribute - if (data()->attribute(SKETCH_SELECTION_ID()).get()) { - if (!selection(SKETCH_SELECTION_ID())->isInitialized() || selection(SKETCH_SELECTION_ID())->context() != aSketchRes) { - selection(SKETCH_SELECTION_ID())->setValue(aSketchRes, std::shared_ptr()); - } + if(aBaseObjectsSelectionList->size() == 0) { + aBaseObjectsSelectionList->append(aSketchRes, GeomShapePtr()); } - int aSketchFacesNum = aConstruction->facesNum(); - if(aSketchFacesNum == 0) { +} + +//================================================================================================= +void FeaturesPlugin_CompositeSketch::getBaseShapes(ListOfShape& theBaseShapesList, + const bool theIsMakeShells) +{ + theBaseShapesList.clear(); + + ListOfShape aBaseFacesList; + AttributeSelectionListPtr aBaseObjectsSelectionList = selectionList(BASE_OBJECTS_ID()); + if(!aBaseObjectsSelectionList.get()) { + setError("Error: Could not get base objects selection list."); return; } - ListOfShape aFacesList; - for(int aFaceIndex = 0; aFaceIndex < aSketchFacesNum; aFaceIndex++) { - std::shared_ptr aFace = std::dynamic_pointer_cast(aConstruction->face(aFaceIndex)); - aFacesList.push_back(aFace); + if(aBaseObjectsSelectionList->size() == 0) { + setError("Error: Base objects list is empty."); + return; + } + for(int anIndex = 0; anIndex < aBaseObjectsSelectionList->size(); anIndex++) { + AttributeSelectionPtr aBaseObjectSelection = aBaseObjectsSelectionList->value(anIndex); + if(!aBaseObjectSelection.get()) { + setError("Error: One of the selected base objects is empty."); + return; + } + GeomShapePtr aBaseShape = aBaseObjectSelection->value(); + if(aBaseShape.get() && !aBaseShape->isNull()) { + aBaseShape->shapeType() == GeomAPI_Shape::FACE ? aBaseFacesList.push_back(aBaseShape) : + theBaseShapesList.push_back(aBaseShape); + } else { + // This may be the whole sketch result selected, check and get faces. + ResultConstructionPtr aConstruction = + std::dynamic_pointer_cast(aBaseObjectSelection->context()); + if(!aConstruction.get()) { + setError("Error: One of selected sketches does not have results."); + return; + } + int aFacesNum = aConstruction->facesNum(); + if(aFacesNum == 0) { + // Probably it can be construction. + aBaseShape = aConstruction->shape(); + if(aBaseShape.get() && !aBaseShape->isNull()) { + aBaseShape->shapeType() == GeomAPI_Shape::FACE ? aBaseFacesList.push_back(aBaseShape) : + theBaseShapesList.push_back(aBaseShape); + } + } else { + for(int aFaceIndex = 0; aFaceIndex < aFacesNum; aFaceIndex++) { + GeomShapePtr aBaseFace = aConstruction->face(aFaceIndex); + if(!aBaseFace.get() || aBaseFace->isNull()) { + setError("Error: One of the faces on selected sketch is Null."); + return; + } + aBaseFacesList.push_back(aBaseFace); + } + } + } } // Searching faces with common edges. - ListOfShape aShells; - ListOfShape aFreeFaces; - std::shared_ptr aFacesCompound = GeomAlgoAPI_CompoundBuilder::compound(aFacesList); - GeomAlgoAPI_ShapeTools::combineShapes(aFacesCompound, GeomAPI_Shape::SHELL, aShells, aFreeFaces); - aShells.insert(aShells.end(), aFreeFaces.begin(), aFreeFaces.end()); - - // Generating result for each shell and face. - int aErrorsNum = 0; - int aResultIndex = 0; - for(ListOfShape::const_iterator anIter = aShells.cbegin(); anIter != aShells.cend(); anIter++) { - std::shared_ptr aMakeShape; - - std::shared_ptr aBaseFace = *anIter; - makeSolid(aBaseFace, aMakeShape); - if(!aMakeShape.get()) { - aErrorsNum++; - continue; - } + if(theIsMakeShells) { + ListOfShape aShells; + ListOfShape aFreeFaces; + GeomShapePtr aFacesCompound = GeomAlgoAPI_CompoundBuilder::compound(aBaseFacesList); + GeomAlgoAPI_ShapeTools::combineShapes(aFacesCompound, GeomAPI_Shape::SHELL, aShells, aFreeFaces); + theBaseShapesList.insert(theBaseShapesList.end(), aFreeFaces.begin(), aFreeFaces.end()); + theBaseShapesList.insert(theBaseShapesList.end(), aShells.begin(), aShells.end()); + } else { + theBaseShapesList.insert(theBaseShapesList.end(), aBaseFacesList.begin(), aBaseFacesList.end()); + } +} - ResultBodyPtr aResultBody = document()->createBody(data(), aResultIndex); - loadNamingDS(aResultBody, aBaseFace, aMakeShape); - setResult(aResultBody, aResultIndex); - aResultIndex++; +//================================================================================================= +bool FeaturesPlugin_CompositeSketch::isMakeShapeValid(const std::shared_ptr theMakeShape) +{ + // Check that algo is done. + if(!theMakeShape->isDone()) { + setError("Error:" + getKind() + "algorithm failed."); + return false; } - if(aErrorsNum > 0) { - std::ostringstream aStringStream; - aStringStream << "Error: Could not create solid(s) from " << aErrorsNum << " face(s)."; - setError(aStringStream.str()); + // Check if shape is not null. + if(!theMakeShape->shape().get() || theMakeShape->shape()->isNull()) { + setError("Error: Resulting shape is null."); + return false; } - // Remove the rest results if there were produced in the previous pass. - removeResults(aResultIndex); + // Check that resulting shape is valid. + if(!theMakeShape->isValid()) { + setError("Error: Resulting shape is not valid."); + return false; + } + + return true; } //================================================================================================= -void FeaturesPlugin_CompositeSketch::loadNamingDS(std::shared_ptr theResultBody, - const std::shared_ptr& theBaseShape, - const std::shared_ptr& theMakeShape) +void FeaturesPlugin_CompositeSketch::storeResult(const GeomShapePtr theBaseShape, + const std::shared_ptr theMakeShape, + const int theResultIndex) { - //load result - theResultBody->storeGenerated(theBaseShape, theMakeShape->shape()); - - //Insert lateral face : Face from Edge - const std::string aLatName = "LateralFace"; - const int aLatTag = 1; - std::shared_ptr aDataMap = theMakeShape->mapOfSubShapes(); - theResultBody->loadAndOrientGeneratedShapes(theMakeShape.get(), theBaseShape, GeomAPI_Shape::EDGE, aLatTag, aLatName, *aDataMap.get()); - - std::shared_ptr aSweepAlgo = std::dynamic_pointer_cast(theMakeShape); - if(aSweepAlgo.get()) { - //Insert to faces - int aToFaceIndex = 1; - const std::string aToName = "ToFace"; - int aToTag = 2; - const ListOfShape& aToFaces = aSweepAlgo->toShapes(); - for(ListOfShape::const_iterator anIt = aToFaces.cbegin(); anIt != aToFaces.cend(); anIt++) { - std::shared_ptr aToFace = *anIt; - if(aDataMap->isBound(aToFace)) { - aToFace = aDataMap->find(aToFace); - } - std::ostringstream aStr; - aStr << aToName << "_" << aToFaceIndex++; - theResultBody->generated(aToFace, aStr.str(), aToTag++); - } + // Create result body. + ResultBodyPtr aResultBody = document()->createBody(data(), theResultIndex); - //Insert from faces - int aFromFaceIndex = 1; - const std::string aFromName = "FromFace"; - int aFromTag = aToTag > 10000 ? aToTag : 10000; - const ListOfShape& aFromFaces = aSweepAlgo->fromShapes(); - for(ListOfShape::const_iterator anIt = aFromFaces.cbegin(); anIt != aFromFaces.cend(); anIt++) { - std::shared_ptr aFromFace = *anIt; - if(aDataMap->isBound(aFromFace)) { - aFromFace = aDataMap->find(aFromFace); - } - std::ostringstream aStr; - aStr << aFromName << "_" << aFromFaceIndex++; - theResultBody->generated(aFromFace, aStr.str(), aFromTag++); + // Store generated shape. + aResultBody->storeGenerated(theBaseShape, theMakeShape->shape()); + + // Store generated edges/faces. + int aGenTag = 1; + storeGenerationHistory(aResultBody, theBaseShape, theMakeShape, aGenTag); + + setResult(aResultBody, theResultIndex); +} + +//================================================================================================= +void FeaturesPlugin_CompositeSketch::storeGenerationHistory(ResultBodyPtr theResultBody, + const GeomShapePtr theBaseShape, + const std::shared_ptr theMakeShape, + int& theTag) +{ + GeomAPI_Shape::ShapeType aBaseShapeType = theBaseShape->shapeType(); + GeomAPI_Shape::ShapeType aShapeTypeToExplode; + std::string aGenName = "Generated_"; + + std::shared_ptr aMapOfSubShapes = theMakeShape->mapOfSubShapes(); + switch(aBaseShapeType) { + case GeomAPI_Shape::VERTEX: { + aShapeTypeToExplode = GeomAPI_Shape::VERTEX; + aGenName += "Edge"; + break; + } + case GeomAPI_Shape::EDGE: + case GeomAPI_Shape::WIRE: { + std::shared_ptr aV1, aV2; + GeomAlgoAPI_ShapeTools::findBounds(theBaseShape, aV1, aV2); + ListOfShape aV1History, aV2History; + theMakeShape->generated(aV1, aV1History); + theMakeShape->generated(aV2, aV2History); + theResultBody->generated(aV1, aV1History.front(), aGenName + "Edge_1", theTag++); + theResultBody->generated(aV2, aV2History.front(), aGenName + "Edge_2", theTag++); + } + case GeomAPI_Shape::FACE: + case GeomAPI_Shape::SHELL: { + aShapeTypeToExplode = GeomAPI_Shape::EDGE; + aGenName += "Face"; + break; } } + theResultBody->loadAndOrientGeneratedShapes(theMakeShape.get(), theBaseShape, aShapeTypeToExplode, + theTag++, aGenName, *aMapOfSubShapes.get()); + + std::shared_ptr aMakeSweep = std::dynamic_pointer_cast(theMakeShape); + if(aMakeSweep.get()) { + // Store from shapes. + storeShapes(theResultBody, aBaseShapeType, aMapOfSubShapes, aMakeSweep->fromShapes(), "From_", theTag); + + // Store to shapes. + storeShapes(theResultBody, aBaseShapeType, aMapOfSubShapes, aMakeSweep->toShapes(), "To_", theTag); + } } + //================================================================================================= -void FeaturesPlugin_CompositeSketch::setSketchObjectToList() +void FeaturesPlugin_CompositeSketch::storeShapes(ResultBodyPtr theResultBody, + const GeomAPI_Shape::ShapeType theBaseShapeType, + const std::shared_ptr theMapOfSubShapes, + const ListOfShape& theShapes, + const std::string theName, + int& theTag) { - std::shared_ptr aSketchFeature = std::dynamic_pointer_cast( - reference(SKETCH_OBJECT_ID())->value()); - - if(aSketchFeature.get() && !aSketchFeature->results().empty()) { - ResultPtr aSketchRes = aSketchFeature->results().front(); - ResultConstructionPtr aConstruction = std::dynamic_pointer_cast(aSketchRes); - if(aConstruction.get()) { - AttributeSelectionListPtr aFacesSelectionList = selectionList(LIST_ID()); - if (aFacesSelectionList.get() && aFacesSelectionList->size() == 0) - aFacesSelectionList->append(aSketchRes, std::shared_ptr()); + GeomAPI_Shape::ShapeType aShapeTypeToExplore = GeomAPI_Shape::FACE; + std::string aShapeTypeStr = "Face"; + switch(theBaseShapeType) { + case GeomAPI_Shape::VERTEX: { + aShapeTypeToExplore = GeomAPI_Shape::VERTEX; + aShapeTypeStr = "Vertex"; + break; + } + case GeomAPI_Shape::EDGE: + case GeomAPI_Shape::WIRE: { + aShapeTypeToExplore = GeomAPI_Shape::EDGE; + aShapeTypeStr = "Edge"; + break; + } + case GeomAPI_Shape::FACE: + case GeomAPI_Shape::SHELL: { + aShapeTypeToExplore = GeomAPI_Shape::FACE; + aShapeTypeStr = "Face"; + break; } } -} + // Store shapes. + int aShapeIndex = 1; + std::string aName = theName + aShapeTypeStr; + for(ListOfShape::const_iterator anIt = theShapes.cbegin(); anIt != theShapes.cend(); ++anIt) { + GeomShapePtr aShape = *anIt; + for(GeomAPI_ShapeExplorer anExp(aShape, aShapeTypeToExplore); anExp.more(); anExp.next()) { + GeomShapePtr aSubShape = anExp.current(); + if(theMapOfSubShapes->isBound(aSubShape)) { + aSubShape = theMapOfSubShapes->find(aSubShape); + } + std::ostringstream aStr; + aStr << aName << "_" << aShapeIndex++; + theResultBody->generated(aSubShape, aStr.str(), theTag++); + } + } +} \ No newline at end of file diff --git a/src/FeaturesPlugin/FeaturesPlugin_CompositeSketch.h b/src/FeaturesPlugin/FeaturesPlugin_CompositeSketch.h index 7f0a9e9ce..d2c7be54e 100644 --- a/src/FeaturesPlugin/FeaturesPlugin_CompositeSketch.h +++ b/src/FeaturesPlugin/FeaturesPlugin_CompositeSketch.h @@ -7,47 +7,32 @@ #ifndef FeaturesPlugin_CompositeSketch_H_ #define FeaturesPlugin_CompositeSketch_H_ -#include +#include "FeaturesPlugin.h" #include -#include +#include -/** \class FeaturesPlugin_CompositeSketch - * \ingroup Plugins - * \brief Interface for the composite sketch feature. - */ +/// \class FeaturesPlugin_CompositeSketch +/// \ingroup Plugins +/// \brief Interface for the composite sketch feature. class FeaturesPlugin_CompositeSketch : public ModelAPI_CompositeFeature { - public: +public: /// Attribute name of sketch feature. - inline static const std::string& SKETCH_OBJECT_ID() + inline static const std::string& SKETCH_ID() { - static const std::string MY_SKETCH_OBJECT_ID("sketch"); - return MY_SKETCH_OBJECT_ID; + static const std::string MY_SKETCH_ID("sketch"); + return MY_SKETCH_ID; } - /// Attribute name of sketch feature selection: needed for naming of the selected sketch. - inline static const std::string& SKETCH_SELECTION_ID() + /// Attribute name of base objects. + inline static const std::string& BASE_OBJECTS_ID() { - static const std::string MY_SKETCH_SELECTION_ID("sketch_selection"); - return MY_SKETCH_SELECTION_ID; + static const std::string MY_BASE_OBJECTS_ID("base"); + return MY_BASE_OBJECTS_ID; } - /// attribute name of references sketch entities list, it should contain a sketch result or - /// a pair a sketch result to sketch face - inline static const std::string& LIST_ID() - { - static const std::string MY_GROUP_LIST_ID("base"); - return MY_GROUP_LIST_ID; - } - - /// Creates a new part document if needed. - FEATURESPLUGIN_EXPORT virtual void execute(); - - /// Request for initialization of data model of the feature: adding all attributes. - FEATURESPLUGIN_EXPORT virtual void initAttributes(); - /// Appends a feature to the sketch sub-elements container. FEATURESPLUGIN_EXPORT virtual std::shared_ptr addFeature(std::string theID); @@ -64,30 +49,53 @@ class FeaturesPlugin_CompositeSketch : public ModelAPI_CompositeFeature FEATURESPLUGIN_EXPORT virtual bool isSub(ObjectPtr theObject) const; /// This method to inform that sub-feature is removed and must be removed from the internal data - /// structures of the owner (the remove from the document will be done outside just after) + /// structures of the owner (the remove from the document will be done outside just after). FEATURESPLUGIN_EXPORT virtual void removeFeature(std::shared_ptr theFeature); - /// removes also all sub-sketch + /// Removes also all sub-sketch. FEATURESPLUGIN_EXPORT virtual void erase(); protected: - FeaturesPlugin_CompositeSketch(){}; - - /// Define this function to init attributes for extrusion/revolution. - //virtual void initMakeSolidsAttributes() {}; + enum InitFlags { + InitSketchLauncher = 1 << 0, + InitBaseObjectsList = 1 << 1 + }; - /// Define this function to create solids from faces with extrusion/revolution. - virtual void makeSolid(const std::shared_ptr theFace, - std::shared_ptr& theMakeShape) {}; + FeaturesPlugin_CompositeSketch(){}; - /// Results naming. - void loadNamingDS(std::shared_ptr theResultBody, - const std::shared_ptr& theBaseShape, - const std::shared_ptr& theMakeShape); + /// Initializes composite sketch attributes. + void initCompositeSketchAttribtues(const int theInitFlags); - /// Set the sub-object to list of exturusion base. + /// Sets the sub-object to list of base. void setSketchObjectToList(); + /// \brief Returns list of base shapes. + /// \param[out] theBaseShapesList list of base shapes (warning: list not cleared). + /// \param[in] theIsMakeShells if true make shells from faces with shared edges. + void getBaseShapes(ListOfShape& theBaseShapesList, const bool theIsMakeShells = true); + + /// Checks make shape algo. + bool isMakeShapeValid(const std::shared_ptr theMakeShape); + + /// Stores result of generation. + void storeResult(const GeomShapePtr theBaseShape, + const std::shared_ptr theMakeShape, + const int theIndex = 0); + + /// Stores generation history. + void storeGenerationHistory(ResultBodyPtr theResultBody, + const GeomShapePtr theBaseShape, + const std::shared_ptr theMakeShape, + int& theTag); + + /// Used to store from and to shapes. + void storeShapes(ResultBodyPtr theResultBody, + const GeomAPI_Shape::ShapeType theBaseShapeType, + const std::shared_ptr theMapOfSubShapes, + const ListOfShape& theShapes, + const std::string theName, + int& theTag); + }; #endif diff --git a/src/FeaturesPlugin/FeaturesPlugin_Extrusion.cpp b/src/FeaturesPlugin/FeaturesPlugin_Extrusion.cpp index 0be521794..20b7c254a 100644 --- a/src/FeaturesPlugin/FeaturesPlugin_Extrusion.cpp +++ b/src/FeaturesPlugin/FeaturesPlugin_Extrusion.cpp @@ -6,21 +6,13 @@ #include "FeaturesPlugin_Extrusion.h" -#include -#include -#include -#include #include #include -#include #include -#include +#include +#include -#include #include -#include - -#include //================================================================================================= FeaturesPlugin_Extrusion::FeaturesPlugin_Extrusion() @@ -30,11 +22,7 @@ FeaturesPlugin_Extrusion::FeaturesPlugin_Extrusion() //================================================================================================= void FeaturesPlugin_Extrusion::initAttributes() { - AttributeSelectionListPtr aSelection = - std::dynamic_pointer_cast(data()->addAttribute( - LIST_ID(), ModelAPI_AttributeSelectionList::typeId())); - // extrusion works with faces always - aSelection->setSelectionType("FACE"); + initCompositeSketchAttribtues(InitBaseObjectsList); data()->addAttribute(CREATION_METHOD(), ModelAPI_AttributeString::typeId()); @@ -47,175 +35,95 @@ void FeaturesPlugin_Extrusion::initAttributes() data()->addAttribute(FROM_OBJECT_ID(), ModelAPI_AttributeSelection::typeId()); data()->addAttribute(FROM_OFFSET_ID(), ModelAPI_AttributeDouble::typeId()); + data()->addAttribute(DIRECTION_OBJECT_ID(), ModelAPI_AttributeSelection::typeId()); + ModelAPI_Session::get()->validators()->registerNotObligatory(getKind(), TO_OBJECT_ID()); ModelAPI_Session::get()->validators()->registerNotObligatory(getKind(), FROM_OBJECT_ID()); + ModelAPI_Session::get()->validators()->registerNotObligatory(getKind(), DIRECTION_OBJECT_ID()); - // Composite Sketch attribute - data()->addAttribute(FeaturesPlugin_CompositeSketch::SKETCH_OBJECT_ID(), - ModelAPI_AttributeReference::typeId()); - ModelAPI_Session::get()->validators()->registerNotObligatory(getKind(), - FeaturesPlugin_CompositeSketch::SKETCH_OBJECT_ID()); + initCompositeSketchAttribtues(InitSketchLauncher); } //================================================================================================= void FeaturesPlugin_Extrusion::execute() { - /// sub feature of the composite should be set in the base list - AttributeSelectionListPtr aFacesSelectionList = selectionList(LIST_ID()); - if (aFacesSelectionList.get() && !aFacesSelectionList->isInitialized()) { - AttributeReferencePtr aSketchAttr = reference(SKETCH_OBJECT_ID()); - if (aSketchAttr.get() && aSketchAttr->isInitialized()) - setSketchObjectToList(); + ListOfShape aBaseShapesList; + ListOfMakeShape aMakeShapesList; + + // Make extrusions. + if(!makeExtrusions(aBaseShapesList, aMakeShapesList)) { + return; } - // Getting faces. - ListOfShape aFacesList; - for(int anIndex = 0; anIndex < aFacesSelectionList->size(); anIndex++) { - AttributeSelectionPtr aFaceSel = aFacesSelectionList->value(anIndex); - std::shared_ptr aFaceShape = aFaceSel->value(); - if(aFaceShape.get() && !aFaceShape->isNull()) { // Getting face. - aFacesList.push_back(aFaceShape); - } else { // This may be the whole sketch result selected, check and get faces. - ResultPtr aContext = aFaceSel->context(); - std::shared_ptr aContextShape = aContext->shape(); - if(!aContextShape.get()) { - static const std::string aContextError = "Error: The selection context is bad."; - setError(aContextError); - return; - } - ResultConstructionPtr aConstruction = std::dynamic_pointer_cast(aContext); - if(!aConstruction.get()) { - static const std::string aFaceError = "Error: Can not find basis for extrusion."; - setError(aFaceError); - return; - } - int aFacesNum = aConstruction->facesNum(); - for(int aFaceIndex = 0; aFaceIndex < aFacesNum || aFacesNum == -1; aFaceIndex++) { - aFaceShape = std::dynamic_pointer_cast(aConstruction->face(aFaceIndex)); - aFacesList.push_back(aFaceShape); - } - } + // Store results. + int aResultIndex = 0; + ListOfShape::const_iterator aBaseIt = aBaseShapesList.cbegin(); + ListOfMakeShape::const_iterator anAlgoIt = aMakeShapesList.cbegin(); + for(; aBaseIt != aBaseShapesList.cend() && anAlgoIt != aMakeShapesList.cend(); ++aBaseIt, ++anAlgoIt) { + storeResult(*aBaseIt, *anAlgoIt, aResultIndex++); } + removeResults(aResultIndex); +} + +//================================================================================================= +bool FeaturesPlugin_Extrusion::makeExtrusions(ListOfShape& theBaseShapes, + ListOfMakeShape& theMakeShapes) +{ + theMakeShapes.clear(); + + /// Sub-feature of the composite should be set in the base list. + setSketchObjectToList(); + + // Getting base shapes. + getBaseShapes(theBaseShapes); + // Getting sizes. double aToSize = 0.0; double aFromSize = 0.0; if(string(CREATION_METHOD())->value() == "BySizes") { aToSize = real(TO_SIZE_ID())->value(); - aFromSize = real(FROM_SIZE_ID())->value(); + aFromSize = real(FROM_SIZE_ID())->value(); } else { aToSize = real(TO_OFFSET_ID())->value(); - aFromSize = real(FROM_OFFSET_ID())->value(); + aFromSize = real(FROM_OFFSET_ID())->value(); } // Getting bounding planes. - std::shared_ptr aToShape; - std::shared_ptr aFromShape; + GeomShapePtr aToShape; + GeomShapePtr aFromShape; if(string(CREATION_METHOD())->value() == "ByPlanesAndOffsets") { - std::shared_ptr anObjRef = selection(TO_OBJECT_ID()); - if(anObjRef.get() != NULL) { - aToShape = std::dynamic_pointer_cast(anObjRef->value()); - if(aToShape.get() == NULL && anObjRef->context().get() != NULL) { - aToShape = anObjRef->context()->shape(); + AttributeSelectionPtr aSelection = selection(TO_OBJECT_ID()); + if(aSelection.get()) { + aToShape = std::dynamic_pointer_cast(aSelection->value()); + if(!aToShape.get() && aSelection->context().get()) { + aToShape = aSelection->context()->shape(); } } - anObjRef = selection(FROM_OBJECT_ID()); - if(anObjRef.get() != NULL) { - aFromShape = std::dynamic_pointer_cast(anObjRef->value()); - if(aFromShape.get() == NULL && anObjRef->context().get() != NULL) { - aFromShape = anObjRef->context()->shape(); + aSelection = selection(FROM_OBJECT_ID()); + if(aSelection.get()) { + aFromShape = std::dynamic_pointer_cast(aSelection->value()); + if(!aFromShape.get() && aSelection->context().get()) { + aFromShape = aSelection->context()->shape(); } } } - // Searching faces with common edges. - ListOfShape aShells; - ListOfShape aFreeFaces; - std::shared_ptr aFacesCompound = GeomAlgoAPI_CompoundBuilder::compound(aFacesList); - GeomAlgoAPI_ShapeTools::combineShapes(aFacesCompound, GeomAPI_Shape::SHELL, aShells, aFreeFaces); - aShells.insert(aShells.end(), aFreeFaces.begin(), aFreeFaces.end()); - - // Generating result for each shell and face. - int aResultIndex = 0; - for(ListOfShape::const_iterator anIter = aShells.cbegin(); anIter != aShells.cend(); anIter++) { + // Generating result for each base shape. + for(ListOfShape::const_iterator anIter = theBaseShapes.cbegin(); anIter != theBaseShapes.cend(); anIter++) { std::shared_ptr aBaseShape = *anIter; - GeomAlgoAPI_Prism aPrismAlgo(aBaseShape, aToShape, aToSize, aFromShape, aFromSize); - if(!aPrismAlgo.isDone()) { - static const std::string aPrismAlgoError = "Error: Extrusion algorithm failed."; - setError(aPrismAlgoError); - aResultIndex = 0; - break; + std::shared_ptr aPrismAlgo(new GeomAlgoAPI_Prism(aBaseShape, + aToShape, aToSize, + aFromShape, aFromSize)); + if(!isMakeShapeValid(aPrismAlgo)) { + return false; } - // Check if shape is valid - if(!aPrismAlgo.shape().get() || aPrismAlgo.shape()->isNull()) { - static const std::string aShapeError = "Error: Resulting shape is Null."; - setError(aShapeError); - aResultIndex = 0; - break; - } - if(!aPrismAlgo.isValid()) { - std::string aPrismAlgoError = "Error: Resulting shape is not valid."; - setError(aPrismAlgoError); - aResultIndex = 0; - break; - } - - ResultBodyPtr aResultBody = document()->createBody(data(), aResultIndex); - loadNamingDS(aPrismAlgo, aResultBody, aBaseShape); - setResult(aResultBody, aResultIndex); - aResultIndex++; - } - - removeResults(aResultIndex); -} - -//================================================================================================= -void FeaturesPlugin_Extrusion::loadNamingDS(GeomAlgoAPI_Prism& thePrismAlgo, - std::shared_ptr theResultBody, - std::shared_ptr theBasis) -{ - //load result - theResultBody->storeGenerated(theBasis, thePrismAlgo.shape()); - - std::shared_ptr aSubShapes = thePrismAlgo.mapOfSubShapes(); - - //Insert lateral face : Face from Edge - const std::string aLatName = "LateralFace"; - const int aLatTag = 1; - theResultBody->loadAndOrientGeneratedShapes(&thePrismAlgo, theBasis, GeomAPI_Shape::EDGE, aLatTag, aLatName, *aSubShapes); - - //Insert to faces - int aToFaceIndex = 1; - const std::string aToName = "ToFace"; - int aToTag = 2; - const ListOfShape& aToFaces = thePrismAlgo.toShapes(); - for(ListOfShape::const_iterator anIt = aToFaces.cbegin(); anIt != aToFaces.cend(); anIt++) { - std::shared_ptr aToFace = *anIt; - if(aSubShapes->isBound(aToFace)) { - aToFace = aSubShapes->find(aToFace); - } - std::ostringstream aStr; - aStr << aToName << "_" << aToFaceIndex++; - theResultBody->generated(aToFace, aStr.str(), aToTag++); + theMakeShapes.push_back(aPrismAlgo); } - //Insert from faces - int aFromFaceIndex = 1; - const std::string aFromName = "FromFace"; - int aFromTag = aToTag > 10000 ? aToTag : 10000; - const ListOfShape& aFromFaces = thePrismAlgo.fromShapes(); - for(ListOfShape::const_iterator anIt = aFromFaces.cbegin(); anIt != aFromFaces.cend(); anIt++) { - std::shared_ptr aFromFace = *anIt; - if(aSubShapes->isBound(aFromFace)) { - aFromFace = aSubShapes->find(aFromFace); - } - std::ostringstream aStr; - aStr << aFromName << "_" << aFromFaceIndex++; - theResultBody->generated(aFromFace, aStr.str(), aFromTag++); - } + return true; } - diff --git a/src/FeaturesPlugin/FeaturesPlugin_Extrusion.h b/src/FeaturesPlugin/FeaturesPlugin_Extrusion.h index a9330faf2..f2a8fc177 100644 --- a/src/FeaturesPlugin/FeaturesPlugin_Extrusion.h +++ b/src/FeaturesPlugin/FeaturesPlugin_Extrusion.h @@ -7,110 +7,108 @@ #ifndef FeaturesPlugin_Extrusion_H_ #define FeaturesPlugin_Extrusion_H_ -#include -#include - -#include - -class GeomAPI_Shape; -class ModelAPI_ResultBody; - -/**\class FeaturesPlugin_Extrusion - * \ingroup Plugins - * \brief Feature for creation of extrusion from the planar face. - * - * Extrusion creates the lateral faces based on edges of the base face and - * the top and bottom faces equal to the base face or this faces can be projection on the - * bounding planes if they were set. Direction of extrusion is taken from the face - * plane or if the bounding faces were set then it will be from the bottom to the top plane. - */ -class FeaturesPlugin_Extrusion : public FeaturesPlugin_CompositeSketch +#include "FeaturesPlugin.h" + +#include "FeaturesPlugin_CompositeSketch.h" + +#include + +/// \class FeaturesPlugin_Extrusion +/// \ingroup Plugins +/// \brief Feature for creation of extrusion from the planar face. +/// Extrusion creates the lateral faces based on edges of the base face and +/// the top and bottom faces equal to the base face or this faces can be projection on the +/// bounding planes if they were set. Direction of extrusion is taken from the face +/// plane or if the bounding faces were set then it will be from the bottom to the top plane. +class FeaturesPlugin_Extrusion: public FeaturesPlugin_CompositeSketch { - public: - /// Extrusion kind +public: + /// Use plugin manager for features creation + FeaturesPlugin_Extrusion(); + + /// Feature kind. inline static const std::string& ID() { - static const std::string MY_EXTRUSION_ID("Extrusion"); - return MY_EXTRUSION_ID; + static const std::string MY_ID("Extrusion"); + return MY_ID; } - /// attribute name of an object to which the extrusion grows - inline static const std::string& AXIS_OBJECT_ID() + /// Attribute name for creation method. + inline static const std::string& CREATION_METHOD() { - static const std::string MY_TO_OBJECT_ID("axis_object"); - return MY_TO_OBJECT_ID; + static const std::string MY_CREATION_METHOD_ID("CreationMethod"); + return MY_CREATION_METHOD_ID; } - /// attribute name for creation method - inline static const std::string& CREATION_METHOD() + /// Attribute name of an object to which the extrusion grows. + inline static const std::string& DIRECTION_OBJECT_ID() { - static const std::string METHOD_ATTR("CreationMethod"); - return METHOD_ATTR; + static const std::string MY_DIRECTION_OBJECT_ID("direction_object"); + return MY_DIRECTION_OBJECT_ID; } - /// attribute name of extrusion size + /// Attribute name of extrusion to size. inline static const std::string& TO_SIZE_ID() { static const std::string MY_TO_SIZE_ID("to_size"); return MY_TO_SIZE_ID; } - /// attribute name of extrusion size + /// Attribute name of extrusion from size. inline static const std::string& FROM_SIZE_ID() { static const std::string MY_FROM_SIZE_ID("from_size"); return MY_FROM_SIZE_ID; } - /// attribute name of an object to which the extrusion grows + /// Attribute name of an object to which the extrusion grows. inline static const std::string& TO_OBJECT_ID() { static const std::string MY_TO_OBJECT_ID("to_object"); return MY_TO_OBJECT_ID; } - /// attribute name of extrusion offset + /// Attribute name of extrusion offset. inline static const std::string& TO_OFFSET_ID() { static const std::string MY_TO_OFFSET_ID("to_offset"); return MY_TO_OFFSET_ID; } - /// attribute name of tool object + /// Attribute name of an object from which the extrusion grows. inline static const std::string& FROM_OBJECT_ID() { static const std::string MY_FROM_OBJECT_ID("from_object"); return MY_FROM_OBJECT_ID; } - /// attribute name of extrusion offset + /// Attribute name of extrusion offset. inline static const std::string& FROM_OFFSET_ID() { static const std::string MY_FROM_OFFSET_ID("from_offset"); return MY_FROM_OFFSET_ID; } - /// Returns the kind of a feature + /// \return the kind of a feature. FEATURESPLUGIN_EXPORT virtual const std::string& getKind() { static std::string MY_KIND = FeaturesPlugin_Extrusion::ID(); return MY_KIND; } - /// Creates a new part document if needed - FEATURESPLUGIN_EXPORT virtual void execute(); - - /// Request for initialization of data model of the feature: adding all attributes + /// Request for initialization of data model of the feature: adding all attributes. FEATURESPLUGIN_EXPORT virtual void initAttributes(); - /// Use plugin manager for features creation - FeaturesPlugin_Extrusion(); + /// Creates a new part document if needed. + FEATURESPLUGIN_EXPORT virtual void execute(); -private: - /// Load Naming data structure of the feature to the document - void loadNamingDS(GeomAlgoAPI_Prism& thePrismAlgo, - std::shared_ptr theResultBody, - std::shared_ptr theBasis); +protected: + /// Generates extrusions. + /// \param[out] theBaseShapes list of base shapes. + /// \param[out] theMakeShapes list of according algos. + /// \return false in case one of algo failed. + bool makeExtrusions(ListOfShape& theBaseShapes, + ListOfMakeShape& theMakeShapes); }; #endif diff --git a/src/FeaturesPlugin/FeaturesPlugin_ExtrusionBoolean.cpp b/src/FeaturesPlugin/FeaturesPlugin_ExtrusionBoolean.cpp index bc514dcd6..4501a8191 100755 --- a/src/FeaturesPlugin/FeaturesPlugin_ExtrusionBoolean.cpp +++ b/src/FeaturesPlugin/FeaturesPlugin_ExtrusionBoolean.cpp @@ -4,86 +4,28 @@ // Created: 11 June 2015 // Author: Dmitry Bobylev -#include - -#include -#include -#include -#include -#include - -#include +#include "FeaturesPlugin_ExtrusionBoolean.h" //================================================================================================= -void FeaturesPlugin_ExtrusionBoolean::initMakeSolidsAttributes() +void FeaturesPlugin_ExtrusionBoolean::initAttributes() { - data()->addAttribute(CREATION_METHOD(), ModelAPI_AttributeString::typeId()); - - data()->addAttribute(TO_SIZE_ID(), ModelAPI_AttributeDouble::typeId()); - data()->addAttribute(FROM_SIZE_ID(), ModelAPI_AttributeDouble::typeId()); + FeaturesPlugin_Extrusion::initAttributes(); - data()->addAttribute(TO_OBJECT_ID(), ModelAPI_AttributeSelection::typeId()); - data()->addAttribute(TO_OFFSET_ID(), ModelAPI_AttributeDouble::typeId()); - - data()->addAttribute(FROM_OBJECT_ID(), ModelAPI_AttributeSelection::typeId()); - data()->addAttribute(FROM_OFFSET_ID(), ModelAPI_AttributeDouble::typeId()); - - ModelAPI_Session::get()->validators()->registerNotObligatory(getKind(), TO_OBJECT_ID()); - ModelAPI_Session::get()->validators()->registerNotObligatory(getKind(), FROM_OBJECT_ID()); + initBooleanAttributes(); } //================================================================================================= -void FeaturesPlugin_ExtrusionBoolean::makeSolids(const ListOfShape& theFaces, - ListOfShape& theResults, - ListOfMakeShape& theAlgos) +bool FeaturesPlugin_ExtrusionBoolean::makeGeneration(ListOfShape& theBaseShapes, + ListOfMakeShape& theMakeShapes) { - // Getting extrusion sizes. - double aToSize = 0.0; - double aFromSize = 0.0; - - if(string(CREATION_METHOD())->value() == "BySizes") { - aToSize = real(TO_SIZE_ID())->value(); - aFromSize = real(FROM_SIZE_ID())->value(); - } else { - aToSize = real(TO_OFFSET_ID())->value(); - aFromSize = real(FROM_OFFSET_ID())->value(); - } - - // Getting extrusion bounding planes. - std::shared_ptr aToShape; - std::shared_ptr aFromShape; - - if(string(CREATION_METHOD())->value() == "ByPlanesAndOffsets") { - std::shared_ptr anObjRef = selection(TO_OBJECT_ID()); - if(anObjRef.get() != NULL) { - aToShape = std::dynamic_pointer_cast(anObjRef->value()); - if(aToShape.get() == NULL && anObjRef->context().get() != NULL) { - aToShape = anObjRef->context()->shape(); - } - } - anObjRef = selection(FROM_OBJECT_ID()); - if(anObjRef.get() != NULL) { - aFromShape = std::dynamic_pointer_cast(anObjRef->value()); - if(aFromShape.get() == NULL && anObjRef->context().get() != NULL) { - aFromShape = anObjRef->context()->shape(); - } - } - } - - // Extrude faces. - theResults.clear(); - for(ListOfShape::const_iterator aFacesIt = theFaces.begin(); aFacesIt != theFaces.end(); aFacesIt++) { - std::shared_ptr aBaseShape = *aFacesIt; - std::shared_ptr aPrismAlgo = std::shared_ptr(new GeomAlgoAPI_Prism(aBaseShape, aToShape, aToSize, aFromShape, aFromSize)); + return makeExtrusions(theBaseShapes, theMakeShapes); +} - // Checking that the algorithm worked properly. - if(!aPrismAlgo->isDone() || !aPrismAlgo->shape().get() || aPrismAlgo->shape()->isNull() || - !aPrismAlgo->isValid()) { - setError("Error: Extrusion algorithm failed."); - theResults.clear(); - return; - } - theResults.push_back(aPrismAlgo->shape()); - theAlgos.push_back(aPrismAlgo); - } +//================================================================================================= +void FeaturesPlugin_ExtrusionBoolean::storeGenerationHistory(ResultBodyPtr theResultBody, + const GeomShapePtr theBaseShape, + const std::shared_ptr theMakeShape, + int& theTag) +{ + FeaturesPlugin_Extrusion::storeGenerationHistory(theResultBody, theBaseShape, theMakeShape, theTag); } diff --git a/src/FeaturesPlugin/FeaturesPlugin_ExtrusionBoolean.h b/src/FeaturesPlugin/FeaturesPlugin_ExtrusionBoolean.h index b9efd63f6..4e4cbad45 100644 --- a/src/FeaturesPlugin/FeaturesPlugin_ExtrusionBoolean.h +++ b/src/FeaturesPlugin/FeaturesPlugin_ExtrusionBoolean.h @@ -7,76 +7,30 @@ #ifndef FeaturesPlugin_ExtrusionBoolean_H_ #define FeaturesPlugin_ExtrusionBoolean_H_ -#include +#include "FeaturesPlugin_Extrusion.h" +#include "FeaturesPlugin_CompositeBoolean.h" -/** \class FeaturesPlugin_ExtrusionBoolean - * \ingroup Plugins - * \brief Interface for the composite extrusion feature. - */ -class FeaturesPlugin_ExtrusionBoolean : public FeaturesPlugin_CompositeBoolean +/// \class FeaturesPlugin_ExtrusionBoolean +/// \ingroup Plugins +/// \brief Interface for the composite extrusion feature. +class FeaturesPlugin_ExtrusionBoolean: public FeaturesPlugin_Extrusion, public FeaturesPlugin_CompositeBoolean { - public: - - /// attribute name for creation method - inline static const std::string& CREATION_METHOD() - { - static const std::string METHOD_ATTR("CreationMethod"); - return METHOD_ATTR; - } - - /// attribute name of extrusion size - inline static const std::string& TO_SIZE_ID() - { - static const std::string MY_TO_SIZE_ID("to_size"); - return MY_TO_SIZE_ID; - } - - /// attribute name of extrusion size - inline static const std::string& FROM_SIZE_ID() - { - static const std::string MY_FROM_SIZE_ID("from_size"); - return MY_FROM_SIZE_ID; - } - - /// attribute name of an object to which the extrusion grows. - inline static const std::string& TO_OBJECT_ID() - { - static const std::string MY_TO_OBJECT_ID("to_object"); - return MY_TO_OBJECT_ID; - } - - /// attribute name of extrusion offset - inline static const std::string& TO_OFFSET_ID() - { - static const std::string MY_TO_OFFSET_ID("to_offset"); - return MY_TO_OFFSET_ID; - } - - /// Attribute name of an object from which the extrusion grows. - inline static const std::string& FROM_OBJECT_ID() - { - static const std::string MY_FROM_OBJECT_ID("from_object"); - return MY_FROM_OBJECT_ID; - } - - /// attribute name of extrusion offset - inline static const std::string& FROM_OFFSET_ID() - { - static const std::string MY_FROM_OFFSET_ID("from_offset"); - return MY_FROM_OFFSET_ID; - } +public: + /// Request for initialization of data model of the feature: adding all attributes. + FEATURESPLUGIN_EXPORT virtual void initAttributes(); protected: - /// Init attributes for extrusion. - virtual void initMakeSolidsAttributes(); + FeaturesPlugin_ExtrusionBoolean(){}; - /// Create solids from faces with extrusion. - virtual void makeSolids(const ListOfShape& theFaces, - ListOfShape& theResults, - ListOfMakeShape& theAlgos); + // Creates extrusions. + bool makeGeneration(ListOfShape& theBaseShapes, + ListOfMakeShape& theMakeShapes); -protected: - FeaturesPlugin_ExtrusionBoolean(){}; + /// Stores generation history. + void storeGenerationHistory(ResultBodyPtr theResultBody, + const GeomShapePtr theBaseShape, + const std::shared_ptr theMakeShape, + int& theTag); }; #endif diff --git a/src/FeaturesPlugin/FeaturesPlugin_ExtrusionCut.cpp b/src/FeaturesPlugin/FeaturesPlugin_ExtrusionCut.cpp index 908986033..7b885df7a 100644 --- a/src/FeaturesPlugin/FeaturesPlugin_ExtrusionCut.cpp +++ b/src/FeaturesPlugin/FeaturesPlugin_ExtrusionCut.cpp @@ -6,7 +6,9 @@ #include "FeaturesPlugin_ExtrusionCut.h" +//================================================================================================= FeaturesPlugin_ExtrusionCut::FeaturesPlugin_ExtrusionCut() { - myBooleanOperationType = GeomAlgoAPI_Boolean::BOOL_CUT; + myFeature = this; + myOperationType = BOOL_CUT; } diff --git a/src/FeaturesPlugin/FeaturesPlugin_ExtrusionCut.h b/src/FeaturesPlugin/FeaturesPlugin_ExtrusionCut.h index fd78e8f6d..acfa643c8 100755 --- a/src/FeaturesPlugin/FeaturesPlugin_ExtrusionCut.h +++ b/src/FeaturesPlugin/FeaturesPlugin_ExtrusionCut.h @@ -7,17 +7,19 @@ #ifndef FeaturesPlugin_ExtrusionCut_H_ #define FeaturesPlugin_ExtrusionCut_H_ -#include +#include "FeaturesPlugin_ExtrusionBoolean.h" -/** \class FeaturesPlugin_ExtrusionCut - * \ingroup Plugins - * \brief This feature allows to create sketch, extrude faces from this sketch and - * cut result from other objects in a single operation. - */ +/// \class FeaturesPlugin_ExtrusionCut +/// \ingroup Plugins +/// \brief This feature allows to create sketch, extrude faces from this sketch and +/// cut result from other objects in a single operation. class FeaturesPlugin_ExtrusionCut : public FeaturesPlugin_ExtrusionBoolean { - public: - /// Feature kind. +public: + /// Use plugin manager for features creation. + FeaturesPlugin_ExtrusionCut(); + + /// Feature kind. inline static const std::string& ID() { static const std::string MY_EXTRUSION_ID("ExtrusionCut"); @@ -30,9 +32,6 @@ class FeaturesPlugin_ExtrusionCut : public FeaturesPlugin_ExtrusionBoolean static std::string MY_KIND = FeaturesPlugin_ExtrusionCut::ID(); return MY_KIND; } - - /// Use plugin manager for features creation. - FeaturesPlugin_ExtrusionCut(); }; #endif diff --git a/src/FeaturesPlugin/FeaturesPlugin_ExtrusionFuse.cpp b/src/FeaturesPlugin/FeaturesPlugin_ExtrusionFuse.cpp index a30db9205..956a02648 100644 --- a/src/FeaturesPlugin/FeaturesPlugin_ExtrusionFuse.cpp +++ b/src/FeaturesPlugin/FeaturesPlugin_ExtrusionFuse.cpp @@ -6,7 +6,9 @@ #include "FeaturesPlugin_ExtrusionFuse.h" +//================================================================================================= FeaturesPlugin_ExtrusionFuse::FeaturesPlugin_ExtrusionFuse() { - myBooleanOperationType = GeomAlgoAPI_Boolean::BOOL_FUSE; + myFeature = this; + myOperationType = BOOL_FUSE; } diff --git a/src/FeaturesPlugin/FeaturesPlugin_ExtrusionFuse.h b/src/FeaturesPlugin/FeaturesPlugin_ExtrusionFuse.h index 706e770db..5e7a3236f 100644 --- a/src/FeaturesPlugin/FeaturesPlugin_ExtrusionFuse.h +++ b/src/FeaturesPlugin/FeaturesPlugin_ExtrusionFuse.h @@ -7,17 +7,19 @@ #ifndef FeaturesPlugin_ExtrusionFuse_H_ #define FeaturesPlugin_ExtrusionFuse_H_ -#include +#include "FeaturesPlugin_ExtrusionBoolean.h" -/** \class FeaturesPlugin_ExtrusionFuse - * \ingroup Plugins - * \brief This feature allows to create sketch, extrude faces from this sketch and - * fuse result with other objects in a single operation. - */ +/// \class FeaturesPlugin_ExtrusionFuse +/// \ingroup Plugins +/// \brief This feature allows to create sketch, extrude faces from this sketch and +/// fuse result with other objects in a single operation. class FeaturesPlugin_ExtrusionFuse : public FeaturesPlugin_ExtrusionBoolean { - public: - /// Feature kind. +public: + /// Use plugin manager for features creation. + FeaturesPlugin_ExtrusionFuse(); + + /// Feature kind. inline static const std::string& ID() { static const std::string MY_EXTRUSION_ID("ExtrusionFuse"); @@ -30,9 +32,6 @@ class FeaturesPlugin_ExtrusionFuse : public FeaturesPlugin_ExtrusionBoolean static std::string MY_KIND = FeaturesPlugin_ExtrusionFuse::ID(); return MY_KIND; } - - /// Use plugin manager for features creation. - FeaturesPlugin_ExtrusionFuse(); }; #endif diff --git a/src/FeaturesPlugin/FeaturesPlugin_ExtrusionSketch.cpp b/src/FeaturesPlugin/FeaturesPlugin_ExtrusionSketch.cpp deleted file mode 100644 index 7854fc251..000000000 --- a/src/FeaturesPlugin/FeaturesPlugin_ExtrusionSketch.cpp +++ /dev/null @@ -1,87 +0,0 @@ -// Copyright (C) 2014-20xx CEA/DEN, EDF R&D - -// File: FeaturesPlugin_ExtrusionSketch.cpp -// Created: 11 September 2015 -// Author: Dmitry Bobylev - -#include - -#include -#include -#include -#include -#include - -#include - -//================================================================================================= -FeaturesPlugin_ExtrusionSketch::FeaturesPlugin_ExtrusionSketch() -{ -} - -//================================================================================================= -void FeaturesPlugin_ExtrusionSketch::initMakeSolidsAttributes() -{ - data()->addAttribute(CREATION_METHOD(), ModelAPI_AttributeString::typeId()); - - data()->addAttribute(TO_SIZE_ID(), ModelAPI_AttributeDouble::typeId()); - data()->addAttribute(FROM_SIZE_ID(), ModelAPI_AttributeDouble::typeId()); - - data()->addAttribute(TO_OBJECT_ID(), ModelAPI_AttributeSelection::typeId()); - data()->addAttribute(TO_OFFSET_ID(), ModelAPI_AttributeDouble::typeId()); - - data()->addAttribute(FROM_OBJECT_ID(), ModelAPI_AttributeSelection::typeId()); - data()->addAttribute(FROM_OFFSET_ID(), ModelAPI_AttributeDouble::typeId()); - - ModelAPI_Session::get()->validators()->registerNotObligatory(getKind(), TO_OBJECT_ID()); - ModelAPI_Session::get()->validators()->registerNotObligatory(getKind(), FROM_OBJECT_ID()); -} - -//================================================================================================= -void FeaturesPlugin_ExtrusionSketch::makeSolid(const std::shared_ptr theFace, - std::shared_ptr& theMakeShape) -{ - // Getting extrusion sizes. - double aToSize = 0.0; - double aFromSize = 0.0; - - if(string(CREATION_METHOD())->value() == "BySizes") { - aToSize = real(TO_SIZE_ID())->value(); - aFromSize = real(FROM_SIZE_ID())->value(); - } else { - aToSize = real(TO_OFFSET_ID())->value(); - aFromSize = real(FROM_OFFSET_ID())->value(); - } - - // Getting extrusion bounding planes. - std::shared_ptr aToShape; - std::shared_ptr aFromShape; - - if(string(CREATION_METHOD())->value() == "ByPlanesAndOffsets") { - std::shared_ptr anObjRef = selection(TO_OBJECT_ID()); - if(anObjRef.get() != NULL) { - aToShape = std::dynamic_pointer_cast(anObjRef->value()); - if(aToShape.get() == NULL && anObjRef->context().get() != NULL) { - aToShape = anObjRef->context()->shape(); - } - } - anObjRef = selection(FROM_OBJECT_ID()); - if(anObjRef.get() != NULL) { - aFromShape = std::dynamic_pointer_cast(anObjRef->value()); - if(aFromShape.get() == NULL && anObjRef->context().get() != NULL) { - aFromShape = anObjRef->context()->shape(); - } - } - } - - // Extrude face - std::shared_ptr aPrismAlgo(new GeomAlgoAPI_Prism(theFace, aToShape, aToSize, aFromShape, aFromSize)); - - // Checking that the algorithm worked properly. - if(!aPrismAlgo->isDone() || !aPrismAlgo->shape().get() || aPrismAlgo->shape()->isNull() || - !aPrismAlgo->isValid()) { - return; - } - - theMakeShape = aPrismAlgo; -} diff --git a/src/FeaturesPlugin/FeaturesPlugin_ExtrusionSketch.h b/src/FeaturesPlugin/FeaturesPlugin_ExtrusionSketch.h deleted file mode 100644 index fd6da45fc..000000000 --- a/src/FeaturesPlugin/FeaturesPlugin_ExtrusionSketch.h +++ /dev/null @@ -1,96 +0,0 @@ -// Copyright (C) 2014-20xx CEA/DEN, EDF R&D - -// File: FeaturesPlugin_ExtrusionSketch.h -// Created: 11 September 2015 -// Author: Dmitry Bobylev - -#ifndef FeaturesPlugin_ExtrusionSketch_H_ -#define FeaturesPlugin_ExtrusionSketch_H_ - -#include - -/** \class FeaturesPlugin_ExtrusionSketch - * \ingroup Plugins - * \brief This feature allows to create sketch and extrude faces from this sketch - * in a single operation. - */ -class FeaturesPlugin_ExtrusionSketch : public FeaturesPlugin_CompositeSketch -{ - public: - /// Feature kind. - inline static const std::string& ID() - { - static const std::string MY_EXTRUSION_ID("ExtrusionSketch"); - return MY_EXTRUSION_ID; - } - - /// \return the kind of a feature - FEATURESPLUGIN_EXPORT virtual const std::string& getKind() - { - static std::string MY_KIND = FeaturesPlugin_ExtrusionSketch::ID(); - return MY_KIND; - } - - /// attribute name for creation method - inline static const std::string& CREATION_METHOD() - { - static const std::string METHOD_ATTR("CreationMethod"); - return METHOD_ATTR; - } - - /// attribute name of extrusion size - inline static const std::string& TO_SIZE_ID() - { - static const std::string MY_TO_SIZE_ID("to_size"); - return MY_TO_SIZE_ID; - } - - /// attribute name of extrusion size - inline static const std::string& FROM_SIZE_ID() - { - static const std::string MY_FROM_SIZE_ID("from_size"); - return MY_FROM_SIZE_ID; - } - - /// attribute name of an object to which the extrusion grows. - inline static const std::string& TO_OBJECT_ID() - { - static const std::string MY_TO_OBJECT_ID("to_object"); - return MY_TO_OBJECT_ID; - } - - /// attribute name of extrusion offset - inline static const std::string& TO_OFFSET_ID() - { - static const std::string MY_TO_OFFSET_ID("to_offset"); - return MY_TO_OFFSET_ID; - } - - /// Attribute name of an object from which the extrusion grows. - inline static const std::string& FROM_OBJECT_ID() - { - static const std::string MY_FROM_OBJECT_ID("from_object"); - return MY_FROM_OBJECT_ID; - } - - /// attribute name of extrusion offset - inline static const std::string& FROM_OFFSET_ID() - { - static const std::string MY_FROM_OFFSET_ID("from_offset"); - return MY_FROM_OFFSET_ID; - } - -protected: - /// Init attributes for extrusion. - virtual void initMakeSolidsAttributes(); - - /// Create solid from face with extrusion. - virtual void makeSolid(const std::shared_ptr theFace, - std::shared_ptr& theMakeShape); - -public: - /// Use plugin manager for features creation. - FeaturesPlugin_ExtrusionSketch(); -}; - -#endif diff --git a/src/FeaturesPlugin/FeaturesPlugin_Plugin.cpp b/src/FeaturesPlugin/FeaturesPlugin_Plugin.cpp index 0fd2ba3b4..baa8a1150 100644 --- a/src/FeaturesPlugin/FeaturesPlugin_Plugin.cpp +++ b/src/FeaturesPlugin/FeaturesPlugin_Plugin.cpp @@ -4,7 +4,6 @@ #include #include -#include #include #include #include @@ -14,7 +13,6 @@ #include #include #include -#include #include #include #include @@ -41,6 +39,8 @@ FeaturesPlugin_Plugin::FeaturesPlugin_Plugin() new FeaturesPlugin_ValidatorTransform); aFactory->registerValidator("FeaturesPlugin_ValidatorExtrusionBase", new FeaturesPlugin_ValidatorExtrusionBase); + aFactory->registerValidator("FeaturesPlugin_ValidatorBaseForGeneration", + new FeaturesPlugin_ValidatorBaseForGeneration); aFactory->registerValidator("FeaturesPlugin_PipeLocationsValidator", new FeaturesPlugin_PipeLocationsValidator); @@ -78,10 +78,6 @@ FeaturePtr FeaturesPlugin_Plugin::createFeature(string theFeatureID) return FeaturePtr(new FeaturesPlugin_RevolutionCut); } else if (theFeatureID == FeaturesPlugin_RevolutionFuse::ID()) { return FeaturePtr(new FeaturesPlugin_RevolutionFuse); - } else if (theFeatureID == FeaturesPlugin_ExtrusionSketch::ID()) { - return FeaturePtr(new FeaturesPlugin_ExtrusionSketch); - } else if (theFeatureID == FeaturesPlugin_RevolutionSketch::ID()) { - return FeaturePtr(new FeaturesPlugin_RevolutionSketch); } // feature of such kind is not found return FeaturePtr(); diff --git a/src/FeaturesPlugin/FeaturesPlugin_Revolution.cpp b/src/FeaturesPlugin/FeaturesPlugin_Revolution.cpp index e71194aef..fb3d594ad 100644 --- a/src/FeaturesPlugin/FeaturesPlugin_Revolution.cpp +++ b/src/FeaturesPlugin/FeaturesPlugin_Revolution.cpp @@ -7,22 +7,16 @@ #include "FeaturesPlugin_Revolution.h" #include -#include +#include #include -#include -#include #include #include -#include -#include -#include -#include +#include + #include #include -#include - //================================================================================================= FeaturesPlugin_Revolution::FeaturesPlugin_Revolution() { @@ -31,11 +25,7 @@ FeaturesPlugin_Revolution::FeaturesPlugin_Revolution() //================================================================================================= void FeaturesPlugin_Revolution::initAttributes() { - AttributeSelectionListPtr aSelection = - std::dynamic_pointer_cast(data()->addAttribute( - LIST_ID(), ModelAPI_AttributeSelectionList::typeId())); - // revolution works with faces always - aSelection->setSelectionType("FACE"); + initCompositeSketchAttribtues(InitBaseObjectsList); data()->addAttribute(AXIS_OBJECT_ID(), ModelAPI_AttributeSelection::typeId()); @@ -53,185 +43,105 @@ void FeaturesPlugin_Revolution::initAttributes() ModelAPI_Session::get()->validators()->registerNotObligatory(getKind(), TO_OBJECT_ID()); ModelAPI_Session::get()->validators()->registerNotObligatory(getKind(), FROM_OBJECT_ID()); - // Composite Sketch attribute - data()->addAttribute(FeaturesPlugin_CompositeSketch::SKETCH_OBJECT_ID(), - ModelAPI_AttributeReference::typeId()); - ModelAPI_Session::get()->validators()->registerNotObligatory(getKind(), - FeaturesPlugin_CompositeSketch::SKETCH_OBJECT_ID()); + initCompositeSketchAttribtues(InitSketchLauncher); } //================================================================================================= void FeaturesPlugin_Revolution::execute() { - /// sub feature of the composite should be set in the base list - AttributeSelectionListPtr aFacesSelectionList = selectionList(LIST_ID()); - if (aFacesSelectionList.get() && !aFacesSelectionList->isInitialized()) { - AttributeReferencePtr aSketchAttr = reference(SKETCH_OBJECT_ID()); - if (aSketchAttr.get() && aSketchAttr->isInitialized()) - setSketchObjectToList(); + ListOfShape aBaseShapesList; + ListOfMakeShape aMakeShapesList; + + // Make revolutions. + if(!makeRevolutions(aBaseShapesList, aMakeShapesList)) { + return; } - // Getting faces. - ListOfShape aFacesList; - aFacesSelectionList = selectionList(LIST_ID()); - for(int anIndex = 0; anIndex < aFacesSelectionList->size(); anIndex++) { - AttributeSelectionPtr aFaceSel = aFacesSelectionList->value(anIndex); - std::shared_ptr aFaceShape = aFaceSel->value(); - if(aFaceShape.get() && !aFaceShape->isNull()) { // Getting face. - aFacesList.push_back(aFaceShape); - } else { // This may be the whole sketch result selected, check and get faces. - ResultPtr aContext = aFaceSel->context(); - std::shared_ptr aContextShape = aContext->shape(); - if(!aContextShape.get()) { - static const std::string aContextError = "Error: The selection context is bad."; - setError(aContextError); - return; - } - ResultConstructionPtr aConstruction = std::dynamic_pointer_cast(aContext); - if(!aConstruction.get()) { - static const std::string aFaceError = "Error: Can not find basis for revolution."; - setError(aFaceError); - return; - } - int aFacesNum = aConstruction->facesNum(); - for(int aFaceIndex = 0; aFaceIndex < aFacesNum || aFacesNum == -1; aFaceIndex++) { - aFaceShape = std::dynamic_pointer_cast(aConstruction->face(aFaceIndex)); - aFacesList.push_back(aFaceShape); - } - } + // Store results. + int aResultIndex = 0; + ListOfShape::const_iterator aBaseIt = aBaseShapesList.cbegin(); + ListOfMakeShape::const_iterator anAlgoIt = aMakeShapesList.cbegin(); + for(; aBaseIt != aBaseShapesList.cend() && anAlgoIt != aMakeShapesList.cend(); ++aBaseIt, ++anAlgoIt) { + storeResult(*aBaseIt, *anAlgoIt, aResultIndex++); } + removeResults(aResultIndex); +} + +//================================================================================================= +bool FeaturesPlugin_Revolution::makeRevolutions(ListOfShape& theBaseShapes, + ListOfMakeShape& theMakeShapes) +{ + theMakeShapes.clear(); + + /// Sub-feature of the composite should be set in the base list. + setSketchObjectToList(); + + // Getting base shapes. + getBaseShapes(theBaseShapes); + //Getting axis. std::shared_ptr anAxis; std::shared_ptr anEdge; - std::shared_ptr anObjRef = selection(AXIS_OBJECT_ID()); - if(anObjRef && anObjRef->value() && anObjRef->value()->isEdge()) { - anEdge = std::shared_ptr(new GeomAPI_Edge(anObjRef->value())); - } else if(anObjRef->context() && anObjRef->context()->shape() && anObjRef->context()->shape()->isEdge()) { - anEdge = std::shared_ptr(new GeomAPI_Edge(anObjRef->context()->shape())); + AttributeSelectionPtr aSelection = selection(AXIS_OBJECT_ID()); + if(aSelection.get() && aSelection->value().get() && aSelection->value()->isEdge()) { + anEdge = std::shared_ptr(new GeomAPI_Edge(aSelection->value())); + } else if(aSelection->context().get() && + aSelection->context()->shape().get() && + aSelection->context()->shape()->isEdge()) { + anEdge = std::shared_ptr(new GeomAPI_Edge(aSelection->context()->shape())); } - if(anEdge) { - anAxis = std::shared_ptr(new GeomAPI_Ax1(anEdge->line()->location(), anEdge->line()->direction())); + if(anEdge.get()) { + anAxis = std::shared_ptr(new GeomAPI_Ax1(anEdge->line()->location(), + anEdge->line()->direction())); } // Getting angles. - double aToAngle = real(TO_ANGLE_ID())->value(); - double aFromAngle = real(FROM_ANGLE_ID())->value(); + double aToAngle = 0.0; + double aFromAngle = 0.0; if(string(CREATION_METHOD())->value() == "ByAngles") { aToAngle = real(TO_ANGLE_ID())->value(); - aFromAngle = real(FROM_ANGLE_ID())->value(); + aFromAngle = real(FROM_ANGLE_ID())->value(); } else { aToAngle = real(TO_OFFSET_ID())->value(); - aFromAngle = real(FROM_OFFSET_ID())->value(); + aFromAngle = real(FROM_OFFSET_ID())->value(); } // Getting bounding planes. - std::shared_ptr aToShape; - std::shared_ptr aFromShape; + GeomShapePtr aToShape; + GeomShapePtr aFromShape; if(string(CREATION_METHOD())->value() == "ByPlanesAndOffsets") { - anObjRef = selection(TO_OBJECT_ID()); - if(anObjRef.get() != NULL) { - aToShape = std::dynamic_pointer_cast(anObjRef->value()); - if(aToShape.get() == NULL && anObjRef->context().get() != NULL) { - aToShape = anObjRef->context()->shape(); + aSelection = selection(TO_OBJECT_ID()); + if(aSelection.get()) { + aToShape = std::dynamic_pointer_cast(aSelection->value()); + if(!aToShape.get() && aSelection->context().get()) { + aToShape = aSelection->context()->shape(); } } - anObjRef = selection(FROM_OBJECT_ID()); - if(anObjRef.get() != NULL) { - aFromShape = std::dynamic_pointer_cast(anObjRef->value()); - if(aFromShape.get() == NULL && anObjRef->context().get() != NULL) { - aFromShape = anObjRef->context()->shape(); + aSelection = selection(FROM_OBJECT_ID()); + if(aSelection.get()) { + aFromShape = std::dynamic_pointer_cast(aSelection->value()); + if(!aFromShape.get() && aSelection->context().get()) { + aFromShape = aSelection->context()->shape(); } } } - // Searching faces with common edges. - ListOfShape aShells; - ListOfShape aFreeFaces; - std::shared_ptr aFacesCompound = GeomAlgoAPI_CompoundBuilder::compound(aFacesList); - GeomAlgoAPI_ShapeTools::combineShapes(aFacesCompound, GeomAPI_Shape::SHELL, aShells, aFreeFaces); - aShells.insert(aShells.end(), aFreeFaces.begin(), aFreeFaces.end()); - - // Generating result for each shell and face. - int aResultIndex = 0; - for(ListOfShape::const_iterator anIter = aShells.cbegin(); anIter != aShells.cend(); anIter++) { - std::shared_ptr aBaseShape = *anIter; - - GeomAlgoAPI_Revolution aRevolAlgo(aBaseShape, anAxis, aToShape, aToAngle, aFromShape, aFromAngle); - if(!aRevolAlgo.isDone()) { - static const std::string aPrismAlgoError = "Error: Revolution algorithm failed."; - setError(aPrismAlgoError); - aResultIndex = 0; - break; - } + // Generating result for each base shape. + for(ListOfShape::const_iterator anIter = theBaseShapes.cbegin(); anIter != theBaseShapes.cend(); anIter++) { + GeomShapePtr aBaseShape = *anIter; - // Check if shape is valid - if(!aRevolAlgo.shape().get() || aRevolAlgo.shape()->isNull()) { - static const std::string aShapeError = "Error: Resulting shape is Null."; - setError(aShapeError); - aResultIndex = 0; - break; - } - if(!aRevolAlgo.isValid()) { - std::string aPrismAlgoError = "Error: Resulting shape is not valid."; - setError(aPrismAlgoError); - aResultIndex = 0; - break; + std::shared_ptr aRevolAlgo(new GeomAlgoAPI_Revolution(aBaseShape, anAxis, + aToShape, aToAngle, + aFromShape, aFromAngle)); + if(!isMakeShapeValid(aRevolAlgo)) { + return false; } - ResultBodyPtr aResultBody = document()->createBody(data(), aResultIndex); - loadNamingDS(aRevolAlgo, aResultBody, aBaseShape); - setResult(aResultBody, aResultIndex); - aResultIndex++; + theMakeShapes.push_back(aRevolAlgo); } - removeResults(aResultIndex); -} - -//================================================================================================= -void FeaturesPlugin_Revolution::loadNamingDS(GeomAlgoAPI_Revolution& theRevolAlgo, - std::shared_ptr theResultBody, - std::shared_ptr theBasis) -{ - //load result - theResultBody->storeGenerated(theBasis, theRevolAlgo.shape()); - - std::shared_ptr aSubShapes = theRevolAlgo.mapOfSubShapes(); - - //Insert lateral face : Face from Edge - const std::string aLatName = "LateralFace"; - const int aLatTag = 1; - theResultBody->loadAndOrientGeneratedShapes(&theRevolAlgo, theBasis, GeomAPI_Shape::EDGE, aLatTag, aLatName, *aSubShapes); - - //Insert to faces - int aToFaceIndex = 1; - const std::string aToName = "ToFace"; - int aToTag = 2; - const ListOfShape& aToFaces = theRevolAlgo.toShapes(); - for(ListOfShape::const_iterator anIt = aToFaces.cbegin(); anIt != aToFaces.cend(); anIt++) { - std::shared_ptr aToFace = *anIt; - if(aSubShapes->isBound(aToFace)) { - aToFace = aSubShapes->find(aToFace); - } - std::ostringstream aStr; - aStr << aToName << "_" << aToFaceIndex++; - theResultBody->generated(aToFace, aStr.str(), aToTag++); - } - - //Insert from faces - int aFromFaceIndex = 1; - const std::string aFromName = "FromFace"; - int aFromTag = aToTag > 10000 ? aToTag : 10000; - const ListOfShape& aFromFaces = theRevolAlgo.fromShapes(); - for(ListOfShape::const_iterator anIt = aFromFaces.cbegin(); anIt != aFromFaces.cend(); anIt++) { - std::shared_ptr aFromFace = *anIt; - if(aSubShapes->isBound(aFromFace)) { - aFromFace = aSubShapes->find(aFromFace); - } - std::ostringstream aStr; - aStr << aFromName << "_" << aFromFaceIndex++; - theResultBody->generated(aFromFace, aStr.str(), aFromTag++); - } + return true; } diff --git a/src/FeaturesPlugin/FeaturesPlugin_Revolution.h b/src/FeaturesPlugin/FeaturesPlugin_Revolution.h index 7c16ec3b2..f31e4c917 100644 --- a/src/FeaturesPlugin/FeaturesPlugin_Revolution.h +++ b/src/FeaturesPlugin/FeaturesPlugin_Revolution.h @@ -7,52 +7,49 @@ #ifndef FeaturesPlugin_Revolution_H_ #define FeaturesPlugin_Revolution_H_ -#include +#include "FeaturesPlugin.h" -#include -#include +#include "FeaturesPlugin_CompositeSketch.h" -class GeomAPI_Shape; -class ModelAPI_ResultBody; +#include -/** \class FeaturesPlugin_Revolution - * \ingroup Plugins - * \brief Feature for creation of revolution from the planar face. - * Revolution creates the lateral faces based on edges of the base face and - * the start and end faces and/or start and end angles. - */ -class FeaturesPlugin_Revolution : public FeaturesPlugin_CompositeSketch +/// \class FeaturesPlugin_Revolution +/// \ingroup Plugins +/// \brief Feature for creation of revolution from the planar face. +/// Revolution creates the lateral faces based on edges of the base face and +/// the start and end faces and/or start and end angles. +class FeaturesPlugin_Revolution: public FeaturesPlugin_CompositeSketch { - public: - /// Revolution kind. +public: + /// Feature kind. inline static const std::string& ID() { - static const std::string MY_REVOLUTION_ID("Revolution"); - return MY_REVOLUTION_ID; + static const std::string MY_ID("Revolution"); + return MY_ID; } - /// Attribute name of an revolution axis. - inline static const std::string& AXIS_OBJECT_ID() + /// Attribute name for creation method. + inline static const std::string& CREATION_METHOD() { - static const std::string MY_AXIS_ID("axis_object"); - return MY_AXIS_ID; + static const std::string MY_CREATION_METHOD_ID("CreationMethod"); + return MY_CREATION_METHOD_ID; } - /// attribute name for creation method - inline static const std::string& CREATION_METHOD() + /// Attribute name of an revolution axis. + inline static const std::string& AXIS_OBJECT_ID() { - static const std::string METHOD_ATTR("CreationMethod"); - return METHOD_ATTR; + static const std::string MY_AXIS_OBJECT_ID("axis_object"); + return MY_AXIS_OBJECT_ID; } - /// Attribute name of revolution angle. + /// Attribute name of revolution to angle. inline static const std::string& TO_ANGLE_ID() { static const std::string MY_TO_ANGLE_ID("to_angle"); return MY_TO_ANGLE_ID; } - /// Attribute name of revolution angle. + /// Attribute name of revolution from angle. inline static const std::string& FROM_ANGLE_ID() { static const std::string MY_FROM_ANGLE_ID("from_angle"); @@ -66,21 +63,21 @@ class FeaturesPlugin_Revolution : public FeaturesPlugin_CompositeSketch return MY_TO_OBJECT_ID; } - /// attribute name of extrusion offset. + /// Attribute name of revolution offset. inline static const std::string& TO_OFFSET_ID() { static const std::string MY_TO_OFFSET_ID("to_offset"); return MY_TO_OFFSET_ID; } - /// Attribute name of tool object. + /// Attribute name of an object from which the revolution grows. inline static const std::string& FROM_OBJECT_ID() { static const std::string MY_FROM_OBJECT_ID("from_object"); return MY_FROM_OBJECT_ID; } - /// attribute name of extrusion offset. + /// Attribute name of revolution offset. inline static const std::string& FROM_OFFSET_ID() { static const std::string MY_FROM_OFFSET_ID("from_offset"); @@ -103,11 +100,13 @@ class FeaturesPlugin_Revolution : public FeaturesPlugin_CompositeSketch /// Use plugin manager for features creation. FeaturesPlugin_Revolution(); -private: - /// Load Naming data structure of the feature to the document. - void loadNamingDS(GeomAlgoAPI_Revolution& theRevolAlgo, - std::shared_ptr theResultBody, - std::shared_ptr theBasis); + protected: + /// Generates revolutions. + /// \param[out] theBaseShapes list of base shapes. + /// \param[out] theMakeShapes list of according algos. + /// \return false in case one of algo failed. + bool makeRevolutions(ListOfShape& theBaseShapes, + ListOfMakeShape& theMakeShapes); }; #endif diff --git a/src/FeaturesPlugin/FeaturesPlugin_RevolutionBoolean.cpp b/src/FeaturesPlugin/FeaturesPlugin_RevolutionBoolean.cpp index aaade0a86..479fd51e9 100644 --- a/src/FeaturesPlugin/FeaturesPlugin_RevolutionBoolean.cpp +++ b/src/FeaturesPlugin/FeaturesPlugin_RevolutionBoolean.cpp @@ -4,103 +4,28 @@ // Created: 11 June 2015 // Author: Dmitry Bobylev -#include - -#include -#include -#include -#include -#include - -#include -#include -#include +#include "FeaturesPlugin_RevolutionBoolean.h" //================================================================================================= -void FeaturesPlugin_RevolutionBoolean::initMakeSolidsAttributes() +void FeaturesPlugin_RevolutionBoolean::initAttributes() { - data()->addAttribute(FeaturesPlugin_RevolutionBoolean::AXIS_OBJECT_ID(), ModelAPI_AttributeSelection::typeId()); - - data()->addAttribute(CREATION_METHOD(), ModelAPI_AttributeString::typeId()); - - data()->addAttribute(TO_ANGLE_ID(), ModelAPI_AttributeDouble::typeId()); - data()->addAttribute(FROM_ANGLE_ID(), ModelAPI_AttributeDouble::typeId()); + FeaturesPlugin_Revolution::initAttributes(); - data()->addAttribute(TO_OBJECT_ID(), ModelAPI_AttributeSelection::typeId()); - data()->addAttribute(TO_OFFSET_ID(), ModelAPI_AttributeDouble::typeId()); - - data()->addAttribute(FROM_OBJECT_ID(), ModelAPI_AttributeSelection::typeId()); - data()->addAttribute(FROM_OFFSET_ID(), ModelAPI_AttributeDouble::typeId()); - - ModelAPI_Session::get()->validators()->registerNotObligatory(getKind(), TO_OBJECT_ID()); - ModelAPI_Session::get()->validators()->registerNotObligatory(getKind(), FROM_OBJECT_ID()); + initBooleanAttributes(); } //================================================================================================= -void FeaturesPlugin_RevolutionBoolean::makeSolids(const ListOfShape& theFaces, - ListOfShape& theResults, - ListOfMakeShape& theAlgos) +bool FeaturesPlugin_RevolutionBoolean::makeGeneration(ListOfShape& theBaseShapes, + ListOfMakeShape& theMakeShapes) { - //Getting axis. - std::shared_ptr anAxis; - std::shared_ptr anEdge; - std::shared_ptr anObjRef = selection(FeaturesPlugin_RevolutionBoolean::AXIS_OBJECT_ID()); - if(anObjRef && anObjRef->value() && anObjRef->value()->isEdge()) { - anEdge = std::shared_ptr(new GeomAPI_Edge(anObjRef->value())); - } else if(anObjRef->context() && anObjRef->context()->shape() && anObjRef->context()->shape()->isEdge()) { - anEdge = std::shared_ptr(new GeomAPI_Edge(anObjRef->context()->shape())); - } - if(anEdge) { - anAxis = std::shared_ptr(new GeomAPI_Ax1(anEdge->line()->location(), anEdge->line()->direction())); - } - - // Getting revolution angles. - double aToAngle = real(TO_ANGLE_ID())->value(); - double aFromAngle = real(FROM_ANGLE_ID())->value(); - - if(string(CREATION_METHOD())->value() == "ByAngles") { - aToAngle = real(TO_ANGLE_ID())->value(); - aFromAngle = real(FROM_ANGLE_ID())->value(); - } else { - aToAngle = real(TO_OFFSET_ID())->value(); - aFromAngle = real(FROM_OFFSET_ID())->value(); - } - - // Getting revolution bounding planes. - std::shared_ptr aToShape; - std::shared_ptr aFromShape; - - if(string(CREATION_METHOD())->value() == "ByPlanesAndOffsets") { - anObjRef = selection(TO_OBJECT_ID()); - if(anObjRef.get() != NULL) { - aToShape = std::dynamic_pointer_cast(anObjRef->value()); - if(aToShape.get() == NULL && anObjRef->context().get() != NULL) { - aToShape = anObjRef->context()->shape(); - } - } - anObjRef = selection(FROM_OBJECT_ID()); - if(anObjRef.get() != NULL) { - aFromShape = std::dynamic_pointer_cast(anObjRef->value()); - if(aFromShape.get() == NULL && anObjRef->context().get() != NULL) { - aFromShape = anObjRef->context()->shape(); - } - } - } - - // Revol faces. - theResults.clear(); - for(ListOfShape::const_iterator aFacesIt = theFaces.begin(); aFacesIt != theFaces.end(); aFacesIt++) { - std::shared_ptr aBaseShape = *aFacesIt; - std::shared_ptr aRevolAlgo = std::shared_ptr(new GeomAlgoAPI_Revolution(aBaseShape, anAxis, aToShape, aToAngle, aFromShape, aFromAngle)); + return makeRevolutions(theBaseShapes, theMakeShapes); +} - // Checking that the algorithm worked properly. - if(!aRevolAlgo->isDone() || !aRevolAlgo->shape().get() || aRevolAlgo->shape()->isNull() || - !aRevolAlgo->isValid()) { - setError("Error: Revolution algorithm failed."); - theResults.clear(); - return; - } - theResults.push_back(aRevolAlgo->shape()); - theAlgos.push_back(aRevolAlgo); - } +//================================================================================================= +void FeaturesPlugin_RevolutionBoolean::storeGenerationHistory(ResultBodyPtr theResultBody, + const GeomShapePtr theBaseShape, + const std::shared_ptr theMakeShape, + int& theTag) +{ + FeaturesPlugin_Revolution::storeGenerationHistory(theResultBody, theBaseShape, theMakeShape, theTag); } diff --git a/src/FeaturesPlugin/FeaturesPlugin_RevolutionBoolean.h b/src/FeaturesPlugin/FeaturesPlugin_RevolutionBoolean.h index b645190f7..fc0252ba1 100644 --- a/src/FeaturesPlugin/FeaturesPlugin_RevolutionBoolean.h +++ b/src/FeaturesPlugin/FeaturesPlugin_RevolutionBoolean.h @@ -7,82 +7,30 @@ #ifndef FeaturesPlugin_RevolutionBoolean_H_ #define FeaturesPlugin_RevolutionBoolean_H_ -#include +#include "FeaturesPlugin_Revolution.h" +#include "FeaturesPlugin_CompositeBoolean.h" -/** \class FeaturesPlugin_RevolutionBoolean - * \ingroup Plugins - * \brief Interface for the composite revolution feature. - */ -class FeaturesPlugin_RevolutionBoolean : public FeaturesPlugin_CompositeBoolean +/// \class FeaturesPlugin_RevolutionBoolean +/// \ingroup Plugins +/// \brief Interface for the composite revolution feature. +class FeaturesPlugin_RevolutionBoolean : public FeaturesPlugin_Revolution, public FeaturesPlugin_CompositeBoolean { public: - /// Attribute name of an revolution axis. - inline static const std::string& AXIS_OBJECT_ID() - { - static const std::string MY_AXIS_ID("axis_object"); - return MY_AXIS_ID; - } - - /// attribute name for creation method - inline static const std::string& CREATION_METHOD() - { - static const std::string METHOD_ATTR("CreationMethod"); - return METHOD_ATTR; - } - - /// Attribute name of revolution to angle. - inline static const std::string& TO_ANGLE_ID() - { - static const std::string MY_TO_ANGLE_ID("to_angle"); - return MY_TO_ANGLE_ID; - } - - /// Attribute name of revolution from angle. - inline static const std::string& FROM_ANGLE_ID() - { - static const std::string MY_FROM_ANGLE_ID("from_angle"); - return MY_FROM_ANGLE_ID; - } - - /// Attribute name of an object to which the revolution grows. - inline static const std::string& TO_OBJECT_ID() - { - static const std::string MY_TO_OBJECT_ID("to_object"); - return MY_TO_OBJECT_ID; - } - - /// Attribute name of extrusion offset. - inline static const std::string& TO_OFFSET_ID() - { - static const std::string MY_TO_OFFSET_ID("to_offset"); - return MY_TO_OFFSET_ID; - } - - /// Attribute name of an object from which the revolution grows. - inline static const std::string& FROM_OBJECT_ID() - { - static const std::string MY_FROM_OBJECT_ID("from_object"); - return MY_FROM_OBJECT_ID; - } - - /// Attribute name of extrusion offset. - inline static const std::string& FROM_OFFSET_ID() - { - static const std::string MY_FROM_OFFSET_ID("from_offset"); - return MY_FROM_OFFSET_ID; - } + /// Request for initialization of data model of the feature: adding all attributes. + FEATURESPLUGIN_EXPORT virtual void initAttributes(); protected: - /// Init attributes for revolution. - virtual void initMakeSolidsAttributes(); + FeaturesPlugin_RevolutionBoolean(){}; - /// Create solids from faces with revolution. - virtual void makeSolids(const ListOfShape& theFaces, - ListOfShape& theResults, - ListOfMakeShape& theAlgos); + // Creates revolutions. + bool makeGeneration(ListOfShape& theBaseShapes, + ListOfMakeShape& theMakeShapes); -protected: - FeaturesPlugin_RevolutionBoolean(){}; + /// Stores generation history. + void storeGenerationHistory(ResultBodyPtr theResultBody, + const GeomShapePtr theBaseShape, + const std::shared_ptr theMakeShape, + int& theTag); }; #endif diff --git a/src/FeaturesPlugin/FeaturesPlugin_RevolutionCut.cpp b/src/FeaturesPlugin/FeaturesPlugin_RevolutionCut.cpp index 521e7337b..7685a77cb 100644 --- a/src/FeaturesPlugin/FeaturesPlugin_RevolutionCut.cpp +++ b/src/FeaturesPlugin/FeaturesPlugin_RevolutionCut.cpp @@ -6,7 +6,9 @@ #include "FeaturesPlugin_RevolutionCut.h" +//================================================================================================= FeaturesPlugin_RevolutionCut::FeaturesPlugin_RevolutionCut() { - myBooleanOperationType = GeomAlgoAPI_Boolean::BOOL_CUT; + myFeature = this; + myOperationType = BOOL_CUT; } diff --git a/src/FeaturesPlugin/FeaturesPlugin_RevolutionCut.h b/src/FeaturesPlugin/FeaturesPlugin_RevolutionCut.h index 3c1340262..481cfd995 100644 --- a/src/FeaturesPlugin/FeaturesPlugin_RevolutionCut.h +++ b/src/FeaturesPlugin/FeaturesPlugin_RevolutionCut.h @@ -7,16 +7,18 @@ #ifndef FeaturesPlugin_RevolutionCut_H_ #define FeaturesPlugin_RevolutionCut_H_ -#include +#include "FeaturesPlugin_RevolutionBoolean.h" -/** \class FeaturesPlugin_RevolutionCut - * \ingroup Plugins - * \brief This feature allows to create sketch, revol faces from this sketch and - * cut result from other objects in a single operation. - */ +/// \class FeaturesPlugin_RevolutionCut +/// \ingroup Plugins +/// \brief This feature allows to create sketch, revol faces from this sketch and +/// cut result from other objects in a single operation. class FeaturesPlugin_RevolutionCut : public FeaturesPlugin_RevolutionBoolean { - public: +public: + /// Use plugin manager for features creation. + FeaturesPlugin_RevolutionCut(); + /// Feature kind. inline static const std::string& ID() { @@ -30,9 +32,6 @@ class FeaturesPlugin_RevolutionCut : public FeaturesPlugin_RevolutionBoolean static std::string MY_KIND = FeaturesPlugin_RevolutionCut::ID(); return MY_KIND; } - - /// Use plugin manager for features creation. - FeaturesPlugin_RevolutionCut(); }; #endif diff --git a/src/FeaturesPlugin/FeaturesPlugin_RevolutionFuse.cpp b/src/FeaturesPlugin/FeaturesPlugin_RevolutionFuse.cpp index a4efacba7..8bed6dad7 100644 --- a/src/FeaturesPlugin/FeaturesPlugin_RevolutionFuse.cpp +++ b/src/FeaturesPlugin/FeaturesPlugin_RevolutionFuse.cpp @@ -6,7 +6,9 @@ #include "FeaturesPlugin_RevolutionFuse.h" +//================================================================================================= FeaturesPlugin_RevolutionFuse::FeaturesPlugin_RevolutionFuse() { - myBooleanOperationType = GeomAlgoAPI_Boolean::BOOL_FUSE; + myFeature = this; + myOperationType = BOOL_FUSE; } diff --git a/src/FeaturesPlugin/FeaturesPlugin_RevolutionFuse.h b/src/FeaturesPlugin/FeaturesPlugin_RevolutionFuse.h index 75f16aa67..bdc7f8e57 100644 --- a/src/FeaturesPlugin/FeaturesPlugin_RevolutionFuse.h +++ b/src/FeaturesPlugin/FeaturesPlugin_RevolutionFuse.h @@ -7,17 +7,19 @@ #ifndef FeaturesPlugin_RevolutionFuse_H_ #define FeaturesPlugin_RevolutionFuse_H_ -#include +#include "FeaturesPlugin_RevolutionBoolean.h" -/** \class FeaturesPlugin_RevolutionFuse - * \ingroup Plugins - * \brief This feature allows to create sketch, revol faces from this sketch and - * fuse result with other objects in a single operation. - */ +/// \class FeaturesPlugin_RevolutionFuse +/// \ingroup Plugins +/// \brief This feature allows to create sketch, revol faces from this sketch and +/// fuse result with other objects in a single operation. class FeaturesPlugin_RevolutionFuse : public FeaturesPlugin_RevolutionBoolean { public: - /// Feature kind. + /// Use plugin manager for features creation. + FeaturesPlugin_RevolutionFuse(); + + /// Feature kind. inline static const std::string& ID() { static const std::string MY_REVOLUTION_ID("RevolutionFuse"); @@ -30,9 +32,6 @@ class FeaturesPlugin_RevolutionFuse : public FeaturesPlugin_RevolutionBoolean static std::string MY_KIND = FeaturesPlugin_RevolutionFuse::ID(); return MY_KIND; } - - /// Use plugin manager for features creation. - FeaturesPlugin_RevolutionFuse(); }; #endif diff --git a/src/FeaturesPlugin/FeaturesPlugin_RevolutionSketch.cpp b/src/FeaturesPlugin/FeaturesPlugin_RevolutionSketch.cpp deleted file mode 100644 index 183508057..000000000 --- a/src/FeaturesPlugin/FeaturesPlugin_RevolutionSketch.cpp +++ /dev/null @@ -1,104 +0,0 @@ -// Copyright (C) 2014-20xx CEA/DEN, EDF R&D - -// File: FeaturesPlugin_RevolutionSketch.cpp -// Created: 11 September 2015 -// Author: Dmitry Bobylev - -#include "FeaturesPlugin_RevolutionSketch.h" - -#include -#include -#include -#include -#include - -#include -#include -#include - -//================================================================================================= -FeaturesPlugin_RevolutionSketch::FeaturesPlugin_RevolutionSketch() -{ -} - -//================================================================================================= -void FeaturesPlugin_RevolutionSketch::initMakeSolidsAttributes() -{ - data()->addAttribute(FeaturesPlugin_RevolutionSketch::AXIS_OBJECT_ID(), ModelAPI_AttributeSelection::typeId()); - - data()->addAttribute(CREATION_METHOD(), ModelAPI_AttributeString::typeId()); - - data()->addAttribute(TO_ANGLE_ID(), ModelAPI_AttributeDouble::typeId()); - data()->addAttribute(FROM_ANGLE_ID(), ModelAPI_AttributeDouble::typeId()); - - data()->addAttribute(TO_OBJECT_ID(), ModelAPI_AttributeSelection::typeId()); - data()->addAttribute(TO_OFFSET_ID(), ModelAPI_AttributeDouble::typeId()); - - data()->addAttribute(FROM_OBJECT_ID(), ModelAPI_AttributeSelection::typeId()); - data()->addAttribute(FROM_OFFSET_ID(), ModelAPI_AttributeDouble::typeId()); - - ModelAPI_Session::get()->validators()->registerNotObligatory(getKind(), TO_OBJECT_ID()); - ModelAPI_Session::get()->validators()->registerNotObligatory(getKind(), FROM_OBJECT_ID()); -} - -//================================================================================================= -void FeaturesPlugin_RevolutionSketch::makeSolid(const std::shared_ptr theFace, - std::shared_ptr& theMakeShape) -{ - //Getting axis. - std::shared_ptr anAxis; - std::shared_ptr anEdge; - std::shared_ptr anObjRef = selection(FeaturesPlugin_RevolutionSketch::AXIS_OBJECT_ID()); - if(anObjRef && anObjRef->value() && anObjRef->value()->isEdge()) { - anEdge = std::shared_ptr(new GeomAPI_Edge(anObjRef->value())); - } else if(anObjRef->context() && anObjRef->context()->shape() && anObjRef->context()->shape()->isEdge()) { - anEdge = std::shared_ptr(new GeomAPI_Edge(anObjRef->context()->shape())); - } - if(anEdge) { - anAxis = std::shared_ptr(new GeomAPI_Ax1(anEdge->line()->location(), anEdge->line()->direction())); - } - - // Getting revolution angles. - double aToAngle = real(TO_ANGLE_ID())->value(); - double aFromAngle = real(FROM_ANGLE_ID())->value(); - - if(string(CREATION_METHOD())->value() == "ByAngles") { - aToAngle = real(TO_ANGLE_ID())->value(); - aFromAngle = real(FROM_ANGLE_ID())->value(); - } else { - aToAngle = real(TO_OFFSET_ID())->value(); - aFromAngle = real(FROM_OFFSET_ID())->value(); - } - - // Getting revolution bounding planes. - std::shared_ptr aToShape; - std::shared_ptr aFromShape; - - if(string(CREATION_METHOD())->value() == "ByPlanesAndOffsets") { - anObjRef = selection(TO_OBJECT_ID()); - if(anObjRef.get() != NULL) { - aToShape = std::dynamic_pointer_cast(anObjRef->value()); - if(aToShape.get() == NULL && anObjRef->context().get() != NULL) { - aToShape = anObjRef->context()->shape(); - } - } - anObjRef = selection(FROM_OBJECT_ID()); - if(anObjRef.get() != NULL) { - aFromShape = std::dynamic_pointer_cast(anObjRef->value()); - if(aFromShape.get() == NULL && anObjRef->context().get() != NULL) { - aFromShape = anObjRef->context()->shape(); - } - } - } - - // Revol face - std::shared_ptr aRevolAlgo(new GeomAlgoAPI_Revolution(theFace, anAxis, aToShape, aToAngle, aFromShape, aFromAngle)); - - // Checking that the algorithm worked properly. - if(!aRevolAlgo->isDone() || !aRevolAlgo->shape().get() || aRevolAlgo->shape()->isNull() || - !aRevolAlgo->isValid()) { - return; - } - - theMakeShape = aRevolAlgo; -} diff --git a/src/FeaturesPlugin/FeaturesPlugin_RevolutionSketch.h b/src/FeaturesPlugin/FeaturesPlugin_RevolutionSketch.h deleted file mode 100644 index b3d61b269..000000000 --- a/src/FeaturesPlugin/FeaturesPlugin_RevolutionSketch.h +++ /dev/null @@ -1,103 +0,0 @@ -// Copyright (C) 2014-20xx CEA/DEN, EDF R&D - -// File: FeaturesPlugin_RevolutionSketch.h -// Created: 11 September 2015 -// Author: Dmitry Bobylev - -#ifndef FeaturesPlugin_RevolutionSketch_H_ -#define FeaturesPlugin_RevolutionSketch_H_ - -#include - -/** \class FeaturesPlugin_RevolutionSketch - * \ingroup Plugins - * \brief This feature allows to create sketch and revol faces from this sketch - * in a single operation. - */ -class FeaturesPlugin_RevolutionSketch : public FeaturesPlugin_CompositeSketch -{ -public: - /// Feature kind. - inline static const std::string& ID() - { - static const std::string MY_REVOLUTION_ID("RevolutionSketch"); - return MY_REVOLUTION_ID; - } - - /// \return the kind of a feature - FEATURESPLUGIN_EXPORT virtual const std::string& getKind() - { - static std::string MY_KIND = FeaturesPlugin_RevolutionSketch::ID(); - return MY_KIND; - } - - /// Attribute name of an revolution axis. - inline static const std::string& AXIS_OBJECT_ID() - { - static const std::string MY_AXIS_ID("axis_object"); - return MY_AXIS_ID; - } - - /// attribute name for creation method - inline static const std::string& CREATION_METHOD() - { - static const std::string METHOD_ATTR("CreationMethod"); - return METHOD_ATTR; - } - - /// Attribute name of revolution to angle. - inline static const std::string& TO_ANGLE_ID() - { - static const std::string MY_TO_ANGLE_ID("to_angle"); - return MY_TO_ANGLE_ID; - } - - /// Attribute name of revolution from angle. - inline static const std::string& FROM_ANGLE_ID() - { - static const std::string MY_FROM_ANGLE_ID("from_angle"); - return MY_FROM_ANGLE_ID; - } - - /// Attribute name of an object to which the revolution grows. - inline static const std::string& TO_OBJECT_ID() - { - static const std::string MY_TO_OBJECT_ID("to_object"); - return MY_TO_OBJECT_ID; - } - - /// Attribute name of extrusion offset. - inline static const std::string& TO_OFFSET_ID() - { - static const std::string MY_TO_OFFSET_ID("to_offset"); - return MY_TO_OFFSET_ID; - } - - /// Attribute name of an object from which the revolution grows. - inline static const std::string& FROM_OBJECT_ID() - { - static const std::string MY_FROM_OBJECT_ID("from_object"); - return MY_FROM_OBJECT_ID; - } - - /// Attribute name of extrusion offset. - inline static const std::string& FROM_OFFSET_ID() - { - static const std::string MY_FROM_OFFSET_ID("from_offset"); - return MY_FROM_OFFSET_ID; - } - -protected: - /// Init attributes for revolution. - virtual void initMakeSolidsAttributes(); - - /// Create solids from faces with revolution. - virtual void makeSolid(const std::shared_ptr theFace, - std::shared_ptr& theMakeShape); - -public: - /// Use plugin manager for features creation. - FeaturesPlugin_RevolutionSketch(); -}; - -#endif diff --git a/src/FeaturesPlugin/FeaturesPlugin_Validators.cpp b/src/FeaturesPlugin/FeaturesPlugin_Validators.cpp index 40c1197db..f23ef720b 100644 --- a/src/FeaturesPlugin/FeaturesPlugin_Validators.cpp +++ b/src/FeaturesPlugin/FeaturesPlugin_Validators.cpp @@ -9,6 +9,7 @@ #include #include #include +#include //================================================================================================= bool FeaturesPlugin_PipeLocationsValidator::isValid(const std::shared_ptr& theFeature, @@ -19,7 +20,6 @@ bool FeaturesPlugin_PipeLocationsValidator::isValid(const std::shared_ptrgetKind() != "Pipe") { theError = "Feature \"" + theFeature->getKind() + "\" does not supported by this validator."; return false; @@ -58,8 +58,105 @@ bool FeaturesPlugin_PipeLocationsValidator::isValid(const std::shared_ptr& theArguments, + std::string& theError) const +{ + // Checking attribute. + if(!isValidAttribute(theAttribute, theError)) { + if(theError.empty()) { + theError = "Attribute contains shape with unacceptable type."; + } + return false; + } + + return true; +} + +//================================================================================================= +bool FeaturesPlugin_ValidatorBaseForGeneration::isValidAttribute(const AttributePtr& theAttribute, + std::string& theError) const +{ + if(!theAttribute.get()) { + theError = "Empty attribute."; + return false; + } + + std::string anAttributeType = theAttribute->attributeType(); + if(anAttributeType == ModelAPI_AttributeSelectionList::typeId()) { + AttributeSelectionListPtr aListAttr = std::dynamic_pointer_cast(theAttribute); + for(int anIndex = 0; anIndex < aListAttr->size(); ++anIndex) { + // If at least one attribute is invalid, the result is false. + if(!isValidAttribute(aListAttr->value(anIndex), theError)) { + return false; + } + } + } else if(anAttributeType == ModelAPI_AttributeSelection::typeId()) { + // Getting context. + AttributeSelectionPtr anAttr = std::dynamic_pointer_cast(theAttribute); + ResultPtr aContext = anAttr->context(); + if(!aContext.get()) { + theError = "Attribute have empty context."; + return false; + } + + GeomShapePtr aShape = anAttr->value(); + GeomShapePtr aContextShape = aContext->shape(); + if(!aShape.get()) { + aShape = aContextShape; + } + if(!aShape.get()) { + theError = "Empty shape selected"; + return false; + } + + ResultConstructionPtr aConstruction = std::dynamic_pointer_cast(aContext); + if(aConstruction.get()) { + // Construciotn selected. Check that is is not infinite. + if(aConstruction->isInfinite()) { + theError = "Infinite constructions is not allowed as base."; + return false; + } + + if(aShape->isEqual(aContextShape)) { + // Whole construction selected. Check that it have faces. + if(aConstruction->facesNum() > 0) { + return true; + } + } else { + // Shape on construction selected. Check that it is a face or wire. + if(aShape->shapeType() == GeomAPI_Shape::WIRE || aShape->shapeType() == GeomAPI_Shape::FACE) { + return true; + } + } + } + + if(!aShape->isEqual(aContextShape)) { + // Local selection on body does not allowed. + theError = "Selected shape is in the local selection. Only global selection is allowed."; + return false; + } + + // Check that object is a shape with allowed type. + aShape = aContext->shape(); + GeomAPI_Shape::ShapeType aShapeType = aShape->shapeType(); + if(aShapeType != GeomAPI_Shape::VERTEX && + aShapeType != GeomAPI_Shape::EDGE && + aShapeType != GeomAPI_Shape::WIRE && + aShapeType != GeomAPI_Shape::FACE) { + theError = "Selected shape has unacceptable type. Acceptable types are: faces or wires on sketch, \ + whole sketch(if it has at least one face), and following objects: vertex, edge, wire, face."; + return false; + } + + } else { + theError = "Following attribute does not supported: " + anAttributeType + "."; + return false; + } + + return true; } \ No newline at end of file diff --git a/src/FeaturesPlugin/FeaturesPlugin_Validators.h b/src/FeaturesPlugin/FeaturesPlugin_Validators.h index 47a12e434..2e0978b91 100644 --- a/src/FeaturesPlugin/FeaturesPlugin_Validators.h +++ b/src/FeaturesPlugin/FeaturesPlugin_Validators.h @@ -7,6 +7,7 @@ #ifndef FeaturesPlugin_Validators_H_ #define FeaturesPlugin_Validators_H_ +#include #include /// \class FeaturesPlugin_PipeLocationsValidator @@ -27,4 +28,24 @@ class FeaturesPlugin_PipeLocationsValidator : public ModelAPI_FeatureValidator virtual bool isNotObligatory(std::string theFeature, std::string theAttribute); }; +/// \class FeaturesPlugin_ValidatorBaseForGeneration +/// \ingroup Validators +/// \brief A validator for selection base for generation. Allows to select faces on sketch, +/// whole sketch(if it has at least one face), and following objects: vertex, edge, wire, face. +class FeaturesPlugin_ValidatorBaseForGeneration : public ModelAPI_AttributeValidator +{ +public: + //! Returns true if attribute has selection type listed in the parameter arguments. + //! \param[in] theAttribute the checked attribute. + //! \param[in] theArguments arguments of the attribute. + //! \param[out] theError error message. + virtual bool isValid(const AttributePtr& theAttribute, + const std::list& theArguments, + std::string& theError) const; + +private: + bool isValidAttribute(const AttributePtr& theAttribute, + std::string& theError) const; +}; + #endif diff --git a/src/FeaturesPlugin/Test/TestExtrusionSketch.py b/src/FeaturesPlugin/Test/TestExtrusionSketch.py deleted file mode 100644 index 9f5aae8fb..000000000 --- a/src/FeaturesPlugin/Test/TestExtrusionSketch.py +++ /dev/null @@ -1,126 +0,0 @@ -#========================================================================= -# Initialization of the test -#========================================================================= -from ModelAPI import * -from GeomDataAPI import * -from GeomAlgoAPI import * -from GeomAPI import * -import math - -aSession = ModelAPI_Session.get() -aDocument = aSession.moduleDocument() - -aSession.startOperation() -aPartFeature = aDocument.addFeature("Part") -aSession.finishOperation() -assert (len(aPartFeature.results()) == 1) -aPartResult = modelAPI_ResultPart(aPartFeature.firstResult()) -aPart = aPartResult.partDoc() - -#========================================================================= -# Make extrusion sketch -#========================================================================= -aSession.startOperation() -anExtrusionSketchFt = featureToCompositeFeature(aPart.addFeature("ExtrusionSketch")) -assert (anExtrusionSketchFt.getKind() == "ExtrusionSketch") -# selection type FACE=4 -aSession.startOperation() -aCircleSketchFeature = featureToCompositeFeature(anExtrusionSketchFt.addFeature("Sketch")) -origin = geomDataAPI_Point(aCircleSketchFeature.attribute("Origin")) -origin.setValue(0, 0, 0) -dirx = geomDataAPI_Dir(aCircleSketchFeature.attribute("DirX")) -dirx.setValue(1, 0, 0) -norm = geomDataAPI_Dir(aCircleSketchFeature.attribute("Norm")) -norm.setValue(0, 0, 1) -aSketchCircle = aCircleSketchFeature.addFeature("SketchCircle") -anCircleCentr = geomDataAPI_Point2D(aSketchCircle.attribute("CircleCenter")) -aCircleRadius = aSketchCircle.real("CircleRadius") -anCircleCentr.setValue(0, 0) -aCircleRadius.setValue(10) -aSession.finishOperation() -aSession.startOperation() -anExtrusionSketchFt.string("CreationMethod").setValue("BySizes") -anExtrusionSketchFt.real("to_size").setValue(10) -anExtrusionSketchFt.real("from_size").setValue(10) -anExtrusionSketchFt.real("to_offset").setValue(0) #TODO: remove -anExtrusionSketchFt.real("from_offset").setValue(0) #TODO: remove -anExtrusionSketchFt.execute() -aSession.finishOperation() -aSession.finishOperation() - -#========================================================================= -# Test results -#========================================================================= -aFactory = ModelAPI_Session.get().validators() -assert (aFactory.validate(anExtrusionSketchFt)) -assert (len(anExtrusionSketchFt.results()) > 0) -aCurrentResult = modelAPI_ResultBody(anExtrusionSketchFt.firstResult()) -assert (aCurrentResult is not None) - -#========================================================================= -# Test extrusion between bounding planes -#========================================================================= -# Create from plane -aSession.startOperation() -aSketchPlaneFeature = aPart.addFeature("Plane") -aSketchPlaneFeature.string("CreationMethod").setValue("PlaneByGeneralEquation") -aSketchPlaneFeature.real("A").setValue(0.) -aSketchPlaneFeature.real("B").setValue(0.) -aSketchPlaneFeature.real("C").setValue(1.) -aSketchPlaneFeature.real("D").setValue(30.) -aSession.finishOperation() -aFromResult = aSketchPlaneFeature.firstResult() -aFromShape = modelAPI_ResultConstruction(aFromResult).shape() - -# Create to plane -aSession.startOperation() -aToPlaneFeature = aPart.addFeature("Plane") -aToPlaneFeature.string("CreationMethod").setValue("PlaneByGeneralEquation") -aToPlaneFeature.real("A").setValue(0.) -aToPlaneFeature.real("B").setValue(0.) -aToPlaneFeature.real("C").setValue(1.) -aToPlaneFeature.real("D").setValue(-30.) -aSession.finishOperation() -aToResult = aToPlaneFeature.firstResult() -aToShape = modelAPI_ResultConstruction(aToResult).shape() - -#========================================================================= -# Make extrusion sketch -#========================================================================= -aSession.startOperation() -anExtrusionSketchFt = featureToCompositeFeature(aPart.addFeature("ExtrusionSketch")) -assert (anExtrusionSketchFt.getKind() == "ExtrusionSketch") -aSession.startOperation() -aCircleSketchFeature = featureToCompositeFeature(anExtrusionSketchFt.addFeature("Sketch")) -origin = geomDataAPI_Point(aCircleSketchFeature.attribute("Origin")) -origin.setValue(0, 0, 0) -dirx = geomDataAPI_Dir(aCircleSketchFeature.attribute("DirX")) -dirx.setValue(1, 0, 0) -norm = geomDataAPI_Dir(aCircleSketchFeature.attribute("Norm")) -norm.setValue(0, 0, 1) -aSketchCircle = aCircleSketchFeature.addFeature("SketchCircle") -anCircleCentr = geomDataAPI_Point2D(aSketchCircle.attribute("CircleCenter")) -aCircleRadius = aSketchCircle.real("CircleRadius") -anCircleCentr.setValue(0, 0) -aCircleRadius.setValue(10) -aSession.finishOperation() -aSession.startOperation() -anExtrusionSketchFt.string("CreationMethod").setValue("ByPlanesAndOffsets") -anExtrusionSketchFt.real("to_size").setValue(0) #TODO: remove -anExtrusionSketchFt.real("from_size").setValue(0) #TODO: remove -anExtrusionSketchFt.selection("to_object").setValue(aToResult, aToShape) -anExtrusionSketchFt.real("to_offset").setValue(0) -anExtrusionSketchFt.selection("from_object").setValue(aFromResult, aFromShape) -anExtrusionSketchFt.real("from_offset").setValue(0) -anExtrusionSketchFt.execute() -aSession.finishOperation() -aSession.finishOperation() - -#========================================================================= -# Test results -#========================================================================= -aFactory = ModelAPI_Session.get().validators() -assert (aFactory.validate(anExtrusionSketchFt)) -assert (len(anExtrusionSketchFt.results()) > 0) -aCurrentResult = modelAPI_ResultBody(anExtrusionSketchFt.firstResult()) -assert (aCurrentResult is not None) diff --git a/src/FeaturesPlugin/Test/TestRevolutionSketch.py b/src/FeaturesPlugin/Test/TestRevolutionSketch.py deleted file mode 100644 index ed54d928a..000000000 --- a/src/FeaturesPlugin/Test/TestRevolutionSketch.py +++ /dev/null @@ -1,153 +0,0 @@ -#========================================================================= -# Initialization of the test -#========================================================================= -from ModelAPI import * -from GeomDataAPI import * -from GeomAlgoAPI import * -from GeomAPI import * -import math - -aSession = ModelAPI_Session.get() -aDocument = aSession.moduleDocument() - -aSession.startOperation() -aPartFeature = aDocument.addFeature("Part") -aSession.finishOperation() -assert (len(aPartFeature.results()) == 1) -aPartResult = modelAPI_ResultPart(aPartFeature.firstResult()) -aPart = aPartResult.partDoc() - -#========================================================================= -# Create a sketch line to revol -#========================================================================= -aSession.startOperation() -aLineSketchFeature = featureToCompositeFeature(aPart.addFeature("Sketch")) -origin = geomDataAPI_Point(aLineSketchFeature.attribute("Origin")) -origin.setValue(0, 0, 0) -dirx = geomDataAPI_Dir(aLineSketchFeature.attribute("DirX")) -dirx.setValue(1, 0, 0) -norm = geomDataAPI_Dir(aLineSketchFeature.attribute("Norm")) -norm.setValue(0, 0, 1) -aSketchLine = aLineSketchFeature.addFeature("SketchLine") -aLineStartPoint = geomDataAPI_Point2D(aSketchLine.attribute("StartPoint")) -aLineEndPoint = geomDataAPI_Point2D(aSketchLine.attribute("EndPoint")) -aLineStartPoint.setValue(-20, -20) -aLineEndPoint.setValue(20, -20) -aSession.finishOperation() - -# Build shape from sketcher results -aLineSketchResult = aLineSketchFeature.firstResult() -aLineSketchShape = modelAPI_ResultConstruction(aLineSketchResult).shape() -aShapeExplorer = GeomAPI_ShapeExplorer(aLineSketchShape, GeomAPI_Shape.EDGE) -aLineEdge = aShapeExplorer.current() - -#========================================================================= -# Make revolution sketch -#========================================================================= -aSession.startOperation() -anRevolutionSketchFt = featureToCompositeFeature(aPart.addFeature("RevolutionSketch")) -assert (anRevolutionSketchFt.getKind() == "RevolutionSketch") -# selection type FACE=4 -aSession.startOperation() -aCircleSketchFeature = featureToCompositeFeature(anRevolutionSketchFt.addFeature("Sketch")) -origin = geomDataAPI_Point(aCircleSketchFeature.attribute("Origin")) -origin.setValue(0, 0, 0) -dirx = geomDataAPI_Dir(aCircleSketchFeature.attribute("DirX")) -dirx.setValue(1, 0, 0) -norm = geomDataAPI_Dir(aCircleSketchFeature.attribute("Norm")) -norm.setValue(0, 0, 1) -aSketchCircle = aCircleSketchFeature.addFeature("SketchCircle") -anCircleCentr = geomDataAPI_Point2D(aSketchCircle.attribute("CircleCenter")) -aCircleRadius = aSketchCircle.real("CircleRadius") -anCircleCentr.setValue(0, 0) -aCircleRadius.setValue(10) -aSession.finishOperation() -aSession.startOperation() -anRevolutionSketchFt.selection("axis_object").setValue(aLineSketchResult, aLineEdge) -anRevolutionSketchFt.string("CreationMethod").setValue("ByAngles") -anRevolutionSketchFt.real("to_angle").setValue(50) -anRevolutionSketchFt.real("from_angle").setValue(50) -anRevolutionSketchFt.real("to_offset").setValue(0) #TODO: remove -anRevolutionSketchFt.real("from_offset").setValue(0) #TODO: remove -anRevolutionSketchFt.execute() -aSession.finishOperation() -aSession.finishOperation() - -#========================================================================= -# Test results -#========================================================================= -aFactory = ModelAPI_Session.get().validators() -assert (aFactory.validate(anRevolutionSketchFt)) -assert (len(anRevolutionSketchFt.results()) > 0) -aCurrentResult = modelAPI_ResultBody(anRevolutionSketchFt.firstResult()) -assert (aCurrentResult is not None) - -#========================================================================= -# Test revolution between bounding planes -#========================================================================= -# Create from plane -aSession.startOperation() -aSketchPlaneFeature = aPart.addFeature("Plane") -aSketchPlaneFeature.string("CreationMethod").setValue("PlaneByGeneralEquation") -aSketchPlaneFeature.real("A").setValue(0.) -aSketchPlaneFeature.real("B").setValue(0.) -aSketchPlaneFeature.real("C").setValue(1.) -aSketchPlaneFeature.real("D").setValue(15.) -aSession.finishOperation() -aFromResult = aSketchPlaneFeature.firstResult() -aFromShape = modelAPI_ResultConstruction(aFromResult).shape() - -# Create to plane -aSession.startOperation() -aToPlaneFeature = aPart.addFeature("Plane") -aToPlaneFeature.string("CreationMethod").setValue("PlaneByGeneralEquation") -aToPlaneFeature.real("A").setValue(0.) -aToPlaneFeature.real("B").setValue(0.) -aToPlaneFeature.real("C").setValue(1.) -aToPlaneFeature.real("D").setValue(-15.) -aSession.finishOperation() -aToResult = aToPlaneFeature.firstResult() -aToShape = modelAPI_ResultConstruction(aToResult).shape() - -#========================================================================= -# Make revolution sketch -#========================================================================= -aSession.startOperation() -anRevolutionSketchFt = featureToCompositeFeature(aPart.addFeature("RevolutionSketch")) -assert (anRevolutionSketchFt.getKind() == "RevolutionSketch") -# selection type FACE=4 -aSession.startOperation() -aCircleSketchFeature = featureToCompositeFeature(anRevolutionSketchFt.addFeature("Sketch")) -origin = geomDataAPI_Point(aCircleSketchFeature.attribute("Origin")) -origin.setValue(0, 0, 0) -dirx = geomDataAPI_Dir(aCircleSketchFeature.attribute("DirX")) -dirx.setValue(1, 0, 0) -norm = geomDataAPI_Dir(aCircleSketchFeature.attribute("Norm")) -norm.setValue(0, 0, 1) -aSketchCircle = aCircleSketchFeature.addFeature("SketchCircle") -anCircleCentr = geomDataAPI_Point2D(aSketchCircle.attribute("CircleCenter")) -aCircleRadius = aSketchCircle.real("CircleRadius") -anCircleCentr.setValue(0, 0) -aCircleRadius.setValue(10) -aSession.finishOperation() -aSession.startOperation() -anRevolutionSketchFt.selection("axis_object").setValue(aLineSketchResult, aLineEdge) -anRevolutionSketchFt.string("CreationMethod").setValue("ByPlanesAndOffsets") -anRevolutionSketchFt.real("to_angle").setValue(0) #TODO: remove -anRevolutionSketchFt.real("from_angle").setValue(0) #TODO: remove -anRevolutionSketchFt.selection("to_object").setValue(aToResult, aToShape) -anRevolutionSketchFt.real("to_offset").setValue(0) -anRevolutionSketchFt.selection("from_object").setValue(aFromResult, aFromShape) -anRevolutionSketchFt.real("from_offset").setValue(0) -anRevolutionSketchFt.execute() -aSession.finishOperation() -aSession.finishOperation() - -#========================================================================= -# Test results -#========================================================================= -aFactory = ModelAPI_Session.get().validators() -assert (aFactory.validate(anRevolutionSketchFt)) -assert (len(anRevolutionSketchFt.results()) > 0) -aCurrentResult = modelAPI_ResultBody(anRevolutionSketchFt.firstResult()) -assert (aCurrentResult is not None) diff --git a/src/FeaturesPlugin/extrusion_widget.xml b/src/FeaturesPlugin/extrusion_widget.xml index 63099b851..7a9043658 100644 --- a/src/FeaturesPlugin/extrusion_widget.xml +++ b/src/FeaturesPlugin/extrusion_widget.xml @@ -2,44 +2,51 @@ + shape_types="faces objects"> + label="Base objects:" + tooltip="Select a base objects" + type_choice="faces objects"> + + + - + - - + - - + - + - - + - - + diff --git a/src/FeaturesPlugin/extrusioncut_widget.xml b/src/FeaturesPlugin/extrusioncut_widget.xml index 610509a09..fe01e3a41 100755 --- a/src/FeaturesPlugin/extrusioncut_widget.xml +++ b/src/FeaturesPlugin/extrusioncut_widget.xml @@ -17,6 +17,14 @@ type_choice="Faces Objects"> + + + @@ -74,7 +82,7 @@ - + + + @@ -74,7 +82,7 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/FeaturesPlugin/pipe_widget.xml b/src/FeaturesPlugin/pipe_widget.xml index 10b07cad8..f964308cc 100644 --- a/src/FeaturesPlugin/pipe_widget.xml +++ b/src/FeaturesPlugin/pipe_widget.xml @@ -1,34 +1,21 @@ + + + + + - - - - - - - + - - - - - - - - - - diff --git a/src/FeaturesPlugin/revolution_widget.xml b/src/FeaturesPlugin/revolution_widget.xml index a7a5b82d2..ac18d203b 100644 --- a/src/FeaturesPlugin/revolution_widget.xml +++ b/src/FeaturesPlugin/revolution_widget.xml @@ -2,60 +2,51 @@ + shape_types="faces objects"> + label="Base objects:" + tooltip="Select a base objects" + type_choice="faces objects"> + + + - - - - + - - + - - + - - - - + - - + - - + diff --git a/src/FeaturesPlugin/revolutioncut_widget.xml b/src/FeaturesPlugin/revolutioncut_widget.xml index 00a984486..a42e01027 100644 --- a/src/FeaturesPlugin/revolutioncut_widget.xml +++ b/src/FeaturesPlugin/revolutioncut_widget.xml @@ -17,16 +17,16 @@ type_choice="Faces Objects"> + + + - - - - - - - + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/GeomAlgoAPI/GeomAlgoAPI_MakeShape.h b/src/GeomAlgoAPI/GeomAlgoAPI_MakeShape.h index b5e40ef24..0131da446 100644 --- a/src/GeomAlgoAPI/GeomAlgoAPI_MakeShape.h +++ b/src/GeomAlgoAPI/GeomAlgoAPI_MakeShape.h @@ -93,6 +93,9 @@ protected: /// \param[in] theShape new shape. void setShape(const std::shared_ptr theShape); +protected: + std::shared_ptr myMap; ///< Data map to keep correct orientation of sub-shapes. + private: /// \brief Initializes internals. void initialize(); @@ -101,7 +104,6 @@ private: GeomAlgoAPI_MakeShape::BuilderType myBuilderType; ///< Type of make shape builder. bool myDone; ///< Builder status. std::shared_ptr myShape; ///< Resulting shape. - std::shared_ptr myMap; ///< Data map to keep correct orientation of sub-shapes. }; typedef std::list > ListOfMakeShape; diff --git a/src/GeomAlgoAPI/GeomAlgoAPI_MakeShapeList.cpp b/src/GeomAlgoAPI/GeomAlgoAPI_MakeShapeList.cpp index 1442c5b32..7be7d7c12 100644 --- a/src/GeomAlgoAPI/GeomAlgoAPI_MakeShapeList.cpp +++ b/src/GeomAlgoAPI/GeomAlgoAPI_MakeShapeList.cpp @@ -24,13 +24,28 @@ GeomAlgoAPI_MakeShapeList::GeomAlgoAPI_MakeShapeList(const ListOfMakeShape& theM //================================================================================================= void GeomAlgoAPI_MakeShapeList::init(const ListOfMakeShape& theMakeShapeList) { + if(myMap.get()) { + myMap->clear(); + } else { + myMap.reset(new GeomAPI_DataMapOfShapeShape); + } + myListOfMakeShape = theMakeShapeList; + + for(ListOfMakeShape::const_iterator anIt = theMakeShapeList.cbegin(); + anIt != theMakeShapeList.cend(); ++anIt) { + myMap->merge((*anIt)->mapOfSubShapes()); + } } //================================================================================================= void GeomAlgoAPI_MakeShapeList::appendAlgo(const std::shared_ptr theMakeShape) { myListOfMakeShape.push_back(theMakeShape); + if(!myMap.get()) { + myMap.reset(new GeomAPI_DataMapOfShapeShape()); + } + myMap->merge(theMakeShape->mapOfSubShapes()); } //================================================================================================= diff --git a/src/GeomValidators/GeomValidators_ShapeType.cpp b/src/GeomValidators/GeomValidators_ShapeType.cpp index 80e6af9d0..9b7df3693 100644 --- a/src/GeomValidators/GeomValidators_ShapeType.cpp +++ b/src/GeomValidators/GeomValidators_ShapeType.cpp @@ -160,8 +160,10 @@ bool GeomValidators_ShapeType::isValidObject(const ObjectPtr& theObject, { bool aValid = true; if (!theObject.get()) { - aValid = false; - theError = "The object is empty"; + if(theShapeType != Empty) { + aValid = false; + theError = "The object is empty"; + } } else { ResultPtr aResult = std::dynamic_pointer_cast(theObject); diff --git a/src/PartSet/PartSet_WidgetSketchCreator.cpp b/src/PartSet/PartSet_WidgetSketchCreator.cpp index b5b7e8b21..91093ed8e 100644 --- a/src/PartSet/PartSet_WidgetSketchCreator.cpp +++ b/src/PartSet/PartSet_WidgetSketchCreator.cpp @@ -414,7 +414,7 @@ void PartSet_WidgetSketchCreator::onResumed(ModuleBase_Operation* theOp) aLoop->flush(aLoop->eventByName(EVENT_OBJECT_TO_REDISPLAY)); // Add Selected body were created the sketcher to list of selected objects - std::string anObjectsAttribute = FeaturesPlugin_CompositeBoolean::BOOLEAN_OBJECTS_ID(); + std::string anObjectsAttribute = FeaturesPlugin_CompositeBoolean::OBJECTS_ID(); AttributeSelectionListPtr aSelList = aCompFeature->data()->selectionList(anObjectsAttribute); if (aSelList.get()) { DataPtr aData = aSketchFeature->data(); -- 2.39.2