X-Git-Url: http://git.salome-platform.org/gitweb/?a=blobdiff_plain;f=src%2FCollectionPlugin%2FCollectionPlugin_Group.cpp;h=bba5dc1e00c83597a2e2463386e57ceea366f543;hb=06e7f5859095193fc7f498bd89a7d28009794f53;hp=82926ab21921946ac76ac567b84f900ec9eb16bb;hpb=010db3efe2e727c4f2cc2e99073e036c5ac07f46;p=modules%2Fshaper.git diff --git a/src/CollectionPlugin/CollectionPlugin_Group.cpp b/src/CollectionPlugin/CollectionPlugin_Group.cpp index 82926ab21..bba5dc1e0 100644 --- a/src/CollectionPlugin/CollectionPlugin_Group.cpp +++ b/src/CollectionPlugin/CollectionPlugin_Group.cpp @@ -1,4 +1,4 @@ -// Copyright (C) 2014-2019 CEA/DEN, EDF R&D +// Copyright (C) 2014-2023 CEA, EDF // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public @@ -24,7 +24,10 @@ #include #include #include +#include #include +#include +#include CollectionPlugin_Group::CollectionPlugin_Group() { @@ -44,3 +47,170 @@ void CollectionPlugin_Group::execute() setResult(aGroup); } } + +// returns name with suffix, not existing in the existing set +static std::wstring findName( + const std::wstring theOrigin, int& theSuffix, std::set& theExisting) +{ + std::wstring aRes; + do { + std::wostringstream aName; + aName<contextFeature().get()) + return 0; + ResultBodyPtr aRes = std::dynamic_pointer_cast(theAttr->context()); + if (aRes.get()) { + int aDepth = 0; + for(aRes = ModelAPI_Tools::bodyOwner(aRes); aRes.get(); aRes = ModelAPI_Tools::bodyOwner(aRes)) + aDepth++; + return aDepth; + } + return 0; +} + +bool CollectionPlugin_Group::customAction(const std::string& theActionId) +{ + if (theActionId == "split") { + DocumentPtr aDoc = document(); + // collect all existing names of features to give unique names + std::set aFeatNames, aResNames; + std::list allFeat = aDoc->allFeatures(); + std::list::iterator allFeatIter = allFeat.begin(); + for(; allFeatIter != allFeat.end(); allFeatIter++) { + FeaturePtr aFeat = *allFeatIter; + if (aFeat->data().get() && aFeat->data()->isValid()) { + aFeatNames.insert(aFeat->name()); + if (aFeat->getKind() == ID() && aFeat->data().get() && aFeat->data()->isValid()) { + std::list::const_iterator aRess = aFeat->results().cbegin(); + for(; aRess != aFeat->results().cend(); aRess++) { + ResultPtr aRes = *aRess; + if (aRes->data().get() && aRes->data()->isValid()) { + aResNames.insert(aRes->data()->name()); + } + } + } + } + } + // searching for the depth on the results, minimal for all contextes: + // groups will be collected at this depth; the root is 0 + int aMinDepth = -1; + std::map aStoredDepth; + AttributeSelectionListPtr aList = selectionList(LIST_ID()); + for (int a = aList->size() - 1; a >= 0; a--) { + AttributeSelectionPtr anAttr = aList->value(a); + if (!anAttr->isInvalid() && anAttr->contextObject().get()) { + int aDepth = getDepth(anAttr); + aStoredDepth[anAttr->contextObject()] = aDepth; + if (aMinDepth == -1 || aDepth < aMinDepth) + aMinDepth = aDepth; + } + } + // get common fathers at the minimal depth and set index of group to them + std::map aFathers; + std::map aFatherGroup; + bool aSplitAnyway = false; + for(int aCurrentDepth = 0; aCurrentDepth <= aMinDepth; aCurrentDepth++) { + aFathers.clear(); + aFatherGroup.clear(); + for (int a = aList->size() - 1; a >= 0; a--) { + // start from zero (this group index), then from the end - as in the next iteration + AttributeSelectionPtr anAttr = aList->value(a); + if (!anAttr->isInvalid() && anAttr->contextObject().get()) { + ObjectPtr anObj = anAttr->contextObject(); + int aDepth = aStoredDepth[anObj]; + if (!aSplitAnyway && aDepth > aCurrentDepth) { + ResultBodyPtr aRes = std::dynamic_pointer_cast(anObj); + while (aDepth > aCurrentDepth) { + aRes = ModelAPI_Tools::bodyOwner(aRes); + aDepth--; + } + anObj = aRes; + } + aFathers[anAttr->contextObject()] = anObj; + if (aFatherGroup.find(anObj) == aFatherGroup.end()) { + int aSize = (int)aFatherGroup.size(); + aFatherGroup[anObj] = aSize; // the first is zero + } + } + } + if (aFatherGroup.size() < (size_t)aList->size() && aFatherGroup.size() != 1) // already good + break; + if (aFatherGroup.size() == (size_t)aList->size()) // no sence to iterate further + break; + if (aFatherGroup.size() == 1 && aList->size() > 1 && aCurrentDepth == aMinDepth) + aSplitAnyway = true; // split anyway, better that just move + } + + std::set aRemoved; + bool aStay = false; // to indicate that the good attribute found stays in the list + // added in the order: 3 2 1 orig=0, so, keep the results to give names later + std::list aResults; + for(int aNext = aList->size() - 1; aNext >= 0; aNext--) { + AttributeSelectionPtr anOldAttr = aList->value(aNext); + if (anOldAttr->isInvalid() || !anOldAttr->contextObject().get()) {// remove invalids + aRemoved.insert(aNext); + continue; + } + if (!aStay) { + aStay = true; + continue; + } + int aFGroup = aFatherGroup[aFathers[anOldAttr->contextObject()]]; + if (!aSplitAnyway && aFGroup == 0) // to stay in this first group + continue; + + aRemoved.insert(aNext); + FeaturePtr aNew; + if (aSplitAnyway || aFGroup > (int)aResults.size()) { + aNew = aDoc->addFeature(ID(), false); + aResults.push_front(aNew); // to keep the order + } else { // appending in already created new result + std::list::reverse_iterator aResIter = aResults.rbegin(); + for (; aFGroup > 1; aResIter++) + aFGroup--; + aNew = *aResIter; + } + + AttributeSelectionListPtr aNewList = aNew->selectionList(LIST_ID()); + aNewList->setSelectionType(aList->selectionType()); + aNewList->append(anOldAttr->contextObject(), anOldAttr->value()); + } + aResults.push_back(std::dynamic_pointer_cast(data()->owner())); + // remove all selections except the first + aList->remove(aRemoved); + // set names + if (aResults.size() > 1) { // rename if there are new groups appeared only + std::list::iterator aResIter = aResults.begin(); + for(int aSuffix = 1; aResIter != aResults.end(); aResIter++) { + FeaturePtr aFeat = std::dynamic_pointer_cast(*aResIter); + aFeat->execute(); + aFeat->data()->setName(findName(name(), aSuffix, aFeatNames)); + if (!aFeat->results().empty() && !results().empty()) { + int aResSuf = aSuffix - 1; + std::wstring aResName = findName(firstResult()->data()->name(), aResSuf, aResNames); + aFeat->firstResult()->data()->setName(aResName); + ModelAPI_Tools::copyVisualizationAttrs(firstResult(), aFeat->firstResult()); + } + } + // remove also filters if split performed + FiltersFeaturePtr aFilters = aList->filters(); + if (aFilters.get()) { + std::list aFiltersList = aFilters->filters(); + std::list::iterator aFilterName = aFiltersList.begin(); + for(; aFilterName != aFiltersList.end(); aFilterName++) { + aFilters->removeFilter(*aFilterName); + } + } + } + } + return true; +}