X-Git-Url: http://git.salome-platform.org/gitweb/?a=blobdiff_plain;f=src%2FModelAPI%2FModelAPI_Tools.cpp;h=a5cd808fda611c026c4e1ba0bbc66c22c9358c79;hb=ebce006a9ba80eab34d5b9e16fab6979fc091a02;hp=f80d20e1b9a9250448009e4923ae56baf8c62eb6;hpb=a8cfbfb436c27ff96edd5c808e9a452c35cef207;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 f80d20e1b..a5cd808fd --- a/src/ModelAPI/ModelAPI_Tools.cpp +++ b/src/ModelAPI/ModelAPI_Tools.cpp @@ -1,25 +1,63 @@ -// Copyright (C) 2014-20xx CEA/DEN, EDF R&D - -// File: ModelAPI_Tools.cpp -// Created: 06 Aug 2014 -// Author: Vitaly Smetannikov +// 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 +// 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 "ModelAPI_Tools.h" #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 +//#define DEBUG_REMOVE_FEATURES_RECURSE +//#define DEBUG_CYCLING_1550 + +#ifdef DEBUG_REMOVE_FEATURES_RECURSE +#include +std::string getFeatureInfo(FeaturePtr theFeature) +{ + if (!theFeature.get()) + return ""; + //std::ostringstream aPtrStr; + //aPtrStr << "[" << theFeature.get() << "] "; + std::string aFeatureInfo = /*aPtrStr.str() + */theFeature->name(); + CompositeFeaturePtr aComposite = ModelAPI_Tools::compositeOwner(theFeature); + if (aComposite.get()) { + aFeatureInfo = aFeatureInfo + "[in " + aComposite->name() + "]"; + } + return aFeatureInfo; +} +#endif #ifdef DEBUG_REMOVE_FEATURES void printMapInfo(const std::map >& theMainList, @@ -42,7 +80,7 @@ void printMapInfo(const std::map >& theMainList anInfo = anInfo + aMainListFeature->name().c_str() + ": " + aRefsInfo + "\n"; } } - std::cout << thePrefix.c_str() << ": " << anInfo.c_str() << std::endl; + std::cout << thePrefix.c_str() << " [feature: references to]: \n" << anInfo.c_str() << std::endl; } void printListInfo(const std::set& theMainList, @@ -68,18 +106,17 @@ std::shared_ptr shape(const ResultPtr& theResult) return theResult->shape(); } -const char* toString(ModelAPI_ExecState theExecState) +// 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) @@ -122,8 +159,10 @@ std::string getFeatureError(const FeaturePtr& theFeature) return anError; } +// LCOV_EXCL_STOP -ObjectPtr objectByName(const DocumentPtr& theDocument, const std::string& theGroup, const std::string& theName) +ObjectPtr objectByName(const DocumentPtr& theDocument, const std::string& theGroup, + const std::string& theName) { for (int anIndex = 0; anIndex < theDocument->size(theGroup); ++anIndex) { ObjectPtr anObject = theDocument->object(theGroup, anIndex); @@ -142,15 +181,19 @@ bool findVariable(const DocumentPtr& theDocument, FeaturePtr theSearcher, if (!theParam.get()) return false; // avoid usage of parameters created later than the initial parameter - if (theSearcher.get() && theDocument->isLater(theDocument->feature(theParam), theSearcher)) - return false; + + if (theSearcher.get()) { + FeaturePtr aParamFeat = theDocument->feature(theParam); + if (aParamFeat == theSearcher || theDocument->isLater(aParamFeat, theSearcher)) + return false; + } AttributeDoublePtr aValueAttribute = theParam->data()->real(ModelAPI_ResultParameter::VALUE()); outValue = aValueAttribute->value(); return true; } -bool findVariable(FeaturePtr theSearcher, const std::string& theName, double& outValue, ResultParameterPtr& theParam, - const DocumentPtr& theDocument) +bool findVariable(FeaturePtr theSearcher, const std::string& theName, double& outValue, + ResultParameterPtr& theParam, const DocumentPtr& theDocument) { SessionPtr aSession = ModelAPI_Session::get(); std::list aDocList; @@ -166,104 +209,11 @@ bool findVariable(FeaturePtr theSearcher, const std::string& theName, double& ou return false; } -static std::map > myColorMap; - -void appendValues(std::vector& theRGB, const int theRed, const int theGreen, const int theBlue) -{ - theRGB.push_back(theRed); - theRGB.push_back(theGreen); - theRGB.push_back(theBlue); -} - -bool containsValues(std::map >& theColorMap, std::vector& theValues) -{ - std::map >::const_iterator anIt = theColorMap.begin(), aLast = theColorMap.end(); - bool isFound = false; - for (; anIt != aLast && !isFound; anIt++) { - std::vector aValues = anIt->second; - isFound = aValues[0] == theValues[0] && - aValues[1] == theValues[1] && - aValues[2] == theValues[2]; - } - return isFound; -} - -std::vector HSVtoRGB(int theH, int theS, int theV) -{ - std::vector aRGB; - if (theH < 0 || theH > 360 || - theS < 0 || theS > 100 || - theV < 0 || theV > 100) - return aRGB; - - int aHi = (int)theH/60; - - double aV = theV; - double aVmin = (100 - theS)*theV/100; - - double anA = (theV - aVmin)* (theH % 60) / 60; - - double aVinc = aVmin + anA; - double aVdec = theV - anA; - - double aPercentToValue = 255./100; - int aV_int = (int)(aV*aPercentToValue); - int aVinc_int = (int)(aVinc*aPercentToValue); - int aVmin_int = (int)(aVmin*aPercentToValue); - int aVdec_int = (int)(aVdec*aPercentToValue); - - switch(aHi) { - case 0: appendValues(aRGB, aV_int, aVinc_int, aVmin_int); break; - case 1: appendValues(aRGB, aVdec_int, aV_int, aVmin_int); break; - case 2: appendValues(aRGB, aVmin_int, aV_int, aVinc_int); break; - case 3: appendValues(aRGB, aVmin_int, aVdec_int, aV_int); break; - case 4: appendValues(aRGB, aVinc_int, aVmin_int, aV_int); break; - case 5: appendValues(aRGB, aV_int, aVmin_int, aVdec_int); break; - default: break; - } - return aRGB; -} - - -void fillColorMap() -{ - if (!myColorMap.empty()) - return; - - int i = 0; - for (int s = 100; s > 0; s = s - 50) - { - for (int v = 100; v >= 40; v = v - 20) - { - for (int h = 0; h < 359 ; h = h + 60) - { - std::vector aColor = HSVtoRGB(h, s, v); - if (containsValues(myColorMap, aColor)) - continue; - myColorMap[i] = aColor; - i++; - } - } - } -} - -void findRandomColor(std::vector& theValues) -{ - theValues.clear(); - if (myColorMap.empty()) { - fillColorMap(); - } - - size_t aSize = myColorMap.size(); - int anIndex = rand() % aSize; - if (myColorMap.find(anIndex) != myColorMap.end()) { - theValues = myColorMap.at(anIndex); - } -} - ResultPtr findPartResult(const DocumentPtr& theMain, const DocumentPtr& theSub) { - if (theMain != theSub) { // to optimize and avoid of crash on partset document close (don't touch the sub-document structure) + // to optimize and avoid of crash on partset document close + // (don't touch the sub-document structure) + if (theMain != theSub) { for (int a = theMain->size(ModelAPI_ResultPart::group()) - 1; a >= 0; a--) { ResultPartPtr aPart = std::dynamic_pointer_cast( theMain->object(ModelAPI_ResultPart::group(), a)); @@ -277,8 +227,12 @@ ResultPtr findPartResult(const DocumentPtr& theMain, const DocumentPtr& theSub) FeaturePtr findPartFeature(const DocumentPtr& theMain, const DocumentPtr& theSub) { - if (theMain != theSub) { // to optimize and avoid of crash on partset document close (don't touch the sub-document structure) - for (int a = theMain->size(ModelAPI_Feature::group()) - 1; a >= 0; a--) { + // to optimize and avoid of crash on partset document close + // (don't touch the sub-document structure) + if (theMain != theSub) { + // iteration from top to bottom to avoid finding the movement documents before the original + int aSize = theMain->size(ModelAPI_Feature::group()); + for (int a = 0; a < aSize; a++) { FeaturePtr aPartFeat = std::dynamic_pointer_cast( theMain->object(ModelAPI_Feature::group(), a)); if (aPartFeat.get()) { @@ -299,7 +253,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++) { @@ -312,44 +266,64 @@ 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) { + // 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); + 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); } } @@ -405,6 +379,7 @@ bool removeFeaturesAndReferences(const std::set& theFeatures, return ModelAPI_Tools::removeFeatures(aFeatures, false); } +//*********************************************************************** bool removeFeatures(const std::set& theFeatures, const bool theFlushRedisplay) { @@ -421,13 +396,15 @@ bool removeFeatures(const std::set& theFeatures, } } if (isDone && theFlushRedisplay) { - // the redisplay signal should be flushed in order to erase the feature presentation in the viewer + // the redisplay signal should be flushed in order to erase + // the feature presentation in the viewer // if should be done after removeFeature() of document Events_Loop::loop()->flush(Events_Loop::loop()->eventByName(EVENT_OBJECT_TO_REDISPLAY)); } 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 @@ -435,8 +412,13 @@ bool removeFeatures(const std::set& theFeatures, // \param theReferences an out container of references void addRefsToFeature(const FeaturePtr& theFeature, const std::map >& theReferencesMap, + int theRecLevel, std::set& theReferences) { + if (theRecLevel > RECURSE_TOP_LEVEL) + return; + theRecLevel++; + 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); @@ -445,9 +427,10 @@ void addRefsToFeature(const FeaturePtr& theFeature, aLast = aMainReferences.end(); for (; anIt != aLast; anIt++) { FeaturePtr aRefFeature = *anIt; - if (theReferences.find(aRefFeature) == theReferences.end()) + if (theReferences.find(aRefFeature) == theReferences.end()) { + addRefsToFeature(aRefFeature, theReferencesMap, theRecLevel, theReferences); theReferences.insert(aRefFeature); - addRefsToFeature(aRefFeature, theReferencesMap, theReferences); + } } } @@ -458,8 +441,11 @@ void addRefsToFeature(const FeaturePtr& theFeature, // \param theReferences an out container of references void findReferences(const std::set& theFeatures, std::map >& theReferences, - const bool theUseComposite, const bool theUseRecursion) + const bool theUseComposite, const bool theUseRecursion, int theRecLevel) { + if (theRecLevel > RECURSE_TOP_LEVEL) + return; + theRecLevel++; std::set::const_iterator anIt = theFeatures.begin(), aLast = theFeatures.end(); for (; anIt != aLast; anIt++) { @@ -477,15 +463,23 @@ void findReferences(const std::set& theFeatures, aLast = aSelRefFeatures.end(); for (; anIt != aLast; anIt++) { FeaturePtr aCFeature = *anIt; - CompositeFeaturePtr aComposite = std::dynamic_pointer_cast(aCFeature); + CompositeFeaturePtr aComposite = + std::dynamic_pointer_cast(aCFeature); if (aComposite.get() && aComposite->isSub(aFeature)) continue; /// composite of the current feature should be skipped aFilteredFeatures.insert(aCFeature); } theReferences[aFeature] = aFilteredFeatures; } - if (theUseRecursion) - findReferences(aSelRefFeatures, theReferences, theUseComposite, theUseRecursion); + if (theUseRecursion) { +#ifdef DEBUG_CYCLING_1550 + findReferences(aSelRefFeatures, theReferences, theUseComposite, + theUseRecursion, theRecLevel); +#else + findReferences(theReferences[aFeature], theReferences, theUseComposite, theUseRecursion, + theRecLevel); +#endif + } } } } @@ -505,7 +499,8 @@ void findAllReferences(const std::set& theFeatures, // Information: bool_1 is not selected, ext_2(bool_2) exists // find all referenced features std::map > aMainList; - findReferences(theFeatures, aMainList, theUseComposite, theUseRecursion); + int aRecLevel = 0; + findReferences(theFeatures, aMainList, theUseComposite, theUseRecursion, aRecLevel); #ifdef DEBUG_REMOVE_FEATURES printMapInfo(aMainList, "firstDependencies"); @@ -521,18 +516,36 @@ void findAllReferences(const std::set& theFeatures, aMainLast = aMainList.end(); for (; aMainIt != aMainLast; aMainIt++) { FeaturePtr aMainListFeature = aMainIt->first; + //std::string aName = aMainListFeature->name(); std::set aMainRefList = aMainIt->second; - std::set anAddRefFeatures; +#ifdef DEBUG_REMOVE_FEATURES_RECURSE + char aBuf[50]; + int n = sprintf(aBuf, "%d", aMainRefList.size()); + std::string aSize(aBuf); + std::cout << "_findAllReferences for the Feature: " << getFeatureInfo(aMainListFeature) + << ", references size = " << aSize << std::endl; +#endif std::set::const_iterator anIt = aMainRefList.begin(), aLast = aMainRefList.end(); + std::set aResultRefList; + aResultRefList.insert(aMainRefList.begin(), aMainRefList.end()); for (; anIt != aLast; anIt++) { FeaturePtr aFeature = *anIt; - addRefsToFeature(aFeature, aMainList, aMainRefList); + int aRecLevel = 0; +#ifdef DEBUG_REMOVE_FEATURES_RECURSE + std::cout << " Ref: " << getFeatureInfo(aFeature) << std::endl; +#endif + aRecLevel++; + addRefsToFeature(aFeature, aMainList, + aRecLevel, aResultRefList/*aMainRefList*/); } - theReferences[aMainListFeature] = aMainRefList; + theReferences[aMainListFeature] = aResultRefList; } +#ifdef DEBUG_REMOVE_FEATURES_RECURSE + std::cout << std::endl; +#endif #ifdef DEBUG_REMOVE_FEATURES printMapInfo(theReferences, "allDependencies"); @@ -553,7 +566,8 @@ void findRefsToFeatures(const std::set& theFeatures, std::set::const_iterator aRefIt = aRefList.begin(), aRefLast = aRefList.end(); for (; aRefIt != aRefLast; aRefIt++) { FeaturePtr aRefFeature = *aRefIt; - CompositeFeaturePtr aComposite = std::dynamic_pointer_cast(aRefFeature); + CompositeFeaturePtr aComposite = + std::dynamic_pointer_cast(aRefFeature); if (aComposite.get() && aComposite->isSub(aFeature)) continue; /// composite of the current feature should not be removed @@ -564,4 +578,184 @@ void findRefsToFeatures(const std::set& theFeatures, } } +void getConcealedResults(const FeaturePtr& theFeature, + std::list >& theResults) +{ + SessionPtr aSession = ModelAPI_Session::get(); + + std::list > > > aRefs; + theFeature->data()->referencesToObjects(aRefs); + std::list > >::const_iterator + anIt = aRefs.begin(), aLast = aRefs.end(); + std::set alreadyThere; // to avoid duplications + for (; anIt != aLast; anIt++) { + if (!aSession->validators()->isConcealed(theFeature->getKind(), anIt->first)) + continue; // use only concealed attributes + std::list anObjects = (*anIt).second; + std::list::const_iterator anOIt = anObjects.begin(), anOLast = anObjects.end(); + for (; anOIt != anOLast; anOIt++) { + ResultPtr aResult = std::dynamic_pointer_cast(*anOIt); + if (aResult && aResult->isConcealed()) { + if (alreadyThere.find(aResult) == alreadyThere.end()) // issue 1712, avoid duplicates + alreadyThere.insert(aResult); + else continue; + theResults.push_back(aResult); + } + } + } +} + +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::ostringstream 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()->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::stringstream 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::stringstream 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; +} + } // namespace ModelAPI_Tools