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_HCurve2d.hxx>
21 #include <Adaptor3d_HCurve.hxx>
22 #include <Adaptor3d_HSurface.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_HCurve.hxx>
46 #include <Extrema_ExtCC.hxx>
47 #include <NCollection_Vector.hxx>
49 #define FuncTol 1.e-10
51 #ifdef OCCT_DEBUG_CHRONO
52 #include <OSD_Timer.hxx>
54 static OSD_Chronometer chr_init_point, chr_dicho_bound;
56 Standard_EXPORT Standard_Real t_init_point, t_dicho_bound;
57 Standard_EXPORT Standard_Integer init_point_count, dicho_bound_count;
59 static void InitChron(OSD_Chronometer& ch)
65 static void ResultChron( OSD_Chronometer & ch, Standard_Real & time)
74 // Structure to perform splits computation.
75 // This structure is not thread-safe since operations under mySplits should be performed in a critical section.
76 // myPeriodicDir - 0 for U periodicity and 1 for V periodicity.
79 SplitDS(const Handle(Adaptor3d_HCurve) &theCurve,
80 const Handle(Adaptor3d_HSurface) &theSurface,
81 NCollection_Vector<Standard_Real> &theSplits)
83 mySurface(theSurface),
87 // Assignment operator is forbidden.
88 void operator=(const SplitDS &theSplitDS);
90 const Handle(Adaptor3d_HCurve) myCurve;
91 const Handle(Adaptor3d_HSurface) mySurface;
92 NCollection_Vector<Standard_Real> &mySplits;
94 Standard_Real myPerMinParam;
95 Standard_Real myPerMaxParam;
96 Standard_Integer myPeriodicDir;
98 Extrema_ExtCC *myExtCC;
99 Extrema_ExtPS *myExtPS;
102 //! Compute split points in the parameter space of the curve.
103 static void BuildCurveSplits(const Handle(Adaptor3d_HCurve) &theCurve,
104 const Handle(Adaptor3d_HSurface) &theSurface,
105 const Standard_Real theTolU,
106 const Standard_Real theTolV,
107 NCollection_Vector<Standard_Real> &theSplits);
109 //! Perform splitting on a specified direction. Sub-method in BuildCurveSplits.
110 static void SplitOnDirection(SplitDS & theSplitDS);
112 //! Perform recursive search of the split points.
113 static void FindSplitPoint(SplitDS & theSplitDS,
114 const Standard_Real theMinParam,
115 const Standard_Real theMaxParam);
118 //=======================================================================
119 //function : Comparator
120 //purpose : used in sort algorithm
121 //=======================================================================
122 inline Standard_Boolean Comparator(const Standard_Real theA,
123 const Standard_Real theB)
128 //=======================================================================
130 //purpose : computes first derivative of the projected curve
131 //=======================================================================
133 static void d1(const Standard_Real t,
134 const Standard_Real u,
135 const Standard_Real v,
137 const Handle(Adaptor3d_HCurve)& Curve,
138 const Handle(Adaptor3d_HSurface)& Surface)
141 gp_Vec DS1_u, DS1_v, DS2_u, DS2_uv, DS2_v, DC1_t;
142 Surface->D2(u, v, S, DS1_u, DS1_v, DS2_u, DS2_v, DS2_uv);
143 Curve->D1(t, C, DC1_t);
144 gp_Vec Ort(C, S);// Ort = S - C
146 gp_Vec2d dE_dt(-DC1_t*DS1_u, -DC1_t*DS1_v);
147 gp_XY dE_du(DS1_u*DS1_u + Ort*DS2_u,
148 DS1_u*DS1_v + Ort*DS2_uv);
149 gp_XY dE_dv(DS1_v*DS1_u + Ort*DS2_uv,
150 DS1_v*DS1_v + Ort*DS2_v);
152 Standard_Real det = dE_du.X()*dE_dv.Y() - dE_du.Y()*dE_dv.X();
153 if (fabs(det) < gp::Resolution()) Standard_ConstructionError::Raise();
155 gp_Mat2d M(gp_XY(dE_dv.Y()/det, -dE_du.Y()/det),
156 gp_XY(-dE_dv.X()/det, dE_du.X()/det));
158 V = - gp_Vec2d(gp_Vec2d(M.Row(1))*dE_dt, gp_Vec2d(M.Row(2))*dE_dt);
161 //=======================================================================
163 //purpose : computes second derivative of the projected curve
164 //=======================================================================
166 static void d2(const Standard_Real t,
167 const Standard_Real u,
168 const Standard_Real v,
169 gp_Vec2d& V1, gp_Vec2d& V2,
170 const Handle(Adaptor3d_HCurve)& Curve,
171 const Handle(Adaptor3d_HSurface)& Surface)
174 gp_Vec DS1_u, DS1_v, DS2_u, DS2_uv, DS2_v,
175 DS3_u, DS3_v, DS3_uuv, DS3_uvv,
177 Surface->D3(u, v, S, DS1_u, DS1_v, DS2_u, DS2_v, DS2_uv,
178 DS3_u, DS3_v, DS3_uuv, DS3_uvv);
179 Curve->D2(t, C, DC1_t, DC2_t);
182 gp_Vec2d dE_dt(-DC1_t*DS1_u, -DC1_t*DS1_v);
183 gp_XY dE_du(DS1_u*DS1_u + Ort*DS2_u,
184 DS1_u*DS1_v + Ort*DS2_uv);
185 gp_XY dE_dv(DS1_v*DS1_u + Ort*DS2_uv,
186 DS1_v*DS1_v + Ort*DS2_v);
188 Standard_Real det = dE_du.X()*dE_dv.Y() - dE_du.Y()*dE_dv.X();
189 if (fabs(det) < gp::Resolution()) Standard_ConstructionError::Raise();
191 gp_Mat2d M(gp_XY(dE_dv.Y()/det, -dE_du.Y()/det),
192 gp_XY(-dE_dv.X()/det, dE_du.X()/det));
195 V1 = - gp_Vec2d(gp_Vec2d(M.Row(1))*dE_dt, gp_Vec2d(M.Row(2))*dE_dt);
197 /* Second derivative */
199 // Computation of d2E_dt2 = S1
200 gp_Vec2d d2E_dt(-DC2_t*DS1_u, -DC2_t*DS1_v);
202 // Computation of 2*(d2E/dtdX)(dX/dt) = S2
203 gp_Vec2d d2E1_dtdX(-DC1_t*DS2_u,
205 gp_Vec2d d2E2_dtdX(-DC1_t*DS2_uv,
207 gp_Vec2d S2 = 2*gp_Vec2d(d2E1_dtdX*V1, d2E2_dtdX*V1);
209 // Computation of (d2E/dX2)*(dX/dt)2 = S3
211 // Row11 = (d2E1/du2, d2E1/dudv)
213 gp_Vec2d Row11(3*DS1_u*DS2_u + Ort*DS3_u,
214 tmp = 2*DS1_u*DS2_uv +
215 DS1_v*DS2_u + Ort*DS3_uuv);
217 // Row12 = (d2E1/dudv, d2E1/dv2)
218 gp_Vec2d Row12(tmp, DS2_v*DS1_u + 2*DS1_v*DS2_uv +
221 // Row21 = (d2E2/du2, d2E2/dudv)
222 gp_Vec2d Row21(DS2_u*DS1_v + 2*DS1_u*DS2_uv + Ort*DS3_uuv,
223 tmp = 2*DS2_uv*DS1_v + DS1_u*DS2_v + Ort*DS3_uvv);
225 // Row22 = (d2E2/duv, d2E2/dvdv)
226 gp_Vec2d Row22(tmp, 3*DS1_v*DS2_v + Ort*DS3_v);
228 gp_Vec2d S3(V1*gp_Vec2d(Row11*V1, Row12*V1),
229 V1*gp_Vec2d(Row21*V1, Row22*V1));
231 gp_Vec2d Sum = d2E_dt + S2 + S3;
233 V2 = - gp_Vec2d(gp_Vec2d(M.Row(1))*Sum, gp_Vec2d(M.Row(2))*Sum);
235 //=======================================================================
236 //function : d1CurveOnSurf
237 //purpose : computes first derivative of the 3d projected curve
238 //=======================================================================
241 static void d1CurvOnSurf(const Standard_Real t,
242 const Standard_Real u,
243 const Standard_Real v,
245 const Handle(Adaptor3d_HCurve)& Curve,
246 const Handle(Adaptor3d_HSurface)& Surface)
250 gp_Vec DS1_u, DS1_v, DS2_u, DS2_uv, DS2_v, DC1_t;
251 Surface->D2(u, v, S, DS1_u, DS1_v, DS2_u, DS2_v, DS2_uv);
252 Curve->D1(t, C, DC1_t);
253 gp_Vec Ort(C, S);// Ort = S - C
255 gp_Vec2d dE_dt(-DC1_t*DS1_u, -DC1_t*DS1_v);
256 gp_XY dE_du(DS1_u*DS1_u + Ort*DS2_u,
257 DS1_u*DS1_v + Ort*DS2_uv);
258 gp_XY dE_dv(DS1_v*DS1_u + Ort*DS2_uv,
259 DS1_v*DS1_v + Ort*DS2_v);
261 Standard_Real det = dE_du.X()*dE_dv.Y() - dE_du.Y()*dE_dv.X();
262 if (fabs(det) < gp::Resolution()) Standard_ConstructionError::Raise();
264 gp_Mat2d M(gp_XY(dE_dv.Y()/det, -dE_du.Y()/det),
265 gp_XY(-dE_dv.X()/det, dE_du.X()/det));
267 V2d = - gp_Vec2d(gp_Vec2d(M.Row(1))*dE_dt, gp_Vec2d(M.Row(2))*dE_dt);
269 V = DS1_u * V2d.X() + DS1_v * V2d.Y();
274 //=======================================================================
275 //function : d2CurveOnSurf
276 //purpose : computes second derivative of the 3D projected curve
277 //=======================================================================
279 static void d2CurvOnSurf(const Standard_Real t,
280 const Standard_Real u,
281 const Standard_Real v,
282 gp_Vec& V1 , gp_Vec& V2 ,
283 const Handle(Adaptor3d_HCurve)& Curve,
284 const Handle(Adaptor3d_HSurface)& Surface)
288 gp_Vec DS1_u, DS1_v, DS2_u, DS2_uv, DS2_v,
289 DS3_u, DS3_v, DS3_uuv, DS3_uvv,
291 Surface->D3(u, v, S, DS1_u, DS1_v, DS2_u, DS2_v, DS2_uv,
292 DS3_u, DS3_v, DS3_uuv, DS3_uvv);
293 Curve->D2(t, C, DC1_t, DC2_t);
296 gp_Vec2d dE_dt(-DC1_t*DS1_u, -DC1_t*DS1_v);
297 gp_XY dE_du(DS1_u*DS1_u + Ort*DS2_u,
298 DS1_u*DS1_v + Ort*DS2_uv);
299 gp_XY dE_dv(DS1_v*DS1_u + Ort*DS2_uv,
300 DS1_v*DS1_v + Ort*DS2_v);
302 Standard_Real det = dE_du.X()*dE_dv.Y() - dE_du.Y()*dE_dv.X();
303 if (fabs(det) < gp::Resolution()) Standard_ConstructionError::Raise();
305 gp_Mat2d M(gp_XY(dE_dv.Y()/det, -dE_du.Y()/det),
306 gp_XY(-dE_dv.X()/det, dE_du.X()/det));
309 V12d = - gp_Vec2d(gp_Vec2d(M.Row(1))*dE_dt, gp_Vec2d(M.Row(2))*dE_dt);
311 /* Second derivative */
313 // Computation of d2E_dt2 = S1
314 gp_Vec2d d2E_dt(-DC2_t*DS1_u, -DC2_t*DS1_v);
316 // Computation of 2*(d2E/dtdX)(dX/dt) = S2
317 gp_Vec2d d2E1_dtdX(-DC1_t*DS2_u,
319 gp_Vec2d d2E2_dtdX(-DC1_t*DS2_uv,
321 gp_Vec2d S2 = 2*gp_Vec2d(d2E1_dtdX*V12d, d2E2_dtdX*V12d);
323 // Computation of (d2E/dX2)*(dX/dt)2 = S3
325 // Row11 = (d2E1/du2, d2E1/dudv)
327 gp_Vec2d Row11(3*DS1_u*DS2_u + Ort*DS3_u,
328 tmp = 2*DS1_u*DS2_uv +
329 DS1_v*DS2_u + Ort*DS3_uuv);
331 // Row12 = (d2E1/dudv, d2E1/dv2)
332 gp_Vec2d Row12(tmp, DS2_v*DS1_u + 2*DS1_v*DS2_uv +
335 // Row21 = (d2E2/du2, d2E2/dudv)
336 gp_Vec2d Row21(DS2_u*DS1_v + 2*DS1_u*DS2_uv + Ort*DS3_uuv,
337 tmp = 2*DS2_uv*DS1_v + DS1_u*DS2_v + Ort*DS3_uvv);
339 // Row22 = (d2E2/duv, d2E2/dvdv)
340 gp_Vec2d Row22(tmp, 3*DS1_v*DS2_v + Ort*DS3_v);
342 gp_Vec2d S3(V12d*gp_Vec2d(Row11*V12d, Row12*V12d),
343 V12d*gp_Vec2d(Row21*V12d, Row22*V12d));
345 gp_Vec2d Sum = d2E_dt + S2 + S3;
347 V22d = - gp_Vec2d(gp_Vec2d(M.Row(1))*Sum, gp_Vec2d(M.Row(2))*Sum);
349 V1 = DS1_u * V12d.X() + DS1_v * V12d.Y();
350 V2 = DS2_u * V12d.X() *V12d.X()
352 + 2 * DS2_uv * V12d.X() *V12d.Y()
353 + DS2_v * V12d.Y() * V12d.Y()
357 //=======================================================================
358 //function : ExactBound
359 //purpose : computes exact boundary point
360 //=======================================================================
362 static Standard_Boolean ExactBound(gp_Pnt& Sol,
363 const Standard_Real NotSol,
364 const Standard_Real Tol,
365 const Standard_Real TolU,
366 const Standard_Real TolV,
367 const Handle(Adaptor3d_HCurve)& Curve,
368 const Handle(Adaptor3d_HSurface)& Surface)
370 Standard_Real U0, V0, t, t1, t2, FirstU, LastU, FirstV, LastV;
374 FirstU = Surface->FirstUParameter();
375 LastU = Surface->LastUParameter();
376 FirstV = Surface->FirstVParameter();
377 LastV = Surface->LastVParameter();
378 // Here we have to compute the boundary that projection is going to intersect
380 //these variables are to estimate which boundary has more apportunity
382 Standard_Real RU1, RU2, RV1, RV2;
383 d1(Sol.X(), U0, V0, D2d, Curve, Surface);
384 // Here we assume that D2d != (0, 0)
385 if(Abs(D2d.X()) < gp::Resolution())
387 RU1 = Precision::Infinite();
388 RU2 = Precision::Infinite();
392 else if(Abs(D2d.Y()) < gp::Resolution())
396 RV1 = Precision::Infinite();
397 RV2 = Precision::Infinite();
401 RU1 = gp_Pnt2d(U0, V0).
402 Distance(gp_Pnt2d(FirstU, V0 + (FirstU - U0)*D2d.Y()/D2d.X()));
403 RU2 = gp_Pnt2d(U0, V0).
404 Distance(gp_Pnt2d(LastU, V0 + (LastU - U0)*D2d.Y()/D2d.X()));
405 RV1 = gp_Pnt2d(U0, V0).
406 Distance(gp_Pnt2d(U0 + (FirstV - V0)*D2d.X()/D2d.Y(), FirstV));
407 RV2 = gp_Pnt2d(U0, V0).
408 Distance(gp_Pnt2d(U0 + (LastV - V0)*D2d.X()/D2d.Y(), LastV));
410 TColgp_SequenceOfPnt Seq;
411 Seq.Append(gp_Pnt(FirstU, RU1, 2));
412 Seq.Append(gp_Pnt(LastU, RU2, 2));
413 Seq.Append(gp_Pnt(FirstV, RV1, 3));
414 Seq.Append(gp_Pnt(LastV, RV2, 3));
415 Standard_Integer i, j;
416 for(i = 1; i <= 3; i++)
417 for(j = 1; j <= 4-i; j++)
418 if(Seq(j).Y() < Seq(j+1).Y())
421 swp = Seq.Value(j+1);
422 Seq.ChangeValue(j+1) = Seq.Value(j);
423 Seq.ChangeValue(j) = swp;
427 t1 = Min(Sol.X(), NotSol);
428 t2 = Max(Sol.X(), NotSol);
430 Standard_Boolean isDone = Standard_False;
431 while (!Seq.IsEmpty())
435 Seq.Remove(Seq.Length());
436 ProjLib_PrjResolve aPrjPS(Curve->Curve(),
438 Standard_Integer(P.Z()));
439 if(Standard_Integer(P.Z()) == 2)
441 aPrjPS.Perform(t, P.X(), V0, gp_Pnt2d(Tol, TolV),
442 gp_Pnt2d(t1, Surface->FirstVParameter()),
443 gp_Pnt2d(t2, Surface->LastVParameter()), FuncTol);
444 if(!aPrjPS.IsDone()) continue;
445 POnS = aPrjPS.Solution();
446 Sol = gp_Pnt(POnS.X(), P.X(), POnS.Y());
447 isDone = Standard_True;
452 aPrjPS.Perform(t, U0, P.X(), gp_Pnt2d(Tol, TolU),
453 gp_Pnt2d(t1, Surface->FirstUParameter()),
454 gp_Pnt2d(t2, Surface->LastUParameter()), FuncTol);
455 if(!aPrjPS.IsDone()) continue;
456 POnS = aPrjPS.Solution();
457 Sol = gp_Pnt(POnS.X(), POnS.Y(), P.X());
458 isDone = Standard_True;
466 //=======================================================================
467 //function : DichExactBound
468 //purpose : computes exact boundary point
469 //=======================================================================
471 static void DichExactBound(gp_Pnt& Sol,
472 const Standard_Real NotSol,
473 const Standard_Real Tol,
474 const Standard_Real TolU,
475 const Standard_Real TolV,
476 const Handle(Adaptor3d_HCurve)& Curve,
477 const Handle(Adaptor3d_HSurface)& Surface)
479 #ifdef OCCT_DEBUG_CHRONO
480 InitChron(chr_dicho_bound);
483 Standard_Real U0, V0, t;
487 ProjLib_PrjResolve aPrjPS(Curve->Curve(), Surface->Surface(), 1);
489 Standard_Real aNotSol = NotSol;
490 while (fabs(Sol.X() - aNotSol) > Tol)
492 t = (Sol.X() + aNotSol)/2;
493 aPrjPS.Perform(t, U0, V0, gp_Pnt2d(TolU, TolV),
494 gp_Pnt2d(Surface->FirstUParameter(),Surface->FirstVParameter()),
495 gp_Pnt2d(Surface->LastUParameter(),Surface->LastVParameter()),
496 FuncTol, Standard_True);
500 POnS = aPrjPS.Solution();
501 Sol = gp_Pnt(t, POnS.X(), POnS.Y());
507 #ifdef OCCT_DEBUG_CHRONO
508 ResultChron(chr_dicho_bound,t_dicho_bound);
513 //=======================================================================
514 //function : InitialPoint
516 //=======================================================================
518 static Standard_Boolean InitialPoint(const gp_Pnt& Point,
519 const Standard_Real t,
520 const Handle(Adaptor3d_HCurve)& C,
521 const Handle(Adaptor3d_HSurface)& S,
522 const Standard_Real TolU,
523 const Standard_Real TolV,
528 ProjLib_PrjResolve aPrjPS(C->Curve(), S->Surface(), 1);
529 Standard_Real ParU,ParV;
530 Extrema_ExtPS aExtPS;
531 aExtPS.Initialize(S->Surface(), S->FirstUParameter(),
532 S->LastUParameter(), S->FirstVParameter(),
533 S->LastVParameter(), TolU, TolV);
535 aExtPS.Perform(Point);
536 Standard_Integer argmin = 0;
537 if (aExtPS.IsDone() && aExtPS.NbExt())
539 Standard_Integer i, Nend;
540 // Search for the nearest solution which is also a normal projection
541 Nend = aExtPS.NbExt();
542 for(i = 1; i <= Nend; i++)
544 Extrema_POnSurf POnS = aExtPS.Point(i);
545 POnS.Parameter(ParU, ParV);
546 aPrjPS.Perform(t, ParU, ParV, gp_Pnt2d(TolU, TolV),
547 gp_Pnt2d(S->FirstUParameter(), S->FirstVParameter()),
548 gp_Pnt2d(S->LastUParameter(), S->LastVParameter()),
549 FuncTol, Standard_True);
551 if (argmin == 0 || aExtPS.SquareDistance(i) < aExtPS.SquareDistance(argmin)) argmin = i;
554 if( argmin == 0 ) return Standard_False;
557 Extrema_POnSurf POnS = aExtPS.Point(argmin);
558 POnS.Parameter(U, V);
559 return Standard_True;
563 //=======================================================================
564 //function : ProjLib_CompProjectedCurve
566 //=======================================================================
568 ProjLib_CompProjectedCurve::ProjLib_CompProjectedCurve()
576 //=======================================================================
577 //function : ProjLib_CompProjectedCurve
579 //=======================================================================
581 ProjLib_CompProjectedCurve::ProjLib_CompProjectedCurve
582 (const Handle(Adaptor3d_HSurface)& theSurface,
583 const Handle(Adaptor3d_HCurve)& theCurve,
584 const Standard_Real theTolU,
585 const Standard_Real theTolV)
586 : mySurface (theSurface),
589 mySequence(new ProjLib_HSequenceOfHSequenceOfPnt()),
597 //=======================================================================
598 //function : ProjLib_CompProjectedCurve
600 //=======================================================================
602 ProjLib_CompProjectedCurve::ProjLib_CompProjectedCurve
603 (const Handle(Adaptor3d_HSurface)& theSurface,
604 const Handle(Adaptor3d_HCurve)& theCurve,
605 const Standard_Real theTolU,
606 const Standard_Real theTolV,
607 const Standard_Real theMaxDist)
608 : mySurface (theSurface),
611 mySequence(new ProjLib_HSequenceOfHSequenceOfPnt()),
614 myMaxDist (theMaxDist)
619 //=======================================================================
622 //=======================================================================
624 void ProjLib_CompProjectedCurve::Init()
627 NCollection_Vector<Standard_Real> aSplits;
630 Standard_Real Tol;// Tolerance for ExactBound
631 Standard_Integer i, Nend = 0, aSplitIdx = 0;
632 Standard_Boolean FromLastU = Standard_False,
633 isSplitsComputed = Standard_False;
635 const Standard_Real aTol3D = Precision::Confusion();
636 Extrema_ExtCS CExt(myCurve->Curve(), mySurface->Surface(), aTol3D, aTol3D);
637 if (CExt.IsDone() && CExt.NbExt())
639 // Search for the minimum solution.
640 // Avoid usage of extrema result that can be wrong for extrusion.
643 mySurface->GetType() != GeomAbs_SurfaceOfExtrusion)
645 Standard_Real min_val2;
646 min_val2 = CExt.SquareDistance(1);
649 for(i = 2; i <= Nend; i++)
651 if (CExt.SquareDistance(i) < min_val2)
652 min_val2 = CExt.SquareDistance(i);
654 if (min_val2 > myMaxDist * myMaxDist)
655 return; // No near solution -> exit.
659 Standard_Real FirstU, LastU, Step, SearchStep, WalkStep, t;
661 FirstU = myCurve->FirstParameter();
662 LastU = myCurve->LastParameter();
663 const Standard_Real GlobalMinStep = 1.e-4;
664 //<GlobalMinStep> is sufficiently small to provide solving from initial point
665 //and, on the other hand, it is sufficiently large to avoid too close solutions.
666 const Standard_Real MinStep = 0.01*(LastU - FirstU),
667 MaxStep = 0.1*(LastU - FirstU);
668 SearchStep = 10*MinStep;
671 gp_Pnt2d aLowBorder(mySurface->FirstUParameter(),mySurface->FirstVParameter());
672 gp_Pnt2d aUppBorder(mySurface->LastUParameter(), mySurface->LastVParameter());
673 gp_Pnt2d aTol(myTolU, myTolV);
674 ProjLib_PrjResolve aPrjPS(myCurve->Curve(), mySurface->Surface(), 1);
677 Standard_Boolean new_part;
678 Standard_Real prevDeb=0.;
679 Standard_Boolean SameDeb=Standard_False;
682 gp_Pnt Triple, prevTriple;
687 // Search for the beginning of a new continuous part
688 // to avoid infinite computation in some difficult cases.
689 new_part = Standard_False;
690 if(t > FirstU && Abs(t-prevDeb) <= Precision::PConfusion()) SameDeb=Standard_True;
691 while(t <= LastU && !new_part && !FromLastU && !SameDeb)
694 if (t == LastU) FromLastU=Standard_True;
695 Standard_Boolean initpoint=Standard_False;
696 Standard_Real U = 0., V = 0.;
698 Standard_Real ParT,ParU,ParV;
700 // Search an initial point in the list of Extrema Curve-Surface
701 if(Nend != 0 && !CExt.IsParallel())
703 for (i=1;i<=Nend;i++)
707 CExt.Points(i,P1,P2);
709 P2.Parameter(ParU, ParV);
711 aPrjPS.Perform(ParT, ParU, ParV, aTol, aLowBorder, aUppBorder, FuncTol, Standard_True);
713 if ( aPrjPS.IsDone() && P1.Parameter() > Max(FirstU,t-Step+Precision::PConfusion())
714 && P1.Parameter() <= t)
720 initpoint = Standard_True;
727 myCurve->D0(t,CPoint);
728 #ifdef OCCT_DEBUG_CHRONO
729 InitChron(chr_init_point);
731 // PConfusion - use geometric tolerances in extrema / optimization.
732 initpoint=InitialPoint(CPoint, t,myCurve,mySurface, Precision::PConfusion(), Precision::PConfusion(), U, V);
733 #ifdef OCCT_DEBUG_CHRONO
734 ResultChron(chr_init_point,t_init_point);
740 // When U or V lie on surface joint in some cases we cannot use them
741 // as initial point for aPrjPS, so we switch them
744 if ((mySurface->IsUPeriodic() &&
745 Abs(aUppBorder.X() - aLowBorder.X() - mySurface->UPeriod()) < Precision::Confusion()) ||
746 (mySurface->IsVPeriodic() &&
747 Abs(aUppBorder.Y() - aLowBorder.Y() - mySurface->VPeriod()) < Precision::Confusion()))
749 if((Abs(U - aLowBorder.X()) < mySurface->UResolution(Precision::PConfusion())) &&
750 mySurface->IsUPeriodic())
752 d1(t, U, V, D, myCurve, mySurface);
753 if (D.X() < 0 ) U = aUppBorder.X();
755 else if((Abs(U - aUppBorder.X()) < mySurface->UResolution(Precision::PConfusion())) &&
756 mySurface->IsUPeriodic())
758 d1(t, U, V, D, myCurve, mySurface);
759 if (D.X() > 0) U = aLowBorder.X();
762 if((Abs(V - aLowBorder.Y()) < mySurface->VResolution(Precision::PConfusion())) &&
763 mySurface->IsVPeriodic())
765 d1(t, U, V, D, myCurve, mySurface);
766 if (D.Y() < 0) V = aUppBorder.Y();
768 else if((Abs(V - aUppBorder.Y()) <= mySurface->VResolution(Precision::PConfusion())) &&
769 mySurface->IsVPeriodic())
771 d1(t, U, V, D, myCurve, mySurface);
772 if (D.Y() > 0) V = aLowBorder.Y();
778 // Here we are going to stop if the distance between projection and
779 // corresponding curve point is greater than myMaxDist
782 mySurface->D0(U, V, POnS);
783 d = CPoint.Distance(POnS);
791 Triple = gp_Pnt(t, U, V);
794 //Search for exact boundary point
795 Tol = Min(myTolU, myTolV);
797 d1(Triple.X(), Triple.Y(), Triple.Z(), aD, myCurve, mySurface);
798 Tol /= Max(Abs(aD.X()), Abs(aD.Y()));
800 if(!ExactBound(Triple, t - Step, Tol,
801 myTolU, myTolV, myCurve, mySurface))
804 cout<<"There is a problem with ExactBound computation"<<endl;
806 DichExactBound(Triple, t - Step, Tol, myTolU, myTolV,
810 new_part = Standard_True;
814 if(t == LastU) break;
823 if (!new_part) break;
825 //We have found a new continuous part
826 Handle(TColgp_HSequenceOfPnt) hSeq = new TColgp_HSequenceOfPnt();
827 mySequence->Append(hSeq);
829 mySequence->Value(myNbCurves)->Append(Triple);
832 if (Triple.X() == LastU) break;//return;
834 //Computation of WalkStep
836 Standard_Real MagnD1, MagnD2;
837 d2CurvOnSurf(Triple.X(), Triple.Y(), Triple.Z(), D1, D2, myCurve, mySurface);
838 MagnD1 = D1.Magnitude();
839 MagnD2 = D2.Magnitude();
840 if(MagnD2 < Precision::Confusion()) WalkStep = MaxStep;
841 else WalkStep = Min(MaxStep, Max(MinStep, 0.1*MagnD1/MagnD2));
845 t = Triple.X() + Step;
846 if (t > LastU) t = LastU;
847 Standard_Real prevStep = Step;
848 Standard_Real U0, V0;
850 //Here we are trying to prolong continuous part
851 while (t <= LastU && new_part)
854 U0 = Triple.Y() + (Step / prevStep) * (Triple.Y() - prevTriple.Y());
855 V0 = Triple.Z() + (Step / prevStep) * (Triple.Z() - prevTriple.Z());
856 // adjust U0 to be in [mySurface->FirstUParameter(),mySurface->LastUParameter()]
857 U0 = Min(Max(U0, aLowBorder.X()), aUppBorder.X());
858 // adjust V0 to be in [mySurface->FirstVParameter(),mySurface->LastVParameter()]
859 V0 = Min(Max(V0, aLowBorder.Y()), aUppBorder.Y());
862 aPrjPS.Perform(t, U0, V0, aTol,
863 aLowBorder, aUppBorder, FuncTol, Standard_True);
866 if (Step <= GlobalMinStep)
868 //Search for exact boundary point
869 Tol = Min(myTolU, myTolV);
871 d1(Triple.X(), Triple.Y(), Triple.Z(), D, myCurve, mySurface);
872 Tol /= Max(Abs(D.X()), Abs(D.Y()));
874 if(!ExactBound(Triple, t, Tol, myTolU, myTolV,
878 cout<<"There is a problem with ExactBound computation"<<endl;
880 DichExactBound(Triple, t, Tol, myTolU, myTolV,
884 if((Triple.X() - mySequence->Value(myNbCurves)->Value(mySequence->Value(myNbCurves)->Length()).X()) > 1.e-10)
885 mySequence->Value(myNbCurves)->Append(Triple);
886 if((LastU - Triple.X()) < Tol) {t = LastU + 1; break;}//return;
889 t = Triple.X() + Step;
890 if (t > (LastU-MinStep/2) )
895 new_part = Standard_False;
900 Standard_Real SaveStep = Step;
902 t = Triple .X() + Step;
903 if (t > (LastU-MinStep/4) )
906 if (Abs(Step - SaveStep) <= Precision::PConfusion())
907 Step = GlobalMinStep; //to avoid looping
917 Triple = gp_Pnt(t, aPrjPS.Solution().X(), aPrjPS.Solution().Y());
919 // Check for possible local traps.
920 UpdateTripleByTrapCriteria(Triple);
922 // Protection from case when the whole curve lies on a seam.
923 if (!isSplitsComputed)
925 Standard_Boolean isUPossible = Standard_False;
926 if (mySurface->IsUPeriodic() &&
927 (Abs(Triple.Y() - mySurface->FirstUParameter() ) > Precision::PConfusion() &&
928 Abs(Triple.Y() - mySurface->LastUParameter() ) > Precision::PConfusion()))
930 isUPossible = Standard_True;
933 Standard_Boolean isVPossible = Standard_False;
934 if (mySurface->IsVPeriodic() &&
935 (Abs(Triple.Z() - mySurface->FirstVParameter() ) > Precision::PConfusion() &&
936 Abs(Triple.Z() - mySurface->LastVParameter() ) > Precision::PConfusion()))
938 isVPossible = Standard_True;
941 if (isUPossible || isVPossible)
943 // When point is good conditioned.
944 BuildCurveSplits(myCurve, mySurface, myTolU, myTolV, aSplits);
945 isSplitsComputed = Standard_True;
949 if((Triple.X() - mySequence->Value(myNbCurves)->Value(mySequence->Value(myNbCurves)->Length()).X()) > 1.e-10)
950 mySequence->Value(myNbCurves)->Append(Triple);
951 if (t == LastU) {t = LastU + 1; break;}//return;
952 //Computation of WalkStep
953 d2CurvOnSurf(Triple.X(), Triple.Y(), Triple.Z(), D1, D2, myCurve, mySurface);
954 MagnD1 = D1.Magnitude();
955 MagnD2 = D2.Magnitude();
956 if(MagnD2 < Precision::Confusion() ) WalkStep = MaxStep;
957 else WalkStep = Min(MaxStep, Max(MinStep, 0.1*MagnD1/MagnD2));
961 if (t > (LastU-MinStep/2))
963 Step = Step + LastU - t;
967 // We assume at least one point of cache inside of a split.
968 const Standard_Integer aSize = aSplits.Size();
969 for(Standard_Integer anIdx = aSplitIdx; anIdx < aSize; ++anIdx)
971 const Standard_Real aParam = aSplits(anIdx);
972 if (Abs(aParam - Triple.X() ) < Precision::PConfusion())
974 // The current point is equal to a split point.
975 new_part = Standard_False;
977 // Move split index to avoid check of the whole list.
981 else if (aParam < t + Precision::PConfusion() )
983 // The next point crosses the split point.
985 Step = t - prevTriple.X();
987 } // for(Standard_Integer anIdx = aSplitIdx; anIdx < aSize; ++anIdx)
992 // Sequence post-proceeding.
995 // 1. Removing poor parts
996 Standard_Integer NbPart=myNbCurves;
997 Standard_Integer ipart=1;
998 for(i = 1; i <= NbPart; i++) {
999 // Standard_Integer NbPoints = mySequence->Value(i)->Length();
1000 if(mySequence->Value(ipart)->Length() < 2) {
1001 mySequence->Remove(ipart);
1007 if(myNbCurves == 0) return;
1009 // 2. Removing common parts of bounds
1010 for(i = 1; i < myNbCurves; i++)
1012 if(mySequence->Value(i)->Value(mySequence->Value(i)->Length()).X() >=
1013 mySequence->Value(i+1)->Value(1).X())
1014 mySequence->ChangeValue(i+1)->ChangeValue(1).SetX(mySequence->Value(i)->Value(mySequence->Value(i)->Length()).X() + 1.e-12);
1017 // 3. Computation of the maximum distance from each part of curve to surface
1019 myMaxDistance = new TColStd_HArray1OfReal(1, myNbCurves);
1020 myMaxDistance->Init(0);
1021 for(i = 1; i <= myNbCurves; i++)
1022 for(j = 1; j <= mySequence->Value(i)->Length(); j++)
1024 gp_Pnt POnC, POnS, aTriple;
1025 Standard_Real Distance;
1026 aTriple = mySequence->Value(i)->Value(j);
1027 myCurve->D0(aTriple.X(), POnC);
1028 mySurface->D0(aTriple.Y(), aTriple.Z(), POnS);
1029 Distance = POnC.Distance(POnS);
1030 if (myMaxDistance->Value(i) < Distance)
1031 myMaxDistance->ChangeValue(i) = Distance;
1035 // 4. Check the projection to be a single point
1037 gp_Pnt2d Pmoy, Pcurr, P;
1038 Standard_Real AveU, AveV;
1039 mySnglPnts = new TColStd_HArray1OfBoolean(1, myNbCurves);
1040 for(i = 1; i <= myNbCurves; i++) mySnglPnts->SetValue(i, Standard_True);
1042 for(i = 1; i <= myNbCurves; i++)
1044 //compute an average U and V
1046 for(j = 1, AveU = 0., AveV = 0.; j <= mySequence->Value(i)->Length(); j++)
1048 AveU += mySequence->Value(i)->Value(j).Y();
1049 AveV += mySequence->Value(i)->Value(j).Z();
1051 AveU /= mySequence->Value(i)->Length();
1052 AveV /= mySequence->Value(i)->Length();
1054 Pmoy.SetCoord(AveU,AveV);
1055 for(j = 1; j <= mySequence->Value(i)->Length(); j++)
1058 gp_Pnt2d(mySequence->Value(i)->Value(j).Y(), mySequence->Value(i)->Value(j).Z());
1059 if (Pcurr.Distance(Pmoy) > ((myTolU < myTolV) ? myTolV : myTolU))
1061 mySnglPnts->SetValue(i, Standard_False);
1067 // 5. Check the projection to be an isoparametric curve of the surface
1069 myUIso = new TColStd_HArray1OfBoolean(1, myNbCurves);
1070 for(i = 1; i <= myNbCurves; i++) myUIso->SetValue(i, Standard_True);
1072 myVIso = new TColStd_HArray1OfBoolean(1, myNbCurves);
1073 for(i = 1; i <= myNbCurves; i++) myVIso->SetValue(i, Standard_True);
1075 for(i = 1; i <= myNbCurves; i++) {
1076 if (IsSinglePnt(i, P)|| mySequence->Value(i)->Length() <=2) {
1077 myUIso->SetValue(i, Standard_False);
1078 myVIso->SetValue(i, Standard_False);
1082 // new test for isoparametrics
1084 if ( mySequence->Value(i)->Length() > 2) {
1085 //compute an average U and V
1087 for(j = 1, AveU = 0., AveV = 0.; j <= mySequence->Value(i)->Length(); j++) {
1088 AveU += mySequence->Value(i)->Value(j).Y();
1089 AveV += mySequence->Value(i)->Value(j).Z();
1091 AveU /= mySequence->Value(i)->Length();
1092 AveV /= mySequence->Value(i)->Length();
1094 // is i-part U-isoparametric ?
1095 for(j = 1; j <= mySequence->Value(i)->Length(); j++)
1097 if(Abs(mySequence->Value(i)->Value(j).Y() - AveU) > myTolU)
1099 myUIso->SetValue(i, Standard_False);
1104 // is i-part V-isoparametric ?
1105 for(j = 1; j <= mySequence->Value(i)->Length(); j++)
1107 if(Abs(mySequence->Value(i)->Value(j).Z() - AveV) > myTolV)
1109 myVIso->SetValue(i, Standard_False);
1117 //=======================================================================
1120 //=======================================================================
1122 void ProjLib_CompProjectedCurve::Load(const Handle(Adaptor3d_HSurface)& S)
1127 //=======================================================================
1130 //=======================================================================
1132 void ProjLib_CompProjectedCurve::Load(const Handle(Adaptor3d_HCurve)& C)
1137 //=======================================================================
1138 //function : GetSurface
1140 //=======================================================================
1142 const Handle(Adaptor3d_HSurface)& ProjLib_CompProjectedCurve::GetSurface() const
1148 //=======================================================================
1149 //function : GetCurve
1151 //=======================================================================
1153 const Handle(Adaptor3d_HCurve)& ProjLib_CompProjectedCurve::GetCurve() const
1158 //=======================================================================
1159 //function : GetTolerance
1161 //=======================================================================
1163 void ProjLib_CompProjectedCurve::GetTolerance(Standard_Real& TolU,
1164 Standard_Real& TolV) const
1170 //=======================================================================
1171 //function : NbCurves
1173 //=======================================================================
1175 Standard_Integer ProjLib_CompProjectedCurve::NbCurves() const
1179 //=======================================================================
1182 //=======================================================================
1184 void ProjLib_CompProjectedCurve::Bounds(const Standard_Integer Index,
1185 Standard_Real& Udeb,
1186 Standard_Real& Ufin) const
1188 if(Index < 1 || Index > myNbCurves) Standard_NoSuchObject::Raise();
1189 Udeb = mySequence->Value(Index)->Value(1).X();
1190 Ufin = mySequence->Value(Index)->Value(mySequence->Value(Index)->Length()).X();
1192 //=======================================================================
1193 //function : IsSinglePnt
1195 //=======================================================================
1197 Standard_Boolean ProjLib_CompProjectedCurve::IsSinglePnt(const Standard_Integer Index, gp_Pnt2d& P) const
1199 if(Index < 1 || Index > myNbCurves) Standard_NoSuchObject::Raise();
1200 P = gp_Pnt2d(mySequence->Value(Index)->Value(1).Y(), mySequence->Value(Index)->Value(1).Z());
1201 return mySnglPnts->Value(Index);
1204 //=======================================================================
1207 //=======================================================================
1209 Standard_Boolean ProjLib_CompProjectedCurve::IsUIso(const Standard_Integer Index, Standard_Real& U) const
1211 if(Index < 1 || Index > myNbCurves) Standard_NoSuchObject::Raise();
1212 U = mySequence->Value(Index)->Value(1).Y();
1213 return myUIso->Value(Index);
1215 //=======================================================================
1218 //=======================================================================
1220 Standard_Boolean ProjLib_CompProjectedCurve::IsVIso(const Standard_Integer Index, Standard_Real& V) const
1222 if(Index < 1 || Index > myNbCurves) Standard_NoSuchObject::Raise();
1223 V = mySequence->Value(Index)->Value(1).Z();
1224 return myVIso->Value(Index);
1226 //=======================================================================
1229 //=======================================================================
1231 gp_Pnt2d ProjLib_CompProjectedCurve::Value(const Standard_Real t) const
1237 //=======================================================================
1240 //=======================================================================
1242 void ProjLib_CompProjectedCurve::D0(const Standard_Real U,gp_Pnt2d& P) const
1244 Standard_Integer i, j;
1245 Standard_Real Udeb, Ufin;
1246 Standard_Boolean found = Standard_False;
1248 for(i = 1; i <= myNbCurves; i++)
1250 Bounds(i, Udeb, Ufin);
1251 if (U >= Udeb && U <= Ufin)
1253 found = Standard_True;
1257 if (!found) Standard_DomainError::Raise("ProjLib_CompProjectedCurve::D0");
1259 Standard_Real U0, V0;
1261 Standard_Integer End = mySequence->Value(i)->Length();
1262 for(j = 1; j < End; j++)
1263 if ((U >= mySequence->Value(i)->Value(j).X()) && (U <= mySequence->Value(i)->Value(j + 1).X())) break;
1265 // U0 = mySequence->Value(i)->Value(j).Y();
1266 // V0 = mySequence->Value(i)->Value(j).Z();
1268 // Cubic Interpolation
1269 if(mySequence->Value(i)->Length() < 4 ||
1270 (Abs(U-mySequence->Value(i)->Value(j).X()) <= Precision::PConfusion()) )
1272 U0 = mySequence->Value(i)->Value(j).Y();
1273 V0 = mySequence->Value(i)->Value(j).Z();
1275 else if (Abs(U-mySequence->Value(i)->Value(j+1).X())
1276 <= Precision::PConfusion())
1278 U0 = mySequence->Value(i)->Value(j+1).Y();
1279 V0 = mySequence->Value(i)->Value(j+1).Z();
1284 if (j > mySequence->Value(i)->Length() - 2)
1285 j = mySequence->Value(i)->Length() - 2;
1287 gp_Vec2d I1, I2, I3, I21, I22, I31, Y1, Y2, Y3, Y4, Res;
1288 Standard_Real X1, X2, X3, X4;
1290 X1 = mySequence->Value(i)->Value(j - 1).X();
1291 X2 = mySequence->Value(i)->Value(j).X();
1292 X3 = mySequence->Value(i)->Value(j + 1).X();
1293 X4 = mySequence->Value(i)->Value(j + 2).X();
1295 Y1 = gp_Vec2d(mySequence->Value(i)->Value(j - 1).Y(),
1296 mySequence->Value(i)->Value(j - 1).Z());
1297 Y2 = gp_Vec2d(mySequence->Value(i)->Value(j).Y(),
1298 mySequence->Value(i)->Value(j).Z());
1299 Y3 = gp_Vec2d(mySequence->Value(i)->Value(j + 1).Y(),
1300 mySequence->Value(i)->Value(j + 1).Z());
1301 Y4 = gp_Vec2d(mySequence->Value(i)->Value(j + 2).Y(),
1302 mySequence->Value(i)->Value(j + 2).Z());
1304 I1 = (Y1 - Y2)/(X1 - X2);
1305 I2 = (Y2 - Y3)/(X2 - X3);
1306 I3 = (Y3 - Y4)/(X3 - X4);
1308 I21 = (I1 - I2)/(X1 - X3);
1309 I22 = (I2 - I3)/(X2 - X4);
1311 I31 = (I21 - I22)/(X1 - X4);
1313 Res = Y1 + (U - X1)*(I1 + (U - X2)*(I21 + (U - X3)*I31));
1318 if(U0 < mySurface->FirstUParameter()) U0 = mySurface->FirstUParameter();
1319 else if(U0 > mySurface->LastUParameter()) U0 = mySurface->LastUParameter();
1321 if(V0 < mySurface->FirstVParameter()) V0 = mySurface->FirstVParameter();
1322 else if(V0 > mySurface->LastVParameter()) V0 = mySurface->LastVParameter();
1324 //End of cubic interpolation
1326 ProjLib_PrjResolve aPrjPS(myCurve->Curve(), mySurface->Surface(), 1);
1327 aPrjPS.Perform(U, U0, V0, gp_Pnt2d(myTolU, myTolV),
1328 gp_Pnt2d(mySurface->FirstUParameter(), mySurface->FirstVParameter()),
1329 gp_Pnt2d(mySurface->LastUParameter(), mySurface->LastVParameter()));
1330 if (aPrjPS.IsDone())
1331 P = aPrjPS.Solution();
1334 gp_Pnt thePoint = myCurve->Value(U);
1335 Extrema_ExtPS aExtPS(thePoint, mySurface->Surface(), myTolU, myTolV);
1336 if (aExtPS.IsDone() && aExtPS.NbExt())
1338 Standard_Integer k, Nend, imin = 1;
1339 // Search for the nearest solution which is also a normal projection
1340 Nend = aExtPS.NbExt();
1341 for(k = 2; k <= Nend; k++)
1342 if (aExtPS.SquareDistance(k) < aExtPS.SquareDistance(imin))
1344 const Extrema_POnSurf& POnS = aExtPS.Point(imin);
1345 Standard_Real ParU,ParV;
1346 POnS.Parameter(ParU, ParV);
1347 P.SetCoord(ParU, ParV);
1353 //=======================================================================
1356 //=======================================================================
1358 void ProjLib_CompProjectedCurve::D1(const Standard_Real t,
1366 d1(t, u, v, V, myCurve, mySurface);
1368 //=======================================================================
1371 //=======================================================================
1373 void ProjLib_CompProjectedCurve::D2(const Standard_Real t,
1382 d2(t, u, v, V1, V2, myCurve, mySurface);
1384 //=======================================================================
1387 //=======================================================================
1389 gp_Vec2d ProjLib_CompProjectedCurve::DN(const Standard_Real t,
1390 const Standard_Integer N) const
1392 if (N < 1 ) Standard_OutOfRange::Raise("ProjLib_CompProjectedCurve : N must be greater than 0");
1408 Standard_NotImplemented::Raise("ProjLib_CompProjectedCurve::DN");
1412 //=======================================================================
1413 //function : GetSequence
1415 //=======================================================================
1417 const Handle(ProjLib_HSequenceOfHSequenceOfPnt)& ProjLib_CompProjectedCurve::GetSequence() const
1421 //=======================================================================
1422 //function : FirstParameter
1424 //=======================================================================
1426 Standard_Real ProjLib_CompProjectedCurve::FirstParameter() const
1428 return myCurve->FirstParameter();
1431 //=======================================================================
1432 //function : LastParameter
1434 //=======================================================================
1436 Standard_Real ProjLib_CompProjectedCurve::LastParameter() const
1438 return myCurve->LastParameter();
1441 //=======================================================================
1442 //function : MaxDistance
1444 //=======================================================================
1446 Standard_Real ProjLib_CompProjectedCurve::MaxDistance(const Standard_Integer Index) const
1448 if(Index < 1 || Index > myNbCurves) Standard_NoSuchObject::Raise();
1449 return myMaxDistance->Value(Index);
1452 //=======================================================================
1453 //function : NbIntervals
1455 //=======================================================================
1457 Standard_Integer ProjLib_CompProjectedCurve::NbIntervals(const GeomAbs_Shape S) const
1459 const_cast<ProjLib_CompProjectedCurve*>(this)->myTabInt.Nullify();
1461 return myTabInt->Length() - 1;
1464 //=======================================================================
1465 //function : Intervals
1467 //=======================================================================
1469 void ProjLib_CompProjectedCurve::Intervals(TColStd_Array1OfReal& T,const GeomAbs_Shape S) const
1471 if (myTabInt.IsNull()) BuildIntervals (S);
1472 T = myTabInt->Array1();
1475 //=======================================================================
1476 //function : BuildIntervals
1478 //=======================================================================
1480 void ProjLib_CompProjectedCurve::BuildIntervals(const GeomAbs_Shape S) const
1482 GeomAbs_Shape SforS = GeomAbs_CN;
1500 Standard_OutOfRange::Raise();
1502 Standard_Integer i, j, k;
1503 Standard_Integer NbIntCur = myCurve->NbIntervals(S);
1504 Standard_Integer NbIntSurU = mySurface->NbUIntervals(SforS);
1505 Standard_Integer NbIntSurV = mySurface->NbVIntervals(SforS);
1507 TColStd_Array1OfReal CutPntsT(1, NbIntCur+1);
1508 TColStd_Array1OfReal CutPntsU(1, NbIntSurU+1);
1509 TColStd_Array1OfReal CutPntsV(1, NbIntSurV+1);
1511 myCurve->Intervals(CutPntsT, S);
1512 mySurface->UIntervals(CutPntsU, SforS);
1513 mySurface->VIntervals(CutPntsV, SforS);
1515 Standard_Real Tl, Tr, Ul, Ur, Vl, Vr, Tol;
1517 Handle(TColStd_HArray1OfReal) BArr = NULL,
1522 // proccessing projection bounds
1523 BArr = new TColStd_HArray1OfReal(1, 2*myNbCurves);
1524 for(i = 1; i <= myNbCurves; i++)
1525 Bounds(i, BArr->ChangeValue(2*i - 1), BArr->ChangeValue(2*i));
1527 // proccessing curve discontinuities
1529 CArr = new TColStd_HArray1OfReal(1, NbIntCur - 1);
1530 for(i = 1; i <= CArr->Length(); i++)
1531 CArr->ChangeValue(i) = CutPntsT(i + 1);
1534 // proccessing U-surface discontinuities
1535 TColStd_SequenceOfReal TUdisc;
1537 for(k = 2; k <= NbIntSurU; k++) {
1538 // cout<<"CutPntsU("<<k<<") = "<<CutPntsU(k)<<endl;
1539 for(i = 1; i <= myNbCurves; i++)
1540 for(j = 1; j < mySequence->Value(i)->Length(); j++) {
1541 Ul = mySequence->Value(i)->Value(j).Y();
1542 Ur = mySequence->Value(i)->Value(j + 1).Y();
1544 if(Abs(Ul - CutPntsU(k)) <= myTolU)
1545 TUdisc.Append(mySequence->Value(i)->Value(j).X());
1546 else if(Abs(Ur - CutPntsU(k)) <= myTolU)
1547 TUdisc.Append(mySequence->Value(i)->Value(j + 1).X());
1548 else if((Ul < CutPntsU(k) && CutPntsU(k) < Ur) ||
1549 (Ur < CutPntsU(k) && CutPntsU(k) < Ul))
1552 V = (mySequence->Value(i)->Value(j).Z()
1553 + mySequence->Value(i)->Value(j +1).Z())/2;
1554 ProjLib_PrjResolve Solver(myCurve->Curve(), mySurface->Surface(), 2);
1558 Triple = mySequence->Value(i)->Value(j);
1559 d1(Triple.X(), Triple.Y(), Triple.Z(), D, myCurve, mySurface);
1560 if (Abs(D.X()) < Precision::Confusion())
1563 Tol = Min(myTolU, myTolU / Abs(D.X()));
1565 Tl = mySequence->Value(i)->Value(j).X();
1566 Tr = mySequence->Value(i)->Value(j + 1).X();
1568 Solver.Perform((Tl + Tr)/2, CutPntsU(k), V,
1569 gp_Pnt2d(Tol, myTolV),
1570 gp_Pnt2d(Tl, mySurface->FirstVParameter()),
1571 gp_Pnt2d(Tr, mySurface->LastVParameter()));
1575 TUdisc.Append(Solver.Solution().X());
1580 for(i = 2; i <= TUdisc.Length(); i++)
1581 if(TUdisc(i) - TUdisc(i-1) < Precision::PConfusion())
1586 UArr = new TColStd_HArray1OfReal(1, TUdisc.Length());
1587 for(i = 1; i <= UArr->Length(); i++)
1588 UArr->ChangeValue(i) = TUdisc(i);
1590 // proccessing V-surface discontinuities
1591 TColStd_SequenceOfReal TVdisc;
1593 for(k = 2; k <= NbIntSurV; k++)
1594 for(i = 1; i <= myNbCurves; i++)
1596 // cout<<"CutPntsV("<<k<<") = "<<CutPntsV(k)<<endl;
1597 for(j = 1; j < mySequence->Value(i)->Length(); j++) {
1599 Vl = mySequence->Value(i)->Value(j).Z();
1600 Vr = mySequence->Value(i)->Value(j + 1).Z();
1602 if(Abs(Vl - CutPntsV(k)) <= myTolV)
1603 TVdisc.Append(mySequence->Value(i)->Value(j).X());
1604 else if (Abs(Vr - CutPntsV(k)) <= myTolV)
1605 TVdisc.Append(mySequence->Value(i)->Value(j + 1).X());
1606 else if((Vl < CutPntsV(k) && CutPntsV(k) < Vr) ||
1607 (Vr < CutPntsV(k) && CutPntsV(k) < Vl))
1610 U = (mySequence->Value(i)->Value(j).Y()
1611 + mySequence->Value(i)->Value(j +1).Y())/2;
1612 ProjLib_PrjResolve Solver(myCurve->Curve(), mySurface->Surface(), 3);
1616 Triple = mySequence->Value(i)->Value(j);
1617 d1(Triple.X(), Triple.Y(), Triple.Z(), D, myCurve, mySurface);
1618 if (Abs(D.Y()) < Precision::Confusion())
1621 Tol = Min(myTolV, myTolV / Abs(D.Y()));
1623 Tl = mySequence->Value(i)->Value(j).X();
1624 Tr = mySequence->Value(i)->Value(j + 1).X();
1626 Solver.Perform((Tl + Tr)/2, U, CutPntsV(k),
1627 gp_Pnt2d(Tol, myTolV),
1628 gp_Pnt2d(Tl, mySurface->FirstUParameter()),
1629 gp_Pnt2d(Tr, mySurface->LastUParameter()));
1633 TVdisc.Append(Solver.Solution().X());
1638 for(i = 2; i <= TVdisc.Length(); i++)
1639 if(TVdisc(i) - TVdisc(i-1) < Precision::PConfusion())
1644 VArr = new TColStd_HArray1OfReal(1, TVdisc.Length());
1645 for(i = 1; i <= VArr->Length(); i++)
1646 VArr->ChangeValue(i) = TVdisc(i);
1650 TColStd_SequenceOfReal Fusion;
1653 GeomLib::FuseIntervals(BArr->ChangeArray1(),
1654 CArr->ChangeArray1(),
1655 Fusion, Precision::PConfusion());
1656 BArr = new TColStd_HArray1OfReal(1, Fusion.Length());
1657 for(i = 1; i <= BArr->Length(); i++)
1658 BArr->ChangeValue(i) = Fusion(i);
1664 GeomLib::FuseIntervals(BArr->ChangeArray1(),
1665 UArr->ChangeArray1(),
1666 Fusion, Precision::PConfusion());
1667 BArr = new TColStd_HArray1OfReal(1, Fusion.Length());
1668 for(i = 1; i <= BArr->Length(); i++)
1669 BArr->ChangeValue(i) = Fusion(i);
1675 GeomLib::FuseIntervals(BArr->ChangeArray1(),
1676 VArr->ChangeArray1(),
1677 Fusion, Precision::PConfusion());
1678 BArr = new TColStd_HArray1OfReal(1, Fusion.Length());
1679 for(i = 1; i <= BArr->Length(); i++)
1680 BArr->ChangeValue(i) = Fusion(i);
1683 const_cast<ProjLib_CompProjectedCurve*>(this)->myTabInt = new TColStd_HArray1OfReal(1, BArr->Length());
1684 for(i = 1; i <= BArr->Length(); i++)
1685 myTabInt->ChangeValue(i) = BArr->Value(i);
1689 //=======================================================================
1692 //=======================================================================
1694 Handle(Adaptor2d_HCurve2d) ProjLib_CompProjectedCurve::Trim
1695 (const Standard_Real First,
1696 const Standard_Real Last,
1697 const Standard_Real Tol) const
1699 Handle(ProjLib_HCompProjectedCurve) HCS =
1700 new ProjLib_HCompProjectedCurve(*this);
1701 HCS->ChangeCurve2d().Load(mySurface);
1702 HCS->ChangeCurve2d().Load(myCurve->Trim(First,Last,Tol));
1706 //=======================================================================
1707 //function : GetType
1709 //=======================================================================
1711 GeomAbs_CurveType ProjLib_CompProjectedCurve::GetType() const
1713 return GeomAbs_OtherCurve;
1716 //=======================================================================
1717 //function : UpdateTripleByTrapCriteria
1719 //=======================================================================
1720 void ProjLib_CompProjectedCurve::UpdateTripleByTrapCriteria(gp_Pnt &thePoint) const
1722 Standard_Boolean isProblemsPossible = Standard_False;
1723 // Check possible traps cases:
1726 if (mySurface->GetType() == GeomAbs_SurfaceOfRevolution)
1728 // Compute maximal deviation from 3D and choose the biggest one.
1729 Standard_Real aVRes = mySurface->VResolution(Precision::Confusion());
1730 Standard_Real aMaxTol = Max(Precision::PConfusion(), aVRes);
1732 if (Abs (thePoint.Z() - mySurface->FirstVParameter()) < aMaxTol ||
1733 Abs (thePoint.Z() - mySurface->LastVParameter() ) < aMaxTol )
1735 isProblemsPossible = Standard_True;
1739 // 27135 bug. Trap on degenerated edge.
1740 if (mySurface->GetType() == GeomAbs_Sphere &&
1741 (Abs (thePoint.Z() - mySurface->FirstVParameter()) < Precision::PConfusion() ||
1742 Abs (thePoint.Z() - mySurface->LastVParameter() ) < Precision::PConfusion() ||
1743 Abs (thePoint.Y() - mySurface->FirstUParameter()) < Precision::PConfusion() ||
1744 Abs (thePoint.Y() - mySurface->LastUParameter() ) < Precision::PConfusion() ))
1746 isProblemsPossible = Standard_True;
1749 if (!isProblemsPossible)
1753 Standard_Boolean isDone =
1754 InitialPoint(myCurve->Value(thePoint.X()), thePoint.X(), myCurve, mySurface,
1755 Precision::PConfusion(), Precision::PConfusion(), U, V);
1760 // Restore original position in case of period jump.
1761 if (mySurface->IsUPeriodic() &&
1762 Abs (Abs(U - thePoint.Y()) - mySurface->UPeriod()) < Precision::PConfusion())
1766 if (mySurface->IsVPeriodic() &&
1767 Abs (Abs(V - thePoint.Z()) - mySurface->VPeriod()) < Precision::PConfusion())
1775 //=======================================================================
1776 //function : BuildCurveSplits
1778 //=======================================================================
1779 void BuildCurveSplits(const Handle(Adaptor3d_HCurve) &theCurve,
1780 const Handle(Adaptor3d_HSurface) &theSurface,
1781 const Standard_Real theTolU,
1782 const Standard_Real theTolV,
1783 NCollection_Vector<Standard_Real> &theSplits)
1785 SplitDS aDS(theCurve, theSurface, theSplits);
1787 Extrema_ExtPS anExtPS;
1788 anExtPS.Initialize(theSurface->Surface(),
1789 theSurface->FirstUParameter(), theSurface->LastUParameter(),
1790 theSurface->FirstVParameter(), theSurface->LastVParameter(),
1792 aDS.myExtPS = &anExtPS;
1794 if (theSurface->IsUPeriodic())
1796 aDS.myPeriodicDir = 0;
1797 SplitOnDirection(aDS);
1799 if (theSurface->IsVPeriodic())
1801 aDS.myPeriodicDir = 1;
1802 SplitOnDirection(aDS);
1805 std::sort(aDS.mySplits.begin(), aDS.mySplits.end(), Comparator);
1808 //=======================================================================
1809 //function : SplitOnDirection
1810 //purpose : This method compute points in the parameter space of the curve
1811 // on which curve should be split since period jump is happen.
1812 //=======================================================================
1813 void SplitOnDirection(SplitDS & theSplitDS)
1816 // Create 3D curve which is correspond to the periodic bound in 2d space.
1817 // Run curve / curve extrema and run extrema point / surface to check that
1818 // the point will be projected to the periodic bound.
1819 // In this method assumed that the points cannot be closer to each other that 1% of the parameter space.
1821 gp_Pnt2d aStartPnt(theSplitDS.mySurface->FirstUParameter(), theSplitDS.mySurface->FirstVParameter());
1822 gp_Dir2d aDir(theSplitDS.myPeriodicDir, (Standard_Integer)!theSplitDS.myPeriodicDir);
1824 theSplitDS.myPerMinParam = !theSplitDS.myPeriodicDir ? theSplitDS.mySurface->FirstUParameter():
1825 theSplitDS.mySurface->FirstVParameter();
1826 theSplitDS.myPerMaxParam = !theSplitDS.myPeriodicDir ? theSplitDS.mySurface->LastUParameter():
1827 theSplitDS.mySurface->LastVParameter();
1828 Standard_Real aLast2DParam = theSplitDS.myPeriodicDir ?
1829 theSplitDS.mySurface->LastUParameter() - theSplitDS.mySurface->FirstUParameter():
1830 theSplitDS.mySurface->LastVParameter() - theSplitDS.mySurface->FirstVParameter();
1832 // Create line which is represent periodic border.
1833 Handle(Geom2d_Curve) aC2GC = new Geom2d_Line(aStartPnt, aDir);
1834 Handle(Geom2dAdaptor_HCurve) aC = new Geom2dAdaptor_HCurve(aC2GC, 0, aLast2DParam);
1835 Adaptor3d_CurveOnSurface aCOnS(aC, theSplitDS.mySurface);
1837 Extrema_ExtCC anExtCC;
1838 anExtCC.SetCurve(1, aCOnS);
1839 anExtCC.SetCurve(2, theSplitDS.myCurve->Curve());
1840 anExtCC.SetSingleSolutionFlag(Standard_True); // Search only one solution since multiple invocations are needed.
1841 anExtCC.SetRange(1, 0, aLast2DParam);
1842 theSplitDS.myExtCC = &anExtCC;
1844 FindSplitPoint(theSplitDS,
1845 theSplitDS.myCurve->FirstParameter(), // Initial curve range.
1846 theSplitDS.myCurve->LastParameter());
1850 //=======================================================================
1851 //function : FindSplitPoint
1853 //=======================================================================
1854 void FindSplitPoint(SplitDS &theSplitDS,
1855 const Standard_Real theMinParam,
1856 const Standard_Real theMaxParam)
1858 // Make extrema copy to avoid dependencies between different levels of the recursion.
1859 Extrema_ExtCC anExtCC(*theSplitDS.myExtCC);
1860 anExtCC.SetRange(2, theMinParam, theMaxParam);
1863 if (anExtCC.IsDone())
1865 const Standard_Integer aNbExt = anExtCC.NbExt();
1866 for (Standard_Integer anIdx = 1; anIdx <= aNbExt; ++anIdx)
1868 Extrema_POnCurv aPOnC1, aPOnC2;
1869 anExtCC.Points(anIdx, aPOnC1, aPOnC2);
1871 theSplitDS.myExtPS->Perform(aPOnC2.Value());
1872 if (!theSplitDS.myExtPS->IsDone())
1875 // Find point with the minimal Euclidean distance to avoid
1876 // false positive points detection.
1877 Standard_Integer aMinIdx = -1;
1878 Standard_Real aMinSqDist = RealLast();
1879 const Standard_Integer aNbPext = theSplitDS.myExtPS->NbExt();
1880 for(Standard_Integer aPIdx = 1; aPIdx <= aNbPext; ++aPIdx)
1882 const Standard_Real aCurrSqDist = theSplitDS.myExtPS->SquareDistance(aPIdx);
1884 if (aCurrSqDist < aMinSqDist)
1886 aMinSqDist = aCurrSqDist;
1891 // Check that is point will be projected to the periodic border.
1892 const Extrema_POnSurf &aPOnS = theSplitDS.myExtPS->Point(aMinIdx);
1893 Standard_Real U, V, aProjParam;
1894 aPOnS.Parameter(U, V);
1895 aProjParam = theSplitDS.myPeriodicDir ? V : U;
1898 if (Abs(aProjParam - theSplitDS.myPerMinParam) < Precision::PConfusion() ||
1899 Abs(aProjParam - theSplitDS.myPerMaxParam) < Precision::PConfusion() )
1901 const Standard_Real aParam = aPOnC2.Parameter();
1902 const Standard_Real aCFParam = theSplitDS.myCurve->FirstParameter();
1903 const Standard_Real aCLParam = theSplitDS.myCurve->LastParameter();
1905 if (aParam > aCFParam + Precision::PConfusion() &&
1906 aParam < aCLParam - Precision::PConfusion() )
1908 // Add only inner points.
1909 theSplitDS.mySplits.Append(aParam);
1912 const Standard_Real aDeltaCoeff = 0.01;
1913 const Standard_Real aDelta = (theMaxParam - theMinParam +
1914 aCLParam - aCFParam) * aDeltaCoeff;
1916 if (aParam - aDelta > theMinParam + Precision::PConfusion())
1918 FindSplitPoint(theSplitDS,
1919 theMinParam, aParam - aDelta); // Curve parameters.
1922 if (aParam + aDelta < theMaxParam - Precision::PConfusion())
1924 FindSplitPoint(theSplitDS,
1925 aParam + aDelta, theMaxParam); // Curve parameters.
1928 } // for (Standard_Integer anIdx = 1; anIdx <= aNbExt; ++anIdx)