0030345: Mesh, BRepMesh_CurveTessellator - GCPnts_TangentialDeflection throws Standar...
[occt.git] / src / GCPnts / GCPnts_UniformDeflection.pxx
1 // Copyright (c) 1995-1999 Matra Datavision
2 // Copyright (c) 1999-2014 OPEN CASCADE SAS
3 //
4 // This file is part of Open CASCADE Technology software library.
5 //
6 // This library is free software; you can redistribute it and/or modify it under
7 // the terms of the GNU Lesser General Public License version 2.1 as published
8 // by the Free Software Foundation, with special exception defined in the file
9 // OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
10 // distribution for complete text of the license and disclaimer of any warranty.
11 //
12 // Alternatively, this file may be used under the terms of Open CASCADE
13 // commercial license or contractual agreement.
14
15 #include <StdFail_NotDone.hxx>
16 #include <Standard_DomainError.hxx>
17 #include <Standard_OutOfRange.hxx>
18 #include <Standard_ConstructionError.hxx>
19 #include <Standard_NotImplemented.hxx>
20 #include <GCPnts_DeflectionType.hxx>
21 #include <CPnts_UniformDeflection.hxx>
22 #include <TColStd_Array1OfReal.hxx>
23 #include <TColStd_SequenceOfReal.hxx>
24 #include <BSplCLib.hxx>
25 #include <gp_Circ.hxx>
26 #include <gp_Circ2d.hxx>
27 #include <Precision.hxx>
28
29
30 //=======================================================================
31 //function : Controle
32 //purpose  :
33 //=======================================================================
34 static void Controle (const TheCurve& C,
35                       TColStd_SequenceOfReal& Parameters,
36                       TColgp_SequenceOfPnt& Points,
37                       const Standard_Real U2)
38 {
39   Standard_Integer nbp = Points.Length();
40
41   if (nbp > 2)
42   {
43     Standard_Real Ua = Parameters (nbp - 2);
44     Standard_Real Ub = Parameters (nbp - 1);
45     if (U2 - Ub < 0.33 * (U2 - Ua))
46     {
47       Standard_Real Uc = (U2 + Ua) * 0.5;
48       Parameters (nbp - 1) = Uc;
49       Points (nbp - 1) = Value (C, Uc);
50     }
51   }
52 }
53
54
55 //=======================================================================
56 //function : PerformLinear
57 //purpose  :
58 //=======================================================================
59 static Standard_Boolean PerformLinear (const TheCurve& C,
60                                        TColStd_SequenceOfReal& Parameters,
61                                        TColgp_SequenceOfPnt& Points,
62                                        const Standard_Real U1,
63                                        const Standard_Real U2)
64 {
65   gp_Pnt aPoint;
66   Parameters.Append (U1);
67   aPoint = Value (C, U1);
68   Points.Append (aPoint);
69
70   Parameters.Append (U2);
71   aPoint = Value (C, U2);
72   Points.Append (aPoint);
73   return Standard_True;
74 }
75
76
77 //=======================================================================
78 //function : PerformCircular
79 //purpose  :
80 //=======================================================================
81 static Standard_Boolean PerformCircular (const TheCurve& C,
82                                          TColStd_SequenceOfReal& Parameters,
83                                          TColgp_SequenceOfPnt& Points,
84                                          const Standard_Real Deflection,
85                                          const Standard_Real U1,
86                                          const Standard_Real U2)
87 {
88   gp_Pnt aPoint;
89   Standard_Real Angle = Max (1.0e0 - (Deflection / C.Circle().Radius()), 0.0e0);
90   Angle = 2.0e0 * ACos (Angle);
91   Standard_Integer NbPoints = (Standard_Integer )((U2 - U1) / Angle);
92   NbPoints += 2;
93   Angle = (U2 - U1) / (Standard_Real) (NbPoints - 1);
94   Standard_Real U = U1;
95   for (Standard_Integer i = 1; i <= NbPoints; ++i)
96   {
97     Parameters.Append (U);
98     aPoint = Value (C, U);
99     Points.Append (aPoint);
100     U += Angle;
101   }
102   return Standard_True;
103 }
104
105
106 static GCPnts_DeflectionType GetDefType (const TheCurve& C)
107 {
108   if (C.NbIntervals (GeomAbs_C2) > 1)
109     return GCPnts_DefComposite;
110
111   switch (C.GetType())
112   {
113     case GeomAbs_Line:   return GCPnts_Linear;
114     case GeomAbs_Circle: return GCPnts_Circular;
115     case GeomAbs_BSplineCurve:
116     {
117       Handle_TheBSplineCurve aBSpline = C.BSpline();
118       return (aBSpline->NbPoles() == 2) ? GCPnts_Linear : GCPnts_Curved;
119     }
120     case GeomAbs_BezierCurve:
121     {
122       Handle_TheBezierCurve aBezier = C.Bezier();
123       return (aBezier->NbPoles() == 2) ? GCPnts_Linear : GCPnts_Curved;
124     }
125     default: return GCPnts_Curved;
126   }
127 }
128
129
130 //=======================================================================
131 //function : PerformCurve
132 //purpose  :
133 //=======================================================================
134 static Standard_Boolean PerformCurve (TColStd_SequenceOfReal& Parameters,
135                                       TColgp_SequenceOfPnt&   Points,
136                                       const TheCurve& C,
137                                       const Standard_Real Deflection,
138                                       const Standard_Real U1,
139                                       const Standard_Real U2,
140                                       const Standard_Real EPSILON,
141                                       const Standard_Boolean WithControl)
142 {
143   CPnts_UniformDeflection Iterator (C, Deflection, U1, U2, EPSILON, WithControl);
144   for(; Iterator.More(); Iterator.Next())
145   {
146     Parameters.Append (Iterator.Value());
147     Points.Append (Iterator.Point());
148   }
149   return Iterator.IsAllDone();
150 }
151
152
153 //=======================================================================
154 //function : PerformComposite
155 //purpose  :
156 //=======================================================================
157 static Standard_Boolean PerformComposite (TColStd_SequenceOfReal& Parameters,
158                                           TColgp_SequenceOfPnt& Points,
159                                           const TheCurve& C,
160                                           const Standard_Real Deflection,
161                                           const Standard_Real U1,
162                                           const Standard_Real U2,
163                                           const Standard_Real EPSILON,
164                                           const Standard_Boolean WithControl)
165 {
166   Standard_Integer NbIntervals = C.NbIntervals (GeomAbs_C2);
167   Standard_Integer PIndex;
168
169   TColStd_Array1OfReal TI (1, NbIntervals + 1);
170   C.Intervals (TI, GeomAbs_C2);
171   BSplCLib::Hunt (TI, U1, PIndex);
172
173   // iterate by continuous segments
174   Standard_Real Ua = U1;
175   for (Standard_Integer Index = PIndex;;)
176   {
177     Standard_Real Ub = Min (U2, TI (Index + 1));
178     if (!PerformCurve (Parameters, Points, C, Deflection,
179                     Ua, Ub, EPSILON, WithControl))
180     {
181       return Standard_False;
182     }
183     ++Index;
184     if (Index > NbIntervals || U2 < TI (Index))
185       return Standard_True;
186
187     // remove last point to avoid duplication
188     Parameters.Remove (Parameters.Length());
189     Points.Remove (Points.Length());
190
191     Ua = Ub;
192   }
193 }
194
195
196 //=======================================================================
197 //function : GCPnts_UniformDeflection
198 //purpose  :
199 //=======================================================================
200 GCPnts_UniformDeflection::GCPnts_UniformDeflection (const TheCurve& C,
201                                                     const Standard_Real Deflection,
202                                                     const Standard_Real U1,
203                                                     const Standard_Real U2,
204                                                     const Standard_Boolean WithControl)
205 {
206   Initialize (C, Deflection, U1, U2, WithControl);
207 }
208
209
210 //=======================================================================
211 //function : GCPnts_UniformDeflection
212 //purpose  :
213 //=======================================================================
214 GCPnts_UniformDeflection::GCPnts_UniformDeflection (const TheCurve& C,
215                                                     const Standard_Real Deflection,
216                                                     const Standard_Boolean WithControl)
217 {
218   Initialize(C, Deflection, WithControl);
219 }
220
221
222 //=======================================================================
223 //function : Initialize
224 //purpose  :
225 //=======================================================================
226 void   GCPnts_UniformDeflection::Initialize (const TheCurve& C,
227                                              const Standard_Real Deflection,
228                                              const Standard_Boolean WithControl)
229 {
230   Initialize (C, Deflection, C.FirstParameter(), C.LastParameter(), WithControl);
231 }
232
233
234 //=======================================================================
235 //function : Initialize
236 //purpose  :
237 //=======================================================================
238 void GCPnts_UniformDeflection::Initialize (const TheCurve& C,
239                                            const Standard_Real Deflection,
240                                            const Standard_Real theU1,
241                                            const Standard_Real theU2,
242                                            const Standard_Boolean WithControl)
243 {
244   Standard_Real EPSILON = C.Resolution (Precision::Confusion());
245   myDeflection = Deflection;
246   myDone = Standard_False;
247   myParams.Clear();
248   myPoints.Clear();
249   Standard_Real U1 = Min (theU1, theU2);
250   Standard_Real U2 = Max (theU1, theU2);
251   GCPnts_DeflectionType Type = GetDefType (C);
252   switch (Type)
253   {
254     case GCPnts_Linear:
255       myDone = PerformLinear (C, myParams, myPoints, U1, U2);
256       break;
257     case GCPnts_Circular:
258       myDone = PerformCircular (C, myParams, myPoints, Deflection, U1, U2);
259       break;
260     case GCPnts_Curved:
261       myDone = PerformCurve (myParams, myPoints, C, Deflection,
262                              U1, U2, EPSILON, WithControl);
263       break;
264     case GCPnts_DefComposite:
265       myDone = PerformComposite (myParams, myPoints, C, Deflection,
266                                  U1, U2, EPSILON, WithControl);
267       break;
268   }
269
270   // controle des derniers points:
271   Controle (C, myParams, myPoints, U2);
272 }