diff --git a/src/ShapeConstruct/ShapeConstruct_ProjectCurveOnSurface.cxx b/src/ShapeConstruct/ShapeConstruct_ProjectCurveOnSurface.cxx index e25429ba22..1c6cf283ea 100644 --- a/src/ShapeConstruct/ShapeConstruct_ProjectCurveOnSurface.cxx +++ b/src/ShapeConstruct/ShapeConstruct_ProjectCurveOnSurface.cxx @@ -33,15 +33,22 @@ #include #include +#include + #include #include #include +#include #include #include #include #include #include +#include +#include +#include +#include #include #include #include @@ -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)) ) @@ -252,15 +257,77 @@ Standard_Boolean ShapeConstruct_ProjectCurveOnSurface::Perform (Handle(Geom_Curv // $$$$ end :92 (big BSplineCurve C0) // this number should be "parametric dependent" - TColgp_Array1OfPnt points(1, nbPini); + TColgp_Array1OfPnt points(1, nbPini); TColStd_Array1OfReal params(1, nbPini); - - Standard_Integer iPnt; + NCollection_Sequence 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 ); - - 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(); - } -#ifdef OCCT_DEBUG - else - cout<<"Warning: ProjLib cutting pcurve "<< First << " -> " << ubeg <<" ; "<< Last << " -> " << ufin << endl; -#endif + ProjLib_ProjectedCurve Projector(GAS, GAC); + + 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 "<< nbSol << " curves in ProjLib"<Print(cout); cout << endl; diff --git a/tests/bugs/heal/bug17129 b/tests/bugs/heal/bug17129 new file mode 100644 index 0000000000..f76edc0cab --- /dev/null +++ b/tests/bugs/heal/bug17129 @@ -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 diff --git a/tests/de/step_2/O3 b/tests/de/step_2/O3 index 9e847f0f6c..09b3c529eb 100644 --- a/tests/de/step_2/O3 +++ b/tests/de/step_2/O3 @@ -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 ) diff --git a/tests/de/step_3/F2 b/tests/de/step_3/F2 index 5b2158d3e0..5a1de261d9 100644 --- a/tests/de/step_3/F2 +++ b/tests/de/step_3/F2 @@ -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 diff --git a/tests/de/step_4/B3 b/tests/de/step_4/B3 index 54264f50fc..6385a5e170 100644 --- a/tests/de/step_4/B3 +++ b/tests/de/step_4/B3 @@ -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} diff --git a/tests/de/step_4/D2 b/tests/de/step_4/D2 index ebb1bf03b6..8ecde034ba 100644 --- a/tests/de/step_4/D2 +++ b/tests/de/step_4/D2 @@ -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 )