From fd90fd9c808d7aa8ba6ab3ecbae80444f582cea4 Mon Sep 17 00:00:00 2001 From: jfa Date: Wed, 25 Oct 2023 11:36:10 +0100 Subject: [PATCH] 0033433: Shape Healing - Implement a new mode to keep initial types of curves. Some changes and fixes. --- src/BRepTest/BRepTest_CurveCommands.cxx | 25 ++++++---- src/ShapeFix/ShapeFix_Wire.cxx | 48 +++++++++---------- src/ShapeFix/ShapeFix_Wire.hxx | 3 ++ src/ShapeFix/ShapeFix_Wire.lxx | 10 ++++ tests/heal/wire_fix_curves/strongwire_circle | 6 +-- tests/heal/wire_fix_curves/strongwire_ellipse | 6 +-- .../wire_fix_curves/strongwire_halfcircle1 | 10 +++- .../wire_fix_curves/strongwire_halfcircle2 | 10 ++-- tests/heal/wire_fix_curves/strongwire_nurb | 6 +-- .../heal/wire_fix_curves/strongwire_triangle | 6 +-- 10 files changed, 78 insertions(+), 52 deletions(-) diff --git a/src/BRepTest/BRepTest_CurveCommands.cxx b/src/BRepTest/BRepTest_CurveCommands.cxx index adf65e09c0..3597d45da7 100644 --- a/src/BRepTest/BRepTest_CurveCommands.cxx +++ b/src/BRepTest/BRepTest_CurveCommands.cxx @@ -283,7 +283,7 @@ static Standard_Integer wire(Draw_Interpretor& di, Standard_Integer n, const cha //======================================================================= // strongwire //======================================================================= -static Standard_Integer strongwire(Draw_Interpretor& theDI, Standard_Integer theArgC, const char** theArgV) +static Standard_Integer strongwire(Draw_Interpretor&, Standard_Integer theArgC, const char** theArgV) { enum StrongWireMode { StrongWireMode_FixTolerance = 1, @@ -358,12 +358,12 @@ static Standard_Integer strongwire(Draw_Interpretor& theDI, Standard_Integer the aFW->Load(aWire); aFW->FixReorder(); - if (aFW->StatusReorder(ShapeExtend_FAIL1)) + if (aFW->StatusReorder(ShapeExtend_FAIL1)) { Message::SendFail() << "Error: Wire construction failed: several loops detected"; return 1; } - else if (aFW->StatusReorder(ShapeExtend_FAIL)) + else if (aFW->StatusReorder(ShapeExtend_FAIL)) { Message::SendFail() << "Wire construction failed"; return 1; @@ -371,7 +371,7 @@ static Standard_Integer strongwire(Draw_Interpretor& theDI, Standard_Integer the bool isClosed = false; Handle(ShapeAnalysis_Wire) aSaw = aFW->Analyzer(); - if (aSaw->CheckGap3d(1)) // between last and first edges + if (aSaw->CheckGap3d(1)) // between last and first edges { Standard_Real aDist = aSaw->MinDistance3d(); if (aDist < aTolerance) @@ -379,8 +379,6 @@ static Standard_Integer strongwire(Draw_Interpretor& theDI, Standard_Integer the } aFW->ClosedWireMode() = isClosed; aFW->FixConnected(aTolerance); - if (aMode == StrongWireMode_KeepCurveType) - aFW->FixCurves(); if (aFW->StatusConnected(ShapeExtend_FAIL)) { @@ -388,16 +386,25 @@ static Standard_Integer strongwire(Draw_Interpretor& theDI, Standard_Integer the return 1; } - if (aFW->StatusConnected(ShapeExtend_DONE3)) + if (aMode == StrongWireMode_KeepCurveType) + { + aFW->FixCurves(); + if (aFW->StatusCurves(ShapeExtend_FAIL)) + { + Message::SendFail() << "Wire construction failed: cannot rebuild curves through new points"; + return 1; + } + } + else if (aFW->StatusConnected(ShapeExtend_DONE3)) { if (aMode != StrongWireMode_Approximation) - aFW->SetPrecision(aTolerance); + aFW->SetPrecision(aTolerance); aFW->FixGapsByRangesMode() = Standard_True; if (aFW->FixGaps3d()) { Handle(ShapeExtend_WireData) sbwd = aFW->WireData(); Handle(ShapeFix_Edge) aFe = new ShapeFix_Edge; - for (Standard_Integer anIdx = 1; anIdx <= sbwd->NbEdges(); anIdx++) + for (Standard_Integer anIdx = 1; anIdx <= sbwd->NbEdges(); anIdx++) { TopoDS_Edge aEdge = TopoDS::Edge(sbwd->Edge(anIdx)); aFe->FixVertexTolerance(aEdge); diff --git a/src/ShapeFix/ShapeFix_Wire.cxx b/src/ShapeFix/ShapeFix_Wire.cxx index 82b6c36522..566456951b 100644 --- a/src/ShapeFix/ShapeFix_Wire.cxx +++ b/src/ShapeFix/ShapeFix_Wire.cxx @@ -83,6 +83,7 @@ #include #include #include +#include #include #include #include @@ -248,6 +249,7 @@ void ShapeFix_Wire::ClearStatuses() myStatusReorder = emptyStatus; myStatusSmall = emptyStatus; myStatusConnected = emptyStatus; + myStatusCurves = emptyStatus; myStatusEdgeCurves = emptyStatus; myStatusDegenerated = emptyStatus; myStatusSelfIntersection = emptyStatus; @@ -534,17 +536,15 @@ Standard_Boolean ShapeFix_Wire::FixConnected (const Standard_Real prec) //======================================================================= Standard_Boolean ShapeFix_Wire::FixCurves() { - myStatusConnected = ShapeExtend::EncodeStatus(ShapeExtend_OK); + myStatusCurves = ShapeExtend::EncodeStatus(ShapeExtend_OK); if (!IsLoaded()) return Standard_False; - Standard_Integer stop = (myClosedMode ? 0 : 1); - for (Standard_Integer anIdx = NbEdges(); anIdx > stop; anIdx--) - { + for (Standard_Integer anIdx = NbEdges(); anIdx > 0; anIdx--) { FixCurves(anIdx); - myStatusConnected |= myLastFixStatus; + myStatusCurves |= myLastFixStatus; } - return StatusConnected(ShapeExtend_DONE); + return StatusCurves(ShapeExtend_DONE); } //======================================================================= @@ -1366,14 +1366,12 @@ Standard_Boolean ShapeFix_Wire::FixCurves(const Standard_Integer theIdx) aCurve3d->D0(aCurBounds[0], aGeomEnds[0]); aCurve3d->D0(aCurBounds[2], aGeomEnds[1]); - // TODO: precise, if IsReversed flag should be considered here Standard_Real aGap0 = Min(anEnds[0].Distance(aGeomEnds[0]), anEnds[0].Distance(aGeomEnds[1])); Standard_Real aGap2 = Min(anEnds[2].Distance(aGeomEnds[0]), anEnds[2].Distance(aGeomEnds[1])); - if (Max (aGap0, aGap2) < aPrec) // nothing to do + if (Max (aGap0, aGap2) < Precision::Confusion()) // nothing to do return true; - if (aCurve3d->IsKind(STANDARD_TYPE(Geom_Circle))) - { + if (aCurve3d->IsKind(STANDARD_TYPE(Geom_Circle))) { Standard_Real anOldR = Handle(Geom_Circle)::DownCast(aCurve3d)->Circ().Radius(); gp_Vec anArcNorm = gp_Vec(anEnds[2], anEnds[0]) / 2; gp_Pnt aCenter(anEnds[0].XYZ() - anArcNorm.XYZ()); @@ -1390,15 +1388,20 @@ Standard_Boolean ShapeFix_Wire::FixCurves(const Standard_Integer theIdx) anSbwd->Set(aNewEdge, theIdx); return true; } - else if (aCurve3d->IsKind(STANDARD_TYPE(Geom_Ellipse))) - { + else if (aCurve3d->IsKind(STANDARD_TYPE(Geom_Ellipse))) { + /// aaajfa: BEGIN - to provide elliptic edge FORWARD orientation + gp_Pnt tmpPnt = anEnds[0]; + anEnds[0] = anEnds[2]; + anEnds[2] = tmpPnt; + /// aaajfa: END - to provide elliptic edge FORWARD orientation + Handle(Geom_Ellipse) anOld = Handle(Geom_Ellipse)::DownCast(aCurve3d); Handle(Geom_Plane) aPln = new Geom_Plane(anEnds[0], gp_Vec(anEnds[2], anEnds[0]).Crossed(gp_Vec(anEnds[1], anEnds[0]))); GeomAPI_ProjectPointOnSurf aProjector(anOld->Elips().Location(), aPln); gp_Pnt anOrigin = aProjector.NearestPoint(); aProjector.Init(anOld->Elips().Location().XYZ() + anOld->Elips().XAxis().Direction().XYZ(), aPln); gp_Ax2 anAx(anOrigin, aPln->Axis().Direction(), aProjector.NearestPoint().XYZ() - anOrigin.XYZ()); - + // compute angle Standard_Real aRec = DBL_MAX; Standard_Real anAngle = 0.; @@ -1406,7 +1409,8 @@ Standard_Boolean ShapeFix_Wire::FixCurves(const Standard_Integer theIdx) for (Standard_Integer anIdxI = -aSplNum; anIdxI < aSplNum; ++anIdxI) { Handle(Geom_Ellipse) anEll = new Geom_Ellipse(anAx, anOld->MajorRadius(), anOld->MinorRadius()); - anEll->Rotate(anAx.Axis(), aPrec*anIdxI / anEll->MajorRadius() / aSplNum); + Standard_Real anAnglei = aPrec*anIdxI / anEll->MajorRadius() / aSplNum; + anEll->Rotate(anAx.Axis(), anAnglei); GeomAPI_ProjectPointOnCurve aProjector1(anEnds[0], anEll); Standard_Real aDist = 0.; for (Standard_Integer anIdxJ = 0; anIdxJ < 2; ++anIdxJ) @@ -1417,7 +1421,7 @@ Standard_Boolean ShapeFix_Wire::FixCurves(const Standard_Integer theIdx) if (aDist < aRec) { aRec = aDist; - anAngle = aPrec*anIdxI / anEll->MajorRadius() / aSplNum; + anAngle = anAnglei; } } gp_Elips aTemp(anAx, anOld->MajorRadius(), anOld->MinorRadius()); @@ -1428,7 +1432,7 @@ Standard_Boolean ShapeFix_Wire::FixCurves(const Standard_Integer theIdx) gp_Vec aY = aTemp.YAxis().Direction(); gp_Pnt2d aP1((anEnds[0].XYZ() - anOrigin.XYZ()).Dot(aX.XYZ()), (anEnds[0].XYZ() - anOrigin.XYZ()).Dot(aY.XYZ())); gp_Pnt2d aP2((anEnds[2].XYZ() - anOrigin.XYZ()).Dot(aX.XYZ()), (anEnds[2].XYZ() - anOrigin.XYZ()).Dot(aY.XYZ())); - + // x = ky + p linear equation // where (x, y) shift point, // k, p constant coefficients @@ -1452,14 +1456,14 @@ Standard_Boolean ShapeFix_Wire::FixCurves(const Standard_Integer theIdx) Standard_Real y2 = (-b + sqrt(b*b - 4 * a*c)) / 2 / a; Standard_Real x1 = k*y1 + p; Standard_Real x2 = k*y2 + p; - + gp_Pnt anOri = anOld->Location(); if (x1*x1 + y1*y1 < x2*x2 + y2*y2) anOri = anOri.XYZ() + aX.XYZ()*x1 + aY.XYZ()*y1; else anOri = anOri.XYZ() + aX.XYZ()*x2 + aY.XYZ()*y2; aTemp.SetLocation(anOri); - + GC_MakeArcOfEllipse anArc(aTemp, anEnds[2], anEnds[0], true); TopoDS_Edge aNewEdge = BRepBuilderAPI_MakeEdge(anArc.Value()).Edge(); anSbwd->Set(aNewEdge, theIdx); @@ -1467,7 +1471,7 @@ Standard_Boolean ShapeFix_Wire::FixCurves(const Standard_Integer theIdx) } else if (aCurve3d->IsKind(STANDARD_TYPE(Geom_Line))) { - TopoDS_Edge aNewEdge = BRepBuilderAPI_MakeEdge(anEnds[2], anEnds[0]).Edge(); + TopoDS_Edge aNewEdge = BRepBuilderAPI_MakeEdge(anEnds[0], anEnds[2]).Edge(); anSbwd->Set(aNewEdge, theIdx); return true; } @@ -1489,12 +1493,6 @@ Standard_Boolean ShapeFix_Wire::FixCurves(const Standard_Integer theIdx) return true; } - // TODO: question: the below code works only for other curve types (not line/arc/circle/ellipse/bspline) - // Is it really needed? - myAnalyzer->CheckConnected(theIdx, aPrec); - if (myAnalyzer->LastCheckStatus(ShapeExtend_FAIL)) - myLastFixStatus |= ShapeExtend::EncodeStatus(ShapeExtend_FAIL1); - return true; } diff --git a/src/ShapeFix/ShapeFix_Wire.hxx b/src/ShapeFix/ShapeFix_Wire.hxx index 660e2a1d94..6e74c9be2c 100644 --- a/src/ShapeFix/ShapeFix_Wire.hxx +++ b/src/ShapeFix/ShapeFix_Wire.hxx @@ -416,6 +416,8 @@ public: Standard_Boolean StatusConnected (const ShapeExtend_Status status) const; + Standard_Boolean StatusCurves (const ShapeExtend_Status status) const; + Standard_Boolean StatusEdgeCurves (const ShapeExtend_Status status) const; Standard_Boolean StatusDegenerated (const ShapeExtend_Status status) const; @@ -501,6 +503,7 @@ protected: Standard_Integer myStatusReorder; Standard_Integer myStatusSmall; Standard_Integer myStatusConnected; + Standard_Integer myStatusCurves; Standard_Integer myStatusEdgeCurves; Standard_Integer myStatusDegenerated; Standard_Integer myStatusClosed; diff --git a/src/ShapeFix/ShapeFix_Wire.lxx b/src/ShapeFix/ShapeFix_Wire.lxx index 2ba6455f1c..ef70ca7f2b 100644 --- a/src/ShapeFix/ShapeFix_Wire.lxx +++ b/src/ShapeFix/ShapeFix_Wire.lxx @@ -447,6 +447,16 @@ inline Standard_Boolean ShapeFix_Wire::StatusConnected(const ShapeExtend_Status return ShapeExtend::DecodeStatus ( myStatusConnected, status ); } +//======================================================================= +//function : StatusCurves +//purpose : +//======================================================================= + +inline Standard_Boolean ShapeFix_Wire::StatusCurves(const ShapeExtend_Status status) const +{ + return ShapeExtend::DecodeStatus ( myStatusCurves, status ); +} + //======================================================================= //function : StatusEdgeCurves //purpose : diff --git a/tests/heal/wire_fix_curves/strongwire_circle b/tests/heal/wire_fix_curves/strongwire_circle index 6e75aca9da..5796a4e895 100644 --- a/tests/heal/wire_fix_curves/strongwire_circle +++ b/tests/heal/wire_fix_curves/strongwire_circle @@ -11,6 +11,6 @@ translate c1 0 0 0.00000005 translate c2 0 0 -0.00000005 mkedge c1 c1 mkedge c2 c2 -strongwire w c1 c2 -checkshape w -whatis w +strongwire result c1 c2 +checkshape result +whatis result diff --git a/tests/heal/wire_fix_curves/strongwire_ellipse b/tests/heal/wire_fix_curves/strongwire_ellipse index 558fe23bbc..6d7a545bc0 100644 --- a/tests/heal/wire_fix_curves/strongwire_ellipse +++ b/tests/heal/wire_fix_curves/strongwire_ellipse @@ -11,6 +11,6 @@ translate e1 0 0 0.00000005 translate e2 0 0 -0.00000005 mkedge e1 e1 mkedge e2 e2 -strongwire w e1 e2 -checkshape w -whatis w +strongwire result e1 e2 +checkshape result +whatis result diff --git a/tests/heal/wire_fix_curves/strongwire_halfcircle1 b/tests/heal/wire_fix_curves/strongwire_halfcircle1 index e0017b3889..a72bd48d37 100644 --- a/tests/heal/wire_fix_curves/strongwire_halfcircle1 +++ b/tests/heal/wire_fix_curves/strongwire_halfcircle1 @@ -11,8 +11,14 @@ vertex vx px vertex vy py edge exy vx vy + gcarc arc cir py pz px + +# Here we have an error during automatic grid execution with test and testgrid: +# Tcl Exception: EMPTY +# But in line-by-line entering or script sourcing mode this line doesn't produce any error + mkedge earc arc -strongwire w exy earc -whatis w \ No newline at end of file +strongwire result exy earc +whatis result diff --git a/tests/heal/wire_fix_curves/strongwire_halfcircle2 b/tests/heal/wire_fix_curves/strongwire_halfcircle2 index b873196424..005fd5fc60 100644 --- a/tests/heal/wire_fix_curves/strongwire_halfcircle2 +++ b/tests/heal/wire_fix_curves/strongwire_halfcircle2 @@ -7,9 +7,11 @@ point p1 0 0 0 point p2 100 0 0 point p4 100 110 0 - gcarc arc cir p1 p2 p4 +# Here we have an error during automatic grid execution with test and testgrid: +# Tcl Exception: EMPTY +# But in line-by-line entering or script sourcing mode this line doesn't produce any error mkedge arc1 arc mkedge arc2 arc @@ -17,7 +19,7 @@ mkedge arc2 arc tmirror arc2 0 0 0 -110 100 0 -copy ttranslate arc2 0 0 0.003 -copy -strongwire w1 arc1 arc2 -t 0.01 -m keepType +strongwire result arc1 arc2 -t 0.01 -m keepType -checkshape w1 -whatis w1 \ No newline at end of file +checkshape result +whatis result diff --git a/tests/heal/wire_fix_curves/strongwire_nurb b/tests/heal/wire_fix_curves/strongwire_nurb index d65cd2d336..b32c5c1bdc 100644 --- a/tests/heal/wire_fix_curves/strongwire_nurb +++ b/tests/heal/wire_fix_curves/strongwire_nurb @@ -9,6 +9,6 @@ translate c1 0 0 0.00000005 translate c2 0 0 -0.00000005 mkedge c1 c1 mkedge c2 c2 -strongwire w c1 c2 -checkshape w -whatis w \ No newline at end of file +strongwire result c1 c2 +checkshape result +whatis result diff --git a/tests/heal/wire_fix_curves/strongwire_triangle b/tests/heal/wire_fix_curves/strongwire_triangle index 433c6edcad..0ad5246ddc 100644 --- a/tests/heal/wire_fix_curves/strongwire_triangle +++ b/tests/heal/wire_fix_curves/strongwire_triangle @@ -11,7 +11,7 @@ edge e1 v1 v2 edge e2 v2 v3 edge e3 v3 v1 -strongwire w1 e1 e2 e3 +strongwire result e1 e2 e3 -checkshape w1 -whatis w1 +checkshape result +whatis result