From e2d306deddb6e7dc40feed3422bf72f1eae68cd9 Mon Sep 17 00:00:00 2001 From: mpv Date: Tue, 23 Oct 2018 11:10:49 +0300 Subject: [PATCH] Pure weak naming implementation in Selector --- .../FeaturesPlugin_CompositeSketch.cpp | 117 ------------------ src/Model/Model_Objects.cpp | 2 +- src/Selector/Selector_NExplode.cpp | 20 +++ src/Selector/Selector_NExplode.h | 4 +- src/Selector/Selector_Selector.cpp | 107 +++++++++++++++- src/Selector/Selector_Selector.h | 1 + 6 files changed, 126 insertions(+), 125 deletions(-) diff --git a/src/FeaturesPlugin/FeaturesPlugin_CompositeSketch.cpp b/src/FeaturesPlugin/FeaturesPlugin_CompositeSketch.cpp index b9399a815..5df959f46 100644 --- a/src/FeaturesPlugin/FeaturesPlugin_CompositeSketch.cpp +++ b/src/FeaturesPlugin/FeaturesPlugin_CompositeSketch.cpp @@ -317,123 +317,6 @@ void FeaturesPlugin_CompositeSketch::storeGenerationHistory(ResultBodyPtr theRes aShapeTypeToExplode == GeomAPI_Shape::COMPOUND) { theResultBody->loadGeneratedShapes(theMakeShape, theBaseShape, GeomAPI_Shape::EDGE); } - // issue #2197: make naming of edges generated from vertices - if (aShapeTypeToExplode == GeomAPI_Shape::EDGE) { - GeomAPI_DataMapOfShapeShape aFacesFromFromEdges; - GeomAPI_ShapeExplorer anEdgeExp(theBaseShape, GeomAPI_Shape::EDGE); - for(; anEdgeExp.more(); anEdgeExp.next()) { - ListOfShape aGenerated; - theMakeShape->generated(anEdgeExp.current(), aGenerated); - ListOfShape::iterator aGenIter = aGenerated.begin(); - for(; aGenIter != aGenerated.end(); aGenIter++) { - GeomShapePtr aGen = *aGenIter; - if (aGen.get() && !aGen->isNull()) { - if ((*aGenIter)->shapeType() == GeomAPI_Shape::FACE) { // normal case - aFacesFromFromEdges.bind(aGen, anEdgeExp.current()); - } - } - } - } - - // closed revolution of 1-3 faces can not distinguish lateral and base edges - if (aFacesFromFromEdges.size() <= 3) { - bool isClosed = false; // lateral edges are closed (in full revolution) - GeomAPI_DataMapOfShapeShape anEdgesFromVertices; - GeomAPI_ShapeExplorer aVertExp(theBaseShape, GeomAPI_Shape::VERTEX); - for(; aVertExp.more(); aVertExp.next()) { - ListOfShape aGenerated; - theMakeShape->generated(aVertExp.current(), aGenerated); - ListOfShape::iterator aGenIter = aGenerated.begin(); - for(; aGenIter != aGenerated.end(); aGenIter++) { - std::shared_ptr aGenerated = *aGenIter; - if (anEdgesFromVertices.isBound(aGenerated)) // already here - continue; - std::ostringstream aStream; - aStream << "Lateral_" << aLateralIndex++; - theResultBody->generated(aGenerated, aStream.str()); - - anEdgesFromVertices.bind(aGenerated, aVertExp.current()); - std::shared_ptr anEdge(new GeomAPI_Edge(aGenerated)); - isClosed = isClosed || anEdge->isClosed(); - } - } - if (isClosed) { - GeomAPI_ShapeExplorer anEdgesExp(theMakeShape->shape(), GeomAPI_Shape::EDGE); - for(; anEdgesExp.more(); anEdgesExp.next()) { - if (!anEdgesFromVertices.isBound(anEdgesExp.current())) { - // found a base edge - std::ostringstream aStream; - aStream << "Base_Edge_" << aBaseEdgeIndex++; - theResultBody->generated(anEdgesExp.current(), aStream.str()); - // only one orientation is needed - anEdgesFromVertices.bind(anEdgesExp.current(), anEdgesExp.current()); - } - } - } else if (aFacesFromFromEdges.size() == 1) { // 2233: sphere created by the revolution: - // vertices at degenerated edges will have the same name - GeomAPI_DataMapOfShapeShape aVertices; - GeomAPI_ShapeExplorer aVertExp(theMakeShape->shape(), GeomAPI_Shape::VERTEX); - for(int anIndex = 1; aVertExp.more(); aVertExp.next()) { - if (!aVertices.isBound(aVertExp.current())) { - // found a base edge - std::ostringstream aStream; - aStream << "Vertex_" << aVertexIndex++; - theResultBody->generated(aVertExp.current(), aStream.str()); - // only one orientation is needed - aVertices.bind(aVertExp.current(), aVertExp.current()); - } - } - } - } else { // issue #2197, test case 4 : edges that produce fully-revolved face, - // but contain only 2 edges (on apex of revolution) - GeomAPI_ShapeExplorer anEdgeExp(theBaseShape, GeomAPI_Shape::EDGE); - for(; anEdgeExp.more(); anEdgeExp.next()) { - ListOfShape aGenerated; - theMakeShape->generated(anEdgeExp.current(), aGenerated); - ListOfShape::iterator aGenIter = aGenerated.begin(); - for(; aGenIter != aGenerated.end(); aGenIter++) { - GeomShapePtr aGen = (*aGenIter); - if (aGen.get() && !aGen->isNull()) { - GeomAPI_ShapeExplorer aFaceEdgeExp(aGen, GeomAPI_Shape::EDGE); - int aNumEdges = 0; - int aNumClosed = 0; - GeomShapePtr aNotClosedEdge; - GeomEdgePtr aDegenerateEdge; - GeomAPI_DataMapOfShapeShape alreadyIterated; - for(; aFaceEdgeExp.more(); aFaceEdgeExp.next()) { - std::shared_ptr anEdge(new GeomAPI_Edge(aFaceEdgeExp.current())); - if (anEdge->isDegenerated()) { - aDegenerateEdge = anEdge; - continue; - } - if (alreadyIterated.isBound(anEdge)) - continue; - alreadyIterated.bind(anEdge, anEdge); - aNumEdges++; - if (anEdge->isClosed()) { - aNumClosed++; - } else { - aNotClosedEdge = anEdge; - } - } - if (aNumEdges == 2 && aNumClosed == 1) { - std::ostringstream aStream; - aStream << "Base_Edge_" << aBaseEdgeIndex++; - theResultBody->generated(aNotClosedEdge, aStream.str()); - if (aDegenerateEdge.get()) { // export vertex of the degenerated edge (apex) #2520 - GeomAPI_ShapeExplorer anEdgeExp(aDegenerateEdge, GeomAPI_Shape::VERTEX); - if (anEdgeExp.more()) { - std::ostringstream aStream; - aStream << "Base_Vertex_" << aBaseVertexIndex++; - theResultBody->generated(anEdgeExp.current(), aStream.str()); - } - } - } - } - } - } - } - } std::shared_ptr aMakeSweep = std::dynamic_pointer_cast(theMakeShape); diff --git a/src/Model/Model_Objects.cpp b/src/Model/Model_Objects.cpp index 9d89e5c64..e6116ebbe 100644 --- a/src/Model/Model_Objects.cpp +++ b/src/Model/Model_Objects.cpp @@ -309,7 +309,7 @@ void Model_Objects::removeFeature(FeaturePtr theFeature) for(; aRefIter != aRefs.end(); aRefIter++) { std::shared_ptr aComposite = std::dynamic_pointer_cast(*aRefIter); - if (aComposite.get() && aComposite->isSub(theFeature)) { + if (aComposite.get() && aComposite->data()->isValid() && aComposite->isSub(theFeature)) { aComposite->removeFeature(theFeature); } } diff --git a/src/Selector/Selector_NExplode.cpp b/src/Selector/Selector_NExplode.cpp index 018f6b438..98b3dd42e 100644 --- a/src/Selector/Selector_NExplode.cpp +++ b/src/Selector/Selector_NExplode.cpp @@ -152,6 +152,26 @@ Selector_NExplode::Selector_NExplode(const TopoDS_ListOfShape& theShapes) } } +Selector_NExplode::Selector_NExplode(const TopoDS_Shape& theShape, const TopAbs_ShapeEnum theType) +{ + 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()); + } + + 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); + } +} + + int Selector_NExplode::index(const TopoDS_Shape& theSubShape) { TopoDS_ListOfShape::Iterator anIter(mySorted); diff --git a/src/Selector/Selector_NExplode.h b/src/Selector/Selector_NExplode.h index 4e020c1a9..dc4d0064b 100644 --- a/src/Selector/Selector_NExplode.h +++ b/src/Selector/Selector_NExplode.h @@ -34,8 +34,10 @@ class Selector_NExplode { public: - /// \brief Initializes the sorted list of shapes by the context shape and type of sub-shapes. + /// \brief Initializes the sorted list of shapes by the shapes list. SELECTOR_EXPORT Selector_NExplode(const TopoDS_ListOfShape& theShapes); + /// \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); /// 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); diff --git a/src/Selector/Selector_Selector.cpp b/src/Selector/Selector_Selector.cpp index 54c8aca55..4627c6b69 100644 --- a/src/Selector/Selector_Selector.cpp +++ b/src/Selector/Selector_Selector.cpp @@ -283,6 +283,8 @@ bool Selector_Selector::select(const TopoDS_Shape theContext, const TopoDS_Shape // try to find the shape of the higher level type in the context shape bool aFacesTried = false; // for identification of vertices, faces are tried, then edges + TopoDS_ListOfShape aLastCommon; // to store the commons not good, but may be used for weak + TopTools_MapOfShape aLastIntersectors; while(aSelectionType != TopAbs_FACE || !aFacesTried) { if (aSelectionType == TopAbs_FACE) { if (theValue.ShapeType() != TopAbs_VERTEX) @@ -308,7 +310,7 @@ bool Selector_Selector::select(const TopoDS_Shape theContext, const TopoDS_Shape commonShapes(anIntList, theValue.ShapeType(), aCommon); if (aCommon.Extent() == 1 && aCommon.First().IsSame(theValue)) { // name the intersectors - std::list aSubSelList; + mySubSelList.clear(); TopTools_MapOfShape::Iterator anInt(anIntersectors); for (; anInt.More(); anInt.Next()) { if (!selectBySubSelector(theContext, anInt.Value())) { @@ -318,7 +320,10 @@ bool Selector_Selector::select(const TopoDS_Shape theContext, const TopoDS_Shape if (!anInt.More()) { // all intersectors were correctly named myType = SELTYPE_INTERSECT; return true; - } + } + } else if (aCommon.Extent() > 1 && aLastCommon.IsEmpty()) { + aLastCommon = aCommon; + aLastIntersectors = anIntersectors; } } @@ -356,6 +361,36 @@ bool Selector_Selector::select(const TopoDS_Shape theContext, const TopoDS_Shape return true; } } + + // weak naming to distinguish commons coming from intersection + if (aLastCommon.Extent() > 1) { + Selector_NExplode aNexp(aLastCommon); + myWeakIndex = aNexp.index(theValue); + if (myWeakIndex != -1) { + // name the intersectors + mySubSelList.clear(); + TopTools_MapOfShape::Iterator anInt(aLastIntersectors); + for (; anInt.More(); anInt.Next()) { + if (!selectBySubSelector(theContext, anInt.Value())) { + break; // if some selector is failed, stop and search another solution + } + } + if (!anInt.More()) { // all intersectors were correctly named + myType = SELTYPE_INTERSECT; + return true; + } + } + } + + // pure weak naming + myType = SELTYPE_WEAK_NAMING; + Selector_NExplode aNexp(theContext, theValue.ShapeType()); + myWeakIndex = aNexp.index(theValue); + if (myWeakIndex != -1) { + myShapeType = theValue.ShapeType(); + return true; + } + return false; } // searching for the base shapes of the value @@ -496,6 +531,9 @@ void Selector_Selector::store() for(; aSubSel != mySubSelList.end(); aSubSel++) { aSubSel->store(); } + if (myWeakIndex != -1) { + TDataStd_Integer::Set(myLab, kWEAK_INDEX, myWeakIndex); + } break; } case SELTYPE_PRIMITIVE: { @@ -531,6 +569,12 @@ void Selector_Selector::store() for(; aSubSel != mySubSelList.end(); aSubSel++) { aSubSel->store(); } + break; + } + case SELTYPE_WEAK_NAMING: { + TDataStd_Integer::Set(myLab, kWEAK_INDEX, myWeakIndex); + TDataStd_Integer::Set(myLab, kSHAPE_TYPE, (int)myShapeType); + break; } default: { // unknown case break; @@ -559,6 +603,10 @@ bool Selector_Selector::restore() if (!mySubSelList.back().restore()) aSubResult = false; } + Handle(TDataStd_Integer) aWeakInt; + if (myLab.FindAttribute(kWEAK_INDEX, aWeakInt)) { + myWeakIndex = aWeakInt->Get(); + } return aSubResult; } case SELTYPE_PRIMITIVE: { @@ -607,6 +655,17 @@ bool Selector_Selector::restore() } return true; } + case SELTYPE_WEAK_NAMING: { + Handle(TDataStd_Integer) aWeakInt; + if (!myLab.FindAttribute(kWEAK_INDEX, aWeakInt)) + return false; + myWeakIndex = aWeakInt->Get(); + Handle(TDataStd_Integer) aShapeTypeAttr; + if (!myLab.FindAttribute(kSHAPE_TYPE, aShapeTypeAttr)) + return false; + myShapeType = TopAbs_ShapeEnum(aShapeTypeAttr->Get()); + return myWeakIndex != -1; + } default: { // unknown case } } @@ -704,9 +763,16 @@ bool Selector_Selector::solve(const TopoDS_Shape& theContext) } TopoDS_ListOfShape aCommon; // common sub shapes in each sub-selector (a result) commonShapes(aSubSelectorShapes, myShapeType, aCommon); - if (aCommon.Extent() != 1) - return false; - aResult = aCommon.First(); + if (aCommon.Extent() != 1) { + if (myWeakIndex != -1) { + Selector_NExplode aNexp(aCommon); + aResult = aNexp.shape(myWeakIndex); + } else { + return false; + } + } else { + aResult = aCommon.First(); + } break; } case SELTYPE_PRIMITIVE: { @@ -751,6 +817,11 @@ bool Selector_Selector::solve(const TopoDS_Shape& theContext) aNBs.push_back(std::pair(aSubSel->value(), *aLevel)); } aResult = findNeighbor(theContext, aNBs); + break; + } + case SELTYPE_WEAK_NAMING: { + Selector_NExplode aNexp(theContext, myShapeType); + aResult = aNexp.shape(myWeakIndex); } default: { // unknown case } @@ -779,13 +850,18 @@ std::string Selector_Selector::name(Selector_NameGenerator* theNameGenerator) { case SELTYPE_CONTAINER: case SELTYPE_INTERSECT: { std::string aResult; - // add names of sub-components one by one in "[]" + // add names of sub-components one by one in "[]" +optionally [weak_name_1] std::list::iterator aSubSel = mySubSelList.begin(); for(; aSubSel != mySubSelList.end(); aSubSel++) { aResult += '['; aResult += aSubSel->name(theNameGenerator); aResult += ']'; } + if (myWeakIndex != -1) { + std::ostringstream aWeakStr; + aWeakStr<<"["<FindAttribute(TDataStd_Name::GetID(), aName)) return ""; + aResult += "&"; aResult += theNameGenerator->contextName(*aBase) + "/" + std::string(TCollection_AsciiString(aName->Get()).ToCString()); } @@ -828,6 +905,13 @@ std::string Selector_Selector::name(Selector_NameGenerator* theNameGenerator) { } return aResult; } + case SELTYPE_WEAK_NAMING: { + // weak_naming_1 + std::ostringstream aWeakStr; + aWeakStr<