-// 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 <ModelAPI_Session.h>
+#include <ModelAPI_CompositeFeature.h>
#include <ModelAPI_Document.h>
#include <ModelAPI_Object.h>
#include <ModelAPI_AttributeDouble.h>
+#include <ModelAPI_ResultBody.h>
#include <ModelAPI_ResultParameter.h>
#include <ModelAPI_ResultPart.h>
#include <ModelAPI_AttributeDocRef.h>
+#include <ModelAPI_Validator.h>
#include <list>
#include <map>
#include <iostream>
+#include <sstream>
#include <Events_Loop.h>
#include <ModelAPI_Events.h>
+#define RECURSE_TOP_LEVEL 50
+
//#define DEBUG_REMOVE_FEATURES
+//#define DEBUG_REMOVE_FEATURES_RECURSE
+//#define DEBUG_CYCLING_1550
+
+#ifdef DEBUG_REMOVE_FEATURES_RECURSE
+#include <sstream>
+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<FeaturePtr, std::set<FeaturePtr> >& 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<FeaturePtr>& theMainList,
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)
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);
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<DocumentPtr> aDocList;
return true;
DocumentPtr aRootDocument = aSession->moduleDocument();
if (aDocument != aRootDocument) {
- ResultPtr aPartResult = findPartResult(aRootDocument, aDocument);
- if (aPartResult.get()) {
- FeaturePtr aPartFeature;
- if (theSearcher.get()) // only if the relative search is needed
- aPartFeature = aRootDocument->feature(aPartResult);
- if (findVariable(aRootDocument, aPartFeature, theName, outValue, theParam))
- return true;
- }
+ // any parameters in PartSet is okindependently on the Part position (issu #1504)
+ if (findVariable(aRootDocument, FeaturePtr(), theName, outValue, theParam))
+ return true;
}
return false;
}
-static std::map<int, std::vector<int> > myColorMap;
-
-void appendValues(std::vector<int>& 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<int, std::vector<int> >& theColorMap, std::vector<int>& theValues)
-{
- std::map<int, std::vector<int> >::const_iterator anIt = theColorMap.begin(), aLast = theColorMap.end();
- bool isFound = false;
- for (; anIt != aLast && !isFound; anIt++) {
- std::vector<int> aValues = anIt->second;
- isFound = aValues[0] == theValues[0] &&
- aValues[1] == theValues[1] &&
- aValues[2] == theValues[2];
- }
- return isFound;
-}
-
-std::vector<int> HSVtoRGB(int theH, int theS, int theV)
-{
- std::vector<int> 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<int> aColor = HSVtoRGB(h, s, v);
- if (containsValues(myColorMap, aColor))
- continue;
- myColorMap[i] = aColor;
- i++;
- }
- }
- }
-}
-
-void findRandomColor(std::vector<int>& 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<ModelAPI_ResultPart>(
theMain->object(ModelAPI_ResultPart::group(), a));
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<ModelAPI_Feature>(
theMain->object(ModelAPI_Feature::group(), a));
if (aPartFeat.get()) {
CompositeFeaturePtr compositeOwner(const FeaturePtr& theFeature)
{
- if (theFeature.get() && theFeature->data()->isValid()) {
+ if (theFeature.get() && theFeature->data() && theFeature->data()->isValid()) {
const std::set<std::shared_ptr<ModelAPI_Attribute> >& aRefs = theFeature->data()->refsToMe();
std::set<std::shared_ptr<ModelAPI_Attribute> >::const_iterator aRefIter = aRefs.begin();
for(; aRefIter != aRefs.end(); aRefIter++) {
return CompositeFeaturePtr(); // not found
}
-ResultCompSolidPtr compSolidOwner(const ResultPtr& theSub)
+ResultBodyPtr bodyOwner(const ResultPtr& theSub, const bool theRoot)
{
- ResultBodyPtr aBody = std::dynamic_pointer_cast<ModelAPI_ResultBody>(theSub);
- if (aBody.get()) {
- FeaturePtr aFeatureOwner = aBody->document()->feature(aBody);
- if (aFeatureOwner.get()) {
- std::list<std::shared_ptr<ModelAPI_Result> >::const_iterator aResIter =
- aFeatureOwner->results().cbegin();
- for(; aResIter != aFeatureOwner->results().cend(); aResIter++) {
- ResultCompSolidPtr aComp = std::dynamic_pointer_cast<ModelAPI_ResultCompSolid>(*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<ModelAPI_Result>(aParent);
+ ResultBodyPtr aGrandParent = bodyOwner(aResultParent, true);
+ if (aGrandParent.get())
+ aParent = aGrandParent;
}
+ return std::dynamic_pointer_cast<ModelAPI_ResultBody>(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<ModelAPI_ResultBody>(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<ModelAPI_ResultCompSolid>(theResult);
+ ResultBodyPtr aCompSolid = std::dynamic_pointer_cast<ModelAPI_ResultBody>(theResult);
return aCompSolid.get() && aCompSolid->numberOfSubs() > 0;
}
+void allSubs(const ResultBodyPtr& theResult, std::list<ResultPtr>& theResults) {
+ // iterate sub-bodies of compsolid
+ ResultBodyPtr aComp = std::dynamic_pointer_cast<ModelAPI_ResultBody>(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<ResultPtr>& theResults)
{
+ if (!theFeature.get()) // safety: for empty feature no results
+ return;
const std::list<std::shared_ptr<ModelAPI_Result> >& aResults = theFeature->results();
- std::list<std::shared_ptr<ModelAPI_Result> >::const_iterator aRIter = aResults.begin();
+ std::list<ResultPtr>::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<ModelAPI_ResultCompSolid>(*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<ModelAPI_ResultBody>(*aRIter);
+ allSubs(aResult, theResults);
}
}
return ModelAPI_Tools::removeFeatures(aFeatures, false);
}
+//***********************************************************************
bool removeFeatures(const std::set<FeaturePtr>& theFeatures,
const bool theFlushRedisplay)
{
}
}
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
// \param theReferences an out container of references
void addRefsToFeature(const FeaturePtr& theFeature,
const std::map<FeaturePtr, std::set<FeaturePtr> >& theReferencesMap,
+ int theRecLevel,
std::set<FeaturePtr>& 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<FeaturePtr> aMainReferences = theReferencesMap.at(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);
+ }
}
}
// \param theReferences an out container of references
void findReferences(const std::set<FeaturePtr>& theFeatures,
std::map<FeaturePtr, std::set<FeaturePtr> >& theReferences,
- const bool theUseComposite, const bool theUseRecursion)
+ const bool theUseComposite, const bool theUseRecursion, int theRecLevel)
{
+ if (theRecLevel > RECURSE_TOP_LEVEL)
+ return;
+ theRecLevel++;
std::set<FeaturePtr>::const_iterator anIt = theFeatures.begin(),
aLast = theFeatures.end();
for (; anIt != aLast; anIt++) {
aLast = aSelRefFeatures.end();
for (; anIt != aLast; anIt++) {
FeaturePtr aCFeature = *anIt;
- CompositeFeaturePtr aComposite = std::dynamic_pointer_cast<ModelAPI_CompositeFeature>(aCFeature);
+ CompositeFeaturePtr aComposite =
+ std::dynamic_pointer_cast<ModelAPI_CompositeFeature>(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
+ }
}
}
}
// Information: bool_1 is not selected, ext_2(bool_2) exists
// find all referenced features
std::map<FeaturePtr, std::set<FeaturePtr> > aMainList;
- findReferences(theFeatures, aMainList, theUseComposite, theUseRecursion);
+ int aRecLevel = 0;
+ findReferences(theFeatures, aMainList, theUseComposite, theUseRecursion, aRecLevel);
#ifdef DEBUG_REMOVE_FEATURES
printMapInfo(aMainList, "firstDependencies");
aMainLast = aMainList.end();
for (; aMainIt != aMainLast; aMainIt++) {
FeaturePtr aMainListFeature = aMainIt->first;
+
//std::string aName = aMainListFeature->name();
std::set<FeaturePtr> aMainRefList = aMainIt->second;
- std::set<FeaturePtr> 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<FeaturePtr>::const_iterator anIt = aMainRefList.begin(),
aLast = aMainRefList.end();
+ std::set<FeaturePtr> 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");
std::set<FeaturePtr>::const_iterator aRefIt = aRefList.begin(), aRefLast = aRefList.end();
for (; aRefIt != aRefLast; aRefIt++) {
FeaturePtr aRefFeature = *aRefIt;
- CompositeFeaturePtr aComposite = std::dynamic_pointer_cast<ModelAPI_CompositeFeature>(aRefFeature);
+ CompositeFeaturePtr aComposite =
+ std::dynamic_pointer_cast<ModelAPI_CompositeFeature>(aRefFeature);
if (aComposite.get() && aComposite->isSub(aFeature))
continue; /// composite of the current feature should not be removed
}
}
-} // namespace ModelAPI_Tools
+void getConcealedResults(const FeaturePtr& theFeature,
+ std::list<std::shared_ptr<ModelAPI_Result> >& theResults)
+{
+ SessionPtr aSession = ModelAPI_Session::get();
+
+ std::list<std::pair<std::string, std::list<std::shared_ptr<ModelAPI_Object> > > > aRefs;
+ theFeature->data()->referencesToObjects(aRefs);
+ std::list<std::pair<std::string, std::list<ObjectPtr> > >::const_iterator
+ anIt = aRefs.begin(), aLast = aRefs.end();
+ std::set<ResultPtr> alreadyThere; // to avoid duplications
+ for (; anIt != aLast; anIt++) {
+ if (!aSession->validators()->isConcealed(theFeature->getKind(), anIt->first))
+ continue; // use only concealed attributes
+ std::list<ObjectPtr> anObjects = (*anIt).second;
+ std::list<ObjectPtr>::const_iterator anOIt = anObjects.begin(), anOLast = anObjects.end();
+ for (; anOIt != anOLast; anOIt++) {
+ ResultPtr aResult = std::dynamic_pointer_cast<ModelAPI_Result>(*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<std::string, bool> getDefaultName(const std::shared_ptr<ModelAPI_Result>& theResult,
+ const bool theInherited)
+{
+ typedef std::list< std::pair < std::string, std::list<ObjectPtr> > > 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<std::string, bool>(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<ResultPtr>& anOwnerResults = anOwner->results();
+ std::list<ResultPtr>::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<ResultPtr, int> aNbRefToObject;
+ // search the object by result index
+ std::list<ObjectPtr>::const_iterator anObjIt = aFoundRef->second.begin();
+ int aResultIndex = anIndexInOwner;
+ while (--aResultIndex >= 0) {
+ ResultPtr aCurRes = std::dynamic_pointer_cast<ModelAPI_Result>(*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<ModelAPI_Result>(*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<ResultPtr, int>::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<std::string, bool>(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<std::string, bool>(aDefaultName.str(), false);
+}
+std::set<FeaturePtr> getParents(const FeaturePtr& theFeature)
+{
+ std::set<FeaturePtr> aParents;
+ for (FeaturePtr aCurFeat = theFeature; aCurFeat; ) {
+ CompositeFeaturePtr aFoundComposite;
+ const std::set<AttributePtr>& aRefs = aCurFeat->data()->refsToMe();
+ for (std::set<AttributePtr>::const_iterator anIt = aRefs.begin();
+ anIt != aRefs.end(); ++anIt) {
+ FeaturePtr aF = ModelAPI_Feature::feature((*anIt)->owner());
+ aFoundComposite = std::dynamic_pointer_cast<ModelAPI_CompositeFeature>(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<FeaturePtr> aPartSetFeatures = aPartSetDoc->allFeatures();
+ for (std::list<FeaturePtr>::const_iterator anIt = aPartSetFeatures.begin();
+ anIt != aPartSetFeatures.end(); ++anIt) {
+ aFoundComposite = std::dynamic_pointer_cast<ModelAPI_CompositeFeature>(*anIt);
+ if (aFoundComposite && aFoundComposite->isSub(aCurFeat)) {
+ aParents.insert(aFoundComposite);
+ break;
+ }
+ }
+
+ aCurFeat = FeaturePtr();
+ }
+ }
+ return aParents;
+}
+
+} // namespace ModelAPI_Tools