1 // File: GeomFill_SectionPlacement.cxx
2 // Created: Mon Dec 15 17:09:47 1997
3 // Author: Philippe MANGIN
7 #include <GeomFill_SectionPlacement.ixx>
10 #include <Geom_Plane.hxx>
11 #include <GeomLProp_CLProps.hxx>
12 #include <GeomAbs_CurveType.hxx>
13 #include <GeomAdaptor_HSurface.hxx>
19 #include <gp_Trsf.hxx>
20 #include <TColgp_HArray1OfPnt.hxx>
21 #include <Bnd_Box.hxx>
22 #include <BndLib_Add3dCurve.hxx>
24 #include <Precision.hxx>
26 #include <Extrema_ExtCC.hxx>
27 #include <Extrema_POnCurv.hxx>
28 #include <IntCurveSurface_HInter.hxx>
29 #include <IntCurveSurface_IntersectionPoint.hxx>
31 #include <Geom_BSplineCurve.hxx>
32 #include <Geom_TrimmedCurve.hxx>
33 #include <Geom_Line.hxx>
34 #include <Geom_Conic.hxx>
35 #include <Geom_BezierCurve.hxx>
37 #include <Geom_CartesianPoint.hxx>
40 //===============================================================
43 //===============================================================
44 static void Tangente(const Adaptor3d_Curve& Path,
45 const Standard_Real Param,
49 Path.D1(Param, P, Tang);
50 Standard_Real Norm = Tang.Magnitude();
52 for (Standard_Integer ii=2; (ii<12) && (Norm < Precision::Confusion());
54 Tang = Path.DN(Param, ii);
55 Norm = Tang.Magnitude();
58 if (Norm > 100*gp::Resolution()) Tang /= Norm;
62 static Standard_Real Penalite(const Standard_Real angle,
63 const Standard_Real dist)
75 penal += 1./angle -2./PI;
84 static Standard_Real EvalAngle(const gp_Vec& V1,
89 if (angle > PI/2) angle = PI - angle;
93 static Standard_Integer NbSamples(const Handle(Geom_Curve)& aCurve)
95 Standard_Real nbs = 100.; //on default
97 Handle(Geom_Curve) theCurve = aCurve;
98 if (aCurve->IsInstance(STANDARD_TYPE(Geom_TrimmedCurve)))
99 theCurve = (Handle(Geom_TrimmedCurve)::DownCast(aCurve))->BasisCurve();
101 if (theCurve->IsInstance(STANDARD_TYPE(Geom_Line)))
103 else if (theCurve->IsKind(STANDARD_TYPE(Geom_Conic)))
105 else if (theCurve->IsInstance(STANDARD_TYPE(Geom_BezierCurve)))
107 Handle(Geom_BezierCurve) BC = Handle(Geom_BezierCurve)::DownCast(theCurve);
108 nbs = 3 + BC->NbPoles();
110 else if (theCurve->IsInstance(STANDARD_TYPE(Geom_BSplineCurve)))
112 Handle(Geom_BSplineCurve) BC = Handle(Geom_BSplineCurve)::DownCast(theCurve);
115 Standard_Real ratio =
116 (aCurve->LastParameter() - aCurve->FirstParameter())/(BC->LastParameter() - BC->FirstParameter());
125 return ((Standard_Integer)nbs);
128 //===============================================================
129 // Function :DistMini
130 // Purpose : Examine un extrema pour updater <Dist> & <Param>
131 //===============================================================
132 static void DistMini(const Extrema_ExtPC& Ext,
133 const Adaptor3d_Curve& C,
135 Standard_Real& Param)
137 Standard_Real dist1, dist2;
140 Standard_Real Dist2 = RealLast();
142 Ext.TrimmedSquareDistances(dist1, dist2, P1, P2);
143 if ( (dist1<Dist2) || (dist2<Dist2) ) {
146 Param = C.FirstParameter();
150 Param = C.LastParameter();
156 for (ii=1; ii<= Ext.NbExt(); ii++) {
157 if (Ext.SquareDistance(ii) < Dist2) {
158 Dist2 = Ext.SquareDistance(ii);
159 Param = Ext.Point(ii).Parameter();
167 //===============================================================
168 // Function : Constructeur
170 //===============================================================
171 GeomFill_SectionPlacement::
172 GeomFill_SectionPlacement(const Handle(GeomFill_LocationLaw)& L,
173 const Handle(Geom_Geometry)& Section) :
174 myLaw(L), /* myAdpSection(Section), mySection(Section), */
175 Dist(RealLast()), AngleMax(0.)
178 done = Standard_False;
179 isplan = Standard_False;
180 myIsPoint = Standard_False;
182 if (Section->IsInstance(STANDARD_TYPE(Geom_CartesianPoint)))
184 myIsPoint = Standard_True;
185 myPoint = Handle(Geom_CartesianPoint)::DownCast(Section)->Pnt();
186 isplan = Standard_True;
190 Handle(Geom_Curve) CurveSection = Handle(Geom_Curve)::DownCast(Section);
191 myAdpSection.Load(CurveSection);
192 mySection = CurveSection;
195 Standard_Integer i, j, NbPoles=0;
196 Standard_Real aXmin, aYmin, aZmin, aXmax, aYmax, aZmax;
198 // Boite d'encombrement de la section pour en deduire le gabarit
203 BndLib_Add3dCurve::Add(myAdpSection, 1.e-4, box);
204 box.Get(aXmin, aYmin, aZmin, aXmax, aYmax, aZmax);
206 Standard_Real DX = aXmax - aXmin ;
207 Standard_Real DY = aYmax - aYmin ;
208 Standard_Real DZ = aZmax - aZmin ;
209 Gabarit = Sqrt( DX*DX+ DY*DY + DZ*DZ )/2. ;
211 Gabarit += Precision::Confusion(); // Cas des toute petite
214 // Initialisation de TheAxe pour les cas singulier
219 Tangente(myAdpSection,
220 (myAdpSection.FirstParameter()+myAdpSection.LastParameter())/2,
222 TheAxe.SetLocation(P);
223 TheAxe.SetDirection(V);
225 // y a t'il un Plan moyen ?
226 GeomAbs_CurveType TheType = myAdpSection.GetType();
230 isplan = Standard_True;
231 TheAxe = myAdpSection.Circle().Axis();
234 case GeomAbs_Ellipse:
236 isplan = Standard_True;
237 TheAxe = myAdpSection.Ellipse().Axis();
240 case GeomAbs_Hyperbola:
242 isplan = Standard_True;
243 TheAxe = myAdpSection.Hyperbola().Axis();
246 case GeomAbs_Parabola:
248 isplan = Standard_True;
249 TheAxe = myAdpSection.Parabola().Axis();
254 NbPoles = 0; // Pas de Plan !!
257 case GeomAbs_BezierCurve:
258 case GeomAbs_BSplineCurve:
260 NbPoles = myAdpSection.NbPoles();
268 if (!isplan && NbPoles>2)
270 // Calcul d'un plan moyen.
271 Handle(TColgp_HArray1OfPnt) Pnts;
272 Standard_Real first = myAdpSection.FirstParameter();
273 Standard_Real last = myAdpSection.LastParameter();
274 Standard_Real t, delta;
275 if (myAdpSection.GetType() == GeomAbs_BSplineCurve)
277 Handle(Geom_BSplineCurve) BC =
278 Handle(Geom_BSplineCurve)::DownCast(myAdpSection.Curve());
279 Standard_Integer I1, I2, I3, I4;
280 BC->LocateU( first, Precision::Confusion(), I1, I2 );
281 BC->LocateU( last, Precision::Confusion(), I3, I4 );
282 Standard_Integer NbKnots = I3 - I2 + 1;
284 Standard_Integer NbLocalPnts = 10;
285 Standard_Integer NbPnts = (NbKnots-1) * NbLocalPnts;
287 NbPnts += NbLocalPnts;
288 if (I3 != I4 && first < BC->Knot(I3))
289 NbPnts += NbLocalPnts;
290 if (!myAdpSection.IsClosed())
292 Pnts = new TColgp_HArray1OfPnt(1, NbPnts);
293 Standard_Integer nb = 1;
296 Standard_Real locallast = (BC->Knot(I2) < last)? BC->Knot(I2) : last;
297 delta = (locallast - first) / NbLocalPnts;
298 for (j = 0; j < NbLocalPnts; j++)
301 Pnts->SetValue( nb++, myAdpSection.Value(t) );
304 for (i = I2; i < I3; i++)
307 delta = (BC->Knot(i+1) - t) / NbLocalPnts;
308 for (j = 0; j < NbLocalPnts; j++)
311 Pnts->SetValue( nb++, myAdpSection.Value(t) );
314 if (I3 != I4 && first < BC->Knot(I3))
317 delta = (last - t) / NbLocalPnts;
318 for (j = 0; j < NbLocalPnts; j++)
321 Pnts->SetValue( nb++, myAdpSection.Value(t) );
324 if (!myAdpSection.IsClosed())
325 Pnts->SetValue( nb, myAdpSection.Value(last) );
329 Standard_Integer NbPnts = NbPoles-1;
330 if (!myAdpSection.IsClosed())
332 Pnts = new TColgp_HArray1OfPnt(1, NbPnts);
333 delta = (last - first) / (NbPoles-1);
334 for (i = 0; i < NbPoles-1; i++)
337 Pnts->SetValue( i+1, myAdpSection.Value(t) );
339 if (!myAdpSection.IsClosed())
340 Pnts->SetValue( NbPnts, myAdpSection.Value(last) );
343 Standard_Boolean issing;
345 GeomLib::AxeOfInertia(Pnts->Array1(), axe, issing, Precision::Confusion());
347 isplan = Standard_True;
348 TheAxe.SetLocation(axe.Location());
349 TheAxe.SetDirection(axe.Direction());
354 myExt.Initialize(myAdpSection,
355 myAdpSection.FirstParameter(),
356 myAdpSection.LastParameter(),
357 Precision::Confusion());
361 //===============================================================
362 // Function :SetLocation
364 //===============================================================
365 void GeomFill_SectionPlacement::
366 SetLocation(const Handle(GeomFill_LocationLaw)& L)
371 //===============================================================
372 // Function : Perform
373 // Purpose : Le plus simple
374 //===============================================================
375 void GeomFill_SectionPlacement::Perform(const Standard_Real Tol)
377 Handle(Adaptor3d_HCurve) Path;
378 Path = myLaw->GetCurve();
382 //===============================================================
384 // Purpose : Recherche automatique
385 //===============================================================
386 void GeomFill_SectionPlacement::Perform(const Handle(Adaptor3d_HCurve)& Path,
387 const Standard_Real Tol)
389 Standard_Real IntTol = 1.e-5;
390 Standard_Real DistCenter = Precision::Infinite();
394 Extrema_ExtPC Projector(myPoint, Path->Curve(), Precision::Confusion());
395 DistMini( Projector, Path->Curve(), Dist, PathParam );
400 PathParam = Path->FirstParameter();
401 SecParam = myAdpSection.FirstParameter();
403 Standard_Real distaux, taux, alpha;
404 gp_Pnt PonPath, PonSec, P;
406 VRef.SetXYZ(TheAxe.Direction().XYZ());
408 Tangente( Path->Curve(), PathParam, PonPath, dp1);
409 PonSec = myAdpSection.Value(SecParam);
410 Dist = PonPath.Distance(PonSec);
411 if (Dist > Tol) { // On Cherche un meilleur point sur la section
412 myExt.Perform(PonPath);
413 if ( myExt.IsDone() ) {
414 DistMini(myExt, myAdpSection, Dist, SecParam);
415 PonSec = myAdpSection.Value(SecParam);
418 AngleMax = EvalAngle(VRef, dp1);
419 if (isplan) AngleMax = PI/2 - AngleMax;
421 Standard_Boolean Trouve = Standard_False;
425 // (1.1) Distances Point-Plan
426 Standard_Real DistPlan;
427 gp_Vec V1 (PonPath, TheAxe.Location());
428 DistPlan = Abs(V1.Dot(VRef));
429 if (DistPlan <= IntTol)
430 DistCenter = V1.Magnitude();
432 gp_Pnt Plast = Path->Value( Path->LastParameter() );
433 V1.SetXYZ( TheAxe.Location().XYZ() - Plast.XYZ() );
434 DistPlan = Abs(V1.Dot(VRef));
435 if (DistPlan <= IntTol)
437 Standard_Real aDist = V1.Magnitude();
438 if (aDist < DistCenter)
442 PathParam = Path->LastParameter();
446 // (1.2) Intersection Plan-courbe
447 gp_Ax3 axe (TheAxe.Location(), TheAxe.Direction());
448 Handle(Geom_Plane) plan = new (Geom_Plane)(axe);
449 Handle(GeomAdaptor_HSurface) adplan =
450 new (GeomAdaptor_HSurface)(plan);
451 IntCurveSurface_HInter Intersector;
452 Intersector.Perform(Path, adplan);
453 if (Intersector.IsDone())
458 for (ii=1; ii<=Intersector.NbPoints(); ii++)
460 w = Intersector.Point(ii).W();
461 P = Path->Value( w );
462 aDist = P.Distance( TheAxe.Location() );
463 if (aDist < DistCenter)
471 if (!Intersector.IsDone() || Intersector.NbPoints() == 0)
473 Standard_Integer NbPnts = NbSamples( mySection );
474 TColgp_Array1OfPnt Pnts( 1, NbPnts+1 );
475 Standard_Real delta = (mySection->LastParameter()-mySection->FirstParameter())/NbPnts;
476 for (ii = 0; ii <= NbPnts; ii++)
477 Pnts(ii+1) = mySection->Value( mySection->FirstParameter() + ii*delta );
481 Standard_Real Xgap, Ygap, Zgap;
482 GeomLib::Inertia( Pnts, BaryCenter, Xdir, Ydir, Xgap, Ygap, Zgap );
484 gp_Pnt Pfirst = Path->Value( Path->FirstParameter() );
485 if (Pfirst.Distance(BaryCenter) < Plast.Distance(BaryCenter))
486 PathParam = Path->FirstParameter();
489 PathParam = Path->LastParameter();
490 Tangente( Path->Curve(), PathParam, PonPath, dp1);
491 PonSec = myAdpSection.Value(SecParam);
492 Dist = PonPath.Distance(PonSec);
493 if (Dist > Tol) { // On Cherche un meilleur point sur la section
494 myExt.Perform(PonPath);
495 if ( myExt.IsDone() ) {
496 DistMini(myExt, myAdpSection, Dist, SecParam);
497 PonSec = myAdpSection.Value(SecParam);
500 AngleMax = EvalAngle(VRef, dp1);
501 AngleMax = PI/2 - AngleMax;
506 // (1.1) Distances Point-Plan
507 Standard_Real DistPlan;
508 gp_Vec V1 (PonPath, TheAxe.Location());
509 DistPlan = Abs(V1.Dot(VRef));
511 // On examine l'autre extremite
513 Tangente(Path->Curve(), Path->LastParameter(), P, dp1);
514 V1.SetXYZ(TheAxe.Location().XYZ()-P.XYZ());
515 if (Abs(V1.Dot(VRef)) <= DistPlan ) { // On prend l'autre extremite
516 alpha = PI/2 - EvalAngle(VRef, dp1);
517 distaux = PonPath.Distance(PonSec);
520 if ( myExt.IsDone() )
521 DistMini(myExt, myAdpSection, distaux, taux);
526 if (Choix(distaux, alpha)) {
530 PathParam = Path->LastParameter();
534 // (1.2) Intersection Plan-courbe
535 gp_Ax3 axe (TheAxe.Location(), TheAxe.Direction());
536 Handle(Geom_Plane) plan = new (Geom_Plane)(axe);
537 Handle(GeomAdaptor_HSurface) adplan =
538 new (GeomAdaptor_HSurface)(plan);
539 IntCurveSurface_HInter Intersector;
540 Intersector.Perform(Path, adplan);
541 if (Intersector.IsDone()) {
544 for (ii=1; ii<=Intersector.NbPoints(); ii++) {
545 w = Intersector.Point(ii).W();
547 Tangente( Path->Curve(), w, P, V);
548 alpha = PI/2 - EvalAngle(V, VRef);
549 //(1.4) Test de distance Point-Courbe
551 if ( myExt.IsDone() ) {
552 DistMini(myExt, myAdpSection, distaux, taux);
553 if (Choix(distaux, alpha)) {
559 PonSec = myAdpSection.Value(SecParam);
563 distaux = P.Distance(PonSec);
564 if (Choix(distaux, alpha)) {
575 if (Intersector.NbPoints() == 0) {
583 // (2.1) Distance avec les extremites ...
584 myExt.Perform(PonPath);
585 if ( myExt.IsDone() ) {
586 DistMini(myExt, myAdpSection, distaux, taux);
587 if (distaux < Dist) {
592 Trouve = (Dist <= Tol);
594 Tangente( Path->Curve(), Path->LastParameter(), P, dp1);
595 alpha = EvalAngle(VRef, dp1);
597 if ( myExt.IsDone() ) {
598 if ( myExt.IsDone() ) {
599 DistMini(myExt, myAdpSection, distaux, taux);
600 if (Choix(distaux, alpha)) {
605 PathParam = Path->LastParameter();
609 Trouve = (Dist <= Tol);
612 // (2.2) Distance courbe-courbe
614 Extrema_ExtCC Ext(Path->Curve(), myAdpSection,
615 Path->FirstParameter(), Path->LastParameter(),
616 myAdpSection.FirstParameter(),
617 myAdpSection.LastParameter(),
618 Path->Resolution(Tol/100),
619 myAdpSection.Resolution(Tol/100));
621 Extrema_POnCurv P1, P2;
622 for (ii=1; ii<=Ext.NbExt(); ii++) {
623 distaux = sqrt (Ext.SquareDistance(ii));
624 Ext.Points(ii, P1, P2);
625 Tangente(Path->Curve(), P1.Parameter(), P, dp1);
626 alpha = EvalAngle(VRef, dp1);
627 if (Choix(distaux, alpha)) {
628 Trouve = Standard_True;
630 PathParam = P1.Parameter();
631 SecParam = P2.Parameter();
639 // Si l'on a toujours rien, on essai une distance point/path
640 // c'est la derniere chance.
642 PExt.Initialize(Path->Curve(),
643 Path->FirstParameter(),
644 Path->LastParameter(),
645 Precision::Confusion());
646 PExt.Perform(PonSec);
647 if ( PExt.IsDone() ) {
648 // modified for OCC13595 Tue Oct 17 15:00:08 2006.BEGIN
649 // DistMini(PExt, myAdpSection, distaux, taux);
650 DistMini(PExt, Path->Curve(), distaux, taux);
651 // modified for OCC13595 Tue Oct 17 15:00:11 2006.END
652 Tangente(Path->Curve(), taux, P, dp1);
653 alpha = EvalAngle(VRef, dp1);
654 if (Choix(distaux, alpha)) {
666 done = Standard_True;
670 //===============================================================
671 // Function : Perform
672 // Purpose : Calcul le placement pour un parametre donne.
673 //===============================================================
674 void GeomFill_SectionPlacement::Perform(const Standard_Real Param,
675 const Standard_Real Tol)
677 done = Standard_True;
678 Handle(Adaptor3d_HCurve) Path;
679 Path = myLaw->GetCurve();
684 gp_Pnt PonPath = Path->Value( PathParam );
685 Dist = PonPath.Distance(myPoint);
690 SecParam = myAdpSection.FirstParameter();
692 // Standard_Real distaux, taux, alpha;
693 // gp_Pnt PonPath, PonSec, P;
694 gp_Pnt PonPath, PonSec;
696 VRef.SetXYZ(TheAxe.Direction().XYZ());
698 Tangente( Path->Curve(), PathParam, PonPath, dp1);
699 PonSec = myAdpSection.Value(SecParam);
700 Dist = PonPath.Distance(PonSec);
701 if (Dist > Tol) { // On Cherche un meilleur point sur la section
702 myExt.Perform(PonPath);
703 if ( myExt.IsDone() ) {
704 DistMini(myExt, myAdpSection, Dist, SecParam);
705 PonSec = myAdpSection.Value(SecParam);
708 AngleMax = EvalAngle(VRef, dp1);
709 if (isplan) AngleMax = PI/2 - AngleMax;
712 done = Standard_True;
715 //===============================================================
718 //===============================================================
719 Standard_Boolean GeomFill_SectionPlacement::IsDone() const
724 //===============================================================
725 // Function : ParameterOnPath
727 //===============================================================
728 Standard_Real GeomFill_SectionPlacement::ParameterOnPath() const
733 //===============================================================
734 // Function : ParameterOnSection
736 //===============================================================
737 Standard_Real GeomFill_SectionPlacement::ParameterOnSection() const
742 //===============================================================
743 // Function : Distance
745 //===============================================================
746 Standard_Real GeomFill_SectionPlacement::Distance() const
751 //===============================================================
754 //===============================================================
755 Standard_Real GeomFill_SectionPlacement::Angle() const
760 //===============================================================
761 // Function : Transformation
763 //===============================================================
764 gp_Trsf GeomFill_SectionPlacement::Transformation(
765 const Standard_Boolean WithTranslation,
766 const Standard_Boolean WithCorrection) const
771 // modified by NIZHNY-MKK Fri Oct 17 15:27:07 2003
772 gp_Pnt P(0., 0., 0.), PSection(0., 0., 0.);
774 // Calcul des reperes
775 myLaw->D0(PathParam, M, V);
778 D.SetXYZ (M.Column(3));
779 DN.SetXYZ(M.Column(1));
780 gp_Ax3 Paxe(P, D, DN);
783 if (WithTranslation || WithCorrection) {
787 PSection = mySection->Value(SecParam);
789 // modified by NIZHNY-MKK Wed Oct 8 15:03:19 2003.BEGIN
792 if (WithCorrection && !myIsPoint) {
796 Standard_Failure::Raise("Illegal usage: can't rotate non-planar profile");
798 gp_Dir ProfileNormal = TheAxe.Direction();
799 gp_Dir SpineStartDir = Paxe.Direction();
801 if (! ProfileNormal.IsParallel( SpineStartDir, Precision::Angular() )) {
802 gp_Dir DirAxeOfRotation = ProfileNormal ^ SpineStartDir;
803 angle = ProfileNormal.AngleWithRef( SpineStartDir, DirAxeOfRotation );
804 gp_Ax1 AxeOfRotation( TheAxe.Location(), DirAxeOfRotation );
805 Rot.SetRotation( AxeOfRotation, angle );
807 PSection.Transform(Rot);
809 // modified by NIZHNY-MKK Wed Oct 8 15:03:21 2003.END
811 if (WithTranslation) {
812 P.ChangeCoord().SetLinearForm(-1,PSection.XYZ(),
816 P.SetCoord(0., 0., 0.);
819 gp_Ax3 Saxe(P, gp::DZ(), gp::DX());
823 Tf.SetTransformation(Saxe, Paxe);
825 if (WithCorrection) {
826 // modified by NIZHNY-MKK Fri Oct 17 15:26:36 2003.BEGIN
827 // Standard_Real angle;
831 // Standard_Failure::Raise("Illegal usage: can't rotate non-planar profile");
833 // gp_Dir ProfileNormal = TheAxe.Direction();
834 // gp_Dir SpineStartDir = Paxe.Direction();
835 // if (! ProfileNormal.IsParallel( SpineStartDir, Precision::Angular() ))
837 // gp_Dir DirAxeOfRotation = ProfileNormal ^ SpineStartDir;
838 // angle = ProfileNormal.AngleWithRef( SpineStartDir, DirAxeOfRotation );
839 // gp_Ax1 AxeOfRotation( TheAxe.Location(), DirAxeOfRotation );
840 // Rot.SetRotation( AxeOfRotation, angle );
842 // modified by NIZHNY-MKK Fri Oct 17 15:26:42 2003.END
850 //===============================================================
851 // Function : Section
853 //===============================================================
854 Handle(Geom_Curve) GeomFill_SectionPlacement::
855 Section(const Standard_Boolean WithTranslation) const
857 Handle(Geom_Curve) TheSection =
858 Handle(Geom_Curve)::DownCast(mySection->Copy());
859 TheSection->Transform(Transformation(WithTranslation, Standard_False));
864 //===============================================================
867 //===============================================================
868 Handle(Geom_Curve) GeomFill_SectionPlacement::
869 ModifiedSection(const Standard_Boolean WithTranslation) const
871 Handle(Geom_Curve) TheSection =
872 Handle(Geom_Curve)::DownCast(mySection->Copy());
873 TheSection->Transform(Transformation(WithTranslation, Standard_True));
877 //===============================================================
878 // Function :SectionAxis
880 //===============================================================
881 void GeomFill_SectionPlacement::SectionAxis(const gp_Mat& M,
886 Standard_Real Eps = 1.e-10;
889 GeomLProp_CLProps CP(mySection, SecParam, 2, Eps);
890 if (CP.IsTangentDefined()) {
894 if (CP.Curvature() > Eps) {
899 // Cas ambigu, on essai de recuperer la normal a la trajectoire
900 // Reste le probleme des points d'inflexions, qui n'est pas
901 // bien traiter par LProp (pas de recuperation de la normal) :
903 PathNormal.SetXYZ(M.Column(1));
904 PathNormal.Normalize();
906 if (BN.Magnitude() > Eps) {
913 else { // Cas indefinie, on prend le triedre
914 // complet sur la trajectoire
915 T.SetXYZ(M.Column(3));
916 N.SetXYZ(M.Column(2));
922 //===============================================================
924 // Purpose : Decide si le couple (dist, angle) est "meilleur" que
926 //===============================================================
927 Standard_Boolean GeomFill_SectionPlacement::Choix(const Standard_Real dist,
928 const Standard_Real angle) const
930 Standard_Real evoldist, evolangle;
931 evoldist = dist - Dist;
932 evolangle = angle - AngleMax;
933 // (1) Si la gain en distance est > que le gabarit, on prend
934 if (evoldist < - Gabarit)
935 return Standard_True;
937 // (2) si l'ecart en distance est de l'ordre du gabarit
938 if (Abs(evoldist) < Gabarit) {
939 // (2.1) si le gain en angle est important on garde
941 return Standard_True;
942 // (2.2) si la variation d'angle est moderee on evalue
943 // une fonction de penalite
944 if (Penalite(angle, dist/Gabarit) < Penalite(AngleMax, Dist/Gabarit) )
945 return Standard_True;
948 return Standard_False;