From ccdb130fee5044d440d8ecf99fc745b9ef5608dd Mon Sep 17 00:00:00 2001 From: mpv Date: Fri, 21 Dec 2018 18:28:45 +0300 Subject: [PATCH] Fix for the robinet model with partitions: final groups selection with neighbors algorithm requires explicit context name. --- src/Model/Model_BodyBuilder.cpp | 5 ++ src/Model/Model_BodyBuilder.h | 2 + src/Model/Model_Document.cpp | 5 +- src/Model/Model_ResultBody.cpp | 14 +++- src/Model/Model_ResultBody.h | 3 + src/ModelAPI/ModelAPI_BodyBuilder.h | 3 + src/ModelAPI/ModelAPI_ResultBody.h | 3 + src/Selector/Selector_Algo.cpp | 71 +++++++++++---------- src/Selector/Selector_FilterByNeighbors.cpp | 45 ++++++++++++- src/Selector/Selector_FilterByNeighbors.h | 4 +- 10 files changed, 114 insertions(+), 41 deletions(-) diff --git a/src/Model/Model_BodyBuilder.cpp b/src/Model/Model_BodyBuilder.cpp index fee31e5c4..f22dfe5bd 100755 --- a/src/Model/Model_BodyBuilder.cpp +++ b/src/Model/Model_BodyBuilder.cpp @@ -267,6 +267,11 @@ void Model_BodyBuilder::clean() } } +void Model_BodyBuilder::cleanCash() +{ + myPrimitivesNamesIndexMap.clear(); +} + Model_BodyBuilder::~Model_BodyBuilder() { clean(); diff --git a/src/Model/Model_BodyBuilder.h b/src/Model/Model_BodyBuilder.h index 0689a0f52..8487a6b81 100755 --- a/src/Model/Model_BodyBuilder.h +++ b/src/Model/Model_BodyBuilder.h @@ -108,6 +108,8 @@ public: /// Removes the stored builders MODEL_EXPORT virtual ~Model_BodyBuilder(); + /// Cleans cash related to the already stored elements + MODEL_EXPORT virtual void cleanCash() override; protected: /// Default constructor accessible only by Model_Objects Model_BodyBuilder(ModelAPI_Object* theOwner); diff --git a/src/Model/Model_Document.cpp b/src/Model/Model_Document.cpp index a8a82e1af..bed5d3455 100755 --- a/src/Model/Model_Document.cpp +++ b/src/Model/Model_Document.cpp @@ -365,7 +365,10 @@ bool Model_Document::save( Handle(Model_Application) anApp = Model_Application::getApplication(); if (isRoot()) { #ifdef WIN32 - CreateDirectory((LPTSTR) theDirName, NULL); + size_t aDirLen = strlen(theDirName); + std::wstring aWStr(aDirLen, L'#'); + mbstowcs(&aWStr[0], theDirName, aDirLen); + CreateDirectory(aWStr.c_str(), NULL); #else mkdir(theDirName, 0x1ff); #endif diff --git a/src/Model/Model_ResultBody.cpp b/src/Model/Model_ResultBody.cpp index 8f8c218bb..4acd17d8f 100644 --- a/src/Model/Model_ResultBody.cpp +++ b/src/Model/Model_ResultBody.cpp @@ -272,8 +272,8 @@ void Model_ResultBody::updateSubs(const std::shared_ptr& theThisS aSub = mySubs[aSubIndex]; } GeomShapePtr anOldSubShape = aSub->shape(); - aSub->store(aShape, false); // store even equal to call "clear": #2814 if (!aShape->isEqual(anOldSubShape)) { + aSub->store(aShape, false); aECreator->sendUpdated(aSub, EVENT_DISP); aECreator->sendUpdated(aSub, EVENT_UPD); } @@ -294,6 +294,7 @@ void Model_ResultBody::updateSubs(const std::shared_ptr& theThisS // redisplay this because result with and without subs are displayed differently aECreator->sendUpdated(data()->owner(), EVENT_DISP); } + cleanCash(); } else if (!mySubs.empty()) { // erase all subs while(!mySubs.empty()) { ResultBodyPtr anErased = *(mySubs.rbegin()); @@ -327,3 +328,14 @@ bool Model_ResultBody::isConnectedTopology() } return false; // invalid case } + +void Model_ResultBody::cleanCash() +{ + myBuilder->cleanCash(); + for (std::vector::const_iterator aSubIter = mySubs.cbegin(); + aSubIter != mySubs.cend(); ++aSubIter) + { + const ResultBodyPtr& aSub = *aSubIter; + aSub->cleanCash(); + } +} diff --git a/src/Model/Model_ResultBody.h b/src/Model/Model_ResultBody.h index 721ad71f3..09824971f 100644 --- a/src/Model/Model_ResultBody.h +++ b/src/Model/Model_ResultBody.h @@ -98,6 +98,9 @@ public: /// Returns true is the topology is connected. MODEL_EXPORT virtual bool isConnectedTopology(); + /// Cleans cash related to the already stored elements + MODEL_EXPORT virtual void cleanCash() override; + protected: /// Makes a body on the given feature Model_ResultBody(); diff --git a/src/ModelAPI/ModelAPI_BodyBuilder.h b/src/ModelAPI/ModelAPI_BodyBuilder.h index 6523241df..f72202360 100755 --- a/src/ModelAPI/ModelAPI_BodyBuilder.h +++ b/src/ModelAPI/ModelAPI_BodyBuilder.h @@ -98,6 +98,9 @@ public: virtual void loadFirstLevel(GeomShapePtr theShape, const std::string& theName) = 0; + /// Cleans cash related to the already stored elements + MODELAPI_EXPORT virtual void cleanCash() = 0; + protected: /// Returns the data manager of this object: attributes MODELAPI_EXPORT virtual std::shared_ptr data() const; diff --git a/src/ModelAPI/ModelAPI_ResultBody.h b/src/ModelAPI/ModelAPI_ResultBody.h index c41854f9d..20e0879f2 100644 --- a/src/ModelAPI/ModelAPI_ResultBody.h +++ b/src/ModelAPI/ModelAPI_ResultBody.h @@ -165,6 +165,9 @@ public: MODELAPI_EXPORT virtual void updateSubs(const GeomShapePtr& theThisShape, const bool theShapeChanged = true) = 0; + /// Cleans cash related to the already stored elements + MODELAPI_EXPORT virtual void cleanCash() = 0; + protected: /// Default constructor accessible only from Model_Objects MODELAPI_EXPORT ModelAPI_ResultBody(); diff --git a/src/Selector/Selector_Algo.cpp b/src/Selector/Selector_Algo.cpp index ee31d00bd..0ddc2ae56 100644 --- a/src/Selector/Selector_Algo.cpp +++ b/src/Selector/Selector_Algo.cpp @@ -67,6 +67,24 @@ Selector_Algo::Selector_Algo() myAlwaysGeometricalNaming = false; } +static TDF_Label findGoodLabelWithShape(const TDF_Label theAccess, const TopoDS_Shape& theShape) { + TDF_Label aResult; + if (TNaming_Tool::HasLabel(theAccess, theShape)) { // selection and delete evolution are not used + for(TNaming_SameShapeIterator aShapes(theShape, theAccess); aShapes.More(); aShapes.Next()) + { + Handle(TNaming_NamedShape) aNS; + if (aShapes.Label().FindAttribute(TNaming_NamedShape::GetID(), aNS)) { + if (aNS->Evolution() == TNaming_MODIFY || aNS->Evolution() == TNaming_GENERATED || + aNS->Evolution() == TNaming_PRIMITIVE) { + aResult = aNS->Label(); + break; + } + } + } + } + return aResult; +} + #define SET_ALGO_FLAGS(algo) \ algo->myLab = theAccess; \ algo->myBaseDocumentLab = theBaseDocument; \ @@ -86,37 +104,9 @@ Selector_Algo* Selector_Algo::select(const TopoDS_Shape theContext, const TopoDS // check the value shape can be named as it is, or it is needed to construct it from the // higher level shapes (like a box vertex by faces that form this vertex) - bool aIsFound = TNaming_Tool::HasLabel(theAccess, theValue); - if (aIsFound) { // additional check for selection and delete evolution only: also could not use - aIsFound = false; - for(TNaming_SameShapeIterator aShapes(theValue, theAccess); aShapes.More(); aShapes.Next()) - { - Handle(TNaming_NamedShape) aNS; - if (aShapes.Label().FindAttribute(TNaming_NamedShape::GetID(), aNS)) { - if (aNS->Evolution() == TNaming_MODIFY || aNS->Evolution() == TNaming_GENERATED || - aNS->Evolution() == TNaming_PRIMITIVE) { - aIsFound = true; - break; - } - } - } - } - // searching in the base document - if (!aIsFound && !theBaseDocument.IsNull() && TNaming_Tool::HasLabel(theBaseDocument, theValue)) - { - TNaming_SameShapeIterator aShapes(theValue, theBaseDocument); - for(; aShapes.More(); aShapes.Next()) - { - Handle(TNaming_NamedShape) aNS; - if (aShapes.Label().FindAttribute(TNaming_NamedShape::GetID(), aNS)) { - if (aNS->Evolution() == TNaming_MODIFY || aNS->Evolution() == TNaming_GENERATED || - aNS->Evolution() == TNaming_PRIMITIVE) { - aIsFound = true; - break; - } - } - } - } + bool aIsFound = !findGoodLabelWithShape(theAccess, theValue).IsNull(); + if (!aIsFound && !theBaseDocument.IsNull()) // searching in the base document + aIsFound = !findGoodLabelWithShape(theBaseDocument, theValue).IsNull(); if (!aIsFound) { TopAbs_ShapeEnum aSelectionType = theValue.ShapeType(); if (aSelectionType == TopAbs_COMPOUND || aSelectionType == TopAbs_COMPSOLID || @@ -144,7 +134,11 @@ Selector_Algo* Selector_Algo::select(const TopoDS_Shape theContext, const TopoDS // searching by neighbors Selector_FilterByNeighbors* aNBs = new Selector_FilterByNeighbors; SET_ALGO_FLAGS(aNBs); - if (aNBs->select(theContext, theValue)) { + // searching a context lab to store in NB algorithm + TDF_Label aContextLab = findGoodLabelWithShape(theAccess, theContext); + if (aContextLab.IsNull() && !theBaseDocument.IsNull()) // search also in the base document + aContextLab = findGoodLabelWithShape(theBaseDocument, theContext); + if (aNBs->select(aContextLab, theContext, theValue)) { delete anIntersect; return aNBs; } @@ -213,7 +207,11 @@ Selector_Algo* Selector_Algo::select(const TopoDS_Shape theContext, const TopoDS // searching by neighbors Selector_FilterByNeighbors* aNBs = new Selector_FilterByNeighbors; SET_ALGO_FLAGS(aNBs); - if (aNBs->select(theContext, theValue)) { + // searching a context lab to store in NB algorithm + TDF_Label aContextLab = findGoodLabelWithShape(theAccess, theContext); + if (aContextLab.IsNull() && !theBaseDocument.IsNull()) // search also in the base document + aContextLab = findGoodLabelWithShape(theBaseDocument, theContext); + if (aNBs->select(aContextLab, theContext, theValue)) { delete aModify; return aNBs; } @@ -472,9 +470,12 @@ bool Selector_Algo::findNewVersion(const TopoDS_Shape& theContext, TopoDS_Shape& if (aNextModification.IsNull()) continue; if (isInContext(theContext, aNextModification)) - aResultShapes.Add(aNextModification); + // don't add vertices generated from edges + if (aNextModification.ShapeType() <= theResult.ShapeType()) + aResultShapes.Add(aNextModification); else if (findNewVersion(theContext, aNextModification)) - aResultShapes.Add(aNextModification); + if (aNextModification.ShapeType() <= theResult.ShapeType()) + aResultShapes.Add(aNextModification); } } if (aResultShapes.IsEmpty()) diff --git a/src/Selector/Selector_FilterByNeighbors.cpp b/src/Selector/Selector_FilterByNeighbors.cpp index 09e0ab314..908ca5fa1 100644 --- a/src/Selector/Selector_FilterByNeighbors.cpp +++ b/src/Selector/Selector_FilterByNeighbors.cpp @@ -176,9 +176,11 @@ static const TopoDS_Shape findNeighbor(const TopoDS_Shape theContext, return aGoodCandidate; } -bool Selector_FilterByNeighbors::select(const TopoDS_Shape theContext, const TopoDS_Shape theValue) +bool Selector_FilterByNeighbors::select( + const TDF_Label theContextLab, const TopoDS_Shape theContext, const TopoDS_Shape theValue) { myShapeType = theValue.ShapeType(); + myContext = theContextLab; // searching by neighbors std::list > aNBs; /// neighbor sub-shape -> level of neighborhood for(int aLevel = 1; true; aLevel++) { @@ -237,6 +239,11 @@ void Selector_FilterByNeighbors::store() for(; aSubSel != list().cend(); aSubSel++) { (*aSubSel)->store(); } + // store context reference if exists + if (!myContext.IsNull()) { + static const TDF_LabelList anEmptyRefList; + storeBaseArray(anEmptyRefList, myContext); + } } bool Selector_FilterByNeighbors::restore() @@ -269,6 +276,10 @@ bool Selector_FilterByNeighbors::restore() } } } + // restore context reference if exists + static TDF_LabelList anEmptyRefList; + restoreBaseArray(anEmptyRefList, myContext); + return myNBLevel.size() == list().size() && !myNBLevel.empty(); } @@ -277,6 +288,7 @@ TDF_Label Selector_FilterByNeighbors::restoreByName(std::string theName, { myShapeType = theShapeType; TDF_Label aContext; + std::string aLastLevel; // last level string (after '(' ) to check the context name in the end for (size_t aStart = 0; aStart != std::string::npos; aStart = theName.find('(', aStart + 1)) { size_t anEndPos = theName.find(')', aStart + 1); @@ -310,7 +322,8 @@ TDF_Label Selector_FilterByNeighbors::restoreByName(std::string theName, anEndPos++) { aLevel += theName[anEndPos]; } - if (aLevel.empty()) + aLastLevel = aLevel; + if (aLevel.empty() || aLevel[0] == '_') myNBLevel.push_back(1); // by default it is 1 else { int aNum = atoi(aLevel.c_str()); @@ -322,6 +335,20 @@ TDF_Label Selector_FilterByNeighbors::restoreByName(std::string theName, } else return TDF_Label(); // invalid parentheses } + if (!aLastLevel.empty()) { // get the context + size_t aLinePos = aLastLevel.find("_"); + if (aLinePos != std::string::npos) { + std::string aContextName = aLastLevel.substr(aLinePos + 1); + if (!aContextName.empty()) { + TDF_Label aThisContext, aValue; + if (theNameGenerator->restoreContext(aContextName, aThisContext, aValue)) { + if (!aThisContext.IsNull()) + aContext = aThisContext; + } + } + } + } + myContext = aContext; return aContext; } @@ -352,18 +379,30 @@ bool Selector_FilterByNeighbors::solve(const TopoDS_Shape& theContext) std::string Selector_FilterByNeighbors::name(Selector_NameGenerator* theNameGenerator) { // (nb1)level_if_more_than_1(nb2)level_if_more_than_1(nb3)level_if_more_than_1 + bool aThisContextNameNeeded = !myContext.IsNull(); + std::string aContextName; + if (aThisContextNameNeeded) + aContextName = theNameGenerator->contextName(myContext); std::string aResult; std::list::iterator aLevel = myNBLevel.begin(); std::list::const_iterator aSubSel = list().cbegin(); for(; aSubSel != list().cend(); aSubSel++, aLevel++) { if (!*aSubSel) continue; - aResult += "(" + (*aSubSel)->name(theNameGenerator) + ")"; + std::string aSubName = (*aSubSel)->name(theNameGenerator); + aResult += "(" + aSubName + ")"; if (*aLevel > 1) { std::ostringstream aLevelStr; aLevelStr<<*aLevel; aResult += aLevelStr.str(); } + // sub-name already contains the needed context name, so, here it is not needed + if (aThisContextNameNeeded && ( + aSubName.find(aContextName) == 0 || aSubName.substr(1).find(aContextName)) == 0) + aThisContextNameNeeded = false; + } + if (aThisContextNameNeeded) { + aResult = aResult + "_" + aContextName; } return aResult; } diff --git a/src/Selector/Selector_FilterByNeighbors.h b/src/Selector/Selector_FilterByNeighbors.h index 721e4a923..9335344d3 100644 --- a/src/Selector/Selector_FilterByNeighbors.h +++ b/src/Selector/Selector_FilterByNeighbors.h @@ -35,9 +35,11 @@ class Selector_FilterByNeighbors: public Selector_AlgoWithSubs { TopAbs_ShapeEnum myShapeType; ///< type of this shape std::list myNBLevel; ///< list of integers corresponding to subs neighborhood level + TDF_Label myContext; ///< label where the context of filter is stored (needed for python name string) public: /// Initializes the selection of this kind - SELECTOR_EXPORT bool select(const TopoDS_Shape theContext, const TopoDS_Shape theValue); + SELECTOR_EXPORT bool select( + const TDF_Label theContextLab, const TopoDS_Shape theContext, const TopoDS_Shape theValue); /// Stores the name to the label and sub-labels tree SELECTOR_EXPORT virtual void store() override; -- 2.30.2