0027108: GCPnt_TangentialDeflection does not respect linear deflection
[occt.git] / src / GCPnts / GCPnts_UniformDeflection.gxx
CommitLineData
b311480e 1// Copyright (c) 1995-1999 Matra Datavision
973c2be1 2// Copyright (c) 1999-2014 OPEN CASCADE SAS
b311480e 3//
973c2be1 4// This file is part of Open CASCADE Technology software library.
b311480e 5//
d5f74e42 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
973c2be1 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.
b311480e 11//
973c2be1 12// Alternatively, this file may be used under the terms of Open CASCADE
13// commercial license or contractual agreement.
b311480e 14
7fd59977 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//=======================================================================
34static 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//=======================================================================
59static 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//=======================================================================
81static 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
37782ec2 106static GCPnts_DeflectionType GetDefType (const TheCurve& C)
7fd59977 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//=======================================================================
134static 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//=======================================================================
157static Standard_Boolean PerformComposite (TColStd_SequenceOfReal& Parameters,
158 TColgp_SequenceOfPnt& Points,
37782ec2 159 const TheCurve& C,
7fd59977 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());
9c1519c4 189 Points.Remove (Points.Length());
7fd59977 190
191 Ua = Ub;
192 }
7fd59977 193}
194
195
196//=======================================================================
197//function : GCPnts_UniformDeflection
198//purpose :
199//=======================================================================
37782ec2 200GCPnts_UniformDeflection::GCPnts_UniformDeflection (const TheCurve& C,
7fd59977 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//=======================================================================
37782ec2 214GCPnts_UniformDeflection::GCPnts_UniformDeflection (const TheCurve& C,
7fd59977 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//=======================================================================
37782ec2 226void GCPnts_UniformDeflection::Initialize (const TheCurve& C,
7fd59977 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//=======================================================================
37782ec2 238void GCPnts_UniformDeflection::Initialize (const TheCurve& C,
7fd59977 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}