0024166: Unable to create file with "Save" menu of voxeldemo Qt sample
[occt.git] / src / GCPnts / GCPnts_AbscissaPoint.gxx
CommitLineData
b311480e 1// Created on: 1995-05-05
2// Created by: Modelistation
3// Copyright (c) 1995-1999 Matra Datavision
4// Copyright (c) 1999-2012 OPEN CASCADE SAS
7fd59977 5//
b311480e 6// The content of this file is subject to the Open CASCADE Technology Public
7// License Version 6.5 (the "License"). You may not use the content of this file
8// except in compliance with the License. Please obtain a copy of the License
9// at http://www.opencascade.org and read it completely before using this file.
10//
11// The Initial Developer of the Original Code is Open CASCADE S.A.S., having its
12// main offices at: 1, place des Freres Montgolfier, 78280 Guyancourt, France.
7fd59977 13//
b311480e 14// The Original Code and all software distributed under the License is
15// distributed on an "AS IS" basis, without warranty of any kind, and the
16// Initial Developer hereby disclaims all such warranties, including without
17// limitation, any warranties of merchantability, fitness for a particular
18// purpose or non-infringement. Please see the License for the specific terms
19// and conditions governing the rights and limitations under the License.
20
21
22// Dimension independant used to implement GCPnts_AbscissaPoint
7fd59977 23
24// compute the type
25// and the length ratio if GCPnts_LengthParametrized
26#include <GCPnts_AbscissaType.hxx>
27#include <gp_Vec.hxx>
28#include <gp_Vec2d.hxx>
29#include <gp_Circ.hxx>
30#include <gp_Circ2d.hxx>
31#include <Precision.hxx>
32#include <TColStd_Array1OfReal.hxx>
33#include <BSplCLib.hxx>
34
35static GCPnts_AbscissaType computeType( TheCurve& C,
36 Standard_Real& Ratio)
37{
38 GCPnts_AbscissaType LocalType ;
39
40 if (C.NbIntervals(GeomAbs_CN) > 1)
41 return GCPnts_AbsComposite;
42
43 switch (C.GetType()) {
44
45 case GeomAbs_Line:
46 Ratio = 1.0e0 ;
47 return GCPnts_LengthParametrized;
48
49 case GeomAbs_Circle:
50 Ratio = C.Circle().Radius();
51 return GCPnts_LengthParametrized;
52
53 case GeomAbs_BezierCurve:
54 {
55 Handle_TheBezierCurve Bz = C.Bezier();
56 if ((Bz->NbPoles() == 2) && !(Bz->IsRational())) {
57 Ratio = Bz->DN(0,1).Magnitude();
58 LocalType = GCPnts_LengthParametrized;
59 }
60 else
61 LocalType = GCPnts_Parametrized;
62 return LocalType ;
63 }
64 case GeomAbs_BSplineCurve:
65 {
66 Handle_TheBSplineCurve Bs = C.BSpline();
67 if ((Bs->NbPoles() == 2) && !(Bs->IsRational())) {
68 Ratio = Bs->DN(Bs->FirstParameter(),1).Magnitude();
69 LocalType = GCPnts_LengthParametrized;
70 }
71 else
72 LocalType = GCPnts_Parametrized;
73 return LocalType ;
74 }
75 default:
76 return GCPnts_Parametrized;
77
78 }
79}
80
81// compute a point at distance Abscis from parameter U0
82// using Ui as initial guess
83
84static void Compute(CPnts_AbscissaPoint& theComputer,
85 TheCurve& C,
86 Standard_Real& Abscis,
87 Standard_Real& U0,
88 Standard_Real& Ui,
89 const Standard_Real EPSILON)
90{
91 // test for easy solution
92 if (Abs(Abscis) <= Precision::Confusion()) {
93 theComputer.SetParameter(U0);
94 return;
95 }
96
97 Standard_Real Ratio;
98 GCPnts_AbscissaType Type = computeType(C,Ratio);
99
100 switch (Type) {
101 case GCPnts_LengthParametrized :
102 theComputer.SetParameter(U0 + Abscis / Ratio);
103 return;
104
105 case GCPnts_Parametrized :
106 theComputer.Init(C);
107 theComputer.Perform(Abscis, U0, Ui, EPSILON);
108 return;
109
110 case GCPnts_AbsComposite :
111 {
112 Standard_Integer NbIntervals = C.NbIntervals(GeomAbs_CN);
113 TColStd_Array1OfReal TI(1,NbIntervals+1);
114 C.Intervals(TI,GeomAbs_CN);
115 Standard_Real L = 0.0, sign = 1.;
116 Standard_Integer Index = 1;
117 BSplCLib::Hunt(TI,U0,Index);
118 Standard_Integer Direction = 1;
119 if (Abscis < 0) {
120 Direction = 0;
121 Abscis = -Abscis;
122 sign = -1.;
123 }
124
125 while ((Index >= 1) && (Index <= NbIntervals)) {
126
127 L = CPnts_AbscissaPoint::Length(C, U0, TI(Index+Direction));
128 if (Abs(L - Abscis) <= Precision::Confusion()) {
129 theComputer.SetParameter(TI(Index+Direction));
130 return;
131 }
132 if(L > Abscis) {
133 if ((Ui < TI(Index)) || (Ui > TI(Index+1))) {
134 Ui = (Abscis / L) * (TI(Index+1) - U0);
135 if (Direction)
136 Ui = U0 + Ui;
137 else
138 Ui = U0 - Ui;
139 }
140 theComputer.Init(C,TI(Index),TI(Index+1));
141 theComputer.Perform(sign*Abscis, U0, Ui, EPSILON);
142 return;
143 }
144 else {
145 U0 = TI(Index+Direction);
146 Abscis -= L;
147 }
148 if (Direction)
149 Index++;
150 else
151 Index--;
152 }
153
154 // Push a little bit outside the limits (hairy !!!)
155 Ui = U0 + 0.1;
156 theComputer.Init(C,U0,U0+0.2);
157 theComputer.Perform(sign*Abscis, U0, Ui, EPSILON);
158 return;
159 }
160 break;
161 }
162
163}
164
165// introduced by rbv for curvilinear parametrization
166// performs more apropriate tolerance managment
167
168static void AdvCompute(CPnts_AbscissaPoint& theComputer,
169 TheCurve& C,
170 Standard_Real& Abscis,
171 Standard_Real& U0,
172 Standard_Real& Ui,
173 const Standard_Real EPSILON)
174{
175 // test for easy solution
176 if (Abs(Abscis) <= EPSILON) {
177 theComputer.SetParameter(U0);
178 return;
179 }
180
181 Standard_Real Ratio;
182 GCPnts_AbscissaType Type = computeType(C,Ratio);
183
184 switch (Type) {
185 case GCPnts_LengthParametrized :
186 theComputer.SetParameter(U0 + Abscis / Ratio);
187 return;
188
189 case GCPnts_Parametrized :
190// theComputer.Init(C);
191 theComputer.Init(C, EPSILON); //rbv's modification
192//
193 theComputer.AdvPerform(Abscis, U0, Ui, EPSILON);
194 return;
195
196 case GCPnts_AbsComposite :
197 {
198 Standard_Integer NbIntervals = C.NbIntervals(GeomAbs_CN);
199 TColStd_Array1OfReal TI(1,NbIntervals+1);
200 C.Intervals(TI,GeomAbs_CN);
201 Standard_Real L = 0.0, sign = 1.;
202 Standard_Integer Index = 1;
203 BSplCLib::Hunt(TI,U0,Index);
204
205 Standard_Integer Direction = 1;
206 if (Abscis < 0) {
207 Direction = 0;
208 Abscis = -Abscis;
209 sign = -1.;
210 }
211
212 if(Index == 0 && Direction > 0) {
213 L = CPnts_AbscissaPoint::Length(C, U0, TI(Index+Direction), EPSILON);
214 if (Abs(L - Abscis) <= /*Precision::Confusion()*/EPSILON) {
215 theComputer.SetParameter(TI(Index+Direction));
216 return;
217 }
218 if(L > Abscis) {
219 if ( Ui > TI(Index+1) ) {
220 Ui = (Abscis / L) * (TI(Index+1) - U0);
221 Ui = U0 + Ui;
222 }
223 theComputer.Init(C,U0,TI(Index+1), EPSILON);
224 theComputer.AdvPerform(sign*Abscis, U0, Ui, EPSILON);
225 return;
226 }
227 else {
228 U0 = TI(Index+Direction);
229 Abscis -= L;
230 }
231 Index++;
232 }
233
234
235 while ((Index >= 1) && (Index <= NbIntervals)) {
236
237 L = CPnts_AbscissaPoint::Length(C, U0, TI(Index+Direction), EPSILON);
238 if (Abs(L - Abscis) <= /*Precision::Confusion()*/EPSILON) {
239 theComputer.SetParameter(TI(Index+Direction));
240 return;
241 }
242 if(L > Abscis) {
243 if ((Ui < TI(Index)) || (Ui > TI(Index+1))) {
244 Ui = (Abscis / L) * (TI(Index+1) - U0);
245 if (Direction)
246 Ui = U0 + Ui;
247 else
248 Ui = U0 - Ui;
249 }
250 theComputer.Init(C,TI(Index),TI(Index+1), EPSILON);
251 theComputer.AdvPerform(sign*Abscis, U0, Ui, EPSILON);
252 return;
253 }
254 else {
255 U0 = TI(Index+Direction);
256 Abscis -= L;
257 }
258 if (Direction) {
259 Index++;
260
261 }
262 else {
263 Index--;
264
265 }
266 }
267
268 // Push a little bit outside the limits (hairy !!!)
269
270 Standard_Boolean nonperiodic = !C.IsPeriodic();
271 Ui = U0 + sign*0.1;
272 Standard_Real U1 = U0 + sign*.2;
273 if(nonperiodic) {
274 if(sign > 0) {
275 Ui = Min(Ui,C.LastParameter());
276 U1 = Min(U1, C.LastParameter());
277 }
278 else {
279 Ui = Max(Ui,C.FirstParameter());
280 U1 = Max(U1, C.FirstParameter());
281 }
282 }
283
284 theComputer.Init(C, U0, U1, EPSILON);
285 theComputer.AdvPerform(sign*Abscis, U0, Ui, EPSILON);
286 return;
287 }
288 break;
289 }
290
291}
292
293//=======================================================================
294//function : Length
295//purpose :
296//=======================================================================
297
298Standard_Real GCPnts_AbscissaPoint::Length(TheCurve& C)
299{
300 return GCPnts_AbscissaPoint::Length(C,C.FirstParameter(),
301 C.LastParameter());
302}
303
304//=======================================================================
305//function : Length
306//purpose :
307//=======================================================================
308
309Standard_Real GCPnts_AbscissaPoint::Length(TheCurve& C,
310 const Standard_Real Tol)
311{
312 return GCPnts_AbscissaPoint::Length(C,C.FirstParameter(),
313 C.LastParameter(),Tol);
314}
315
316
317//=======================================================================
318//function : Length
319//purpose :
320//=======================================================================
321
322Standard_Real GCPnts_AbscissaPoint::Length(TheCurve& C,
323 const Standard_Real U1,
324 const Standard_Real U2)
325{
326 Standard_Real Ratio;
327 GCPnts_AbscissaType Type = computeType(C,Ratio);
328 switch (Type) {
329
330 case GCPnts_LengthParametrized:
331 return Abs(U2-U1) * Ratio;
332
333 case GCPnts_Parametrized:
334 return CPnts_AbscissaPoint::Length(C, U1, U2);
335
336 case GCPnts_AbsComposite:
337 {
338 Standard_Integer NbIntervals = C.NbIntervals(GeomAbs_CN);
339 TColStd_Array1OfReal TI(1,NbIntervals+1);
340 C.Intervals(TI,GeomAbs_CN);
341 Standard_Real UU1 = Min(U1, U2);
342 Standard_Real UU2 = Max(U1, U2);
343 Standard_Real L = 0.0;
344 for(Standard_Integer Index = 1; Index <= NbIntervals; Index++) {
345 if (TI(Index) > UU2) break;
346 if (TI(Index+1) < UU1) continue;
347 L += CPnts_AbscissaPoint::Length(C,
348 Max(TI(Index),UU1),
349 Min(TI(Index+1),UU2));
350 }
351 return L;
352 }
353 }
354 return RealLast();
355}
356
357//=======================================================================
358//function : Length
359//purpose :
360//=======================================================================
361
362Standard_Real GCPnts_AbscissaPoint::Length(TheCurve& C,
363 const Standard_Real U1,
364 const Standard_Real U2,
365 const Standard_Real Tol)
366{
367 Standard_Real Ratio;
368 GCPnts_AbscissaType Type = computeType(C,Ratio);
369 switch (Type) {
370
371 case GCPnts_LengthParametrized:
372 return Abs(U2-U1) * Ratio;
373
374 case GCPnts_Parametrized:
375 return CPnts_AbscissaPoint::Length(C, U1, U2, Tol);
376
377 case GCPnts_AbsComposite:
378 {
379 Standard_Integer NbIntervals = C.NbIntervals(GeomAbs_CN);
380 TColStd_Array1OfReal TI(1,NbIntervals+1);
381 C.Intervals(TI,GeomAbs_CN);
382 Standard_Real UU1 = Min(U1, U2);
383 Standard_Real UU2 = Max(U1, U2);
384 Standard_Real L = 0.0;
385 for(Standard_Integer Index = 1; Index <= NbIntervals; Index++) {
386 if (TI(Index) > UU2) break;
387 if (TI(Index+1) < UU1) continue;
388 L += CPnts_AbscissaPoint::Length(C,
389 Max(TI(Index),UU1),
390 Min(TI(Index+1),UU2),
391 Tol);
392 }
393 return L;
394 }
395 }
396 return RealLast();
397}
398
399
400//=======================================================================
401//function : GCPnts_AbscissaPoint
402//purpose :
403//=======================================================================
404
405GCPnts_AbscissaPoint::GCPnts_AbscissaPoint
406 (TheCurve& C,
407 const Standard_Real Abscissa,
408 const Standard_Real U0)
409{
410 Standard_Real L = GCPnts_AbscissaPoint::Length(C);
411 if (L < Precision::Confusion()) {
412 Standard_ConstructionError::Raise();
413 }
414 Standard_Real Abscis = Abscissa;
415 Standard_Real UU0 = U0;
416 Standard_Real UUi = U0 +
417 (Abscis / L) * (C.LastParameter() - C.FirstParameter());
418 Compute(myComputer, C, Abscis, UU0, UUi,
419 C.Resolution(Precision::Confusion()));
420}
421
422//=======================================================================
423//function : GCPnts_AbscissaPoint
424//purpose : rbv for curvilinear parametrization
425//=======================================================================
426
427GCPnts_AbscissaPoint::GCPnts_AbscissaPoint
428 (const Standard_Real Tol,
429 TheCurve& C,
430 const Standard_Real Abscissa,
431 const Standard_Real U0)
432{
433 Standard_Real L = GCPnts_AbscissaPoint::Length(C, Tol);
434/* if (L < Precision::Confusion()) {
435 cout<<"FirstParameter = "<<C.FirstParameter()<<endl;
436 cout<<"LastParameter = "<<C.LastParameter()<<endl;
437 Standard_ConstructionError::Raise("GCPnts_AbscissaPoint::GCPnts_AbscissaPoint");
438 }
439*/
440 Standard_Real Abscis = Abscissa;
441 Standard_Real UU0 = U0;
442 Standard_Real UUi;
443 if (L >= Precision::Confusion())
444 UUi= U0 +
445 (Abscis / L) * (C.LastParameter() - C.FirstParameter());
446 else UUi = U0;
447
448 AdvCompute(myComputer, C, Abscis, UU0, UUi, Tol);
449}
450
451//=======================================================================
452//function : GCPnts_AbscissaPoint
453//purpose :
454//=======================================================================
455
456GCPnts_AbscissaPoint::GCPnts_AbscissaPoint
457 (TheCurve& C,
458 const Standard_Real Abscissa,
459 const Standard_Real U0,
460 const Standard_Real Ui)
461{
462 Standard_Real Abscis = Abscissa;
463 Standard_Real UU0 = U0;
464 Standard_Real UUi = Ui;
465 Compute(myComputer, C, Abscis, UU0, UUi,
466 C.Resolution(Precision::Confusion()));
467}
468
469//=======================================================================
470//function : GCPnts_AbscissaPoint
471//purpose : rbv for curvilinear parametrization
472//=======================================================================
473
474GCPnts_AbscissaPoint::GCPnts_AbscissaPoint
475 (TheCurve& C,
476 const Standard_Real Abscissa,
477 const Standard_Real U0,
478 const Standard_Real Ui,
479 const Standard_Real Tol)
480{
481 Standard_Real Abscis = Abscissa;
482 Standard_Real UU0 = U0;
483 Standard_Real UUi = Ui;
484 AdvCompute(myComputer, C, Abscis, UU0, UUi, Tol);
485}