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 | //======================================================================= |
25 | static 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 | |
43 | Standard_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 | |
92 | Handle(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 | |
139 | Standard_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 | } |