0023022: This is desirable to access OpenGl extensions and core API (1.2+) in one...
[occt.git] / src / ShapeCustom / ShapeCustom_Curve2d.cxx
CommitLineData
7fd59977 1// File: ShapeCustom_Curve2d.cxx
2// Created: 20.12.01 15:45:21
3// Author: Pavel TELKOV
4// Copyright: Matra Datavision 2001
5
6// Last modification:
7
8#include <ShapeCustom_Curve2d.ixx>
9
10#include <Standard_ErrorHandler.hxx>
11#include <gp_Vec2d.hxx>
12#include <gp_Dir2d.hxx>
13#include <gp_Lin2d.hxx>
14#include <gp_Pnt2d.hxx>
15#include <ElCLib.hxx>
16#include <Precision.hxx>
17#include <Geom2d_BSplineCurve.hxx>
18#include <Geom2d_BezierCurve.hxx>
19
20
21//=======================================================================
22//function : GetLine
23//purpose : static
24//=======================================================================
25static gp_Lin2d GetLine (const gp_Pnt2d& P1, const gp_Pnt2d& P2,
26 const Standard_Real c1, Standard_Real& cf, Standard_Real& cl)
27{
28 gp_Vec2d avec (P1,P2);
29 gp_Dir2d adir (avec);
30 gp_Lin2d alin (P1,adir);
31 alin.SetLocation (ElCLib::Value (c1, alin));
32 cf = ElCLib::Parameter (alin, P1);
33 cl = ElCLib::Parameter (alin, P2);
34 return alin;
35}
36
37
38//=======================================================================
39//function : IsLinear
40//purpose : static
41//=======================================================================
42
43Standard_Boolean ShapeCustom_Curve2d::IsLinear(const TColgp_Array1OfPnt2d& thePoles,
44 const Standard_Real tolerance,
45 Standard_Real& Deviation)
46{
47 Standard_Integer nbPoles = thePoles.Length();
48 if(nbPoles < 2)
49 return Standard_False;
50
51 Standard_Real dMax = 0;
52 Standard_Integer iMax1=0,iMax2=0;
53
54 Standard_Integer i;
55 for(i = 1; i < nbPoles; i++)
56 for(Standard_Integer j = i+1; j <= nbPoles; j++) {
57 Standard_Real dist = thePoles(i).SquareDistance(thePoles(j));
58 if(dist > dMax) {
59 dMax = dist;
60 iMax1 = i;
61 iMax2 = j;
62 }
63 }
64
65 Standard_Real dPreci = Precision::PConfusion()*Precision::PConfusion();
66 if(dMax < dPreci)
67 return Standard_False;
68
69 Standard_Real tol2 = tolerance*tolerance;
70 gp_Vec2d avec (thePoles(iMax1),thePoles(iMax2));
71 gp_Dir2d adir (avec);
72 gp_Lin2d alin (thePoles(iMax1),adir);
73
74 Standard_Real aMax = 0.;
75 for(i = 1; i <= nbPoles; i++) {
76 Standard_Real dist = alin.SquareDistance(thePoles(i));
77 if(dist > tol2)
78 return Standard_False;
79 if(dist > aMax)
80 aMax = dist;
81 }
82 Deviation = sqrt(aMax);
83
84 return Standard_True;
85}
86
87//=======================================================================
88//function : ConvertToLine2d
89//purpose : static
90//=======================================================================
91
92Handle(Geom2d_Line) ShapeCustom_Curve2d::ConvertToLine2d (const Handle(Geom2d_Curve)& theCurve,
93 const Standard_Real c1,
94 const Standard_Real c2,
95 const Standard_Real theTolerance,
96 Standard_Real& cf,
97 Standard_Real& cl,
98 Standard_Real& theDeviation)
99{
100 Handle(Geom2d_Line) aLine2d;
101 gp_Pnt2d P1 = theCurve->Value(c1);
102 gp_Pnt2d P2 = theCurve->Value(c2);
103 Standard_Real dPreci = theTolerance*theTolerance;
104 if(P1.SquareDistance(P2) < dPreci)
105 return aLine2d; // it is not a line
106
107 Handle(Geom2d_BSplineCurve) bsc = Handle(Geom2d_BSplineCurve)::DownCast(theCurve);
108 if (!bsc.IsNull()) {
109 Standard_Integer nbPoles = bsc->NbPoles();
110 TColgp_Array1OfPnt2d Poles(1,nbPoles);
111 bsc->Poles(Poles);
112 if(!ShapeCustom_Curve2d::IsLinear(Poles,theTolerance,theDeviation))
113 return aLine2d; // non
114 gp_Lin2d alin = GetLine (P1,P2,c1,cf,cl);
115 aLine2d = new Geom2d_Line (alin);
116 return aLine2d;
117 }
118
119 Handle(Geom2d_BezierCurve) bzc = Handle(Geom2d_BezierCurve)::DownCast(theCurve);
120 if (!bzc.IsNull()) {
121 Standard_Integer nbPoles = bzc->NbPoles();
122 TColgp_Array1OfPnt2d Poles(1,nbPoles);
123 bzc->Poles(Poles);
124 if(!ShapeCustom_Curve2d::IsLinear(Poles,theTolerance,theDeviation))
125 return aLine2d; // non
126 gp_Lin2d alin = GetLine (P1,P2,c1,cf,cl);
127 aLine2d = new Geom2d_Line (alin);
128 return aLine2d;
129 }
130
131 return aLine2d;
132}
133
134//=======================================================================
135//function : SimplifyBSpline2d
136//purpose :
137//=======================================================================
138
139Standard_Boolean ShapeCustom_Curve2d::SimplifyBSpline2d (Handle(Geom2d_BSplineCurve)& theBSpline2d,
140 const Standard_Real theTolerance)
141{
142 Standard_Integer aInitNbK;
143 Standard_Integer NbK = aInitNbK = theBSpline2d->NbKnots();
144 // search knot to remove
145 Standard_Boolean IsToRemove = Standard_True;
146 Standard_Integer aKnotIndx = NbK-1;
147 while (IsToRemove && NbK > 2)
148 {
149 Standard_Integer aMult = theBSpline2d->Multiplicity(aKnotIndx);
150 Standard_Integer DegMult = theBSpline2d->Degree() - aMult;
151 if ((DegMult > 1) && theBSpline2d->IsCN(DegMult))
152 {
153 Standard_Real U = theBSpline2d->Knot(aKnotIndx);
154 gp_Vec2d aVec1 = theBSpline2d->LocalDN(U, aKnotIndx-1, aKnotIndx, DegMult);
155 gp_Vec2d aVec2 = theBSpline2d->LocalDN(U, aKnotIndx, aKnotIndx+1, DegMult);
156 // check the derivations are have the "same" angle
157 if (aVec1.IsParallel(aVec2, Precision::Angular()))
158 {
159 // remove knot
160 try
161 {
162 OCC_CATCH_SIGNALS
163 theBSpline2d->RemoveKnot(aKnotIndx,
164 aMult-1,
165 theTolerance);
166 }
167 catch(Standard_Failure)
168 {
169 }
170 }
171 }
172 aKnotIndx--;
173
174 NbK = theBSpline2d->NbKnots();
175 if (aKnotIndx == 1 || aKnotIndx == NbK)
176 IsToRemove = Standard_False;
177 }
178 return (aInitNbK > NbK);
179}