mirror of
https://git.dev.opencascade.org/repos/occt.git
synced 2025-04-16 10:08:36 +03:00
0017129: ShapeFix projector makes 2d curves with oscillations
Usage of Projlib added in case of uneven points distribution. Test cases are updated to the new behavior. Test cases for issue CR17129 Correction of test case for issue CR17129
This commit is contained in:
parent
43e9197e9a
commit
9a6ea9c479
@ -33,15 +33,22 @@
|
||||
#include <Standard_ErrorHandler.hxx>
|
||||
#include <Standard_Failure.hxx>
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
#include <Precision.hxx>
|
||||
#include <TColStd_Array1OfInteger.hxx>
|
||||
#include <TColgp_Array1OfPnt.hxx>
|
||||
#include <NCollection_Sequence.hxx>
|
||||
|
||||
#include <GeomAPI_PointsToBSpline.hxx>
|
||||
#include <Geom2dAPI_Interpolate.hxx>
|
||||
#include <GeomAPI_Interpolate.hxx>
|
||||
#include <Geom2dAdaptor.hxx>
|
||||
#include <Geom2d_Line.hxx>
|
||||
#include <Geom2d_Circle.hxx>
|
||||
#include <Geom2d_Ellipse.hxx>
|
||||
#include <Geom2d_Hyperbola.hxx>
|
||||
#include <Geom2d_Parabola.hxx>
|
||||
#include <Geom2d_TrimmedCurve.hxx>
|
||||
#include <Geom2d_BSplineCurve.hxx>
|
||||
#include <Geom_BSplineCurve.hxx>
|
||||
@ -191,7 +198,6 @@ static Standard_Integer NbSurfIntervals(const Handle(GeomAdaptor_HSurface)& GAS,
|
||||
//function : Perform
|
||||
//purpose :
|
||||
//=======================================================================
|
||||
|
||||
Standard_Boolean ShapeConstruct_ProjectCurveOnSurface::Perform (Handle(Geom_Curve)& c3d,
|
||||
const Standard_Real First,
|
||||
const Standard_Real Last,
|
||||
@ -208,7 +214,6 @@ Standard_Boolean ShapeConstruct_ProjectCurveOnSurface::Perform (Handle(Geom_Curv
|
||||
myStatus |= ShapeExtend::EncodeStatus (ShapeExtend_FAIL1);
|
||||
return Standard_False;
|
||||
}
|
||||
|
||||
// Projection Analytique
|
||||
Handle(Geom_Curve) crv3dtrim = c3d;
|
||||
if ( ! c3d->IsKind(STANDARD_TYPE(Geom_BoundedCurve)) )
|
||||
@ -254,13 +259,75 @@ Standard_Boolean ShapeConstruct_ProjectCurveOnSurface::Perform (Handle(Geom_Curv
|
||||
// this number should be "parametric dependent"
|
||||
TColgp_Array1OfPnt points(1, nbPini);
|
||||
TColStd_Array1OfReal params(1, nbPini);
|
||||
|
||||
Standard_Integer iPnt;
|
||||
NCollection_Sequence<Standard_Real> aKnotCoeffs;
|
||||
gp_Pnt p3d;
|
||||
Standard_Integer iPnt;
|
||||
|
||||
// In case of bspline compute parametrization speed on each
|
||||
// knot interval inside [aFirstParam, aLastParam].
|
||||
// If quotient = (MaxSpeed / MinSpeed) >= aMaxQuotientCoeff then
|
||||
// use PerformByProjLib algorithm.
|
||||
if(!bspl.IsNull())
|
||||
{
|
||||
Standard_Integer aNbIntPnts = NCONTROL;
|
||||
Standard_Real aFirstParam = First; // First parameter of current interval.
|
||||
Standard_Real aLastParam = Last; // Last parameter of current interval.
|
||||
|
||||
// First index computation.
|
||||
Standard_Integer anIdx = 1;
|
||||
for(; anIdx <= bspl->NbKnots() && aFirstParam < Last; anIdx++)
|
||||
{
|
||||
if(bspl->Knot(anIdx) > First)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
for(; anIdx <= bspl->NbKnots() && aFirstParam < Last; anIdx++)
|
||||
{
|
||||
// Fill current knot interval.
|
||||
aLastParam = Min(Last, bspl->Knot(anIdx));
|
||||
Standard_Real aStep = (aLastParam - aFirstParam) / (aNbIntPnts - 1);
|
||||
Standard_Integer anIntIdx;
|
||||
gp_Pnt p3d1, p3d2;
|
||||
Standard_Real aLength3d = 0.0;
|
||||
for(anIntIdx = 0; anIntIdx < aNbIntPnts - 1; anIntIdx++)
|
||||
{
|
||||
// Start filling from first point.
|
||||
Standard_Real aParam1 = aFirstParam + aStep * anIntIdx;
|
||||
Standard_Real aParam2 = aFirstParam + aStep * (anIntIdx + 1);
|
||||
c3d->D0 (aParam1, p3d1);
|
||||
c3d->D0 (aParam2, p3d2);
|
||||
aLength3d += p3d2.Distance(p3d1);
|
||||
}
|
||||
aKnotCoeffs.Append(aLength3d / (aLastParam - aFirstParam));
|
||||
aFirstParam = aLastParam;
|
||||
}
|
||||
|
||||
Standard_Real anEvenlyCoeff = 0;
|
||||
if (aKnotCoeffs.Size() > 0)
|
||||
{
|
||||
anEvenlyCoeff = *std::max_element(aKnotCoeffs.begin(), aKnotCoeffs.end()) /
|
||||
*std::min_element(aKnotCoeffs.begin(), aKnotCoeffs.end());
|
||||
}
|
||||
|
||||
const Standard_Real aMaxQuotientCoeff = 1500.0;
|
||||
if (anEvenlyCoeff > aMaxQuotientCoeff)
|
||||
{
|
||||
PerformByProjLib(c3d, First, Last, c2d);
|
||||
// PerformByProjLib fail detection:
|
||||
if (!c2d.IsNull())
|
||||
{
|
||||
return Status (ShapeExtend_DONE);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Standard_Real deltaT, t;
|
||||
deltaT = (Last - First) / (nbPini-1);
|
||||
nbrPnt = nbPini;
|
||||
for (iPnt = 1; iPnt <= nbPini; iPnt ++) {
|
||||
for (iPnt = 1; iPnt <= nbPini; iPnt ++)
|
||||
{
|
||||
if (iPnt == 1) t = First;
|
||||
else if (iPnt == nbPini) t = Last;
|
||||
else t = First + (iPnt - 1) * deltaT;
|
||||
@ -270,8 +337,7 @@ Standard_Boolean ShapeConstruct_ProjectCurveOnSurface::Perform (Handle(Geom_Curv
|
||||
params(iPnt) = t;
|
||||
}
|
||||
|
||||
// CALCUL par approximation
|
||||
|
||||
// CALCUL par approximation
|
||||
TColgp_Array1OfPnt2d pnt2d(1, nbrPnt);
|
||||
ApproxPCurve (nbrPnt,points,params,pnt2d,c2d); //szv#4:S4163:12Mar99 OK not needed
|
||||
if (!c2d.IsNull()) {
|
||||
@ -320,9 +386,9 @@ Standard_Boolean ShapeConstruct_ProjectCurveOnSurface::PerformByProjLib(Handle(G
|
||||
const Standard_Real First,
|
||||
const Standard_Real Last,
|
||||
Handle(Geom2d_Curve)& c2d,
|
||||
const GeomAbs_Shape continuity,
|
||||
const Standard_Integer maxdeg,
|
||||
const Standard_Integer nbinterval)
|
||||
const GeomAbs_Shape /*continuity*/,
|
||||
const Standard_Integer /*maxdeg */,
|
||||
const Standard_Integer /*nbinterval */)
|
||||
{
|
||||
//Standard_Boolean OK = Standard_True; //szv#4:S4163:12Mar99 unused
|
||||
c2d.Nullify();
|
||||
@ -331,51 +397,53 @@ Standard_Boolean ShapeConstruct_ProjectCurveOnSurface::PerformByProjLib(Handle(G
|
||||
return Standard_False;
|
||||
}
|
||||
|
||||
try {
|
||||
try
|
||||
{
|
||||
OCC_CATCH_SIGNALS
|
||||
Handle(GeomAdaptor_HSurface) GAS = mySurf->Adaptor3d();
|
||||
Standard_Real URes = GAS->ChangeSurface().UResolution ( myPreci );
|
||||
Standard_Real VRes = GAS->ChangeSurface().VResolution ( myPreci );
|
||||
Handle(GeomAdaptor_HCurve) GAC = new GeomAdaptor_HCurve (c3d,First,Last);
|
||||
ProjLib_CompProjectedCurve Projector ( GAS, GAC, URes, VRes );
|
||||
ProjLib_ProjectedCurve Projector(GAS, GAC);
|
||||
|
||||
Standard_Real ubeg, ufin;
|
||||
Standard_Integer nbSol = Projector.NbCurves();
|
||||
if (nbSol==1) {
|
||||
Projector.Bounds(1, ubeg, ufin);
|
||||
if((ubeg<=First)&&(ufin>=Last)) {
|
||||
Standard_Integer nbintervals = ( nbinterval < 1 ?
|
||||
NbSurfIntervals(GAS, GeomAbs_C3)+GAC->NbIntervals(GeomAbs_C3)+2:
|
||||
nbinterval);
|
||||
Handle(ProjLib_HCompProjectedCurve) HProjector = new ProjLib_HCompProjectedCurve();
|
||||
HProjector->Set(Projector);
|
||||
Handle(Adaptor2d_HCurve2d) HPCur = HProjector;
|
||||
Approx_CurveOnSurface appr(HPCur, GAS, First, Last, myPreci,
|
||||
continuity, maxdeg,
|
||||
nbintervals,
|
||||
Standard_False, Standard_True);
|
||||
if ( appr.IsDone() )
|
||||
c2d = appr.Curve2d();
|
||||
switch (Projector.GetType())
|
||||
{
|
||||
case GeomAbs_Line :
|
||||
c2d = new Geom2d_Line(Projector.Line());
|
||||
break;
|
||||
case GeomAbs_Circle :
|
||||
c2d = new Geom2d_Circle(Projector.Circle());
|
||||
break;
|
||||
case GeomAbs_Ellipse :
|
||||
c2d = new Geom2d_Ellipse(Projector.Ellipse());
|
||||
break;
|
||||
case GeomAbs_Parabola :
|
||||
c2d = new Geom2d_Parabola(Projector.Parabola());
|
||||
break;
|
||||
case GeomAbs_Hyperbola :
|
||||
c2d = new Geom2d_Hyperbola(Projector.Hyperbola());
|
||||
break;
|
||||
case GeomAbs_BSplineCurve :
|
||||
c2d = Projector.BSpline();
|
||||
break;
|
||||
case GeomAbs_BezierCurve :
|
||||
case GeomAbs_OtherCurve :
|
||||
// Not possible, handling added to avoid gcc warning.
|
||||
break;
|
||||
}
|
||||
#ifdef OCCT_DEBUG
|
||||
else
|
||||
cout<<"Warning: ProjLib cutting pcurve "<< First << " -> " << ubeg <<" ; "<< Last << " -> " << ufin << endl;
|
||||
#endif
|
||||
}
|
||||
#ifdef OCCT_DEBUG
|
||||
else cout<<"Warning: ProjLib "<< nbSol << " curves in ProjLib"<<endl;
|
||||
#endif
|
||||
if(c2d.IsNull()) {
|
||||
|
||||
if(c2d.IsNull())
|
||||
{
|
||||
myStatus = ShapeExtend::EncodeStatus (ShapeExtend_FAIL2);
|
||||
return Standard_False;
|
||||
}
|
||||
else {
|
||||
else
|
||||
{
|
||||
myStatus = ShapeExtend::EncodeStatus (ShapeExtend_DONE1);
|
||||
return Standard_True;
|
||||
}
|
||||
|
||||
}
|
||||
catch(Standard_Failure) {
|
||||
catch(Standard_Failure)
|
||||
{
|
||||
#ifdef OCCT_DEBUG
|
||||
cout << "Warning: ShapeConstruct_ProjectCurveOnSurface::PerformByProjLib(): Exception: ";
|
||||
Standard_Failure::Caught()->Print(cout); cout << endl;
|
||||
|
18
tests/bugs/heal/bug17129
Normal file
18
tests/bugs/heal/bug17129
Normal file
@ -0,0 +1,18 @@
|
||||
puts "============"
|
||||
puts "OCC17129"
|
||||
puts "============"
|
||||
puts ""
|
||||
#######################################################################
|
||||
# ShapeFix projector makes 2d curves with oscillations
|
||||
#######################################################################
|
||||
|
||||
restore [locate_data_file bug17129_ff_1285_proj.brep] a
|
||||
fixshape r a
|
||||
|
||||
pcurve r
|
||||
|
||||
#v2d2
|
||||
view 1 -2D- 728 20 400 400
|
||||
|
||||
2dfit
|
||||
set only_screen_axo 1
|
@ -1,5 +1,5 @@
|
||||
# !!!! This file is generated automatically, do not edit manually! See end script
|
||||
puts "TODO CR23096 ALL: TPSTAT : Faulty"
|
||||
puts "TODO CR23096 ALL: NBSHAPES : Faulty"
|
||||
|
||||
|
||||
set filename ie_soapbox-A.stp
|
||||
@ -8,9 +8,9 @@ set ref_data {
|
||||
DATA : Faulties = 0 ( 0 ) Warnings = 0 ( 0 ) Summary = 0 ( 0 )
|
||||
TPSTAT : Faulties = 0 ( 0 ) Warnings = 28 ( 20 ) Summary = 28 ( 20 )
|
||||
CHECKSHAPE : Wires = 0 ( 0 ) Faces = 0 ( 0 ) Shells = 0 ( 0 ) Solids = 0 ( 0 )
|
||||
NBSHAPES : Solid = 2 ( 2 ) Shell = 2 ( 2 ) Face = 112 ( 112 ) Summary = 687 ( 687 )
|
||||
STATSHAPE : Solid = 2 ( 2 ) Shell = 2 ( 2 ) Face = 112 ( 112 ) FreeWire = 0 ( 0 ) FreeEdge = 0 ( 0 ) SharedEdge = 288 ( 288 )
|
||||
TOLERANCE : MaxTol = 0.009966026823 ( 0.009966026821 ) AvgTol = 0.001107205459 ( 0.001088049274 )
|
||||
NBSHAPES : Solid = 2 ( 2 ) Shell = 2 ( 2 ) Face = 112 ( 112 ) Summary = 685 ( 687 )
|
||||
STATSHAPE : Solid = 2 ( 2 ) Shell = 2 ( 2 ) Face = 112 ( 112 ) FreeWire = 0 ( 0 ) FreeEdge = 0 ( 0 ) SharedEdge = 286 ( 288 )
|
||||
TOLERANCE : MaxTol = 0.5384357498 ( 0.5384357497 ) AvgTol = 0.009441130625 ( 0.009436309132 )
|
||||
LABELS : N0Labels = 1 ( 1 ) N1Labels = 0 ( 0 ) N2Labels = 0 ( 0 ) TotalLabels = 1 ( 1 ) NameLabels = 1 ( 1 ) ColorLabels = 0 ( 0 ) LayerLabels = 0 ( 0 )
|
||||
PROPS : Centroid = 0 ( 0 ) Volume = 0 ( 0 ) Area = 0 ( 0 )
|
||||
NCOLORS : NColors = 0 ( 0 )
|
||||
|
@ -1,6 +1,4 @@
|
||||
# !!!! This file is generated automatically, do not edit manually! See end script
|
||||
puts "TODO CR23096 ALL: CHECKSHAPE : Faulty"
|
||||
|
||||
|
||||
set filename PRO10368.stp
|
||||
|
||||
|
@ -1,5 +1,6 @@
|
||||
# !!!! This file is generated automatically, do not edit manually! See end script
|
||||
puts "TODO CR23096 ALL: NBSHAPES : Faulty"
|
||||
puts "TODO CR23096 ALL: TPSTAT : Faulty"
|
||||
|
||||
set LinuxDiff 1
|
||||
set LinuxFaulties {TOLERANCE}
|
||||
|
@ -7,7 +7,7 @@ TPSTAT : Faulties = 0 ( 0 ) Warnings = 10 ( 14 ) Summary = 10 ( 14 )
|
||||
CHECKSHAPE : Wires = 0 ( 0 ) Faces = 0 ( 0 ) Shells = 0 ( 0 ) Solids = 0 ( 0 )
|
||||
NBSHAPES : Solid = 2 ( 2 ) Shell = 2 ( 2 ) Face = 108 ( 108 ) Summary = 673 ( 673 )
|
||||
STATSHAPE : Solid = 2 ( 2 ) Shell = 2 ( 2 ) Face = 108 ( 108 ) FreeWire = 0 ( 0 ) FreeEdge = 0 ( 0 ) SharedEdge = 282 ( 282 )
|
||||
TOLERANCE : MaxTol = 0.01749235594 ( 0.01749235594 ) AvgTol = 0.003723787424 ( 0.003735669579 )
|
||||
TOLERANCE : MaxTol = 0.5384357498 ( 0.5384357497 ) AvgTol = 0.01216240032 ( 0.0121742825 )
|
||||
LABELS : N0Labels = 1 ( 1 ) N1Labels = 0 ( 0 ) N2Labels = 0 ( 0 ) TotalLabels = 1 ( 1 ) NameLabels = 1 ( 1 ) ColorLabels = 0 ( 0 ) LayerLabels = 0 ( 0 )
|
||||
PROPS : Centroid = 0 ( 0 ) Volume = 0 ( 0 ) Area = 0 ( 0 )
|
||||
NCOLORS : NColors = 0 ( 0 )
|
||||
|
Loading…
x
Reference in New Issue
Block a user