1
0
mirror of https://git.dev.opencascade.org/repos/occt.git synced 2025-08-09 13:22:24 +03:00

0033433: Shape Healing - Implement a new mode to keep initial types of curves. Some changes and fixes.

This commit is contained in:
jfa
2023-10-25 11:36:10 +01:00
parent 2d1ed9a4a2
commit fd90fd9c80
10 changed files with 78 additions and 52 deletions

View File

@@ -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);

View File

@@ -83,6 +83,7 @@
#include <GeomAPI_ProjectPointOnCurve.hxx>
#include <GeomAPI_ProjectPointOnSurf.hxx>
#include <GeomConvert_CompCurveToBSplineCurve.hxx>
#include <gp_Elips.hxx>
#include <gp_Pln.hxx>
#include <IntRes2d_IntersectionPoint.hxx>
#include <IntRes2d_SequenceOfIntersectionPoint.hxx>
@@ -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;
}

View File

@@ -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;

View File

@@ -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 :

View File

@@ -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

View File

@@ -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

View File

@@ -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
strongwire result exy earc
whatis result

View File

@@ -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
checkshape result
whatis result

View File

@@ -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
strongwire result c1 c2
checkshape result
whatis result

View File

@@ -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