0031662: Modeling Algorithms - Incomplete result of section operation
[occt.git] / src / Approx / Approx_CurveOnSurface.cxx
CommitLineData
b311480e 1// Created on: 1997-10-06
2// Created by: Roman BORISOV
3// Copyright (c) 1997-1999 Matra Datavision
973c2be1 4// Copyright (c) 1999-2014 OPEN CASCADE SAS
b311480e 5//
973c2be1 6// This file is part of Open CASCADE Technology software library.
b311480e 7//
d5f74e42 8// This library is free software; you can redistribute it and/or modify it under
9// the terms of the GNU Lesser General Public License version 2.1 as published
973c2be1 10// by the Free Software Foundation, with special exception defined in the file
11// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
12// distribution for complete text of the license and disclaimer of any warranty.
b311480e 13//
973c2be1 14// Alternatively, this file may be used under the terms of Open CASCADE
15// commercial license or contractual agreement.
7fd59977 16
42cf5bc1 17
18#include <Adaptor2d_HCurve2d.hxx>
7fd59977 19#include <Adaptor3d_CurveOnSurface.hxx>
7fd59977 20#include <Adaptor3d_HCurve.hxx>
7fd59977 21#include <Adaptor3d_HCurveOnSurface.hxx>
42cf5bc1 22#include <Adaptor3d_HSurface.hxx>
23#include <AdvApprox_ApproxAFunction.hxx>
24#include <AdvApprox_DichoCutting.hxx>
25#include <AdvApprox_PrefAndRec.hxx>
26#include <Approx_CurveOnSurface.hxx>
27#include <Geom2d_BSplineCurve.hxx>
28#include <Geom2dAdaptor_HCurve.hxx>
29#include <Geom_BSplineCurve.hxx>
552a74d8 30#include <Geom_RectangularTrimmedSurface.hxx>
f04de133 31#include <Geom_TrimmedCurve.hxx>
42cf5bc1 32#include <GeomAdaptor_HCurve.hxx>
33#include <GeomAdaptor_HSurface.hxx>
f04de133 34#include <GeomConvert.hxx>
42cf5bc1 35#include <gp_Pnt.hxx>
36#include <gp_Vec.hxx>
37#include <Precision.hxx>
38#include <Standard_ConstructionError.hxx>
39#include <Standard_OutOfRange.hxx>
40#include <TColgp_Array1OfPnt.hxx>
7fd59977 41#include <TColgp_Array1OfPnt2d.hxx>
42#include <TColStd_Array1OfReal.hxx>
42cf5bc1 43#include <TColStd_HArray1OfReal.hxx>
7fd59977 44
45//=======================================================================
46//class : Approx_CurveOnSurface_Eval
47//purpose: evaluator class for approximation of both 2d and 3d curves
48//=======================================================================
7fd59977 49class Approx_CurveOnSurface_Eval : public AdvApprox_EvaluatorFunction
50{
51 public:
52 Approx_CurveOnSurface_Eval (const Handle(Adaptor3d_HCurve)& theFunc,
53 const Handle(Adaptor2d_HCurve2d)& theFunc2d,
54 Standard_Real First, Standard_Real Last)
55 : fonct(theFunc), fonct2d(theFunc2d)
56 { StartEndSav[0] = First; StartEndSav[1] = Last; }
57
58 virtual void Evaluate (Standard_Integer *Dimension,
59 Standard_Real StartEnd[2],
60 Standard_Real *Parameter,
61 Standard_Integer *DerivativeRequest,
62 Standard_Real *Result, // [Dimension]
63 Standard_Integer *ErrorCode);
64
65 private:
66 Handle(Adaptor3d_HCurve) fonct;
67 Handle(Adaptor2d_HCurve2d) fonct2d;
68 Standard_Real StartEndSav[2];
69};
70
71void Approx_CurveOnSurface_Eval::Evaluate (Standard_Integer *Dimension,
72 Standard_Real StartEnd[2],
73 Standard_Real *Param, // Parameter at which evaluation
74 Standard_Integer *Order, // Derivative Request
75 Standard_Real *Result,// [Dimension]
76 Standard_Integer *ErrorCode)
77{
78 *ErrorCode = 0;
79 Standard_Real par = *Param;
80
81// Dimension is incorrect
82 if (*Dimension != 5) {
83 *ErrorCode = 1;
84 }
85
86// Parameter is incorrect
87 if(StartEnd[0] != StartEndSav[0] || StartEnd[1]!= StartEndSav[1])
88 {
89 fonct = fonct->Trim(StartEnd[0],StartEnd[1],Precision::PConfusion());
90 fonct2d = fonct2d->Trim(StartEnd[0],StartEnd[1],
91 Precision::PConfusion());
92 StartEndSav[0]=StartEnd[0];
93 StartEndSav[1]=StartEnd[1];
94 }
95 gp_Pnt pnt;
96
97
98 gp_Pnt2d pnt2d;
99
100 switch (*Order) {
101 case 0:
102 {
103 fonct2d->D0(par, pnt2d);
104 fonct->D0(par, pnt);
105 Result[0] = pnt2d.X();
106 Result[1] = pnt2d.Y();
107 Result[2] = pnt.X();
108 Result[3] = pnt.Y();
109 Result[4] = pnt.Z();
110 break;
111 }
112 case 1:
113 {
114 gp_Vec v1;
115 gp_Vec2d v21;
116 fonct2d->D1(par, pnt2d, v21);
117 fonct->D1(par,pnt, v1);
118 Result[0] = v21.X();
119 Result[1] = v21.Y();
120 Result[2] = v1.X();
121 Result[3] = v1.Y();
122 Result[4] = v1.Z();
123 break;
124 }
125 case 2:
126 {
127 gp_Vec v1, v2;
128 gp_Vec2d v21, v22;
129 fonct2d->D2(par, pnt2d, v21, v22);
130 fonct->D2(par, pnt, v1, v2);
131 Result[0] = v22.X();
132 Result[1] = v22.Y();
133 Result[2] = v2.X();
134 Result[3] = v2.Y();
135 Result[4] = v2.Z();
136 break;
137 }
138 default:
139 Result[0] = Result[1] = Result[2] = Result[3] = Result[4] = 0.;
140 *ErrorCode = 3;
141 break;
142 }
143}
144
145//=======================================================================
146//class : Approx_CurveOnSurface_Eval3d
147//purpose: evaluator class for approximation of 3d curve
148//=======================================================================
149
150class Approx_CurveOnSurface_Eval3d : public AdvApprox_EvaluatorFunction
151{
152 public:
153 Approx_CurveOnSurface_Eval3d (const Handle(Adaptor3d_HCurve)& theFunc,
154 Standard_Real First, Standard_Real Last)
155 : fonct(theFunc) { StartEndSav[0] = First; StartEndSav[1] = Last; }
156
157 virtual void Evaluate (Standard_Integer *Dimension,
158 Standard_Real StartEnd[2],
159 Standard_Real *Parameter,
160 Standard_Integer *DerivativeRequest,
161 Standard_Real *Result, // [Dimension]
162 Standard_Integer *ErrorCode);
163
164 private:
165 Handle(Adaptor3d_HCurve) fonct;
166 Standard_Real StartEndSav[2];
167};
168
169void Approx_CurveOnSurface_Eval3d::Evaluate (Standard_Integer *Dimension,
170 Standard_Real StartEnd[2],
171 Standard_Real *Param, // Parameter at which evaluation
172 Standard_Integer *Order, // Derivative Request
173 Standard_Real *Result,// [Dimension]
174 Standard_Integer *ErrorCode)
175{
176 *ErrorCode = 0;
177 Standard_Real par = *Param;
178
179// Dimension is incorrect
180 if (*Dimension != 3) {
181 *ErrorCode = 1;
182 }
183
184// Parameter is incorrect
185 if(StartEnd[0] != StartEndSav[0] || StartEnd[1]!= StartEndSav[1])
186 {
187 fonct = fonct->Trim(StartEnd[0],StartEnd[1],Precision::PConfusion());
188 StartEndSav[0]=StartEnd[0];
189 StartEndSav[1]=StartEnd[1];
190 }
191
192 gp_Pnt pnt;
193
194 switch (*Order) {
195 case 0:
196 pnt = fonct->Value(par);
197 Result[0] = pnt.X();
198 Result[1] = pnt.Y();
199 Result[2] = pnt.Z();
200 break;
201 case 1:
202 {
203 gp_Vec v1;
204 fonct->D1(par, pnt, v1);
205 Result[0] = v1.X();
206 Result[1] = v1.Y();
207 Result[2] = v1.Z();
208 break;
209 }
210 case 2:
211 {
212 gp_Vec v1, v2;
213 fonct->D2(par, pnt, v1, v2);
214 Result[0] = v2.X();
215 Result[1] = v2.Y();
216 Result[2] = v2.Z();
217 break;
218 }
219 default:
220 Result[0] = Result[1] = Result[2] = 0.;
221 *ErrorCode = 3;
222 break;
223 }
224}
225
226//=======================================================================
227//class : Approx_CurveOnSurface_Eval2d
228//purpose: evaluator class for approximation of 2d curve
229//=======================================================================
230
231class Approx_CurveOnSurface_Eval2d : public AdvApprox_EvaluatorFunction
232{
233 public:
234 Approx_CurveOnSurface_Eval2d (const Handle(Adaptor2d_HCurve2d)& theFunc2d,
235 Standard_Real First, Standard_Real Last)
236 : fonct2d(theFunc2d) { StartEndSav[0] = First; StartEndSav[1] = Last; }
237
238 virtual void Evaluate (Standard_Integer *Dimension,
239 Standard_Real StartEnd[2],
240 Standard_Real *Parameter,
241 Standard_Integer *DerivativeRequest,
242 Standard_Real *Result, // [Dimension]
243 Standard_Integer *ErrorCode);
244
245 private:
246 Handle(Adaptor2d_HCurve2d) fonct2d;
247 Standard_Real StartEndSav[2];
248};
249
250void Approx_CurveOnSurface_Eval2d::Evaluate (Standard_Integer *Dimension,
251 Standard_Real StartEnd[2],
252 Standard_Real *Param, // Parameter at which evaluation
253 Standard_Integer *Order, // Derivative Request
254 Standard_Real *Result,// [Dimension]
255 Standard_Integer *ErrorCode)
256{
257 *ErrorCode = 0;
258 Standard_Real par = *Param;
259
260// Dimension is incorrect
261 if (*Dimension != 2) {
262 *ErrorCode = 1;
263 }
264
265// Parameter is incorrect
266 if(StartEnd[0] != StartEndSav[0] || StartEnd[1]!= StartEndSav[1])
267 {
268 fonct2d = fonct2d->Trim(StartEnd[0],StartEnd[1],Precision::PConfusion());
269 StartEndSav[0]=StartEnd[0];
270 StartEndSav[1]=StartEnd[1];
271 }
272
273 gp_Pnt2d pnt;
274
275 switch (*Order) {
276 case 0:
277 {
278 pnt = fonct2d->Value(par);
279 Result[0] = pnt.X();
280 Result[1] = pnt.Y();
281 break;
282 }
283 case 1:
284 {
285 gp_Vec2d v1;
286 fonct2d->D1(par, pnt, v1);
287 Result[0] = v1.X();
288 Result[1] = v1.Y();
289 break;
290 }
291 case 2:
292 {
293 gp_Vec2d v1, v2;
294 fonct2d->D2(par, pnt, v1, v2);
295 Result[0] = v2.X();
296 Result[1] = v2.Y();
297 break;
298 }
299 default:
300 Result[0] = Result[1] = 0.;
301 *ErrorCode = 3;
302 break;
303 }
304}
305
f04de133 306//=============================================================================
307//function : Approx_CurveOnSurface
308//purpose : Constructor
309//=============================================================================
7fd59977 310 Approx_CurveOnSurface::Approx_CurveOnSurface(const Handle(Adaptor2d_HCurve2d)& C2D,
311 const Handle(Adaptor3d_HSurface)& Surf,
312 const Standard_Real First,
313 const Standard_Real Last,
314 const Standard_Real Tol,
315 const GeomAbs_Shape S,
316 const Standard_Integer MaxDegree,
317 const Standard_Integer MaxSegments,
318 const Standard_Boolean only3d,
319 const Standard_Boolean only2d)
f04de133 320: myC2D(C2D),
321 mySurf(Surf),
322 myFirst(First),
323 myLast(Last),
324 myTol(Tol),
325 myIsDone(Standard_False),
326 myHasResult(Standard_False),
327 myError3d(0.0),
328 myError2dU(0.0),
329 myError2dV(0.0)
330 {
331 Perform(MaxSegments, MaxDegree, S, only3d, only2d);
332 }
333
334//=============================================================================
335//function : Approx_CurveOnSurface
336//purpose : Constructor
337//=============================================================================
338 Approx_CurveOnSurface::Approx_CurveOnSurface(const Handle(Adaptor2d_HCurve2d)& theC2D,
339 const Handle(Adaptor3d_HSurface)& theSurf,
340 const Standard_Real theFirst,
341 const Standard_Real theLast,
342 const Standard_Real theTol)
343: myC2D(theC2D),
344 mySurf(theSurf),
345 myFirst(theFirst),
346 myLast(theLast),
347 myTol(theTol),
348 myIsDone(Standard_False),
349 myHasResult(Standard_False),
350 myError3d(0.0),
351 myError2dU(0.0),
352 myError2dV(0.0)
353{
354}
355
356//=============================================================================
357//function : Perform
358//purpose :
359//=============================================================================
360void Approx_CurveOnSurface::Perform(const Standard_Integer theMaxSegments,
361 const Standard_Integer theMaxDegree,
362 const GeomAbs_Shape theContinuity,
363 const Standard_Boolean theOnly3d,
364 const Standard_Boolean theOnly2d)
7fd59977 365{
366 myIsDone = Standard_False;
f04de133 367 myHasResult = Standard_False;
368 myError2dU = 0.0;
369 myError2dV = 0.0;
370 myError3d = 0.0;
7fd59977 371
f04de133 372 if(theOnly3d && theOnly2d) throw Standard_ConstructionError();
373
374 Handle( Adaptor2d_HCurve2d ) TrimmedC2D = myC2D->Trim( myFirst, myLast, Precision::PConfusion() );
375
376 Standard_Boolean isU, isForward;
377 Standard_Real aParam;
378 if (theOnly3d && isIsoLine(TrimmedC2D, isU, aParam, isForward))
379 {
380 if (buildC3dOnIsoLine(TrimmedC2D, isU, aParam, isForward))
381 {
382 myIsDone = Standard_True;
383 myHasResult = Standard_True;
384 return;
385 }
386 }
7fd59977 387
f04de133 388 Adaptor3d_CurveOnSurface COnS( TrimmedC2D, mySurf );
7fd59977 389 Handle(Adaptor3d_HCurveOnSurface) HCOnS = new Adaptor3d_HCurveOnSurface();
390 HCOnS->Set(COnS);
391
392 Standard_Integer Num1DSS = 0, Num2DSS=0, Num3DSS=0;
393 Handle(TColStd_HArray1OfReal) OneDTol;
394 Handle(TColStd_HArray1OfReal) TwoDTolNul;
395 Handle(TColStd_HArray1OfReal) ThreeDTol;
396
397 // create evaluators and choose appropriate one
f04de133 398 Approx_CurveOnSurface_Eval3d Eval3dCvOnSurf (HCOnS, myFirst, myLast);
399 Approx_CurveOnSurface_Eval2d Eval2dCvOnSurf ( TrimmedC2D, myFirst, myLast);
400 Approx_CurveOnSurface_Eval EvalCvOnSurf (HCOnS, TrimmedC2D, myFirst, myLast);
7fd59977 401 AdvApprox_EvaluatorFunction* EvalPtr;
f04de133 402 if ( theOnly3d ) EvalPtr = &Eval3dCvOnSurf;
403 else if ( theOnly2d ) EvalPtr = &Eval2dCvOnSurf;
7fd59977 404 else EvalPtr = &EvalCvOnSurf;
405
406 // Initialization for 2d approximation
f04de133 407 if(!theOnly3d) {
7fd59977 408 Num1DSS = 2;
409 OneDTol = new TColStd_HArray1OfReal(1,Num1DSS);
410
411 Standard_Real TolU, TolV;
412
f04de133 413 TolU = mySurf->UResolution(myTol)/2;
414 TolV = mySurf->VResolution(myTol)/2;
7fd59977 415
416 OneDTol->SetValue(1,TolU);
417 OneDTol->SetValue(2,TolV);
418 }
419
f04de133 420 if(!theOnly2d) {
7fd59977 421 Num3DSS=1;
422 ThreeDTol = new TColStd_HArray1OfReal(1,Num3DSS);
f04de133 423 ThreeDTol->Init(myTol/2);
7fd59977 424 }
425
7fd59977 426
427 Standard_Integer NbInterv_C2 = HCOnS->NbIntervals(GeomAbs_C2);
428 TColStd_Array1OfReal CutPnts_C2(1, NbInterv_C2 + 1);
429 HCOnS->Intervals(CutPnts_C2, GeomAbs_C2);
430 Standard_Integer NbInterv_C3 = HCOnS->NbIntervals(GeomAbs_C3);
431 TColStd_Array1OfReal CutPnts_C3(1, NbInterv_C3 + 1);
432 HCOnS->Intervals(CutPnts_C3, GeomAbs_C3);
433
434 AdvApprox_PrefAndRec CutTool(CutPnts_C2,CutPnts_C3);
435 AdvApprox_ApproxAFunction aApprox (Num1DSS, Num2DSS, Num3DSS,
436 OneDTol, TwoDTolNul, ThreeDTol,
f04de133 437 myFirst, myLast, theContinuity,
438 theMaxDegree, theMaxSegments,
7fd59977 439 *EvalPtr, CutTool);
440
441 myIsDone = aApprox.IsDone();
442 myHasResult = aApprox.HasResult();
443
444 if (myHasResult) {
445 Handle(TColStd_HArray1OfReal) Knots = aApprox.Knots();
446 Handle(TColStd_HArray1OfInteger) Mults = aApprox.Multiplicities();
447 Standard_Integer Degree = aApprox.Degree();
448
f04de133 449 if(!theOnly2d)
7fd59977 450 {
451 TColgp_Array1OfPnt Poles(1,aApprox.NbPoles());
452 aApprox.Poles(1,Poles);
453 myCurve3d = new Geom_BSplineCurve(Poles, Knots->Array1(), Mults->Array1(), Degree);
454 myError3d = aApprox.MaxError(3, 1);
455 }
f04de133 456 if(!theOnly3d)
7fd59977 457 {
458 TColgp_Array1OfPnt2d Poles2d(1,aApprox.NbPoles());
459 TColStd_Array1OfReal Poles1dU(1,aApprox.NbPoles());
460 aApprox.Poles1d(1, Poles1dU);
461 TColStd_Array1OfReal Poles1dV(1,aApprox.NbPoles());
462 aApprox.Poles1d(2, Poles1dV);
463 for(Standard_Integer i = 1; i <= aApprox.NbPoles(); i++)
464 Poles2d.SetValue(i, gp_Pnt2d(Poles1dU.Value(i), Poles1dV.Value(i)));
465 myCurve2d = new Geom2d_BSplineCurve(Poles2d, Knots->Array1(), Mults->Array1(), Degree);
466
467 myError2dU = aApprox.MaxError(1, 1);
468 myError2dV = aApprox.MaxError(1, 2);
469 }
470 }
471
7fd59977 472}
473
474 Standard_Boolean Approx_CurveOnSurface::IsDone() const
475{
476 return myIsDone;
477}
478
479 Standard_Boolean Approx_CurveOnSurface::HasResult() const
480{
481 return myHasResult;
482}
483
484 Handle(Geom_BSplineCurve) Approx_CurveOnSurface::Curve3d() const
485{
486 return myCurve3d;
487}
488
489 Handle(Geom2d_BSplineCurve) Approx_CurveOnSurface::Curve2d() const
490{
491 return myCurve2d;
492}
493
494 Standard_Real Approx_CurveOnSurface::MaxError3d() const
495{
496 return myError3d;
497}
498
499 Standard_Real Approx_CurveOnSurface::MaxError2dU() const
500{
501 return myError2dU;
502}
503
504 Standard_Real Approx_CurveOnSurface::MaxError2dV() const
505{
506 return myError2dV;
507}
508
f04de133 509//=============================================================================
510//function : isIsoLine
511//purpose :
512//=============================================================================
513Standard_Boolean Approx_CurveOnSurface::isIsoLine(const Handle(Adaptor2d_HCurve2d) theC2D,
514 Standard_Boolean& theIsU,
515 Standard_Real& theParam,
516 Standard_Boolean& theIsForward) const
517{
518 // These variables are used to check line state (vertical or horizontal).
519 Standard_Boolean isAppropriateType = Standard_False;
520 gp_Pnt2d aLoc2d;
521 gp_Dir2d aDir2d;
522
523 // Test type.
524 const GeomAbs_CurveType aType = theC2D->GetType();
525 if (aType == GeomAbs_Line)
526 {
527 gp_Lin2d aLin2d = theC2D->Line();
528 aLoc2d = aLin2d.Location();
529 aDir2d = aLin2d.Direction();
530 isAppropriateType = Standard_True;
531 }
532 else if (aType == GeomAbs_BSplineCurve)
533 {
534 Handle(Geom2d_BSplineCurve) aBSpline2d = theC2D->BSpline();
535 if (aBSpline2d->Degree() != 1 || aBSpline2d->NbPoles() != 2)
536 return Standard_False; // Not a line or uneven parameterization.
537
538 aLoc2d = aBSpline2d->Pole(1);
539
540 // Vector should be non-degenerated.
541 gp_Vec2d aVec2d(aBSpline2d->Pole(1), aBSpline2d->Pole(2));
542 if (aVec2d.SquareMagnitude() < Precision::Confusion())
543 return Standard_False; // Degenerated spline.
544 aDir2d = aVec2d;
545
546 isAppropriateType = Standard_True;
547 }
548 else if (aType == GeomAbs_BezierCurve)
549 {
550 Handle(Geom2d_BezierCurve) aBezier2d = theC2D->Bezier();
551 if (aBezier2d->Degree() != 1 || aBezier2d->NbPoles() != 2)
552 return Standard_False; // Not a line or uneven parameterization.
553
554 aLoc2d = aBezier2d->Pole(1);
555
556 // Vector should be non-degenerated.
557 gp_Vec2d aVec2d(aBezier2d->Pole(1), aBezier2d->Pole(2));
558 if (aVec2d.SquareMagnitude() < Precision::Confusion())
559 return Standard_False; // Degenerated spline.
560 aDir2d = aVec2d;
561
562 isAppropriateType = Standard_True;
563 }
564
565 if (!isAppropriateType)
566 return Standard_False;
567
568 // Check line to be vertical or horizontal.
569 if (aDir2d.IsParallel(gp::DX2d(), Precision::Angular()))
570 {
571 // Horizontal line. V = const.
572 theIsU = Standard_False;
573 theParam = aLoc2d.Y();
574 theIsForward = aDir2d.Dot(gp::DX2d()) > 0.0;
575 return Standard_True;
576 }
577 else if (aDir2d.IsParallel(gp::DY2d(), Precision::Angular()))
578 {
579 // Vertical line. U = const.
580 theIsU = Standard_True;
581 theParam = aLoc2d.X();
582 theIsForward = aDir2d.Dot(gp::DY2d()) > 0.0;
583 return Standard_True;
584 }
585
586 return Standard_False;
587}
588
589#include <GeomLib.hxx>
590
591//=============================================================================
592//function : buildC3dOnIsoLine
593//purpose :
594//=============================================================================
595Standard_Boolean Approx_CurveOnSurface::buildC3dOnIsoLine(const Handle(Adaptor2d_HCurve2d) theC2D,
596 const Standard_Boolean theIsU,
597 const Standard_Real theParam,
598 const Standard_Boolean theIsForward)
599{
600 // Convert adapter to the appropriate type.
601 Handle(GeomAdaptor_HSurface) aGeomAdapter = Handle(GeomAdaptor_HSurface)::DownCast(mySurf);
602 if (aGeomAdapter.IsNull())
603 return Standard_False;
604
605 if (mySurf->GetType() == GeomAbs_Sphere)
606 return Standard_False;
607
608 // Extract isoline
609 Handle(Geom_Surface) aSurf = aGeomAdapter->ChangeSurface().Surface();
610 Handle(Geom_Curve) aC3d;
611
612 gp_Pnt2d aF2d = theC2D->Value(theC2D->FirstParameter());
613 gp_Pnt2d aL2d = theC2D->Value(theC2D->LastParameter());
614
552a74d8 615 Standard_Boolean isToTrim = Standard_True;
616 Standard_Real U1, U2, V1, V2;
617 aSurf->Bounds(U1, U2, V1, V2);
618
f04de133 619 if (theIsU)
620 {
552a74d8 621 Standard_Real aV1Param = Min(aF2d.Y(), aL2d.Y());
622 Standard_Real aV2Param = Max(aF2d.Y(), aL2d.Y());
623 if (aV2Param < V1 - myTol || aV1Param > V2 + myTol)
624 {
625 return Standard_False;
626 }
627 else if (Precision::IsInfinite(V1) || Precision::IsInfinite(V2))
628 {
629 if (Abs(aV2Param - aV1Param) < Precision::PConfusion())
630 {
631 return Standard_False;
632 }
633 aSurf = new Geom_RectangularTrimmedSurface(aSurf, U1, U2, aV1Param, aV2Param);
634 isToTrim = Standard_False;
635 }
636 else
637 {
638 aV1Param = Max(aV1Param, V1);
639 aV2Param = Min(aV2Param, V2);
640 if (Abs(aV2Param - aV1Param) < Precision::PConfusion())
641 {
642 return Standard_False;
643 }
644 }
f04de133 645 aC3d = aSurf->UIso(theParam);
552a74d8 646 if (isToTrim)
647 aC3d = new Geom_TrimmedCurve(aC3d, aV1Param, aV2Param);
f04de133 648 }
649 else
650 {
552a74d8 651 Standard_Real aU1Param = Min(aF2d.X(), aL2d.X());
652 Standard_Real aU2Param = Max(aF2d.X(), aL2d.X());
653 if (aU2Param < U1 - myTol || aU1Param > U2 + myTol)
654 {
655 return Standard_False;
656 }
657 else if (Precision::IsInfinite(U1) || Precision::IsInfinite(U2))
658 {
659 if (Abs(aU2Param - aU1Param) < Precision::PConfusion())
660 {
661 return Standard_False;
662 }
663 aSurf = new Geom_RectangularTrimmedSurface(aSurf, aU1Param, aU2Param, V1, V2);
664 isToTrim = Standard_False;
665 }
666 else
667 {
668 aU1Param = Max(aU1Param, U1);
669 aU2Param = Min(aU2Param, U2);
670 if (Abs(aU2Param - aU1Param) < Precision::PConfusion())
671 {
672 return Standard_False;
673 }
674 }
f04de133 675 aC3d = aSurf->VIso(theParam);
552a74d8 676 if (isToTrim)
677 aC3d = new Geom_TrimmedCurve(aC3d, aU1Param, aU2Param);
f04de133 678 }
679
680 // Convert arbitrary curve type to the b-spline.
681 myCurve3d = GeomConvert::CurveToBSplineCurve(aC3d, Convert_QuasiAngular);
682 if (!theIsForward)
683 myCurve3d->Reverse();
684
685 // Rebuild parameterization for the 3d curve to have the same parameterization with
686 // a two-dimensional curve.
687 TColStd_Array1OfReal aKnots = myCurve3d->Knots();
688 BSplCLib::Reparametrize(theC2D->FirstParameter(), theC2D->LastParameter(), aKnots);
689 myCurve3d->SetKnots(aKnots);
690
691 // Evaluate error.
692 myError3d = 0.0;
693
694 const Standard_Real aParF = myFirst;
695 const Standard_Real aParL = myLast;
696 const Standard_Integer aNbPnt = 23;
697 for(Standard_Integer anIdx = 0; anIdx <= aNbPnt; ++anIdx)
698 {
699 const Standard_Real aPar = aParF + ((aParL - aParF) * anIdx) / aNbPnt;
700
701 const gp_Pnt2d aPnt2d = theC2D->Value(aPar);
702
703 const gp_Pnt aPntC3D = myCurve3d->Value(aPar);
704 const gp_Pnt aPntC2D = mySurf->Value(aPnt2d.X(), aPnt2d.Y());
705
706 const Standard_Real aSqDeviation = aPntC3D.SquareDistance(aPntC2D);
707 myError3d = Max(aSqDeviation, myError3d);
708 }
709
710 myError3d = Sqrt(myError3d);
711
712 // Target tolerance is not obtained. This situation happens for isolines on the sphere.
713 // OCCT is unable to convert it keeping original parameterization, while the geometric
714 // form of the result is entirely identical. In that case, it is better to utilize
715 // a general-purpose approach.
716 if (myError3d > myTol)
717 return Standard_False;
718
719 return Standard_True;
720}