X-Git-Url: http://git.salome-platform.org/gitweb/?a=blobdiff_plain;f=src%2FModel%2FModel_Objects.cpp;h=505a8a81208a6efddda704d65100edbbe8a5c532;hb=5fb6a80c4e86e21b1181b4e6ee940d946b5c52e4;hp=35df5f6816e3d7f3e54d3ad451de29d91f38efff;hpb=1fc65915c37c446c6308054ebbaaea5dba7e76d3;p=modules%2Fshaper.git diff --git a/src/Model/Model_Objects.cpp b/src/Model/Model_Objects.cpp index 35df5f681..505a8a812 100644 --- a/src/Model/Model_Objects.cpp +++ b/src/Model/Model_Objects.cpp @@ -26,7 +26,6 @@ #include #include #include -#include #include #include #include @@ -60,6 +59,22 @@ static const std::string& groupNameFoldering(const std::string& theGroupID, return theGroupID; } +// Check theFeature is a first or last feature in folder and return this folder +static FolderPtr inFolder(const FeaturePtr& theFeature, const std::string& theFolderAttr) +{ + const std::set& aRefs = theFeature->data()->refsToMe(); + for (std::set::iterator anIt = aRefs.begin(); anIt != aRefs.end(); ++anIt) { + if ((*anIt)->id() != theFolderAttr) + continue; + + ObjectPtr anOwner = (*anIt)->owner(); + FolderPtr aFolder = std::dynamic_pointer_cast(anOwner); + if (aFolder.get()) + return aFolder; + } + return FolderPtr(); +} + static const int TAG_OBJECTS = 2; // tag of the objects sub-tree (features, results) @@ -160,12 +175,24 @@ void Model_Objects::addFeature(FeaturePtr theFeature, const FeaturePtr theAfterT // store feature in the features array: before "initData" because in macro features // in initData it creates new features, appeared later than this TDF_Label aPrevFeateureLab; + FolderPtr aParentFolder; if (theAfterThis.get()) { // searching for the previous feature label std::shared_ptr aPrevData = std::dynamic_pointer_cast(theAfterThis->data()); if (aPrevData.get()) { aPrevFeateureLab = aPrevData->label().Father(); } + // Check if the previous feature is the last feature in a folder, + // then the folder should be updated to contain additional feature. + // Macro features are not stored in folder. + if (!theFeature->isMacro()) { + // If the last feature is a sub-feature of composite, use parent feature + // to check belonging to a folder. + FeaturePtr afterThis = ModelAPI_Tools::compositeOwner(theAfterThis); + if (!afterThis) + afterThis = theAfterThis; + aParentFolder = inFolder(afterThis, ModelAPI_Folder::LAST_FEATURE_ID()); + } } AddToRefArray(aFeaturesLab, aFeatureLab, aPrevFeateureLab); @@ -183,6 +210,12 @@ void Model_Objects::addFeature(FeaturePtr theFeature, const FeaturePtr theAfterT // must be after binding to the map because of "Box" macro feature that // creates other features in "initData" initData(theFeature, aFeatureLab, TAG_FEATURE_ARGUMENTS); + // put feature to the end of folder if it is added while + // the history line is set to the last feature from the folder + if (aParentFolder) { + aParentFolder->reference(ModelAPI_Folder::LAST_FEATURE_ID())->setValue(theFeature); + updateHistory(ModelAPI_Folder::group()); + } // event: feature is added, mist be before "initData" to update OB correctly on Duplicate: // first new part, then the content static Events_ID anEvent = Events_Loop::eventByName(EVENT_OBJECT_CREATED); @@ -281,6 +314,8 @@ void Model_Objects::removeFeature(FeaturePtr theFeature) aComposite->removeFeature(theFeature); } } + // remove feature from folder + removeFromFolder(std::list(1, theFeature)); // this must be before erase since theFeature erasing removes all information about // the feature results and groups of results // To reproduce: create sketch, extrusion, remove sketch => constructions tree is not updated @@ -343,6 +378,9 @@ void Model_Objects::moveFeature(FeaturePtr theMoved, FeaturePtr theAfterThis) if (theAfterThis.get()) anAfterLab = std::dynamic_pointer_cast(theAfterThis->data())->label().Father(); + // check whether some folder refers to the moved feature by start or end: if yes, remove from it + removeFromFolder(std::list(1, theMoved)); + Handle(TDataStd_HLabelArray1) aNewArray = new TDataStd_HLabelArray1(aRefs->Lower(), aRefs->Upper()); int aPassedMovedFrom = 0; // the prev feature location is found and passed @@ -451,7 +489,7 @@ void Model_Objects::createHistory(const std::string& theGroupID) } else { // it may be a folder - ObjectPtr aFolder = folder(aRefs->Value(a)); + const ObjectPtr& aFolder = folder(aRefs->Value(a)); if (aFolder.get()) { // store folder information for the Features group only if (isFeature || isFolder) { @@ -499,11 +537,12 @@ void Model_Objects::updateHistory(const std::string theGroup) } } -ObjectPtr Model_Objects::folder(TDF_Label theLabel) const +const ObjectPtr& Model_Objects::folder(TDF_Label theLabel) const { if (myFolders.IsBound(theLabel)) return myFolders.Find(theLabel); - return ObjectPtr(); + static ObjectPtr anEmptyResult; + return anEmptyResult; } FeaturePtr Model_Objects::feature(TDF_Label theLabel) const @@ -519,41 +558,54 @@ ObjectPtr Model_Objects::object(TDF_Label theLabel) FeaturePtr aFeature = feature(theLabel); if (aFeature.get()) return feature(theLabel); - TDF_Label aFeatureLabel = theLabel.Father().Father(); // let's suppose it is result - aFeature = feature(aFeatureLabel); - bool isSubResult = false; - if (!aFeature.get() && aFeatureLabel.Depth() > 1) { // let's suppose this is sub-result of result + TDF_Label aFeatureLabel = theLabel; // let's suppose it is result of this feature + TDF_LabelList aSubLabs; // sub - labels from higher level to lower level of result + while(!aFeature.get() && aFeatureLabel.Depth() > 1) { + aSubLabs.Prepend(aFeatureLabel); aFeatureLabel = aFeatureLabel.Father().Father(); aFeature = feature(aFeatureLabel); - isSubResult = true; } if (aFeature.get()) { - const std::list >& aResults = aFeature->results(); - std::list >::const_iterator aRIter = aResults.cbegin(); - for (; aRIter != aResults.cend(); aRIter++) { - if (isSubResult) { - ResultCompSolidPtr aCompRes = std::dynamic_pointer_cast(*aRIter); - if (aCompRes.get()) { - int aNumSubs = aCompRes->numberOfSubs(); - for(int a = 0; a < aNumSubs; a++) { - ResultPtr aSub = aCompRes->subResult(a); - if (aSub.get()) { - std::shared_ptr aSubData = std::dynamic_pointer_cast( - aSub->data()); - if (aSubData->label().Father().IsEqual(theLabel)) - return aSub; + ResultPtr aCurrentResult; + // searching for results then sub-results label by label + for(TDF_ListIteratorOfLabelList aSubLab(aSubLabs); aSubLab.More(); aSubLab.Next()) { + if (aCurrentResult.get()) { // iterate sub-results of result + ResultBodyPtr anOwner = std::dynamic_pointer_cast(aCurrentResult); + if (!anOwner) + return ObjectPtr(); // only Body can have sub-results + int a, aNumSubs = anOwner->numberOfSubs(); + for(a = 0; a < aNumSubs; a++) { + ResultPtr aSub = anOwner->subResult(a); + if (aSub.get()) { + std::shared_ptr aSubData = std::dynamic_pointer_cast( + aSub->data()); + const TDF_Label& aSubLabVal = aSubLab.ChangeValue(); + if (aSubData->label().Father().IsEqual(aSubLabVal)) { + aCurrentResult = aSub; + break; } } } - } else { - std::shared_ptr aResData = std::dynamic_pointer_cast( - (*aRIter)->data()); - if (aResData->label().Father().IsEqual(theLabel)) - return *aRIter; + if (a == aNumSubs) // not found an appropriate sub-result of result + return ObjectPtr(); + } else { // iterate results of feature + const std::list& aResults = aFeature->results(); + std::list >::const_iterator aRIter = aResults.cbegin(); + for(; aRIter != aResults.cend(); aRIter++) { + std::shared_ptr aResData = + std::dynamic_pointer_cast((*aRIter)->data()); + if (aResData->label().Father().IsEqual(aSubLab.ChangeValue())) { + aCurrentResult = *aRIter; + break; + } + } + if (aRIter == aResults.cend()) // not found an appropriate result of feature + return ObjectPtr(); } } + return aCurrentResult; } - return FeaturePtr(); // not found + return ObjectPtr(); // not found } ObjectPtr Model_Objects::object(const std::string& theGroupID, @@ -564,6 +616,9 @@ ObjectPtr Model_Objects::object(const std::string& theGroupID, return ObjectPtr(); createHistory(theGroupID); const std::string& aGroupID = groupNameFoldering(theGroupID, theAllowFolder); + const std::vector& aVec = myHistory[theGroupID]; + //if (aVec.size() <= theIndex) + // return aVec[aVec.size() - 1]; // too high index requested (to avoid crash in #2360) return aGroupID.empty() ? myHistory[theGroupID][theIndex] : myHistory[aGroupID][theIndex]; } @@ -582,24 +637,12 @@ std::shared_ptr Model_Objects::objectByName( std::list > allObjs = allFeatures(); std::list >::iterator anObjIter = allObjs.begin(); for(; anObjIter != allObjs.end(); anObjIter++) { - const std::list >& aResults = (*anObjIter)->results(); - std::list >::const_iterator aRIter = aResults.cbegin(); - for (; aRIter != aResults.cend(); aRIter++) { - if (aRIter->get() && (*aRIter)->groupName() == theGroupID) { - if ((*aRIter)->data()->name() == theName) - return *aRIter; - ResultCompSolidPtr aCompRes = - std::dynamic_pointer_cast(*aRIter); - if (aCompRes.get()) { - int aNumSubs = aCompRes->numberOfSubs(); - for(int a = 0; a < aNumSubs; a++) { - ResultPtr aSub = aCompRes->subResult(a); - if (aSub.get() && aSub->groupName() == theGroupID) { - if (aSub->data()->name() == theName) - return aSub; - } - } - } + std::list allRes; + ModelAPI_Tools::allResults(*anObjIter, allRes); + for(std::list::iterator aRes = allRes.begin(); aRes != allRes.end(); aRes++) { + if (aRes->get() && (*aRes)->groupName() == theGroupID) { + if ((*aRes)->data()->name() == theName) + return *aRes; } } } @@ -638,6 +681,21 @@ int Model_Objects::size(const std::string& theGroupID, const bool theAllowFolder return aGroupID.empty() ? int(myHistory[theGroupID].size()) : int(myHistory[aGroupID].size()); } +std::shared_ptr Model_Objects::parent( + const std::shared_ptr theChild) +{ + if (theChild.get()) { + std::shared_ptr aData = std::dynamic_pointer_cast(theChild->data()); + TDF_Label aLab = aData->label(); + if (!aLab.IsNull() && aLab.Depth() > 2) { + ObjectPtr anObj = object(aLab.Father().Father().Father()); + return anObj; + } + } + return ObjectPtr(); +} + + void Model_Objects::allResults(const std::string& theGroupID, std::list& theResults) { // iterate the array of references and get feature by feature from the array @@ -998,6 +1056,35 @@ void Model_Objects::synchronizeBackRefsForObject(const std::set& t } else aCurrentIter++; } } + // for the last feature in the folder, check if it is a sub-feature, + // then refer the folder to a top-level parent composite feature + const std::set& aRefs = aData->refsToMe(); + std::set::iterator anIt = aRefs.begin(); + for (; anIt != aRefs.end(); ++anIt) + if ((*anIt)->id() == ModelAPI_Folder::LAST_FEATURE_ID()) + break; + if (anIt != aRefs.end()) { + FeaturePtr aFeature = ModelAPI_Feature::feature(theObject); + if (aFeature) { + CompositeFeaturePtr aParent; + CompositeFeaturePtr aGrandParent = ModelAPI_Tools::compositeOwner(aFeature); + do { + aParent = aGrandParent; + if (aGrandParent) + aGrandParent = ModelAPI_Tools::compositeOwner(aParent); + } while (aGrandParent.get()); + if (aParent) { + ObjectPtr aFolder = (*anIt)->owner(); + // remove reference from the current feature + aData->removeBackReference(aFolder, ModelAPI_Folder::LAST_FEATURE_ID()); + // set reference to a top-level parent + aFolder->data()->reference(ModelAPI_Folder::LAST_FEATURE_ID())->setValue(aParent); + std::shared_ptr aParentData = + std::dynamic_pointer_cast(aParent->data()); + aParentData->addBackReference(aFolder, ModelAPI_Folder::LAST_FEATURE_ID()); + } + } + } aData->updateConcealmentFlag(); } @@ -1097,29 +1184,33 @@ bool Model_Objects::hasCustomName(DataPtr theFeatureData, int theResultIndex, std::string& theParentName) const { - ResultCompSolidPtr aCompSolidRes = - std::dynamic_pointer_cast(theFeatureData->owner()); - if (aCompSolidRes) { - FeaturePtr anOwner = ModelAPI_Feature::feature(theResult->data()->owner()); + ResultBodyPtr aBodyRes = std::dynamic_pointer_cast(theFeatureData->owner()); + if (aBodyRes) { + // only for top-results (works for the cases when results are not yet added to the feature) + FeaturePtr anOwner = ModelAPI_Feature::feature(theResult); // names of sub-solids in CompSolid should be default (for example, // result of boolean operation 'Boolean_1' is a CompSolid which is renamed to 'MyBOOL', // however, sub-elements of 'MyBOOL' should be named 'Boolean_1_1', 'Boolean_1_2' etc.) - std::ostringstream aDefaultName; - aDefaultName << anOwner->name(); - // compute default name of CompSolid (name of feature + index of CompSolid's result) - int aCompSolidResultIndex = 0; - const std::list& aResults = anOwner->results(); - for (std::list::const_iterator anIt = aResults.begin(); - anIt != aResults.end(); ++anIt, ++aCompSolidResultIndex) - if (aCompSolidRes == *anIt) - break; - aDefaultName << "_" << (aCompSolidResultIndex + 1); - theParentName = aDefaultName.str(); + if (std::dynamic_pointer_cast(aBodyRes->data())->label().Depth() == 6) { + std::ostringstream aDefaultName; + // compute default name of CompSolid (name of feature + index of CompSolid's result) + int aBodyResultIndex = 0; + const std::list& aResults = anOwner->results(); + std::list::const_iterator anIt = aResults.begin(); + for (; anIt != aResults.end(); ++anIt, ++aBodyResultIndex) + if (aBodyRes == *anIt) + break; + aDefaultName << anOwner->name(); + aDefaultName << "_" << (aBodyResultIndex + 1); + theParentName = aDefaultName.str(); + } else { // just name of the parent result if it is deeper than just a sub-result + theParentName = aBodyRes->data()->name(); + } return false; } - std::pair aName = ModelAPI_Tools::getDefaultName(theResult, theResultIndex); + std::pair aName = ModelAPI_Tools::getDefaultName(theResult); if (aName.second) theParentName = aName.first; return aName.second; @@ -1173,27 +1264,14 @@ std::shared_ptr Model_Objects::createBody( const std::shared_ptr& theFeatureData, const int theIndex) { TDF_Label aLab = resultLabel(theFeatureData, theIndex); - // for feature create compsolid, but for result sub create body: - // only one level of recursion is supported now - ResultPtr aResultOwner = std::dynamic_pointer_cast(theFeatureData->owner()); - ObjectPtr anOldObject; - if (aResultOwner.get()) { - TDataStd_Comment::Set(aLab, ModelAPI_ResultBody::group().c_str()); - } else { // in compsolid (higher level result) old object probably may be found - TDataStd_Comment::Set(aLab, ModelAPI_ResultCompSolid::group().c_str()); - anOldObject = object(aLab); - } + TDataStd_Comment::Set(aLab, ModelAPI_ResultBody::group().c_str()); + ObjectPtr anOldObject = object(aLab); std::shared_ptr aResult; if (anOldObject.get()) { aResult = std::dynamic_pointer_cast(anOldObject); } if (!aResult.get()) { - // create compsolid anyway; if it is compsolid, it will create sub-bodies internally - if (aResultOwner.get()) { - aResult = std::shared_ptr(new Model_ResultBody); - } else { - aResult = std::shared_ptr(new Model_ResultCompSolid); - } + aResult = std::shared_ptr(new Model_ResultBody); storeResult(theFeatureData, aResult, theIndex); } return aResult; @@ -1415,8 +1493,9 @@ std::shared_ptr Model_Objects::findFolder( continue; } - aFoundFolder = std::dynamic_pointer_cast(folder(aCurLabel)); - if (aFoundFolder) { + const ObjectPtr& aFolderObj = folder(aCurLabel); + if (aFolderObj.get()) { + aFoundFolder = std::dynamic_pointer_cast(aFolderObj); AttributeReferencePtr aLastFeatAttr = aFoundFolder->reference(ModelAPI_Folder::LAST_FEATURE_ID()); if (aLastFeatAttr) { @@ -1544,21 +1623,6 @@ bool Model_Objects::moveToFolder( return true; } -static FolderPtr inFolder(const FeaturePtr& theFeature, const std::string& theFolderAttr) -{ - const std::set& aRefs = theFeature->data()->refsToMe(); - for (std::set::iterator anIt = aRefs.begin(); anIt != aRefs.end(); ++anIt) { - if ((*anIt)->id() != theFolderAttr) - continue; - - ObjectPtr anOwner = (*anIt)->owner(); - FolderPtr aFolder = std::dynamic_pointer_cast(anOwner); - if (aFolder.get()) - return aFolder; - } - return FolderPtr(); -} - static FolderPtr isExtractionCorrect(const FolderPtr& theFirstFeatureFolder, const FolderPtr& theLastFeatureFolder, bool& isExtractBefore) @@ -1679,19 +1743,31 @@ FolderPtr Model_Objects::findContainingFolder(const FeaturePtr& theFeature, int& for (int aRefIndex = aRefs->Lower(); aRefIndex <= aRefs->Upper(); ++aRefIndex) { TDF_Label aCurLabel = aRefs->Value(aRefIndex); - if (isSkippedFeature(feature(aCurLabel))) - continue; if (aFoundFolder) ++theIndexInFolder; - if (aCurLabel == aLabelToFind) // the feature is reached + if (aCurLabel == aLabelToFind) { // the feature is reached + if (aFoundFolder) { + if (isSkippedFeature(theFeature)) { + theIndexInFolder = -1; + return FolderPtr(); + } + // decrease the index of the feature in the folder by the number of skipped features + for (int anIndex = theIndexInFolder - 1; anIndex > 0; anIndex--) { + aCurLabel = aRefs->Value(aRefIndex - anIndex); + if (isSkippedFeature(feature(aCurLabel))) + theIndexInFolder--; + } + } return aFoundFolder; + } if (!aFoundFolder) { // if the current label refers to a folder, feel all necessary data - aFoundFolder = std::dynamic_pointer_cast(folder(aCurLabel)); - if (aFoundFolder) { + const ObjectPtr& aFolderObj = folder(aCurLabel); + if (aFolderObj.get()) { + aFoundFolder = std::dynamic_pointer_cast(aFolderObj); theIndexInFolder = -1; AttributeReferencePtr aLastRef = @@ -1723,7 +1799,7 @@ std::shared_ptr Model_Objects::feature( if (aData.get()) { TDF_Label aFeatureLab = aData->label().Father().Father().Father(); FeaturePtr aFeature = feature(aFeatureLab); - if (!aFeature.get() && aFeatureLab.Depth() > 1) { // this may be sub-result of result + while(!aFeature.get() && aFeatureLab.Depth() > 1) { // this may be sub-result of result aFeatureLab = aFeatureLab.Father().Father(); aFeature = feature(aFeatureLab); } @@ -1796,8 +1872,7 @@ void Model_Objects::updateResults(FeaturePtr theFeature, std::set& t TDF_Label anArgLab = aLabIter.Value(); Handle(TDataStd_Comment) aGroup; if (anArgLab.FindAttribute(TDataStd_Comment::GetID(), aGroup)) { - if (aGroup->Get() == ModelAPI_ResultBody::group().c_str() || - aGroup->Get() == ModelAPI_ResultCompSolid::group().c_str()) { + if (aGroup->Get() == ModelAPI_ResultBody::group().c_str()) { aNewBody = createBody(theFeature->data(), aResIndex); } else if (aGroup->Get() == ModelAPI_ResultPart::group().c_str()) { std::shared_ptr aNewP = createPart(theFeature->data(), aResIndex); @@ -1807,6 +1882,9 @@ void Model_Objects::updateResults(FeaturePtr theFeature, std::set& t theFeature->execute(); } else if (aGroup->Get() == ModelAPI_ResultConstruction::group().c_str()) { theFeature->execute(); // construction shapes are needed for sketch solver + if (!theFeature->results().empty()) // to fix #2640 : update sketch, but not naming + std::dynamic_pointer_cast(theFeature->firstResult()) + ->facesNum(false); } else if (aGroup->Get() == ModelAPI_ResultGroup::group().c_str()) { aNewBody = createGroup(theFeature->data(), aResIndex); } else if (aGroup->Get() == ModelAPI_ResultField::group().c_str()) { @@ -1823,6 +1901,15 @@ void Model_Objects::updateResults(FeaturePtr theFeature, std::set& t } } } + if (aResSize > 0) { // check there exist a body that must be updated + std::list::const_iterator aRes = theFeature->results().cbegin(); + for (; aResSize && aRes != theFeature->results().cend(); aRes++, aResSize++) { + if ((*aRes)->data()->isValid() && (*aRes)->groupName() == ModelAPI_ResultBody::group()) { + ResultBodyPtr aBody = std::dynamic_pointer_cast(*aRes); + aBody->updateSubs(aBody->shape(), false); + } + } + } } ResultPtr Model_Objects::findByName(const std::string theName) @@ -1874,9 +1961,16 @@ FeaturePtr Model_Objects::nextFeature(FeaturePtr theCurrent, const bool theRever std::shared_ptr aData = std::static_pointer_cast(theCurrent->data()); if (aData.get() && aData->isValid()) { TDF_Label aFeatureLabel = aData->label().Father(); - TDF_Label aNextLabel = nextLabel(aFeatureLabel, theReverse); - if (!aNextLabel.IsNull()) - return feature(aNextLabel); + do { + TDF_Label aNextLabel = nextLabel(aFeatureLabel, theReverse); + if (aNextLabel.IsNull()) + break; // last or something is wrong + FeaturePtr aFound = feature(aNextLabel); + if (aFound) + return aFound; // the feature is found + // if the next label is a folder, skip it + aFeatureLabel = folder(aNextLabel).get() ? aNextLabel : TDF_Label(); + } while (!aFeatureLabel.IsNull()); } return FeaturePtr(); // not found, last, or something is wrong } @@ -1894,6 +1988,11 @@ FeaturePtr Model_Objects::lastFeature() { Handle(TDataStd_ReferenceArray) aRefs; if (featuresLabel().FindAttribute(TDataStd_ReferenceArray::GetID(), aRefs)) { + FeaturePtr aLast = feature(aRefs->Value(aRefs->Upper())); + if (!aLast.get() && aRefs->Length() != 0) { // erase the invalid feature from the array + RemoveFromRefArray(featuresLabel(), aRefs->Value(aRefs->Upper())); + return lastFeature(); // try once again, after the last was removed + } return feature(aRefs->Value(aRefs->Upper())); } return FeaturePtr(); // no features at all