1 // Created on: 1997-09-23
2 // Created by: Roman BORISOV
3 // Copyright (c) 1997-1999 Matra Datavision
4 // Copyright (c) 1999-2014 OPEN CASCADE SAS
6 // This file is part of Open CASCADE Technology software library.
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
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.
14 // Alternatively, this file may be used under the terms of Open CASCADE
15 // commercial license or contractual agreement.
20 #include <Adaptor2d_Curve2d.hxx>
21 #include <Adaptor3d_Curve.hxx>
22 #include <Adaptor3d_Surface.hxx>
23 #include <Extrema_ExtCS.hxx>
24 #include <Extrema_ExtPS.hxx>
25 #include <Extrema_GenLocateExtPS.hxx>
26 #include <Extrema_POnCurv.hxx>
27 #include <Extrema_POnSurf.hxx>
28 #include <GeomAbs_CurveType.hxx>
29 #include <GeomLib.hxx>
30 #include <gp_Mat2d.hxx>
31 #include <gp_Pnt2d.hxx>
32 #include <gp_Vec2d.hxx>
34 #include <Precision.hxx>
35 #include <ProjLib_CompProjectedCurve.hxx>
36 #include <ProjLib_HCompProjectedCurve.hxx>
37 #include <ProjLib_PrjResolve.hxx>
38 #include <Standard_DomainError.hxx>
39 #include <Standard_NoSuchObject.hxx>
40 #include <Standard_NotImplemented.hxx>
41 #include <Standard_OutOfRange.hxx>
42 #include <TColgp_HSequenceOfPnt.hxx>
43 #include <Adaptor3d_CurveOnSurface.hxx>
44 #include <Geom2d_Line.hxx>
45 #include <Geom2dAdaptor_Curve.hxx>
46 #include <Extrema_ExtCC.hxx>
47 #include <NCollection_Vector.hxx>
49 #define FuncTol 1.e-10
51 IMPLEMENT_STANDARD_RTTIEXT(ProjLib_CompProjectedCurve, Adaptor2d_Curve2d)
53 #ifdef OCCT_DEBUG_CHRONO
54 #include <OSD_Timer.hxx>
56 static OSD_Chronometer chr_init_point, chr_dicho_bound;
58 Standard_EXPORT Standard_Real t_init_point, t_dicho_bound;
59 Standard_EXPORT Standard_Integer init_point_count, dicho_bound_count;
61 static void InitChron(OSD_Chronometer& ch)
67 static void ResultChron( OSD_Chronometer & ch, Standard_Real & time)
76 // Structure to perform splits computation.
77 // This structure is not thread-safe since operations under mySplits should be performed in a critical section.
78 // myPeriodicDir - 0 for U periodicity and 1 for V periodicity.
81 SplitDS(const Handle(Adaptor3d_Curve) &theCurve,
82 const Handle(Adaptor3d_Surface) &theSurface,
83 NCollection_Vector<Standard_Real> &theSplits)
85 mySurface(theSurface),
91 myExtCCLast2DParam(0.0),
95 const Handle(Adaptor3d_Curve) myCurve;
96 const Handle(Adaptor3d_Surface) mySurface;
97 NCollection_Vector<Standard_Real> &mySplits;
99 Standard_Real myPerMinParam;
100 Standard_Real myPerMaxParam;
101 Standard_Integer myPeriodicDir;
103 Adaptor3d_CurveOnSurface* myExtCCCurve1;
104 Standard_Real myExtCCLast2DParam;
106 Extrema_ExtPS *myExtPS;
110 // Assignment operator is forbidden.
111 void operator=(const SplitDS &theSplitDS);
115 //! Compute split points in the parameter space of the curve.
116 static void BuildCurveSplits(const Handle(Adaptor3d_Curve) &theCurve,
117 const Handle(Adaptor3d_Surface) &theSurface,
118 const Standard_Real theTolU,
119 const Standard_Real theTolV,
120 NCollection_Vector<Standard_Real> &theSplits);
122 //! Perform splitting on a specified direction. Sub-method in BuildCurveSplits.
123 static void SplitOnDirection(SplitDS & theSplitDS);
125 //! Perform recursive search of the split points.
126 static void FindSplitPoint(SplitDS & theSplitDS,
127 const Standard_Real theMinParam,
128 const Standard_Real theMaxParam);
131 //=======================================================================
132 //function : Comparator
133 //purpose : used in sort algorithm
134 //=======================================================================
135 inline Standard_Boolean Comparator(const Standard_Real theA,
136 const Standard_Real theB)
141 //=======================================================================
143 //purpose : computes first derivative of the projected curve
144 //=======================================================================
146 static void d1(const Standard_Real t,
147 const Standard_Real u,
148 const Standard_Real v,
150 const Handle(Adaptor3d_Curve)& Curve,
151 const Handle(Adaptor3d_Surface)& Surface)
154 gp_Vec DS1_u, DS1_v, DS2_u, DS2_uv, DS2_v, DC1_t;
155 Surface->D2(u, v, S, DS1_u, DS1_v, DS2_u, DS2_v, DS2_uv);
156 Curve->D1(t, C, DC1_t);
157 gp_Vec Ort(C, S);// Ort = S - C
159 gp_Vec2d dE_dt(-DC1_t*DS1_u, -DC1_t*DS1_v);
160 gp_XY dE_du(DS1_u*DS1_u + Ort*DS2_u,
161 DS1_u*DS1_v + Ort*DS2_uv);
162 gp_XY dE_dv(DS1_v*DS1_u + Ort*DS2_uv,
163 DS1_v*DS1_v + Ort*DS2_v);
165 Standard_Real det = dE_du.X()*dE_dv.Y() - dE_du.Y()*dE_dv.X();
166 if (fabs(det) < gp::Resolution()) throw Standard_ConstructionError();
168 gp_Mat2d M(gp_XY(dE_dv.Y()/det, -dE_du.Y()/det),
169 gp_XY(-dE_dv.X()/det, dE_du.X()/det));
171 V = - gp_Vec2d(gp_Vec2d(M.Row(1))*dE_dt, gp_Vec2d(M.Row(2))*dE_dt);
174 //=======================================================================
176 //purpose : computes second derivative of the projected curve
177 //=======================================================================
179 static void d2(const Standard_Real t,
180 const Standard_Real u,
181 const Standard_Real v,
182 gp_Vec2d& V1, gp_Vec2d& V2,
183 const Handle(Adaptor3d_Curve)& Curve,
184 const Handle(Adaptor3d_Surface)& Surface)
187 gp_Vec DS1_u, DS1_v, DS2_u, DS2_uv, DS2_v,
188 DS3_u, DS3_v, DS3_uuv, DS3_uvv,
190 Surface->D3(u, v, S, DS1_u, DS1_v, DS2_u, DS2_v, DS2_uv,
191 DS3_u, DS3_v, DS3_uuv, DS3_uvv);
192 Curve->D2(t, C, DC1_t, DC2_t);
195 gp_Vec2d dE_dt(-DC1_t*DS1_u, -DC1_t*DS1_v);
196 gp_XY dE_du(DS1_u*DS1_u + Ort*DS2_u,
197 DS1_u*DS1_v + Ort*DS2_uv);
198 gp_XY dE_dv(DS1_v*DS1_u + Ort*DS2_uv,
199 DS1_v*DS1_v + Ort*DS2_v);
201 Standard_Real det = dE_du.X()*dE_dv.Y() - dE_du.Y()*dE_dv.X();
202 if (fabs(det) < gp::Resolution()) throw Standard_ConstructionError();
204 gp_Mat2d M(gp_XY(dE_dv.Y()/det, -dE_du.Y()/det),
205 gp_XY(-dE_dv.X()/det, dE_du.X()/det));
208 V1 = - gp_Vec2d(gp_Vec2d(M.Row(1))*dE_dt, gp_Vec2d(M.Row(2))*dE_dt);
210 /* Second derivative */
212 // Computation of d2E_dt2 = S1
213 gp_Vec2d d2E_dt(-DC2_t*DS1_u, -DC2_t*DS1_v);
215 // Computation of 2*(d2E/dtdX)(dX/dt) = S2
216 gp_Vec2d d2E1_dtdX(-DC1_t*DS2_u,
218 gp_Vec2d d2E2_dtdX(-DC1_t*DS2_uv,
220 gp_Vec2d S2 = 2*gp_Vec2d(d2E1_dtdX*V1, d2E2_dtdX*V1);
222 // Computation of (d2E/dX2)*(dX/dt)2 = S3
224 // Row11 = (d2E1/du2, d2E1/dudv)
226 gp_Vec2d Row11(3*DS1_u*DS2_u + Ort*DS3_u,
227 tmp = 2*DS1_u*DS2_uv +
228 DS1_v*DS2_u + Ort*DS3_uuv);
230 // Row12 = (d2E1/dudv, d2E1/dv2)
231 gp_Vec2d Row12(tmp, DS2_v*DS1_u + 2*DS1_v*DS2_uv +
234 // Row21 = (d2E2/du2, d2E2/dudv)
235 gp_Vec2d Row21(DS2_u*DS1_v + 2*DS1_u*DS2_uv + Ort*DS3_uuv,
236 tmp = 2*DS2_uv*DS1_v + DS1_u*DS2_v + Ort*DS3_uvv);
238 // Row22 = (d2E2/duv, d2E2/dvdv)
239 gp_Vec2d Row22(tmp, 3*DS1_v*DS2_v + Ort*DS3_v);
241 gp_Vec2d S3(V1*gp_Vec2d(Row11*V1, Row12*V1),
242 V1*gp_Vec2d(Row21*V1, Row22*V1));
244 gp_Vec2d Sum = d2E_dt + S2 + S3;
246 V2 = - gp_Vec2d(gp_Vec2d(M.Row(1))*Sum, gp_Vec2d(M.Row(2))*Sum);
248 //=======================================================================
249 //function : d1CurveOnSurf
250 //purpose : computes first derivative of the 3d projected curve
251 //=======================================================================
254 static void d1CurvOnSurf(const Standard_Real t,
255 const Standard_Real u,
256 const Standard_Real v,
258 const Handle(Adaptor3d_Curve)& Curve,
259 const Handle(Adaptor3d_Surface)& Surface)
263 gp_Vec DS1_u, DS1_v, DS2_u, DS2_uv, DS2_v, DC1_t;
264 Surface->D2(u, v, S, DS1_u, DS1_v, DS2_u, DS2_v, DS2_uv);
265 Curve->D1(t, C, DC1_t);
266 gp_Vec Ort(C, S);// Ort = S - C
268 gp_Vec2d dE_dt(-DC1_t*DS1_u, -DC1_t*DS1_v);
269 gp_XY dE_du(DS1_u*DS1_u + Ort*DS2_u,
270 DS1_u*DS1_v + Ort*DS2_uv);
271 gp_XY dE_dv(DS1_v*DS1_u + Ort*DS2_uv,
272 DS1_v*DS1_v + Ort*DS2_v);
274 Standard_Real det = dE_du.X()*dE_dv.Y() - dE_du.Y()*dE_dv.X();
275 if (fabs(det) < gp::Resolution()) throw Standard_ConstructionError();
277 gp_Mat2d M(gp_XY(dE_dv.Y()/det, -dE_du.Y()/det),
278 gp_XY(-dE_dv.X()/det, dE_du.X()/det));
280 V2d = - gp_Vec2d(gp_Vec2d(M.Row(1))*dE_dt, gp_Vec2d(M.Row(2))*dE_dt);
282 V = DS1_u * V2d.X() + DS1_v * V2d.Y();
287 //=======================================================================
288 //function : d2CurveOnSurf
289 //purpose : computes second derivative of the 3D projected curve
290 //=======================================================================
292 static void d2CurvOnSurf(const Standard_Real t,
293 const Standard_Real u,
294 const Standard_Real v,
295 gp_Vec& V1 , gp_Vec& V2 ,
296 const Handle(Adaptor3d_Curve)& Curve,
297 const Handle(Adaptor3d_Surface)& Surface)
301 gp_Vec DS1_u, DS1_v, DS2_u, DS2_uv, DS2_v,
302 DS3_u, DS3_v, DS3_uuv, DS3_uvv,
304 Surface->D3(u, v, S, DS1_u, DS1_v, DS2_u, DS2_v, DS2_uv,
305 DS3_u, DS3_v, DS3_uuv, DS3_uvv);
306 Curve->D2(t, C, DC1_t, DC2_t);
309 gp_Vec2d dE_dt(-DC1_t*DS1_u, -DC1_t*DS1_v);
310 gp_XY dE_du(DS1_u*DS1_u + Ort*DS2_u,
311 DS1_u*DS1_v + Ort*DS2_uv);
312 gp_XY dE_dv(DS1_v*DS1_u + Ort*DS2_uv,
313 DS1_v*DS1_v + Ort*DS2_v);
315 Standard_Real det = dE_du.X()*dE_dv.Y() - dE_du.Y()*dE_dv.X();
316 if (fabs(det) < gp::Resolution()) throw Standard_ConstructionError();
318 gp_Mat2d M(gp_XY(dE_dv.Y()/det, -dE_du.Y()/det),
319 gp_XY(-dE_dv.X()/det, dE_du.X()/det));
322 V12d = - gp_Vec2d(gp_Vec2d(M.Row(1))*dE_dt, gp_Vec2d(M.Row(2))*dE_dt);
324 /* Second derivative */
326 // Computation of d2E_dt2 = S1
327 gp_Vec2d d2E_dt(-DC2_t*DS1_u, -DC2_t*DS1_v);
329 // Computation of 2*(d2E/dtdX)(dX/dt) = S2
330 gp_Vec2d d2E1_dtdX(-DC1_t*DS2_u,
332 gp_Vec2d d2E2_dtdX(-DC1_t*DS2_uv,
334 gp_Vec2d S2 = 2*gp_Vec2d(d2E1_dtdX*V12d, d2E2_dtdX*V12d);
336 // Computation of (d2E/dX2)*(dX/dt)2 = S3
338 // Row11 = (d2E1/du2, d2E1/dudv)
340 gp_Vec2d Row11(3*DS1_u*DS2_u + Ort*DS3_u,
341 tmp = 2*DS1_u*DS2_uv +
342 DS1_v*DS2_u + Ort*DS3_uuv);
344 // Row12 = (d2E1/dudv, d2E1/dv2)
345 gp_Vec2d Row12(tmp, DS2_v*DS1_u + 2*DS1_v*DS2_uv +
348 // Row21 = (d2E2/du2, d2E2/dudv)
349 gp_Vec2d Row21(DS2_u*DS1_v + 2*DS1_u*DS2_uv + Ort*DS3_uuv,
350 tmp = 2*DS2_uv*DS1_v + DS1_u*DS2_v + Ort*DS3_uvv);
352 // Row22 = (d2E2/duv, d2E2/dvdv)
353 gp_Vec2d Row22(tmp, 3*DS1_v*DS2_v + Ort*DS3_v);
355 gp_Vec2d S3(V12d*gp_Vec2d(Row11*V12d, Row12*V12d),
356 V12d*gp_Vec2d(Row21*V12d, Row22*V12d));
358 gp_Vec2d Sum = d2E_dt + S2 + S3;
360 V22d = - gp_Vec2d(gp_Vec2d(M.Row(1))*Sum, gp_Vec2d(M.Row(2))*Sum);
362 V1 = DS1_u * V12d.X() + DS1_v * V12d.Y();
363 V2 = DS2_u * V12d.X() *V12d.X()
365 + 2 * DS2_uv * V12d.X() *V12d.Y()
366 + DS2_v * V12d.Y() * V12d.Y()
370 //=======================================================================
371 //function : ExactBound
372 //purpose : computes exact boundary point
373 //=======================================================================
375 static Standard_Boolean ExactBound(gp_Pnt& Sol,
376 const Standard_Real NotSol,
377 const Standard_Real Tol,
378 const Standard_Real TolU,
379 const Standard_Real TolV,
380 const Handle(Adaptor3d_Curve)& Curve,
381 const Handle(Adaptor3d_Surface)& Surface)
383 Standard_Real U0, V0, t, t1, t2, FirstU, LastU, FirstV, LastV;
387 FirstU = Surface->FirstUParameter();
388 LastU = Surface->LastUParameter();
389 FirstV = Surface->FirstVParameter();
390 LastV = Surface->LastVParameter();
391 // Here we have to compute the boundary that projection is going to intersect
393 //these variables are to estimate which boundary has more apportunity
395 Standard_Real RU1, RU2, RV1, RV2;
396 d1(Sol.X(), U0, V0, D2d, Curve, Surface);
397 // Here we assume that D2d != (0, 0)
398 if(Abs(D2d.X()) < gp::Resolution())
400 RU1 = Precision::Infinite();
401 RU2 = Precision::Infinite();
405 else if(Abs(D2d.Y()) < gp::Resolution())
409 RV1 = Precision::Infinite();
410 RV2 = Precision::Infinite();
414 RU1 = gp_Pnt2d(U0, V0).
415 Distance(gp_Pnt2d(FirstU, V0 + (FirstU - U0)*D2d.Y()/D2d.X()));
416 RU2 = gp_Pnt2d(U0, V0).
417 Distance(gp_Pnt2d(LastU, V0 + (LastU - U0)*D2d.Y()/D2d.X()));
418 RV1 = gp_Pnt2d(U0, V0).
419 Distance(gp_Pnt2d(U0 + (FirstV - V0)*D2d.X()/D2d.Y(), FirstV));
420 RV2 = gp_Pnt2d(U0, V0).
421 Distance(gp_Pnt2d(U0 + (LastV - V0)*D2d.X()/D2d.Y(), LastV));
423 TColgp_SequenceOfPnt Seq;
424 Seq.Append(gp_Pnt(FirstU, RU1, 2));
425 Seq.Append(gp_Pnt(LastU, RU2, 2));
426 Seq.Append(gp_Pnt(FirstV, RV1, 3));
427 Seq.Append(gp_Pnt(LastV, RV2, 3));
428 Standard_Integer i, j;
429 for(i = 1; i <= 3; i++)
431 for(j = 1; j <= 4-i; j++)
433 if(Seq(j).Y() < Seq(j+1).Y())
436 swp = Seq.Value(j+1);
437 Seq.ChangeValue(j+1) = Seq.Value(j);
438 Seq.ChangeValue(j) = swp;
444 t1 = Min (Sol.X (), NotSol);
445 t2 = Max (Sol.X (), NotSol);
447 Standard_Boolean isDone = Standard_False;
448 while (!Seq.IsEmpty ())
452 Seq.Remove (Seq.Length ());
453 ProjLib_PrjResolve aPrjPS (*Curve, *Surface, Standard_Integer (P.Z ()));
454 if (Standard_Integer (P.Z ()) == 2)
456 aPrjPS.Perform (t, P.X (), V0, gp_Pnt2d (Tol, TolV),
457 gp_Pnt2d (t1, Surface->FirstVParameter ()),
458 gp_Pnt2d (t2, Surface->LastVParameter ()), FuncTol);
459 if (!aPrjPS.IsDone ()) continue;
460 POnS = aPrjPS.Solution ();
461 Sol = gp_Pnt (POnS.X (), P.X (), POnS.Y ());
462 isDone = Standard_True;
467 aPrjPS.Perform (t, U0, P.X (), gp_Pnt2d (Tol, TolU),
468 gp_Pnt2d (t1, Surface->FirstUParameter ()),
469 gp_Pnt2d (t2, Surface->LastUParameter ()), FuncTol);
470 if (!aPrjPS.IsDone ()) continue;
471 POnS = aPrjPS.Solution ();
472 Sol = gp_Pnt (POnS.X (), POnS.Y (), P.X ());
473 isDone = Standard_True;
481 //=======================================================================
482 //function : DichExactBound
483 //purpose : computes exact boundary point
484 //=======================================================================
486 static void DichExactBound(gp_Pnt& Sol,
487 const Standard_Real NotSol,
488 const Standard_Real Tol,
489 const Standard_Real TolU,
490 const Standard_Real TolV,
491 const Handle(Adaptor3d_Curve)& Curve,
492 const Handle(Adaptor3d_Surface)& Surface)
494 #ifdef OCCT_DEBUG_CHRONO
495 InitChron(chr_dicho_bound);
498 Standard_Real U0, V0, t;
502 ProjLib_PrjResolve aPrjPS (*Curve, *Surface, 1);
504 Standard_Real aNotSol = NotSol;
505 while (fabs(Sol.X() - aNotSol) > Tol)
507 t = (Sol.X() + aNotSol)/2;
508 aPrjPS.Perform(t, U0, V0, gp_Pnt2d(TolU, TolV),
509 gp_Pnt2d(Surface->FirstUParameter(),Surface->FirstVParameter()),
510 gp_Pnt2d(Surface->LastUParameter(),Surface->LastVParameter()),
511 FuncTol, Standard_True);
515 POnS = aPrjPS.Solution();
516 Sol = gp_Pnt(t, POnS.X(), POnS.Y());
522 #ifdef OCCT_DEBUG_CHRONO
523 ResultChron(chr_dicho_bound,t_dicho_bound);
528 //=======================================================================
529 //function : InitialPoint
531 //=======================================================================
533 static Standard_Boolean InitialPoint(const gp_Pnt& Point,
534 const Standard_Real t,
535 const Handle(Adaptor3d_Curve)& C,
536 const Handle(Adaptor3d_Surface)& S,
537 const Standard_Real TolU,
538 const Standard_Real TolV,
543 ProjLib_PrjResolve aPrjPS (*C, *S, 1);
544 Standard_Real ParU,ParV;
545 Extrema_ExtPS aExtPS;
546 aExtPS.Initialize (*S, S->FirstUParameter(),
547 S->LastUParameter(), S->FirstVParameter(),
548 S->LastVParameter(), TolU, TolV);
550 aExtPS.Perform(Point);
551 Standard_Integer argmin = 0;
552 if (aExtPS.IsDone() && aExtPS.NbExt())
554 Standard_Integer i, Nend;
555 // Search for the nearest solution which is also a normal projection
556 Nend = aExtPS.NbExt();
557 for(i = 1; i <= Nend; i++)
559 Extrema_POnSurf POnS = aExtPS.Point(i);
560 POnS.Parameter(ParU, ParV);
561 aPrjPS.Perform(t, ParU, ParV, gp_Pnt2d(TolU, TolV),
562 gp_Pnt2d(S->FirstUParameter(), S->FirstVParameter()),
563 gp_Pnt2d(S->LastUParameter(), S->LastVParameter()),
564 FuncTol, Standard_True);
566 if (argmin == 0 || aExtPS.SquareDistance(i) < aExtPS.SquareDistance(argmin)) argmin = i;
569 if( argmin == 0 ) return Standard_False;
572 Extrema_POnSurf POnS = aExtPS.Point(argmin);
573 POnS.Parameter(U, V);
574 return Standard_True;
578 //=======================================================================
579 //function : ProjLib_CompProjectedCurve
581 //=======================================================================
583 ProjLib_CompProjectedCurve::ProjLib_CompProjectedCurve()
591 //=======================================================================
592 //function : ProjLib_CompProjectedCurve
594 //=======================================================================
596 ProjLib_CompProjectedCurve::ProjLib_CompProjectedCurve
597 (const Handle(Adaptor3d_Surface)& theSurface,
598 const Handle(Adaptor3d_Curve)& theCurve,
599 const Standard_Real theTolU,
600 const Standard_Real theTolV)
601 : mySurface (theSurface),
604 mySequence(new ProjLib_HSequenceOfHSequenceOfPnt()),
612 //=======================================================================
613 //function : ProjLib_CompProjectedCurve
615 //=======================================================================
617 ProjLib_CompProjectedCurve::ProjLib_CompProjectedCurve
618 (const Handle(Adaptor3d_Surface)& theSurface,
619 const Handle(Adaptor3d_Curve)& theCurve,
620 const Standard_Real theTolU,
621 const Standard_Real theTolV,
622 const Standard_Real theMaxDist)
623 : mySurface (theSurface),
626 mySequence(new ProjLib_HSequenceOfHSequenceOfPnt()),
629 myMaxDist (theMaxDist)
634 //=======================================================================
635 //function : ShallowCopy
637 //=======================================================================
639 Handle(Adaptor2d_Curve2d) ProjLib_CompProjectedCurve::ShallowCopy() const
641 Handle(ProjLib_CompProjectedCurve) aCopy = new ProjLib_CompProjectedCurve();
643 if (!mySurface.IsNull())
645 aCopy->mySurface = mySurface->ShallowCopy();
647 if (!myCurve.IsNull())
649 aCopy->myCurve = myCurve->ShallowCopy();
651 aCopy->myNbCurves = myNbCurves;
652 aCopy->mySequence = mySequence;
653 aCopy->myTolU = myTolU;
654 aCopy->myTolV = myTolV;
655 aCopy->myMaxDist = myMaxDist;
656 aCopy->myUIso = myUIso;
657 aCopy->myVIso = myVIso;
658 aCopy->mySnglPnts = mySnglPnts;
659 aCopy->myMaxDistance = myMaxDistance;
664 //=======================================================================
667 //=======================================================================
669 void ProjLib_CompProjectedCurve::Init()
672 NCollection_Vector<Standard_Real> aSplits;
675 Standard_Real Tol;// Tolerance for ExactBound
676 Standard_Integer i, Nend = 0, aSplitIdx = 0;
677 Standard_Boolean FromLastU = Standard_False,
678 isSplitsComputed = Standard_False;
680 const Standard_Real aTolExt = Precision::PConfusion();
681 Extrema_ExtCS CExt (*myCurve, *mySurface, aTolExt, aTolExt);
682 if (CExt.IsDone() && CExt.NbExt())
684 // Search for the minimum solution.
685 // Avoid usage of extrema result that can be wrong for extrusion.
688 mySurface->GetType() != GeomAbs_SurfaceOfExtrusion)
690 Standard_Real min_val2;
691 min_val2 = CExt.SquareDistance(1);
694 for(i = 2; i <= Nend; i++)
696 if (CExt.SquareDistance(i) < min_val2)
697 min_val2 = CExt.SquareDistance(i);
699 if (min_val2 > myMaxDist * myMaxDist)
700 return; // No near solution -> exit.
704 Standard_Real FirstU, LastU, Step, SearchStep, WalkStep, t;
706 FirstU = myCurve->FirstParameter();
707 LastU = myCurve->LastParameter();
708 const Standard_Real GlobalMinStep = 1.e-4;
709 //<GlobalMinStep> is sufficiently small to provide solving from initial point
710 //and, on the other hand, it is sufficiently large to avoid too close solutions.
711 const Standard_Real MinStep = 0.01*(LastU - FirstU),
712 MaxStep = 0.1*(LastU - FirstU);
713 SearchStep = 10*MinStep;
716 gp_Pnt2d aLowBorder(mySurface->FirstUParameter(),mySurface->FirstVParameter());
717 gp_Pnt2d aUppBorder(mySurface->LastUParameter(), mySurface->LastVParameter());
718 gp_Pnt2d aTol(myTolU, myTolV);
719 ProjLib_PrjResolve aPrjPS (*myCurve, *mySurface, 1);
722 Standard_Boolean new_part;
723 Standard_Real prevDeb=0.;
724 Standard_Boolean SameDeb=Standard_False;
727 gp_Pnt Triple, prevTriple;
732 // Search for the beginning of a new continuous part
733 // to avoid infinite computation in some difficult cases.
734 new_part = Standard_False;
735 if(t > FirstU && Abs(t-prevDeb) <= Precision::PConfusion()) SameDeb=Standard_True;
736 while(t <= LastU && !new_part && !FromLastU && !SameDeb)
739 if (t == LastU) FromLastU=Standard_True;
740 Standard_Boolean initpoint=Standard_False;
741 Standard_Real U = 0., V = 0.;
743 Standard_Real ParT,ParU,ParV;
745 // Search an initial point in the list of Extrema Curve-Surface
746 if(Nend != 0 && !CExt.IsParallel())
748 for (i=1;i<=Nend;i++)
752 CExt.Points(i,P1,P2);
754 P2.Parameter(ParU, ParV);
756 aPrjPS.Perform(ParT, ParU, ParV, aTol, aLowBorder, aUppBorder, FuncTol, Standard_True);
758 if ( aPrjPS.IsDone() && P1.Parameter() > Max(FirstU,t-Step+Precision::PConfusion())
759 && P1.Parameter() <= t)
765 initpoint = Standard_True;
772 myCurve->D0(t,CPoint);
773 #ifdef OCCT_DEBUG_CHRONO
774 InitChron(chr_init_point);
776 // PConfusion - use geometric tolerances in extrema / optimization.
777 initpoint=InitialPoint(CPoint, t,myCurve,mySurface, Precision::PConfusion(), Precision::PConfusion(), U, V);
778 #ifdef OCCT_DEBUG_CHRONO
779 ResultChron(chr_init_point,t_init_point);
785 // When U or V lie on surface joint in some cases we cannot use them
786 // as initial point for aPrjPS, so we switch them
789 if ((mySurface->IsUPeriodic() &&
790 Abs(aUppBorder.X() - aLowBorder.X() - mySurface->UPeriod()) < Precision::Confusion()) ||
791 (mySurface->IsVPeriodic() &&
792 Abs(aUppBorder.Y() - aLowBorder.Y() - mySurface->VPeriod()) < Precision::Confusion()))
794 if((Abs(U - aLowBorder.X()) < mySurface->UResolution(Precision::PConfusion())) &&
795 mySurface->IsUPeriodic())
797 d1(t, U, V, D, myCurve, mySurface);
798 if (D.X() < 0 ) U = aUppBorder.X();
800 else if((Abs(U - aUppBorder.X()) < mySurface->UResolution(Precision::PConfusion())) &&
801 mySurface->IsUPeriodic())
803 d1(t, U, V, D, myCurve, mySurface);
804 if (D.X() > 0) U = aLowBorder.X();
807 if((Abs(V - aLowBorder.Y()) < mySurface->VResolution(Precision::PConfusion())) &&
808 mySurface->IsVPeriodic())
810 d1(t, U, V, D, myCurve, mySurface);
811 if (D.Y() < 0) V = aUppBorder.Y();
813 else if((Abs(V - aUppBorder.Y()) <= mySurface->VResolution(Precision::PConfusion())) &&
814 mySurface->IsVPeriodic())
816 d1(t, U, V, D, myCurve, mySurface);
817 if (D.Y() > 0) V = aLowBorder.Y();
823 // Here we are going to stop if the distance between projection and
824 // corresponding curve point is greater than myMaxDist
827 mySurface->D0(U, V, POnS);
828 d = CPoint.Distance(POnS);
836 Triple = gp_Pnt(t, U, V);
839 //Search for exact boundary point
840 Tol = Min(myTolU, myTolV);
842 d1(Triple.X(), Triple.Y(), Triple.Z(), aD, myCurve, mySurface);
843 Tol /= Max(Abs(aD.X()), Abs(aD.Y()));
845 if(!ExactBound(Triple, t - Step, Tol,
846 myTolU, myTolV, myCurve, mySurface))
849 std::cout<<"There is a problem with ExactBound computation"<<std::endl;
851 DichExactBound(Triple, t - Step, Tol, myTolU, myTolV,
855 new_part = Standard_True;
859 if(t == LastU) break;
868 if (!new_part) break;
870 //We have found a new continuous part
871 Handle(TColgp_HSequenceOfPnt) hSeq = new TColgp_HSequenceOfPnt();
872 mySequence->Append(hSeq);
874 mySequence->Value(myNbCurves)->Append(Triple);
877 if (Triple.X() == LastU) break;//return;
879 //Computation of WalkStep
881 Standard_Real MagnD1, MagnD2;
882 d2CurvOnSurf(Triple.X(), Triple.Y(), Triple.Z(), D1, D2, myCurve, mySurface);
883 MagnD1 = D1.Magnitude();
884 MagnD2 = D2.Magnitude();
885 if(MagnD2 < Precision::Confusion()) WalkStep = MaxStep;
886 else WalkStep = Min(MaxStep, Max(MinStep, 0.1*MagnD1/MagnD2));
890 t = Triple.X() + Step;
891 if (t > LastU) t = LastU;
892 Standard_Real prevStep = Step;
893 Standard_Real U0, V0;
895 //Here we are trying to prolong continuous part
896 while (t <= LastU && new_part)
899 U0 = Triple.Y() + (Step / prevStep) * (Triple.Y() - prevTriple.Y());
900 V0 = Triple.Z() + (Step / prevStep) * (Triple.Z() - prevTriple.Z());
901 // adjust U0 to be in [mySurface->FirstUParameter(),mySurface->LastUParameter()]
902 U0 = Min(Max(U0, aLowBorder.X()), aUppBorder.X());
903 // adjust V0 to be in [mySurface->FirstVParameter(),mySurface->LastVParameter()]
904 V0 = Min(Max(V0, aLowBorder.Y()), aUppBorder.Y());
907 aPrjPS.Perform(t, U0, V0, aTol,
908 aLowBorder, aUppBorder, FuncTol, Standard_True);
911 if (Step <= GlobalMinStep)
913 //Search for exact boundary point
914 Tol = Min(myTolU, myTolV);
916 d1(Triple.X(), Triple.Y(), Triple.Z(), D, myCurve, mySurface);
917 Tol /= Max(Abs(D.X()), Abs(D.Y()));
919 if(!ExactBound(Triple, t, Tol, myTolU, myTolV,
923 std::cout<<"There is a problem with ExactBound computation"<<std::endl;
925 DichExactBound(Triple, t, Tol, myTolU, myTolV,
929 if((Triple.X() - mySequence->Value(myNbCurves)->Value(mySequence->Value(myNbCurves)->Length()).X()) > 1.e-10)
930 mySequence->Value(myNbCurves)->Append(Triple);
931 if((LastU - Triple.X()) < Tol) {t = LastU + 1; break;}//return;
934 t = Triple.X() + Step;
935 if (t > (LastU-MinStep/2) )
940 new_part = Standard_False;
945 Standard_Real SaveStep = Step;
947 t = Triple .X() + Step;
948 if (t > (LastU-MinStep/4) )
951 if (Abs(Step - SaveStep) <= Precision::PConfusion())
952 Step = GlobalMinStep; //to avoid looping
962 Triple = gp_Pnt(t, aPrjPS.Solution().X(), aPrjPS.Solution().Y());
964 // Check for possible local traps.
965 UpdateTripleByTrapCriteria(Triple);
967 // Protection from case when the whole curve lies on a seam.
968 if (!isSplitsComputed)
970 Standard_Boolean isUPossible = Standard_False;
971 if (mySurface->IsUPeriodic() &&
972 (Abs(Triple.Y() - mySurface->FirstUParameter() ) > Precision::PConfusion() &&
973 Abs(Triple.Y() - mySurface->LastUParameter() ) > Precision::PConfusion()))
975 isUPossible = Standard_True;
978 Standard_Boolean isVPossible = Standard_False;
979 if (mySurface->IsVPeriodic() &&
980 (Abs(Triple.Z() - mySurface->FirstVParameter() ) > Precision::PConfusion() &&
981 Abs(Triple.Z() - mySurface->LastVParameter() ) > Precision::PConfusion()))
983 isVPossible = Standard_True;
986 if (isUPossible || isVPossible)
988 // When point is good conditioned.
989 BuildCurveSplits(myCurve, mySurface, myTolU, myTolV, aSplits);
990 isSplitsComputed = Standard_True;
994 if((Triple.X() - mySequence->Value(myNbCurves)->Value(mySequence->Value(myNbCurves)->Length()).X()) > 1.e-10)
995 mySequence->Value(myNbCurves)->Append(Triple);
996 if (t == LastU) {t = LastU + 1; break;}//return;
997 //Computation of WalkStep
998 d2CurvOnSurf(Triple.X(), Triple.Y(), Triple.Z(), D1, D2, myCurve, mySurface);
999 MagnD1 = D1.Magnitude();
1000 MagnD2 = D2.Magnitude();
1001 if(MagnD2 < Precision::Confusion() ) WalkStep = MaxStep;
1002 else WalkStep = Min(MaxStep, Max(MinStep, 0.1*MagnD1/MagnD2));
1006 if (t > (LastU-MinStep/2))
1008 Step = Step + LastU - t;
1012 // We assume at least one point of cache inside of a split.
1013 const Standard_Integer aSize = aSplits.Size();
1014 for(Standard_Integer anIdx = aSplitIdx; anIdx < aSize; ++anIdx)
1016 const Standard_Real aParam = aSplits(anIdx);
1017 if (Abs(aParam - Triple.X() ) < Precision::PConfusion())
1019 // The current point is equal to a split point.
1020 new_part = Standard_False;
1022 // Move split index to avoid check of the whole list.
1026 else if (aParam < t + Precision::PConfusion() )
1028 // The next point crosses the split point.
1030 Step = t - prevTriple.X();
1032 } // for(Standard_Integer anIdx = aSplitIdx; anIdx < aSize; ++anIdx)
1037 // Sequence post-proceeding.
1040 // 1. Removing poor parts
1041 Standard_Integer NbPart=myNbCurves;
1042 Standard_Integer ipart=1;
1043 for(i = 1; i <= NbPart; i++) {
1044 // Standard_Integer NbPoints = mySequence->Value(i)->Length();
1045 if(mySequence->Value(ipart)->Length() < 2) {
1046 mySequence->Remove(ipart);
1052 if(myNbCurves == 0) return;
1054 // 2. Removing common parts of bounds
1055 for(i = 1; i < myNbCurves; i++)
1057 if(mySequence->Value(i)->Value(mySequence->Value(i)->Length()).X() >=
1058 mySequence->Value(i+1)->Value(1).X())
1060 mySequence->ChangeValue(i+1)->ChangeValue(1).SetX(mySequence->Value(i)->Value(mySequence->Value(i)->Length()).X() + 1.e-12);
1064 // 3. Computation of the maximum distance from each part of curve to surface
1066 myMaxDistance = new TColStd_HArray1OfReal(1, myNbCurves);
1067 myMaxDistance->Init(0);
1068 for(i = 1; i <= myNbCurves; i++)
1070 for(j = 1; j <= mySequence->Value(i)->Length(); j++)
1072 gp_Pnt POnC, POnS, aTriple;
1073 Standard_Real Distance;
1074 aTriple = mySequence->Value(i)->Value(j);
1075 myCurve->D0(aTriple.X(), POnC);
1076 mySurface->D0(aTriple.Y(), aTriple.Z(), POnS);
1077 Distance = POnC.Distance(POnS);
1078 if (myMaxDistance->Value(i) < Distance)
1080 myMaxDistance->ChangeValue(i) = Distance;
1085 // 4. Check the projection to be a single point
1087 gp_Pnt2d Pmoy, Pcurr, P;
1088 Standard_Real AveU, AveV;
1089 mySnglPnts = new TColStd_HArray1OfBoolean(1, myNbCurves);
1090 mySnglPnts->Init (Standard_True);
1092 for(i = 1; i <= myNbCurves; i++)
1094 //compute an average U and V
1096 for(j = 1, AveU = 0., AveV = 0.; j <= mySequence->Value(i)->Length(); j++)
1098 AveU += mySequence->Value(i)->Value(j).Y();
1099 AveV += mySequence->Value(i)->Value(j).Z();
1101 AveU /= mySequence->Value(i)->Length();
1102 AveV /= mySequence->Value(i)->Length();
1104 Pmoy.SetCoord(AveU,AveV);
1105 for(j = 1; j <= mySequence->Value(i)->Length(); j++)
1108 gp_Pnt2d(mySequence->Value(i)->Value(j).Y(), mySequence->Value(i)->Value(j).Z());
1109 if (Pcurr.Distance(Pmoy) > ((myTolU < myTolV) ? myTolV : myTolU))
1111 mySnglPnts->SetValue(i, Standard_False);
1117 // 5. Check the projection to be an isoparametric curve of the surface
1119 myUIso = new TColStd_HArray1OfBoolean(1, myNbCurves);
1120 myUIso->Init (Standard_True);
1122 myVIso = new TColStd_HArray1OfBoolean(1, myNbCurves);
1123 myVIso->Init (Standard_True);
1125 for(i = 1; i <= myNbCurves; i++) {
1126 if (IsSinglePnt(i, P)|| mySequence->Value(i)->Length() <=2) {
1127 myUIso->SetValue(i, Standard_False);
1128 myVIso->SetValue(i, Standard_False);
1132 // new test for isoparametrics
1134 if ( mySequence->Value(i)->Length() > 2) {
1135 //compute an average U and V
1137 for(j = 1, AveU = 0., AveV = 0.; j <= mySequence->Value(i)->Length(); j++) {
1138 AveU += mySequence->Value(i)->Value(j).Y();
1139 AveV += mySequence->Value(i)->Value(j).Z();
1141 AveU /= mySequence->Value(i)->Length();
1142 AveV /= mySequence->Value(i)->Length();
1144 // is i-part U-isoparametric ?
1145 for(j = 1; j <= mySequence->Value(i)->Length(); j++)
1147 if(Abs(mySequence->Value(i)->Value(j).Y() - AveU) > myTolU)
1149 myUIso->SetValue(i, Standard_False);
1154 // is i-part V-isoparametric ?
1155 for(j = 1; j <= mySequence->Value(i)->Length(); j++)
1157 if(Abs(mySequence->Value(i)->Value(j).Z() - AveV) > myTolV)
1159 myVIso->SetValue(i, Standard_False);
1167 //=======================================================================
1170 //=======================================================================
1172 void ProjLib_CompProjectedCurve::Load(const Handle(Adaptor3d_Surface)& S)
1177 //=======================================================================
1180 //=======================================================================
1182 void ProjLib_CompProjectedCurve::Load(const Handle(Adaptor3d_Curve)& C)
1187 //=======================================================================
1188 //function : GetSurface
1190 //=======================================================================
1192 const Handle(Adaptor3d_Surface)& ProjLib_CompProjectedCurve::GetSurface() const
1198 //=======================================================================
1199 //function : GetCurve
1201 //=======================================================================
1203 const Handle(Adaptor3d_Curve)& ProjLib_CompProjectedCurve::GetCurve() const
1208 //=======================================================================
1209 //function : GetTolerance
1211 //=======================================================================
1213 void ProjLib_CompProjectedCurve::GetTolerance(Standard_Real& TolU,
1214 Standard_Real& TolV) const
1220 //=======================================================================
1221 //function : NbCurves
1223 //=======================================================================
1225 Standard_Integer ProjLib_CompProjectedCurve::NbCurves() const
1229 //=======================================================================
1232 //=======================================================================
1234 void ProjLib_CompProjectedCurve::Bounds(const Standard_Integer Index,
1235 Standard_Real& Udeb,
1236 Standard_Real& Ufin) const
1238 if(Index < 1 || Index > myNbCurves) throw Standard_NoSuchObject();
1239 Udeb = mySequence->Value(Index)->Value(1).X();
1240 Ufin = mySequence->Value(Index)->Value(mySequence->Value(Index)->Length()).X();
1242 //=======================================================================
1243 //function : IsSinglePnt
1245 //=======================================================================
1247 Standard_Boolean ProjLib_CompProjectedCurve::IsSinglePnt(const Standard_Integer Index, gp_Pnt2d& P) const
1249 if(Index < 1 || Index > myNbCurves) throw Standard_NoSuchObject();
1250 P = gp_Pnt2d(mySequence->Value(Index)->Value(1).Y(), mySequence->Value(Index)->Value(1).Z());
1251 return mySnglPnts->Value(Index);
1254 //=======================================================================
1257 //=======================================================================
1259 Standard_Boolean ProjLib_CompProjectedCurve::IsUIso(const Standard_Integer Index, Standard_Real& U) const
1261 if(Index < 1 || Index > myNbCurves) throw Standard_NoSuchObject();
1262 U = mySequence->Value(Index)->Value(1).Y();
1263 return myUIso->Value(Index);
1265 //=======================================================================
1268 //=======================================================================
1270 Standard_Boolean ProjLib_CompProjectedCurve::IsVIso(const Standard_Integer Index, Standard_Real& V) const
1272 if(Index < 1 || Index > myNbCurves) throw Standard_NoSuchObject();
1273 V = mySequence->Value(Index)->Value(1).Z();
1274 return myVIso->Value(Index);
1276 //=======================================================================
1279 //=======================================================================
1281 gp_Pnt2d ProjLib_CompProjectedCurve::Value(const Standard_Real t) const
1287 //=======================================================================
1290 //=======================================================================
1292 void ProjLib_CompProjectedCurve::D0(const Standard_Real U,gp_Pnt2d& P) const
1294 Standard_Integer i, j;
1295 Standard_Real Udeb, Ufin;
1296 Standard_Boolean found = Standard_False;
1298 for(i = 1; i <= myNbCurves; i++)
1300 Bounds(i, Udeb, Ufin);
1301 if (U >= Udeb && U <= Ufin)
1303 found = Standard_True;
1309 throw Standard_DomainError("ProjLib_CompProjectedCurve::D0");
1312 Standard_Real U0, V0;
1314 Standard_Integer End = mySequence->Value(i)->Length();
1315 for(j = 1; j < End; j++)
1316 if ((U >= mySequence->Value(i)->Value(j).X()) && (U <= mySequence->Value(i)->Value(j + 1).X())) break;
1318 // U0 = mySequence->Value(i)->Value(j).Y();
1319 // V0 = mySequence->Value(i)->Value(j).Z();
1321 // Cubic Interpolation
1322 if(mySequence->Value(i)->Length() < 4 ||
1323 (Abs(U-mySequence->Value(i)->Value(j).X()) <= Precision::PConfusion()) )
1325 U0 = mySequence->Value(i)->Value(j).Y();
1326 V0 = mySequence->Value(i)->Value(j).Z();
1328 else if (Abs(U-mySequence->Value(i)->Value(j+1).X())
1329 <= Precision::PConfusion())
1331 U0 = mySequence->Value(i)->Value(j+1).Y();
1332 V0 = mySequence->Value(i)->Value(j+1).Z();
1337 if (j > mySequence->Value(i)->Length() - 2)
1338 j = mySequence->Value(i)->Length() - 2;
1340 gp_Vec2d I1, I2, I3, I21, I22, I31, Y1, Y2, Y3, Y4, Res;
1341 Standard_Real X1, X2, X3, X4;
1343 X1 = mySequence->Value(i)->Value(j - 1).X();
1344 X2 = mySequence->Value(i)->Value(j).X();
1345 X3 = mySequence->Value(i)->Value(j + 1).X();
1346 X4 = mySequence->Value(i)->Value(j + 2).X();
1348 Y1 = gp_Vec2d(mySequence->Value(i)->Value(j - 1).Y(),
1349 mySequence->Value(i)->Value(j - 1).Z());
1350 Y2 = gp_Vec2d(mySequence->Value(i)->Value(j).Y(),
1351 mySequence->Value(i)->Value(j).Z());
1352 Y3 = gp_Vec2d(mySequence->Value(i)->Value(j + 1).Y(),
1353 mySequence->Value(i)->Value(j + 1).Z());
1354 Y4 = gp_Vec2d(mySequence->Value(i)->Value(j + 2).Y(),
1355 mySequence->Value(i)->Value(j + 2).Z());
1357 I1 = (Y1 - Y2)/(X1 - X2);
1358 I2 = (Y2 - Y3)/(X2 - X3);
1359 I3 = (Y3 - Y4)/(X3 - X4);
1361 I21 = (I1 - I2)/(X1 - X3);
1362 I22 = (I2 - I3)/(X2 - X4);
1364 I31 = (I21 - I22)/(X1 - X4);
1366 Res = Y1 + (U - X1)*(I1 + (U - X2)*(I21 + (U - X3)*I31));
1371 if(U0 < mySurface->FirstUParameter()) U0 = mySurface->FirstUParameter();
1372 else if(U0 > mySurface->LastUParameter()) U0 = mySurface->LastUParameter();
1374 if(V0 < mySurface->FirstVParameter()) V0 = mySurface->FirstVParameter();
1375 else if(V0 > mySurface->LastVParameter()) V0 = mySurface->LastVParameter();
1377 //End of cubic interpolation
1379 ProjLib_PrjResolve aPrjPS (*myCurve, *mySurface, 1);
1380 aPrjPS.Perform(U, U0, V0, gp_Pnt2d(myTolU, myTolV),
1381 gp_Pnt2d(mySurface->FirstUParameter(), mySurface->FirstVParameter()),
1382 gp_Pnt2d(mySurface->LastUParameter(), mySurface->LastVParameter()));
1383 if (aPrjPS.IsDone())
1384 P = aPrjPS.Solution();
1387 gp_Pnt thePoint = myCurve->Value(U);
1388 Extrema_ExtPS aExtPS(thePoint, *mySurface, myTolU, myTolV);
1389 if (aExtPS.IsDone() && aExtPS.NbExt())
1391 Standard_Integer k, Nend, imin = 1;
1392 // Search for the nearest solution which is also a normal projection
1393 Nend = aExtPS.NbExt();
1394 for(k = 2; k <= Nend; k++)
1395 if (aExtPS.SquareDistance(k) < aExtPS.SquareDistance(imin))
1397 const Extrema_POnSurf& POnS = aExtPS.Point(imin);
1398 Standard_Real ParU,ParV;
1399 POnS.Parameter(ParU, ParV);
1400 P.SetCoord(ParU, ParV);
1406 //=======================================================================
1409 //=======================================================================
1411 void ProjLib_CompProjectedCurve::D1(const Standard_Real t,
1419 d1(t, u, v, V, myCurve, mySurface);
1421 //=======================================================================
1424 //=======================================================================
1426 void ProjLib_CompProjectedCurve::D2(const Standard_Real t,
1435 d2(t, u, v, V1, V2, myCurve, mySurface);
1437 //=======================================================================
1440 //=======================================================================
1442 gp_Vec2d ProjLib_CompProjectedCurve::DN(const Standard_Real t,
1443 const Standard_Integer N) const
1445 if (N < 1 ) throw Standard_OutOfRange("ProjLib_CompProjectedCurve : N must be greater than 0");
1461 throw Standard_NotImplemented("ProjLib_CompProjectedCurve::DN");
1465 //=======================================================================
1466 //function : GetSequence
1468 //=======================================================================
1470 const Handle(ProjLib_HSequenceOfHSequenceOfPnt)& ProjLib_CompProjectedCurve::GetSequence() const
1474 //=======================================================================
1475 //function : FirstParameter
1477 //=======================================================================
1479 Standard_Real ProjLib_CompProjectedCurve::FirstParameter() const
1481 return myCurve->FirstParameter();
1484 //=======================================================================
1485 //function : LastParameter
1487 //=======================================================================
1489 Standard_Real ProjLib_CompProjectedCurve::LastParameter() const
1491 return myCurve->LastParameter();
1494 //=======================================================================
1495 //function : MaxDistance
1497 //=======================================================================
1499 Standard_Real ProjLib_CompProjectedCurve::MaxDistance(const Standard_Integer Index) const
1501 if(Index < 1 || Index > myNbCurves) throw Standard_NoSuchObject();
1502 return myMaxDistance->Value(Index);
1505 //=======================================================================
1506 //function : NbIntervals
1508 //=======================================================================
1510 Standard_Integer ProjLib_CompProjectedCurve::NbIntervals(const GeomAbs_Shape S) const
1512 const_cast<ProjLib_CompProjectedCurve*>(this)->myTabInt.Nullify();
1514 return myTabInt->Length() - 1;
1517 //=======================================================================
1518 //function : Intervals
1520 //=======================================================================
1522 void ProjLib_CompProjectedCurve::Intervals(TColStd_Array1OfReal& T,const GeomAbs_Shape S) const
1524 if (myTabInt.IsNull()) BuildIntervals (S);
1525 T = myTabInt->Array1();
1528 //=======================================================================
1529 //function : BuildIntervals
1531 //=======================================================================
1533 void ProjLib_CompProjectedCurve::BuildIntervals(const GeomAbs_Shape S) const
1535 GeomAbs_Shape SforS = GeomAbs_CN;
1553 throw Standard_OutOfRange();
1555 Standard_Integer i, j, k;
1556 Standard_Integer NbIntCur = myCurve->NbIntervals(S);
1557 Standard_Integer NbIntSurU = mySurface->NbUIntervals(SforS);
1558 Standard_Integer NbIntSurV = mySurface->NbVIntervals(SforS);
1560 TColStd_Array1OfReal CutPntsT(1, NbIntCur+1);
1561 TColStd_Array1OfReal CutPntsU(1, NbIntSurU+1);
1562 TColStd_Array1OfReal CutPntsV(1, NbIntSurV+1);
1564 myCurve->Intervals(CutPntsT, S);
1565 mySurface->UIntervals(CutPntsU, SforS);
1566 mySurface->VIntervals(CutPntsV, SforS);
1568 Standard_Real Tl, Tr, Ul, Ur, Vl, Vr, Tol;
1570 Handle(TColStd_HArray1OfReal) BArr = NULL,
1575 // processing projection bounds
1576 BArr = new TColStd_HArray1OfReal(1, 2*myNbCurves);
1577 for(i = 1; i <= myNbCurves; i++)
1579 Bounds(i, BArr->ChangeValue(2*i - 1), BArr->ChangeValue(2*i));
1582 // processing curve discontinuities
1584 CArr = new TColStd_HArray1OfReal(1, NbIntCur - 1);
1585 for(i = 1; i <= CArr->Length(); i++)
1587 CArr->ChangeValue(i) = CutPntsT(i + 1);
1591 // processing U-surface discontinuities
1592 TColStd_SequenceOfReal TUdisc;
1594 for(k = 2; k <= NbIntSurU; k++) {
1595 // std::cout<<"CutPntsU("<<k<<") = "<<CutPntsU(k)<<std::endl;
1596 for(i = 1; i <= myNbCurves; i++)
1598 for(j = 1; j < mySequence->Value(i)->Length(); j++)
1600 Ul = mySequence->Value(i)->Value(j).Y();
1601 Ur = mySequence->Value(i)->Value(j + 1).Y();
1603 if(Abs(Ul - CutPntsU(k)) <= myTolU)
1604 TUdisc.Append(mySequence->Value(i)->Value(j).X());
1605 else if(Abs(Ur - CutPntsU(k)) <= myTolU)
1606 TUdisc.Append(mySequence->Value(i)->Value(j + 1).X());
1607 else if((Ul < CutPntsU(k) && CutPntsU(k) < Ur) ||
1608 (Ur < CutPntsU(k) && CutPntsU(k) < Ul))
1611 V = (mySequence->Value(i)->Value(j).Z()
1612 + mySequence->Value(i)->Value(j +1).Z())/2;
1613 ProjLib_PrjResolve Solver (*myCurve, *mySurface, 2);
1617 Triple = mySequence->Value(i)->Value(j);
1618 d1(Triple.X(), Triple.Y(), Triple.Z(), D, myCurve, mySurface);
1619 if (Abs(D.X()) < Precision::Confusion())
1622 Tol = Min(myTolU, myTolU / Abs(D.X()));
1624 Tl = mySequence->Value(i)->Value(j).X();
1625 Tr = mySequence->Value(i)->Value(j + 1).X();
1627 Solver.Perform((Tl + Tr)/2, CutPntsU(k), V,
1628 gp_Pnt2d(Tol, myTolV),
1629 gp_Pnt2d(Tl, mySurface->FirstVParameter()),
1630 gp_Pnt2d(Tr, mySurface->LastVParameter()));
1634 TUdisc.Append(Solver.Solution().X());
1640 for(i = 2; i <= TUdisc.Length(); i++)
1642 if(TUdisc(i) - TUdisc(i-1) < Precision::PConfusion())
1650 UArr = new TColStd_HArray1OfReal(1, TUdisc.Length());
1651 for(i = 1; i <= UArr->Length(); i++)
1653 UArr->ChangeValue(i) = TUdisc(i);
1656 // processing V-surface discontinuities
1657 TColStd_SequenceOfReal TVdisc;
1659 for(k = 2; k <= NbIntSurV; k++)
1661 for(i = 1; i <= myNbCurves; i++)
1663 // std::cout<<"CutPntsV("<<k<<") = "<<CutPntsV(k)<<std::endl;
1664 for(j = 1; j < mySequence->Value(i)->Length(); j++) {
1666 Vl = mySequence->Value(i)->Value(j).Z();
1667 Vr = mySequence->Value(i)->Value(j + 1).Z();
1669 if(Abs(Vl - CutPntsV(k)) <= myTolV)
1670 TVdisc.Append(mySequence->Value(i)->Value(j).X());
1671 else if (Abs(Vr - CutPntsV(k)) <= myTolV)
1672 TVdisc.Append(mySequence->Value(i)->Value(j + 1).X());
1673 else if((Vl < CutPntsV(k) && CutPntsV(k) < Vr) ||
1674 (Vr < CutPntsV(k) && CutPntsV(k) < Vl))
1677 U = (mySequence->Value(i)->Value(j).Y()
1678 + mySequence->Value(i)->Value(j +1).Y())/2;
1679 ProjLib_PrjResolve Solver (*myCurve, *mySurface, 3);
1683 Triple = mySequence->Value(i)->Value(j);
1684 d1(Triple.X(), Triple.Y(), Triple.Z(), D, myCurve, mySurface);
1685 if (Abs(D.Y()) < Precision::Confusion())
1688 Tol = Min(myTolV, myTolV / Abs(D.Y()));
1690 Tl = mySequence->Value(i)->Value(j).X();
1691 Tr = mySequence->Value(i)->Value(j + 1).X();
1693 Solver.Perform((Tl + Tr)/2, U, CutPntsV(k),
1694 gp_Pnt2d(Tol, myTolV),
1695 gp_Pnt2d(Tl, mySurface->FirstUParameter()),
1696 gp_Pnt2d(Tr, mySurface->LastUParameter()));
1700 TVdisc.Append(Solver.Solution().X());
1707 for(i = 2; i <= TVdisc.Length(); i++)
1709 if(TVdisc(i) - TVdisc(i-1) < Precision::PConfusion())
1717 VArr = new TColStd_HArray1OfReal(1, TVdisc.Length());
1718 for(i = 1; i <= VArr->Length(); i++)
1720 VArr->ChangeValue(i) = TVdisc(i);
1725 TColStd_SequenceOfReal Fusion;
1728 GeomLib::FuseIntervals(BArr->ChangeArray1(),
1729 CArr->ChangeArray1(),
1730 Fusion, Precision::PConfusion());
1731 BArr = new TColStd_HArray1OfReal(1, Fusion.Length());
1732 for(i = 1; i <= BArr->Length(); i++)
1734 BArr->ChangeValue(i) = Fusion(i);
1741 GeomLib::FuseIntervals(BArr->ChangeArray1(),
1742 UArr->ChangeArray1(),
1743 Fusion, Precision::PConfusion());
1744 BArr = new TColStd_HArray1OfReal(1, Fusion.Length());
1745 for(i = 1; i <= BArr->Length(); i++)
1747 BArr->ChangeValue(i) = Fusion(i);
1754 GeomLib::FuseIntervals(BArr->ChangeArray1(),
1755 VArr->ChangeArray1(),
1756 Fusion, Precision::PConfusion());
1757 BArr = new TColStd_HArray1OfReal(1, Fusion.Length());
1758 for(i = 1; i <= BArr->Length(); i++)
1760 BArr->ChangeValue(i) = Fusion(i);
1764 const_cast<ProjLib_CompProjectedCurve*>(this)->myTabInt = new TColStd_HArray1OfReal(1, BArr->Length());
1765 for(i = 1; i <= BArr->Length(); i++)
1767 myTabInt->ChangeValue(i) = BArr->Value(i);
1771 //=======================================================================
1774 //=======================================================================
1776 Handle(Adaptor2d_Curve2d) ProjLib_CompProjectedCurve::Trim
1777 (const Standard_Real First,
1778 const Standard_Real Last,
1779 const Standard_Real Tol) const
1781 Handle(ProjLib_HCompProjectedCurve) HCS =
1782 new ProjLib_HCompProjectedCurve(*this);
1783 HCS->Load(mySurface);
1784 HCS->Load(myCurve->Trim(First,Last,Tol));
1788 //=======================================================================
1789 //function : GetType
1791 //=======================================================================
1793 GeomAbs_CurveType ProjLib_CompProjectedCurve::GetType() const
1795 return GeomAbs_OtherCurve;
1798 //=======================================================================
1799 //function : UpdateTripleByTrapCriteria
1801 //=======================================================================
1802 void ProjLib_CompProjectedCurve::UpdateTripleByTrapCriteria(gp_Pnt &thePoint) const
1804 Standard_Boolean isProblemsPossible = Standard_False;
1805 // Check possible traps cases:
1808 if (mySurface->GetType() == GeomAbs_SurfaceOfRevolution)
1810 // Compute maximal deviation from 3D and choose the biggest one.
1811 Standard_Real aVRes = mySurface->VResolution(Precision::Confusion());
1812 Standard_Real aMaxTol = Max(Precision::PConfusion(), aVRes);
1814 if (Abs (thePoint.Z() - mySurface->FirstVParameter()) < aMaxTol ||
1815 Abs (thePoint.Z() - mySurface->LastVParameter() ) < aMaxTol )
1817 isProblemsPossible = Standard_True;
1821 // 27135 bug. Trap on degenerated edge.
1822 if (mySurface->GetType() == GeomAbs_Sphere &&
1823 (Abs (thePoint.Z() - mySurface->FirstVParameter()) < Precision::PConfusion() ||
1824 Abs (thePoint.Z() - mySurface->LastVParameter() ) < Precision::PConfusion() ||
1825 Abs (thePoint.Y() - mySurface->FirstUParameter()) < Precision::PConfusion() ||
1826 Abs (thePoint.Y() - mySurface->LastUParameter() ) < Precision::PConfusion() ))
1828 isProblemsPossible = Standard_True;
1831 if (!isProblemsPossible)
1835 Standard_Boolean isDone =
1836 InitialPoint(myCurve->Value(thePoint.X()), thePoint.X(), myCurve, mySurface,
1837 Precision::PConfusion(), Precision::PConfusion(), U, V);
1842 // Restore original position in case of period jump.
1843 if (mySurface->IsUPeriodic() &&
1844 Abs (Abs(U - thePoint.Y()) - mySurface->UPeriod()) < Precision::PConfusion())
1848 if (mySurface->IsVPeriodic() &&
1849 Abs (Abs(V - thePoint.Z()) - mySurface->VPeriod()) < Precision::PConfusion())
1857 //=======================================================================
1858 //function : BuildCurveSplits
1860 //=======================================================================
1861 void BuildCurveSplits(const Handle(Adaptor3d_Curve) &theCurve,
1862 const Handle(Adaptor3d_Surface) &theSurface,
1863 const Standard_Real theTolU,
1864 const Standard_Real theTolV,
1865 NCollection_Vector<Standard_Real> &theSplits)
1867 SplitDS aDS(theCurve, theSurface, theSplits);
1869 Extrema_ExtPS anExtPS;
1870 anExtPS.Initialize(*theSurface,
1871 theSurface->FirstUParameter(), theSurface->LastUParameter(),
1872 theSurface->FirstVParameter(), theSurface->LastVParameter(),
1874 aDS.myExtPS = &anExtPS;
1876 if (theSurface->IsUPeriodic())
1878 aDS.myPeriodicDir = 0;
1879 SplitOnDirection(aDS);
1881 if (theSurface->IsVPeriodic())
1883 aDS.myPeriodicDir = 1;
1884 SplitOnDirection(aDS);
1887 std::sort(aDS.mySplits.begin(), aDS.mySplits.end(), Comparator);
1890 //=======================================================================
1891 //function : SplitOnDirection
1892 //purpose : This method compute points in the parameter space of the curve
1893 // on which curve should be split since period jump is happen.
1894 //=======================================================================
1895 void SplitOnDirection(SplitDS & theSplitDS)
1898 // Create 3D curve which is correspond to the periodic bound in 2d space.
1899 // Run curve / curve extrema and run extrema point / surface to check that
1900 // the point will be projected to the periodic bound.
1901 // In this method assumed that the points cannot be closer to each other that 1% of the parameter space.
1903 gp_Pnt2d aStartPnt(theSplitDS.mySurface->FirstUParameter(), theSplitDS.mySurface->FirstVParameter());
1904 gp_Dir2d aDir(theSplitDS.myPeriodicDir, (Standard_Integer)!theSplitDS.myPeriodicDir);
1906 theSplitDS.myPerMinParam = !theSplitDS.myPeriodicDir ? theSplitDS.mySurface->FirstUParameter():
1907 theSplitDS.mySurface->FirstVParameter();
1908 theSplitDS.myPerMaxParam = !theSplitDS.myPeriodicDir ? theSplitDS.mySurface->LastUParameter():
1909 theSplitDS.mySurface->LastVParameter();
1910 Standard_Real aLast2DParam = theSplitDS.myPeriodicDir ?
1911 theSplitDS.mySurface->LastUParameter() - theSplitDS.mySurface->FirstUParameter():
1912 theSplitDS.mySurface->LastVParameter() - theSplitDS.mySurface->FirstVParameter();
1914 // Create line which is represent periodic border.
1915 Handle(Geom2d_Curve) aC2GC = new Geom2d_Line(aStartPnt, aDir);
1916 Handle(Geom2dAdaptor_Curve) aC = new Geom2dAdaptor_Curve(aC2GC, 0, aLast2DParam);
1917 Adaptor3d_CurveOnSurface aCOnS(aC, theSplitDS.mySurface);
1918 theSplitDS.myExtCCCurve1 = &aCOnS;
1919 theSplitDS.myExtCCLast2DParam = aLast2DParam;
1921 FindSplitPoint(theSplitDS,
1922 theSplitDS.myCurve->FirstParameter(), // Initial curve range.
1923 theSplitDS.myCurve->LastParameter());
1927 //=======================================================================
1928 //function : FindSplitPoint
1930 //=======================================================================
1931 void FindSplitPoint(SplitDS &theSplitDS,
1932 const Standard_Real theMinParam,
1933 const Standard_Real theMaxParam)
1935 // Make extrema copy to avoid dependencies between different levels of the recursion.
1936 Extrema_ExtCC anExtCC;
1937 anExtCC.SetCurve(1, *theSplitDS.myExtCCCurve1);
1938 anExtCC.SetCurve(2, *theSplitDS.myCurve);
1939 anExtCC.SetSingleSolutionFlag (Standard_True); // Search only one solution since multiple invocations are needed.
1940 anExtCC.SetRange(1, 0, theSplitDS.myExtCCLast2DParam);
1941 anExtCC.SetRange(2, theMinParam, theMaxParam);
1944 if (anExtCC.IsDone() && !anExtCC.IsParallel())
1946 const Standard_Integer aNbExt = anExtCC.NbExt();
1947 for (Standard_Integer anIdx = 1; anIdx <= aNbExt; ++anIdx)
1949 Extrema_POnCurv aPOnC1, aPOnC2;
1950 anExtCC.Points(anIdx, aPOnC1, aPOnC2);
1952 theSplitDS.myExtPS->Perform(aPOnC2.Value());
1953 if (!theSplitDS.myExtPS->IsDone())
1956 // Find point with the minimal Euclidean distance to avoid
1957 // false positive points detection.
1958 Standard_Integer aMinIdx = -1;
1959 Standard_Real aMinSqDist = RealLast();
1960 const Standard_Integer aNbPext = theSplitDS.myExtPS->NbExt();
1961 for(Standard_Integer aPIdx = 1; aPIdx <= aNbPext; ++aPIdx)
1963 const Standard_Real aCurrSqDist = theSplitDS.myExtPS->SquareDistance(aPIdx);
1965 if (aCurrSqDist < aMinSqDist)
1967 aMinSqDist = aCurrSqDist;
1972 // Check that is point will be projected to the periodic border.
1973 const Extrema_POnSurf &aPOnS = theSplitDS.myExtPS->Point(aMinIdx);
1974 Standard_Real U, V, aProjParam;
1975 aPOnS.Parameter(U, V);
1976 aProjParam = theSplitDS.myPeriodicDir ? V : U;
1979 if (Abs(aProjParam - theSplitDS.myPerMinParam) < Precision::PConfusion() ||
1980 Abs(aProjParam - theSplitDS.myPerMaxParam) < Precision::PConfusion() )
1982 const Standard_Real aParam = aPOnC2.Parameter();
1983 const Standard_Real aCFParam = theSplitDS.myCurve->FirstParameter();
1984 const Standard_Real aCLParam = theSplitDS.myCurve->LastParameter();
1986 if (aParam > aCFParam + Precision::PConfusion() &&
1987 aParam < aCLParam - Precision::PConfusion() )
1989 // Add only inner points.
1990 theSplitDS.mySplits.Append(aParam);
1993 const Standard_Real aDeltaCoeff = 0.01;
1994 const Standard_Real aDelta = (theMaxParam - theMinParam +
1995 aCLParam - aCFParam) * aDeltaCoeff;
1997 if (aParam - aDelta > theMinParam + Precision::PConfusion())
1999 FindSplitPoint(theSplitDS,
2000 theMinParam, aParam - aDelta); // Curve parameters.
2003 if (aParam + aDelta < theMaxParam - Precision::PConfusion())
2005 FindSplitPoint(theSplitDS,
2006 aParam + aDelta, theMaxParam); // Curve parameters.
2009 } // for (Standard_Integer anIdx = 1; anIdx <= aNbExt; ++anIdx)