X-Git-Url: http://git.salome-platform.org/gitweb/?a=blobdiff_plain;f=src%2FFeaturesPlugin%2FFeaturesPlugin_CompositeSketch.cpp;h=56f5861753a606f4fa7da04369ad4c0f5b452e0c;hb=46c0759fa291dad10b713cf02b341d6e9e60c1a4;hp=d9ff9ccfce5966c2e27f3d39656674cc71450b70;hpb=24f9658d6e124a268c6a3abcf24f07aa2dc6d268;p=modules%2Fshaper.git diff --git a/src/FeaturesPlugin/FeaturesPlugin_CompositeSketch.cpp b/src/FeaturesPlugin/FeaturesPlugin_CompositeSketch.cpp index d9ff9ccfc..56f586175 100644 --- a/src/FeaturesPlugin/FeaturesPlugin_CompositeSketch.cpp +++ b/src/FeaturesPlugin/FeaturesPlugin_CompositeSketch.cpp @@ -1,209 +1,310 @@ -// Copyright (C) 2014-20xx CEA/DEN, EDF R&D - -// File: FeaturesPlugin_CompositeSketch.cpp -// Created: 11 September 2015 -// Author: Dmitry Bobylev +// Copyright (C) 2014-2020 CEA/DEN, EDF R&D +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2.1 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com +// #include +#include #include #include #include -#include #include #include #include -#include -#include #include -#include -#include +#include + + +static void storeSubShape(const std::shared_ptr theMakeShape, + ResultBodyPtr theResultBody, + const GeomShapePtr theShape, + const GeomAPI_Shape::ShapeType theType, + const std::string& theName); //================================================================================================= -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; } //================================================================================================= -int FeaturesPlugin_CompositeSketch::numberOfSubs(bool forTree) const +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) +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()); - return std::shared_ptr(); + FeaturePtr aSubFeature; + if(theIndex == 0) { + aSubFeature = + std::dynamic_pointer_cast(data()->reference(SKETCH_ID())->value()); + } + return aSubFeature; } //================================================================================================= 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 + bool isSubFeature = false; + // 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; + if (aFeature.get()) { + ObjectPtr aSub = data()->reference(SKETCH_ID())->value(); + isSubFeature = aSub == theObject; + } + return isSubFeature; } //================================================================================================= void FeaturesPlugin_CompositeSketch::removeFeature(std::shared_ptr theFeature) { + AttributeSelectionListPtr aBaseObjectsSelectionList = selectionList(BASE_OBJECTS_ID()); + if(aBaseObjectsSelectionList.get() && aBaseObjectsSelectionList->size() > 0) { + aBaseObjectsSelectionList->clear(); + } + + reference(SKETCH_ID())->setValue(ObjectPtr()); } //================================================================================================= -void FeaturesPlugin_CompositeSketch::erase() +void FeaturesPlugin_CompositeSketch::getBaseShapes(ListOfShape& theBaseShapesList, + const bool theIsMakeShells) { - 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); - } - } - ModelAPI_CompositeFeature::erase(); + AttributeSelectionListPtr aBaseObjectsSelectionList = selectionList(BASE_OBJECTS_ID()); + std::string anError; + bool isOk = FeaturesPlugin_Tools::getShape( + aBaseObjectsSelectionList, theIsMakeShells, theBaseShapesList, anError); + if (!isOk) + setError(anError); } +//================================================================================================= +void FeaturesPlugin_CompositeSketch::storeResult(const GeomShapePtr theBaseShape, + const std::shared_ptr theMakeShape, + const int theIndex) +{ + // Create result body. + ResultBodyPtr aResultBody = document()->createBody(data(), theIndex); + + // Store generated shape. + aResultBody->storeGenerated(theBaseShape, theMakeShape->shape()); + + // Store generated edges/faces. + storeGenerationHistory(aResultBody, theBaseShape, theMakeShape); + + setResult(aResultBody, theIndex); +} //================================================================================================= -void FeaturesPlugin_CompositeSketch::execute() +void FeaturesPlugin_CompositeSketch::storeGenerationHistory(ResultBodyPtr theResultBody, + const GeomShapePtr theBaseShape, + const std::shared_ptr theMakeShape) { - // 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; - } + GeomAPI_Shape::ShapeType aBaseShapeType = theBaseShape->shapeType(); + GeomAPI_Shape::ShapeType aShapeTypeToExplode = GeomAPI_Shape::SHAPE; - if (!selection(SKETCH_SELECTION_ID())->isInitialized() || selection(SKETCH_SELECTION_ID())->context() != aSketchRes) { - selection(SKETCH_SELECTION_ID())->setValue(aSketchRes, std::shared_ptr()); + switch(aBaseShapeType) { + case GeomAPI_Shape::EDGE: { + aShapeTypeToExplode = GeomAPI_Shape::VERTEX; + break; + } + case GeomAPI_Shape::WIRE: { + aShapeTypeToExplode = GeomAPI_Shape::COMPOUND; + break; + } + case GeomAPI_Shape::FACE: + case GeomAPI_Shape::SHELL: { + aShapeTypeToExplode = GeomAPI_Shape::EDGE; + break; + } + case GeomAPI_Shape::COMPOUND: { + aShapeTypeToExplode = GeomAPI_Shape::COMPOUND; + } + default: // [to avoid compilation warnings] + break; } - int aSketchFacesNum = aConstruction->facesNum(); - if(aSketchFacesNum == 0) { - return; + + if(aShapeTypeToExplode == GeomAPI_Shape::VERTEX || + aShapeTypeToExplode == GeomAPI_Shape::COMPOUND) { + theResultBody->loadGeneratedShapes(theMakeShape, theBaseShape, GeomAPI_Shape::VERTEX); } - 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(aShapeTypeToExplode == GeomAPI_Shape::EDGE || + aShapeTypeToExplode == GeomAPI_Shape::COMPOUND) { + theResultBody->loadGeneratedShapes(theMakeShape, theBaseShape, GeomAPI_Shape::EDGE); } - - // 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 aResult; - ListOfShape aFromFaces, aToFaces; - std::shared_ptr aMakeShape; - std::shared_ptr aDataMap; - - std::shared_ptr aBaseFace = *anIter; - makeSolid(aBaseFace, aResult, aFromFaces, aToFaces, aMakeShape, aDataMap); - if(!aResult.get()) { - aErrorsNum++; - continue; + std::list > aSweeps; // all sweeps collected + std::shared_ptr aMakeSweep = + std::dynamic_pointer_cast(theMakeShape); + if(aMakeSweep.get()) { + aSweeps.push_back(aMakeSweep); + } else { + std::shared_ptr aMakeList = + std::dynamic_pointer_cast(theMakeShape); + if (aMakeList.get()) { + ListOfMakeShape::const_iterator anIter = aMakeList->list().cbegin(); + for(; anIter != aMakeList->list().cend(); anIter++) { + std::shared_ptr aSweep = + std::dynamic_pointer_cast(*anIter); + if (aSweep.get()) + aSweeps.push_back(aSweep); + } } - - ResultBodyPtr aResultBody = document()->createBody(data(), aResultIndex); - loadNamingDS(aResultBody, aBaseFace, aResult, aFromFaces, aToFaces, aMakeShape, aDataMap); - setResult(aResultBody, aResultIndex); - aResultIndex++; } + std::list >::iterator aSweep = aSweeps.begin(); + for(; aSweep != aSweeps.end(); aSweep++) { + // Store from shapes. + storeShapes(theMakeShape, theResultBody, aBaseShapeType, (*aSweep)->fromShapes(), "From_"); - if(aErrorsNum > 0) { - std::ostringstream aStringStream; - aStringStream << "Warning: could not create solid(s) from " << aErrorsNum << " face(s)."; - setError(aStringStream.str()); + // Store to shapes. + storeShapes(theMakeShape, theResultBody, aBaseShapeType, (*aSweep)->toShapes(), "To_"); } - - // Remove the rest results if there were produced in the previous pass. - removeResults(aResultIndex); } //================================================================================================= -void FeaturesPlugin_CompositeSketch::loadNamingDS(std::shared_ptr theResultBody, - const std::shared_ptr& theBaseShape, - const std::shared_ptr& theResult, - const ListOfShape& theFromFaces, - const ListOfShape& theToFaces, - const std::shared_ptr& theMakeShape, - const std::shared_ptr& theDataMap) +void FeaturesPlugin_CompositeSketch::storeShapes( + const std::shared_ptr theMakeShape, + ResultBodyPtr theResultBody, + const GeomAPI_Shape::ShapeType theBaseShapeType, + const ListOfShape& theShapes, + const std::string theName) { - //load result - theResultBody->storeGenerated(theBaseShape, theResult); - - //Insert lateral face : Face from Edge - const std::string aLatName = "LateralFace"; - const int aLatTag = 1; - theResultBody->loadAndOrientGeneratedShapes(theMakeShape.get(), theBaseShape, GeomAPI_Shape::EDGE, aLatTag, aLatName, *theDataMap); - - //Insert to faces - const std::string aToName = "ToFace"; - int aToTag = 2; - for(ListOfShape::const_iterator anIt = theToFaces.cbegin(); anIt != theToFaces.cend(); anIt++) { - std::shared_ptr aToFace = *anIt; - if(theDataMap->isBound(aToFace)) { - aToFace = theDataMap->find(aToFace); + GeomAPI_Shape::ShapeType aShapeTypeToExplore = GeomAPI_Shape::FACE; + std::string aShapeTypeStr = "Face"; + switch(theBaseShapeType) { + case GeomAPI_Shape::VERTEX: { + aShapeTypeToExplore = GeomAPI_Shape::VERTEX; + aShapeTypeStr = "Vertex"; + break; } - theResultBody->generated(aToFace, aToName, aToTag++); + 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; + } + case GeomAPI_Shape::COMPOUND: { + aShapeTypeToExplore = GeomAPI_Shape::COMPOUND; + break; + } + default: // [to avoid compilation warnings] + break; } - //Insert from faces - const std::string aFromName = "FromFace"; - int aFromTag = aToTag > 10000 ? aToTag : 10000; - for(ListOfShape::const_iterator anIt = theFromFaces.cbegin(); anIt != theFromFaces.cend(); anIt++) { - std::shared_ptr aFromFace = *anIt; - if(theDataMap->isBound(aFromFace)) { - aFromFace = theDataMap->find(aFromFace); + // Store shapes. + for(ListOfShape::const_iterator anIt = theShapes.cbegin(); anIt != theShapes.cend(); ++anIt) { + GeomShapePtr aShape = *anIt; + + if(aShapeTypeToExplore == GeomAPI_Shape::COMPOUND) { + std::string aName = theName + (aShape->shapeType() == GeomAPI_Shape::EDGE ? "Edge" : "Face"); + storeSubShape(theMakeShape, theResultBody, aShape, aShape->shapeType(), aName); + } else { + std::string aName = theName + aShapeTypeStr; + storeSubShape(theMakeShape, theResultBody, aShape, aShapeTypeToExplore, aName); + if (theBaseShapeType == GeomAPI_Shape::WIRE) { // issue 2289: special names also for vertices + aName = theName + "Vertex"; + storeSubShape(theMakeShape, theResultBody, aShape, GeomAPI_Shape::VERTEX, aName); + } + } + } +} + +void storeSubShape( + const std::shared_ptr theMakeShape, + ResultBodyPtr theResultBody, + const GeomShapePtr theShape, + const GeomAPI_Shape::ShapeType theType, + const std::string& theName) +{ + for(GeomAPI_ShapeExplorer anExp(theShape, theType); anExp.more(); anExp.next()) { + GeomShapePtr aSubShape = anExp.current(); + if (!theResultBody->generated(aSubShape, theName)) { + int aNbSubs = theResultBody->numberOfSubs(); + if (aNbSubs > 0) { + // check the modified shape is in the result body, don't store it if not + ListOfShape aNewShapes; + theMakeShape->modified(aSubShape, aNewShapes); + for (int i = 0; i < aNbSubs; ++i) { + ResultBodyPtr aSubRes = theResultBody->subResult(i); + GeomShapePtr aShape = aSubRes->shape(); + ListOfShape::iterator aNewIt = aNewShapes.begin(); + for (; aNewIt != aNewShapes.end(); ++aNewIt) + if (aShape->isSubShape(*aNewIt, false)) + break; + if (aNewIt != aNewShapes.end()) { + // store from/to shapes as primitives and then store modification of them by the boolean + aSubRes->generated(aSubShape, theName, false); + aSubRes->loadModifiedShapes(theMakeShape, aSubShape, theType); + } + } + } + else { + // store from/to shapes as primitives and then store modification of them by the boolean + theResultBody->generated(aSubShape, theName, false); + theResultBody->loadModifiedShapes(theMakeShape, aSubShape, theType); + } } - theResultBody->generated(aFromFace, aFromName, aFromTag++); } }