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 <GCPnts_UniformDeflection.hxx>
16 
17 #include <CPnts_UniformDeflection.hxx>
18 #include <GCPnts_DeflectionType.hxx>
19 #include <GCPnts_TCurveTypes.hxx>
20 #include <gp_Pnt.hxx>
21 #include <gp_Pnt2d.hxx>
22 #include <Standard_ConstructionError.hxx>
23 #include <Standard_DomainError.hxx>
24 #include <Standard_NotImplemented.hxx>
25 #include <Standard_OutOfRange.hxx>
26 #include <StdFail_NotDone.hxx>
27 
28 // mask the return of a Adaptor2d_Curve2d as a gp_Pnt
Value(const Adaptor3d_Curve & theC,const Standard_Real theParameter)29 static gp_Pnt Value (const Adaptor3d_Curve& theC,
30                      const Standard_Real theParameter)
31 {
32   return theC.Value (theParameter);
33 }
34 
Value(const Adaptor2d_Curve2d & theC,const Standard_Real theParameter)35 static gp_Pnt Value (const Adaptor2d_Curve2d& theC,
36                      const Standard_Real theParameter)
37 {
38   const gp_Pnt2d a2dPoint = theC.Value (theParameter);
39   return gp_Pnt (a2dPoint.X(), a2dPoint.Y(), 0.0);
40 }
41 
42 //=======================================================================
43 //function : GCPnts_UniformDeflection
44 //purpose  :
45 //=======================================================================
GCPnts_UniformDeflection()46 GCPnts_UniformDeflection::GCPnts_UniformDeflection()
47 : myDone (Standard_False),
48   myDeflection (0.0)
49 {
50   //
51 }
52 
53 //=======================================================================
54 //function : GCPnts_UniformDeflection
55 //purpose  :
56 //=======================================================================
GCPnts_UniformDeflection(const Adaptor3d_Curve & theC,const Standard_Real theDeflection,const Standard_Real theU1,const Standard_Real theU2,const Standard_Boolean theWithControl)57 GCPnts_UniformDeflection::GCPnts_UniformDeflection (const Adaptor3d_Curve& theC,
58                                                     const Standard_Real theDeflection,
59                                                     const Standard_Real theU1,
60                                                     const Standard_Real theU2,
61                                                     const Standard_Boolean theWithControl)
62 : myDone (Standard_False),
63   myDeflection (theDeflection)
64 {
65   Initialize (theC, theDeflection, theU1, theU2, theWithControl);
66 }
67 
68 //=======================================================================
69 //function : GCPnts_UniformDeflection
70 //purpose  :
71 //=======================================================================
GCPnts_UniformDeflection(const Adaptor3d_Curve & theC,const Standard_Real theDeflection,const Standard_Boolean theWithControl)72 GCPnts_UniformDeflection::GCPnts_UniformDeflection (const Adaptor3d_Curve& theC,
73                                                     const Standard_Real theDeflection,
74                                                     const Standard_Boolean theWithControl)
75 : myDone (Standard_False),
76   myDeflection (theDeflection)
77 {
78   Initialize (theC, theDeflection, theWithControl);
79 }
80 
81 //=======================================================================
82 //function : GCPnts_UniformDeflection
83 //purpose  :
84 //=======================================================================
GCPnts_UniformDeflection(const Adaptor2d_Curve2d & theC,const Standard_Real theDeflection,const Standard_Real theU1,const Standard_Real theU2,const Standard_Boolean theWithControl)85 GCPnts_UniformDeflection::GCPnts_UniformDeflection (const Adaptor2d_Curve2d& theC,
86                                                     const Standard_Real theDeflection,
87                                                     const Standard_Real theU1,
88                                                     const Standard_Real theU2,
89                                                     const Standard_Boolean theWithControl)
90 : myDone (Standard_False),
91   myDeflection (theDeflection)
92 {
93   Initialize (theC, theDeflection, theU1, theU2, theWithControl);
94 }
95 
96 //=======================================================================
97 //function : GCPnts_UniformDeflection
98 //purpose  :
99 //=======================================================================
GCPnts_UniformDeflection(const Adaptor2d_Curve2d & theC,const Standard_Real theDeflection,const Standard_Boolean theWithControl)100 GCPnts_UniformDeflection::GCPnts_UniformDeflection (const Adaptor2d_Curve2d& theC,
101                                                     const Standard_Real theDeflection,
102                                                     const Standard_Boolean theWithControl)
103 : myDone (Standard_False),
104   myDeflection (theDeflection)
105 {
106   Initialize (theC, theDeflection, theWithControl);
107 }
108 
109 //=======================================================================
110 //function : Initialize
111 //purpose  :
112 //=======================================================================
Initialize(const Adaptor3d_Curve & theC,const Standard_Real theDeflection,const Standard_Boolean theWithControl)113 void GCPnts_UniformDeflection::Initialize (const Adaptor3d_Curve& theC,
114                                            const Standard_Real theDeflection,
115                                            const Standard_Boolean theWithControl)
116 {
117   Initialize (theC, theDeflection, theC.FirstParameter(), theC.LastParameter(), theWithControl);
118 }
119 
120 //=======================================================================
121 //function : Initialize
122 //purpose  :
123 //=======================================================================
Initialize(const Adaptor2d_Curve2d & theC,const Standard_Real theDeflection,const Standard_Boolean theWithControl)124 void GCPnts_UniformDeflection::Initialize (const Adaptor2d_Curve2d& theC,
125                                            const Standard_Real theDeflection,
126                                            const Standard_Boolean theWithControl)
127 {
128   Initialize (theC, theDeflection, theC.FirstParameter(), theC.LastParameter(), theWithControl);
129 }
130 
131 //=======================================================================
132 //function : Initialize
133 //purpose  :
134 //=======================================================================
Initialize(const Adaptor3d_Curve & theC,const Standard_Real theDeflection,const Standard_Real theU1,const Standard_Real theU2,const Standard_Boolean theWithControl)135 void GCPnts_UniformDeflection::Initialize (const Adaptor3d_Curve& theC,
136                                            const Standard_Real theDeflection,
137                                            const Standard_Real theU1,
138                                            const Standard_Real theU2,
139                                            const Standard_Boolean theWithControl)
140 {
141   initialize (theC, theDeflection, theU1, theU2, theWithControl);
142 }
143 
144 //=======================================================================
145 //function : Initialize
146 //purpose  :
147 //=======================================================================
Initialize(const Adaptor2d_Curve2d & theC,const Standard_Real theDeflection,const Standard_Real theU1,const Standard_Real theU2,const Standard_Boolean theWithControl)148 void GCPnts_UniformDeflection::Initialize (const Adaptor2d_Curve2d& theC,
149                                            const Standard_Real theDeflection,
150                                            const Standard_Real theU1,
151                                            const Standard_Real theU2,
152                                            const Standard_Boolean theWithControl)
153 {
154   initialize (theC, theDeflection, theU1, theU2, theWithControl);
155 }
156 
157 //=======================================================================
158 //function : Value
159 //purpose  :
160 //=======================================================================
Value(const Standard_Integer theIndex) const161 gp_Pnt GCPnts_UniformDeflection::Value (const Standard_Integer theIndex) const
162 {
163   StdFail_NotDone_Raise_if(!myDone, "GCPnts_UniformAbscissa::Parameter()");
164   return myPoints.Value (theIndex);
165 }
166 
167 //! Control of the last points.
168 template<class TheCurve>
Controle(const TheCurve & theC,TColStd_SequenceOfReal & theParameters,TColgp_SequenceOfPnt & thePoints,const Standard_Real theU2)169 static void Controle (const TheCurve& theC,
170                       TColStd_SequenceOfReal& theParameters,
171                       TColgp_SequenceOfPnt& thePoints,
172                       const Standard_Real theU2)
173 {
174   const Standard_Integer aNbPnts = thePoints.Length();
175   if (aNbPnts > 2)
176   {
177     const Standard_Real aUa = theParameters (aNbPnts - 2);
178     const Standard_Real aUb = theParameters (aNbPnts - 1);
179     if (theU2 - aUb < 0.33 * (theU2 - aUa))
180     {
181       const Standard_Real aUc = (theU2 + aUa) * 0.5;
182       theParameters (aNbPnts - 1) = aUc;
183       thePoints (aNbPnts - 1) = Value (theC, aUc);
184     }
185   }
186 }
187 
188 //=======================================================================
189 //function : PerformLinear
190 //purpose  :
191 //=======================================================================
192 template<class TheCurve>
PerformLinear(const TheCurve & theC,TColStd_SequenceOfReal & theParameters,TColgp_SequenceOfPnt & thePoints,const Standard_Real theU1,const Standard_Real theU2)193 static Standard_Boolean PerformLinear (const TheCurve& theC,
194                                        TColStd_SequenceOfReal& theParameters,
195                                        TColgp_SequenceOfPnt& thePoints,
196                                        const Standard_Real theU1,
197                                        const Standard_Real theU2)
198 {
199   theParameters.Append (theU1);
200   gp_Pnt aPoint = Value (theC, theU1);
201   thePoints.Append (aPoint);
202 
203   theParameters.Append (theU2);
204   aPoint = Value (theC, theU2);
205   thePoints.Append (aPoint);
206   return Standard_True;
207 }
208 
209 //=======================================================================
210 //function : PerformCircular
211 //purpose  :
212 //=======================================================================
213 template<class TheCurve>
PerformCircular(const TheCurve & theC,TColStd_SequenceOfReal & theParameters,TColgp_SequenceOfPnt & thePoints,const Standard_Real theDeflection,const Standard_Real theU1,const Standard_Real theU2)214 static Standard_Boolean PerformCircular (const TheCurve& theC,
215                                          TColStd_SequenceOfReal& theParameters,
216                                          TColgp_SequenceOfPnt& thePoints,
217                                          const Standard_Real theDeflection,
218                                          const Standard_Real theU1,
219                                          const Standard_Real theU2)
220 {
221   gp_Pnt aPoint;
222   Standard_Real anAngle = Max (1.0 - (theDeflection / theC.Circle().Radius()), 0.0);
223   anAngle = 2.0e0 * ACos (anAngle);
224   Standard_Integer aNbPoints = (Standard_Integer )((theU2 - theU1) / anAngle);
225   aNbPoints += 2;
226   anAngle = (theU2 - theU1) / (Standard_Real) (aNbPoints - 1);
227   Standard_Real aU = theU1;
228   for (Standard_Integer i = 1; i <= aNbPoints; ++i)
229   {
230     theParameters.Append (aU);
231     aPoint = Value (theC, aU);
232     thePoints.Append (aPoint);
233     aU += anAngle;
234   }
235   return Standard_True;
236 }
237 
238 //=======================================================================
239 //function : GetDefType
240 //purpose  :
241 //=======================================================================
242 template<class TheCurve>
GetDefType(const TheCurve & theC)243 static GCPnts_DeflectionType GetDefType (const TheCurve& theC)
244 {
245   if (theC.NbIntervals (GeomAbs_C2) > 1)
246   {
247     return GCPnts_DefComposite;
248   }
249 
250   switch (theC.GetType())
251   {
252     case GeomAbs_Line:   return GCPnts_Linear;
253     case GeomAbs_Circle: return GCPnts_Circular;
254     case GeomAbs_BSplineCurve:
255     {
256       Handle(typename GCPnts_TCurveTypes<TheCurve>::BSplineCurve) aBSpline = theC.BSpline();
257       return (aBSpline->NbPoles() == 2) ? GCPnts_Linear : GCPnts_Curved;
258     }
259     case GeomAbs_BezierCurve:
260     {
261       Handle(typename GCPnts_TCurveTypes<TheCurve>::BezierCurve) aBezier = theC.Bezier();
262       return (aBezier->NbPoles() == 2) ? GCPnts_Linear : GCPnts_Curved;
263     }
264     default:
265     {
266       return GCPnts_Curved;
267     }
268   }
269 }
270 
271 //=======================================================================
272 //function : PerformCurve
273 //purpose  :
274 //=======================================================================
275 template<class TheCurve>
PerformCurve(TColStd_SequenceOfReal & theParameters,TColgp_SequenceOfPnt & thePoints,const TheCurve & theC,const Standard_Real theDeflection,const Standard_Real theU1,const Standard_Real theU2,const Standard_Real theEPSILON,const Standard_Boolean theWithControl)276 static Standard_Boolean PerformCurve (TColStd_SequenceOfReal& theParameters,
277                                       TColgp_SequenceOfPnt&   thePoints,
278                                       const TheCurve& theC,
279                                       const Standard_Real theDeflection,
280                                       const Standard_Real theU1,
281                                       const Standard_Real theU2,
282                                       const Standard_Real theEPSILON,
283                                       const Standard_Boolean theWithControl)
284 {
285   CPnts_UniformDeflection anIterator (theC, theDeflection, theU1, theU2, theEPSILON, theWithControl);
286   for (; anIterator.More(); anIterator.Next())
287   {
288     theParameters.Append (anIterator.Value());
289     thePoints.Append (anIterator.Point());
290   }
291   return anIterator.IsAllDone();
292 }
293 
294 
295 //=======================================================================
296 //function : PerformComposite
297 //purpose  :
298 //=======================================================================
299 template<class TheCurve>
PerformComposite(TColStd_SequenceOfReal & theParameters,TColgp_SequenceOfPnt & thePoints,const TheCurve & theC,const Standard_Real theDeflection,const Standard_Real theU1,const Standard_Real theU2,const Standard_Real theEPSILON,const Standard_Boolean theWithControl)300 static Standard_Boolean PerformComposite (TColStd_SequenceOfReal& theParameters,
301                                           TColgp_SequenceOfPnt& thePoints,
302                                           const TheCurve& theC,
303                                           const Standard_Real theDeflection,
304                                           const Standard_Real theU1,
305                                           const Standard_Real theU2,
306                                           const Standard_Real theEPSILON,
307                                           const Standard_Boolean theWithControl)
308 {
309   const Standard_Integer aNbIntervals = theC.NbIntervals (GeomAbs_C2);
310   Standard_Integer aPIndex = 0;
311 
312   TColStd_Array1OfReal aTI (1, aNbIntervals + 1);
313   theC.Intervals (aTI, GeomAbs_C2);
314   BSplCLib::Hunt (aTI, theU1, aPIndex);
315 
316   // iterate by continuous segments
317   Standard_Real aUa = theU1;
318   for (Standard_Integer anIndex = aPIndex;;)
319   {
320     Standard_Real aUb = anIndex + 1 <= aTI.Upper()
321                       ? Min (theU2, aTI (anIndex + 1))
322                       : theU2;
323     if (!PerformCurve (theParameters, thePoints, theC, theDeflection,
324 		                   aUa, aUb, theEPSILON, theWithControl))
325     {
326       return Standard_False;
327     }
328     ++anIndex;
329     if (anIndex > aNbIntervals || theU2 < aTI (anIndex))
330     {
331       return Standard_True;
332     }
333 
334     // remove last point to avoid duplication
335     theParameters.Remove (theParameters.Length());
336     thePoints.Remove (thePoints.Length());
337 
338     aUa = aUb;
339   }
340 }
341 
342 //=======================================================================
343 //function : initialize
344 //purpose  :
345 //=======================================================================
346 template<class TheCurve>
initialize(const TheCurve & theC,const Standard_Real theDeflection,const Standard_Real theU1,const Standard_Real theU2,const Standard_Boolean theWithControl)347 void GCPnts_UniformDeflection::initialize (const TheCurve& theC,
348                                            const Standard_Real theDeflection,
349                                            const Standard_Real theU1,
350                                            const Standard_Real theU2,
351                                            const Standard_Boolean theWithControl)
352 {
353   const Standard_Real anEPSILON = theC.Resolution (Precision::Confusion());
354   myDeflection = theDeflection;
355   myDone = Standard_False;
356   myParams.Clear();
357   myPoints.Clear();
358 
359   const Standard_Real aU1 = Min (theU1, theU2);
360   const Standard_Real aU2 = Max (theU1, theU2);
361   const GCPnts_DeflectionType aType = GetDefType (theC);
362   switch (aType)
363   {
364     case GCPnts_Linear:
365       myDone = PerformLinear (theC, myParams, myPoints, aU1, aU2);
366       break;
367     case GCPnts_Circular:
368       myDone = PerformCircular (theC, myParams, myPoints, theDeflection, aU1, aU2);
369       break;
370     case GCPnts_Curved:
371       myDone = PerformCurve (myParams, myPoints, theC, theDeflection,
372                              aU1, aU2, anEPSILON, theWithControl);
373       break;
374     case GCPnts_DefComposite:
375       myDone = PerformComposite (myParams, myPoints, theC, theDeflection,
376                                  aU1, aU2, anEPSILON, theWithControl);
377       break;
378   }
379 
380   // control of the last points
381   Controle (theC, myParams, myPoints, aU2);
382 }
383