X-Git-Url: http://git.salome-platform.org/gitweb/?a=blobdiff_plain;f=src%2FModelAPI%2FModelAPI_Tools.cpp;h=1baf30d0c5ef0fc806789b4158acc57b6ca87227;hb=08a991619fbd4f803d52e698dd48f0f7f46d118e;hp=9dd0d9d6c7eee1985ad332b2c8a2614e4ca7c4d5;hpb=87b6a30a3afb8fb32e7e43ade8d9c947d9eb1684;p=modules%2Fshaper.git diff --git a/src/ModelAPI/ModelAPI_Tools.cpp b/src/ModelAPI/ModelAPI_Tools.cpp old mode 100755 new mode 100644 index 9dd0d9d6c..1baf30d0c --- a/src/ModelAPI/ModelAPI_Tools.cpp +++ b/src/ModelAPI/ModelAPI_Tools.cpp @@ -1,4 +1,4 @@ -// Copyright (C) 2014-2017 CEA/DEN, EDF R&D +// Copyright (C) 2014-2019 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 @@ -12,10 +12,9 @@ // // 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 +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA // -// See http://www.salome-platform.org/ or -// email : webmaster.salome@opencascade.com +// See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com // #include "ModelAPI_Tools.h" @@ -24,18 +23,28 @@ #include #include #include -#include +#include +#include #include #include +#include #include #include +#include +#include +#include #include #include #include +#include #include +#include #include +#include +#include + #define RECURSE_TOP_LEVEL 50 //#define DEBUG_REMOVE_FEATURES @@ -106,18 +115,17 @@ std::shared_ptr shape(const ResultPtr& theResult) return theResult->shape(); } +// LCOV_EXCL_START const char* toString(ModelAPI_ExecState theExecState) { -#define TO_STRING(__NAME__) case __NAME__: return #__NAME__; switch (theExecState) { - TO_STRING(ModelAPI_StateDone) - TO_STRING(ModelAPI_StateMustBeUpdated) - TO_STRING(ModelAPI_StateExecFailed) - TO_STRING(ModelAPI_StateInvalidArgument) - TO_STRING(ModelAPI_StateNothing) + case ModelAPI_StateDone: return "Done"; + case ModelAPI_StateMustBeUpdated: return "Must be updated"; + case ModelAPI_StateExecFailed: return "Execution failed"; + case ModelAPI_StateInvalidArgument: return "Invalid argument"; + case ModelAPI_StateNothing: return "Empty state"; default: return "Unknown ExecState."; } -#undef TO_STRING } std::string getFeatureError(const FeaturePtr& theFeature) @@ -160,13 +168,15 @@ std::string getFeatureError(const FeaturePtr& theFeature) return anError; } +// LCOV_EXCL_STOP ObjectPtr objectByName(const DocumentPtr& theDocument, const std::string& theGroup, const std::string& theName) { + std::wstring aName = Locale::Convert::toWString(theName); for (int anIndex = 0; anIndex < theDocument->size(theGroup); ++anIndex) { ObjectPtr anObject = theDocument->object(theGroup, anIndex); - if (anObject->data()->name() == theName) + if (anObject->data()->name() == aName) return anObject; } // not found @@ -253,7 +263,7 @@ FeaturePtr findPartFeature(const DocumentPtr& theMain, const DocumentPtr& theSub CompositeFeaturePtr compositeOwner(const FeaturePtr& theFeature) { - if (theFeature.get() && theFeature->data()->isValid()) { + if (theFeature.get() && theFeature->data() && theFeature->data()->isValid()) { const std::set >& aRefs = theFeature->data()->refsToMe(); std::set >::const_iterator aRefIter = aRefs.begin(); for(; aRefIter != aRefs.end(); aRefIter++) { @@ -266,53 +276,73 @@ CompositeFeaturePtr compositeOwner(const FeaturePtr& theFeature) return CompositeFeaturePtr(); // not found } -ResultCompSolidPtr compSolidOwner(const ResultPtr& theSub) +ResultBodyPtr bodyOwner(const ResultPtr& theSub, const bool theRoot) { - ResultBodyPtr aBody = std::dynamic_pointer_cast(theSub); - if (aBody.get()) { - FeaturePtr aFeatureOwner = aBody->document()->feature(aBody); - if (aFeatureOwner.get()) { - std::list >::const_iterator aResIter = - aFeatureOwner->results().cbegin(); - for(; aResIter != aFeatureOwner->results().cend(); aResIter++) { - ResultCompSolidPtr aComp = std::dynamic_pointer_cast(*aResIter); - if (aComp && aComp->isSub(aBody)) - return aComp; + if (theSub.get()) { + ObjectPtr aParent = theSub->document()->parent(theSub); + if (aParent.get()) { + if (theRoot) { // try to find parent of parent + ResultPtr aResultParent = std::dynamic_pointer_cast(aParent); + ResultBodyPtr aGrandParent = bodyOwner(aResultParent, true); + if (aGrandParent.get()) + aParent = aGrandParent; } + return std::dynamic_pointer_cast(aParent); } } - return ResultCompSolidPtr(); // not found + return ResultBodyPtr(); // not found +} + +int bodyIndex(const ResultPtr& theSub) +{ + int anIndex = -1; + ResultBodyPtr aParent = bodyOwner(theSub); + if (aParent.get()) { + ResultBodyPtr aBody = std::dynamic_pointer_cast(theSub); + if (aBody.get() && aParent->isSub(aBody, anIndex)) + return anIndex; + } + return anIndex; // not found } bool hasSubResults(const ResultPtr& theResult) { - ResultCompSolidPtr aCompSolid = std::dynamic_pointer_cast(theResult); + ResultBodyPtr aCompSolid = std::dynamic_pointer_cast(theResult); return aCompSolid.get() && aCompSolid->numberOfSubs() > 0; } +void allSubs(const ResultBodyPtr& theResult, std::list& theResults, + const bool theLowerOnly) { + // iterate sub-bodies of compsolid + ResultBodyPtr aComp = std::dynamic_pointer_cast(theResult); + if (aComp.get()) { + int aNumSub = aComp->numberOfSubs(); + for (int a = 0; a < aNumSub; a++) { + ResultBodyPtr aSub = aComp->subResult(a); + if (!theLowerOnly || aSub->numberOfSubs() == 0) + theResults.push_back(aSub); + allSubs(aSub, theResults); + } + } +} + void allResults(const FeaturePtr& theFeature, std::list& theResults) { if (!theFeature.get()) // safety: for empty feature no results return; const std::list >& aResults = theFeature->results(); - std::list >::const_iterator aRIter = aResults.begin(); + std::list::const_iterator aRIter = aResults.begin(); for (; aRIter != aResults.cend(); aRIter++) { theResults.push_back(*aRIter); - // iterate sub-bodies of compsolid - ResultCompSolidPtr aComp = std::dynamic_pointer_cast(*aRIter); - if (aComp.get()) { - int aNumSub = aComp->numberOfSubs(); - for(int a = 0; a < aNumSub; a++) { - theResults.push_back(aComp->subResult(a)); - } - } + ResultBodyPtr aResult = std::dynamic_pointer_cast(*aRIter); + allSubs(aResult, theResults); } } //****************************************************************** -bool allDocumentsActivated(std::string& theNotActivatedNames) +bool allDocumentsActivated(std::wstring& theNotActivatedNames) { - theNotActivatedNames = ""; + theNotActivatedNames = L""; bool anAllPartActivated = true; DocumentPtr aRootDoc = ModelAPI_Session::get()->moduleDocument(); @@ -323,7 +353,7 @@ bool allDocumentsActivated(std::string& theNotActivatedNames) if (!aPart->isActivated()) { anAllPartActivated = false; if (!theNotActivatedNames.empty()) - theNotActivatedNames += ", "; + theNotActivatedNames += L", "; theNotActivatedNames += aObject->data()->name().c_str(); } } @@ -361,6 +391,7 @@ bool removeFeaturesAndReferences(const std::set& theFeatures, return ModelAPI_Tools::removeFeatures(aFeatures, false); } +//*********************************************************************** bool removeFeatures(const std::set& theFeatures, const bool theFlushRedisplay) { @@ -385,6 +416,7 @@ bool removeFeatures(const std::set& theFeatures, return true; } +//*********************************************************************** // Fills the references list by all references of the feature from the references map. // This is a recusive method to find references by next found feature in the map of references. // \param theFeature a feature to find references @@ -392,7 +424,6 @@ bool removeFeatures(const std::set& theFeatures, // \param theReferences an out container of references void addRefsToFeature(const FeaturePtr& theFeature, const std::map >& theReferencesMap, - std::map >& theProcessedReferences, int theRecLevel, std::set& theReferences) { @@ -400,34 +431,18 @@ void addRefsToFeature(const FeaturePtr& theFeature, return; theRecLevel++; - // if the feature is already processed, get the ready references from the map - if (theProcessedReferences.find(theFeature) != theProcessedReferences.end()) { - std::set aReferences = theProcessedReferences.at(theFeature); - theReferences.insert(aReferences.begin(), aReferences.end()); - return; - } - if (theReferencesMap.find(theFeature) == theReferencesMap.end()) return; // this feature is not in the selection list, so exists without references to it std::set aMainReferences = theReferencesMap.at(theFeature); std::set::const_iterator anIt = aMainReferences.begin(), aLast = aMainReferences.end(); -#ifdef DEBUG_REMOVE_FEATURES_RECURSE - std::string aSpacing; - for (int i = 0; i < theRecLevel; i++) - aSpacing.append(" "); -#endif - for (; anIt != aLast; anIt++) { FeaturePtr aRefFeature = *anIt; -#ifdef DEBUG_REMOVE_FEATURES_RECURSE - std::cout << aSpacing << " Ref: " << getFeatureInfo(aRefFeature) << std::endl; -#endif - if (theReferences.find(aRefFeature) == theReferences.end()) + if (theReferences.find(aRefFeature) == theReferences.end()) { + addRefsToFeature(aRefFeature, theReferencesMap, theRecLevel, theReferences); theReferences.insert(aRefFeature); - addRefsToFeature(aRefFeature, theReferencesMap, theProcessedReferences, - theRecLevel, theReferences); + } } } @@ -535,7 +550,7 @@ void findAllReferences(const std::set& theFeatures, std::cout << " Ref: " << getFeatureInfo(aFeature) << std::endl; #endif aRecLevel++; - addRefsToFeature(aFeature, aMainList, theReferences, + addRefsToFeature(aFeature, aMainList, aRecLevel, aResultRefList/*aMainRefList*/); } theReferences[aMainListFeature] = aResultRefList; @@ -602,4 +617,493 @@ void getConcealedResults(const FeaturePtr& theFeature, } } +std::pair getDefaultName(const std::shared_ptr& theResult, + const bool theInherited) +{ + typedef std::list< std::pair < std::string, std::list > > ListOfReferences; + + SessionPtr aSession = ModelAPI_Session::get(); + + ResultBodyPtr anOwnerRes = bodyOwner(theResult); + if (anOwnerRes) { + // names of sub-solids in CompSolid should be default (for example, + // result of boolean operation 'Boolean_1_1' is a CompSolid which is renamed to 'MyBOOL', + // however, sub-elements of 'MyBOOL' should be named 'Boolean_1_1_1', 'Boolean_1_1_2' etc.) + std::wostringstream aDefaultName; + aDefaultName << getDefaultName(anOwnerRes).first; + aDefaultName << "_" << (bodyIndex(theResult) + 1); + return std::pair(aDefaultName.str(), false); + } + + FeaturePtr anOwner = ModelAPI_Feature::feature(theResult->data()->owner()); + DataPtr aData = anOwner->data(); + + ListOfReferences aReferences; + // find first result with user-defined name + ListOfReferences::const_iterator aFoundRef = aReferences.end(); + if (theInherited) { + aData->referencesToObjects(aReferences); + + for (ListOfReferences::const_iterator aRefIt = aReferences.begin(); + aRefIt != aReferences.end(); ++aRefIt) { + bool isConcealed = aSession->validators()->isConcealed(anOwner->getKind(), aRefIt->first); + bool isMainArg = isConcealed && + aSession->validators()->isMainArgument(anOwner->getKind(), aRefIt->first); + if (isConcealed) { + // check the referred object is a Body + // (for example, ExtrusionCut has a sketch as a first attribute which is concealing) + bool isBody = aRefIt->second.size() > 1 || (aRefIt->second.size() == 1 && + aRefIt->second.front().get() && + aRefIt->second.front()->groupName() == ModelAPI_ResultBody::group()); + if (isBody && (isMainArg || aFoundRef == aReferences.end() || + aData->isPrecedingAttribute(aRefIt->first, aFoundRef->first))) + aFoundRef = aRefIt; + + if (isMainArg) + break; + } + } + } + // get the result number in the feature + int anIndexInOwner = 0; + const std::list& anOwnerResults = anOwner->results(); + std::list::const_iterator aResIt = anOwnerResults.cbegin(); + for(; aResIt != anOwnerResults.cend(); aResIt++) { + if(*aResIt == theResult) + break; + anIndexInOwner++; + } + + // find an object which is concealed by theResult + if (aFoundRef != aReferences.end() && !aFoundRef->second.empty()) { + // store number of references for each object + std::map aNbRefToObject; + // search the object by result index + std::list::const_iterator anObjIt = aFoundRef->second.begin(); + int aResultIndex = anIndexInOwner; + while (--aResultIndex >= 0) { + ResultPtr aCurRes = std::dynamic_pointer_cast(*anObjIt); + ResultBodyPtr aParentBody = ModelAPI_Tools::bodyOwner(aCurRes); + if (aParentBody) + aCurRes = aParentBody; + if (aNbRefToObject.find(aCurRes) == aNbRefToObject.end()) + aNbRefToObject[aCurRes] = 1; + else + aNbRefToObject[aCurRes] += 1; + + ++anObjIt; + if (anObjIt == aFoundRef->second.end()) { + anObjIt = aFoundRef->second.begin(); + break; + } + } + // check the result is a Body + if ((*anObjIt)->groupName() == ModelAPI_ResultBody::group()) { + // check the result is part of CompSolid + ResultPtr anObjRes = std::dynamic_pointer_cast(*anObjIt); + ResultBodyPtr aParentBody = ModelAPI_Tools::bodyOwner(anObjRes); + if (aParentBody) + anObjRes = aParentBody; + + // return name of reference result only if it has been renamed by the user, + // in other case compose a default name + if (anObjRes->data()->hasUserDefinedName()) { + std::wstringstream aName; + aName << anObjRes->data()->name(); + std::map::iterator aFound = aNbRefToObject.find(anObjRes); + if (aFound != aNbRefToObject.end()) { + // to generate unique name, add suffix if there are several results + // referring to the same shape + aName << "_" << aFound->second + 1; + } + return std::pair(aName.str(), true); + } + } + } + + // compose default name by the name of the feature and the index of result + std::wstringstream aDefaultName; + aDefaultName << anOwner->name(); + // if there are several results (issue #899: any number of result), + // add unique prefix starting from second + if (anIndexInOwner > 0 || theResult->groupName() == ModelAPI_ResultBody::group()) + aDefaultName << "_" << anIndexInOwner + 1; + return std::pair(aDefaultName.str(), false); +} + +std::set getParents(const FeaturePtr& theFeature) +{ + std::set aParents; + for (FeaturePtr aCurFeat = theFeature; aCurFeat; ) { + CompositeFeaturePtr aFoundComposite; + const std::set& aRefs = aCurFeat->data()->refsToMe(); + for (std::set::const_iterator anIt = aRefs.begin(); + anIt != aRefs.end(); ++anIt) { + FeaturePtr aF = ModelAPI_Feature::feature((*anIt)->owner()); + aFoundComposite = std::dynamic_pointer_cast(aF); + if (aFoundComposite && aFoundComposite->isSub(aCurFeat)) + break; + else + aFoundComposite = CompositeFeaturePtr(); + } + + if (aFoundComposite) { + aParents.insert(aFoundComposite); + aCurFeat = aFoundComposite; + } + else { + // add the part containing high-level feature + SessionPtr aSession = ModelAPI_Session::get(); + DocumentPtr aPartSetDoc = aSession->moduleDocument(); + std::list aPartSetFeatures = aPartSetDoc->allFeatures(); + for (std::list::const_iterator anIt = aPartSetFeatures.begin(); + anIt != aPartSetFeatures.end(); ++anIt) { + aFoundComposite = std::dynamic_pointer_cast(*anIt); + if (aFoundComposite && aFoundComposite->isSub(aCurFeat)) { + aParents.insert(aFoundComposite); + break; + } + } + + aCurFeat = FeaturePtr(); + } + } + return aParents; +} + +void fillShapeHierarchy(const GeomShapePtr& theShape, + const ResultPtr& theContext, + GeomAPI_ShapeHierarchy& theHierarchy) +{ + ResultBodyPtr aResCompSolidPtr = ModelAPI_Tools::bodyOwner(theContext); + if (aResCompSolidPtr.get()) { + std::shared_ptr aContextShape = aResCompSolidPtr->shape(); + if (aContextShape->shapeType() <= GeomAPI_Shape::COMPSOLID) { + theHierarchy.addParent(theShape, aContextShape); + fillShapeHierarchy(aContextShape, aResCompSolidPtr, theHierarchy); + } + } +} + + +void removeResults(const std::list& theResults) +{ + // collect all documents where the results must be removed + std::map > aDocs; + + std::list::const_iterator aResIter = theResults.cbegin(); + for(; aResIter != theResults.cend(); aResIter++) { + DocumentPtr aDoc = (*aResIter)->document(); + if (!aDocs.count(aDoc)) + aDocs[aDoc] = std::list(); + aDocs[aDoc].push_back(*aResIter); + } + // create a "remove" feature in each doc + std::map >::iterator aDoc = aDocs.begin(); + for(; aDoc != aDocs.end(); aDoc++) { + FeaturePtr aRemove = aDoc->first->addFeature("RemoveResults"); + if (aRemove) { + for(aResIter = aDoc->second.cbegin(); aResIter != aDoc->second.cend(); aResIter++) + aRemove->selectionList("results")->append(*aResIter, GeomShapePtr()); + } + } +} + +// used by GUI only +// LCOV_EXCL_START + +//************************************************************** +void setDeflection(ResultPtr theResult, const double theDeflection) +{ + if (!theResult.get()) + return; + + AttributeDoublePtr aDeflectionAttr = theResult->data()->real(ModelAPI_Result::DEFLECTION_ID()); + if (aDeflectionAttr.get() != NULL) { + aDeflectionAttr->setValue(theDeflection); + } +} + +double getDeflection(const std::shared_ptr& theResult) +{ + double aDeflection = -1; + // get deflection from the attribute of the result + if (theResult.get() != NULL && + theResult->data()->attribute(ModelAPI_Result::DEFLECTION_ID()).get() != NULL) { + AttributeDoublePtr aDoubleAttr = theResult->data()->real(ModelAPI_Result::DEFLECTION_ID()); + if (aDoubleAttr.get() && aDoubleAttr->isInitialized()) { + double aValue = aDoubleAttr->value(); + if (aValue > 0) /// zero value should not be used as a deflection(previous studies) + aDeflection = aDoubleAttr->value(); + } + } + return aDeflection; +} + +//****************************************************** +void setColor(ResultPtr theResult, const std::vector& theColor) +{ + if (!theResult.get()) + return; + + AttributeIntArrayPtr aColorAttr = theResult->data()->intArray(ModelAPI_Result::COLOR_ID()); + if (aColorAttr.get() != NULL) { + if (!aColorAttr->size()) { + aColorAttr->setSize(3); + } + aColorAttr->setValue(0, theColor[0]); + aColorAttr->setValue(1, theColor[1]); + aColorAttr->setValue(2, theColor[2]); + } +} + +void getColor(const std::shared_ptr& theResult, std::vector& theColor) +{ + theColor.clear(); + // get color from the attribute of the result + if (theResult.get() != NULL && + theResult->data()->attribute(ModelAPI_Result::COLOR_ID()).get() != NULL) { + AttributeIntArrayPtr aColorAttr = theResult->data()->intArray(ModelAPI_Result::COLOR_ID()); + if (aColorAttr.get() && aColorAttr->size()) { + theColor.push_back(aColorAttr->value(0)); + theColor.push_back(aColorAttr->value(1)); + theColor.push_back(aColorAttr->value(2)); + } + } +} + +//****************************************************** +void getIsoLines(const std::shared_ptr& theResult, + bool& isVisible, std::vector& theNbLines) +{ + theNbLines.clear(); + isVisible = false; + if (!theResult.get()) + return; + if (theResult->groupName() == ModelAPI_ResultConstruction::group()) { + theNbLines.push_back(0); + theNbLines.push_back(0); + } + else { + // get color from the attribute of the result + AttributeIntArrayPtr aAttr = theResult->data()->intArray(ModelAPI_Result::ISO_LINES_ID()); + if (aAttr.get()) { + if (aAttr->size()) { + theNbLines.push_back(aAttr->value(0)); + theNbLines.push_back(aAttr->value(1)); + } + } + AttributeBooleanPtr aBoolAttr = + theResult->data()->boolean(ModelAPI_Result::SHOW_ISO_LINES_ID()); + if (aBoolAttr.get()) { + isVisible = aBoolAttr->value(); + } + } +} + +//****************************************************** +void setIsoLines(ResultPtr theResult, const std::vector& theIso) +{ + if (!theResult.get()) + return; + + AttributeIntArrayPtr aAttr = theResult->data()->intArray(ModelAPI_Result::ISO_LINES_ID()); + if (aAttr.get() != NULL) { + if (!aAttr->size()) { + aAttr->setSize(2); + } + aAttr->setValue(0, theIso[0]); + aAttr->setValue(1, theIso[1]); + } +} + +//****************************************************** +void showIsoLines(std::shared_ptr theResult, bool theShow) +{ + if (!theResult.get()) + return; + + AttributeBooleanPtr aAttr = theResult->data()->boolean(ModelAPI_Result::SHOW_ISO_LINES_ID()); + if (aAttr.get() != NULL) { + aAttr->setValue(theShow); + } +} + +//****************************************************** +bool isShownIsoLines(std::shared_ptr theResult) +{ + if (!theResult.get()) + return false; + + AttributeBooleanPtr aAttr = theResult->data()->boolean(ModelAPI_Result::SHOW_ISO_LINES_ID()); + if (aAttr.get() != NULL) { + return aAttr->value(); + } + return false; +} + +//************************************************************** +void setTransparency(ResultPtr theResult, double theTransparency) +{ + if (!theResult.get()) + return; + + AttributeDoublePtr anAttribute = theResult->data()->real(ModelAPI_Result::TRANSPARENCY_ID()); + if (anAttribute.get() != NULL) { + anAttribute->setValue(theTransparency); + } +} + +double getTransparency(const std::shared_ptr& theResult) +{ + double aTransparency = -1; + // get transparency from the attribute of the result + if (theResult.get() != NULL && + theResult->data()->attribute(ModelAPI_Result::TRANSPARENCY_ID()).get() != NULL) { + AttributeDoublePtr aDoubleAttr = theResult->data()->real(ModelAPI_Result::TRANSPARENCY_ID()); + if (aDoubleAttr.get() && aDoubleAttr->isInitialized()) { + aTransparency = aDoubleAttr->value(); + } + } + return aTransparency; +} + +void copyVisualizationAttrs( + std::shared_ptr theSource, std::shared_ptr theDest) +{ + // color + AttributeIntArrayPtr aSourceColor = theSource->data()->intArray(ModelAPI_Result::COLOR_ID()); + if (aSourceColor.get() && aSourceColor->isInitialized() && aSourceColor->size()) { + AttributeIntArrayPtr aDestColor = theDest->data()->intArray(ModelAPI_Result::COLOR_ID()); + if (aDestColor.get()) { + aDestColor->setSize(aSourceColor->size()); + for(int a = 0; a < aSourceColor->size(); a++) + aDestColor->setValue(a, aSourceColor->value(a)); + } + } + // Iso-lines + AttributeIntArrayPtr aSource = theSource->data()->intArray(ModelAPI_Result::ISO_LINES_ID()); + if (aSource.get() && aSource->isInitialized() && aSource->size()) { + AttributeIntArrayPtr aDest = theDest->data()->intArray(ModelAPI_Result::ISO_LINES_ID()); + if (aDest.get()) { + aDest->setSize(aSource->size()); + for(int a = 0; a < aSource->size(); a++) + aDest->setValue(a, aSource->value(a)); + } + } + // deflection + AttributeDoublePtr aSourceDefl = theSource->data()->real(ModelAPI_Result::DEFLECTION_ID()); + if (aSourceDefl.get() && aSourceDefl->isInitialized()) { + AttributeDoublePtr aDestDefl = theDest->data()->real(ModelAPI_Result::DEFLECTION_ID()); + if (aDestDefl.get()) { + aDestDefl->setValue(aSourceDefl->value()); + } + } + // transparency + AttributeDoublePtr aSourceTransp = theSource->data()->real(ModelAPI_Result::TRANSPARENCY_ID()); + if (aSourceTransp.get() && aSourceTransp->isInitialized()) { + AttributeDoublePtr aDestTransp = theDest->data()->real(ModelAPI_Result::TRANSPARENCY_ID()); + if (aDestTransp.get()) { + aDestTransp->setValue(aSourceTransp->value()); + } + } +} + +std::list referencedFeatures( + std::shared_ptr theTarget, const std::string& theFeatureKind, + const bool theSortResults) +{ + std::set aResSet; // collect in the set initially to avoid duplicates + std::list allSubRes; + allSubRes.push_back(theTarget); + ResultBodyPtr aBody = std::dynamic_pointer_cast(theTarget); + if (aBody.get()) + allSubs(aBody, allSubRes); + std::list::iterator aSub = allSubRes.begin(); + for(; aSub != allSubRes.end(); aSub++) { + const std::set& aRefs = (*aSub)->data()->refsToMe(); + std::set::const_iterator aRef = aRefs.cbegin(); + for(; aRef != aRefs.cend(); aRef++) { + FeaturePtr aFeat = std::dynamic_pointer_cast((*aRef)->owner()); + if (aFeat.get() && (theFeatureKind.empty() || aFeat->getKind() == theFeatureKind)) + aResSet.insert(aFeat); + } + } + // add also feature of the target that may be referenced as a whole + FeaturePtr aTargetFeature = theTarget->document()->feature(theTarget); + const std::set& aRefs = aTargetFeature->data()->refsToMe(); + std::set::const_iterator aRef = aRefs.cbegin(); + for(; aRef != aRefs.cend(); aRef++) { + FeaturePtr aFeat = std::dynamic_pointer_cast((*aRef)->owner()); + if (aFeat.get() && (theFeatureKind.empty() || aFeat->getKind() == theFeatureKind)) + aResSet.insert(aFeat); + } + // check also Group-operations that may refer to groups - add them for theFeatureKind "Group" + if (theFeatureKind == "Group") { + std::set aGroupOperations; + for(bool aNeedIterate = true; aNeedIterate; ) { + std::set::iterator aResIter = aResSet.begin(); + for(; aResIter != aResSet.end(); aResIter++) { + std::list::const_iterator aGroupRes = (*aResIter)->results().cbegin(); + for(; aGroupRes != (*aResIter)->results().cend(); aGroupRes++) { + const std::set& aRefs = (*aGroupRes)->data()->refsToMe(); + std::set::const_iterator aRef = aRefs.cbegin(); + for(; aRef != aRefs.cend(); aRef++) { + FeaturePtr aFeat = std::dynamic_pointer_cast((*aRef)->owner()); + if (aFeat.get() && !aGroupOperations.count(aFeat) && !aFeat->results().empty() && + aFeat->firstResult()->groupName() == ModelAPI_ResultGroup::group()) { + // iterate results of this group operation because it may be without theTarget shape + GeomShapePtr aTargetShape = theTarget->shape(); + bool anIsIn = false; + std::list::const_iterator anOpRes = aFeat->results().cbegin(); + for(; anOpRes != aFeat->results().cend() && !anIsIn; anOpRes++) { + GeomShapePtr anOpShape = (*anOpRes)->shape(); + if (!anOpShape.get() || anOpShape->isNull()) + continue; + for(GeomAPI_ShapeIterator aSubIt(anOpShape); aSubIt.more(); aSubIt.next()) { + if (aTargetShape->isSubShape(aSubIt.current(), false)) { + anIsIn = true; + break; + } + } + } + if (anIsIn) + aGroupOperations.insert(aFeat); + } + } + } + } + // insert all new group operations into result and if they are, check for next dependencies + aNeedIterate = false; + std::set::iterator aGroupOpIter = aGroupOperations.begin(); + for(; aGroupOpIter != aGroupOperations.end(); aGroupOpIter++) { + if (aResSet.find(*aGroupOpIter) == aResSet.end()) { + aResSet.insert(*aGroupOpIter); + aNeedIterate = true; + } + } + } + } + + std::list aResList; + std::set::iterator aResIter = aResSet.begin(); + for(; aResIter != aResSet.end(); aResIter++) { + if (theSortResults) { // sort results by creation-order + std::list::iterator aListIter = aResList.begin(); + for(; aListIter != aResList.end(); aListIter++) { + if ((*aResIter)->document()->isLater(*aListIter, *aResIter)) + break; + } + if (aListIter == aResList.end()) // goes to the end + aResList.push_back(*aResIter); + else + aResList.insert(aListIter, *aResIter); + } else //just push to the end unsorted + aResList.push_back(*aResIter); + } + return aResList; +} + +// LCOV_EXCL_STOP + } // namespace ModelAPI_Tools