From baa76d28eb5e3997ab0296bfcecbf40a910b2345 Mon Sep 17 00:00:00 2001 From: ifv Date: Thu, 16 Mar 2017 11:02:12 +0300 Subject: [PATCH] 0028346: Function ProjectOnSegments of ShapeAnalysis_Curve returns only single solution leading to projection result far from optimal --- src/Extrema/Extrema_Curve2dTool.cxx | 74 +++++++++++++++++++++++++++++ src/Extrema/Extrema_Curve2dTool.hxx | 8 +++- src/Extrema/Extrema_CurveTool.cxx | 56 +++++++++++++++++++++- src/Extrema/Extrema_CurveTool.hxx | 10 +++- src/Extrema/Extrema_GExtPC.gxx | 45 +++++++++++++----- src/Extrema/FILES | 1 + src/GeomFill/GeomFill_SnglrFunc.cxx | 37 +++++++++------ src/SWDRAW/SWDRAW_ShapeAnalysis.cxx | 51 +++++++++++++++++++- 8 files changed, 251 insertions(+), 31 deletions(-) create mode 100644 src/Extrema/Extrema_Curve2dTool.cxx diff --git a/src/Extrema/Extrema_Curve2dTool.cxx b/src/Extrema/Extrema_Curve2dTool.cxx new file mode 100644 index 0000000000..aae64823bd --- /dev/null +++ b/src/Extrema/Extrema_Curve2dTool.cxx @@ -0,0 +1,74 @@ +// Created on: 1995-07-18 +// Created by: Modelistation +// Copyright (c) 1995-1999 Matra Datavision +// Copyright (c) 1999-2014 OPEN CASCADE SAS +// +// This file is part of Open CASCADE Technology software library. +// +// This library is free software; you can redistribute it and/or modify it under +// the terms of the GNU Lesser General Public License version 2.1 as published +// by the Free Software Foundation, with special exception defined in the file +// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT +// distribution for complete text of the license and disclaimer of any warranty. +// +// Alternatively, this file may be used under the terms of Open CASCADE +// commercial license or contractual agreement. + +#include +#include +#include +#include +#include + +//======================================================================= +//function : DeflCurvIntervals +//purpose : +//======================================================================= +Handle(TColStd_HArray1OfReal) + Extrema_Curve2dTool::DeflCurvIntervals(const Adaptor2d_Curve2d& C) +{ + const Standard_Real epsd = 1.e-3; + const Standard_Real maxdefl = 1.e3; + const Standard_Real mindefl = 1.e-3; + Handle(TColStd_HArray1OfReal) Intervals; + Standard_Integer nbpnts = 23, i; + Standard_Real L = 0.; + Standard_Real tf = C.FirstParameter(), tl = C.LastParameter(); + gp_Pnt2d aP = C.Value(tf); + for (i = 2; i <= nbpnts; ++i) + { + Standard_Real t = (tf * (nbpnts - i) + (i - 1) * tl) / (nbpnts - 1); + gp_Pnt2d aP1 = C.Value(t); + L += aP.Distance(aP1); + } + // + Standard_Real dLdt = L / (tl - tf); + if (L <= Precision::Confusion() || dLdt < epsd || (tl - tf) > 10000.) + { + nbpnts = 2; + Intervals = new TColStd_HArray1OfReal(1, nbpnts); + Intervals->SetValue(1, tf); + Intervals->SetValue(nbpnts, tl); + return Intervals; + } + // + Standard_Real aDefl = Max(0.01 * L / (2. * M_PI), mindefl); + if (aDefl > maxdefl) + { + nbpnts = 2; + Intervals = new TColStd_HArray1OfReal(1, nbpnts); + Intervals->SetValue(1, tf); + Intervals->SetValue(nbpnts, tl); + return Intervals; + } + Standard_Real aMinLen = Max(.00001*L, Precision::Confusion()); + Standard_Real aTol = Max(0.00001*(tl - tf), Precision::PConfusion()); + GCPnts_TangentialDeflection aPntGen(C, M_PI / 6, aDefl, 2, aTol, aMinLen); + nbpnts = aPntGen.NbPoints(); + Intervals = new TColStd_HArray1OfReal(1, nbpnts); + for (i = 1; i <= nbpnts; ++i) + { + Intervals->SetValue(i, aPntGen.Parameter(i)); + } + return Intervals; +} diff --git a/src/Extrema/Extrema_Curve2dTool.hxx b/src/Extrema/Extrema_Curve2dTool.hxx index 8e89a95a74..b4497dcc24 100644 --- a/src/Extrema/Extrema_Curve2dTool.hxx +++ b/src/Extrema/Extrema_Curve2dTool.hxx @@ -25,6 +25,7 @@ #include #include #include +#include #include #include #include @@ -63,7 +64,12 @@ public: //! Stores in the parameters bounding the intervals //! of continuity . static void Intervals (const Adaptor2d_Curve2d& C, TColStd_Array1OfReal& T, const GeomAbs_Shape S); - + + //! Returns the parameters bounding the intervals of subdivision of curve + //! according to Curvature deflection. Value of deflection is defined in method. + //! + Standard_EXPORT static Handle(TColStd_HArray1OfReal) DeflCurvIntervals(const Adaptor2d_Curve2d& C); + static Standard_Boolean IsClosed (const Adaptor2d_Curve2d& C); static Standard_Boolean IsPeriodic (const Adaptor2d_Curve2d& C); diff --git a/src/Extrema/Extrema_CurveTool.cxx b/src/Extrema/Extrema_CurveTool.cxx index 2e43311759..995e311ce0 100644 --- a/src/Extrema/Extrema_CurveTool.cxx +++ b/src/Extrema/Extrema_CurveTool.cxx @@ -21,6 +21,7 @@ #include #include #include +#include //======================================================================= //function : IsPeriodic @@ -36,4 +37,57 @@ Standard_Boolean Extrema_CurveTool::IsPeriodic(const Adaptor3d_Curve& C) return C.IsPeriodic(); } - +//======================================================================= +//function : DeflCurvIntervals +//purpose : +//======================================================================= +Handle(TColStd_HArray1OfReal) +Extrema_CurveTool::DeflCurvIntervals(const Adaptor3d_Curve& C) +{ + const Standard_Real epsd = 1.e-3; + const Standard_Real maxdefl = 1.e3; + const Standard_Real mindefl = 1.e-3; + Handle(TColStd_HArray1OfReal) Intervals; + Standard_Integer nbpnts = 23, i; + Standard_Real L = 0.; + Standard_Real tf = C.FirstParameter(), tl = C.LastParameter(); + gp_Pnt aP = C.Value(tf); + for (i = 2; i <= nbpnts; ++i) + { + Standard_Real t = (tf * (nbpnts - i) + (i - 1) * tl) / (nbpnts - 1); + gp_Pnt aP1 = C.Value(t); + L += aP.Distance(aP1); + } + // + Standard_Real dLdt = L / (tl - tf); + if (L <= Precision::Confusion() || dLdt < epsd || (tl - tf) > 10000.) // To avoid problemwith GCPnts + { + nbpnts = 2; + Intervals = new TColStd_HArray1OfReal(1, nbpnts); + Intervals->SetValue(1, tf); + Intervals->SetValue(nbpnts, tl); + return Intervals; + } + // + Standard_Real aDefl = Max(0.01 * L / (2. * M_PI), mindefl); + if (aDefl > maxdefl) + { + nbpnts = 2; + Intervals = new TColStd_HArray1OfReal(1, nbpnts); + Intervals->SetValue(1, tf); + Intervals->SetValue(nbpnts, tl); + return Intervals; + } + // + Standard_Real aMinLen = Max(.00001*L, Precision::Confusion()); + Standard_Real aTol = Max(0.00001*(tl - tf), Precision::PConfusion()); + // + GCPnts_TangentialDeflection aPntGen(C, M_PI / 6, aDefl, 2, aTol, aMinLen); + nbpnts = aPntGen.NbPoints(); + Intervals = new TColStd_HArray1OfReal(1, nbpnts); + for (i = 1; i <= nbpnts; ++i) + { + Intervals->SetValue(i, aPntGen.Parameter(i)); + } + return Intervals; +} diff --git a/src/Extrema/Extrema_CurveTool.hxx b/src/Extrema/Extrema_CurveTool.hxx index 8dd3077c8f..163b1550e9 100644 --- a/src/Extrema/Extrema_CurveTool.hxx +++ b/src/Extrema/Extrema_CurveTool.hxx @@ -25,6 +25,7 @@ #include #include #include +#include #include #include #include @@ -65,8 +66,13 @@ public: //! The array must provide enough room to accomodate //! for the parameters. i.e. T.Length() > NbIntervals() static void Intervals (Adaptor3d_Curve& C, TColStd_Array1OfReal& T, const GeomAbs_Shape S); - - Standard_EXPORT static Standard_Boolean IsPeriodic (const Adaptor3d_Curve& C); + + //! Returns the parameters bounding the intervals of subdivision of curve + //! according to Curvature deflection. Value of deflection is defined in method. + //! + Standard_EXPORT static Handle(TColStd_HArray1OfReal) DeflCurvIntervals(const Adaptor3d_Curve& C); + + Standard_EXPORT static Standard_Boolean IsPeriodic (const Adaptor3d_Curve& C); static Standard_Real Period (const Adaptor3d_Curve& C); diff --git a/src/Extrema/Extrema_GExtPC.gxx b/src/Extrema/Extrema_GExtPC.gxx index 2ed746dac7..d69b0464b2 100644 --- a/src/Extrema/Extrema_GExtPC.gxx +++ b/src/Extrema/Extrema_GExtPC.gxx @@ -28,6 +28,7 @@ #include #include #include +#include #include @@ -260,13 +261,32 @@ void Extrema_GExtPC::Perform(const ThePoint& P) } default: { + const Standard_Integer aMaxSample = 17; Standard_Boolean IntExtIsDone = Standard_False; Standard_Boolean IntIsNotValid; + Handle(TColStd_HArray1OfReal) theHInter; n = TheCurveTool::NbIntervals(aCurve, GeomAbs_C2); - TColStd_Array1OfReal theInter(1, n+1); + if (n > 1) + { + theHInter = new TColStd_HArray1OfReal(1, n + 1); + TheCurveTool::Intervals(aCurve, theHInter->ChangeArray1(), GeomAbs_C2); + } + else + { + theHInter = TheCurveTool::DeflCurvIntervals(aCurve); + n = theHInter->Length() - 1; + } + mysample = Max(mysample / n, aMaxSample); + Standard_Real maxint = 0.; + for (i = 1; i <= n; ++i) + { + Standard_Real dt = theHInter->Value(i + 1) - theHInter->Value(i); + if (maxint < dt) + { + maxint = dt; + } + } Standard_Boolean isPeriodic = TheCurveTool::IsPeriodic(aCurve); - TheCurveTool::Intervals(aCurve, theInter, GeomAbs_C2); - mysample = Max(mysample/n, 17); TheVector V1; ThePoint PP; Standard_Real s1 = 0.0 ; @@ -274,8 +294,9 @@ void Extrema_GExtPC::Perform(const ThePoint& P) myExtPC.Initialize(aCurve); for (i = 1; i <= n; i++) { - myintuinf = theInter(i); - myintusup = theInter(i+1); + myintuinf = theHInter->Value(i); + myintusup = theHInter->Value(i+1); + mysample = Max(RealToInt(aMaxSample*(myintusup - myintuinf) / maxint), 3); Standard_Real anInfToCheck = myintuinf; Standard_Real aSupToCheck = myintusup; @@ -509,8 +530,8 @@ Standard_Boolean Extrema_GExtPC::IsDone() const Standard_Real Extrema_GExtPC::SquareDistance(const Standard_Integer N) const { - if(!mydone) StdFail_NotDone::Raise(); - if ((N < 1) || (N > mySqDist.Length())) Standard_OutOfRange::Raise(); + if(!mydone) throw StdFail_NotDone(); + if ((N < 1) || (N > mySqDist.Length())) throw Standard_OutOfRange(); return mySqDist.Value(N); } @@ -522,7 +543,7 @@ Standard_Real Extrema_GExtPC::SquareDistance(const Standard_Integer N) const Standard_Integer Extrema_GExtPC::NbExt() const { - if(!mydone) StdFail_NotDone::Raise(); + if(!mydone) throw StdFail_NotDone(); return mySqDist.Length(); } @@ -534,8 +555,8 @@ Standard_Integer Extrema_GExtPC::NbExt() const Standard_Boolean Extrema_GExtPC::IsMin(const Standard_Integer N) const { - if(!mydone) StdFail_NotDone::Raise(); - if ((N < 1) || (N > mySqDist.Length())) Standard_OutOfRange::Raise(); + if(!mydone) throw StdFail_NotDone(); + if ((N < 1) || (N > mySqDist.Length())) throw Standard_OutOfRange(); return myismin.Value(N); } @@ -548,8 +569,8 @@ Standard_Boolean Extrema_GExtPC::IsMin(const Standard_Integer N) const const ThePOnC & Extrema_GExtPC::Point(const Standard_Integer N) const { - if(!mydone) StdFail_NotDone::Raise(); - if ((N < 1) || (N > mySqDist.Length())) Standard_OutOfRange::Raise(); + if(!mydone) throw StdFail_NotDone(); + if ((N < 1) || (N > mySqDist.Length())) throw Standard_OutOfRange(); return mypoint.Value(N); } diff --git a/src/Extrema/FILES b/src/Extrema/FILES index 1156af9202..34ec6a72e0 100644 --- a/src/Extrema/FILES +++ b/src/Extrema/FILES @@ -9,6 +9,7 @@ Extrema_CCLocFOfLocECC.hxx Extrema_CCLocFOfLocECC2d.hxx Extrema_CCLocFOfLocECC2d_0.cxx Extrema_CCLocFOfLocECC_0.cxx +Extrema_Curve2dTool.cxx Extrema_Curve2dTool.hxx Extrema_Curve2dTool.lxx Extrema_CurveLocator.gxx diff --git a/src/GeomFill/GeomFill_SnglrFunc.cxx b/src/GeomFill/GeomFill_SnglrFunc.cxx index bfaeb2f282..07ecd327cf 100644 --- a/src/GeomFill/GeomFill_SnglrFunc.cxx +++ b/src/GeomFill/GeomFill_SnglrFunc.cxx @@ -47,11 +47,17 @@ void GeomFill_SnglrFunc::SetRatio(const Standard_Real Ratio) Standard_Integer GeomFill_SnglrFunc::NbIntervals(const GeomAbs_Shape S) const { GeomAbs_Shape HCS=GeomAbs_C0; - switch(S) { - case GeomAbs_C0: HCS = GeomAbs_C2; break; - case GeomAbs_C1: HCS = GeomAbs_C3; break; - case GeomAbs_C2: HCS = GeomAbs_CN; break; - default: Standard_DomainError::Raise(); + if (S == GeomAbs_C0) + { + HCS = GeomAbs_C2; + } + else if (S == GeomAbs_C1) + { + HCS = GeomAbs_C3; + } + else if (S >= GeomAbs_C2) + { + HCS = GeomAbs_CN; } return myHCurve->NbIntervals(HCS); } @@ -59,11 +65,17 @@ void GeomFill_SnglrFunc::SetRatio(const Standard_Real Ratio) void GeomFill_SnglrFunc::Intervals(TColStd_Array1OfReal& T,const GeomAbs_Shape S) const { GeomAbs_Shape HCS=GeomAbs_C0; - switch(S) { - case GeomAbs_C0: HCS = GeomAbs_C2; break; - case GeomAbs_C1: HCS = GeomAbs_C3; break; - case GeomAbs_C2: HCS = GeomAbs_CN; break; - default: Standard_DomainError::Raise(); + if (S == GeomAbs_C0) + { + HCS = GeomAbs_C2; + } + else if (S == GeomAbs_C1) + { + HCS = GeomAbs_C3; + } + else if (S >= GeomAbs_C2) + { + HCS = GeomAbs_CN; } myHCurve->Intervals(T, HCS); } @@ -153,12 +165,9 @@ gp_Vec GeomFill_SnglrFunc::DN(const Standard_Real U,const Standard_Integer N) co D3(U,C,D1C,D2C,D3C); return D3C; default: - Standard_NotImplemented::Raise("Exception: Derivative order is greater than 3. " + throw Standard_NotImplemented("Exception: Derivative order is greater than 3. " "Cannot compute of derivative."); } - - return gp_Vec(); - } Standard_Real GeomFill_SnglrFunc::Resolution(const Standard_Real R3D) const diff --git a/src/SWDRAW/SWDRAW_ShapeAnalysis.cxx b/src/SWDRAW/SWDRAW_ShapeAnalysis.cxx index 7128290491..7c449e34f9 100644 --- a/src/SWDRAW/SWDRAW_ShapeAnalysis.cxx +++ b/src/SWDRAW/SWDRAW_ShapeAnalysis.cxx @@ -60,6 +60,9 @@ #include #include #include +#include +#include +#include #include static Standard_Integer tolerance @@ -227,6 +230,50 @@ static Standard_Integer projcurve di<<"Result : "<