X-Git-Url: http://git.salome-platform.org/gitweb/?a=blobdiff_plain;f=src%2FModelAPI%2FModelAPI_Tools.cpp;h=84c5de685d83c7cbd6a5c7ba02dbd1f12639865b;hb=9270adddc12db9661c676544537b0e8eb78c1624;hp=0dd1c1c8eca884b38805aa741acaa4e54f548fd5;hpb=0ff6e3441d023e37c2c7b71fb15e485e65c912ce;p=modules%2Fshaper.git diff --git a/src/ModelAPI/ModelAPI_Tools.cpp b/src/ModelAPI/ModelAPI_Tools.cpp index 0dd1c1c8e..84c5de685 100644 --- a/src/ModelAPI/ModelAPI_Tools.cpp +++ b/src/ModelAPI/ModelAPI_Tools.cpp @@ -1,4 +1,4 @@ -// Copyright (C) 2014-2021 CEA/DEN, EDF R&D +// Copyright (C) 2014-2022 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 @@ -20,6 +20,7 @@ #include #include #include +#include #include #include #include @@ -39,14 +40,18 @@ #include #include +#include #include #include +#include #include #include #include #include #include +#include +#include #define RECURSE_TOP_LEVEL 50 @@ -195,6 +200,125 @@ ObjectPtr objectByName(const DocumentPtr& theDocument, const std::string& theGro return ObjectPtr(); } +//================================================================================================== +void loadModifiedShapes(ResultBodyPtr theResultBody, + const ListOfShape& theBaseShapes, + const ListOfShape& theTools, + const GeomMakeShapePtr& theMakeShape, + const GeomShapePtr theResultShape, + const std::string& theNamePrefix) +{ + theResultBody->storeModified(theBaseShapes, theResultShape, theMakeShape); + + ListOfShape aShapes = theBaseShapes; + ListOfShape::const_iterator aToolIter = theTools.cbegin(); + for (; aToolIter != theTools.cend(); aToolIter++) + aShapes.push_back(*aToolIter); + + for (ListOfShape::const_iterator anIter = aShapes.begin(); anIter != aShapes.end(); ++anIter) + { + theResultBody->loadModifiedShapes(theMakeShape, *anIter, GeomAPI_Shape::VERTEX, theNamePrefix); + theResultBody->loadModifiedShapes(theMakeShape, *anIter, GeomAPI_Shape::EDGE, theNamePrefix); + theResultBody->loadModifiedShapes(theMakeShape, *anIter, GeomAPI_Shape::FACE, theNamePrefix); + } +} + +//================================================================================================== +void loadModifiedShapes(ResultBodyPtr theResultBody, + const GeomShapePtr& theBaseShape, + const GeomMakeShapePtr& theMakeShape, + const std::string theName) +{ + switch (theBaseShape->shapeType()) { + case GeomAPI_Shape::COMPOUND: { + for (GeomAPI_ShapeIterator anIt(theBaseShape); anIt.more(); anIt.next()) + { + loadModifiedShapes(theResultBody, + anIt.current(), + theMakeShape, + theName); + } + break; + } + case GeomAPI_Shape::COMPSOLID: + case GeomAPI_Shape::SOLID: + case GeomAPI_Shape::SHELL: { + theResultBody->loadModifiedShapes(theMakeShape, + theBaseShape, + GeomAPI_Shape::FACE, + theName); + } + case GeomAPI_Shape::FACE: + case GeomAPI_Shape::WIRE: { + theResultBody->loadModifiedShapes(theMakeShape, + theBaseShape, + GeomAPI_Shape::EDGE, + theName); + } + case GeomAPI_Shape::EDGE: { + theResultBody->loadModifiedShapes(theMakeShape, + theBaseShape, + GeomAPI_Shape::VERTEX, + theName); + } + default: // [to avoid compilation warning] + break; + } +} + +//================================================================================================== +void loadDeletedShapes(ResultBodyPtr theResultBody, + const GeomShapePtr theBaseShape, + const ListOfShape& theTools, + const GeomMakeShapePtr& theMakeShape, + const GeomShapePtr theResultShapesCompound) +{ + ListOfShape aShapes = theTools; + if (theBaseShape.get()) + aShapes.push_front(theBaseShape); + + for (ListOfShape::const_iterator anIter = aShapes.begin(); anIter != aShapes.end(); anIter++) + { + theResultBody->loadDeletedShapes(theMakeShape, + *anIter, + GeomAPI_Shape::VERTEX, + theResultShapesCompound); + theResultBody->loadDeletedShapes(theMakeShape, + *anIter, + GeomAPI_Shape::EDGE, + theResultShapesCompound); + theResultBody->loadDeletedShapes(theMakeShape, + *anIter, + GeomAPI_Shape::FACE, + theResultShapesCompound); + // store information about deleted solids because of unittest TestBooleanCommon_SolidsHistory + // on OCCT 7.4.0 : common produces modified compsolid, so, move to the end for removed solids + // starts to produce whole compsolid + theResultBody->loadDeletedShapes(theMakeShape, + *anIter, + GeomAPI_Shape::SOLID, + theResultShapesCompound); + } +} + +//================================================================================================== +void loadDeletedShapes(std::vector& theResultBaseAlgoList, + const ListOfShape& theTools, + const GeomShapePtr theResultShapesCompound) +{ + for (std::vector::iterator anIt = theResultBaseAlgoList.begin(); + anIt != theResultBaseAlgoList.end(); + ++anIt) + { + ResultBaseAlgo& aRCA = *anIt; + loadDeletedShapes(aRCA.resultBody, + aRCA.baseShape, + theTools, + aRCA.makeShape, + theResultShapesCompound); + } +} + bool findVariable(const DocumentPtr& theDocument, FeaturePtr theSearcher, const std::wstring& theName, double& outValue, ResultParameterPtr& theParam) { @@ -231,6 +355,95 @@ bool findVariable(FeaturePtr theSearcher, const std::wstring& theName, double& o return false; } +static void cacheSubresults(const ResultBodyPtr& theTopLevelResult, + std::set& theCashedResults) +{ + std::list aResults; + ModelAPI_Tools::allSubs(theTopLevelResult, aResults, false); + for (std::list::iterator aR = aResults.begin(); aR != aResults.end(); ++aR) { + theCashedResults.insert(*aR); + } +} + +bool isInResults(AttributeSelectionListPtr theSelection, + const std::list& theResults, + std::set& theCashedResults) +{ + // collect all results into a cashed set + if (theCashedResults.empty()) { + std::list::const_iterator aRes = theResults.cbegin(); + for(; aRes != theResults.cend(); aRes++) { + if (theCashedResults.count(*aRes)) + continue; + else + theCashedResults.insert(*aRes); + + if ((*aRes)->groupName() == ModelAPI_ResultBody::group()) { + ResultBodyPtr aResBody = std::dynamic_pointer_cast(*aRes); + cacheSubresults(aResBody, theCashedResults); + } else if ((*aRes)->groupName() == ModelAPI_ResultPart::group()) { // all results of the part + ResultPartPtr aResPart = std::dynamic_pointer_cast(*aRes); + DocumentPtr aPartDoc = aResPart->partDoc(); + if (!aPartDoc.get() || !aPartDoc->isOpened()) { // document is not accessible + return false; + } + int aBodyCount = aPartDoc->size(ModelAPI_ResultBody::group()); + for (int aBodyIndex = 0; aBodyIndex < aBodyCount; ++aBodyIndex) { + ResultBodyPtr aResBody = + std::dynamic_pointer_cast( + aPartDoc->object(ModelAPI_ResultBody::group(), aBodyIndex)); + if (aResBody.get()) { + theCashedResults.insert(aResBody); + cacheSubresults(aResBody, theCashedResults); + } + } + } + } + } + // if context is in results, return true + for(int a = 0; a < theSelection->size(); a++) { + AttributeSelectionPtr anAttr = theSelection->value(a); + ResultPtr aContext = anAttr->context(); + // check is it group selected for groups BOP + if (aContext.get() && aContext->groupName() == ModelAPI_ResultGroup::group()) { + // it is impossible by used results check which result is used in this group result, + // so check the results shapes is it in results of this document or not + FeaturePtr aSelFeature = + std::dynamic_pointer_cast(theSelection->owner()); + if (!aSelFeature.get() || aSelFeature->results().empty()) + continue; + GeomShapePtr aGroupResShape = aSelFeature->firstResult()->shape(); + + std::set::iterator allResultsIter = theCashedResults.begin(); + for(; allResultsIter != theCashedResults.end(); allResultsIter++) { + GeomShapePtr aResultShape = (*allResultsIter)->shape(); + + GeomAPI_Shape::ShapeType aType = + GeomAPI_Shape::shapeTypeByStr(theSelection->selectionType()); + GeomAPI_ShapeExplorer aGroupResExp(aGroupResShape, aType); + for(; aGroupResExp.more(); aGroupResExp.next()) { + if (aResultShape->isSubShape(aGroupResExp.current(), false)) + return true; // at least one shape of the group is in the used results + } + } + } + ResultBodyPtr aSelected = std::dynamic_pointer_cast(anAttr->context()); + if (!aSelected.get()) { // try to get selected feature and all its results + FeaturePtr aContextFeature = anAttr->contextFeature(); + if (aContextFeature.get() && !aContextFeature->results().empty()) { + const std::list& allResluts = aContextFeature->results(); + std::list::const_iterator aResIter = allResluts.cbegin(); + for(; aResIter != allResluts.cend(); aResIter++) { + if (aResIter->get() && theCashedResults.count(*aResIter)) + return true; + } + } + } else if (aSelected.get() && theCashedResults.count(aSelected)) + return true; + } + return false; +} + ResultPtr findPartResult(const DocumentPtr& theMain, const DocumentPtr& theSub) { // to optimize and avoid of crash on partset document close @@ -956,6 +1169,31 @@ bool isShownIsoLines(std::shared_ptr theResult) return false; } +//****************************************************** +void showEdgesDirection(std::shared_ptr theResult, bool theShow) +{ + if (!theResult.get()) + return; + + AttributeBooleanPtr aAttr = theResult->data()->boolean(ModelAPI_Result::SHOW_EDGES_DIRECTION_ID()); + if (aAttr.get() != NULL) { + aAttr->setValue(theShow); + } +} + +//****************************************************** +bool isShowEdgesDirection(std::shared_ptr theResult) +{ + if (!theResult.get()) + return false; + + AttributeBooleanPtr aAttr = theResult->data()->boolean(ModelAPI_Result::SHOW_EDGES_DIRECTION_ID()); + if (aAttr.get() != NULL) { + return aAttr->value(); + } + return false; +} + //************************************************************** void setTransparency(ResultPtr theResult, double theTransparency) { @@ -1023,6 +1261,30 @@ void copyVisualizationAttrs( } } + +void copyImageAttribute (std::shared_ptr theSource, + std::shared_ptr theDest) +{ + if (!theSource.get() || !theDest.get()) + return; + + // images allowed only for ResultBody + ResultBodyPtr aSourceBody = std::dynamic_pointer_cast(theSource); + ResultBodyPtr aDestBody = std::dynamic_pointer_cast(theDest); + if (!aSourceBody.get() || !aDestBody.get()) + return; + + AttributeImagePtr aSourceImage = + theSource->data()->image(ModelAPI_ResultBody::IMAGE_ID()); + if (aSourceImage.get() && aSourceImage->hasTexture()) { + AttributeImagePtr aDestImage = + theDest->data()->image(ModelAPI_ResultBody::IMAGE_ID()); + if (aDestImage.get()) { + aSourceImage->copyTo(aDestImage); + } + } +} + std::list referencedFeatures( std::shared_ptr theTarget, const std::string& theFeatureKind, const bool theSortResults) @@ -1172,7 +1434,7 @@ std::array, 10> myColorTab = { void findRandomColor(std::vector& theValues, bool theReset) { - static int i = 0; + static size_t i = 0; static std::vector> usedGeneratedColor; // True when disabling auto-color @@ -1204,4 +1466,127 @@ void findRandomColor(std::vector& theValues, bool theReset) // LCOV_EXCL_STOP +/// Returns name of the higher level feature (Part or feature of PartSet). +static FeaturePtr topOwner(const FeaturePtr& theFeature) +{ + FeaturePtr anOwner = theFeature; + while (anOwner.get()) + { + FeaturePtr aNextOwner = compositeOwner(anOwner); + if (aNextOwner.get()) + anOwner = aNextOwner; + else + break; + } + if (anOwner->document() != ModelAPI_Session::get()->moduleDocument()) // the part-owner name + anOwner = findPartFeature(ModelAPI_Session::get()->moduleDocument(), anOwner->document()); + return anOwner; +} + +std::wstring validateMovement(const FeaturePtr& theAfter, const std::list theMoved) +{ + std::wstring aResult; + if (theMoved.empty()) + return aResult; // nothing to move, nothing to check, ok + DocumentPtr aDoc = theAfter.get() ? theAfter->document() : (*(theMoved.cbegin()))->document(); + std::set aMoved(theMoved.begin(), theMoved.end()); // fast access to moved + std::set aPassed, aPassedMoved; // all features and all moved before the current one + std::set aPassedAfter; // all passed features after theAfter + bool anAfterIsPassed = theAfter.get() == 0; // flag that iterator already passed theAfter + std::list allFeat = aDoc->allFeatures(); + for (std::list::iterator aFeat = allFeat.begin(); aFeat != allFeat.end(); aFeat++) + { + if (!anAfterIsPassed) + { + if (aMoved.count(*aFeat)) + aPassedMoved.insert(*aFeat); + else // check aPassedMoved are not referenced by the current feature + aPassed.insert(*aFeat); + + anAfterIsPassed = *aFeat == theAfter; + if (anAfterIsPassed && !aPassedMoved.empty()) + { // check dependencies of moved relatively to the passed + std::map > aReferences; + findAllReferences(aPassedMoved, aReferences); + std::map >::iterator aRefIter = aReferences.begin(); + for (; aRefIter != aReferences.end(); aRefIter++) + { + if (aPassed.count(aRefIter->first)) + { + aResult += topOwner(aRefIter->first)->name() + L" -> "; + // iterate all passed moved to check is it referenced by described feature or not + std::set::iterator aMovedIter = aPassedMoved.begin(); + for (; aMovedIter != aPassedMoved.end(); aMovedIter++) + { + std::map > aPassedRefs; + std::set aMovedOne; + aMovedOne.insert(*aMovedIter); + findAllReferences(aMovedOne, aPassedRefs); + if (aPassedRefs.count(aRefIter->first)) + aResult += topOwner(*aMovedIter)->name() + L" "; + } + aResult += L"\n"; + } + } + } + } + else // iteration after theAfter + { + if (aMoved.count(*aFeat)) { // check dependencies of moved relatively to ones after theAfter + std::map > aReferences; + findAllReferences(aPassedAfter, aReferences); + bool aFoundRef = aReferences.find(*aFeat) != aReferences.end(); + if (!aFoundRef && !(*aFeat)->results().empty()) // reference may be a feature in moved part + { + ResultPartPtr aFeatPart = + std::dynamic_pointer_cast((*aFeat)->firstResult()); + if (aFeatPart.get() && aFeatPart->partDoc().get()) + { + std::map >::iterator aRef = aReferences.begin(); + for (; aRef != aReferences.end() && !aFoundRef; aRef++) + aFoundRef = aRef->first->document() == aFeatPart->partDoc(); + } + } + + if (aFoundRef) + { + aResult += topOwner(*aFeat)->name() + L" -> "; + std::set aReferencedCount; // to avoid duplicates in the displayed references + // iterate all passed after theAfter to check refers it described feature or not + FeaturePtr aFeatTop = topOwner(*aFeat); + std::set::iterator aPassedIter = aPassedAfter.begin(); + for (; aPassedIter != aPassedAfter.end(); aPassedIter++) + { + FeaturePtr aPassedTop = topOwner(*aPassedIter); + if (aReferencedCount.count(aPassedTop)) + continue; + std::map > aPassedRefs; + std::set aPassedOne; + aPassedOne.insert(*aPassedIter); + findAllReferences(aPassedOne, aPassedRefs); + std::map >::iterator aPRIter = aPassedRefs.begin(); + for (; aPRIter != aPassedRefs.end(); aPRIter++) + { + FeaturePtr aPRTop = topOwner(aPRIter->first); + if (aPRIter->first == *aFeat || aPRIter->first == aFeatTop || + aPRTop == *aFeat || aPRTop == aFeatTop) + { + aResult += aPassedTop->name() + L" "; + aReferencedCount.insert(aPassedTop); + break; + } + } + } + aResult += L"\n"; + } + } + else { + aPassedAfter.insert(*aFeat); + } + } + + } + return aResult; +} + } // namespace ModelAPI_Tools