From a48a3b574fbf6f526fbeebfd637e1f5d9f4f6ea9 Mon Sep 17 00:00:00 2001 From: Artem Zhidkov Date: Sat, 9 May 2020 22:57:55 +0300 Subject: [PATCH] Issue #19058: Error in sketch projection when changing parameter Provide the backward compatibility of selection mechanism. --- src/Selector/Selector_Algo.cpp | 3 +- src/Selector/Selector_Algo.h | 16 ++++- src/Selector/Selector_Intersect.cpp | 13 ++++- src/Selector/Selector_Intersect.h | 1 + src/Selector/Selector_Modify.cpp | 17 ++++-- src/Selector/Selector_Modify.h | 1 + src/Selector/Selector_NExplode.cpp | 91 ++++++++++++++++++----------- src/Selector/Selector_NExplode.h | 20 +++++-- src/Selector/Selector_WeakName.cpp | 9 ++- src/Selector/Selector_WeakName.h | 1 + 10 files changed, 119 insertions(+), 53 deletions(-) diff --git a/src/Selector/Selector_Algo.cpp b/src/Selector/Selector_Algo.cpp index 4a186b67b..a21be5fa5 100644 --- a/src/Selector/Selector_Algo.cpp +++ b/src/Selector/Selector_Algo.cpp @@ -431,7 +431,8 @@ Selector_Algo* Selector_Algo::restoreByName(TDF_Label theLab, TDF_Label theBaseD } } else if (theName[0] == '(') { // filter by neighbors aResult = new Selector_FilterByNeighbors; - } else if (theName.find(pureWeakNameID()) == 0) { // weak naming identifier + } else if (theName.find(pureWeakNameID()) == 0 || + theName.find(oldPureWeakNameID()) == 0) { // weak naming identifier aResult = new Selector_WeakName; } else if (theName.find('&') != std::string::npos) { // modification aResult = new Selector_Modify; diff --git a/src/Selector/Selector_Algo.h b/src/Selector/Selector_Algo.h index 5a21a7544..a946a1c83 100644 --- a/src/Selector/Selector_Algo.h +++ b/src/Selector/Selector_Algo.h @@ -148,16 +148,28 @@ protected: static const Standard_GUID kSHAPE_TYPE("864b3267-cb9d-4107-bf58-c3ce1775b171"); return kSHAPE_TYPE; } + /// old string identifier of the weak name in modification or intersection types of algorithm + static const std::string& oldWeakNameID() + { + static const std::string kWEAK_NAME_IDENTIFIER = "weak_name_"; + return kWEAK_NAME_IDENTIFIER; + } + /// old string identifier of the pure weak name + static const std::string& oldPureWeakNameID() + { + static const std::string kPURE_WEAK_NAME_IDENTIFIER = "_weak_name_"; + return kPURE_WEAK_NAME_IDENTIFIER; + } /// string identifier of the weak name in modification or intersection types of algorithm static const std::string& weakNameID() { - static const std::string kWEAK_NAME_IDENTIFIER = "weak_name_"; + static const std::string kWEAK_NAME_IDENTIFIER = std::string("new_") + oldWeakNameID(); return kWEAK_NAME_IDENTIFIER; } /// string identifier of the pure weak name static const std::string& pureWeakNameID() { - static const std::string kPURE_WEAK_NAME_IDENTIFIER = "_weak_name_"; + static const std::string kPURE_WEAK_NAME_IDENTIFIER = std::string("_new") + oldPureWeakNameID(); return kPURE_WEAK_NAME_IDENTIFIER; } /// Stores the type of an algorithm in the data tree (in myLab) diff --git a/src/Selector/Selector_Intersect.cpp b/src/Selector/Selector_Intersect.cpp index e473bb697..a104911de 100644 --- a/src/Selector/Selector_Intersect.cpp +++ b/src/Selector/Selector_Intersect.cpp @@ -36,6 +36,7 @@ Selector_Intersect::Selector_Intersect() : Selector_AlgoWithSubs() { myWeakIndex = -1; // no index by default + myRecomputeWeakIndex = false; } // returns the sub-shapes of theSubType which belong to all theShapes (so, common or intersection) @@ -190,9 +191,14 @@ TDF_Label Selector_Intersect::restoreByName(std::string theName, size_t anEndPos = theName.find(']', aStart + 1); if (anEndPos != std::string::npos) { std::string aSubStr = theName.substr(aStart + 1, anEndPos - aStart - 1); - if (aSubStr.find(weakNameID()) == 0) { // weak name identifier - std::string aWeakIndex = aSubStr.substr(weakNameID().size()); + size_t aFoundOldWeak = aSubStr.find(oldWeakNameID()); + size_t aFoundNewWeak = aFoundOldWeak != std::string::npos ? + aSubStr.find(weakNameID()) : + aFoundOldWeak; + if (aFoundOldWeak == 0 || aFoundNewWeak == 0) { // weak name identifier + std::string aWeakIndex = aSubStr.substr(aFoundOldWeak + oldWeakNameID().size()); myWeakIndex = atoi(aWeakIndex.c_str()); + myRecomputeWeakIndex = aFoundOldWeak == 0; continue; } TopAbs_ShapeEnum aSubShapeType = TopAbs_FACE; @@ -245,8 +251,9 @@ bool Selector_Intersect::solve(const TopoDS_Shape& theContext) commonShapes(aSubSelectorShapes, myShapeType, aCommon); if (aCommon.Extent() != 1) { if (myWeakIndex != -1) { - Selector_NExplode aNexp(aCommon); + Selector_NExplode aNexp(aCommon, myRecomputeWeakIndex); aResult = aNexp.shape(myWeakIndex); + myRecomputeWeakIndex = false; } else if (geometricalNaming() && aCommon.Extent() > 1) { // check results are on the same geometry, create compound TopoDS_ListOfShape::Iterator aCommonIter(aCommon); diff --git a/src/Selector/Selector_Intersect.h b/src/Selector/Selector_Intersect.h index 52a9b89a4..1df1326c6 100644 --- a/src/Selector/Selector_Intersect.h +++ b/src/Selector/Selector_Intersect.h @@ -32,6 +32,7 @@ class Selector_Intersect: public Selector_AlgoWithSubs { TopAbs_ShapeEnum myShapeType; ///< type of this shape int myWeakIndex; ///< weak index in case intersection produces several shapes + bool myRecomputeWeakIndex; ///< if the index is stored with old (unstable) order, recompute it public: /// Initializes the selection of this kind SELECTOR_EXPORT bool select(const TopoDS_Shape theContext, const TopoDS_Shape theValue); diff --git a/src/Selector/Selector_Modify.cpp b/src/Selector/Selector_Modify.cpp index 4b719df2c..eb0817d83 100644 --- a/src/Selector/Selector_Modify.cpp +++ b/src/Selector/Selector_Modify.cpp @@ -40,6 +40,7 @@ Selector_Modify::Selector_Modify() : Selector_Algo() { myWeakIndex = -1; // no index by default + myRecomputeWeakIndex = false; } // adds to theResult all labels that contain initial shapes for theValue located in theFinal @@ -253,9 +254,13 @@ TDF_Label Selector_Modify::restoreByName(std::string theName, anEnd = theName.find('&', aStart); std::string aSubStr = theName.substr(aStart, anEnd == std::string::npos ? anEnd : anEnd - aStart); - if (aSubStr.find(weakNameID()) == 0) { // weak name identifier - std::string aWeakIndex = aSubStr.substr(weakNameID().size()); - myWeakIndex = atoi(aWeakIndex.c_str()); + size_t aFoundOldWeak = aSubStr.find(oldWeakNameID()); + size_t aFoundNewWeak = aFoundOldWeak != std::string::npos ? + aSubStr.find(weakNameID()) : + aFoundOldWeak; + if (aFoundOldWeak == 0 || aFoundNewWeak == 0) { // weak name identifier + std::string aWeakIndex = aSubStr.substr(aFoundOldWeak + oldWeakNameID().size()); myWeakIndex = atoi(aWeakIndex.c_str()); + myRecomputeWeakIndex = aFoundOldWeak == 0; continue; } TDF_Label aSubContext, aValue; @@ -310,8 +315,9 @@ bool Selector_Modify::solve(const TopoDS_Shape& theContext) aCommon.Append(aNewShape); } } - Selector_NExplode aNexp(aCommon); + Selector_NExplode aNexp(aCommon, myRecomputeWeakIndex); aResult = aNexp.shape(myWeakIndex); + myRecomputeWeakIndex = false; } else { // standard case TopoDS_ListOfShape aFinalsCommon; // final shapes presented in all results from bases findModificationResult(aFinalsCommon); @@ -319,8 +325,9 @@ bool Selector_Modify::solve(const TopoDS_Shape& theContext) aResult = aFinalsCommon.First(); findNewVersion(theContext, aResult); } else if (aFinalsCommon.Extent() > 1 && myWeakIndex > 0) { - Selector_NExplode aNExp(aFinalsCommon); + Selector_NExplode aNExp(aFinalsCommon, myRecomputeWeakIndex); aResult = aNExp.shape(myWeakIndex); + myRecomputeWeakIndex = false; findNewVersion(theContext, aResult); } else if (aFinalsCommon.Extent() > 1 && geometricalNaming()) {// if same geometry - compound TopoDS_ListOfShape::Iterator aCommonIter(aFinalsCommon); diff --git a/src/Selector/Selector_Modify.h b/src/Selector/Selector_Modify.h index 5b1a4ac93..25e0f5ba4 100644 --- a/src/Selector/Selector_Modify.h +++ b/src/Selector/Selector_Modify.h @@ -36,6 +36,7 @@ class Selector_Modify: public Selector_Algo TDF_Label myFinal; ///< final label of the primitive or generation, where the value is TDF_LabelList myBases; ///< initial labels that contain shapes that produce the modification int myWeakIndex; ///< weak index in case modification produces several shapes + bool myRecomputeWeakIndex; ///< if the index is stored with old (unstable) order, recompute it public: /// Initializes the selection of this kind by list of named shapes where the modification results /// are presented and the selected value. diff --git a/src/Selector/Selector_NExplode.cpp b/src/Selector/Selector_NExplode.cpp index 93e510e6c..2a69c2527 100644 --- a/src/Selector/Selector_NExplode.cpp +++ b/src/Selector/Selector_NExplode.cpp @@ -33,10 +33,22 @@ #include #include -#include #include -static std::pair ShapeToDouble (const TopoDS_Shape& S) +static void dummy(gp_Pnt& thePoint) +{ + // do nothing (new approach to order shapes) +} + +static void pointToDouble(gp_Pnt& thePoint) +{ + // old approach to order shapes + double dMidXYZ = thePoint.X() * 999.0 + thePoint.Y() * 99.0 + thePoint.Z() * 0.9; + thePoint.SetCoord(dMidXYZ, 0.0, 0.0); +} + +static std::pair ShapeToDouble (const TopoDS_Shape& S, + void (*convertPoint)(gp_Pnt&)) { // Computing of CentreOfMass gp_Pnt GPoint; @@ -61,6 +73,7 @@ static std::pair ShapeToDouble (const TopoDS_Shape& S) Len = GPr.Mass(); } + (*convertPoint)(GPoint); return std::make_pair(GPoint, Len); } @@ -71,22 +84,24 @@ struct CompareShapes : public std::binary_function > DataMapOfShapeDouble; - CompareShapes(DataMapOfShapeDouble* theCashMap) : myMap(theCashMap) {} + CompareShapes(DataMapOfShapeDouble* theCashMap, void (*convertPoint)(gp_Pnt&)) + : myMap(theCashMap), myConvertPoint(convertPoint) {} bool operator() (const TopoDS_Shape& lhs, const TopoDS_Shape& rhs); DataMapOfShapeDouble* myMap; + void (*myConvertPoint)(gp_Pnt&); }; bool CompareShapes::operator() (const TopoDS_Shape& theShape1, const TopoDS_Shape& theShape2) { if (!myMap->IsBound(theShape1)) { - myMap->Bind(theShape1, ShapeToDouble(theShape1)); + myMap->Bind(theShape1, ShapeToDouble(theShape1, myConvertPoint)); } if (!myMap->IsBound(theShape2)) { - myMap->Bind(theShape2, ShapeToDouble(theShape2)); + myMap->Bind(theShape2, ShapeToDouble(theShape2, myConvertPoint)); } const std::pair& val1 = myMap->Find(theShape1); @@ -139,60 +154,68 @@ bool CompareShapes::operator() (const TopoDS_Shape& theShape1, return !exchange; } -Selector_NExplode::Selector_NExplode(const TopoDS_ListOfShape& theShapes) +Selector_NExplode::Selector_NExplode(const TopoDS_ListOfShape& theShapes, const bool theOldOrder) + : myToBeReordered(theOldOrder) { - std::vector aShapesVec; - for(TopoDS_ListOfShape::Iterator anIter(theShapes); anIter.More(); anIter.Next()) { - aShapesVec.push_back(anIter.Value()); + mySorted.push_back(anIter.Value()); } CompareShapes::DataMapOfShapeDouble aCash; - CompareShapes shComp(&aCash); - std::stable_sort(aShapesVec.begin(), aShapesVec.end(), shComp); - - std::vector::const_iterator anIter = aShapesVec.begin(); - for (; anIter != aShapesVec.end(); ++anIter) { - mySorted.Append(*anIter); - } + CompareShapes shComp(&aCash, theOldOrder ? pointToDouble : dummy); + std::stable_sort(mySorted.begin(), mySorted.end(), shComp); } -Selector_NExplode::Selector_NExplode(const TopoDS_Shape& theShape, const TopAbs_ShapeEnum theType) +Selector_NExplode::Selector_NExplode(const TopoDS_Shape& theShape, const TopAbs_ShapeEnum theType, + const bool theOldOrder) + : myToBeReordered(theOldOrder) { - std::vector aShapesVec; TopTools_MapOfShape anAdded; // to avoid same shapes duplication for(TopExp_Explorer anExp(theShape, theType); anExp.More(); anExp.Next()) { if (anAdded.Add(anExp.Current())) - aShapesVec.push_back(anExp.Current()); + mySorted.push_back(anExp.Current()); } CompareShapes::DataMapOfShapeDouble aCash; - CompareShapes shComp(&aCash); - std::stable_sort(aShapesVec.begin(), aShapesVec.end(), shComp); - - std::vector::const_iterator anIter = aShapesVec.begin(); - for (; anIter != aShapesVec.end(); ++anIter) { - mySorted.Append(*anIter); - } + CompareShapes shComp(&aCash, theOldOrder ? pointToDouble : dummy); + std::stable_sort(mySorted.begin(), mySorted.end(), shComp); } int Selector_NExplode::index(const TopoDS_Shape& theSubShape) { - TopoDS_ListOfShape::Iterator anIter(mySorted); - for(int anIndex = 1; anIter.More(); anIter.Next(), anIndex++) { - if (anIter.Value().IsSame(theSubShape)) + // reorder if necessary + reorder(); + + std::vector::iterator anIter = mySorted.begin(); + for(int anIndex = 1; anIter != mySorted.end(); anIter++, anIndex++) { + if ((*anIter).IsSame(theSubShape)) return anIndex; } return -1; // not found } -TopoDS_Shape Selector_NExplode::shape(const int theIndex) +TopoDS_Shape Selector_NExplode::shape(int& theIndex) { - TopoDS_ListOfShape::Iterator anIter(mySorted); - for(int anIndex = 1; anIter.More(); anIter.Next(), anIndex++) { - if (anIndex == theIndex) - return anIter.Value(); + std::vector::iterator anIter = mySorted.begin(); + for(int anIndex = 1; anIter != mySorted.end(); anIter++, anIndex++) { + if (anIndex == theIndex) { + TopoDS_Shape aShape = *anIter; + if (myToBeReordered) + theIndex = index(aShape); + return aShape; + } } return TopoDS_Shape(); // not found } + +void Selector_NExplode::reorder() +{ + if (!myToBeReordered) + return; + + myToBeReordered = false; + CompareShapes::DataMapOfShapeDouble aCash; + CompareShapes shComp(&aCash, dummy); + std::stable_sort(mySorted.begin(), mySorted.end(), shComp); +} diff --git a/src/Selector/Selector_NExplode.h b/src/Selector/Selector_NExplode.h index 849a3c291..412620b8c 100644 --- a/src/Selector/Selector_NExplode.h +++ b/src/Selector/Selector_NExplode.h @@ -23,7 +23,8 @@ #include "Selector.h" #include -#include + +#include /// \class Selector_NExplode /// \ingroup DataModel @@ -34,17 +35,26 @@ class Selector_NExplode { public: /// \brief Initializes the sorted list of shapes by the shapes list. - SELECTOR_EXPORT Selector_NExplode(const TopoDS_ListOfShape& theShapes); + SELECTOR_EXPORT Selector_NExplode(const TopoDS_ListOfShape& theShapes, + const bool theOldOrder = false); /// \brief Initializes the sorted list of shapes by the context shape and type of sub-shapes. - SELECTOR_EXPORT Selector_NExplode(const TopoDS_Shape& theShape, const TopAbs_ShapeEnum theType); + SELECTOR_EXPORT Selector_NExplode(const TopoDS_Shape& theShape, + const TopAbs_ShapeEnum theType, + const bool theOldOrder = false); /// Returns an index (started from one) of sub-shape in the sorted list. Returns 0 if not found. SELECTOR_EXPORT int index(const TopoDS_Shape& theSubShape); /// Returns a shape by an index (started from one). Returns null if not found. - SELECTOR_EXPORT TopoDS_Shape shape(const int theIndex); + /// Recompute the index if the old order was used. The value will contain the new ordered index. + SELECTOR_EXPORT TopoDS_Shape shape(int& theIndex); + +private: + /// Reorder list of shapes. + void reorder(); protected: - TopoDS_ListOfShape mySorted; ///< keep the ordered list of shapes + std::vector mySorted; ///< keep the ordered list of shapes + bool myToBeReordered; ///< the list has to be reordered }; #endif diff --git a/src/Selector/Selector_WeakName.cpp b/src/Selector/Selector_WeakName.cpp index 077ce7db4..813fa0b4e 100644 --- a/src/Selector/Selector_WeakName.cpp +++ b/src/Selector/Selector_WeakName.cpp @@ -27,7 +27,7 @@ #include #include -Selector_WeakName::Selector_WeakName() : Selector_Algo() +Selector_WeakName::Selector_WeakName() : Selector_Algo(), myRecomputeWeakIndex(false) { } @@ -88,9 +88,11 @@ bool Selector_WeakName::restore() TDF_Label Selector_WeakName::restoreByName(std::string theName, const TopAbs_ShapeEnum theShapeType, Selector_NameGenerator* theNameGenerator) { - std::string aWeakIndex = theName.substr(pureWeakNameID().size()); + size_t aFoundWeak = theName.find(oldPureWeakNameID()); + std::string aWeakIndex = theName.substr(aFoundWeak + oldPureWeakNameID().size()); std::size_t aContextPosition = aWeakIndex.find("_"); myWeakIndex = atoi(aWeakIndex.c_str()); + myRecomputeWeakIndex = aFoundWeak == 0; myShapeType = theShapeType; TDF_Label aContext; if (aContextPosition != std::string::npos) { // context is also defined @@ -116,8 +118,9 @@ bool Selector_WeakName::solve(const TopoDS_Shape& theContext) } } if (!aContext.IsNull()) { - Selector_NExplode aNexp(aContext, myShapeType); + Selector_NExplode aNexp(aContext, myShapeType, myRecomputeWeakIndex); TopoDS_Shape aResult = aNexp.shape(myWeakIndex); + myRecomputeWeakIndex = false; if (!aResult.IsNull()) { Selector_Algo::store(aResult); return true; diff --git a/src/Selector/Selector_WeakName.h b/src/Selector/Selector_WeakName.h index 6e2e67b25..317dcc4af 100644 --- a/src/Selector/Selector_WeakName.h +++ b/src/Selector/Selector_WeakName.h @@ -31,6 +31,7 @@ class Selector_WeakName: public Selector_Algo { TopAbs_ShapeEnum myShapeType; ///< type of this shape int myWeakIndex; ///< weak index in case modification produces several shapes + bool myRecomputeWeakIndex; ///< if the index is stored with old (unstable) order, recompute it TDF_Label myContext; ///< context shape label public: /// Initializes the selection of this kind -- 2.39.2