From b355b9b8ffa5fad1240e5c322301744b32d4534a Mon Sep 17 00:00:00 2001 From: mpv Date: Wed, 10 Aug 2016 16:01:22 +0300 Subject: [PATCH] Make naming names in sub-elements of sketch based on names, not persistent indexes (in the frames of the python dump, issue #1648 ) --- src/Model/Model_AttributeSelection.cpp | 62 ++++++----- src/Model/Model_SelectionNaming.cpp | 143 +++++++++++++++++-------- src/Model/Model_SelectionNaming.h | 8 ++ 3 files changed, 142 insertions(+), 71 deletions(-) diff --git a/src/Model/Model_AttributeSelection.cpp b/src/Model/Model_AttributeSelection.cpp index 33326b351..923b2cd48 100644 --- a/src/Model/Model_AttributeSelection.cpp +++ b/src/Model/Model_AttributeSelection.cpp @@ -642,6 +642,7 @@ void Model_AttributeSelection::selectBody( static void registerSubShape(TDF_Label theMainLabel, TopoDS_Shape theShape, const int theID, const FeaturePtr& theContextFeature, std::shared_ptr theDoc, std::string theAdditionalName, std::map& theOrientations, + std::map& theSubNames, // name of sub-elements by ID to be exported instead of indexes Handle(TDataStd_IntPackedMap) theRefs = Handle(TDataStd_IntPackedMap)(), const int theOrientation = 0) { @@ -652,29 +653,32 @@ static void registerSubShape(TDF_Label theMainLabel, TopoDS_Shape theShape, TNaming_Builder aBuilder(aLab); aBuilder.Generated(theShape); std::stringstream aName; - aName<name()<<"/"; - if (!theAdditionalName.empty()) - aName<GetMap()); - for(; aRef.More(); aRef.Next()) { - aName<<"-"<name(); + if (theShape.ShapeType() != TopAbs_COMPOUND) { // compound means the whole result for construction + aName<<"/"; + if (!theAdditionalName.empty()) + aName<GetMap()); + for(; aRef.More(); aRef.Next()) { + aName<<"-"< anOrientations; //map from edges IDs to orientations of these edges in face + std::map aSubNames; //map from edges IDs to names of edges aRefs->Clear(); const int aSubNum = aComposite->numberOfSubs(); for(int a = 0; a < aSubNum; a++) { @@ -740,6 +745,7 @@ void Model_AttributeSelection::selectConstruction( gp_Pnt aPnt = BRep_Tool::Pnt(TopoDS::Vertex(aVertex)); if (aPnt.IsEqual(aVertexPos, Precision::Confusion())) { aRefs->Add(aComposite->subFeatureId(a)); + aSubNames[aComposite->subFeatureId(a)] = Model_SelectionNaming::shortName(aConstr); } } else { // get first or last vertex of the edge: last is stored with additional delta const TopoDS_Shape& anEdge = aConstr->shape()->impl(); @@ -748,6 +754,8 @@ void Model_AttributeSelection::selectConstruction( gp_Pnt aPnt = BRep_Tool::Pnt(TopoDS::Vertex(aVExp.Current())); if (aPnt.IsEqual(aVertexPos, Precision::Confusion())) { aRefs->Add(aDelta + aComposite->subFeatureId(a)); + aSubNames[aDelta + aComposite->subFeatureId(a)] = + Model_SelectionNaming::shortName(aConstr, aDelta / kSTART_VERTEX_DELTA); break; } aDelta += kSTART_VERTEX_DELTA; @@ -763,6 +771,7 @@ void Model_AttributeSelection::selectConstruction( if (allCurves.Contains(aCurve)) { int anID = aComposite->subFeatureId(a); aRefs->Add(anID); + aSubNames[anID] = Model_SelectionNaming::shortName(aConstr); if (aShapeType != TopAbs_EDGE) { // face needs the sub-edges on sub-labels // add edges to sub-label to support naming for edges selection TopExp_Explorer anEdgeExp(aSubShape, TopAbs_EDGE); @@ -775,7 +784,7 @@ void Model_AttributeSelection::selectConstruction( anOrientations[anID] = anOrient; registerSubShape( selectionLabel(), anEdge, anID, aContextFeature, aMyDoc, "", anOrientations, - Handle(TDataStd_IntPackedMap)(), anOrient); + aSubNames, Handle(TDataStd_IntPackedMap)(), anOrient); } } } else { // put vertices of the selected edge to sub-labels @@ -787,7 +796,8 @@ void Model_AttributeSelection::selectConstruction( std::stringstream anAdditionalName; registerSubShape( - selectionLabel(), aV, aTagIndex, aContextFeature, aMyDoc, "", anOrientations); + selectionLabel(), aV, aTagIndex, aContextFeature, aMyDoc, "", anOrientations, + aSubNames); } } } @@ -800,7 +810,7 @@ void Model_AttributeSelection::selectConstruction( TNaming_Builder aBuilder(selectionLabel()); aBuilder.Generated(aSubShape); registerSubShape( - selectionLabel(), aSubShape, 0, aContextFeature, aMyDoc, "", anOrientations, aRefs); + selectionLabel(), aSubShape, 0, aContextFeature, aMyDoc, "", anOrientations, aSubNames, aRefs); } bool Model_AttributeSelection::selectPart( diff --git a/src/Model/Model_SelectionNaming.cpp b/src/Model/Model_SelectionNaming.cpp index 6f39a650f..68311d6f2 100644 --- a/src/Model/Model_SelectionNaming.cpp +++ b/src/Model/Model_SelectionNaming.cpp @@ -29,7 +29,7 @@ #include #include #include - +#include #ifdef DEB_NAMING #include @@ -458,40 +458,63 @@ std::string getContextName(const std::string& theSubShapeName) { std::string aName; std::string::size_type n = theSubShapeName.find('/'); - if (n == std::string::npos) return aName; + if (n == std::string::npos) return theSubShapeName; aName = theSubShapeName.substr(0, n); return aName; } /// Parses naming name of sketch sub-elements: takes indices and orientation /// (if theOriented = true) from this name. Map theIDs constains indices -> -/// orientations (true by default) -bool parseSubIndices(const std::string& theName, const char* theShapeType, - std::map& theIDs, const bool theOriented = false) +/// orientations and start/end vertices: negative is reversed, 2 - start, 3 - end +bool parseSubIndices(CompositeFeaturePtr theComp, //< to iterate names + const std::string& theName, const char* theShapeType, + std::map& theIDs, const bool theOriented = false) { // collect all IDs in the name - std::set anIDs; + std::map aNames; // short name of sub -> ID of sub of theComp + const int aSubNum = theComp->numberOfSubs(); + for(int a = 0; a < aSubNum; a++) { + FeaturePtr aSub = theComp->subFeature(a); + const std::list >& aResults = aSub->results(); + std::list >::const_iterator aRes = aResults.cbegin(); + // there may be many shapes (circle and center) + for(; aRes != aResults.cend(); aRes++) { + ResultConstructionPtr aConstr = + std::dynamic_pointer_cast(*aRes); + if (aConstr.get()) { + aNames[Model_SelectionNaming::shortName(aConstr)] = theComp->subFeatureId(a); + } + } + } + size_t aPrevPos = theName.find("/") + 1, aLastNamePos; bool isShape = false; // anyway the first world must be 'Vertex' do { aLastNamePos = theName.find('-', aPrevPos); - const std::string anID = theName.substr(aPrevPos, aLastNamePos - aPrevPos); + std::string anID = theName.substr(aPrevPos, aLastNamePos - aPrevPos); if (!isShape) { if (anID != theShapeType) return false; isShape = true; } else { - bool anOrientation = true; // default + int anOrientation = 1; // default if (theOriented) { // here must be a symbol in the end of digit 'f' or 'r' - const char aSymbol = theName.back(); - anOrientation = aSymbol == 'f'; + const char aSymbol = anID.back(); + if (aSymbol == 'r') anOrientation = -1; + anID.pop_back(); + } + // check start/end symbols + if (anID.back() == 's') { + anOrientation *= 2; + anID.pop_back(); + } else if (anID.back() == 'e') { + anOrientation *= 3; + anID.pop_back(); + } + + if (aNames.find(anID) != aNames.end()) { + theIDs[aNames[anID]] = anOrientation; } - int anInt = 0; - try { - anInt = std::stoi(anID, nullptr); - } catch (const std::invalid_argument&) {} - if (anInt != 0) - theIDs[anInt] = anOrientation; } aPrevPos = aLastNamePos + 1; } while (aLastNamePos != std::string::npos); @@ -560,6 +583,27 @@ std::shared_ptr Model_SelectionNaming::findAppropriateFace( return aResult; } +std::string Model_SelectionNaming::shortName( + std::shared_ptr& theConstr, const int theEdgeVertexPos) +{ + std::string aName = theConstr->data()->name(); + // remove "-", "/" and "&" command-symbols + aName.erase(std::remove(aName.begin(), aName.end(), '-'), aName.end()); + aName.erase(std::remove(aName.begin(), aName.end(), '/'), aName.end()); + aName.erase(std::remove(aName.begin(), aName.end(), '&'), aName.end()); + // remove the last 's', 'e', 'f' and 'r' symbols: they are used as markers of start/end/forward/rewersed indicators + static const std::string aSyms("sefr"); + while(aSyms.find(aName.back()) != std::string::npos) { + aName.pop_back(); + } + if (theEdgeVertexPos == 1) { + aName += "s"; // start + } else if (theEdgeVertexPos == 2) { + aName += "e"; // end + } + return aName; +} + // type ::= COMP | COMS | SOLD | SHEL | FACE | WIRE | EDGE | VERT bool Model_SelectionNaming::selectSubShape(const std::string& theType, const std::string& theSubShapeName, std::shared_ptr theDoc, @@ -611,9 +655,16 @@ bool Model_SelectionNaming::selectSubShape(const std::string& theType, case TopAbs_SOLID: case TopAbs_SHELL: case TopAbs_WIRE: - default: //TopAbs_SHAPE + default: {//TopAbs_SHAPE + /// case when the whole sketch is selected, so, selection type is compound, but there is no value + if (aCont.get() && aCont->shape().get() && + aCont->shape()->impl().ShapeType() == aType) { + theCont = aCont; + return true; + } return false; } + } // another try to find edge or vertex by faces std::list aListofNames; size_t aN = aSelection.IsNull() ? ParseName(theSubShapeName, aListofNames) : 0; @@ -656,8 +707,9 @@ bool Model_SelectionNaming::selectSubShape(const std::string& theType, if (aComposite.get()) { if (aType == TopAbs_VERTEX || aType == TopAbs_EDGE) { // collect all IDs in the name - std::map anIDs; - if (!parseSubIndices(theSubShapeName, aType == TopAbs_EDGE ? "Edge" : "Vertex", anIDs)) + std::map anIDs; + if (!parseSubIndices(aComposite, theSubShapeName, + aType == TopAbs_EDGE ? "Edge" : "Vertex", anIDs)) return false; const int aSubNum = aComposite->numberOfSubs(); @@ -665,38 +717,39 @@ bool Model_SelectionNaming::selectSubShape(const std::string& theType, int aCompID = aComposite->subFeatureId(a); if (anIDs.find(aCompID) != anIDs.end()) { // found the vertex/edge shape FeaturePtr aSub = aComposite->subFeature(a); - ResultConstructionPtr aV = std::dynamic_pointer_cast - (*(aSub->results().begin())); - if (aV) { - theShapeToBeSelected = aV->shape(); - return true; - } - } else if (aType == TopAbs_VERTEX && - (anIDs.find(aCompID + kSTART_VERTEX_DELTA) != anIDs.end() || - anIDs.find(aCompID + 2 * kSTART_VERTEX_DELTA) != anIDs.end())) { - FeaturePtr aSub = aComposite->subFeature(a); const std::list >& aResults = aSub->results(); - std::list >::const_iterator aRes = aResults.cbegin(); + std::list >::const_iterator aRIt = aResults.cbegin(); // there may be many shapes (circle and center) - for(; aRes != aResults.cend(); aRes++) { - ResultConstructionPtr aE = - std::dynamic_pointer_cast(*aRes); - if (aE && aE->shape()->isEdge()) { - const TopoDS_Shape& anEdge = aE->shape()->impl(); - TopExp_Explorer aVExp(anEdge, TopAbs_VERTEX); // first vertex - if (anIDs.find(aCompID + kSTART_VERTEX_DELTA) == anIDs.end()) - aVExp.Next(); // second vertex - std::shared_ptr aShapeToBeSelected(new GeomAPI_Shape()); - aShapeToBeSelected->setImpl(new TopoDS_Shape(aVExp.Current())); - theShapeToBeSelected = aShapeToBeSelected; - return true; + for(; aRIt != aResults.cend(); aRIt++) { + ResultConstructionPtr aRes = + std::dynamic_pointer_cast(*aRIt); + if (aRes) { + int anOrientation = abs(anIDs[aCompID]); + TopoDS_Shape aShape = aRes->shape()->impl(); + if (anOrientation == 1) { + if (aType == aShape.ShapeType()) { + theShapeToBeSelected = aRes->shape(); + return true; + } + } else { // take first or second vertex of the edge + TopoDS_Shape aShape = aRes->shape()->impl(); + TopExp_Explorer anExp(aShape, aType); + for(; anExp.More() && anOrientation != 2; anOrientation--) + anExp.Next(); + if (anExp.More()) { + std::shared_ptr aShapeToBeSelected(new GeomAPI_Shape()); + aShapeToBeSelected->setImpl(new TopoDS_Shape(anExp.Current())); + theShapeToBeSelected = aShapeToBeSelected; + return true; + } + } } } } } } else if (aType == TopAbs_FACE) { // sketch faces is identified by format "Sketch_1/Face-2f-8f-11r" - std::map anIDs; - if (!parseSubIndices(theSubShapeName, "Face", anIDs, true)) + std::map anIDs; + if (!parseSubIndices(aComposite, theSubShapeName, "Face", anIDs, true)) return false; NCollection_DataMap allCurves; // curves and orientations of edges @@ -716,7 +769,7 @@ bool Model_SelectionNaming::selectSubShape(const std::string& theType, if (!anEdge.IsNull()) { Standard_Real aFirst, aLast; Handle(Geom_Curve) aCurve = BRep_Tool::Curve(anEdge, aFirst, aLast); - allCurves.Bind(aCurve, anIDs[aSubID] ? 1 : -1); + allCurves.Bind(aCurve, anIDs[aSubID] > 0 ? 1 : -1); } } } diff --git a/src/Model/Model_SelectionNaming.h b/src/Model/Model_SelectionNaming.h index 8a7fbfda0..134d0186e 100644 --- a/src/Model/Model_SelectionNaming.h +++ b/src/Model/Model_SelectionNaming.h @@ -53,6 +53,14 @@ public: /// Returns orientation of the edge in the context shape static int edgeOrientation(const TopoDS_Shape& theContext, TopoDS_Edge& theEdge); + /// Returns the name of sketch sub-element, shortened by exclusion of some symbols and with added + /// the vertex position (if needed) + /// \param theConstr result with name - basis for the name + /// \param theEdgeVertexPos position of the vertex on edge: 1 - first , 2 - second + /// \returns the generated name + static std::string shortName(std::shared_ptr& theConstr, + const int theEdgeVertexPos = 0); + protected: /// Gets the stored name from the document std::string getShapeName(std::shared_ptr theDoc, const TopoDS_Shape& theShape); -- 2.39.2