From 59b59e6820883255cae4c9eed33433b0f3d293bb Mon Sep 17 00:00:00 2001 From: mpv Date: Thu, 16 Nov 2017 15:22:05 +0300 Subject: [PATCH] Correct names generation for tests. --- src/Model/Model_Document.cpp | 66 +++++++++++++++---- src/Model/Model_Document.h | 8 ++- src/Model/Model_Objects.cpp | 13 ++-- src/Model/Model_SelectionNaming.cpp | 29 ++++---- src/ModelAPI/Test/Test1757.py | 4 +- .../Transformations/TestTranslation_3.py | 9 +++ 6 files changed, 100 insertions(+), 29 deletions(-) diff --git a/src/Model/Model_Document.cpp b/src/Model/Model_Document.cpp index 2272a8f33..bb82a340e 100755 --- a/src/Model/Model_Document.cpp +++ b/src/Model/Model_Document.cpp @@ -1271,10 +1271,22 @@ Standard_Boolean IsEqual(const TDF_Label& theLab1, const TDF_Label& theLab2) return TDF_LabelMapHasher::IsEqual(theLab1, theLab2); } +// searches in this document feature that contains this label +FeaturePtr Model_Document::featureByLab(const TDF_Label& theLab) { + TDF_Label aCurrentLab = theLab; + while(aCurrentLab.Depth() > 3) + aCurrentLab = aCurrentLab.Father(); + return myObjs->feature(aCurrentLab); +} + void Model_Document::addNamingName(const TDF_Label theLabel, std::string theName) { std::map >::iterator aFind = myNamingNames.find(theName); + if (aFind != myNamingNames.end()) { // to avoid duplicate-labels + // to keep correct order inspite of history line management + std::list::iterator anAddAfterThis = aFind->second.end(); + FeaturePtr anAddedFeature = featureByLab(theLabel); std::list::iterator aLabIter = aFind->second.begin(); while(aLabIter != aFind->second.end()) { if (theLabel.IsEqual(*aLabIter)) { @@ -1282,9 +1294,21 @@ void Model_Document::addNamingName(const TDF_Label theLabel, std::string theName aLabIter++; aFind->second.erase(aTmpIter); } else { + FeaturePtr aCurFeature = featureByLab(*aLabIter); + if (aCurFeature.get() && anAddedFeature.get() && + myObjs->isLater(anAddedFeature, aCurFeature)) + anAddAfterThis = aLabIter; + aLabIter++; } } + if (anAddAfterThis != aFind->second.end()) { + anAddAfterThis++; + if (anAddAfterThis != aFind->second.end()) { + myNamingNames[theName].insert(anAddAfterThis, theLabel); // inserts before anAddAfterThis + return; + } + } } myNamingNames[theName].push_back(theLabel); } @@ -1366,6 +1390,30 @@ TDF_Label Model_Document::findNamingName(std::string theName, ResultPtr theConte return TDF_Label(); // not found } +bool Model_Document::isLaterByDep(FeaturePtr theThis, FeaturePtr theOther) { + // check dependencies first: if theOther depends on theThis, theThis is not later + std::list > > > aRefs; + theOther->data()->referencesToObjects(aRefs); + std::list > > >::iterator + aRefIt = aRefs.begin(); + for(; aRefIt != aRefs.end(); aRefIt++) { + std::list::iterator aRefObjIt = aRefIt->second.begin(); + for(; aRefObjIt != aRefIt->second.end(); aRefObjIt++) { + ObjectPtr aRefObj = *aRefObjIt; + if (aRefObj.get()) { + FeaturePtr aRefFeat = std::dynamic_pointer_cast(aRefObj); + if (!aRefFeat.get()) { // take feature of the result + aRefFeat = feature(std::dynamic_pointer_cast(aRefObj)); + } + if (aRefFeat.get() && aRefFeat == theThis) { + return false; // other references to this, so this later than other + } + } + } + } + return myObjs->isLater(theThis, theOther); +} + int Model_Document::numberOfNameInHistory( const ObjectPtr& theNameObject, const TDF_Label& theStartFrom) { @@ -1388,35 +1436,31 @@ int Model_Document::numberOfNameInHistory( // iterate all labels with this name to find the nearest just before or equal relative std::list::reverse_iterator aLabIter = aFind->second.rbegin(); for(; aLabIter != aFind->second.rend(); aLabIter++) { - TDF_Label aCurrentLab = *aLabIter; - while(aCurrentLab.Depth() > 3) - aCurrentLab = aCurrentLab.Father(); - FeaturePtr aLabFeat = myObjs->feature(aCurrentLab); + FeaturePtr aLabFeat = featureByLab(*aLabIter); if (!aLabFeat.get()) continue; - if (aLabFeat == aStart || myObjs->isLater(aStart, aLabFeat)) + if (isLaterByDep(aStart, aLabFeat)) // skip also start: its result don't used break; } int aResIndex = 1; for(; aLabIter != aFind->second.rend(); aLabIter++) { - TDF_Label aCurrentLab = *aLabIter; - while(aCurrentLab.Depth() > 3) - aCurrentLab = aCurrentLab.Father(); - FeaturePtr aLabFeat = myObjs->feature(aCurrentLab); + FeaturePtr aLabFeat = featureByLab(*aLabIter); if (!aLabFeat.get()) continue; - if (aLabFeat == aNameFeature || myObjs->isLater(aNameFeature, aLabFeat)) + if (aLabFeat == aNameFeature || isLaterByDep(aNameFeature, aLabFeat)) return aResIndex; aResIndex++; } return aResIndex; // strange } -ResultPtr Model_Document::findByName(std::string& theName, std::string& theSubShapeName) +ResultPtr Model_Document::findByName( + std::string& theName, std::string& theSubShapeName, bool& theUniqueContext) { int aNumInHistory = 0; std::string aName = theName; ResultPtr aRes = myObjs->findByName(aName); + theUniqueContext = !(aRes.get() && myNamingNames.find(aName) != myNamingNames.end()); while(!aRes.get() && aName[0] == '_') { // this may be thecontext with the history index aNumInHistory++; aName = aName.substr(1); diff --git a/src/Model/Model_Document.h b/src/Model/Model_Document.h index 93f50e359..4b33be6af 100644 --- a/src/Model/Model_Document.h +++ b/src/Model/Model_Document.h @@ -215,7 +215,7 @@ class Model_Document : public ModelAPI_Document int numberOfNameInHistory(const ObjectPtr& theNameObject, const TDF_Label& theStartFrom); //! Returns the result by name of the result (names of results must be unique, used for naming //! selection by name. - ResultPtr findByName(std::string& theName, std::string& theSubShapeName); + ResultPtr findByName(std::string& theName, std::string& theSubShapeName, bool& theUniqueContext); ///! Returns all features of the document including the hidden features which are not in ///! history. Not very fast method, for calling once, not in big cycles. @@ -313,6 +313,12 @@ class Model_Document : public ModelAPI_Document /// Label that constains structures for selection of constructions of another document TDF_Label extConstructionsLabel() const; + /// searches in this document feature that contains this label + FeaturePtr featureByLab(const TDF_Label& theLab); + + /// returns true if theThis is later in the features trre and dependencies than theOther + bool isLaterByDep(FeaturePtr theThis, FeaturePtr theOther); + friend class Model_Application; friend class Model_Session; friend class Model_Update; diff --git a/src/Model/Model_Objects.cpp b/src/Model/Model_Objects.cpp index e1636118d..85460450c 100644 --- a/src/Model/Model_Objects.cpp +++ b/src/Model/Model_Objects.cpp @@ -1222,6 +1222,8 @@ void Model_Objects::updateResults(FeaturePtr theFeature, std::set& t ResultPtr Model_Objects::findByName(const std::string theName) { + ResultPtr aResult; + FeaturePtr aResFeature; // keep feature to return the latest one NCollection_DataMap::Iterator anObjIter(myFeatures); for(; anObjIter.More(); anObjIter.Next()) { FeaturePtr& aFeature = anObjIter.ChangeValue(); @@ -1233,13 +1235,16 @@ ResultPtr Model_Objects::findByName(const std::string theName) for (; aRIter != allResults.cend(); aRIter++) { ResultPtr aRes = *aRIter; if (aRes.get() && aRes->data() && aRes->data()->isValid() && !aRes->isDisabled() && - aRes->data()->name() == theName) { - return aRes; + aRes->data()->name() == theName) + { + if (!aResult.get() || isLater(aFeature, aResFeature)) { // select the latest + aResult = aRes; + aResFeature = aFeature; + } } } } - // not found - return ResultPtr(); + return aResult; } FeaturePtr Model_Objects::nextFeature(FeaturePtr theCurrent, const bool theReverse) diff --git a/src/Model/Model_SelectionNaming.cpp b/src/Model/Model_SelectionNaming.cpp index ad202ae1b..6de12da8d 100644 --- a/src/Model/Model_SelectionNaming.cpp +++ b/src/Model/Model_SelectionNaming.cpp @@ -484,17 +484,20 @@ const TopoDS_Shape getShapeFromNS( const TopoDS_Shape findFaceByName( const std::string& theSubShapeName, std::shared_ptr theDoc, - const ResultPtr theDetectedContext) + const ResultPtr theDetectedContext, bool theContextIsUnique) { TopoDS_Shape aFace; std::string aSubString = theSubShapeName; - TDF_Label aLabel = theDoc->findNamingName(aSubString, theDetectedContext); + static const ResultPtr anEmpty; + TDF_Label aLabel = theDoc->findNamingName(aSubString, + theContextIsUnique ? theDetectedContext : anEmpty); if (aLabel.IsNull()) { // try to remove additional artificial suffix std::string::size_type n = aSubString.rfind('_'); if (n != std::string::npos) { aSubString = aSubString.substr(0, n); - aLabel = theDoc->findNamingName(aSubString, theDetectedContext); + aLabel = theDoc->findNamingName(aSubString, + theContextIsUnique ? theDetectedContext : anEmpty); } } if(aLabel.IsNull()) return aFace; @@ -733,7 +736,8 @@ bool Model_SelectionNaming::selectSubShape(const std::string& theType, std::string aContName = getContextName(aSubShapeName); if(aContName.empty()) return false; - ResultPtr aCont = aDoc->findByName(aContName, aSubShapeName); + bool anUniqueContext = false; + ResultPtr aCont = aDoc->findByName(aContName, aSubShapeName, anUniqueContext); // possible this is body where postfix is added to distinguish several shapes on the same label int aSubShapeId = -1; // -1 means sub shape not found // for result body the name wihtout "_" has higher priority than with it: it is always added @@ -742,7 +746,7 @@ bool Model_SelectionNaming::selectSubShape(const std::string& theType, size_t aPostIndex = aContName.rfind('_'); if (aPostIndex != std::string::npos) { std::string anEmpty, aSubContName = aContName.substr(0, aPostIndex); - ResultPtr aSubCont = aDoc->findByName(aSubContName, anEmpty); + ResultPtr aSubCont = aDoc->findByName(aSubContName, anEmpty, anUniqueContext); if (aSubCont.get()) { try { std::string aNum = aContName.substr(aPostIndex + 1); @@ -759,18 +763,20 @@ bool Model_SelectionNaming::selectSubShape(const std::string& theType, } + static const ResultPtr anEmpty; TopoDS_Shape aSelection; switch (aType) { case TopAbs_FACE: case TopAbs_WIRE: { - aSelection = findFaceByName(aSubShapeName, aDoc, aCont); + aSelection = findFaceByName(aSubShapeName, aDoc, aCont, anUniqueContext); } break; case TopAbs_EDGE: { - const TDF_Label& aLabel = aDoc->findNamingName(aSubShapeName, aCont); + const TDF_Label& aLabel = + aDoc->findNamingName(aSubShapeName, anUniqueContext ? aCont : anEmpty); if(!aLabel.IsNull()) { Handle(TNaming_NamedShape) aNS; if(aLabel.FindAttribute(TNaming_NamedShape::GetID(), aNS)) { @@ -781,7 +787,8 @@ bool Model_SelectionNaming::selectSubShape(const std::string& theType, break; case TopAbs_VERTEX: { - const TDF_Label& aLabel = aDoc->findNamingName(aSubShapeName, aCont); + const TDF_Label& aLabel = + aDoc->findNamingName(aSubShapeName, anUniqueContext ? aCont : anEmpty); if(!aLabel.IsNull()) { Handle(TNaming_NamedShape) aNS; if(aLabel.FindAttribute(TNaming_NamedShape::GetID(), aNS)) { @@ -834,10 +841,10 @@ bool Model_SelectionNaming::selectSubShape(const std::string& theType, if (it != aListofNames.begin()) { // there may be other context for different sub-faces std::string aContName = getContextName(*it); if(!aContName.empty()) { - aFaceContext = aDoc->findByName(aContName, *it); + aFaceContext = aDoc->findByName(aContName, *it, anUniqueContext); } } - const TopoDS_Shape aFace = findFaceByName(*it, aDoc, aFaceContext); + const TopoDS_Shape aFace = findFaceByName(*it, aDoc, aFaceContext, anUniqueContext); if(!aFace.IsNull()) aList.Append(aFace); } @@ -850,7 +857,7 @@ bool Model_SelectionNaming::selectSubShape(const std::string& theType, size_t aConstrNamePos = aSubShapeName.find("/"); bool isFullName = aConstrNamePos == std::string::npos; std::string anEmpty, aContrName = aContName; - ResultPtr aConstr = aDoc->findByName(aContrName, anEmpty); + ResultPtr aConstr = aDoc->findByName(aContrName, anEmpty, anUniqueContext); if (aConstr.get() && aConstr->groupName() == ModelAPI_ResultConstruction::group()) { theCont = aConstr; if (isFullName) { diff --git a/src/ModelAPI/Test/Test1757.py b/src/ModelAPI/Test/Test1757.py index e76525a1e..8c300a578 100644 --- a/src/ModelAPI/Test/Test1757.py +++ b/src/ModelAPI/Test/Test1757.py @@ -79,7 +79,7 @@ model.do() #========================================================================= # Make a cylindrical hole using one of the produced faces #========================================================================= -ExtrusionCut_2 = model.addExtrusionCut(Part_1_doc, [], model.selection(), model.selection(), 0, model.selection("FACE", "__Extrusion_1_1/Generated_Face_2"), 0, [model.selection("SOLID", "Extrusion_1_1")]) +ExtrusionCut_2 = model.addExtrusionCut(Part_1_doc, [], model.selection(), model.selection(), 0, model.selection("FACE", "_Extrusion_1_1/Generated_Face_2"), 0, [model.selection("SOLID", "Extrusion_1_1")]) Sketch_3 = model.addSketch(Part_1_doc, model.selection("FACE", "Extrusion_1_1/Modfied_4")) SketchCircle_1 = Sketch_3.addCircle(143.412751420315, -228.52745656314, 32.158435160764) ExtrusionCut_2.setNestedSketch(Sketch_3) @@ -125,6 +125,6 @@ import ModelAPI assert(ModelAPI.ModelAPI_Session.get().validators().validate(Sketch_4.feature())) assert(ModelAPI.ModelAPI_Session.get().validators().validate(ExtrusionCut_2.feature())) -assert(Sketch_3.feature().selection("External").namingName() == "ExtrusionCut_3_1/Modfied_6") +assert(Sketch_3.feature().selection("External").namingName() == "Extrusion_1_1/Modfied_6") assert(model.checkPythonDump()) diff --git a/test.API/SHAPER/Transformations/TestTranslation_3.py b/test.API/SHAPER/Transformations/TestTranslation_3.py index 8d7af9855..dadc9d953 100644 --- a/test.API/SHAPER/Transformations/TestTranslation_3.py +++ b/test.API/SHAPER/Transformations/TestTranslation_3.py @@ -162,14 +162,23 @@ Face_13 = model.addFace(Part_1_doc, [model.selection("WIRE", "Sketch_7/Wire-Sket # Shells Shell_1 = model.addShell(Part_1_doc, [model.selection("FACE", "Face_10_1"), model.selection("FACE", "Face_11_1")]) +Shell_1.result().setName("Shell_1_1") Shell_2 = model.addShell(Part_1_doc, [model.selection("FACE", "Face_10_1"), model.selection("FACE", "Face_11_1")]) +Shell_2.result().setName("Shell_2_1") Shell_3 = model.addShell(Part_1_doc, [model.selection("FACE", "Face_10_1"), model.selection("FACE", "Face_11_1")]) +Shell_3.result().setName("Shell_3_1") Shell_4 = model.addShell(Part_1_doc, [model.selection("FACE", "Face_10_1"), model.selection("FACE", "Face_11_1")]) +Shell_4.result().setName("Shell_4_1") Shell_5 = model.addShell(Part_1_doc, [model.selection("FACE", "Face_10_1"), model.selection("FACE", "Face_11_1")]) +Shell_5.result().setName("Shell_5_1") Shell_6 = model.addShell(Part_1_doc, [model.selection("FACE", "Face_12_1"), model.selection("FACE", "Face_13_1")]) +Shell_6.result().setName("Shell_6_1") Shell_7 = model.addShell(Part_1_doc, [model.selection("FACE", "Face_12_1"), model.selection("FACE", "Face_13_1")]) +Shell_7.result().setName("Shell_7_1") Shell_8 = model.addShell(Part_1_doc, [model.selection("FACE", "Face_10_1"), model.selection("FACE", "Face_11_1")]) +Shell_8.result().setName("Shell_8_1") Shell_9 = model.addShell(Part_1_doc, [model.selection("FACE", "Face_10_1"), model.selection("FACE", "Face_11_1")]) +Shell_9.result().setName("Shell_9_1") # Parameters model.addParameter(Part_1_doc, "d", "15") -- 2.39.2