1 // Copyright (c) 1999-2014 OPEN CASCADE SAS
3 // This file is part of Open CASCADE Technology software library.
5 // This library is free software; you can redistribute it and/or modify it under
6 // the terms of the GNU Lesser General Public License version 2.1 as published
7 // by the Free Software Foundation, with special exception defined in the file
8 // OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
9 // distribution for complete text of the license and disclaimer of any warranty.
11 // Alternatively, this file may be used under the terms of Open CASCADE
12 // commercial license or contractual agreement.
14 //:k1 abv 16.12.98 K4L PRO10107, PRO10108, PRO10109
15 //:j8 abv 10.12.98 TR10 r0501_db.stp #9423
16 //:S4030 abv, pdn: new methods - interface to standard ProjLib_CompProjectedCurve
17 //%12 pdn 15.02.99 PRO9234 optimizing
18 //%12 pdn 15.02.99 PRO9234 using improved ProjectDegenerated method
19 // rln 03.03.99 S4135: bm2_sd_t4-A.stp treatment of Geom_SphericalSurface together with V-closed surfaces
20 //:p9 abv 11.03.99 PRO7226 #489490: make IsAnIsoparametric to find nearest case
21 //:q1 abv 15.03.99 (pdn) PRO7226 #525030: limit NextValueOfUV() by tolerance
22 //:q5 abv 19.03.99 code improvement
23 //:q9 abv 23.03.99 PRO7226.stp #489490: cashe for projecting end points
24 //#78 rln 12.03.99 S4135: checking spatial closure with myPreci
25 // pdn 12.03.99 S4135: creating pcurve with minimal length in the case of densed points
26 // abv 29.03.99 IsAnIsoparametric with Precision::Confusion
27 // pdn 09.04.99 IsAnisoparametric uses already computed parameters (S4030, fix PRO14323)
29 //:s5 abv 22.04.99 Adding debug printouts in catch {} blocks
30 //#1 svv 11.01.00 Porting on DEC
32 #include <Approx_CurveOnSurface.hxx>
33 #include <Geom2d_BSplineCurve.hxx>
34 #include <Geom2d_Circle.hxx>
35 #include <Geom2d_Curve.hxx>
36 #include <Geom2d_Ellipse.hxx>
37 #include <Geom2d_Hyperbola.hxx>
38 #include <Geom2d_Line.hxx>
39 #include <Geom2d_Parabola.hxx>
40 #include <Geom2d_TrimmedCurve.hxx>
41 #include <Geom2dAdaptor.hxx>
42 #include <Geom2dAPI_Interpolate.hxx>
43 #include <Geom_BezierSurface.hxx>
44 #include <Geom_BoundedCurve.hxx>
45 #include <Geom_BSplineCurve.hxx>
46 #include <Geom_BSplineSurface.hxx>
47 #include <Geom_Curve.hxx>
48 #include <Geom_OffsetSurface.hxx>
49 #include <Geom_Plane.hxx>
50 #include <Geom_RectangularTrimmedSurface.hxx>
51 #include <Geom_SphericalSurface.hxx>
52 #include <Geom_Surface.hxx>
53 #include <Geom_SurfaceOfLinearExtrusion.hxx>
54 #include <Geom_TrimmedCurve.hxx>
55 #include <GeomAdaptor_HCurve.hxx>
56 #include <GeomAdaptor_HSurface.hxx>
57 #include <GeomAPI_Interpolate.hxx>
58 #include <GeomAPI_PointsToBSpline.hxx>
59 #include <GeomProjLib.hxx>
60 #include <gp_Pnt2d.hxx>
62 #include <NCollection_Sequence.hxx>
63 #include <Precision.hxx>
64 #include <ProjLib_CompProjectedCurve.hxx>
65 #include <ProjLib_HCompProjectedCurve.hxx>
66 #include <ProjLib_ProjectedCurve.hxx>
67 #include <ShapeAnalysis.hxx>
68 #include <ShapeAnalysis_Curve.hxx>
69 #include <ShapeAnalysis_Surface.hxx>
70 #include <ShapeConstruct_ProjectCurveOnSurface.hxx>
71 #include <ShapeExtend.hxx>
72 #include <Standard_ErrorHandler.hxx>
73 #include <Standard_Failure.hxx>
74 #include <Standard_Type.hxx>
75 #include <TColgp_Array1OfPnt.hxx>
76 #include <TColStd_Array1OfInteger.hxx>
77 #include <IntRes2d_Domain.hxx>
78 #include <IntCurve_IntConicConic.hxx>
81 IMPLEMENT_STANDARD_RTTIEXT(ShapeConstruct_ProjectCurveOnSurface,Standard_Transient)
86 static void AdjustSecondPointToFirstPoint(const gp_Pnt2d& theFirstPoint,
87 gp_Pnt2d& theSecondPoint,
88 const Handle(Geom_Surface)& theSurf)
90 if (theSurf->IsUPeriodic())
92 Standard_Real UPeriod = theSurf->UPeriod();
93 Standard_Real NewU = ElCLib::InPeriod(theSecondPoint.X(),
94 theFirstPoint.X() - UPeriod/2,
95 theFirstPoint.X() + UPeriod/2);
96 theSecondPoint.SetX(NewU);
98 if (theSurf->IsVPeriodic())
100 Standard_Real VPeriod = theSurf->VPeriod();
101 Standard_Real NewV = ElCLib::InPeriod(theSecondPoint.Y(),
102 theFirstPoint.Y() - VPeriod/2,
103 theFirstPoint.Y() + VPeriod/2);
104 theSecondPoint.SetY(NewV);
109 //=======================================================================
110 //function : ShapeConstruct_ProjectCurveOnSurface
112 //=======================================================================
114 ShapeConstruct_ProjectCurveOnSurface::ShapeConstruct_ProjectCurveOnSurface()
116 myPreci = Precision::Confusion();
117 myBuild = Standard_False;
118 myAdjustOverDegen = 1; //:c0 //szv#4:S4163:12Mar99 was boolean
122 //=======================================================================
125 //=======================================================================
127 void ShapeConstruct_ProjectCurveOnSurface::Init(const Handle(Geom_Surface)& surf,const Standard_Real preci)
129 Init (new ShapeAnalysis_Surface (surf), preci);
132 //=======================================================================
135 //=======================================================================
137 void ShapeConstruct_ProjectCurveOnSurface::Init(const Handle(ShapeAnalysis_Surface)& surf,const Standard_Real preci)
140 SetPrecision (preci);
143 //=======================================================================
144 //function : SetSurface
146 //=======================================================================
148 void ShapeConstruct_ProjectCurveOnSurface::SetSurface(const Handle(Geom_Surface)& surf)
150 SetSurface (new ShapeAnalysis_Surface (surf));
153 //=======================================================================
154 //function : SetSurface
156 //=======================================================================
158 void ShapeConstruct_ProjectCurveOnSurface::SetSurface(const Handle(ShapeAnalysis_Surface)& surf)
160 if ( mySurf == surf ) return;
165 //=======================================================================
166 //function : SetPrecision
168 //=======================================================================
170 void ShapeConstruct_ProjectCurveOnSurface::SetPrecision(const Standard_Real preci)
175 //=======================================================================
176 //function : BuildCurveMode
178 //=======================================================================
180 Standard_Boolean& ShapeConstruct_ProjectCurveOnSurface::BuildCurveMode()
185 //=======================================================================
186 //function : AdjustOverDegenMode
188 //=======================================================================
191 //szv#4:S4163:12Mar99 was Boolean
192 Standard_Integer& ShapeConstruct_ProjectCurveOnSurface::AdjustOverDegenMode()
194 return myAdjustOverDegen;
197 //=======================================================================
200 //=======================================================================
202 Standard_Boolean ShapeConstruct_ProjectCurveOnSurface::Status (const ShapeExtend_Status theStatus) const
204 return ShapeExtend::DecodeStatus (myStatus, theStatus);
207 //=======================================================================
210 //=======================================================================
211 Standard_Boolean ShapeConstruct_ProjectCurveOnSurface::Perform (Handle(Geom_Curve)& c3d,
212 const Standard_Real First,
213 const Standard_Real Last,
214 Handle(Geom2d_Curve)& c2d,
215 const Standard_Real TolFirst,
216 const Standard_Real TolLast)
218 myStatus = ShapeExtend::EncodeStatus (ShapeExtend_OK);
219 //Standard_Boolean OK = Standard_True; //szv#4:S4163:12Mar99 not needed
221 if (mySurf.IsNull()) {
223 myStatus |= ShapeExtend::EncodeStatus (ShapeExtend_FAIL1);
224 return Standard_False;
226 // Projection Analytique
227 Handle(Geom_Curve) crv3dtrim = c3d;
228 if ( ! c3d->IsKind(STANDARD_TYPE(Geom_BoundedCurve)) )
229 crv3dtrim = new Geom_TrimmedCurve ( c3d, First, Last );
230 c2d = ProjectAnalytic ( crv3dtrim );
232 myStatus |= ShapeExtend::EncodeStatus (ShapeExtend_DONE1);
233 return Standard_True;
236 // Projection par approximation
238 // discretize the 3d curve
240 Standard_Integer nbrPnt;
242 // $$$$ :92 abv 28 Jan 98 see PRO10107, big BSplineCurve C0
243 Standard_Integer nbPini = NCONTROL; // as in BRepCheck_Edge (RLN/Nijni)
244 // 20; // number of points for interpolation, should be "parametric dependent"
246 //:92 abv 28 Jan 98: if curve is BSpline with many intervals,
247 // increase number of points to provide at least Degree()+1 points per interval
248 Handle(Geom_BSplineCurve) bspl;
249 if ( c3d->IsKind(STANDARD_TYPE(Geom_TrimmedCurve)) ) {
250 Handle(Geom_TrimmedCurve) ctrim = Handle(Geom_TrimmedCurve)::DownCast(c3d);
251 bspl = Handle(Geom_BSplineCurve)::DownCast ( ctrim->BasisCurve() );
253 else bspl = Handle(Geom_BSplineCurve)::DownCast ( c3d );
254 if ( ! bspl.IsNull() ) {
255 Standard_Integer nint = 0;
256 for ( Standard_Integer i=1; i < bspl->NbKnots(); i++ )
258 if ( bspl->Knot(i+1) > First && bspl->Knot(i) < Last )
261 Standard_Integer minPnt = nint * ( bspl->Degree() + 1 );
262 while ( nbPini < minPnt ) nbPini += NCONTROL - 1;
264 if ( nbPini > NCONTROL )
265 std::cout << "Warning: number of points for projecting is " << nbPini << std::endl;
269 // $$$$ end :92 (big BSplineCurve C0)
271 // this number should be "parametric dependent"
272 TColgp_SequenceOfPnt points;
273 TColStd_SequenceOfReal params;
274 NCollection_Sequence<Standard_Real> aKnotCoeffs;
276 Standard_Integer iPnt;
278 // In case of bspline compute parametrization speed on each
279 // knot interval inside [aFirstParam, aLastParam].
280 // If quotient = (MaxSpeed / MinSpeed) >= aMaxQuotientCoeff then
281 // use PerformByProjLib algorithm.
284 Standard_Real aFirstParam = First; // First parameter of current interval.
285 Standard_Real aLastParam = Last; // Last parameter of current interval.
287 // First index computation.
288 Standard_Integer anIdx = 1;
289 for(; anIdx <= bspl->NbKnots() && aFirstParam < Last; anIdx++)
291 if(bspl->Knot(anIdx) > First)
297 GeomAdaptor_Curve aC3DAdaptor(c3d);
298 Standard_Real aMinParSpeed = Precision::Infinite(); // Minimal parameterization speed.
299 for(; anIdx <= bspl->NbKnots() && aFirstParam < Last; anIdx++)
301 // Fill current knot interval.
302 aLastParam = Min(Last, bspl->Knot(anIdx));
303 Standard_Integer aNbIntPnts = NCONTROL;
304 // Number of inner points is adapted according to the length of the interval
305 // to avoid a lot of calculations on small range of parameters.
308 const Standard_Real aLenThres = 1.e-2;
309 const Standard_Real aLenRatio =
310 (aLastParam - aFirstParam) / (bspl->Knot(anIdx) - bspl->Knot(anIdx - 1));
311 if (aLenRatio < aLenThres)
313 aNbIntPnts = Standard_Integer(aLenRatio / aLenThres * aNbIntPnts);
318 Standard_Real aStep = (aLastParam - aFirstParam) / (aNbIntPnts - 1);
319 Standard_Integer anIntIdx;
321 // Start filling from first point.
322 aC3DAdaptor.D0(aFirstParam, p3d1);
324 Standard_Real aLength3d = 0.0;
325 for(anIntIdx = 1; anIntIdx < aNbIntPnts; anIntIdx++)
327 Standard_Real aParam = aFirstParam + aStep * anIntIdx;
328 aC3DAdaptor.D0 (aParam, p3d2);
329 const Standard_Real aDist = p3d2.Distance(p3d1);
334 aMinParSpeed = Min(aMinParSpeed, aDist / aStep);
336 const Standard_Real aCoeff = aLength3d / (aLastParam - aFirstParam);
337 if (Abs(aCoeff) > gp::Resolution())
338 aKnotCoeffs.Append(aCoeff);
339 aFirstParam = aLastParam;
342 Standard_Real anEvenlyCoeff = 0;
343 if (aKnotCoeffs.Size() > 0)
345 anEvenlyCoeff = *std::max_element(aKnotCoeffs.begin(), aKnotCoeffs.end()) /
346 *std::min_element(aKnotCoeffs.begin(), aKnotCoeffs.end());
349 const Standard_Real aMaxQuotientCoeff = 1500.0;
350 if (anEvenlyCoeff > aMaxQuotientCoeff &&
351 aMinParSpeed > Precision::Confusion() )
353 PerformByProjLib(c3d, First, Last, c2d);
354 // PerformByProjLib fail detection:
357 return Status (ShapeExtend_DONE);
362 Standard_Real deltaT, t;
363 deltaT = (Last - First) / (nbPini-1);
365 for (iPnt = 1; iPnt <= nbPini; iPnt ++)
367 if (iPnt == 1) t = First;
368 else if (iPnt == nbPini) t = Last;
369 else t = First + (iPnt - 1) * deltaT;
376 // CALCUL par approximation
377 TColgp_SequenceOfPnt2d pnt2d;
378 ApproxPCurve (nbrPnt,c3d,TolFirst,TolLast,
379 points,params,pnt2d,c2d); //szv#4:S4163:12Mar99 OK not needed
380 nbPini = points.Length();
382 myStatus |= ShapeExtend::EncodeStatus (ShapeExtend_DONE2);
383 return Standard_True;
384 }// cas particulier d iso
386 // INTERPOLATION du resultat
389 Handle(TColgp_HArray1OfPnt) thePnts = new TColgp_HArray1OfPnt (1, nbPini);
390 Handle(TColStd_HArray1OfReal) theParams = new TColStd_HArray1OfReal(1, nbPini);
391 for (iPnt = 1; iPnt <= nbPini ; iPnt ++) {
392 thePnts->SetValue(iPnt, points(iPnt));
393 theParams->SetValue(iPnt, params(iPnt));
396 Handle(Geom_Curve) newc3d = InterpolateCurve3d (nbPini,thePnts,theParams, c3d);
397 if ( newc3d.IsNull() ) myStatus |= ShapeExtend::EncodeStatus (ShapeExtend_FAIL2);
399 myStatus |= ShapeExtend::EncodeStatus (ShapeExtend_DONE3);
404 Handle(TColgp_HArray1OfPnt2d) thePnts2d = new TColgp_HArray1OfPnt2d(1, nbPini);
405 Handle(TColStd_HArray1OfReal) theParams2d = new TColStd_HArray1OfReal(1, nbPini);
406 for (iPnt = 1; iPnt <= nbPini ; iPnt ++) {
407 theParams2d->SetValue(iPnt, params(iPnt));
408 thePnts2d->SetValue(iPnt, pnt2d(iPnt));
411 c2d = InterpolatePCurve (nbPini, thePnts2d, theParams2d, c3d);
412 // c2d = ApproximatePCurve (nbPini, thePnts2d, theParams2d, c3d);
413 // Faut-il aussi reprendre la C3D ?
414 myStatus |= ShapeExtend::EncodeStatus (c2d.IsNull() ? ShapeExtend_FAIL1 : ShapeExtend_DONE2);
415 return Status (ShapeExtend_DONE);
418 //=======================================================================
419 //function : PerformByProjLib
421 //=======================================================================
423 Standard_Boolean ShapeConstruct_ProjectCurveOnSurface::PerformByProjLib(Handle(Geom_Curve)& c3d,
424 const Standard_Real First,
425 const Standard_Real Last,
426 Handle(Geom2d_Curve)& c2d,
427 const GeomAbs_Shape /*continuity*/,
428 const Standard_Integer /*maxdeg */,
429 const Standard_Integer /*nbinterval */)
431 //Standard_Boolean OK = Standard_True; //szv#4:S4163:12Mar99 unused
433 if (mySurf.IsNull()) {
434 myStatus = ShapeExtend::EncodeStatus (ShapeExtend_FAIL1);
435 return Standard_False;
441 Handle(GeomAdaptor_HSurface) GAS = mySurf->Adaptor3d();
442 Handle(GeomAdaptor_HCurve) GAC = new GeomAdaptor_HCurve (c3d,First,Last);
443 ProjLib_ProjectedCurve Projector(GAS, GAC);
445 switch (Projector.GetType())
448 c2d = new Geom2d_Line(Projector.Line());
450 case GeomAbs_Circle :
451 c2d = new Geom2d_Circle(Projector.Circle());
453 case GeomAbs_Ellipse :
454 c2d = new Geom2d_Ellipse(Projector.Ellipse());
456 case GeomAbs_Parabola :
457 c2d = new Geom2d_Parabola(Projector.Parabola());
459 case GeomAbs_Hyperbola :
460 c2d = new Geom2d_Hyperbola(Projector.Hyperbola());
462 case GeomAbs_BSplineCurve :
463 c2d = Projector.BSpline();
466 // Not possible, handling added to avoid gcc warning.
472 myStatus = ShapeExtend::EncodeStatus (ShapeExtend_FAIL2);
473 return Standard_False;
477 myStatus = ShapeExtend::EncodeStatus (ShapeExtend_DONE1);
478 return Standard_True;
482 catch(Standard_Failure const& anException) {
484 std::cout << "Warning: ShapeConstruct_ProjectCurveOnSurface::PerformByProjLib(): Exception: ";
485 anException.Print(std::cout); std::cout << std::endl;
488 myStatus = ShapeExtend::EncodeStatus (ShapeExtend_FAIL3);
491 return Standard_False;
494 //=======================================================================
495 //function : ProjectAnalytic
497 //=======================================================================
499 Handle(Geom2d_Curve) ShapeConstruct_ProjectCurveOnSurface::ProjectAnalytic(const Handle(Geom_Curve)& c3d) const
501 Handle(Geom2d_Curve) result;
503 //:k1 abv 16 Dec 98: limit analytic cases by Plane surfaces only
504 // This is necessary for K4L since it fails on other surfaces
505 // when general method GeomProjLib::Curve2d() is used
506 // Projection is done as in BRep_Tool and BRepCheck_Edge
507 Handle(Geom_Surface) surf = mySurf->Surface();
508 Handle(Geom_Plane) Plane = Handle(Geom_Plane)::DownCast ( surf );
509 if ( Plane.IsNull() ) {
510 Handle(Geom_RectangularTrimmedSurface) RTS =
511 Handle(Geom_RectangularTrimmedSurface)::DownCast ( surf );
512 if ( ! RTS.IsNull() ) Plane = Handle(Geom_Plane)::DownCast ( RTS->BasisSurface() );
514 Handle(Geom_OffsetSurface) OS =
515 Handle(Geom_OffsetSurface)::DownCast ( surf );
517 Plane = Handle(Geom_Plane)::DownCast ( OS->BasisSurface() );
520 if ( ! Plane.IsNull() ) {
521 Handle(Geom_Curve) ProjOnPlane =
522 GeomProjLib::ProjectOnPlane (c3d, Plane,
523 Plane->Position().Direction(), Standard_True);
524 Handle(GeomAdaptor_HCurve) HC = new GeomAdaptor_HCurve ( ProjOnPlane );
525 ProjLib_ProjectedCurve Proj ( mySurf->Adaptor3d(), HC );
527 result = Geom2dAdaptor::MakeCurve(Proj);
528 if ( result.IsNull() ) return result;
529 if ( result->IsKind(STANDARD_TYPE(Geom2d_TrimmedCurve)) ) {
530 Handle(Geom2d_TrimmedCurve) TC = Handle(Geom2d_TrimmedCurve)::DownCast ( result );
531 result = TC->BasisCurve();
540 //! Fix possible period jump and handle walking period parameter.
541 static Standard_Boolean fixPeriodictyTroubles(gp_Pnt2d *thePnt, // pointer to gp_Pnt2d[4] beginning
542 Standard_Integer theIdx, // Index of objective coord: 1 ~ X, 2 ~ Y
543 Standard_Real thePeriod, // Period on objective coord
544 Standard_Integer theSavedPoint, // Point number to choose period
545 Standard_Real theSavedParam) // Param from cashe to choose period
547 Standard_Real aSavedParam;
548 Standard_Integer aSavedPoint;
549 Standard_Real aMinParam = 0.0, aMaxParam = thePeriod;
550 if (theSavedPoint < 0) {
551 // normalize to first period by default
552 aSavedParam = 0.5 * thePeriod;
556 aSavedParam = theSavedParam;
557 aSavedPoint = theSavedPoint;
558 while (aMinParam > aSavedParam) {
559 aMinParam -= thePeriod;
560 aMaxParam -= thePeriod;
562 while (aMaxParam < aSavedParam) {
563 aMinParam += thePeriod;
564 aMaxParam += thePeriod;
568 Standard_Real aFixIsoParam = aMinParam;
569 Standard_Boolean isIsoLine = Standard_False;
570 if (aMaxParam - aSavedParam < Precision::PConfusion() ||
571 aSavedParam - aMinParam < Precision::PConfusion()) {
572 aFixIsoParam = aSavedParam;
573 isIsoLine = Standard_True;
575 // normalize all coordinates to [aMinParam, aMaxParam)
576 for (Standard_Integer i = 0; i < 4; i++) {
577 Standard_Real aParam = thePnt[i].Coord(theIdx);
578 Standard_Real aShift = ShapeAnalysis::AdjustToPeriod(aParam, aMinParam, aMaxParam);
580 // Walk over period coord -> not walking on another isoline in parameter space.
582 if (aMaxParam - aParam < Precision::PConfusion() || aParam - aMinParam < Precision::PConfusion())
583 aParam = aFixIsoParam;
586 if (aMaxParam - aParam < Precision::PConfusion())
588 if (aParam - aMinParam < Precision::PConfusion())
592 thePnt[i].SetCoord(theIdx, aParam);
595 // find possible period jump and increasing or decreasing coordinates vector
596 Standard_Boolean isJump = Standard_False;
597 Standard_Real aPrevDiff = 0.0;
598 Standard_Real aSumDiff = 1.0;
599 for (Standard_Integer i = 0; i < 3; i++) {
600 Standard_Real aDiff = thePnt[i + 1].Coord(theIdx) - thePnt[i].Coord(theIdx);
601 if (aDiff < -Precision::PConfusion()) {
604 //if first derivative changes its sign then period jump may exists in this place
605 if (aDiff * aPrevDiff < -Precision::PConfusion()) {
606 isJump = Standard_True;
612 return Standard_False;
614 if (aSumDiff > 0) { // decreasing sequence (parameters decrease twice(--) and one period jump(+))
615 for (Standard_Integer i = aSavedPoint; i > 0; i--)
616 if (thePnt[i].Coord(theIdx) > thePnt[i - 1].Coord(theIdx)) {
617 thePnt[i - 1].SetCoord(theIdx, thePnt[i - 1].Coord(theIdx) + thePeriod);
619 for (Standard_Integer i = aSavedPoint; i < 3; i++)
620 if (thePnt[i].Coord(theIdx) < thePnt[i + 1].Coord(theIdx)) {
621 thePnt[i + 1].SetCoord(theIdx, thePnt[i + 1].Coord(theIdx) - thePeriod);
624 else {// increasing sequence (parameters increase twice(++) and one period jump(-))
625 for (Standard_Integer i = aSavedPoint; i > 0; i--)
626 if (thePnt[i].Coord(theIdx) < thePnt[i - 1].Coord(theIdx)) {
627 thePnt[i - 1].SetCoord(theIdx, thePnt[i - 1].Coord(theIdx) - thePeriod);
629 for (Standard_Integer i = aSavedPoint; i < 3; i++)
630 if (thePnt[i].Coord(theIdx) > thePnt[i + 1].Coord(theIdx)) {
631 thePnt[i + 1].SetCoord(theIdx, thePnt[i + 1].Coord(theIdx) + thePeriod);
635 // Do not return false, because for nonlinear 2d curves vector of parameters
636 // may change its first derivative and shifted parameters will be broken for this case.
637 return Standard_True;
640 //=======================================================================
643 //=======================================================================
645 Handle(Geom2d_Curve) ShapeConstruct_ProjectCurveOnSurface::getLine(
646 const TColgp_SequenceOfPnt& thepoints,
647 const TColStd_SequenceOfReal& theparams,
648 TColgp_SequenceOfPnt2d& thePnt2ds,
649 Standard_Real theTol,
650 Standard_Boolean &isRecompute,
651 Standard_Boolean &isFromCashe) const
653 Standard_Integer nb = thepoints.Length();
655 aP[0] = thepoints(1);
656 aP[1] = thepoints(2);
657 aP[2] = thepoints(nb - 1);
658 aP[3] = thepoints(nb);
660 Standard_Integer i = 0;
662 Standard_Real aTol2 = theTol * theTol;
663 Standard_Boolean isPeriodicU = mySurf->Surface()->IsUPeriodic();
664 Standard_Boolean isPeriodicV = mySurf->Surface()->IsVPeriodic();
667 // Protection against bad "tolerance" shapes.
670 theTol = Precision::Confusion();
671 aTol2 = theTol * theTol;
673 if (aTol2 < Precision::SquareConfusion())
674 aTol2 = Precision::SquareConfusion();
675 Standard_Real anOldTol2 = aTol2;
676 // auxiliary variables to choose period for connection with previous 2dcurve (if exist)
677 Standard_Integer aSavedPointNum = -1;
678 gp_Pnt2d aSavedPoint;
680 // project first and last points
684 for (j = 0; j < myNbCashe; j++)
686 if ( myCashe3d[j].SquareDistance (aP[i] ) < aTol2)
688 aP2d[i] = mySurf->NextValueOfUV (myCashe2d[j], aP[i], theTol, theTol);
690 aSavedPoint = myCashe2d[j];
692 isFromCashe = Standard_True;
698 aP2d[i] = mySurf->ValueOfUV(aP[i], theTol);
700 Standard_Real aDist = mySurf->Gap();
701 Standard_Real aCurDist = aDist * aDist;
702 if( aTol2 < aDist * aDist)
706 if ( isPeriodicU || isPeriodicV )
708 // Compute second and last but one c2d points.
709 for(i = 1; i < 3; i++)
712 for (j = 0; j < myNbCashe; j++)
714 if ( myCashe3d[j].SquareDistance (aP[i] ) < aTol2)
716 aP2d[i] = mySurf->NextValueOfUV (myCashe2d[j], aP[i], theTol, theTol);
718 aSavedPoint = myCashe2d[j];
724 aP2d[i] = mySurf->ValueOfUV(aP[i], theTol);
726 Standard_Real aDist = mySurf->Gap();
727 Standard_Real aCurDist = aDist * aDist;
728 if( aTol2 < aDist * aDist)
734 isRecompute = fixPeriodictyTroubles(&aP2d[0], 1 /* X Coord */, mySurf->Surface()->UPeriod(), aSavedPointNum, aSavedPoint.X());
739 isRecompute = fixPeriodictyTroubles(&aP2d[0], 2 /* Y Coord */, mySurf->Surface()->VPeriod(), aSavedPointNum, aSavedPoint.Y());
743 if (isRecompute && mySurf->Surface()->IsKind(STANDARD_TYPE(Geom_SphericalSurface))) {
744 // Do not try to make line, because in this case may be very special case when 3d curve
745 // go over the pole of, e.g., sphere, and partly lies along seam
746 // (see ApproxPCurve() for more information).
750 thePnt2ds.SetValue(1, aP2d[0]);
751 thePnt2ds.SetValue(nb, aP2d[3]);
753 // Restore old tolerance in 2d space to avoid big gap cases.
755 // Check that straight line in 2d with parameterisation as in 3d will fit
756 // fit 3d curve at all points.
757 Standard_Real dPar = theparams(nb) - theparams(1);
758 if ( Abs(dPar) < Precision::PConfusion() )
760 gp_Vec2d aVec0 (aP2d[0], aP2d[3]);
761 gp_Vec2d aVec = aVec0 / dPar;
762 Handle(Geom_Surface) aSurf = mySurf->Surface();
763 Standard_Boolean isNormalCheck = aSurf->IsCNu(1) && aSurf->IsCNv(1);
765 for(i = 1; i <= nb; i++)
767 gp_XY aCurPoint = aP2d[0].XY() + aVec.XY() * (theparams(i) - theparams(1));
769 gp_Vec aNormalVec, aDu, aDv;
770 aSurf->D1(aCurPoint.X(), aCurPoint.Y(), aCurP, aDu, aDv);
771 aNormalVec = aDu ^ aDv;
772 if (aNormalVec.SquareMagnitude() < Precision::SquareConfusion()) {
773 isNormalCheck = Standard_False;
776 gp_Lin aNormalLine(aCurP, gp_Dir(aNormalVec));
777 Standard_Real aDist = aNormalLine.Distance(thepoints(i));
782 if (!isNormalCheck) {
783 Standard_Real aFirstPointDist = mySurf->Surface()->Value(aP2d[0].X(), aP2d[0].Y()).
784 SquareDistance(thepoints(1));
785 aTol2 = Max(aTol2, aTol2 * 2 * aFirstPointDist);
786 for(i = 2; i < nb; i++)
788 gp_XY aCurPoint = aP2d[0].XY() + aVec.XY() * (theparams(i) - theparams(1));
790 aSurf->D0(aCurPoint.X(), aCurPoint.Y(), aCurP);
791 Standard_Real aDist1 = aCurP.SquareDistance(thepoints(i));
793 if(Abs (aFirstPointDist - aDist1) > aTol2)
798 // check if pcurve can be represented by Geom2d_Line (parameterised by length)
799 Standard_Real aLLength = aVec0.Magnitude();
800 if ( Abs (aLLength - dPar) <= Precision::PConfusion() )
802 gp_XY aDirL = aVec0.XY() / aLLength;
803 gp_Pnt2d aPL (aP2d[0].XY() - theparams(1) * aDirL);
804 return new Geom2d_Line (aPL, gp_Dir2d(aDirL));
807 // create straight bspline
808 TColgp_Array1OfPnt2d aPoles(1, 2);
812 TColStd_Array1OfReal aKnots(1,2);
813 aKnots(1) = theparams(1);
814 aKnots(2) = theparams(theparams.Length());
816 TColStd_Array1OfInteger aMults(1,2);
819 Standard_Integer aDegree = 1;
820 Handle(Geom2d_BSplineCurve) abspl2d =
821 new Geom2d_BSplineCurve (aPoles, aKnots, aMults, aDegree);
825 //=======================================================================
826 //function : ApproxPCurve
828 //=======================================================================
830 Standard_Boolean ShapeConstruct_ProjectCurveOnSurface::ApproxPCurve(const Standard_Integer nbrPnt,
831 const Handle(Geom_Curve)& c3d,
832 const Standard_Real TolFirst,
833 const Standard_Real TolLast,
834 TColgp_SequenceOfPnt& points,
835 TColStd_SequenceOfReal& params,
836 TColgp_SequenceOfPnt2d& pnt2d,
837 Handle(Geom2d_Curve)& c2d)
839 // for performance, first try to handle typical case when pcurve is straight
840 Standard_Boolean isRecompute = Standard_False;
841 Standard_Boolean isFromCasheLine = Standard_False;
842 for (Standard_Integer iseq = 1; iseq <= nbrPnt; iseq++)
844 gp_Pnt2d aP2d(0.,0.);
847 c2d = getLine(points, params, pnt2d, myPreci, isRecompute, isFromCasheLine);
851 Standard_Boolean ChangeCycle = Standard_False;
852 if(myNbCashe>0 && myCashe3d[0].Distance(points(1)) > myCashe3d[0].Distance(points(nbrPnt)) &&
853 myCashe3d[0].Distance(points(nbrPnt))<Precision::Confusion())
854 ChangeCycle = Standard_True;
857 myCashe3d[0] = points(1);
858 myCashe3d[1] = points(nbrPnt);
859 myCashe2d[0] = pnt2d(1);
860 myCashe2d[1] = pnt2d(nbrPnt);
863 myCashe3d[1] = points(1);
864 myCashe3d[0] = points(nbrPnt);
865 myCashe2d[1] = pnt2d(1);
866 myCashe2d[0] = pnt2d(nbrPnt);
868 return Standard_True;
870 Standard_Boolean isDone = Standard_True;
871 // test if the curve 3d is a boundary of the surface
872 // (only for Bezier or BSpline surface)
874 Standard_Boolean isoParam, isoPar2d3d, isoTypeU, p1OnIso, p2OnIso, isoclosed;
875 gp_Pnt2d valueP1, valueP2;
876 Handle(Geom_Curve) cIso;
877 Standard_Real t1, t2;
879 Handle(Standard_Type) sType = mySurf->Surface()->DynamicType();
880 Standard_Boolean isAnalytic = Standard_True;
881 if (sType == STANDARD_TYPE(Geom_BezierSurface) || sType == STANDARD_TYPE(Geom_BSplineSurface)) isAnalytic = Standard_False;
882 Standard_Real uf, ul, vf, vl;
883 mySurf->Surface()->Bounds(uf, ul, vf, vl);
884 isoclosed = Standard_False;
885 TColStd_Array1OfReal pout(1, nbrPnt);
887 isoParam = IsAnIsoparametric(nbrPnt, points, params,
888 isoTypeU, p1OnIso, valueP1, p2OnIso, valueP2,
889 isoPar2d3d, cIso, t1, t2, pout);
891 // projection of the points on surfaces
895 Standard_Real isoValue=0., isoPar1=0., isoPar2=0., tPar=0., tdeb,tfin;
896 Standard_Real Cf, Cl, parf, parl; //szv#4:S4163:12Mar99 dist not needed
898 // Le calcul part-il dans le bon sens, c-a-d deb et fin dans le bon ordre ?
899 // Si uclosed et iso en V, attention isoPar1 ET/OU 2 peut toucher la fermeture
902 isoValue = valueP1.X();
903 isoPar1 = valueP1.Y();
904 isoPar2 = valueP2.Y();
905 isoclosed = mySurf->IsVClosed(myPreci);//#78 rln 12.03.99 S4135
906 parf = vf; parl = vl;
909 isoValue = valueP1.Y();
910 isoPar1 = valueP1.X();
911 isoPar2 = valueP2.X();
912 isoclosed = mySurf->IsUClosed(myPreci);//#78 rln 12.03.99 S4135
913 parf = uf; parl = ul;
915 if (!isoPar2d3d && !isAnalytic) {
916 Cf = cIso->FirstParameter();
917 Cl = cIso->LastParameter();
918 if (Precision::IsInfinite(Cf)) Cf = -1000;
919 if (Precision::IsInfinite(Cl)) Cl = +1000;
920 //pdn S4030 optimizing and fix isopar case on PRO41323
922 // dist = ShapeAnalysis_Curve().Project (cIso,points(2),myPreci,pt,tdeb,Cf,Cl);
923 // Chacun des par1 ou par2 est-il sur un bord. Attention first/last : recaler
924 if (isoclosed && (isoPar1 == parf || isoPar1 == parl)) {
925 if (Abs(tdeb-parf) < Abs(tdeb-parl)) isoPar1 = parf;
927 if (isoTypeU) valueP1.SetY (isoPar1);
928 else valueP1.SetX (isoPar1);
930 if (isoclosed && (isoPar2 == parf || isoPar2 == parl)) {
931 //pdn S4030 optimizing and fix isopar case on PRO41323
932 tfin = pout(nbrPnt-1);
933 //dist = ShapeAnalysis_Curve().Project (cIso,points(nbrPnt-1),myPreci,pt,tfin,Cf,Cl);
934 if (Abs(tfin-parf) < Abs(tfin-parl)) isoPar2 = parf;
936 if (isoTypeU) valueP2.SetY (isoPar2);
937 else valueP2.SetX (isoPar2);
940 // Interversion Par1/Par2 (ne veut que si les 2 sont sur les bords ...)
941 // Est-ce encore necessaire apres ce qui vient d etre fait ?
943 // PTV 05.02.02 fix for translation face from 12_hp_mouse (PARASOLID) face 24008
944 // if curve is periodic do not change the points
945 // skl change "if" for pout(nbrPnt-1) 19.11.2003
947 if( (Abs(tdeb-isoPar1)>Abs(tdeb-isoPar2)) &&
948 (Abs(pout(nbrPnt-1)-isoPar2)>Abs(pout(nbrPnt-1)-isoPar1)) ) {
949 gp_Pnt2d valueTmp = valueP1;
950 valueP1 = valueP2; valueP2 = valueTmp;
952 isoValue = valueP1.X();
953 isoPar1 = valueP1.Y();
954 isoPar2 = valueP2.Y();
957 isoValue = valueP1.Y();
958 isoPar1 = valueP1.X();
959 isoPar2 = valueP2.X();
961 // Fin calcul sens de courbe iso
963 } // end of fix check 05.02.02
967 // Si pas isoParam, on a quand meme du p1OnIso/p2OnIso possible ... !!!
968 // (utile pour detromper bug de projection). Mais detromper aussi circularite
970 //if (p1OnIso) valueP1 =
971 //BestExtremum (valueP1,points(1),points(2));
972 //if (p2OnIso) valueP2 =
973 //BestExtremum (valueP2,points(nbrPnt),points(nbrPnt-1));
976 Standard_Real gap = myPreci; //:q1
977 Standard_Boolean ChangeCycle = Standard_False; //skl for OCC3430
978 // auxiliaruy variables to shift 2dcurve, according to previous
979 Standard_Boolean isFromCashe = Standard_False;
980 gp_Pnt2d aSavedPoint;
981 if( myNbCashe>0 && myCashe3d[0].Distance(points(1))>myCashe3d[0].Distance(points(nbrPnt)) )
982 //if(myCashe3d[0].Distance(points(nbrPnt))<myPreci)
983 if(myCashe3d[0].Distance(points(nbrPnt))<Precision::Confusion())
984 ChangeCycle = Standard_True;
985 //for( i = 1; i <= nbrPnt; i ++) {
986 for(Standard_Integer ii=1; ii<=nbrPnt; ii++) {
987 const Standard_Integer aPntIndex = ChangeCycle ? (nbrPnt - ii + 1) : ii;
988 p3d = points (aPntIndex);
992 if (isoPar2 > isoPar1) tPar = params (aPntIndex);
993 else tPar = t1 + t2 - params(aPntIndex);
994 } else if (!isAnalytic) {
996 if (aPntIndex == 1) tPar = isoPar1;
997 else if (aPntIndex == nbrPnt) tPar = isoPar2;
999 tPar = pout(aPntIndex);
1000 //:S4030 ShapeAnalysis_Curve().Project (cIso,p3d,myPreci,pt,tPar,Cf,Cl); //szv#4:S4163:12Mar99 `dist=` not needed
1004 if (!isoPar2d3d && isAnalytic) {
1005 if (aPntIndex == 1) p2d = valueP1;
1006 else if (aPntIndex == nbrPnt) p2d = valueP2;
1008 p2d = mySurf->NextValueOfUV(p2d,p3d, myPreci, //%12 pdn 15.02.99 optimizing
1009 Precision::Confusion()+1000*gap); //:q1
1010 gap = mySurf->Gap();
1013 if(isoTypeU) { p2d.SetX(isoValue); p2d.SetY(tPar); }
1014 else { p2d.SetX(tPar); p2d.SetY(isoValue); }
1019 if ( (aPntIndex == 1) && p1OnIso) p2d = valueP1;
1020 else if( (aPntIndex == nbrPnt) && p2OnIso) p2d = valueP2;
1021 else {// general case (not an iso) mais attention aux singularites !
1022 // first and last points are already computed by getLine()
1023 if (aPntIndex == 1 || aPntIndex == nbrPnt)
1027 p2d = pnt2d (aPntIndex);
1028 gap = mySurf->Gap();
1029 if (aPntIndex == 1) {
1030 isFromCashe = isFromCasheLine;
1037 //:q9 abv 23 Mar 99: use cashe as 1st approach
1038 Standard_Integer j; // svv #1
1039 for (j = 0; j < myNbCashe; ++j)
1041 if ( myCashe3d[j].SquareDistance ( p3d ) < myPreci*myPreci )
1043 p2d = mySurf->NextValueOfUV (myCashe2d[j], p3d, myPreci, Precision::Confusion()+gap);
1046 isFromCashe = Standard_True;
1047 aSavedPoint = myCashe2d[j];
1054 p2d = mySurf->ValueOfUV(p3d, myPreci);
1059 p2d = mySurf->NextValueOfUV (p2d, p3d, myPreci, //:S4030: optimizing
1060 Precision::Confusion()+1000*gap); //:q1
1062 gap = mySurf->Gap();
1065 pnt2d (aPntIndex) = p2d;
1068 p2d.SetXY ( 2. * p2d.XY() - pnt2d(aPntIndex + 1).XY() );
1070 p2d.SetXY ( 2. * p2d.XY() - pnt2d(aPntIndex - 1).XY() );
1074 //pdn %12 11.02.99 PRO9234 entity 15402
1076 mySurf->ProjectDegenerated(nbrPnt,points,pnt2d,myPreci,Standard_True);
1077 mySurf->ProjectDegenerated(nbrPnt,points,pnt2d,myPreci,Standard_False);
1080 //Check the extremities of 3d curve for coinciding with singularities of surf
1081 //Standard_Integer NbSing = mySurf->NbSingularities(Precision::Confusion());
1082 gp_Pnt PointFirst = points.First(), PointLast = points.Last();
1083 Standard_Real aTolFirst = (TolFirst == -1)? Precision::Confusion() : TolFirst;
1084 Standard_Real aTolLast = (TolLast == -1)? Precision::Confusion() : TolLast;
1085 for (Standard_Integer i = 1; ; i++)
1087 Standard_Real aPreci, aFirstPar, aLastPar;
1089 gp_Pnt2d aFirstP2d, aLastP2d;
1090 Standard_Boolean IsUiso;
1091 if (!mySurf->Singularity(i, aPreci, aP3d, aFirstP2d, aLastP2d, aFirstPar, aLastPar, IsUiso))
1093 if (aPreci <= Precision::Confusion() &&
1094 PointFirst.Distance(aP3d) <= aTolFirst)
1096 CorrectExtremity(c3d, params, pnt2d,
1097 Standard_True, //first point
1101 if (aPreci <= Precision::Confusion() &&
1102 PointLast.Distance(aP3d) <= aTolLast)
1104 CorrectExtremity(c3d, params, pnt2d,
1105 Standard_False, //last point
1111 // attention aux singularites ... (hors cas iso qui les traite deja)
1114 // if (mySurf->ProjectDegenerated (points(1),myPreci,pnt2d (2),p2d))
1116 // p2d = pnt2d (nbrPnt);
1117 // if (mySurf->ProjectDegenerated (points(nbrPnt),myPreci,pnt2d (nbrPnt-1),p2d))
1118 // pnt2d (nbrPnt) = p2d;
1121 // Si la surface est UCLosed et VClosed, on recadre les points
1122 // algo un peu complique, on retarde l implementation
1123 Standard_Real Up = ul - uf;
1124 Standard_Real Vp = vl - vf;
1125 Standard_Real dist2d;
1126 const Standard_Real TolOnUPeriod = Precision::Confusion() * Up;
1127 const Standard_Real TolOnVPeriod = Precision::Confusion() * Vp;
1129 if (mySurf->IsUClosed(myPreci) && mySurf->IsVClosed(myPreci)) {//#78 rln 12.03.99 S4135
1130 std::cout << "WARNING : Recadrage incertain sur U & VClosed" << std::endl;
1133 // Si la surface est UCLosed, on recadre les points
1134 if (mySurf->IsUClosed(myPreci)) {//#78 rln 12.03.99 S4135
1135 // Premier point dans le domain [uf, ul]
1136 Standard_Real prevX, firstX = pnt2d (1).X();
1138 // do not shift 2dcurve, if it connects to previous
1139 while (firstX < uf) { firstX += Up; pnt2d (1).SetX(firstX); }
1140 while (firstX > ul) { firstX -= Up; pnt2d (1).SetX(firstX); }
1142 // shift first point, according to cashe
1143 if (mySurf->Surface()->IsUPeriodic() && isFromCashe) {
1144 Standard_Real aMinParam = uf, aMaxParam = ul;
1145 while (aMinParam > aSavedPoint.X()) {
1149 while (aMaxParam < aSavedPoint.X()) {
1153 Standard_Real aShift = ShapeAnalysis::AdjustToPeriod(firstX, aMinParam, aMaxParam);
1155 pnt2d(1).SetX(firstX);
1159 //:97 abv 1 Feb 98: treat case when curve is whole out of surface bounds
1160 Standard_Real minX = firstX, maxX = firstX;
1161 Standard_Boolean ToAdjust = Standard_False;
1163 // On decalle toujours le suivant
1164 for (Standard_Integer aPntIter = 2; aPntIter <= pnt2d.Length(); ++aPntIter)
1166 // dist2d = pnt2d (aPntIter - 1).Distance(pnt2d (aPntIter));
1167 Standard_Real CurX = pnt2d (aPntIter).X();
1168 dist2d = Abs (CurX - prevX);
1169 if (dist2d > ( Up / 2) )
1171 InsertAdditionalPointOrAdjust(ToAdjust, 1, Up, TolOnUPeriod,
1175 points, params, pnt2d);
1178 if ( minX > CurX ) minX = CurX; //:97
1179 else if ( maxX < CurX ) maxX = CurX; //:97
1184 // do not shift 2dcurve, if it connects to previous
1185 Standard_Real midX = 0.5 * ( minX + maxX );
1186 Standard_Real shiftX=0.;
1187 if ( midX > ul ) shiftX = -Up;
1188 else if ( midX < uf ) shiftX = Up;
1190 for (Standard_Integer aPntIter = 1; aPntIter <= pnt2d.Length(); ++aPntIter)
1191 pnt2d (aPntIter).SetX ( pnt2d (aPntIter).X() + shiftX );
1194 // Si la surface est VCLosed, on recadre les points
1195 // Same code as UClosed : optimisation souhaitable !!
1196 // CKY : d abord un code IDENTIQUE A UClosed; PUIS le special Seam ...
1197 // Si la surface est UCLosed, on recadre les points
1199 //#69 rln 01.03.99 S4135 bm2_sd_t4-A.stp entity 30
1200 //#78 rln 12.03.99 S4135
1201 if (mySurf->IsVClosed(myPreci) || mySurf->Surface()->IsKind (STANDARD_TYPE (Geom_SphericalSurface))) {
1202 // Premier point dans le domain [vf, vl]
1203 Standard_Real prevY, firstY = pnt2d (1).Y();
1205 // do not shift 2dcurve, if it connects to previous
1206 while (firstY < vf) { firstY += Vp; pnt2d (1).SetY(firstY); }
1207 while (firstY > vl) { firstY -= Vp; pnt2d (1).SetY(firstY); }
1209 // shift first point, according to cashe
1210 if (mySurf->Surface()->IsVPeriodic() && isFromCashe) {
1211 Standard_Real aMinParam = vf, aMaxParam = vl;
1212 while (aMinParam > aSavedPoint.Y()) {
1216 while (aMaxParam < aSavedPoint.Y()) {
1220 Standard_Real aShift = ShapeAnalysis::AdjustToPeriod(firstY, aMinParam, aMaxParam);
1222 pnt2d(1).SetY(firstY);
1226 //:97 abv 1 Feb 98: treat case when curve is whole out of surface bounds
1227 Standard_Real minY = firstY, maxY = firstY;
1228 Standard_Boolean ToAdjust = Standard_False;
1230 // On decalle toujours le suivant
1231 for (Standard_Integer aPntIter = 2; aPntIter <= pnt2d.Length(); ++aPntIter)
1233 // dist2d = pnt2d (i-1).Distance(pnt2d (i));
1234 Standard_Real CurY = pnt2d (aPntIter).Y();
1235 dist2d = Abs (CurY - prevY);
1236 if (dist2d > ( Vp / 2) )
1238 InsertAdditionalPointOrAdjust(ToAdjust, 2, Vp, TolOnVPeriod,
1242 points, params, pnt2d);
1245 if ( minY > CurY ) minY = CurY; //:97
1246 else if ( maxY < CurY ) maxY = CurY; //:97
1251 // do not shift 2dcurve, if it connects to previous
1252 Standard_Real midY = 0.5 * ( minY + maxY );
1253 Standard_Real shiftY=0.;
1254 if ( midY > vl ) shiftY = -Vp;
1255 else if ( midY < vf ) shiftY = Vp;
1257 for (Standard_Integer aPntIter = 1; aPntIter <= pnt2d.Length(); ++aPntIter)
1258 pnt2d(aPntIter).SetY ( pnt2d(aPntIter).Y() + shiftY );
1262 //#69 rln 01.03.99 S4135 bm2_sd_t4-A.stp entity 30
1263 //#78 rln 12.03.99 S4135
1264 if (mySurf->IsVClosed(myPreci) || mySurf->Surface()->IsKind (STANDARD_TYPE (Geom_SphericalSurface))) {
1265 for (Standard_Integer aPntIter = 2; aPntIter <= pnt2d.Length(); ++aPntIter) {
1266 //#1 rln 11/02/98 ca_exhaust.stp entity #9869 dist2d = pnt2d (i-1).Distance(pnt2d (i));
1267 dist2d = Abs (pnt2d (aPntIter).Y() - pnt2d (aPntIter - 1).Y());
1268 if (dist2d > ( Vp / 2) ) {
1269 // ATTENTION : il faut regarder ou le decalage se fait.
1270 // si plusieurs points sont decalles, il faut plusieurs passes
1271 // pour obtenir un resultat correct.
1272 // NOT YET IMPLEMENTED
1274 // one of those point is incorrectly placed
1275 // i.e on the wrong side of the "seam"
1276 // on prend le point le plus pres des bords vf ou vl
1277 Standard_Boolean prevOnFirst = Standard_False;
1278 Standard_Boolean prevOnLast = Standard_False;
1279 Standard_Boolean currOnFirst = Standard_False;
1280 Standard_Boolean currOnLast = Standard_False;
1282 // .X ? plutot .Y , non ?
1283 Standard_Real distPrevVF = Abs(pnt2d (aPntIter - 1).Y() - vf);
1284 Standard_Real distPrevVL = Abs(pnt2d (aPntIter - 1).Y() - vl);
1285 Standard_Real distCurrVF = Abs(pnt2d (aPntIter).Y() - vf);
1286 Standard_Real distCurrVL = Abs(pnt2d (aPntIter).Y() - vl);
1288 Standard_Real theMin = distPrevVF;
1289 prevOnFirst = Standard_True;
1290 if (distPrevVL < theMin) {
1291 theMin = distPrevVL;
1292 prevOnFirst = Standard_False;
1293 prevOnLast = Standard_True;
1295 if (distCurrVF < theMin) {
1296 theMin = distCurrVF;
1297 prevOnFirst = Standard_False;
1298 prevOnLast = Standard_False;
1299 currOnFirst = Standard_True;
1301 if (distCurrVL < theMin) {
1302 theMin = distCurrVL;
1303 prevOnFirst = Standard_False;
1304 prevOnLast = Standard_False;
1305 currOnFirst = Standard_False;
1306 currOnLast = Standard_True;
1308 // Modifs RLN/Nijni 3-DEC-1997
1310 // on decalle le point (aPntIter - 1) en V Last
1311 gp_Pnt2d newPrev(pnt2d (aPntIter - 1).X(), vf); // instead of vl RLN/Nijni
1312 pnt2d (aPntIter - 1) = newPrev;
1314 else if (prevOnLast) {
1315 // on decalle le point (aPntIter - 1) en V first
1316 gp_Pnt2d newPrev(pnt2d (aPntIter - 1).X(), vl); // instead of vf RLN/Nijni
1317 pnt2d (aPntIter - 1) = newPrev;
1319 else if (currOnFirst) {
1320 // on decalle le point (aPntIter) en V Last
1321 gp_Pnt2d newCurr(pnt2d (aPntIter).X(),vf); // instead of vl RLN/Nijni
1322 pnt2d (aPntIter) = newCurr;
1324 else if (currOnLast) {
1325 // on decalle le point (aPntIter) en V First
1326 gp_Pnt2d newCurr(pnt2d (aPntIter).X(), vl); // instead of vf RLN/Nijni
1327 pnt2d (aPntIter) = newCurr;
1331 dist2d = pnt2d (aPntIter - 1).Distance(pnt2d (aPntIter));
1332 if (dist2d > ( Vp / 2) ) {
1333 std::cout << "Echec dans le recadrage" << std::endl;
1340 //:c0 abv 20 Feb 98: treat very special case when 3d curve
1341 // go over the pole of, e.g., sphere, and partly lies along seam.
1342 // 2d representation of such a curve should consist of 3 parts - one on
1343 // regular part of surface (interior), one part along degenerated boundary
1344 // and one along seam.
1345 // Since it cannot be adjusted later by arranging pcurves (curve is single),
1346 // to fix it it is nesessary to have a possibility of adjusting seam
1347 // part of such curve either to left or right boundary of surface.
1348 // Test is performed only if flag AdjustOverDegen is not -1.
1349 // If AdjustOverDegen is True, seam part of curve is adjusted to
1350 // the left, and if False - to the right parametric boundary
1351 // If treated case is detected, flag DONE4 is set to status
1352 // NOTE: currently, precision is Precision::PConfusion() since it
1353 // is enough on encountered example
1354 // (ug_turbine-A.stp from ProSTEP Benchmark #3, entities ##2470 & 5680)
1355 // (r1001_ac.stp from Test Rally #10, face #35027 and others)
1356 if ( myAdjustOverDegen != -1 ) {
1357 if ( mySurf->IsUClosed(myPreci) ) {//#78 rln 12.03.99 S4135
1358 mySurf->IsDegenerated ( gp_Pnt(0,0,0), myPreci ); // pour calculer les dgnr
1359 if ( mySurf->NbSingularities(myPreci) > 0 ) { //rln S4135
1360 // 1st, find gap point (degenerated pole)
1361 Standard_Real PrevX=0.;
1362 Standard_Integer OnBound=0, PrevOnBound=0;
1363 Standard_Integer ind; // svv #1
1364 Standard_Boolean start = Standard_True;
1365 for ( ind=1; ind <= pnt2d.Length(); ind++ ) {
1366 Standard_Real CurX = pnt2d(ind).X();
1367 // abv 16 Mar 00: trj3_s1-ug.stp #697: ignore points in singularity
1368 if ( mySurf->IsDegenerated ( points(ind), Precision::Confusion() ) )
1370 OnBound = ( Abs ( Abs ( CurX - 0.5 * ( ul + uf ) ) - Up/2 ) <=
1371 Precision::PConfusion() );
1372 if ( ! start && Abs ( Abs ( CurX - PrevX ) - Up/2 ) <= 0.01*Up )
1374 start = Standard_False;
1376 PrevOnBound = OnBound;
1378 // if found, adjust seam part
1379 if ( ind <= pnt2d.Length() ) {
1380 PrevX = ( myAdjustOverDegen ? uf : ul );
1381 Standard_Real dU = Up/2 + Precision::PConfusion();
1382 if ( PrevOnBound ) {
1383 pnt2d(ind-1).SetX ( PrevX );
1384 for ( Standard_Integer j=ind-2; j >0; j-- ) {
1385 Standard_Real CurX = pnt2d(j).X();
1386 while ( CurX < PrevX - dU ) pnt2d(j).SetX ( CurX += Up );
1387 while ( CurX > PrevX + dU ) pnt2d(j).SetX ( CurX -= Up );
1390 else if ( OnBound ) {
1391 pnt2d(ind).SetX ( PrevX );
1392 for ( Standard_Integer j=ind+1; j <= pnt2d.Length(); j++ ) {
1393 Standard_Real CurX = pnt2d(j).X();
1394 while ( CurX < PrevX - dU ) pnt2d(j).SetX ( CurX += Up );
1395 while ( CurX > PrevX + dU ) pnt2d(j).SetX ( CurX -= Up );
1398 myStatus |= ShapeExtend::EncodeStatus (ShapeExtend_DONE4);
1402 else if ( mySurf->IsVClosed(myPreci) ) {//#78 rln 12.03.99 S4135
1403 mySurf->IsDegenerated ( gp_Pnt(0,0,0), myPreci ); // pour calculer les dgnr
1404 if ( mySurf->NbSingularities(myPreci) > 0 ) { //rln S4135
1405 // 1st, find gap point (degenerated pole)
1406 Standard_Real PrevY=0.;
1407 Standard_Integer OnBound=0, PrevOnBound=0;
1408 Standard_Integer ind; // svv #1
1409 Standard_Boolean start = Standard_True;
1410 for ( ind=1; ind <= pnt2d.Length(); ind++ ) {
1411 Standard_Real CurY = pnt2d(ind).Y();
1412 // abv 16 Mar 00: trj3_s1-ug.stp #697: ignore points in singularity
1413 if ( mySurf->IsDegenerated ( points(ind), Precision::Confusion() ) )
1415 OnBound = ( Abs ( Abs ( CurY - 0.5 * ( vl + vf ) ) - Vp/2 ) <=
1416 Precision::PConfusion() );
1417 if ( ! start && Abs ( Abs ( CurY - PrevY ) - Vp/2 ) <= 0.01*Vp )
1419 start = Standard_False;
1421 PrevOnBound = OnBound;
1423 // if found, adjust seam part
1424 if ( ind <= pnt2d.Length() ) {
1425 PrevY = ( myAdjustOverDegen ? vf : vl );
1426 Standard_Real dV = Vp/2 + Precision::PConfusion();
1427 if ( PrevOnBound ) {
1428 pnt2d(ind-1).SetY ( PrevY );
1429 for ( Standard_Integer j=ind-2; j >0; j-- ) {
1430 Standard_Real CurY = pnt2d(j).Y();
1431 while ( CurY < PrevY - dV ) pnt2d(j).SetY ( CurY += Vp );
1432 while ( CurY > PrevY + dV ) pnt2d(j).SetY ( CurY -= Vp );
1435 else if ( OnBound ) {
1436 pnt2d(ind).SetY ( PrevY );
1437 for ( Standard_Integer j=ind+1; j <= pnt2d.Length(); j++ ) {
1438 Standard_Real CurY = pnt2d(j).Y();
1439 while ( CurY < PrevY - dV ) pnt2d(j).SetY ( CurY += Vp );
1440 while ( CurY > PrevY + dV ) pnt2d(j).SetY ( CurY -= Vp );
1443 myStatus |= ShapeExtend::EncodeStatus (ShapeExtend_DONE4);
1451 if(ChangeCycle) { // msv 10.08.04: avoid using of uninitialised field
1452 //if(myCashe3d[0].Distance(points(1))>Precision::Confusion() &&
1453 // myCashe3d[1].Distance(points(1))>Precision::Confusion()) {
1454 myCashe3d[0] = points(1);
1455 myCashe3d[1] = points.Last();
1456 myCashe2d[0] = pnt2d(1);
1457 myCashe2d[1] = pnt2d.Last();
1460 myCashe3d[1] = points(1);
1461 myCashe3d[0] = points.Last();
1462 myCashe2d[1] = pnt2d(1);
1463 myCashe2d[0] = pnt2d.Last();
1468 //=======================================================================
1469 //function : ApproximatePCurve
1471 //=======================================================================
1473 Handle(Geom2d_Curve) ShapeConstruct_ProjectCurveOnSurface::ApproximatePCurve(const Standard_Integer /*nbrPnt*/,
1474 Handle(TColgp_HArray1OfPnt2d)& points2d,
1475 Handle(TColStd_HArray1OfReal)& params,
1476 const Handle(Geom_Curve)& /*orig*/) const
1478 // Standard_Real resol = Min(mySurf->Adaptor3d()->VResolution(myPreci), mySurf->Adaptor3d()->UResolution(myPreci));
1479 Standard_Real theTolerance2d = myPreci; // (100*nbrPnt);//resol;
1480 Handle(Geom2d_Curve) C2d;
1483 CheckPoints2d (points2d, params, theTolerance2d);
1484 Standard_Integer numberPnt = points2d->Length();
1486 TColgp_Array1OfPnt points3d(1,numberPnt);
1489 Standard_Integer i; // svv #1
1490 for( i = 1; i <= numberPnt; i++) {
1491 pnt2d = points2d->Value(i);
1492 pnt.SetCoord(pnt2d.X(),pnt2d.Y(),0);
1496 GeomAPI_PointsToBSpline appr(points3d, params->Array1(), 1, 10, GeomAbs_C1, theTolerance2d);
1497 Handle(Geom_BSplineCurve) crv3d = appr.Curve();
1498 Standard_Integer NbPoles = crv3d->NbPoles();
1499 TColgp_Array1OfPnt poles3d (1, NbPoles);
1500 TColgp_Array1OfPnt2d poles2d (1, NbPoles);
1501 crv3d->Poles(poles3d);
1502 for( i = 1; i <= NbPoles; i++) {
1503 pnt2d.SetCoord(poles3d(i).X(),poles3d(i).Y());
1506 TColStd_Array1OfReal weights (1,NbPoles);
1507 TColStd_Array1OfInteger multiplicities (1,crv3d->NbKnots());
1508 TColStd_Array1OfReal knots(1,crv3d->NbKnots());
1509 crv3d->Knots(knots);
1510 crv3d->Weights(weights);
1511 crv3d->Multiplicities(multiplicities);
1512 C2d = new Geom2d_BSplineCurve ( poles2d, weights, knots, multiplicities, crv3d->Degree(), crv3d->IsPeriodic());
1515 catch(Standard_Failure const& anException) {
1519 Standard_Integer nbp = params->Length();
1520 Standard_Integer nb2 = points2d->Length();
1521 std::cout << "Warning: ShapeConstruct_ProjectCurveOnSurface::ApproximatePCurve(): Exception: ";
1522 anException.Print(std::cout);
1523 std::cout<<"Pb Geom2dAPI_Approximate, tol2d="<<theTolerance2d<<" NbParams="<<nbp<<" NbPnts="<<nb2<<std::endl;
1524 // if (nb2 > nbp) nb2 = nbp;
1525 // Standard_Real rbp,rb2; rbp = nbp; rb2 = nb2;
1526 // // dbl.AddString ("NbP2d/NbParams puis X Y Param -> mini");
1527 // dbl.AddReals (rb2,rbp);
1528 // for (Standard_Integer i = 1; i <= nb2; i ++) {
1529 // gp_XYZ quoi (points2d->Value(i).X(),points2d->Value(i).Y(),params->Value(i) );
1530 // dbl.AddXYZ (quoi);
1539 //=======================================================================
1540 //function : InterpolatePCurve
1542 //=======================================================================
1544 Handle(Geom2d_Curve) ShapeConstruct_ProjectCurveOnSurface::InterpolatePCurve(const Standard_Integer nbrPnt,
1545 Handle(TColgp_HArray1OfPnt2d)& points2d,
1546 Handle(TColStd_HArray1OfReal)& params,
1547 const Handle(Geom_Curve)& /*orig*/) const
1549 Handle(Geom2d_Curve) C2d; // NULL si echec
1550 Standard_Real theTolerance2d = myPreci / (100 * nbrPnt);
1553 // on verifie d abord s il n y a pas de points confondus
1554 // si besoin on retouche les valeurs ...
1555 CheckPoints2d (points2d, params, theTolerance2d);
1556 Geom2dAPI_Interpolate myInterPol2d (points2d, params,
1557 Standard_False, theTolerance2d);
1558 myInterPol2d.Perform();
1559 if (myInterPol2d.IsDone()) C2d = myInterPol2d.Curve();
1561 catch(Standard_Failure const& anException) {
1565 Standard_Integer nbp = params->Length();
1566 Standard_Integer nb2 = points2d->Length();
1567 std::cout << "Warning: ShapeConstruct_ProjectCurveOnSurface::InterpolatePCurve(): Exception: ";
1568 anException.Print(std::cout);
1569 std::cout<<"Pb Geom2dAPI_Interpolate, tol2d="<<theTolerance2d<<" NbParams="<<nbp<<" NbPnts="<<nb2<<std::endl;
1570 // if (nb2 > nbp) nb2 = nbp;
1571 // Standard_Real rbp,rb2; rbp = nbp; rb2 = nb2;
1572 // // dbl.AddString ("NbP2d/NbParams puis X Y Param -> mini");
1573 // dbl.AddReals (rb2,rbp);
1574 // for (Standard_Integer i = 1; i <= nb2; i ++) {
1575 // gp_XYZ quoi (points2d->Value(i).X(),points2d->Value(i).Y(),params->Value(i) );
1576 // dbl.AddXYZ (quoi);
1585 //=======================================================================
1586 //function : InterpolateCurve3d
1588 //=======================================================================
1590 Handle(Geom_Curve) ShapeConstruct_ProjectCurveOnSurface::InterpolateCurve3d(const Standard_Integer,
1591 Handle(TColgp_HArray1OfPnt)& points,
1592 Handle(TColStd_HArray1OfReal)& params,
1593 const Handle(Geom_Curve)& /*orig*/) const
1595 Handle(Geom_Curve) C3d; // NULL si echec
1598 Standard_Real Tol = myPreci;
1599 CheckPoints(points, params, Tol);
1600 GeomAPI_Interpolate myInterPol(points, params, Standard_False, Tol);
1601 myInterPol.Perform();
1602 if (myInterPol.IsDone()) C3d = myInterPol.Curve();
1604 catch(Standard_Failure const& anException) {
1607 std::cout << "Warning: ShapeConstruct_ProjectCurveOnSurface::InterpolateCurve3d(): Exception: ";
1608 anException.Print(std::cout); std::cout << std::endl;
1616 //============================================================================================
1617 //function : CorrectExtremity
1618 //purpose : corrects first or last 2d point of future curve
1619 // in the case when it coincids with a singularity of surface
1620 //============================================================================================
1622 void ShapeConstruct_ProjectCurveOnSurface::CorrectExtremity(const Handle(Geom_Curve)& theC3d,
1623 const TColStd_SequenceOfReal& theParams,
1624 TColgp_SequenceOfPnt2d& thePnt2d,
1625 const Standard_Boolean theIsFirstPoint,
1626 const gp_Pnt2d& thePointOnIsoLine,
1627 const Standard_Boolean theIsUiso)
1629 Standard_Integer NbPnt = thePnt2d.Length();
1630 Standard_Integer IndCoord = (theIsUiso)? 2 : 1;
1631 Standard_Real SingularityCoord = thePointOnIsoLine.Coord(3-IndCoord);
1632 gp_Pnt2d EndPoint = (theIsFirstPoint)? thePnt2d(1) : thePnt2d(NbPnt);
1633 Standard_Real FinishCoord = EndPoint.Coord(3-IndCoord); //the constant coord of isoline
1635 gp_Dir2d aDir = (theIsUiso)? gp::DY2d() : gp::DX2d();
1636 gp_Lin2d anIsoLine(EndPoint, aDir);
1637 IntRes2d_Domain Dom1, Dom2;
1639 Standard_Boolean IsPeriodic = (theIsUiso)?
1640 mySurf->Surface()->IsVPeriodic() : mySurf->Surface()->IsUPeriodic();
1642 gp_Pnt2d FirstPointOfLine, SecondPointOfLine;
1643 Standard_Real FinishParam, FirstParam, SecondParam;
1645 if (theIsFirstPoint)
1647 FirstPointOfLine = thePnt2d(3);
1648 SecondPointOfLine = thePnt2d(2);
1649 FinishParam = theParams(1);
1650 FirstParam = theParams(3);
1651 SecondParam = theParams(2);
1655 FirstPointOfLine = thePnt2d(NbPnt-2);
1656 SecondPointOfLine = thePnt2d(NbPnt-1);
1657 FinishParam = theParams(NbPnt);
1658 FirstParam = theParams(NbPnt-2);
1659 SecondParam = theParams(NbPnt-1);
1662 if (SingularityCoord > FinishCoord &&
1663 SecondPointOfLine.Coord(3-IndCoord) > FinishCoord)
1664 return; //the curve passes through the singularity, do nothing
1665 if (SingularityCoord < FinishCoord &&
1666 SecondPointOfLine.Coord(3-IndCoord) < FinishCoord)
1667 return; //the curve passes through the singularity, do nothing
1668 //Check correctness of <EndPoint>
1670 const Standard_Real aPrevDist = Abs(SecondPointOfLine.Coord(IndCoord) - FirstPointOfLine.Coord(IndCoord));
1671 const Standard_Real aCurDist = Abs(EndPoint.Coord(IndCoord) - SecondPointOfLine.Coord(IndCoord));
1672 if (aCurDist <= 2 * aPrevDist)
1676 gp_Pnt2d FinishPoint = (theIsUiso)? gp_Pnt2d(FinishCoord, SecondPointOfLine.Y()) :
1677 gp_Pnt2d(SecondPointOfLine.X(), FinishCoord); //first approximation of <FinishPoint>
1681 if (Abs(SecondPointOfLine.Coord(3-IndCoord) - FinishCoord) <= 2*Precision::PConfusion())
1684 gp_Vec2d aVec(FirstPointOfLine, SecondPointOfLine);
1685 Standard_Real aSqMagnitude = aVec.SquareMagnitude();
1686 if (aSqMagnitude <= 1.e-32)
1688 aDir.SetCoord(aVec.X(), aVec.Y());
1690 gp_Lin2d aLine(FirstPointOfLine, aDir);
1691 IntCurve_IntConicConic Intersector(anIsoLine, Dom1,
1694 if (Intersector.IsDone() && !Intersector.IsEmpty())
1696 IntRes2d_IntersectionPoint IntPoint = Intersector.Point(1);
1697 FinishPoint = IntPoint.Value();
1700 FinishPoint = (theIsUiso)? gp_Pnt2d(FinishCoord, SecondPointOfLine.Y()) :
1701 gp_Pnt2d(SecondPointOfLine.X(), FinishCoord);
1703 gp_Pnt2d PrevPoint = FirstPointOfLine;
1704 FirstPointOfLine = SecondPointOfLine;
1705 FirstParam = SecondParam;
1706 SecondParam = (FirstParam + FinishParam)/2;
1707 if (Abs(SecondParam - FirstParam) <= 2*Precision::PConfusion())
1710 theC3d->D0(SecondParam, aP3d);
1711 SecondPointOfLine = mySurf->NextValueOfUV(FirstPointOfLine, aP3d,
1712 myPreci, Precision::Confusion());
1714 AdjustSecondPointToFirstPoint(FirstPointOfLine, SecondPointOfLine, mySurf->Surface());
1716 //Check <SecondPointOfLine> to be enough close to <FirstPointOfLine>
1717 //because when a projected point is too close to singularity,
1718 //the non-constant coordinate becomes random.
1719 const Standard_Real aPrevDist = Abs(FirstPointOfLine.Coord(IndCoord) - PrevPoint.Coord(IndCoord));
1720 const Standard_Real aCurDist = Abs(SecondPointOfLine.Coord(IndCoord) - FirstPointOfLine.Coord(IndCoord));
1721 if (aCurDist > 2 * aPrevDist)
1725 if (theIsFirstPoint)
1726 thePnt2d(1) = FinishPoint;
1728 thePnt2d(NbPnt) = FinishPoint;
1731 //============================================================================================
1732 //function : InsertAdditionalPointOrAdjust
1733 //purpose : If the current point is too far from the previous point
1734 // (more than half-period of surface), it can happen in two cases:
1735 // 1. Real current step on corresponding coordinate is small, all we need is adjust;
1736 // 2. Current step on corresponding coordinate is really bigger than half-period of
1737 // surface in this parametric direction, so we must add additional point to exclude
1738 // such big intervals between points in 2d space.
1739 //============================================================================================
1741 void ShapeConstruct_ProjectCurveOnSurface::
1742 InsertAdditionalPointOrAdjust(Standard_Boolean& ToAdjust,
1743 const Standard_Integer theIndCoord,
1744 const Standard_Real Period,
1745 const Standard_Real TolOnPeriod,
1746 Standard_Real& CurCoord,
1747 const Standard_Real prevCoord,
1748 const Handle(Geom_Curve)& c3d,
1749 Standard_Integer& theIndex,
1750 TColgp_SequenceOfPnt& points,
1751 TColStd_SequenceOfReal& params,
1752 TColgp_SequenceOfPnt2d& pnt2d)
1754 Standard_Real CorrectedCurCoord = ElCLib::InPeriod(CurCoord,
1755 prevCoord - Period/2,
1756 prevCoord + Period/2);
1759 Standard_Real CurPar = params(theIndex);
1760 Standard_Real PrevPar = params(theIndex-1);
1761 Standard_Real MidPar = (PrevPar + CurPar)/2;
1763 c3d->D0(MidPar, MidP3d);
1764 gp_Pnt2d MidP2d = mySurf->ValueOfUV(MidP3d, myPreci);
1765 Standard_Real MidCoord = MidP2d.Coord(theIndCoord);
1766 MidCoord = ElCLib::InPeriod(MidCoord, prevCoord - Period/2, prevCoord + Period/2);
1767 Standard_Real FirstCoord = prevCoord, LastCoord = CorrectedCurCoord;
1768 if (LastCoord < FirstCoord)
1769 {Standard_Real tmp = FirstCoord; FirstCoord = LastCoord; LastCoord = tmp;}
1770 if (LastCoord - FirstCoord <= TolOnPeriod)
1771 ToAdjust = Standard_True;
1772 else if (FirstCoord <= MidCoord && MidCoord <= LastCoord)
1773 ToAdjust = Standard_True;
1774 else //add mid point
1776 //Standard_Real RefU = prevX;
1777 Standard_Boolean Success = Standard_True;
1778 Standard_Real FirstT = PrevPar; //params(i-1)
1779 Standard_Real LastT = CurPar; //params(i)
1780 MidCoord = MidP2d.Coord(theIndCoord);
1781 while (Abs(MidCoord - prevCoord) >= Period/2 - TolOnPeriod ||
1782 Abs(CurCoord - MidCoord) >= Period/2 - TolOnPeriod)
1784 if (MidPar - FirstT <= Precision::PConfusion() ||
1785 LastT - MidPar <= Precision::PConfusion())
1787 Success = Standard_False;
1788 break; //wrong choice
1790 if (Abs(MidCoord - prevCoord) >= Period/2 - TolOnPeriod)
1791 LastT = (FirstT + LastT)/2;
1793 FirstT = (FirstT + LastT)/2;
1794 MidPar = (FirstT + LastT)/2;
1795 c3d->D0(MidPar, MidP3d);
1796 MidP2d = mySurf->ValueOfUV(MidP3d, myPreci);
1797 MidCoord = MidP2d.Coord(theIndCoord);
1801 points.InsertBefore(theIndex, MidP3d);
1802 params.InsertBefore(theIndex, MidPar);
1803 pnt2d.InsertBefore(theIndex, MidP2d);
1807 ToAdjust = Standard_True;
1812 CurCoord = CorrectedCurCoord;
1813 pnt2d(theIndex).SetCoord (theIndCoord, CurCoord);
1817 //=======================================================================
1818 //function : CheckPoints
1820 //=======================================================================
1822 void ShapeConstruct_ProjectCurveOnSurface::CheckPoints(Handle(TColgp_HArray1OfPnt)& points,Handle(TColStd_HArray1OfReal)& params,Standard_Real& preci) const
1824 Standard_Integer firstElem = points->Lower();
1825 Standard_Integer lastElem = points->Upper();
1827 Standard_Integer nbPntDropped = 0;
1828 Standard_Integer lastValid = firstElem; // indice of last undropped point
1830 // will store 0 when the point is to be removed, 1 otherwise
1831 TColStd_Array1OfInteger tmpParam(firstElem, lastElem);
1832 for (i = firstElem; i<=lastElem ; i++)
1833 tmpParam.SetValue(i,1);
1834 Standard_Real DistMin2 = RealLast();
1835 gp_Pnt Prev = points->Value (lastValid);
1837 for (i = firstElem + 1; i <= lastElem ; i ++) {
1838 Curr = points->Value(i);
1839 Standard_Real CurDist2 = Prev.SquareDistance(Curr);
1840 if (CurDist2 < gp::Resolution()) { // test 0
1842 if ( i == lastElem ) tmpParam.SetValue(lastValid, 0); // last point kept
1843 else tmpParam.SetValue(i, 0); // current dropped, lastValid unchanged
1845 if (CurDist2 < DistMin2)
1846 DistMin2 = CurDist2;
1847 // lastValid becomes the current (i.e. i)
1852 if (DistMin2 < RealLast())
1853 preci = 0.9 * Sqrt (DistMin2); // preci est la distance min entre les points on la reduit un peu
1854 if (nbPntDropped == 0)
1858 std::cout << "Warning : removing 3d points for interpolation" << std::endl;
1860 // Build new HArrays
1861 Standard_Integer newLast = lastElem - nbPntDropped;
1862 if ((newLast - firstElem + 1) < 2) {
1864 std::cout << "Too many degenerated points for 3D interpolation" << std::endl;
1868 Handle(TColgp_HArray1OfPnt) newPnts =
1869 new TColgp_HArray1OfPnt(firstElem, newLast);
1870 Handle(TColStd_HArray1OfReal) newParams =
1871 new TColStd_HArray1OfReal(firstElem, newLast);
1872 Standard_Integer newCurr = 1;
1873 for (i = firstElem; i<= lastElem ; i++) {
1874 if (tmpParam.Value(i) == 1) {
1875 newPnts->SetValue(newCurr, points->Value(i));
1876 newParams->SetValue(newCurr, params->Value(i));
1882 // on la reduit un peu
1885 //=======================================================================
1886 //function : CheckPoints2d
1888 //=======================================================================
1890 void ShapeConstruct_ProjectCurveOnSurface::CheckPoints2d(Handle(TColgp_HArray1OfPnt2d)& points,
1891 Handle(TColStd_HArray1OfReal)& params,
1892 Standard_Real& preci) const
1894 Standard_Integer firstElem = points->Lower();
1895 Standard_Integer lastElem = points->Upper();
1897 Standard_Integer nbPntDropped = 0;
1898 Standard_Integer lastValid = firstElem; // indice of last undropped point
1900 // will store 0 when the point is to be removed, 1 otherwise
1901 TColStd_Array1OfInteger tmpParam(firstElem, lastElem);
1902 for (i = firstElem; i<=lastElem ; i++) {
1903 tmpParam.SetValue(i,1);
1905 Standard_Real DistMin2 = RealLast();
1906 gp_Pnt2d Prev = points->Value(lastValid);
1908 for (i = firstElem + 1; i<=lastElem ; i++) {
1909 Curr = points->Value(i);
1910 Standard_Real CurDist2 = Prev.SquareDistance(Curr);
1911 if (CurDist2 < gp::Resolution()) { // test 0
1913 if ( i == lastElem ) tmpParam.SetValue(lastValid, 0); // last point kept
1914 else tmpParam.SetValue(i, 0); // current dropped, lastValid unchanged
1916 if (CurDist2 < DistMin2)
1917 DistMin2 = CurDist2;
1918 // lastValid becomes the current (i.e. i)
1923 if (DistMin2 < RealLast())
1924 preci = 0.9 * Sqrt (DistMin2);
1925 if (nbPntDropped == 0)
1929 std::cout << "Warning : removing 2d points for interpolation" << std::endl;
1931 // Build new HArrays
1932 Standard_Integer newLast = lastElem - nbPntDropped;
1933 if ((newLast - firstElem + 1) < 2) {
1935 std::cout << "Too many degenerated points for 2D interpolation" << std::endl;
1937 //pdn 12.02.99 S4135 Creating pcurve with minimal length.
1938 tmpParam.SetValue(firstElem,1);
1939 tmpParam.SetValue(lastElem,1);
1940 gp_XY lastPnt = points->Value(lastElem).XY();
1941 lastPnt.Add(gp_XY(preci,preci));
1942 points->SetValue(lastElem,lastPnt);
1943 newLast = firstElem+1;
1946 Handle(TColgp_HArray1OfPnt2d) newPnts =
1947 new TColgp_HArray1OfPnt2d(firstElem, newLast);
1948 Handle(TColStd_HArray1OfReal) newParams =
1949 new TColStd_HArray1OfReal(firstElem, newLast);
1950 Standard_Integer newCurr = 1;
1951 for (i = firstElem; i <= lastElem ; i++) {
1952 if (tmpParam.Value(i) == 1) {
1954 std::cout << "Point " << i << " : " << points->Value(i).X() << " " << points->Value(i).Y() << " at param " << params->Value(i) << std::endl;
1956 newPnts->SetValue(newCurr, points->Value(i));
1957 newParams->SetValue(newCurr, params->Value(i));
1962 std::cout << "Removed " << i << " : " << points->Value(i).X() << " " << points->Value(i).Y() << " at param " << params->Value(i) << std::endl;
1970 //=======================================================================
1971 //function : IsAnIsoparametric
1973 //=======================================================================
1974 //:S4030: modified for optimization
1975 //:p9 abv 11 Mar 99: PRO7226 #489490: find nearest boundary instead of first one
1977 Standard_Boolean ShapeConstruct_ProjectCurveOnSurface::IsAnIsoparametric(const Standard_Integer nbrPnt,
1978 const TColgp_SequenceOfPnt& points,
1979 const TColStd_SequenceOfReal& params,
1980 Standard_Boolean& isoTypeU,
1981 Standard_Boolean& p1OnIso,
1983 Standard_Boolean& p2OnIso,
1985 Standard_Boolean& isoPar2d3d,
1986 Handle(Geom_Curve)& cIso,
1989 TColStd_Array1OfReal& pout) const
1994 Standard_Real prec = Precision::Confusion();//myPreci;
1996 Standard_Boolean isoParam = Standard_False;
1997 isoPar2d3d = Standard_False;
1999 Standard_Real U1, U2, V1, V2;
2000 mySurf->Bounds(U1, U2, V1, V2);
2002 if ( mySurf->Surface()->IsKind(STANDARD_TYPE(Geom_RectangularTrimmedSurface))) {
2003 Handle(Geom_RectangularTrimmedSurface) sTrim =
2004 Handle(Geom_RectangularTrimmedSurface)::DownCast(mySurf->Surface());
2005 sTrim->Bounds(U1, U2, V1, V2);
2009 Standard_Integer mpt[2]; mpt[0] = mpt[1] = 0;
2010 Standard_Real t, tpar[2] = { 0.0, 0.0 }, isoValue=0.;
2011 Standard_Real mindist2;
2012 Standard_Real mind2[2];
2013 mindist2 = mind2[0] = mind2[1] = 4*prec*prec;
2015 p1OnIso = Standard_False;
2016 p2OnIso = Standard_False;
2017 const Bnd_Box* aBox = 0;
2019 for (Standard_Integer j=1; (j<=4) /*&& !isoParam*/; j++) {
2020 Standard_Real isoVal=0.;
2021 Standard_Boolean isoU=Standard_False; //szv#4:S4163:12Mar99 `isoU` must be Standard_Boolean
2022 Handle(Geom_Curve) cI;
2023 Standard_Real tt1, tt2;
2026 if (Precision::IsInfinite(U1)) continue;
2027 cI = mySurf->UIso(U1);
2028 isoU = Standard_True;
2030 aBox = & mySurf->GetBoxUF();
2033 if (Precision::IsInfinite(U2)) continue;
2034 cI = mySurf->UIso(U2);
2035 isoU = Standard_True;
2037 aBox = & mySurf->GetBoxUL();
2040 if (Precision::IsInfinite(V1)) continue;
2041 cI = mySurf->VIso(V1);
2042 isoU = Standard_False;
2044 aBox = & mySurf->GetBoxVF();
2047 if (Precision::IsInfinite(V2)) continue;
2048 cI = mySurf->VIso(V2);
2049 isoU = Standard_False;
2051 aBox = & mySurf->GetBoxVL();
2056 if (isoU) { tt1 = V1; tt2 = V2; }
2057 else { tt1 = U1; tt2 = U2; }
2063 // PATCH CKY 9-JUL-1998 : protection contre singularite
2065 cI->D0( (tt1+tt2)/2,extmi);
2066 if (ext1.IsEqual(ext2,prec) && ext1.IsEqual(extmi,prec)) continue;
2068 Standard_Boolean PtEQext1 = Standard_False;
2069 Standard_Boolean PtEQext2 = Standard_False;
2071 Standard_Real currd2[2], tp[2] = {0, 0};
2072 Standard_Integer mp[2];
2074 for (Standard_Integer i=0; i<2; i++) {
2076 Standard_Integer k = (i == 0 ? 1 : nbrPnt);
2078 // si ext1 == ext2 => valueP1 == valueP2 => vect null plus tard
2079 currd2[i] = points(k).SquareDistance ( ext1 );
2080 if ( currd2[i] <= prec*prec && !PtEQext1) {
2083 PtEQext1 = Standard_True;
2087 currd2[i] = points(k).SquareDistance ( ext2 );
2088 if ( currd2[i] <= prec*prec && !PtEQext2) {
2091 PtEQext2 = Standard_True;
2095 // On evite de projecter sur un iso degenere
2096 // on doit egalement le faire pour l apex du cone
2097 if (mySurf->Surface()->IsKind(STANDARD_TYPE(Geom_SphericalSurface)) && !isoU) {
2101 if(aBox->IsOut(points(k))) continue;
2103 Standard_Real Cf = cI->FirstParameter();
2104 Standard_Real Cl = cI->LastParameter();
2105 if (Precision::IsInfinite(Cf)) Cf = -1000;
2106 if (Precision::IsInfinite(Cl)) Cl = +1000;
2108 ShapeAnalysis_Curve sac;
2109 Standard_Real dist = sac.Project (cI,points(k),prec,pt,t,Cf,Cl);
2110 currd2[i] = dist * dist;
2111 if ((dist <= prec) && (t>= Cf) && (t<=Cl)) {
2117 //:e7 abv 21 Apr 98: ProSTEP TR8, r0501_pe #56679:
2118 // avoid possible null-length curves
2119 if ( mp[0] >0 && mp[1] >0 &&
2120 Abs ( tp[0] - tp[1] ) < Precision::PConfusion() ) continue;
2124 ( ! p1OnIso || currd2[0] < mind2[0] ) ) {
2125 p1OnIso = Standard_True;
2126 mind2[0] = currd2[0]; // LP2.stp #105899: FLT_INVALID_OPERATION on Windows 7 VC 9 Release mode on the whole file
2127 if (isoU) valueP1.SetCoord(isoVal, tp[0]);
2128 else valueP1.SetCoord(tp[0], isoVal);
2132 ( ! p2OnIso || currd2[1] < mind2[1] ) ) {
2133 p2OnIso = Standard_True;
2134 mind2[1] = currd2[1];
2135 if (isoU) valueP2.SetCoord(isoVal, tp[1]);
2136 else valueP2.SetCoord(tp[1], isoVal);
2139 if ( mp[0] <=0 || mp[1] <=0 ) continue;
2141 Standard_Real md2 = currd2[0] + currd2[1];
2142 if ( mindist2 <= md2 ) continue;
2156 // probablely it concerns an isoparametrics
2157 if ( mpt[0] >0 && mpt[1] >0 ) {
2159 p1OnIso = p2OnIso = Standard_True;
2161 valueP1.SetCoord(isoValue, tpar[0]);
2162 valueP2.SetCoord(isoValue, tpar[1]);
2165 valueP1.SetCoord(tpar[0], isoValue);
2166 valueP2.SetCoord(tpar[1], isoValue);
2169 if ( mpt[0] != 3 && mpt[1] != 3 ) {
2170 isoPar2d3d = Standard_True;
2171 for (Standard_Integer i=2; i < nbrPnt && isoPar2d3d; i++){
2172 if (tpar[1] > tpar[0]) t = params(i);
2173 else t = t1+t2-params(i);
2175 if (!points(i).IsEqual(pt, prec)) isoPar2d3d = Standard_False;
2179 if (isoPar2d3d) isoParam = Standard_True;
2181 Standard_Real prevParam = tpar[0];
2182 Standard_Real Cf, Cl;
2183 Standard_Boolean isoByDistance = Standard_True;
2184 Cf = cIso->FirstParameter();
2185 Cl = cIso->LastParameter();
2186 if (Precision::IsInfinite(Cf)) Cf = -1000;
2187 if (Precision::IsInfinite(Cl)) Cl = +1000;
2189 ShapeAnalysis_Curve sac;
2190 for (Standard_Integer i=2; i < nbrPnt && isoByDistance; i++) {
2191 Standard_Real dist = sac.NextProject (prevParam,cIso,points(i),
2193 Standard_False); //:j8 abv 10.12.98: TR10 r0501_db.stp #9423: avoid adjusting to ends
2196 if( (dist > prec) || (t < Cf) || (t > Cl) )
2197 isoByDistance = Standard_False;
2199 if (isoByDistance) isoParam = Standard_True;
2202 /* if (!isoParam) { CKY 29-mai-1997 : garder tout ce qu on peut ?
2203 p1OnIso = Standard_False;
2204 p2OnIso = Standard_False;
2208 catch(Standard_Failure const& anException) {
2210 // pb : on affiche ce qu on peut
2211 for (Standard_Integer numpnt = 1; numpnt <= nbrPnt; numpnt ++) {
2212 std::cout<<"["<<numpnt<<"]param="<<params(numpnt)<<" point=("<<
2213 points(numpnt).X()<<" "<<points(numpnt).Y()<<" "<<points(numpnt).Z()<<")"<<std::endl;
2215 std::cout << "Warning: ShapeConstruct_ProjectCurveOnSurface::IsAnIsoparametric(): Exception: ";
2216 anException.Print(std::cout); std::cout << std::endl;
2219 return Standard_False;
2223 /* S4135 : BestExtremum is commented after IsAnIsoparametric works with Precision::Confusion()
2224 //=======================================================================
2225 //function : BestExtremum
2226 //purpose : auxiliaire prenant le meilleur extremum si ISO car doute possible
2227 //=======================================================================
2229 gp_Pnt2d ShapeConstruct_ProjectCurveOnSurface::BestExtremum(const gp_Pnt2d& P2iso,const gp_Pnt& P3ext,const gp_Pnt& P3next) const
2231 // P2iso a ete calcule depuis P3ext sur une iso externe de la surface
2232 // En principe bon mais circularite possible ... et IsU/VClosed faillible
2233 // (si baillement 1e-4 ou 1e-5, on est dedans !). DONC
2234 // 1/ on privilegie l iso mais a tout hasard on verifie si Surf meilleur
2235 // 2/ si iso, attention a la circularite (cas limite)
2237 // NB : si isoParam, on suppose que P2iso est bon (car il y en a 2). A voir...
2239 // D abord, calcul p2ext depuis la surface. choix surface/iso
2241 Standard_Real prec = Precision::Confusion();//myPreci;
2242 gp_Pnt2d P2cal = mySurf->ValueOfUV(P3ext, prec);
2243 gp_Pnt P3cal = mySurf->Value (P2cal);
2244 Standard_Real dcal = P3ext.Distance (P3cal);
2245 Standard_Real dnxt = P3ext.Distance (P3next);
2246 if (dcal > dnxt) return P2iso; // en fait protection sur BUG (PRO8468)
2248 // On choisit entre P2iso et P2cal, le plus proche de P2next ... !!!
2249 gp_Pnt2d P2next = mySurf->ValueOfUV(P3next, prec);
2250 if (P2next.Distance(P2cal) < P2next.Distance(P2iso)) return P2cal;