b311480e |
1 | // Created on: 2001-12-20 |
2 | // Created by: Pavel TELKOV |
973c2be1 |
3 | // Copyright (c) 2001-2014 OPEN CASCADE SAS |
b311480e |
4 | // |
973c2be1 |
5 | // This file is part of Open CASCADE Technology software library. |
b311480e |
6 | // |
d5f74e42 |
7 | // This library is free software; you can redistribute it and/or modify it under |
8 | // the terms of the GNU Lesser General Public License version 2.1 as published |
973c2be1 |
9 | // by the Free Software Foundation, with special exception defined in the file |
10 | // OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT |
11 | // distribution for complete text of the license and disclaimer of any warranty. |
b311480e |
12 | // |
973c2be1 |
13 | // Alternatively, this file may be used under the terms of Open CASCADE |
14 | // commercial license or contractual agreement. |
7fd59977 |
15 | |
16 | // Last modification: |
17 | |
42cf5bc1 |
18 | #include <ElCLib.hxx> |
19 | #include <Geom2d_BezierCurve.hxx> |
20 | #include <Geom2d_BSplineCurve.hxx> |
21 | #include <Geom2d_Curve.hxx> |
22 | #include <Geom2d_Line.hxx> |
7fd59977 |
23 | #include <gp_Dir2d.hxx> |
24 | #include <gp_Lin2d.hxx> |
25 | #include <gp_Pnt2d.hxx> |
42cf5bc1 |
26 | #include <gp_Vec2d.hxx> |
7fd59977 |
27 | #include <Precision.hxx> |
42cf5bc1 |
28 | #include <ShapeCustom_Curve2d.hxx> |
29 | #include <Standard_ErrorHandler.hxx> |
7fd59977 |
30 | |
31 | //======================================================================= |
32 | //function : GetLine |
33 | //purpose : static |
34 | //======================================================================= |
35 | static gp_Lin2d GetLine (const gp_Pnt2d& P1, const gp_Pnt2d& P2, |
36 | const Standard_Real c1, Standard_Real& cf, Standard_Real& cl) |
37 | { |
38 | gp_Vec2d avec (P1,P2); |
39 | gp_Dir2d adir (avec); |
40 | gp_Lin2d alin (P1,adir); |
41 | alin.SetLocation (ElCLib::Value (c1, alin)); |
42 | cf = ElCLib::Parameter (alin, P1); |
43 | cl = ElCLib::Parameter (alin, P2); |
44 | return alin; |
45 | } |
46 | |
47 | |
48 | //======================================================================= |
49 | //function : IsLinear |
50 | //purpose : static |
51 | //======================================================================= |
52 | |
53 | Standard_Boolean ShapeCustom_Curve2d::IsLinear(const TColgp_Array1OfPnt2d& thePoles, |
54 | const Standard_Real tolerance, |
55 | Standard_Real& Deviation) |
56 | { |
57 | Standard_Integer nbPoles = thePoles.Length(); |
58 | if(nbPoles < 2) |
59 | return Standard_False; |
60 | |
61 | Standard_Real dMax = 0; |
62 | Standard_Integer iMax1=0,iMax2=0; |
63 | |
64 | Standard_Integer i; |
65 | for(i = 1; i < nbPoles; i++) |
66 | for(Standard_Integer j = i+1; j <= nbPoles; j++) { |
67 | Standard_Real dist = thePoles(i).SquareDistance(thePoles(j)); |
68 | if(dist > dMax) { |
69 | dMax = dist; |
70 | iMax1 = i; |
71 | iMax2 = j; |
72 | } |
73 | } |
74 | |
75 | Standard_Real dPreci = Precision::PConfusion()*Precision::PConfusion(); |
76 | if(dMax < dPreci) |
77 | return Standard_False; |
78 | |
79 | Standard_Real tol2 = tolerance*tolerance; |
80 | gp_Vec2d avec (thePoles(iMax1),thePoles(iMax2)); |
81 | gp_Dir2d adir (avec); |
82 | gp_Lin2d alin (thePoles(iMax1),adir); |
83 | |
84 | Standard_Real aMax = 0.; |
85 | for(i = 1; i <= nbPoles; i++) { |
86 | Standard_Real dist = alin.SquareDistance(thePoles(i)); |
87 | if(dist > tol2) |
88 | return Standard_False; |
89 | if(dist > aMax) |
90 | aMax = dist; |
91 | } |
92 | Deviation = sqrt(aMax); |
93 | |
94 | return Standard_True; |
95 | } |
96 | |
97 | //======================================================================= |
98 | //function : ConvertToLine2d |
99 | //purpose : static |
100 | //======================================================================= |
101 | |
102 | Handle(Geom2d_Line) ShapeCustom_Curve2d::ConvertToLine2d (const Handle(Geom2d_Curve)& theCurve, |
103 | const Standard_Real c1, |
104 | const Standard_Real c2, |
105 | const Standard_Real theTolerance, |
106 | Standard_Real& cf, |
107 | Standard_Real& cl, |
108 | Standard_Real& theDeviation) |
109 | { |
110 | Handle(Geom2d_Line) aLine2d; |
111 | gp_Pnt2d P1 = theCurve->Value(c1); |
112 | gp_Pnt2d P2 = theCurve->Value(c2); |
113 | Standard_Real dPreci = theTolerance*theTolerance; |
114 | if(P1.SquareDistance(P2) < dPreci) |
115 | return aLine2d; // it is not a line |
116 | |
117 | Handle(Geom2d_BSplineCurve) bsc = Handle(Geom2d_BSplineCurve)::DownCast(theCurve); |
118 | if (!bsc.IsNull()) { |
119 | Standard_Integer nbPoles = bsc->NbPoles(); |
120 | TColgp_Array1OfPnt2d Poles(1,nbPoles); |
121 | bsc->Poles(Poles); |
122 | if(!ShapeCustom_Curve2d::IsLinear(Poles,theTolerance,theDeviation)) |
123 | return aLine2d; // non |
124 | gp_Lin2d alin = GetLine (P1,P2,c1,cf,cl); |
125 | aLine2d = new Geom2d_Line (alin); |
126 | return aLine2d; |
127 | } |
128 | |
129 | Handle(Geom2d_BezierCurve) bzc = Handle(Geom2d_BezierCurve)::DownCast(theCurve); |
130 | if (!bzc.IsNull()) { |
131 | Standard_Integer nbPoles = bzc->NbPoles(); |
132 | TColgp_Array1OfPnt2d Poles(1,nbPoles); |
133 | bzc->Poles(Poles); |
134 | if(!ShapeCustom_Curve2d::IsLinear(Poles,theTolerance,theDeviation)) |
135 | return aLine2d; // non |
136 | gp_Lin2d alin = GetLine (P1,P2,c1,cf,cl); |
137 | aLine2d = new Geom2d_Line (alin); |
138 | return aLine2d; |
139 | } |
140 | |
141 | return aLine2d; |
142 | } |
143 | |
144 | //======================================================================= |
145 | //function : SimplifyBSpline2d |
146 | //purpose : |
147 | //======================================================================= |
148 | |
149 | Standard_Boolean ShapeCustom_Curve2d::SimplifyBSpline2d (Handle(Geom2d_BSplineCurve)& theBSpline2d, |
150 | const Standard_Real theTolerance) |
151 | { |
152 | Standard_Integer aInitNbK; |
153 | Standard_Integer NbK = aInitNbK = theBSpline2d->NbKnots(); |
154 | // search knot to remove |
155 | Standard_Boolean IsToRemove = Standard_True; |
156 | Standard_Integer aKnotIndx = NbK-1; |
157 | while (IsToRemove && NbK > 2) |
158 | { |
159 | Standard_Integer aMult = theBSpline2d->Multiplicity(aKnotIndx); |
160 | Standard_Integer DegMult = theBSpline2d->Degree() - aMult; |
161 | if ((DegMult > 1) && theBSpline2d->IsCN(DegMult)) |
162 | { |
163 | Standard_Real U = theBSpline2d->Knot(aKnotIndx); |
164 | gp_Vec2d aVec1 = theBSpline2d->LocalDN(U, aKnotIndx-1, aKnotIndx, DegMult); |
165 | gp_Vec2d aVec2 = theBSpline2d->LocalDN(U, aKnotIndx, aKnotIndx+1, DegMult); |
166 | // check the derivations are have the "same" angle |
167 | if (aVec1.IsParallel(aVec2, Precision::Angular())) |
168 | { |
169 | // remove knot |
170 | try |
171 | { |
172 | OCC_CATCH_SIGNALS |
173 | theBSpline2d->RemoveKnot(aKnotIndx, |
174 | aMult-1, |
175 | theTolerance); |
176 | } |
177 | catch(Standard_Failure) |
178 | { |
179 | } |
180 | } |
181 | } |
182 | aKnotIndx--; |
183 | |
184 | NbK = theBSpline2d->NbKnots(); |
185 | if (aKnotIndx == 1 || aKnotIndx == NbK) |
186 | IsToRemove = Standard_False; |
187 | } |
188 | return (aInitNbK > NbK); |
189 | } |