0024171: Eliminate CLang compiler warning -Wreorder
[occt.git] / src / ShapeCustom / ShapeCustom_Curve2d.cxx
1 // Created on: 2001-12-20
2 // Created by: Pavel TELKOV
3 // Copyright (c) 2001-2012 OPEN CASCADE SAS
4 //
5 // The content of this file is subject to the Open CASCADE Technology Public
6 // License Version 6.5 (the "License"). You may not use the content of this file
7 // except in compliance with the License. Please obtain a copy of the License
8 // at http://www.opencascade.org and read it completely before using this file.
9 //
10 // The Initial Developer of the Original Code is Open CASCADE S.A.S., having its
11 // main offices at: 1, place des Freres Montgolfier, 78280 Guyancourt, France.
12 //
13 // The Original Code and all software distributed under the License is
14 // distributed on an "AS IS" basis, without warranty of any kind, and the
15 // Initial Developer hereby disclaims all such warranties, including without
16 // limitation, any warranties of merchantability, fitness for a particular
17 // purpose or non-infringement. Please see the License for the specific terms
18 // and conditions governing the rights and limitations under the License.
19
20
21 // Last modification:
22
23 #include <ShapeCustom_Curve2d.ixx>
24
25 #include <Standard_ErrorHandler.hxx>
26 #include <gp_Vec2d.hxx>
27 #include <gp_Dir2d.hxx>
28 #include <gp_Lin2d.hxx>
29 #include <gp_Pnt2d.hxx>
30 #include <ElCLib.hxx>
31 #include <Precision.hxx>
32 #include <Geom2d_BSplineCurve.hxx>
33 #include <Geom2d_BezierCurve.hxx>
34
35
36 //=======================================================================
37 //function : GetLine
38 //purpose  : static
39 //=======================================================================
40 static gp_Lin2d GetLine (const gp_Pnt2d& P1, const gp_Pnt2d& P2,
41                          const Standard_Real c1, Standard_Real& cf, Standard_Real& cl)
42 {
43   gp_Vec2d avec (P1,P2);
44   gp_Dir2d adir (avec);
45   gp_Lin2d alin (P1,adir);
46   alin.SetLocation (ElCLib::Value (c1, alin));
47   cf = ElCLib::Parameter (alin, P1);
48   cl = ElCLib::Parameter (alin, P2);
49   return alin;
50 }
51
52
53 //=======================================================================
54 //function : IsLinear
55 //purpose  : static
56 //=======================================================================
57
58 Standard_Boolean ShapeCustom_Curve2d::IsLinear(const TColgp_Array1OfPnt2d& thePoles,
59                                                const Standard_Real tolerance,
60                                                Standard_Real& Deviation)
61 {
62   Standard_Integer nbPoles = thePoles.Length();
63   if(nbPoles < 2)
64     return Standard_False;
65   
66   Standard_Real dMax = 0;
67   Standard_Integer iMax1=0,iMax2=0;
68   
69   Standard_Integer i;
70   for(i = 1; i < nbPoles; i++)
71     for(Standard_Integer j = i+1; j <= nbPoles; j++) {
72       Standard_Real dist = thePoles(i).SquareDistance(thePoles(j));
73       if(dist > dMax) {
74         dMax = dist;
75         iMax1 = i;
76         iMax2 = j;
77       }
78     }
79   
80   Standard_Real dPreci = Precision::PConfusion()*Precision::PConfusion();
81   if(dMax < dPreci)
82     return Standard_False;
83   
84   Standard_Real tol2 = tolerance*tolerance;
85   gp_Vec2d avec (thePoles(iMax1),thePoles(iMax2));
86   gp_Dir2d adir (avec);
87   gp_Lin2d alin (thePoles(iMax1),adir);
88   
89   Standard_Real aMax = 0.;
90   for(i = 1; i <= nbPoles; i++) {
91     Standard_Real dist = alin.SquareDistance(thePoles(i));
92     if(dist > tol2)
93       return Standard_False;
94     if(dist > aMax)
95       aMax = dist;
96   }
97   Deviation = sqrt(aMax);
98   
99   return Standard_True;
100 }
101
102 //=======================================================================
103 //function : ConvertToLine2d
104 //purpose  : static
105 //=======================================================================
106
107 Handle(Geom2d_Line) ShapeCustom_Curve2d::ConvertToLine2d (const Handle(Geom2d_Curve)& theCurve,
108                                                           const Standard_Real c1,
109                                                           const Standard_Real c2,
110                                                           const Standard_Real theTolerance,
111                                                           Standard_Real& cf,
112                                                           Standard_Real& cl,
113                                                           Standard_Real& theDeviation)
114 {
115   Handle(Geom2d_Line) aLine2d;
116   gp_Pnt2d P1 = theCurve->Value(c1);
117   gp_Pnt2d P2 = theCurve->Value(c2);
118   Standard_Real dPreci = theTolerance*theTolerance;
119   if(P1.SquareDistance(P2) < dPreci)
120     return aLine2d; // it is not a line
121   
122   Handle(Geom2d_BSplineCurve) bsc = Handle(Geom2d_BSplineCurve)::DownCast(theCurve);
123   if (!bsc.IsNull()) {
124     Standard_Integer nbPoles = bsc->NbPoles();
125     TColgp_Array1OfPnt2d Poles(1,nbPoles);
126     bsc->Poles(Poles);
127     if(!ShapeCustom_Curve2d::IsLinear(Poles,theTolerance,theDeviation))
128       return aLine2d;  // non
129     gp_Lin2d alin = GetLine (P1,P2,c1,cf,cl);
130     aLine2d = new Geom2d_Line (alin);
131     return aLine2d;
132   }
133   
134   Handle(Geom2d_BezierCurve) bzc = Handle(Geom2d_BezierCurve)::DownCast(theCurve);
135   if (!bzc.IsNull()) {
136     Standard_Integer nbPoles = bzc->NbPoles();
137     TColgp_Array1OfPnt2d Poles(1,nbPoles);
138     bzc->Poles(Poles);
139     if(!ShapeCustom_Curve2d::IsLinear(Poles,theTolerance,theDeviation))
140       return aLine2d;  // non
141     gp_Lin2d alin = GetLine (P1,P2,c1,cf,cl);
142     aLine2d = new Geom2d_Line (alin);
143     return aLine2d;
144   }
145   
146   return aLine2d;
147 }
148
149 //=======================================================================
150 //function : SimplifyBSpline2d
151 //purpose  : 
152 //=======================================================================
153
154 Standard_Boolean ShapeCustom_Curve2d::SimplifyBSpline2d (Handle(Geom2d_BSplineCurve)& theBSpline2d,
155                                                          const Standard_Real theTolerance)
156 {
157   Standard_Integer aInitNbK;
158   Standard_Integer NbK = aInitNbK = theBSpline2d->NbKnots();
159   // search knot to remove
160   Standard_Boolean IsToRemove = Standard_True;
161   Standard_Integer aKnotIndx = NbK-1;
162   while (IsToRemove && NbK > 2)
163   {
164     Standard_Integer aMult = theBSpline2d->Multiplicity(aKnotIndx);
165     Standard_Integer DegMult = theBSpline2d->Degree() - aMult;
166     if ((DegMult > 1) && theBSpline2d->IsCN(DegMult))
167     {
168       Standard_Real U = theBSpline2d->Knot(aKnotIndx);
169       gp_Vec2d aVec1 = theBSpline2d->LocalDN(U, aKnotIndx-1, aKnotIndx, DegMult);
170       gp_Vec2d aVec2 = theBSpline2d->LocalDN(U, aKnotIndx, aKnotIndx+1, DegMult);
171       // check the derivations are have the "same" angle
172       if (aVec1.IsParallel(aVec2, Precision::Angular()))
173       {
174         // remove knot
175         try
176         {
177           OCC_CATCH_SIGNALS
178           theBSpline2d->RemoveKnot(aKnotIndx,
179                                  aMult-1,
180                                  theTolerance);
181         }
182         catch(Standard_Failure)
183         {
184         }
185       }
186     }
187     aKnotIndx--;
188     
189     NbK = theBSpline2d->NbKnots();
190     if (aKnotIndx == 1 || aKnotIndx == NbK)
191       IsToRemove = Standard_False;
192   }
193   return (aInitNbK > NbK);
194 }