From 99e762ef5f6d13cba5b1bd226b3b9f5f48bb5f7d Mon Sep 17 00:00:00 2001 From: mpv Date: Thu, 4 Oct 2018 14:47:58 +0300 Subject: [PATCH] Fix for the big models (like flange) naming correctness. Make sketch sub-elements named in the same way (same is Equal) as isEqual for the GeomAPI_Edge. --- src/GeomAPI/GeomAPI_Edge.cpp | 8 +- src/Model/Model_ResultConstruction.cpp | 122 +++++++++++++++---------- src/Model/Model_SelectionNaming.cpp | 68 +++++++++++++- src/Model/Model_SelectionNaming.h | 27 +++++- 4 files changed, 167 insertions(+), 58 deletions(-) diff --git a/src/GeomAPI/GeomAPI_Edge.cpp b/src/GeomAPI/GeomAPI_Edge.cpp index cd3c08466..01c98124c 100644 --- a/src/GeomAPI/GeomAPI_Edge.cpp +++ b/src/GeomAPI/GeomAPI_Edge.cpp @@ -217,16 +217,16 @@ bool GeomAPI_Edge::isEqual(const std::shared_ptr theEdge) const double aInStart, aInEnd; Handle(Geom_Curve) aInCurve = BRep_Tool::Curve(TopoDS::Edge(aInShape), aInStart, aInEnd); + // Check that end point parameters are the same + if ((aMyStart != aInStart) || (aMyEnd != aInEnd)) + return false; + // Check that curves a the same type GeomAdaptor_Curve aMyAdaptor(aMyCurve); GeomAdaptor_Curve aInAdaptor(aInCurve); if (aMyAdaptor.GetType() != aInAdaptor.GetType()) return false; - // Check that end point parameters are the same - if ((aMyStart != aInStart) || (aMyEnd != aInEnd)) - return false; - // Check that end points are equal gp_Pnt aMyPnt1 = aMyAdaptor.Value(aMyStart); gp_Pnt aMyPnt2 = aMyAdaptor.Value(aMyEnd); diff --git a/src/Model/Model_ResultConstruction.cpp b/src/Model/Model_ResultConstruction.cpp index ad9c9a307..432f56b13 100644 --- a/src/Model/Model_ResultConstruction.cpp +++ b/src/Model/Model_ResultConstruction.cpp @@ -177,12 +177,16 @@ std::string fullName(CompositeFeaturePtr theComposite, const TopoDS_Shape& theSu { TopAbs_ShapeEnum aShapeType = theSubShape.ShapeType(); gp_Pnt aVertexPos; - TColStd_MapOfTransient allCurves; + NCollection_Map allExactEdges; + NCollection_Map allEdges; + NCollection_Map allCurves; if (aShapeType == TopAbs_VERTEX) { // compare positions aVertexPos = BRep_Tool::Pnt(TopoDS::Vertex(theSubShape)); } else { for(TopExp_Explorer anEdgeExp(theSubShape, TopAbs_EDGE); anEdgeExp.More(); anEdgeExp.Next()) { TopoDS_Edge anEdge = TopoDS::Edge(anEdgeExp.Current()); + allExactEdges.Add(anEdge); + allEdges.Add(anEdge); Standard_Real aFirst, aLast; Handle(Geom_Curve) aCurve = BRep_Tool::Curve(anEdge, aFirst, aLast); allCurves.Add(aCurve); @@ -193,47 +197,58 @@ std::string fullName(CompositeFeaturePtr theComposite, const TopoDS_Shape& theSu TColStd_PackedMapOfInteger aRefs; // indixes of sub-elements in composite const int aSubNum = theComposite->numberOfSubs(); - for(int a = 0; a < aSubNum; a++) { - FeaturePtr aSub = theComposite->subFeature(a); - const std::list >& aResults = aSub->results(); - std::list >::const_iterator aRes = aResults.cbegin(); - // there may be many shapes (circle and center): register if at least one is in selection - for(; aRes != aResults.cend(); aRes++) { - ResultConstructionPtr aConstr = - std::dynamic_pointer_cast(*aRes); - if (!aConstr->shape()) { - continue; - } - if (aShapeType == TopAbs_VERTEX) { - if (aConstr->shape()->isVertex()) { // compare vertices positions - const TopoDS_Shape& aVertex = aConstr->shape()->impl(); - gp_Pnt aPnt = BRep_Tool::Pnt(TopoDS::Vertex(aVertex)); - if (aPnt.IsEqual(aVertexPos, Precision::Confusion())) { - aRefs.Add(theComposite->subFeatureId(a)); - aSubNames[theComposite->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(); - int aDelta = kSTART_VERTEX_DELTA; - for(TopExp_Explorer aVExp(anEdge, TopAbs_VERTEX); aVExp.More(); aVExp.Next()) { - gp_Pnt aPnt = BRep_Tool::Pnt(TopoDS::Vertex(aVExp.Current())); + // reduce equality criteria from strong to weak + for(int aTypeOfIdentification = 0; aTypeOfIdentification < 3; aTypeOfIdentification++) { + for(int a = 0; a < aSubNum; a++) { + FeaturePtr aSub = theComposite->subFeature(a); + const std::list >& aResults = aSub->results(); + std::list >::const_iterator aRes = aResults.cbegin(); + // there may be many shapes (circle and center): register if at least one is in selection + for(; aRes != aResults.cend(); aRes++) { + ResultConstructionPtr aConstr = + std::dynamic_pointer_cast(*aRes); + if (!aConstr->shape()) { + continue; + } + if (aShapeType == TopAbs_VERTEX) { + if (aConstr->shape()->isVertex()) { // compare vertices positions + const TopoDS_Shape& aVertex = aConstr->shape()->impl(); + gp_Pnt aPnt = BRep_Tool::Pnt(TopoDS::Vertex(aVertex)); if (aPnt.IsEqual(aVertexPos, Precision::Confusion())) { - aRefs.Add(aDelta + theComposite->subFeatureId(a)); - aSubNames[aDelta + theComposite->subFeatureId(a)] = - Model_SelectionNaming::shortName(aConstr, aDelta / kSTART_VERTEX_DELTA); - break; + aRefs.Add(theComposite->subFeatureId(a)); + aSubNames[theComposite->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(); + int aDelta = kSTART_VERTEX_DELTA; + for(TopExp_Explorer aVExp(anEdge, TopAbs_VERTEX); aVExp.More(); aVExp.Next()) { + gp_Pnt aPnt = BRep_Tool::Pnt(TopoDS::Vertex(aVExp.Current())); + if (aPnt.IsEqual(aVertexPos, Precision::Confusion())) { + aRefs.Add(aDelta + theComposite->subFeatureId(a)); + aSubNames[aDelta + theComposite->subFeatureId(a)] = + Model_SelectionNaming::shortName(aConstr, aDelta / kSTART_VERTEX_DELTA); + break; + } + aDelta += kSTART_VERTEX_DELTA; } - aDelta += kSTART_VERTEX_DELTA; } - } - } else { - if (aConstr->shape()->isEdge()) { - const TopoDS_Shape& aResShape = aConstr->shape()->impl(); - TopoDS_Edge anEdge = TopoDS::Edge(aResShape); - if (!anEdge.IsNull()) { - Standard_Real aFirst, aLast; - Handle(Geom_Curve) aCurve = BRep_Tool::Curve(anEdge, aFirst, aLast); - if (allCurves.Contains(aCurve)) { + } else { + if (aConstr->shape()->isEdge()) { + const TopoDS_Shape& aResShape = aConstr->shape()->impl(); + TopoDS_Edge anEdge = TopoDS::Edge(aResShape); + if (anEdge.IsNull()) + continue; + bool aIsEqual = false; + if (aTypeOfIdentification == 0) { // check equality of curves + aIsEqual = allExactEdges.Contains(anEdge); + } else if (aTypeOfIdentification == 1) { // check EdgesHash equality of edges + aIsEqual = allEdges.Contains(anEdge); + } else { // check CurvesHash equality of curves + Standard_Real aFirst, aLast; + Handle(Geom_Curve) aCurve = BRep_Tool::Curve(anEdge, aFirst, aLast); + aIsEqual = allCurves.Contains(aCurve); + } + if (aIsEqual) { int anID = theComposite->subFeatureId(a); aRefs.Add(anID); aSubNames[anID] = Model_SelectionNaming::shortName(aConstr); @@ -241,11 +256,20 @@ std::string fullName(CompositeFeaturePtr theComposite, const TopoDS_Shape& theSu // add edges to sub-label to support naming for edges selection TopExp_Explorer anEdgeExp(theSubShape, TopAbs_EDGE); for(; anEdgeExp.More(); anEdgeExp.Next()) { - TopoDS_Edge anEdge = TopoDS::Edge(anEdgeExp.Current()); - Standard_Real aFirst, aLast; - Handle(Geom_Curve) aFaceCurve = BRep_Tool::Curve(anEdge, aFirst, aLast); - if (aFaceCurve == aCurve) { - int anOrient = Model_SelectionNaming::edgeOrientation(theSubShape, anEdge); + TopoDS_Edge aFaceEdge = TopoDS::Edge(anEdgeExp.Current()); + bool aIsEqual = false; + if (aTypeOfIdentification == 0) { // check equality of curves + aIsEqual = anEdge.IsSame(aFaceEdge); + } else if (aTypeOfIdentification == 1) { // check EdgesHash equality of edges + aIsEqual = Model_EdgesHasher::IsEqual(aFaceEdge, anEdge); + } else { // check CurvesHash equality of curves + Standard_Real aFirst, aLast; + Handle(Geom_Curve) aFaceCurve = BRep_Tool::Curve(aFaceEdge, aFirst, aLast); + Handle(Geom_Curve) aCurve = BRep_Tool::Curve(anEdge, aFirst, aLast); + aIsEqual = Model_CurvesHasher::IsEqual(aFaceCurve, aCurve); + } + if (aIsEqual) { + int anOrient = Model_SelectionNaming::edgeOrientation(theSubShape, aFaceEdge); anOrientations[anID] = anOrient; } } @@ -255,6 +279,8 @@ std::string fullName(CompositeFeaturePtr theComposite, const TopoDS_Shape& theSu } } } + if (!aRefs.IsEmpty() || aShapeType == TopAbs_VERTEX) + break; } std::stringstream aName; // #1839 : do not store name of the feature in the tree, since this name could be changed @@ -303,7 +329,7 @@ static void saveSubName(CompositeFeaturePtr theComposite, TopoDS_Edge anEdge = TopoDS::Edge(anExp.Current()); Standard_Real aFirst, aLast; Handle(Geom_Curve) aCurve = BRep_Tool::Curve(anEdge, aFirst, aLast); - if (aCurve == aSubCurve && + if (Model_CurvesHasher::IsEqual(aCurve, aSubCurve) && ((fabs(aFirst - aSubFirst) < 1.e-9 && fabs(aLast - aSubLast) < 1.e-9)) || (fabs(aFirst - aSubLast) < 1.e-9 && fabs(aLast - aSubFirst) < 1.e-9)) { aSub = anEdge; @@ -474,7 +500,7 @@ int Model_ResultConstruction::select(const std::shared_ptr& theSu TopAbs_ShapeEnum aShapeType = aSubShape.ShapeType(); TDataStd_Integer::Set(aLab, (int)aShapeType); gp_Pnt aVertexPos; - TColStd_MapOfTransient allCurves; + TColStd_MapOfTransient allCurves; // curves of the sketc hsub-elements are used, so, edges are not equal if (aShapeType == TopAbs_VERTEX) { // compare positions aVertexPos = BRep_Tool::Pnt(TopoDS::Vertex(aSubShape)); } else { @@ -521,7 +547,7 @@ int Model_ResultConstruction::select(const std::shared_ptr& theSu TopoDS_Edge anEdge = TopoDS::Edge(anEdgeExp.Current()); Standard_Real aFirst, aLast; Handle(Geom_Curve) aFaceCurve = BRep_Tool::Curve(anEdge, aFirst, aLast); - if (aFaceCurve == aCurve) { + if (Model_CurvesHasher::IsEqual(aFaceCurve, aCurve)) { while(aUsedIDMap.Contains(anID)) anID += 100000; aUsedIDMap.Add(anID); @@ -700,7 +726,7 @@ bool Model_ResultConstruction::update(const int theIndex, } else { // searching for most looks-like initial face by the indexes // prepare edges of the current result for the fast searching // curves and orientations of edges - NCollection_DataMap allCurves; + NCollection_DataMap allCurves; const int aSubNum = aComposite->numberOfSubs(); for(int a = 0; a < aSubNum; a++) { int aSubID = aComposite->subFeatureId(a); diff --git a/src/Model/Model_SelectionNaming.cpp b/src/Model/Model_SelectionNaming.cpp index 1b1c51e9e..9daf02c95 100644 --- a/src/Model/Model_SelectionNaming.cpp +++ b/src/Model/Model_SelectionNaming.cpp @@ -30,6 +30,7 @@ #include #include #include +#include #include #include @@ -50,6 +51,7 @@ #include #include #include +#include #include #include @@ -700,9 +702,67 @@ int Model_SelectionNaming::edgeOrientation(const TopoDS_Shape& theContext, TopoD return 0; // unknown } +int Model_CurvesHasher::HashCode(const Handle(Geom_Curve)& theCurve, const Standard_Integer Upper) +{ + double aFirstParam = theCurve->FirstParameter(); + if (aFirstParam < -1.e+100 || aFirstParam > 1.e+100) + aFirstParam = 0; + double aLastParam = theCurve->LastParameter(); + if (aLastParam < -1.e+100 || aLastParam > 1.e+100) + aLastParam = 2; + else aLastParam = (aLastParam + aFirstParam) / 2.; // to avoid in periodic same first and last + + gp_XYZ aCoordSum = theCurve->Value(aFirstParam).XYZ() + theCurve->Value(aLastParam).XYZ(); + return ::HashCode(aCoordSum.X() + aCoordSum.Y() / 123. + aCoordSum.Z() / 123456., Upper); +} +bool Model_CurvesHasher::IsEqual(const Handle(Geom_Curve)& theC1, const Handle(Geom_Curve)& theC2) +{ + if (theC1->DynamicType() != theC2->DynamicType()) + return false; + double aFirstParam1 = theC1->FirstParameter(); + if (aFirstParam1 < -1.e+100 || aFirstParam1 > 1.e+100) + aFirstParam1 = 0; + double aFirstParam2 = theC2->FirstParameter(); + if (aFirstParam2 < -1.e+100 || aFirstParam2 > 1.e+100) + aFirstParam2 = 0; + if (fabs(aFirstParam1 - aFirstParam2) > 1.e-9) + return false; + + double aLastParam1 = theC1->LastParameter(); + if (aLastParam1 < -1.e+100 || aLastParam1 > 1.e+100) + aLastParam1 = 2.; + else aLastParam1 = (aLastParam1 + aFirstParam1) / 2.; // to avoid in periodic same first and last + double aLastParam2 = theC2->LastParameter(); + if (aLastParam2 < -1.e+100 || aLastParam2 > 1.e+100) + aLastParam2 = 2.; + else aLastParam2 = (aLastParam2 + aFirstParam2) / 2.; // to avoid in periodic same first and last + + if (fabs(aLastParam1 - aLastParam2) > 1.e-9) + return false; + + return theC1->Value(aFirstParam1).IsEqual(theC2->Value(aFirstParam2), Precision::Confusion()) && + theC1->Value(aLastParam1).IsEqual(theC2->Value(aLastParam2), Precision::Confusion()); +} + +int Model_EdgesHasher::HashCode(const TopoDS_Edge& theEdge, const Standard_Integer Upper) +{ + Standard_Real aFirst, aLast; + Handle(Geom_Curve) aCurve = BRep_Tool::Curve(theEdge, aFirst, aLast); + return Model_CurvesHasher::HashCode(aCurve, Upper); +} + +bool Model_EdgesHasher::IsEqual(const TopoDS_Edge& theE1, const TopoDS_Edge& theE2) +{ + GeomEdgePtr aSh1(new GeomAPI_Edge); + aSh1->setImpl(new TopoDS_Shape(theE1)); + GeomEdgePtr aSh2(new GeomAPI_Edge); + aSh2->setImpl(new TopoDS_Shape(theE2)); + return aSh1->isEqual(aSh2); +} + std::shared_ptr Model_SelectionNaming::findAppropriateFace( std::shared_ptr& theConstr, - NCollection_DataMap& theCurves, const bool theIsWire) + NCollection_DataMap& theCurves, const bool theIsWire) { int aBestFound = 0; // best number of found edges (not percentage: issue 1019) int aBestOrient = 0; // for the equal "BestFound" additional parameter is orientation @@ -726,7 +786,7 @@ std::shared_ptr Model_SelectionNaming::findAppropriateFace( std::list::iterator aFW = aFacesWires.begin(); for(; aFW != aFacesWires.end(); aFW++) { TopExp_Explorer anEdgesExp(*aFW, TopAbs_EDGE); - TColStd_MapOfTransient alreadyProcessed; // to avoid counting edges with same curved (841) + TColStd_MapOfTransient alreadyProcessed; // to avoid counting edges with same curves (841) for(; anEdgesExp.More(); anEdgesExp.Next()) { TopoDS_Edge anEdge = TopoDS::Edge(anEdgesExp.Current()); if (!anEdge.IsNull()) { @@ -1048,7 +1108,7 @@ bool Model_SelectionNaming::selectSubShape(const std::string& theType, return false; // curves and orientations of edges - NCollection_DataMap allCurves; + NCollection_DataMap allCurves; const int aSubNum = aComposite->numberOfSubs(); for(int a = 0; a < aSubNum; a++) { int aSubID = aComposite->subFeatureId(a); @@ -1084,7 +1144,7 @@ bool Model_SelectionNaming::selectSubShape(const std::string& theType, return false; // curves and orientations of edges - NCollection_DataMap allCurves; + NCollection_DataMap allCurves; const int aSubNum = aComposite->numberOfSubs(); for(int a = 0; a < aSubNum; a++) { int aSubID = aComposite->subFeatureId(a); diff --git a/src/Model/Model_SelectionNaming.h b/src/Model/Model_SelectionNaming.h index d6ebc7137..3494369df 100644 --- a/src/Model/Model_SelectionNaming.h +++ b/src/Model/Model_SelectionNaming.h @@ -30,11 +30,33 @@ #include #include +// class to compare curves in the same way as in GeomAPI_Edge +class Model_CurvesHasher +{ +public: + DEFINE_STANDARD_ALLOC + /// standard hash code + static int HashCode (const Handle(Geom_Curve)& theCurve, const Standard_Integer Upper); + /// comapre curves by parameters and points on them + static bool IsEqual (const Handle(Geom_Curve)& theC1, const Handle(Geom_Curve)& theC2); +}; + +// class to compare edges in the same way as in GeomAPI_Edge +class Model_EdgesHasher +{ +public: + DEFINE_STANDARD_ALLOC + /// standard hash code + static int HashCode (const TopoDS_Edge& theEdge, const Standard_Integer Upper); + /// comapre curves by parameters and points on them + static bool IsEqual (const TopoDS_Edge& theE1, const TopoDS_Edge& theE2); +}; + + /**\class Model_SelectionNaming * \ingroup DataModel * \brief The set of methods that allow to generate a string-name for the selection attribute. */ - class Model_SelectionNaming { TDF_Label myLab; ///< Selection label of the selection attribute @@ -66,7 +88,8 @@ public: /// \returns faces fron this construction if found static std::shared_ptr findAppropriateFace( std::shared_ptr& theConstr, - NCollection_DataMap& theCurves, const bool theIsWire); + NCollection_DataMap& theCurves, + const bool theIsWire); /// Returns orientation of the edge in the context shape static int edgeOrientation(const TopoDS_Shape& theContext, TopoDS_Edge& theEdge); -- 2.39.2