1 // Created on: 1993-07-07
2 // Created by: Jean Claude VAUTHIER
3 // Copyright (c) 1993-1999 Matra Datavision
4 // Copyright (c) 1999-2014 OPEN CASCADE SAS
6 // This file is part of Open CASCADE Technology software library.
8 // This library is free software; you can redistribute it and/or modify it under
9 // the terms of the GNU Lesser General Public License version 2.1 as published
10 // by the Free Software Foundation, with special exception defined in the file
11 // OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
12 // distribution for complete text of the license and disclaimer of any warranty.
14 // Alternatively, this file may be used under the terms of Open CASCADE
15 // commercial license or contractual agreement.
18 //pmn 24/09/96 Ajout du prolongement de courbe.
19 // jct 15/04/97 Ajout du prolongement de surface.
20 // jct 24/04/97 simplification ou suppression de calculs
21 // inutiles dans ExtendSurfByLength
22 // correction de Tbord et Continuity=0 accepte
23 // correction du calcul de lambda et appel a
24 // TangExtendToConstraint avec lambmin au lieu de 1.
25 // correction du passage Sr rat --> BSp nD
26 // xab 26/06/97 treatement partiel anulation des derivees
27 // partiels du denonimateur des Surfaces BSplines Rationnelles
28 // dans le cas de valeurs proportionnelles des denominateurs
29 // en umin umax et/ou vmin vmax.
30 // pmn 4/07/97 Gestion de la continuite dans BuildCurve3d (PRO9097)
31 // xab 10/07/97 on revient en arriere sur l'ajout du 26/06/97
32 // pmn 26/09/97 Ajout des parametres d'approx dans BuildCurve3d
33 // xab 29/09/97 on reintegre l'ajout du 26/06/97
34 // pmn 31/10/97 Ajoute AdjustExtremity
35 // jct 26/11/98 blindage dans ExtendSurf qd NTgte = 0 (CTS21288)
36 // jct 19/01/99 traitement de la periodicite dans ExtendSurf
44 #include <Adaptor2d_HCurve2d.hxx>
45 #include <Adaptor3d_Curve.hxx>
46 #include <Adaptor3d_CurveOnSurface.hxx>
47 #include <Adaptor3d_HCurve.hxx>
48 #include <Adaptor3d_HSurface.hxx>
49 #include <AdvApprox_ApproxAFunction.hxx>
50 #include <AdvApprox_PrefAndRec.hxx>
51 #include <BSplCLib.hxx>
52 #include <BSplSLib.hxx>
54 #include <CSLib_NormalStatus.hxx>
56 #include <Geom2d_BezierCurve.hxx>
57 #include <Geom2d_BSplineCurve.hxx>
58 #include <Geom2d_Circle.hxx>
59 #include <Geom2d_Curve.hxx>
60 #include <Geom2d_Ellipse.hxx>
61 #include <Geom2d_Hyperbola.hxx>
62 #include <Geom2d_Line.hxx>
63 #include <Geom2d_OffsetCurve.hxx>
64 #include <Geom2d_Parabola.hxx>
65 #include <Geom2d_TrimmedCurve.hxx>
66 #include <Geom2dAdaptor_Curve.hxx>
67 #include <Geom2dAdaptor_GHCurve.hxx>
68 #include <Geom2dAdaptor_HCurve.hxx>
69 #include <Geom2dConvert.hxx>
70 #include <Geom_BezierCurve.hxx>
71 #include <Geom_BezierSurface.hxx>
72 #include <Geom_BoundedCurve.hxx>
73 #include <Geom_BoundedSurface.hxx>
74 #include <Geom_BSplineCurve.hxx>
75 #include <Geom_BSplineSurface.hxx>
76 #include <Geom_Circle.hxx>
77 #include <Geom_Curve.hxx>
78 #include <Geom_Ellipse.hxx>
79 #include <Geom_Hyperbola.hxx>
80 #include <Geom_Line.hxx>
81 #include <Geom_OffsetCurve.hxx>
82 #include <Geom_Parabola.hxx>
83 #include <Geom_Plane.hxx>
84 #include <Geom_RectangularTrimmedSurface.hxx>
85 #include <Geom_Surface.hxx>
86 #include <Geom_TrimmedCurve.hxx>
87 #include <GeomAdaptor_HSurface.hxx>
88 #include <GeomAdaptor_Surface.hxx>
89 #include <GeomConvert.hxx>
90 #include <GeomConvert_ApproxSurface.hxx>
91 #include <GeomConvert_CompCurveToBSplineCurve.hxx>
92 #include <GeomLib.hxx>
93 #include <GeomLib_DenominatorMultiplier.hxx>
94 #include <GeomLib_DenominatorMultiplierPtr.hxx>
95 #include <GeomLib_LogSample.hxx>
96 #include <GeomLib_MakeCurvefromApprox.hxx>
97 #include <GeomLib_PolyFunc.hxx>
99 #include <gp_Circ.hxx>
100 #include <gp_Circ2d.hxx>
101 #include <gp_Dir.hxx>
102 #include <gp_Elips.hxx>
103 #include <gp_Elips2d.hxx>
104 #include <gp_GTrsf2d.hxx>
105 #include <gp_Hypr.hxx>
106 #include <gp_Hypr2d.hxx>
107 #include <gp_Lin.hxx>
108 #include <gp_Lin2d.hxx>
109 #include <gp_Parab.hxx>
110 #include <gp_Parab2d.hxx>
111 #include <gp_Pnt.hxx>
112 #include <gp_Pnt2d.hxx>
113 #include <gp_Trsf2d.hxx>
114 #include <gp_TrsfForm.hxx>
115 #include <gp_Vec.hxx>
116 #include <Hermit.hxx>
118 #include <math_FunctionAllRoots.hxx>
119 #include <math_FunctionSample.hxx>
120 #include <math_Jacobi.hxx>
121 #include <math_Matrix.hxx>
122 #include <math_Vector.hxx>
124 #include <Precision.hxx>
125 #include <Standard_ConstructionError.hxx>
126 #include <Standard_NotImplemented.hxx>
127 #include <TColgp_Array1OfPnt.hxx>
128 #include <TColgp_Array1OfPnt2d.hxx>
129 #include <TColgp_Array1OfVec.hxx>
130 #include <TColgp_Array1OfXYZ.hxx>
131 #include <TColgp_Array2OfPnt.hxx>
132 #include <TColgp_HArray2OfPnt.hxx>
133 #include <TColStd_Array1OfInteger.hxx>
134 #include <TColStd_Array1OfReal.hxx>
135 #include <TColStd_Array2OfReal.hxx>
136 #include <TColStd_HArray1OfReal.hxx>
137 #include <TColStd_HArray2OfReal.hxx>
139 static Standard_Boolean CompareWeightPoles(const TColgp_Array1OfPnt& thePoles1,
140 const TColStd_Array1OfReal* const theW1,
141 const TColgp_Array1OfPnt& thePoles2,
142 const TColStd_Array1OfReal* const theW2,
143 const Standard_Real theTol);
145 //=======================================================================
146 //function : ComputeLambda
147 //purpose : Calcul le facteur lambda qui minimise la variation de vittesse
148 // sur une interpolation d'hermite d'ordre (i,0)
149 //=======================================================================
150 static void ComputeLambda(const math_Matrix& Constraint,
151 const math_Matrix& Hermit,
152 const Standard_Real Length,
153 Standard_Real& Lambda )
155 Standard_Integer size = Hermit.RowNumber();
156 Standard_Integer Continuity = size-2;
157 Standard_Integer ii, jj, ip, pp;
160 math_Matrix HDer(1, size-1, 1, size);
161 for (jj=1; jj<=size; jj++) {
162 for (ii=1; ii<size;ii++) {
163 HDer(ii, jj) = ii*Hermit(jj, ii+1);
167 math_Vector V(1, size);
168 math_Vector Vec1(1, Constraint.RowNumber());
169 math_Vector Vec2(1, Constraint.RowNumber());
170 math_Vector Vec3(1, Constraint.RowNumber());
171 math_Vector Vec4(1, Constraint.RowNumber());
173 Standard_Real * polynome = &HDer(1,1);
174 Standard_Real * valhder = &V(1);
175 Vec2 = Constraint.Col(2);
177 Standard_Real t, squared1 = Vec2.Norm2(), GW;
178 // math_Matrix Vec(1, Constraint.RowNumber(), 1, size-1);
179 // gp_Vec Vfirst(p0.XYZ()), Vlast(Point.XYZ());
180 // TColgp_Array1OfVec Der(2, 4);
181 // Der(2) = d1; Der(3) = d2; Der(4) = d3;
183 Standard_Integer GOrdre = 4 + 4*Continuity,
184 DDim=Continuity*(Continuity+2);
185 math_Vector GaussP(1, GOrdre), GaussW(1, GOrdre),
186 pol2(1, 2*Continuity+1),
187 pol4(1, 4*Continuity+1);
188 math::GaussPoints(GOrdre, GaussP);
189 math::GaussWeights (GOrdre, GaussW);
192 for (ip=1; ip<=GOrdre; ip++) {
193 t = (GaussP(ip)+1.)/2;
195 PLib::NoDerivativeEvalPolynomial(t , Continuity, Continuity+2, DDim,
196 polynome[0], valhder[0]);
197 V /= Length; //Normalisation
200 // C'(t) = SUM Vi*Lambda
201 Vec1 = Constraint.Col(1);
203 Vec1 += V(size)*Constraint.Col(size);
204 Vec2 = Constraint.Col(2);
206 if (Continuity > 1) {
207 Vec3 = Constraint.Col(3);
209 if (Continuity > 2) {
210 Vec4 = Constraint.Col(4);
219 pol2(1) = Vec1.Norm2();
220 pol2(2) = 2*(Vec1.Multiplied(Vec2));
221 pol2(3) = Vec2.Norm2() - squared1;
223 pol2(3) += 2*(Vec1.Multiplied(Vec3));
224 pol2(4) = 2*(Vec2.Multiplied(Vec3));
225 pol2(5) = Vec3.Norm2();
227 pol2(4)+= 2*(Vec1.Multiplied(Vec4));
228 pol2(5)+= 2*(Vec2.Multiplied(Vec4));
229 pol2(6) = 2*(Vec3.Multiplied(Vec4));
230 pol2(7) = Vec4.Norm2();
235 // Integrale de ( C'(t) - C'(0) )
236 for (ii=1; ii<=pol2.Length(); ii++) {
238 for(jj=1; jj<ii; jj++, pp++) {
239 pol4(pp) += 2*GW*pol2(ii)*pol2(jj);
241 pol4(2*ii-1) += GW*Pow(pol2(ii), 2);
245 Standard_Real EMin, E;
246 PLib::NoDerivativeEvalPolynomial(Lambda , pol4.Length()-1, 1,
250 if (EMin > Precision::Confusion()) {
251 // Recheche des extrema de la fonction
252 GeomLib_PolyFunc FF(pol4);
253 GeomLib_LogSample S(Lambda/1000, 50*Lambda, 100);
254 math_FunctionAllRoots Solve(FF, S, Precision::Confusion(),
255 Precision::Confusion()*(Length+1),
257 if (Solve.IsDone()) {
258 for (ii=1; ii<=Solve.NbPoints(); ii++) {
259 t = Solve.GetPoint(ii);
260 PLib::NoDerivativeEvalPolynomial(t , pol4.Length()-1, 1,
272 #include <Extrema_LocateExtPC.hxx>
273 #include <Geom2d_Curve.hxx>
274 //=======================================================================
275 //function : RemovePointsFromArray
277 //=======================================================================
279 void GeomLib::RemovePointsFromArray(const Standard_Integer NumPoints,
280 const TColStd_Array1OfReal& InParameters,
281 Handle(TColStd_HArray1OfReal)& OutParameters)
292 loc_num_points = Max(0,NumPoints-2) ;
293 delta = InParameters(InParameters.Upper()) - InParameters(InParameters.Lower()) ;
294 delta /= (Standard_Real) (loc_num_points + 1) ;
296 current_parameter = InParameters(InParameters.Lower()) + delta * 0.5e0 ;
297 ii = InParameters.Lower() + 1 ;
298 for (jj = 0 ; ii < InParameters.Upper() && jj < NumPoints ; jj++) {
300 while ( ii < InParameters.Upper() && InParameters(ii) < current_parameter) {
304 num_points += add_one_point ;
305 current_parameter += delta ;
307 if (NumPoints <= 2) {
311 current_parameter = InParameters(InParameters.Lower()) + delta * 0.5e0 ;
313 new TColStd_HArray1OfReal(1,num_points) ;
314 OutParameters->ChangeArray1()(1) = InParameters(InParameters.Lower()) ;
315 ii = InParameters.Lower() + 1 ;
316 for (jj = 0 ; ii < InParameters.Upper() && jj < NumPoints ; jj++) {
318 while (ii < InParameters.Upper() && InParameters(ii) < current_parameter) {
322 if (add_one_point && index <= num_points) {
323 OutParameters->ChangeArray1()(index) = InParameters(ii-1) ;
326 current_parameter += delta ;
328 OutParameters->ChangeArray1()(num_points) = InParameters(InParameters.Upper()) ;
330 //=======================================================================
331 //function : DensifyArray1OfReal
333 //=======================================================================
335 void GeomLib::DensifyArray1OfReal(const Standard_Integer MinNumPoints,
336 const TColStd_Array1OfReal& InParameters,
337 Handle(TColStd_HArray1OfReal)& OutParameters)
342 num_parameters_to_add,
348 if (MinNumPoints > InParameters.Length()) {
351 // checks the paramaters are in increasing order
353 for (ii = InParameters.Lower() ; ii < InParameters.Upper() ; ii++) {
354 if (InParameters(ii) > InParameters(ii+1)) {
360 num_parameters_to_add = MinNumPoints - InParameters.Length() ;
361 delta = InParameters(InParameters.Upper()) - InParameters(InParameters.Lower()) ;
362 delta /= (Standard_Real) (num_parameters_to_add + 1) ;
363 num_points = MinNumPoints ;
365 new TColStd_HArray1OfReal(1,num_points) ;
367 current_parameter = InParameters(InParameters.Lower()) ;
368 OutParameters->ChangeArray1()(index) = current_parameter ;
370 current_parameter += delta ;
371 for (ii = InParameters.Lower() + 1 ; index <= num_points && ii <= InParameters.Upper() ; ii++) {
372 while (current_parameter < InParameters(ii) && index <= num_points) {
373 OutParameters->ChangeArray1()(index) = current_parameter ;
375 current_parameter += delta ;
377 if (index <= num_points) {
378 OutParameters->ChangeArray1()(index) = InParameters(ii) ;
383 // beware of roundoff !
385 OutParameters->ChangeArray1()(num_points) = InParameters(InParameters.Upper()) ;
389 num_points = InParameters.Length() ;
391 new TColStd_HArray1OfReal(1,num_points) ;
392 for (ii = InParameters.Lower() ; ii <= InParameters.Upper() ; ii++) {
393 OutParameters->ChangeArray1()(index) = InParameters(ii) ;
400 num_points = InParameters.Length() ;
402 new TColStd_HArray1OfReal(1,num_points) ;
403 for (ii = InParameters.Lower() ; ii <= InParameters.Upper() ; ii++) {
404 OutParameters->ChangeArray1()(index) = InParameters(ii) ;
410 //=======================================================================
411 //function : FuseIntervals
413 //=======================================================================
414 void GeomLib::FuseIntervals(const TColStd_Array1OfReal& I1,
415 const TColStd_Array1OfReal& I2,
416 TColStd_SequenceOfReal& Seq,
417 const Standard_Real Epspar)
419 Standard_Integer ind1=1, ind2=1;
420 Standard_Real v1, v2;
421 // Initialisations : les IND1 et IND2 pointent sur le 1er element
422 // de chacune des 2 tables a traiter.INDS pointe sur le dernier
423 // element cree de TABSOR
426 //--- On remplit TABSOR en parcourant TABLE1 et TABLE2 simultanement ---
427 //------------------ en eliminant les occurrences multiples ------------
429 while ((ind1<=I1.Upper()) && (ind2<=I2.Upper())) {
432 if (Abs(v1-v2)<= Epspar) {
433 // Ici les elements de I1 et I2 conviennent .
434 Seq.Append((v1+v2)/2);
439 // Ici l' element de I1 convient.
444 // Ici l' element de TABLE2 convient.
450 if (ind1>I1.Upper()) {
451 //----- Ici I1 est epuise, on complete avec la fin de TABLE2 -------
453 for (; ind2<=I2.Upper(); ind2++) {
454 Seq.Append(I2(ind2));
458 if (ind2>I2.Upper()) {
459 //----- Ici I2 est epuise, on complete avec la fin de I1 -------
460 for (; ind1<=I1.Upper(); ind1++) {
461 Seq.Append(I1(ind1));
467 //=======================================================================
468 //function : EvalMaxParametricDistance
470 //=======================================================================
472 void GeomLib::EvalMaxParametricDistance(const Adaptor3d_Curve& ACurve,
473 const Adaptor3d_Curve& AReferenceCurve,
474 // const Standard_Real Tolerance,
475 const Standard_Real ,
476 const TColStd_Array1OfReal& Parameters,
477 Standard_Real& MaxDistance)
479 Standard_Integer ii ;
481 Standard_Real max_squared = 0.0e0,
482 // tolerance_squared,
483 local_distance_squared ;
485 // tolerance_squared = Tolerance * Tolerance ;
488 for (ii = Parameters.Lower() ; ii <= Parameters.Upper() ; ii++) {
489 ACurve.D0(Parameters(ii),
491 AReferenceCurve.D0(Parameters(ii),
493 local_distance_squared =
494 Point1.SquareDistance (Point2) ;
495 max_squared = Max(max_squared,local_distance_squared) ;
497 if (max_squared > 0.0e0) {
498 MaxDistance = sqrt(max_squared) ;
501 MaxDistance = 0.0e0 ;
505 //=======================================================================
506 //function : EvalMaxDistanceAlongParameter
508 //=======================================================================
510 void GeomLib::EvalMaxDistanceAlongParameter(const Adaptor3d_Curve& ACurve,
511 const Adaptor3d_Curve& AReferenceCurve,
512 const Standard_Real Tolerance,
513 const TColStd_Array1OfReal& Parameters,
514 Standard_Real& MaxDistance)
516 Standard_Integer ii ;
517 Standard_Real max_squared = 0.0e0,
518 tolerance_squared = Tolerance * Tolerance,
521 local_distance_squared ;
528 AReferenceCurve.Resolution(Tolerance) ;
529 other_parameter = Parameters(Parameters.Lower()) ;
530 ACurve.D0(other_parameter,
532 Extrema_LocateExtPC a_projector(Point1,
536 for (ii = Parameters.Lower() ; ii <= Parameters.Upper() ; ii++) {
537 ACurve.D0(Parameters(ii),
539 AReferenceCurve.D0(Parameters(ii),
541 local_distance_squared =
542 Point1.SquareDistance (Point2) ;
544 local_distance_squared =
545 Point1.SquareDistance (Point2) ;
548 if (local_distance_squared > tolerance_squared) {
551 a_projector.Perform(Point1,
553 if (a_projector.IsDone()) {
555 a_projector.Point().Parameter() ;
556 AReferenceCurve.D0(other_parameter,
558 local_distance_squared =
559 Point1.SquareDistance (Point2) ;
562 local_distance_squared = 0.0e0 ;
563 other_parameter = Parameters(ii) ;
567 other_parameter = Parameters(ii) ;
571 max_squared = Max(max_squared,local_distance_squared) ;
573 if (max_squared > tolerance_squared) {
574 MaxDistance = sqrt(max_squared) ;
577 MaxDistance = Tolerance ;
585 // Global data definitions:
590 //=======================================================================
593 //=======================================================================
595 Handle(Geom_Curve) GeomLib::To3d (const gp_Ax2& Position,
596 const Handle(Geom2d_Curve)& Curve2d ) {
597 Handle(Geom_Curve) Curve3d;
598 Handle(Standard_Type) KindOfCurve = Curve2d->DynamicType();
600 if (KindOfCurve == STANDARD_TYPE (Geom2d_TrimmedCurve)) {
601 Handle(Geom2d_TrimmedCurve) Ct =
602 Handle(Geom2d_TrimmedCurve)::DownCast(Curve2d);
603 Standard_Real U1 = Ct->FirstParameter ();
604 Standard_Real U2 = Ct->LastParameter ();
605 Handle(Geom2d_Curve) CBasis2d = Ct->BasisCurve();
606 Handle(Geom_Curve) CC = GeomLib::To3d(Position, CBasis2d);
607 Curve3d = new Geom_TrimmedCurve (CC, U1, U2);
609 else if (KindOfCurve == STANDARD_TYPE (Geom2d_OffsetCurve)) {
610 Handle(Geom2d_OffsetCurve) Co =
611 Handle(Geom2d_OffsetCurve)::DownCast(Curve2d);
612 Standard_Real Offset = Co->Offset();
613 Handle(Geom2d_Curve) CBasis2d = Co->BasisCurve();
614 Handle(Geom_Curve) CC = GeomLib::To3d(Position, CBasis2d);
615 Curve3d = new Geom_OffsetCurve (CC, Offset, Position.Direction());
617 else if (KindOfCurve == STANDARD_TYPE (Geom2d_BezierCurve)) {
618 Handle(Geom2d_BezierCurve) CBez2d =
619 Handle(Geom2d_BezierCurve)::DownCast (Curve2d);
620 Standard_Integer Nbpoles = CBez2d->NbPoles ();
621 TColgp_Array1OfPnt2d Poles2d (1, Nbpoles);
622 CBez2d->Poles (Poles2d);
623 TColgp_Array1OfPnt Poles3d (1, Nbpoles);
624 for (Standard_Integer i = 1; i <= Nbpoles; i++) {
625 Poles3d (i) = ElCLib::To3d (Position, Poles2d (i));
627 Handle(Geom_BezierCurve) CBez3d;
628 if (CBez2d->IsRational()) {
629 TColStd_Array1OfReal TheWeights (1, Nbpoles);
630 CBez2d->Weights (TheWeights);
631 CBez3d = new Geom_BezierCurve (Poles3d, TheWeights);
634 CBez3d = new Geom_BezierCurve (Poles3d);
638 else if (KindOfCurve == STANDARD_TYPE (Geom2d_BSplineCurve)) {
639 Handle(Geom2d_BSplineCurve) CBSpl2d =
640 Handle(Geom2d_BSplineCurve)::DownCast (Curve2d);
641 Standard_Integer Nbpoles = CBSpl2d->NbPoles ();
642 Standard_Integer Nbknots = CBSpl2d->NbKnots ();
643 Standard_Integer TheDegree = CBSpl2d->Degree ();
644 Standard_Boolean IsPeriodic = CBSpl2d->IsPeriodic();
645 TColgp_Array1OfPnt2d Poles2d (1, Nbpoles);
646 CBSpl2d->Poles (Poles2d);
647 TColgp_Array1OfPnt Poles3d (1, Nbpoles);
648 for (Standard_Integer i = 1; i <= Nbpoles; i++) {
649 Poles3d (i) = ElCLib::To3d (Position, Poles2d (i));
651 TColStd_Array1OfReal TheKnots (1, Nbknots);
652 TColStd_Array1OfInteger TheMults (1, Nbknots);
653 CBSpl2d->Knots (TheKnots);
654 CBSpl2d->Multiplicities (TheMults);
655 Handle(Geom_BSplineCurve) CBSpl3d;
656 if (CBSpl2d->IsRational()) {
657 TColStd_Array1OfReal TheWeights (1, Nbpoles);
658 CBSpl2d->Weights (TheWeights);
659 CBSpl3d = new Geom_BSplineCurve (Poles3d, TheWeights, TheKnots, TheMults, TheDegree, IsPeriodic);
662 CBSpl3d = new Geom_BSplineCurve (Poles3d, TheKnots, TheMults, TheDegree, IsPeriodic);
666 else if (KindOfCurve == STANDARD_TYPE (Geom2d_Line)) {
667 Handle(Geom2d_Line) Line2d = Handle(Geom2d_Line)::DownCast (Curve2d);
668 gp_Lin2d L2d = Line2d->Lin2d();
669 gp_Lin L3d = ElCLib::To3d (Position, L2d);
670 Handle(Geom_Line) GeomL3d = new Geom_Line (L3d);
673 else if (KindOfCurve == STANDARD_TYPE (Geom2d_Circle)) {
674 Handle(Geom2d_Circle) Circle2d =
675 Handle(Geom2d_Circle)::DownCast (Curve2d);
676 gp_Circ2d C2d = Circle2d->Circ2d();
677 gp_Circ C3d = ElCLib::To3d (Position, C2d);
678 Handle(Geom_Circle) GeomC3d = new Geom_Circle (C3d);
681 else if (KindOfCurve == STANDARD_TYPE (Geom2d_Ellipse)) {
682 Handle(Geom2d_Ellipse) Ellipse2d =
683 Handle(Geom2d_Ellipse)::DownCast (Curve2d);
684 gp_Elips2d E2d = Ellipse2d->Elips2d ();
685 gp_Elips E3d = ElCLib::To3d (Position, E2d);
686 Handle(Geom_Ellipse) GeomE3d = new Geom_Ellipse (E3d);
689 else if (KindOfCurve == STANDARD_TYPE (Geom2d_Parabola)) {
690 Handle(Geom2d_Parabola) Parabola2d =
691 Handle(Geom2d_Parabola)::DownCast (Curve2d);
692 gp_Parab2d Prb2d = Parabola2d->Parab2d ();
693 gp_Parab Prb3d = ElCLib::To3d (Position, Prb2d);
694 Handle(Geom_Parabola) GeomPrb3d = new Geom_Parabola (Prb3d);
697 else if (KindOfCurve == STANDARD_TYPE (Geom2d_Hyperbola)) {
698 Handle(Geom2d_Hyperbola) Hyperbola2d =
699 Handle(Geom2d_Hyperbola)::DownCast (Curve2d);
700 gp_Hypr2d H2d = Hyperbola2d->Hypr2d ();
701 gp_Hypr H3d = ElCLib::To3d (Position, H2d);
702 Handle(Geom_Hyperbola) GeomH3d = new Geom_Hyperbola (H3d);
706 throw Standard_NotImplemented();
714 //=======================================================================
715 //function : GTransform
717 //=======================================================================
719 Handle(Geom2d_Curve) GeomLib::GTransform(const Handle(Geom2d_Curve)& Curve,
720 const gp_GTrsf2d& GTrsf)
722 gp_TrsfForm Form = GTrsf.Form();
724 if ( Form != gp_Other) {
726 // Alors, la GTrsf est en fait une Trsf.
727 // La geometrie des courbes sera alors inchangee.
729 Handle(Geom2d_Curve) C =
730 Handle(Geom2d_Curve)::DownCast(Curve->Transformed(GTrsf.Trsf2d()));
735 // Alors, la GTrsf est une other Transformation.
736 // La geometrie des courbes est alors changee, et les conics devront
737 // etre converties en BSplines.
739 Handle(Standard_Type) TheType = Curve->DynamicType();
741 if ( TheType == STANDARD_TYPE(Geom2d_TrimmedCurve)) {
743 // On va recurer sur la BasisCurve
745 Handle(Geom2d_TrimmedCurve) C =
746 Handle(Geom2d_TrimmedCurve)::DownCast(Curve->Copy());
748 Handle(Standard_Type) TheBasisType = (C->BasisCurve())->DynamicType();
750 if (TheBasisType == STANDARD_TYPE(Geom2d_BSplineCurve) ||
751 TheBasisType == STANDARD_TYPE(Geom2d_BezierCurve) ) {
753 // Dans ces cas le parametrage est conserve sur la courbe transformee
754 // on peut donc la trimmer avec les parametres de la courbe de base.
756 Standard_Real U1 = C->FirstParameter();
757 Standard_Real U2 = C->LastParameter();
759 Handle(Geom2d_TrimmedCurve) result =
760 new Geom2d_TrimmedCurve(GTransform(C->BasisCurve(), GTrsf), U1,U2);
763 else if ( TheBasisType == STANDARD_TYPE(Geom2d_Line)) {
765 // Dans ce cas, le parametrage n`est plus conserve.
766 // Il faut recalculer les parametres de Trimming sur la courbe
767 // resultante. ( Calcul par projection ( ElCLib) des points debut
768 // et fin transformes)
770 Handle(Geom2d_Line) L =
771 Handle(Geom2d_Line)::DownCast(GTransform(C->BasisCurve(), GTrsf));
772 gp_Lin2d Lin = L->Lin2d();
774 gp_Pnt2d P1 = C->StartPoint();
775 gp_Pnt2d P2 = C->EndPoint();
776 P1.SetXY(GTrsf.Transformed(P1.XY()));
777 P2.SetXY(GTrsf.Transformed(P2.XY()));
778 Standard_Real U1 = ElCLib::Parameter(Lin,P1);
779 Standard_Real U2 = ElCLib::Parameter(Lin,P2);
781 Handle(Geom2d_TrimmedCurve) result =
782 new Geom2d_TrimmedCurve(L,U1,U2);
785 else if (TheBasisType == STANDARD_TYPE(Geom2d_Circle) ||
786 TheBasisType == STANDARD_TYPE(Geom2d_Ellipse) ||
787 TheBasisType == STANDARD_TYPE(Geom2d_Parabola) ||
788 TheBasisType == STANDARD_TYPE(Geom2d_Hyperbola) ) {
790 // Dans ces cas, la geometrie de la courbe n`est pas conservee
791 // on la convertir en BSpline avant de lui appliquer la Trsf.
793 Handle(Geom2d_BSplineCurve) BS =
794 Geom2dConvert::CurveToBSplineCurve(C);
795 return GTransform(BS,GTrsf);
799 // La transformee d`une OffsetCurve vaut ????? Sais pas faire !!
801 Handle(Geom2d_Curve) dummy;
805 else if ( TheType == STANDARD_TYPE(Geom2d_Line)) {
807 Handle(Geom2d_Line) L =
808 Handle(Geom2d_Line)::DownCast(Curve->Copy());
809 gp_Lin2d Lin = L->Lin2d();
810 gp_Pnt2d P = Lin.Location();
811 gp_Pnt2d PP = L->Value(10.); // pourquoi pas !!
812 P.SetXY(GTrsf.Transformed(P.XY()));
813 PP.SetXY(GTrsf.Transformed(PP.XY()));
816 L->SetDirection(gp_Dir2d(V));
819 else if ( TheType == STANDARD_TYPE(Geom2d_BezierCurve)) {
821 // Les GTrsf etant des operation lineaires, la transformee d`une courbe
822 // a poles est la courbe dont les poles sont la transformee des poles
823 // de la courbe de base.
825 Handle(Geom2d_BezierCurve) C =
826 Handle(Geom2d_BezierCurve)::DownCast(Curve->Copy());
827 Standard_Integer NbPoles = C->NbPoles();
828 TColgp_Array1OfPnt2d Poles(1,NbPoles);
830 for ( Standard_Integer i = 1; i <= NbPoles; i++) {
831 Poles(i).SetXY(GTrsf.Transformed(Poles(i).XY()));
832 C->SetPole(i,Poles(i));
836 else if ( TheType == STANDARD_TYPE(Geom2d_BSplineCurve)) {
838 // Voir commentaire pour les Bezier.
840 Handle(Geom2d_BSplineCurve) C =
841 Handle(Geom2d_BSplineCurve)::DownCast(Curve->Copy());
842 Standard_Integer NbPoles = C->NbPoles();
843 TColgp_Array1OfPnt2d Poles(1,NbPoles);
845 for ( Standard_Integer i = 1; i <= NbPoles; i++) {
846 Poles(i).SetXY(GTrsf.Transformed(Poles(i).XY()));
847 C->SetPole(i,Poles(i));
851 else if ( TheType == STANDARD_TYPE(Geom2d_Circle) ||
852 TheType == STANDARD_TYPE(Geom2d_Ellipse) ) {
854 // Dans ces cas, la geometrie de la courbe n`est pas conservee
855 // on la convertir en BSpline avant de lui appliquer la Trsf.
857 Handle(Geom2d_BSplineCurve) C =
858 Geom2dConvert::CurveToBSplineCurve(Curve);
859 return GTransform(C, GTrsf);
861 else if ( TheType == STANDARD_TYPE(Geom2d_Parabola) ||
862 TheType == STANDARD_TYPE(Geom2d_Hyperbola) ||
863 TheType == STANDARD_TYPE(Geom2d_OffsetCurve) ) {
865 // On ne sait pas faire : return a null Handle;
867 Handle(Geom2d_Curve) dummy;
872 Handle(Geom2d_Curve) WNT__; // portage Windows.
877 //=======================================================================
878 //function : SameRange
880 //=======================================================================
881 void GeomLib::SameRange(const Standard_Real Tolerance,
882 const Handle(Geom2d_Curve)& CurvePtr,
883 const Standard_Real FirstOnCurve,
884 const Standard_Real LastOnCurve,
885 const Standard_Real RequestedFirst,
886 const Standard_Real RequestedLast,
887 Handle(Geom2d_Curve)& NewCurvePtr)
889 if(CurvePtr.IsNull()) throw Standard_Failure();
890 if (Abs(LastOnCurve - RequestedLast) <= Tolerance &&
891 Abs(FirstOnCurve - RequestedFirst) <= Tolerance)
893 NewCurvePtr = CurvePtr;
897 // the parametrisation lentgh must at least be the same.
898 if (Abs(LastOnCurve - FirstOnCurve - RequestedLast + RequestedFirst)
901 if (CurvePtr->IsKind(STANDARD_TYPE(Geom2d_Line)))
903 Handle(Geom2d_Line) Line =
904 Handle(Geom2d_Line)::DownCast(CurvePtr->Copy());
905 Standard_Real dU = FirstOnCurve - RequestedFirst;
906 gp_Dir2d D = Line->Direction() ;
907 Line->Translate(dU * gp_Vec2d(D));
910 else if (CurvePtr->IsKind(STANDARD_TYPE(Geom2d_Circle)))
913 NewCurvePtr = Handle(Geom2d_Curve)::DownCast(CurvePtr->Copy());
914 Handle(Geom2d_Circle) Circ =
915 Handle(Geom2d_Circle)::DownCast(NewCurvePtr);
916 gp_Pnt2d P = Circ->Location();
918 if (Circ->Circ2d().IsDirect()) {
919 dU = FirstOnCurve - RequestedFirst;
922 dU = RequestedFirst - FirstOnCurve;
924 Trsf.SetRotation(P,dU);
925 NewCurvePtr->Transform(Trsf) ;
927 else if (CurvePtr->IsKind(STANDARD_TYPE(Geom2d_TrimmedCurve)))
929 Handle(Geom2d_TrimmedCurve) TC =
930 Handle(Geom2d_TrimmedCurve)::DownCast(CurvePtr);
931 GeomLib::SameRange(Tolerance,
933 FirstOnCurve , LastOnCurve,
934 RequestedFirst, RequestedLast,
936 NewCurvePtr = new Geom2d_TrimmedCurve( NewCurvePtr, RequestedFirst, RequestedLast );
939 // attention a des problemes de limitation : utiliser le MEME test que dans
940 // Geom2d_TrimmedCurve::SetTrim car sinon comme on risque de relimite sur
941 // RequestedFirst et RequestedLast on aura un probleme
944 else if (Abs(LastOnCurve - FirstOnCurve) > Precision::PConfusion() ||
945 Abs(RequestedLast + RequestedFirst) > Precision::PConfusion())
948 Handle(Geom2d_TrimmedCurve) TC =
949 new Geom2d_TrimmedCurve(CurvePtr,FirstOnCurve,LastOnCurve);
951 Handle(Geom2d_BSplineCurve) BS =
952 Geom2dConvert::CurveToBSplineCurve(TC);
953 TColStd_Array1OfReal Knots(1,BS->NbKnots());
956 BSplCLib::Reparametrize(RequestedFirst,RequestedLast,Knots);
963 { // On segmente le resultat
964 Handle(Geom2d_TrimmedCurve) TC;
965 Handle(Geom2d_Curve) aCCheck = CurvePtr;
967 if(aCCheck->IsKind(STANDARD_TYPE(Geom2d_TrimmedCurve)))
969 aCCheck = Handle(Geom2d_TrimmedCurve)::DownCast(aCCheck)->BasisCurve();
972 if(aCCheck->IsPeriodic())
974 if(Abs(LastOnCurve - FirstOnCurve) > Precision::PConfusion())
976 TC = new Geom2d_TrimmedCurve( CurvePtr, FirstOnCurve, LastOnCurve );
980 TC = new Geom2d_TrimmedCurve( CurvePtr, CurvePtr->FirstParameter(), CurvePtr->LastParameter() );
985 const Standard_Real Udeb = Max(CurvePtr->FirstParameter(), FirstOnCurve);
986 const Standard_Real Ufin = Min(CurvePtr->LastParameter(), LastOnCurve);
987 if(Abs(Ufin - Udeb) > Precision::PConfusion())
989 TC = new Geom2d_TrimmedCurve( CurvePtr, Udeb, Ufin );
993 TC = new Geom2d_TrimmedCurve( CurvePtr, CurvePtr->FirstParameter(), CurvePtr->LastParameter());
998 Handle(Geom2d_BSplineCurve) BS =
999 Geom2dConvert::CurveToBSplineCurve(TC);
1000 TColStd_Array1OfReal Knots(1,BS->NbKnots());
1003 BSplCLib::Reparametrize(RequestedFirst,RequestedLast,Knots);
1005 BS->SetKnots(Knots);
1010 //=======================================================================
1011 //class : GeomLib_CurveOnSurfaceEvaluator
1012 //purpose: The evaluator for the Curve 3D building
1013 //=======================================================================
1015 class GeomLib_CurveOnSurfaceEvaluator : public AdvApprox_EvaluatorFunction
1018 GeomLib_CurveOnSurfaceEvaluator (Adaptor3d_CurveOnSurface& theCurveOnSurface,
1019 Standard_Real theFirst, Standard_Real theLast)
1020 : CurveOnSurface(theCurveOnSurface), FirstParam(theFirst), LastParam(theLast) {}
1022 virtual void Evaluate (Standard_Integer *Dimension,
1023 Standard_Real StartEnd[2],
1024 Standard_Real *Parameter,
1025 Standard_Integer *DerivativeRequest,
1026 Standard_Real *Result, // [Dimension]
1027 Standard_Integer *ErrorCode);
1030 Adaptor3d_CurveOnSurface& CurveOnSurface;
1031 Standard_Real FirstParam;
1032 Standard_Real LastParam;
1034 Handle(Adaptor3d_HCurve) TrimCurve;
1037 void GeomLib_CurveOnSurfaceEvaluator::Evaluate (Standard_Integer *,/*Dimension*/
1038 Standard_Real DebutFin[2],
1039 Standard_Real *Parameter,
1040 Standard_Integer *DerivativeRequest,
1041 Standard_Real *Result,// [Dimension]
1042 Standard_Integer *ReturnCode)
1046 //Gestion des positionnements gauche / droite
1047 if ((DebutFin[0] != FirstParam) || (DebutFin[1] != LastParam))
1049 TrimCurve = CurveOnSurface.Trim(DebutFin[0], DebutFin[1], Precision::PConfusion());
1050 FirstParam = DebutFin[0];
1051 LastParam = DebutFin[1];
1055 if (*DerivativeRequest == 0)
1057 TrimCurve->D0((*Parameter), Point) ;
1059 for (Standard_Integer ii = 0 ; ii < 3 ; ii++)
1060 Result[ii] = Point.Coord(ii + 1);
1062 if (*DerivativeRequest == 1)
1065 TrimCurve->D1((*Parameter), Point, Vector);
1066 for (Standard_Integer ii = 0 ; ii < 3 ; ii++)
1067 Result[ii] = Vector.Coord(ii + 1) ;
1069 if (*DerivativeRequest == 2)
1071 gp_Vec Vector, VecBis;
1072 TrimCurve->D2((*Parameter), Point, VecBis, Vector);
1073 for (Standard_Integer ii = 0 ; ii < 3 ; ii++)
1074 Result[ii] = Vector.Coord(ii + 1) ;
1079 //=======================================================================
1080 //function : BuildCurve3d
1082 //=======================================================================
1084 void GeomLib::BuildCurve3d(const Standard_Real Tolerance,
1085 Adaptor3d_CurveOnSurface& Curve,
1086 const Standard_Real FirstParameter,
1087 const Standard_Real LastParameter,
1088 Handle(Geom_Curve)& NewCurvePtr,
1089 Standard_Real& MaxDeviation,
1090 Standard_Real& AverageDeviation,
1091 const GeomAbs_Shape Continuity,
1092 const Standard_Integer MaxDegree,
1093 const Standard_Integer MaxSegment)
1098 Standard_Integer curve_not_computed = 1 ;
1099 MaxDeviation = 0.0e0 ;
1100 AverageDeviation = 0.0e0 ;
1101 Handle(GeomAdaptor_HSurface) geom_adaptor_surface_ptr (Handle(GeomAdaptor_HSurface)::DownCast(Curve.GetSurface()) );
1102 Handle(Geom2dAdaptor_HCurve) geom_adaptor_curve_ptr (Handle(Geom2dAdaptor_HCurve)::DownCast(Curve.GetCurve()) );
1104 if (! geom_adaptor_curve_ptr.IsNull() &&
1105 ! geom_adaptor_surface_ptr.IsNull()) {
1106 Handle(Geom_Plane) P ;
1107 const GeomAdaptor_Surface & geom_surface =
1108 * (GeomAdaptor_Surface *) &geom_adaptor_surface_ptr->Surface() ;
1110 Handle(Geom_RectangularTrimmedSurface) RT =
1111 Handle(Geom_RectangularTrimmedSurface)::
1112 DownCast(geom_surface.Surface());
1114 P = Handle(Geom_Plane)::DownCast(geom_surface.Surface());
1117 P = Handle(Geom_Plane)::DownCast(RT->BasisSurface());
1122 // compute the 3d curve
1123 gp_Ax2 axes = P->Position().Ax2();
1124 const Geom2dAdaptor_Curve & geom2d_curve =
1125 * (Geom2dAdaptor_Curve *) & geom_adaptor_curve_ptr->Curve2d() ;
1128 geom2d_curve.Curve());
1129 curve_not_computed = 0 ;
1133 if (curve_not_computed) {
1138 Handle(TColStd_HArray1OfReal) Tolerance1DPtr,Tolerance2DPtr;
1139 Handle(TColStd_HArray1OfReal) Tolerance3DPtr =
1140 new TColStd_HArray1OfReal(1,1) ;
1141 Tolerance3DPtr->SetValue(1,Tolerance);
1143 // Recherche des discontinuitees
1144 Standard_Integer NbIntervalC2 = Curve.NbIntervals(GeomAbs_C2);
1145 TColStd_Array1OfReal Param_de_decoupeC2 (1, NbIntervalC2+1);
1146 Curve.Intervals(Param_de_decoupeC2, GeomAbs_C2);
1148 Standard_Integer NbIntervalC3 = Curve.NbIntervals(GeomAbs_C3);
1149 TColStd_Array1OfReal Param_de_decoupeC3 (1, NbIntervalC3+1);
1150 Curve.Intervals(Param_de_decoupeC3, GeomAbs_C3);
1152 // Note extension of the parameteric range
1153 // Pour forcer le Trim au premier appel de l'evaluateur
1154 GeomLib_CurveOnSurfaceEvaluator ev (Curve, FirstParameter - 1., LastParameter + 1.);
1156 // Approximation avec decoupe preferentiel
1157 AdvApprox_PrefAndRec Preferentiel(Param_de_decoupeC2,
1158 Param_de_decoupeC3);
1159 AdvApprox_ApproxAFunction anApproximator(0,
1171 // CurveOnSurfaceEvaluator,
1174 if (anApproximator.HasResult()) {
1175 GeomLib_MakeCurvefromApprox
1176 aCurveBuilder(anApproximator) ;
1178 Handle(Geom_BSplineCurve) aCurvePtr =
1179 aCurveBuilder.Curve(1) ;
1180 // On rend les resultats de l'approx
1181 MaxDeviation = anApproximator.MaxError(3,1) ;
1182 AverageDeviation = anApproximator.AverageError(3,1) ;
1183 NewCurvePtr = aCurvePtr ;
1188 //=======================================================================
1189 //function : AdjustExtremity
1191 //=======================================================================
1193 void GeomLib::AdjustExtremity(Handle(Geom_BoundedCurve)& Curve,
1199 // il faut Convertir l'entree (en preservant si possible le parametrage)
1200 Handle(Geom_BSplineCurve) aIn, aDef;
1201 aIn = GeomConvert::CurveToBSplineCurve(Curve, Convert_QuasiAngular);
1203 Standard_Integer ii, jj;
1206 TColgp_Array1OfPnt PolesDef(1,4), Coeffs(1,4);
1207 TColStd_Array1OfReal FK(1, 8);
1208 TColStd_Array1OfReal Ti(1, 4);
1209 TColStd_Array1OfInteger Contact(1, 4);
1211 Ti(1) = Ti(2) = aIn->FirstParameter();
1212 Ti(3) = Ti(4) = aIn->LastParameter();
1213 Contact(1) = Contact(3) = 0;
1214 Contact(2) = Contact(4) = 1;
1215 for (ii=1; ii<=4; ii++) {
1216 FK(ii) = aIn->FirstParameter();
1217 FK(ii) = aIn->LastParameter();
1220 // Calculs des contraintes de deformations
1221 aIn->D1(Ti(1), P, V);
1222 PolesDef(1).ChangeCoord() = P1.XYZ()-P.XYZ();
1225 DV = Vtan * (Vtan * V) - V;
1226 PolesDef(2).ChangeCoord() = (Ti(4)-Ti(1))*DV.XYZ();
1228 aIn->D1(Ti(4), P, V);
1229 PolesDef(3).ChangeCoord() = P2.XYZ()-P.XYZ();
1232 DV = Vtan * (Vtan * V) - V;
1233 PolesDef(4).ChangeCoord() = (Ti(4)-Ti(1))* DV.XYZ();
1235 // Interpolation des contraintes
1236 math_Matrix Mat(1, 4, 1, 4);
1237 if (!PLib::HermiteCoefficients(0., 1., 1, 1, Mat))
1238 throw Standard_ConstructionError();
1240 for (jj=1; jj<=4; jj++) {
1241 gp_XYZ aux(0.,0.,0.);
1242 for (ii=1; ii<=4; ii++) {
1243 aux.SetLinearForm(Mat(ii,jj), PolesDef(ii).XYZ(), aux);
1245 Coeffs(jj).SetXYZ(aux);
1248 PLib::CoefficientsPoles(Coeffs, PLib::NoWeights(),
1249 PolesDef, PLib::NoWeights());
1251 // Ajout de la deformation
1252 TColStd_Array1OfReal K(1, 2);
1253 TColStd_Array1OfInteger M(1, 2);
1258 aDef = new (Geom_BSplineCurve) (PolesDef, K, M, 3);
1259 if (aIn->Degree() < 3) aIn->IncreaseDegree(3);
1260 else aDef->IncreaseDegree(aIn->Degree());
1262 for (ii=2; ii<aIn->NbKnots(); ii++) {
1263 aDef->InsertKnot(aIn->Knot(ii), aIn->Multiplicity(ii));
1266 if (aDef->NbPoles() != aIn->NbPoles())
1267 throw Standard_ConstructionError("Inconsistent poles's number");
1269 for (ii=1; ii<=aDef->NbPoles(); ii++) {
1271 P.ChangeCoord() += aDef->Pole(ii).XYZ();
1272 aIn->SetPole(ii, P);
1276 //=======================================================================
1277 //function : ExtendCurveToPoint
1279 //=======================================================================
1281 void GeomLib::ExtendCurveToPoint(Handle(Geom_BoundedCurve)& Curve,
1282 const gp_Pnt& Point,
1283 const Standard_Integer Continuity,
1284 const Standard_Boolean After)
1286 if(Continuity < 1 || Continuity > 3) return;
1287 Standard_Integer size = Continuity + 2;
1288 Standard_Real Ubord, Tol=1.e-6;
1289 math_Matrix MatCoefs(1,size, 1,size);
1290 Standard_Real Lambda, L1;
1291 Standard_Integer ii, jj;
1294 // il faut Convertir l'entree (en preservant si possible le parametrage)
1295 GeomConvert_CompCurveToBSplineCurve Concat(Curve, Convert_QuasiAngular);
1297 // Les contraintes de constructions
1298 TColgp_Array1OfXYZ Cont(1,size);
1300 Ubord = Curve->LastParameter();
1304 Ubord = Curve->FirstParameter();
1306 PLib::HermiteCoefficients(0, 1, // Les Bornes
1307 Continuity, 0, // Les Ordres de contraintes
1310 Curve->D3(Ubord, p0, d1, d2, d3);
1311 if (!After) { // Inversion du parametrage
1316 L1 = p0.Distance(Point);
1318 // Lambda est le ratio qu'il faut appliquer a la derive de la courbe
1319 // pour obtenir la derive du prolongement (fixe arbitrairement a la
1320 // longueur du segment bout de la courbe - point cible.
1321 // On essai d'avoir sur le prolongement la vitesse moyenne que l'on
1325 Standard_Real f= Curve->FirstParameter(), t, dt, norm;
1326 dt = (Curve->LastParameter()-f)/9;
1327 norm = d1.Magnitude();
1328 for (ii=1, t=f+dt; ii<=8; ii++, t+=dt) {
1329 Curve->D1(t, pp, daux);
1330 norm += daux.Magnitude();
1333 dt = d1.Magnitude() / norm;
1334 if ((dt<1.5) && (dt>0.75)) { // Le bord est dans la moyenne on le garde
1335 Lambda = ((Standard_Real)1) / Max (d1.Magnitude() / L1, Tol);
1338 Lambda = ((Standard_Real)1) / Max (norm / L1, Tol);
1342 return; // Pas d'extension
1345 // Optimisation du Lambda
1346 math_Matrix Cons(1, 3, 1, size);
1347 Cons(1,1) = p0.X(); Cons(2,1) = p0.Y(); Cons(3,1) = p0.Z();
1348 Cons(1,2) = d1.X(); Cons(2,2) = d1.Y(); Cons(3,2) = d1.Z();
1349 Cons(1,size) = Point.X(); Cons(2,size) = Point.Y(); Cons(3,size) = Point.Z();
1350 if (Continuity >= 2) {
1351 Cons(1,3) = d2.X(); Cons(2,3) = d2.Y(); Cons(3,3) = d2.Z();
1353 if (Continuity >= 3) {
1354 Cons(1,4) = d3.X(); Cons(2,4) = d3.Y(); Cons(3,4) = d3.Z();
1356 ComputeLambda(Cons, MatCoefs, L1, Lambda);
1358 // Construction dans la Base Polynomiale
1360 Cont(2) = d1.XYZ() * Lambda;
1361 if(Continuity >= 2) Cont(3) = d2.XYZ() * Pow(Lambda,2);
1362 if(Continuity >= 3) Cont(4) = d3.XYZ() * Pow(Lambda,3);
1363 Cont(size) = Point.XYZ();
1366 TColgp_Array1OfPnt ExtrapPoles(1, size);
1367 TColgp_Array1OfPnt ExtraCoeffs(1, size);
1369 gp_Pnt PNull(0.,0.,0.);
1370 ExtraCoeffs.Init(PNull);
1371 for (ii=1; ii<=size; ii++) {
1372 for (jj=1; jj<=size; jj++) {
1373 ExtraCoeffs(jj).ChangeCoord() += MatCoefs(ii,jj)*Cont(ii);
1377 // Convertion Dans la Base de Bernstein
1378 PLib::CoefficientsPoles(ExtraCoeffs, PLib::NoWeights(),
1379 ExtrapPoles, PLib::NoWeights());
1381 Handle(Geom_BezierCurve) Bezier = new (Geom_BezierCurve) (ExtrapPoles);
1383 Standard_Real dist = ExtrapPoles(1).Distance(p0);
1384 Standard_Boolean Ok;
1388 Ok = Concat.Add(Bezier, Tol, After);
1389 if (!Ok) throw Standard_ConstructionError("ExtendCurveToPoint");
1391 Curve = Concat.BSplineCurve();
1395 //=======================================================================
1396 //function : ExtendKPart
1397 //purpose : Extension par longueur des surfaces cannonique
1398 //=======================================================================
1399 static Standard_Boolean
1400 ExtendKPart(Handle(Geom_RectangularTrimmedSurface)& Surface,
1401 const Standard_Real Length,
1402 const Standard_Boolean InU,
1403 const Standard_Boolean After)
1406 if (Surface.IsNull()) return Standard_False;
1408 Standard_Boolean Ok=Standard_True;
1409 Standard_Real Uf, Ul, Vf, Vl;
1410 Handle(Geom_Surface) Support = Surface->BasisSurface();
1411 GeomAbs_SurfaceType Type;
1413 Surface->Bounds(Uf, Ul, Vf, Vl);
1414 GeomAdaptor_Surface AS(Surface);
1415 Type = AS.GetType();
1419 case GeomAbs_Plane :
1421 if (After) Ul+=Length;
1423 Surface = new (Geom_RectangularTrimmedSurface)
1424 (Support, Uf, Ul, Vf, Vl);
1429 Ok = Standard_False;
1434 case GeomAbs_Plane :
1435 case GeomAbs_Cylinder :
1436 case GeomAbs_SurfaceOfExtrusion :
1438 if (After) Vl+=Length;
1440 Surface = new (Geom_RectangularTrimmedSurface)
1441 (Support, Uf, Ul, Vf, Vl);
1445 Ok = Standard_False;
1452 //=======================================================================
1453 //function : ExtendSurfByLength
1455 //=======================================================================
1456 void GeomLib::ExtendSurfByLength(Handle(Geom_BoundedSurface)& Surface,
1457 const Standard_Real Length,
1458 const Standard_Integer Continuity,
1459 const Standard_Boolean InU,
1460 const Standard_Boolean After)
1462 if(Continuity < 0 || Continuity > 3) return;
1463 Standard_Integer Cont = Continuity;
1466 Handle(Geom_RectangularTrimmedSurface) TS =
1467 Handle(Geom_RectangularTrimmedSurface)::DownCast (Surface);
1468 if (ExtendKPart(TS,Length, InU, After) ) {
1473 // format BSplineSurface avec un degre suffisant pour la continuite voulue
1474 Handle(Geom_BSplineSurface) BS =
1475 Handle(Geom_BSplineSurface)::DownCast (Surface);
1477 //BS = GeomConvert::SurfaceToBSplineSurface(Surface);
1478 Standard_Real Tol = Precision::Confusion(); //1.e-4;
1479 GeomAbs_Shape UCont = GeomAbs_C1, VCont = GeomAbs_C1;
1480 Standard_Integer degU = 14, degV = 14;
1481 Standard_Integer nmax = 16;
1482 Standard_Integer thePrec = 1;
1483 const Handle(Geom_Surface)& aSurf = Surface; // to resolve ambiguity
1484 GeomConvert_ApproxSurface theApprox(aSurf,Tol,UCont,VCont,degU,degV,nmax,thePrec);
1485 if (theApprox.HasResult())
1486 BS = theApprox.Surface();
1488 BS = GeomConvert::SurfaceToBSplineSurface(Surface);
1490 if (InU&&(BS->UDegree()<Continuity+1))
1491 BS->IncreaseDegree(Continuity+1,BS->VDegree());
1492 if (!InU&&(BS->VDegree()<Continuity+1))
1493 BS->IncreaseDegree(BS->UDegree(),Continuity+1);
1495 // si BS etait periodique dans le sens de l'extension, elle ne le sera plus
1496 if ( (InU&&(BS->IsUPeriodic())) || (!InU&&(BS->IsVPeriodic())) ) {
1497 Standard_Real U0,U1,V0,V1;
1498 BS->Bounds(U0,U1,V0,V1);
1499 BS->Segment(U0,U1,V0,V1);
1503 // IFV Fix OCC bug 0022694 - wrong result extrapolating rational surfaces
1504 // Standard_Boolean rational = ( InU && BS->IsURational() )
1505 // || ( !InU && BS->IsVRational() ) ;
1506 Standard_Boolean rational = (BS->IsURational() || BS->IsVRational());
1507 Standard_Boolean NullWeight;
1508 Standard_Real EpsW = 10*Precision::PConfusion();
1509 Standard_Integer gap = 3;
1510 if ( rational ) gap++;
1514 Standard_Integer Cdeg = 0, Cdim = 0, NbP = 0, Ksize = 0, Psize = 1;
1515 Standard_Integer ii, jj, ipole, Kount;
1516 Standard_Real Tbord, lambmin=Length;
1517 Standard_Real * Padr = NULL;
1518 Standard_Boolean Ok;
1519 Handle(TColStd_HArray1OfReal) FKnots, Point, lambda, Tgte, Poles;
1524 for (Kount=0, Ok=Standard_False; Kount<=2 && !Ok; Kount++) {
1525 // transformation de la surface en une BSpline non rationnelle a une variable
1526 // de degre UDegree ou VDegree et de dimension 3 ou 4 x NbVpoles ou NbUpoles
1527 // le nombre de poles egal a NbUpoles ou NbVpoles
1528 // ATTENTION : dans le cas rationnel, un point de coordonnees (x,y,z)
1529 // et de poids w devient un point de coordonnees (wx, wy, wz, w )
1533 Cdeg = BS->UDegree();
1534 NbP = BS->NbUPoles();
1535 Cdim = BS->NbVPoles() * gap;
1538 Cdeg = BS->VDegree();
1539 NbP = BS->NbVPoles();
1540 Cdim = BS->NbUPoles() * gap;
1544 Ksize = NbP + Cdeg + 1;
1545 FKnots = new (TColStd_HArray1OfReal) (1,Ksize);
1547 BS->UKnotSequence(FKnots->ChangeArray1());
1549 BS->VKnotSequence(FKnots->ChangeArray1());
1551 // le parametre du noeud de raccord
1553 Tbord = FKnots->Value(FKnots->Upper()-Cdeg);
1555 Tbord = FKnots->Value(FKnots->Lower()+Cdeg);
1559 Poles = new (TColStd_HArray1OfReal) (1,Psize);
1562 for (ii=1,ipole=1; ii<=NbP; ii++) {
1563 for (jj=1;jj<=BS->NbVPoles();jj++) {
1564 Poles->SetValue(ipole, BS->Pole(ii,jj).X());
1565 Poles->SetValue(ipole+1, BS->Pole(ii,jj).Y());
1566 Poles->SetValue(ipole+2, BS->Pole(ii,jj).Z());
1567 if (rational) Poles->SetValue(ipole+3, BS->Weight(ii,jj));
1573 for (jj=1,ipole=1; jj<=NbP; jj++) {
1574 for (ii=1;ii<=BS->NbUPoles();ii++) {
1575 Poles->SetValue(ipole, BS->Pole(ii,jj).X());
1576 Poles->SetValue(ipole+1, BS->Pole(ii,jj).Y());
1577 Poles->SetValue(ipole+2, BS->Pole(ii,jj).Z());
1578 if (rational) Poles->SetValue(ipole+3, BS->Weight(ii,jj));
1583 Padr = (Standard_Real *) &Poles->ChangeValue(1);
1585 // calcul du point de raccord et de la tangente
1586 Point = new (TColStd_HArray1OfReal)(1,Cdim);
1587 Tgte = new (TColStd_HArray1OfReal)(1,Cdim);
1588 lambda = new (TColStd_HArray1OfReal)(1,Cdim);
1590 Standard_Boolean periodic_flag = Standard_False ;
1591 Standard_Integer extrap_mode[2], derivative_request = Max(Continuity,1);
1592 extrap_mode[0] = extrap_mode[1] = Cdeg;
1593 TColStd_Array1OfReal Result(1, Cdim * (derivative_request+1)) ;
1595 TColStd_Array1OfReal& tgte = Tgte->ChangeArray1();
1596 TColStd_Array1OfReal& point = Point->ChangeArray1();
1597 TColStd_Array1OfReal& lamb = lambda->ChangeArray1();
1599 Standard_Real * Radr = (Standard_Real *) &Result(1) ;
1601 BSplCLib::Eval(Tbord,periodic_flag,derivative_request,extrap_mode[0],
1602 Cdeg,FKnots->Array1(),Cdim,*Padr,*Radr);
1604 for (ii=1;ii<=Cdim;ii++) {
1605 point(ii) = Result(ii);
1606 tgte(ii) = Result(ii+Cdim);
1609 // calcul de la contrainte a atteindre
1613 Standard_Real NTgte, val, Tgtol = 1.e-12, OldN = 0.0;
1615 for (ii=gap;ii<=Cdim;ii+=gap) {
1618 for (ii=gap;ii<=Cdim;ii+=gap) {
1619 CurT.SetCoord(tgte(ii-3),tgte(ii-2), tgte(ii-1));
1620 NTgte=CurT.Magnitude();
1623 // Attentions aux Cas ou le segment donne par les poles
1624 // est oppose au sens de la derive
1625 // Exemple: Certaine portions de tore.
1626 if ( (OldN > Tgtol) && (CurT.Angle(OldT) > 2)) {
1627 Ok = Standard_False;
1630 lamb(ii-1) = lamb(ii-2) = lamb(ii-3) = val;
1632 lambmin = Min(lambmin, val);
1635 lamb(ii-1) = lamb(ii-2) = lamb(ii-3) = 0.;
1643 for (ii=gap;ii<=Cdim;ii+=gap) {
1644 CurT.SetCoord(tgte(ii-2),tgte(ii-1), tgte(ii));
1645 NTgte=CurT.Magnitude();
1648 // Attentions aux Cas ou le segment donne par les poles
1649 // est oppose au sens de la derive
1650 // Exemple: Certaine portion de tore.
1651 if ( (OldN > Tgtol) && (CurT.Angle(OldT) > 2)) {
1652 Ok = Standard_False;
1654 lamb(ii) = lamb(ii-1) = lamb(ii-2) = val;
1655 lambmin = Min(lambmin, val);
1658 lamb(ii) =lamb(ii-1) = lamb(ii-2) = 0.;
1664 if (!Ok && Kount<2) {
1665 // On augmente le degre de l'iso bord afin de rapprocher les poles de la surface
1667 if (InU) BS->IncreaseDegree(BS->UDegree(), BS->VDegree()+2);
1668 else BS->IncreaseDegree(BS->UDegree()+2, BS->VDegree());
1673 TColStd_Array1OfReal ConstraintPoint(1,Cdim);
1675 for (ii=1;ii<=Cdim;ii++) {
1676 ConstraintPoint(ii) = Point->Value(ii) + lambda->Value(ii)*Tgte->Value(ii);
1680 for (ii=1;ii<=Cdim;ii++) {
1681 ConstraintPoint(ii) = Point->Value(ii) - lambda->Value(ii)*Tgte->Value(ii);
1685 // cas particulier du rationnel
1687 for (ipole=1;ipole<=Psize;ipole+=gap) {
1688 Poles->ChangeValue(ipole) *= Poles->Value(ipole+3);
1689 Poles->ChangeValue(ipole+1) *= Poles->Value(ipole+3);
1690 Poles->ChangeValue(ipole+2) *= Poles->Value(ipole+3);
1692 for (ii=1;ii<=Cdim;ii+=gap) {
1693 ConstraintPoint(ii) *= ConstraintPoint(ii+3);
1694 ConstraintPoint(ii+1) *= ConstraintPoint(ii+3);
1695 ConstraintPoint(ii+2) *= ConstraintPoint(ii+3);
1699 // tableaux necessaires pour l'extension
1700 Standard_Integer Ksize2 = Ksize+Cdeg, NbPoles, NbKnots = 0;
1701 TColStd_Array1OfReal FK(1, Ksize2) ;
1702 Standard_Real * FKRadr = &FK(1);
1704 Standard_Integer Psize2 = Psize+Cdeg*Cdim;
1705 TColStd_Array1OfReal PRes(1, Psize2) ;
1706 Standard_Real * PRadr = &PRes(1);
1708 Standard_Boolean ExtOk = Standard_False;
1709 Handle(TColgp_HArray2OfPnt) NewPoles;
1710 Handle(TColStd_HArray2OfReal) NewWeights;
1713 for (Kount=1; Kount<=5 && !ExtOk; Kount++) {
1715 BSplCLib::TangExtendToConstraint(FKnots->Array1(),
1718 ConstraintPoint, Cont, After,
1719 NbPoles, NbKnots,*FKRadr, *PRadr);
1721 // recopie des poles du resultat sous forme de points 3D et de poids
1722 Standard_Integer NU, NV, indice ;
1725 NV = BS->NbVPoles();
1728 NU = BS->NbUPoles();
1732 NewPoles = new (TColgp_HArray2OfPnt)(1,NU,1,NV);
1733 TColgp_Array2OfPnt& NewP = NewPoles->ChangeArray2();
1734 NewWeights = new (TColStd_HArray2OfReal) (1,NU,1,NV);
1735 TColStd_Array2OfReal& NewW = NewWeights->ChangeArray2();
1737 if (!rational) NewW.Init(1.);
1738 NullWeight= Standard_False;
1741 for (ii=1; ii<=NU && !NullWeight; ii++) {
1742 for (jj=1; jj<=NV && !NullWeight; jj++) {
1743 indice = 1+(ii-1)*Cdim+(jj-1)*gap;
1744 NewP(ii,jj).SetCoord(1,PRes(indice));
1745 NewP(ii,jj).SetCoord(2,PRes(indice+1));
1746 NewP(ii,jj).SetCoord(3,PRes(indice+2));
1748 ww = PRes(indice+3);
1749 if (Abs(ww - 1.0) < EpsW)
1752 NullWeight = Standard_True;
1756 NewP(ii,jj).ChangeCoord() /= ww;
1763 for (jj=1; jj<=NV && !NullWeight; jj++) {
1764 for (ii=1; ii<=NU && !NullWeight; ii++) {
1765 indice = 1+(ii-1)*gap+(jj-1)*Cdim;
1766 NewP(ii,jj).SetCoord(1,PRes(indice));
1767 NewP(ii,jj).SetCoord(2,PRes(indice+1));
1768 NewP(ii,jj).SetCoord(3,PRes(indice+2));
1770 ww = PRes(indice+3);
1771 if (Abs(ww - 1.0) < EpsW)
1774 NullWeight = Standard_True;
1778 NewP(ii,jj).ChangeCoord() /= ww;
1787 std::cout << "Echec de l'Extension rationnelle" << std::endl;
1790 NullWeight = Standard_False;
1793 ExtOk = Standard_True;
1798 // recopie des noeuds plats sous forme de noeuds avec leurs multiplicites
1799 // calcul des degres du resultat
1800 Standard_Integer Usize = BS->NbUKnots(), Vsize = BS->NbVKnots(), UDeg, VDeg;
1805 TColStd_Array1OfReal UKnots(1,Usize);
1806 TColStd_Array1OfReal VKnots(1,Vsize);
1807 TColStd_Array1OfInteger UMults(1,Usize);
1808 TColStd_Array1OfInteger VMults(1,Vsize);
1809 TColStd_Array1OfReal FKRes(1, NbKnots);
1811 for (ii=1; ii<=NbKnots; ii++)
1815 BSplCLib::Knots(FKRes, UKnots, UMults);
1817 UMults(Usize) = UDeg+1; // Petite verrue utile quand la continuite
1820 BS->VMultiplicities(VMults);
1821 VDeg = BS->VDegree();
1824 BSplCLib::Knots(FKRes, VKnots, VMults);
1826 VMults(Vsize) = VDeg+1;
1828 BS->UMultiplicities(UMults);
1829 UDeg = BS->UDegree();
1832 // construction de la surface BSpline resultat
1833 Handle(Geom_BSplineSurface) Res =
1834 new (Geom_BSplineSurface) (NewPoles->Array2(),
1835 NewWeights->Array2(),
1844 //=======================================================================
1845 //function : Inertia
1847 //=======================================================================
1848 void GeomLib::Inertia(const TColgp_Array1OfPnt& Points,
1852 Standard_Real& Xgap,
1853 Standard_Real& Ygap,
1854 Standard_Real& Zgap)
1856 gp_XYZ GB(0., 0., 0.), Diff;
1859 Standard_Integer i,nb=Points.Length();
1860 GB.SetCoord(0.,0.,0.);
1861 for (i=1; i<=nb; i++)
1862 GB += Points(i).XYZ();
1866 math_Matrix M (1, 3, 1, 3);
1868 for (i=1; i<=nb; i++) {
1869 Diff.SetLinearForm(-1, Points(i).XYZ(), GB);
1870 M(1,1) += Diff.X() * Diff.X();
1871 M(2,2) += Diff.Y() * Diff.Y();
1872 M(3,3) += Diff.Z() * Diff.Z();
1873 M(1,2) += Diff.X() * Diff.Y();
1874 M(1,3) += Diff.X() * Diff.Z();
1875 M(2,3) += Diff.Y() * Diff.Z();
1887 std::cout << "Erreur dans Jacobbi" << std::endl;
1892 Standard_Real n1,n2,n3;
1898 Standard_Real r1 = Min(Min(n1,n2),n3), r2;
1899 Standard_Integer m1, m2, m3;
1939 math_Vector V2(1,3),V3(1,3);
1944 XDir.SetCoord(V3(1),V3(2),V3(3));
1945 YDir.SetCoord(V2(1),V2(2),V2(3));
1947 Zgap = sqrt(Abs(J.Value(m1)));
1948 Ygap = sqrt(Abs(J.Value(m2)));
1949 Xgap = sqrt(Abs(J.Value(m3)));
1951 //=======================================================================
1952 //function : AxeOfInertia
1954 //=======================================================================
1955 void GeomLib::AxeOfInertia(const TColgp_Array1OfPnt& Points,
1957 Standard_Boolean& IsSingular,
1958 const Standard_Real Tol)
1962 Standard_Real gx, gy, gz;
1964 GeomLib::Inertia(Points, Bary, OX, OY, gx, gy, gz);
1966 if (gy*Points.Length()<=Tol) {
1967 gp_Ax2 axe (Bary, OX);
1968 OY = axe.XDirection();
1969 IsSingular = Standard_True;
1972 IsSingular = Standard_False;
1976 gp_Ax2 TheAxe(Bary, OZ, OX);
1980 //=======================================================================
1981 //function : CanBeTreated
1982 //purpose : indicates if the surface can be treated(if the conditions are
1983 // filled) and need to be treated(if the surface hasn't been yet
1984 // treated or if the surface is rationnal and non periodic)
1985 //=======================================================================
1987 static Standard_Boolean CanBeTreated(Handle(Geom_BSplineSurface)& BSurf)
1989 {Standard_Integer i;
1990 Standard_Real lambda; //proportionnality coefficient
1991 Standard_Boolean AlreadyTreated=Standard_True;
1993 if (!BSurf->IsURational()||(BSurf->IsUPeriodic()))
1994 return Standard_False;
1996 lambda=(BSurf->Weight(1,1)/BSurf->Weight(BSurf->NbUPoles(),1));
1997 for (i=1;i<=BSurf->NbVPoles();i++) //test of the proportionnality of the denominator on the boundaries
1998 if ((BSurf->Weight(1,i)/(lambda*BSurf->Weight(BSurf->NbUPoles(),i))<(1-Precision::Confusion()))||
1999 (BSurf->Weight(1,i)/(lambda*BSurf->Weight(BSurf->NbUPoles(),i))>(1+Precision::Confusion())))
2000 return Standard_False;
2002 while ((AlreadyTreated) && (i<=BSurf->NbVPoles())){ //tests if the surface has already been treated
2003 if (((BSurf->Weight(1,i)/(BSurf->Weight(2,i)))<(1-Precision::Confusion()))||
2004 ((BSurf->Weight(1,i)/(BSurf->Weight(2,i)))>(1+Precision::Confusion()))||
2005 ((BSurf->Weight(BSurf->NbUPoles()-1,i)/(BSurf->Weight(BSurf->NbUPoles(),i)))<(1-Precision::Confusion()))||
2006 ((BSurf->Weight(BSurf->NbUPoles()-1,i)/(BSurf->Weight(BSurf->NbUPoles(),i)))>(1+Precision::Confusion())))
2007 AlreadyTreated=Standard_False;
2011 return Standard_False;
2013 return Standard_True;
2016 //=======================================================================
2017 //class : law_evaluator
2018 //purpose : usefull to estimate the value of a function of 2 variables
2019 //=======================================================================
2021 class law_evaluator : public BSplSLib_EvaluatorFunction
2026 law_evaluator (const GeomLib_DenominatorMultiplierPtr theDenominatorPtr)
2027 : myDenominator (theDenominatorPtr) {}
2029 virtual void Evaluate (const Standard_Integer theDerivativeRequest,
2030 const Standard_Real theUParameter,
2031 const Standard_Real theVParameter,
2032 Standard_Real& theResult,
2033 Standard_Integer& theErrorCode) const
2035 if ((myDenominator != NULL) && (theDerivativeRequest == 0))
2037 theResult = myDenominator->Value (theUParameter, theVParameter);
2048 GeomLib_DenominatorMultiplierPtr myDenominator;
2052 //=======================================================================
2053 //function : CheckIfKnotExists
2054 //purpose : true if the knot already exists in the knot sequence
2055 //=======================================================================
2057 static Standard_Boolean CheckIfKnotExists(const TColStd_Array1OfReal& surface_knots,
2058 const Standard_Real knot)
2060 {Standard_Integer i;
2061 for (i=1;i<=surface_knots.Length();i++)
2062 if ((surface_knots(i)-Precision::Confusion()<=knot)&&(surface_knots(i)+Precision::Confusion()>=knot))
2063 return Standard_True;
2064 return Standard_False;
2067 //=======================================================================
2068 //function : AddAKnot
2069 //purpose : add a knot and its multiplicity to the knot sequence. This knot
2070 // will be C2 and the degree is increased of deltasurface_degree
2071 //=======================================================================
2073 static void AddAKnot(const TColStd_Array1OfReal& knots,
2074 const TColStd_Array1OfInteger& mults,
2075 const Standard_Real knotinserted,
2076 const Standard_Integer deltasurface_degree,
2077 const Standard_Integer finalsurfacedegree,
2078 Handle(TColStd_HArray1OfReal) & newknots,
2079 Handle(TColStd_HArray1OfInteger) & newmults)
2081 {Standard_Integer i;
2083 newknots=new TColStd_HArray1OfReal(1,knots.Length()+1);
2084 newmults=new TColStd_HArray1OfInteger(1,knots.Length()+1);
2086 while (knots(i)<knotinserted){
2087 newknots->SetValue(i,knots(i));
2088 newmults->SetValue(i,mults(i)+deltasurface_degree);
2091 newknots->SetValue(i,knotinserted); //insertion of the new knot
2092 newmults->SetValue(i,finalsurfacedegree-2);
2094 while (i<=newknots->Length()){
2095 newknots->SetValue(i,knots(i-1));
2096 newmults->SetValue(i,mults(i-1)+deltasurface_degree);
2101 //=======================================================================
2103 //purpose : give the new flat knots(u or v) of the surface
2104 //=======================================================================
2106 static void BuildFlatKnot(const TColStd_Array1OfReal& surface_knots,
2107 const TColStd_Array1OfInteger& surface_mults,
2108 const Standard_Integer deltasurface_degree,
2109 const Standard_Integer finalsurface_degree,
2110 const Standard_Real knotmin,
2111 const Standard_Real knotmax,
2112 Handle(TColStd_HArray1OfReal)& ResultKnots,
2113 Handle(TColStd_HArray1OfInteger)& ResultMults)
2118 if (CheckIfKnotExists(surface_knots,knotmin) &&
2119 CheckIfKnotExists(surface_knots,knotmax)){
2120 ResultKnots=new TColStd_HArray1OfReal(1,surface_knots.Length());
2121 ResultMults=new TColStd_HArray1OfInteger(1,surface_knots.Length());
2122 for (i=1;i<=surface_knots.Length();i++){
2123 ResultKnots->SetValue(i,surface_knots(i));
2124 ResultMults->SetValue(i,surface_mults(i)+deltasurface_degree);
2128 if ((CheckIfKnotExists(surface_knots,knotmin))&&(!CheckIfKnotExists(surface_knots,knotmax)))
2129 AddAKnot(surface_knots,surface_mults,knotmax,deltasurface_degree,finalsurface_degree,ResultKnots,ResultMults);
2131 if ((!CheckIfKnotExists(surface_knots,knotmin))&&(CheckIfKnotExists(surface_knots,knotmax)))
2132 AddAKnot(surface_knots,surface_mults,knotmin,deltasurface_degree,finalsurface_degree,ResultKnots,ResultMults);
2134 if ((!CheckIfKnotExists(surface_knots,knotmin))&&(!CheckIfKnotExists(surface_knots,knotmax))&&
2135 (knotmin==knotmax)){
2136 AddAKnot(surface_knots,surface_mults,knotmin,deltasurface_degree,finalsurface_degree,ResultKnots,ResultMults);
2139 Handle(TColStd_HArray1OfReal) IntermedKnots;
2140 Handle(TColStd_HArray1OfInteger) IntermedMults;
2141 AddAKnot(surface_knots,surface_mults,knotmin,deltasurface_degree,finalsurface_degree,IntermedKnots,IntermedMults);
2142 AddAKnot(IntermedKnots->ChangeArray1(),IntermedMults->ChangeArray1(),knotmax,0,finalsurface_degree,ResultKnots,ResultMults);
2149 //=======================================================================
2150 //function : FunctionMultiply
2151 //purpose : multiply the surface BSurf by a(u,v) (law_evaluator) on its
2152 // numerator and denominator
2153 //=======================================================================
2155 static void FunctionMultiply(Handle(Geom_BSplineSurface)& BSurf,
2156 const Standard_Real knotmin,
2157 const Standard_Real knotmax)
2159 {TColStd_Array1OfReal surface_u_knots(1,BSurf->NbUKnots()) ;
2160 TColStd_Array1OfInteger surface_u_mults(1,BSurf->NbUKnots()) ;
2161 TColStd_Array1OfReal surface_v_knots(1,BSurf->NbVKnots()) ;
2162 TColStd_Array1OfInteger surface_v_mults(1,BSurf->NbVKnots()) ;
2163 TColgp_Array2OfPnt surface_poles(1,BSurf->NbUPoles(),
2164 1,BSurf->NbVPoles()) ;
2165 TColStd_Array2OfReal surface_weights(1,BSurf->NbUPoles(),
2166 1,BSurf->NbVPoles()) ;
2167 Standard_Integer i,j,k,status,new_num_u_poles,new_num_v_poles,length=0;
2168 Handle(TColStd_HArray1OfReal) newuknots,newvknots;
2169 Handle(TColStd_HArray1OfInteger) newumults,newvmults;
2171 BSurf->UKnots(surface_u_knots) ;
2172 BSurf->UMultiplicities(surface_u_mults) ;
2173 BSurf->VKnots(surface_v_knots) ;
2174 BSurf->VMultiplicities(surface_v_mults) ;
2175 BSurf->Poles(surface_poles) ;
2176 BSurf->Weights(surface_weights) ;
2178 TColStd_Array1OfReal Knots(1,2);
2179 TColStd_Array1OfInteger Mults(1,2);
2180 Handle(TColStd_HArray1OfReal) NewKnots;
2181 Handle(TColStd_HArray1OfInteger) NewMults;
2187 BuildFlatKnot(Knots,Mults,0,3,knotmin,knotmax,NewKnots,NewMults);
2189 for (i=1;i<=NewMults->Length();i++)
2190 length+=NewMults->Value(i);
2191 TColStd_Array1OfReal FlatKnots(1,length);
2192 BSplCLib::KnotSequence(NewKnots->ChangeArray1(),NewMults->ChangeArray1(),FlatKnots);
2194 GeomLib_DenominatorMultiplier aDenominator (BSurf, FlatKnots);
2196 BuildFlatKnot(surface_u_knots,
2204 BuildFlatKnot(surface_v_knots,
2207 2*(BSurf->VDegree()),
2213 for (i=1;i<=newumults->Length();i++)
2214 length+=newumults->Value(i);
2215 new_num_u_poles=(length-BSurf->UDegree()-3-1);
2216 TColStd_Array1OfReal newuflatknots(1,length);
2218 for (i=1;i<=newvmults->Length();i++)
2219 length+=newvmults->Value(i);
2220 new_num_v_poles=(length-2*BSurf->VDegree()-1);
2221 TColStd_Array1OfReal newvflatknots(1,length);
2223 TColgp_Array2OfPnt NewNumerator(1,new_num_u_poles,1,new_num_v_poles);
2224 TColStd_Array2OfReal NewDenominator(1,new_num_u_poles,1,new_num_v_poles);
2226 BSplCLib::KnotSequence(newuknots->ChangeArray1(),newumults->ChangeArray1(),newuflatknots);
2227 BSplCLib::KnotSequence(newvknots->ChangeArray1(),newvmults->ChangeArray1(),newvflatknots);
2229 law_evaluator ev (&aDenominator);
2230 // BSplSLib::FunctionMultiply(law_evaluator, //multiplication
2231 BSplSLib::FunctionMultiply(ev, //multiplication
2243 2*(BSurf->VDegree()),
2248 throw Standard_ConstructionError("GeomLib Multiplication Error") ;
2249 for (i = 1 ; i <= new_num_u_poles ; i++) {
2250 for (j = 1 ; j <= new_num_v_poles ; j++) {
2251 for (k = 1 ; k <= 3 ; k++) {
2252 NewNumerator(i,j).SetCoord(k,NewNumerator(i,j).Coord(k)/NewDenominator(i,j)) ;
2256 BSurf= new Geom_BSplineSurface(NewNumerator,
2258 newuknots->ChangeArray1(),
2259 newvknots->ChangeArray1(),
2260 newumults->ChangeArray1(),
2261 newvmults->ChangeArray1(),
2263 2*(BSurf->VDegree()) );
2266 //=======================================================================
2267 //function : CancelDenominatorDerivative1D
2268 //purpose : cancel the denominator derivative in one direction
2269 //=======================================================================
2271 static void CancelDenominatorDerivative1D(Handle(Geom_BSplineSurface) & BSurf)
2273 {Standard_Integer i,j;
2274 Standard_Real uknotmin=1.0,uknotmax=0.0,
2278 TColStd_Array1OfReal BSurf_u_knots(1,BSurf->NbUKnots()) ;
2280 startu_value=BSurf->UKnot(1);
2281 endu_value=BSurf->UKnot(BSurf->NbUKnots());
2282 BSurf->UKnots(BSurf_u_knots) ;
2283 BSplCLib::Reparametrize(0.0,1.0,BSurf_u_knots);
2284 BSurf->SetUKnots(BSurf_u_knots); //reparametrisation of the surface
2285 Handle(Geom_BSplineCurve) BCurve;
2286 TColStd_Array1OfReal BCurveWeights(1,BSurf->NbUPoles());
2287 TColgp_Array1OfPnt BCurvePoles(1,BSurf->NbUPoles());
2288 TColStd_Array1OfReal BCurveKnots(1,BSurf->NbUKnots());
2289 TColStd_Array1OfInteger BCurveMults(1,BSurf->NbUKnots());
2291 if (CanBeTreated(BSurf)){
2292 for (i=1;i<=BSurf->NbVPoles();i++){ //loop on each pole function
2294 for (j=1;j<=BSurf->NbUPoles();j++){
2295 BCurveWeights(j)=BSurf->Weight(j,i);
2296 BCurvePoles(j)=BSurf->Pole(j,i);
2298 BSurf->UKnots(BCurveKnots);
2299 BSurf->UMultiplicities(BCurveMults);
2300 BCurve = new Geom_BSplineCurve(BCurvePoles, //building of a pole function
2305 Hermit::Solutionbis(BCurve,x,y,Precision::Confusion(),Precision::Confusion());
2307 uknotmin=x; //uknotmin,uknotmax:extremal knots
2308 if ((x!=1.0)&&(x>uknotmax))
2310 if ((y!=0.0)&&(y<uknotmin))
2316 FunctionMultiply(BSurf,uknotmin,uknotmax); //multiplication
2318 BSurf->UKnots(BSurf_u_knots) ;
2319 BSplCLib::Reparametrize(startu_value,endu_value,BSurf_u_knots);
2320 BSurf->SetUKnots(BSurf_u_knots);
2324 //=======================================================================
2325 //function : CancelDenominatorDerivative
2327 //=======================================================================
2329 void GeomLib::CancelDenominatorDerivative(Handle(Geom_BSplineSurface) & BSurf,
2330 const Standard_Boolean udirection,
2331 const Standard_Boolean vdirection)
2333 {if (udirection && !vdirection)
2334 CancelDenominatorDerivative1D(BSurf);
2336 if (!udirection && vdirection) {
2337 BSurf->ExchangeUV();
2338 CancelDenominatorDerivative1D(BSurf);
2339 BSurf->ExchangeUV();
2342 if (udirection && vdirection){ //optimize the treatment
2343 if (BSurf->UDegree()<=BSurf->VDegree()){
2344 CancelDenominatorDerivative1D(BSurf);
2345 BSurf->ExchangeUV();
2346 CancelDenominatorDerivative1D(BSurf);
2347 BSurf->ExchangeUV();
2350 BSurf->ExchangeUV();
2351 CancelDenominatorDerivative1D(BSurf);
2352 BSurf->ExchangeUV();
2353 CancelDenominatorDerivative1D(BSurf);
2360 //=======================================================================
2361 //function : NormEstim
2363 //=======================================================================
2365 Standard_Integer GeomLib::NormEstim(const Handle(Geom_Surface)& S,
2367 const Standard_Real Tol, gp_Dir& N)
2371 Standard_Real aTol2 = Square(Tol);
2373 S->D1(UV.X(), UV.Y(), DummyPnt, DU, DV);
2375 Standard_Real MDU = DU.SquareMagnitude(), MDV = DV.SquareMagnitude();
2377 if(MDU >= aTol2 && MDV >= aTol2) {
2378 gp_Vec Norm = DU^DV;
2379 Standard_Real Magn = Norm.SquareMagnitude();
2380 if(Magn < aTol2) return 3;
2382 //Magn = sqrt(Magn);
2383 N.SetXYZ(Norm.XYZ());
2388 gp_Vec D2U, D2V, D2UV;
2389 Standard_Boolean isDone;
2390 CSLib_NormalStatus aStatus;
2393 S->D2(UV.X(), UV.Y(), DummyPnt, DU, DV, D2U, D2V, D2UV);
2394 CSLib::Normal(DU, DV, D2U, D2V, D2UV, Tol, isDone, aStatus, aNormal);
2397 Standard_Real Umin, Umax, Vmin, Vmax;
2398 Standard_Real step = 1.0e-5;
2399 Standard_Real eps = 1.0e-16;
2400 Standard_Real sign = -1.0;
2402 S->Bounds(Umin, Umax, Vmin, Vmax);
2404 // check for cone apex singularity point
2405 if ((UV.Y() > Vmin + step) && (UV.Y() < Vmax - step))
2407 gp_Dir aNormal1, aNormal2;
2408 Standard_Real aConeSingularityAngleEps = 1.0e-4;
2409 S->D1(UV.X(), UV.Y() - sign * step, DummyPnt, DU, DV);
2410 if ((DU.XYZ().SquareModulus() > eps) && (DV.XYZ().SquareModulus() > eps)) {
2412 S->D1(UV.X(), UV.Y() + sign * step, DummyPnt, DU, DV);
2413 if ((DU.XYZ().SquareModulus() > eps) && (DV.XYZ().SquareModulus() > eps)) {
2415 if (aNormal1.IsOpposite(aNormal2, aConeSingularityAngleEps))
2422 if(MDU < aTol2 && MDV >= aTol2) {
2423 if ((Vmax - UV.Y()) > (UV.Y() - Vmin))
2425 S->D1(UV.X(), UV.Y() + sign * step, DummyPnt, DU, DV);
2426 gp_Vec Norm = DU^DV;
2427 if (Norm.SquareMagnitude() < eps) {
2428 Standard_Real sign1 = -1.0;
2429 if ((Umax - UV.X()) > (UV.X() - Umin))
2431 S->D1(UV.X() + sign1 * step, UV.Y() + sign * step, DummyPnt, DU, DV);
2434 if ((Norm.SquareMagnitude() >= eps) && (Norm.Dot(aNormal) < 0.0))
2439 if(MDV < aTol2 && MDU >= aTol2) {
2440 if ((Umax - UV.X()) > (UV.X() - Umin))
2442 S->D1(UV.X() + sign * step, UV.Y(), DummyPnt, DU, DV);
2443 gp_Vec Norm = DU^DV;
2444 if (Norm.SquareMagnitude() < eps) {
2445 Standard_Real sign1 = -1.0;
2446 if ((Vmax - UV.Y()) > (UV.Y() - Vmin))
2448 S->D1(UV.X() + sign * step, UV.Y() + sign1 * step, DummyPnt, DU, DV);
2451 if ((Norm.SquareMagnitude() >= eps) && (Norm.Dot(aNormal) < 0.0))
2456 if ((aStatus == CSLib_D1NuIsNull) || (aStatus == CSLib_D1NvIsNull) ||
2457 (aStatus == CSLib_D1NuIsParallelD1Nv)) {
2458 N.SetXYZ(aNormal.XYZ());
2462 if (aStatus == CSLib_InfinityOfSolutions)
2465 // computation is impossible
2468 if (aStatus == CSLib_D1NIsNull) {
2477 //=======================================================================
2478 //function : IsClosed
2480 //=======================================================================
2481 void GeomLib::IsClosed (const Handle(Geom_Surface)& S,
2482 const Standard_Real Tol,
2483 Standard_Boolean& isUClosed, Standard_Boolean& isVClosed)
2485 isUClosed = Standard_False;
2486 isVClosed = Standard_False;
2488 GeomAdaptor_Surface aGAS(S);
2489 GeomAbs_SurfaceType aSType = aGAS.GetType();
2491 Standard_Real u1, u2, v1, v2;
2492 u1 = aGAS.FirstUParameter();
2493 u2 = aGAS.LastUParameter();
2494 v1 = aGAS.FirstVParameter();
2495 v2 = aGAS.LastVParameter();
2497 Standard_Real Tol2 = Tol * Tol;
2504 case GeomAbs_SurfaceOfExtrusion:
2506 if (Precision::IsInfinite(u1) || Precision::IsInfinite(u2)) {
2511 Standard_FALLTHROUGH
2512 case GeomAbs_Cylinder:
2514 if(Precision::IsInfinite(v1))
2516 gp_Pnt p1 = aGAS.Value(u1, v1);
2517 gp_Pnt p2 = aGAS.Value(u2, v1);
2518 isUClosed = p1.SquareDistance(p2) <= Tol2;
2523 //find v with maximal distance from axis
2524 if(!(Precision::IsInfinite(v1) || Precision::IsInfinite(v2)))
2526 gp_Cone aCone = aGAS.Cone();
2527 gp_Pnt anApex = aCone.Apex();
2528 gp_Pnt P1 = aGAS.Value(u1, v1);
2529 gp_Pnt P2 = aGAS.Value(u1, v2);
2530 if(P2.SquareDistance(anApex) > P1.SquareDistance(anApex))
2539 gp_Pnt p1 = aGAS.Value(u1, v1);
2540 gp_Pnt p2 = aGAS.Value(u2, v1);
2541 isUClosed = p1.SquareDistance(p2) <= Tol2;
2544 case GeomAbs_Sphere:
2546 //find v with maximal distance from axis
2558 gp_Pnt p1 = aGAS.Value(u1, v1);
2559 gp_Pnt p2 = aGAS.Value(u2, v1);
2560 isUClosed = p1.SquareDistance(p2) <= Tol2;
2565 Standard_Real ures = aGAS.UResolution(Tol);
2566 Standard_Real vres = aGAS.VResolution(Tol);
2568 isUClosed = (u2 - u1) >= aGAS.UPeriod() - ures;
2569 isVClosed = (v2 - v1) >= aGAS.VPeriod() - vres;
2572 case GeomAbs_BSplineSurface:
2574 Handle(Geom_BSplineSurface) aBSpl = aGAS.BSpline();
2575 isUClosed = GeomLib::IsBSplUClosed(aBSpl, u1, u2, Tol);
2576 isVClosed = GeomLib::IsBSplVClosed(aBSpl, v1, v2, Tol);
2579 case GeomAbs_BezierSurface:
2581 Handle(Geom_BezierSurface) aBz = aGAS.Bezier();
2582 isUClosed = GeomLib::IsBzUClosed(aBz, u1, u2, Tol);
2583 isVClosed = GeomLib::IsBzVClosed(aBz, v1, v2, Tol);
2586 case GeomAbs_SurfaceOfRevolution:
2587 case GeomAbs_OffsetSurface:
2588 case GeomAbs_OtherSurface:
2590 Standard_Integer nbp = 23;
2591 if(Precision::IsInfinite(v1))
2595 if(Precision::IsInfinite(v2))
2600 if(aSType == GeomAbs_OffsetSurface ||
2601 aSType == GeomAbs_OtherSurface)
2603 if(Precision::IsInfinite(u1))
2607 if(Precision::IsInfinite(u2))
2612 isUClosed = Standard_True;
2613 Standard_Real dt = (v2 - v1) / (nbp - 1);
2614 Standard_Real res = Max(aGAS.UResolution(Tol), Precision::PConfusion());
2617 nbp = RealToInt((v2 - v1) /(2.*res)) + 1;
2619 dt = (v2 - v1) / (nbp - 1);
2623 for(i = 0; i < nbp; ++i)
2625 t = (i == nbp-1 ? v2 : v1 + i * dt);
2626 gp_Pnt p1 = aGAS.Value(u1, t);
2627 gp_Pnt p2 = aGAS.Value(u2, t);
2628 if(p1.SquareDistance(p2) > Tol2)
2630 isUClosed = Standard_False;
2636 isVClosed = Standard_True;
2637 dt = (u2 - u1) / (nbp - 1);
2638 res = Max(aGAS.VResolution(Tol), Precision::PConfusion());
2641 nbp = RealToInt((u2 - u1) /(2.*res)) + 1;
2643 dt = (u2 - u1) / (nbp - 1);
2645 for(i = 0; i < nbp; ++i)
2647 t = (i == nbp-1 ? u2 : u1 + i * dt);
2648 gp_Pnt p1 = aGAS.Value(t, v1);
2649 gp_Pnt p2 = aGAS.Value(t, v2);
2650 if(p1.SquareDistance(p2) > Tol2)
2652 isVClosed = Standard_False;
2665 //=======================================================================
2666 //function : IsBSplUClosed
2668 //=======================================================================
2669 Standard_Boolean GeomLib::IsBSplUClosed (const Handle(Geom_BSplineSurface)& S,
2670 const Standard_Real U1,
2671 const Standard_Real U2,
2672 const Standard_Real Tol)
2674 Handle(Geom_Curve) aCUF = S->UIso( U1 );
2675 Handle(Geom_Curve) aCUL = S->UIso( U2 );
2676 if(aCUF.IsNull() || aCUL.IsNull())
2677 return Standard_False;
2678 Standard_Real Tol2 = 2.*Tol;
2679 Handle(Geom_BSplineCurve) aBsF = Handle(Geom_BSplineCurve)::DownCast(aCUF);
2680 Handle(Geom_BSplineCurve) aBsL = Handle(Geom_BSplineCurve)::DownCast(aCUL);
2681 const TColgp_Array1OfPnt& aPF = aBsF->Poles();
2682 const TColgp_Array1OfPnt& aPL = aBsL->Poles();
2683 const TColStd_Array1OfReal* WF = aBsF->Weights();
2684 const TColStd_Array1OfReal* WL = aBsL->Weights();
2685 return CompareWeightPoles(aPF, WF, aPL, WL, Tol2);
2688 //=======================================================================
2689 //function : IsBSplVClosed
2691 //=======================================================================
2692 Standard_Boolean GeomLib::IsBSplVClosed (const Handle(Geom_BSplineSurface)& S,
2693 const Standard_Real V1,
2694 const Standard_Real V2,
2695 const Standard_Real Tol)
2697 Handle(Geom_Curve) aCVF = S->VIso( V1 );
2698 Handle(Geom_Curve) aCVL = S->VIso( V2 );
2699 if(aCVF.IsNull() || aCVL.IsNull())
2700 return Standard_False;
2701 Standard_Real Tol2 = 2.*Tol;
2702 Handle(Geom_BSplineCurve) aBsF = Handle(Geom_BSplineCurve)::DownCast(aCVF);
2703 Handle(Geom_BSplineCurve) aBsL = Handle(Geom_BSplineCurve)::DownCast(aCVL);
2704 const TColgp_Array1OfPnt& aPF = aBsF->Poles();
2705 const TColgp_Array1OfPnt& aPL = aBsL->Poles();
2706 const TColStd_Array1OfReal* WF = aBsF->Weights();
2707 const TColStd_Array1OfReal* WL = aBsL->Weights();
2708 return CompareWeightPoles(aPF, WF, aPL, WL, Tol2);
2710 //=======================================================================
2711 //function : IsBzUClosed
2713 //=======================================================================
2714 Standard_Boolean GeomLib::IsBzUClosed (const Handle(Geom_BezierSurface)& S,
2715 const Standard_Real U1,
2716 const Standard_Real U2,
2717 const Standard_Real Tol)
2719 Handle(Geom_Curve) aCUF = S->UIso( U1 );
2720 Handle(Geom_Curve) aCUL = S->UIso( U2 );
2721 if(aCUF.IsNull() || aCUL.IsNull())
2722 return Standard_False;
2723 Standard_Real Tol2 = 2.*Tol;
2724 Handle(Geom_BezierCurve) aBzF = Handle(Geom_BezierCurve)::DownCast(aCUF);
2725 Handle(Geom_BezierCurve) aBzL = Handle(Geom_BezierCurve)::DownCast(aCUL);
2726 const TColgp_Array1OfPnt& aPF = aBzF->Poles();
2727 const TColgp_Array1OfPnt& aPL = aBzL->Poles();
2729 return CompareWeightPoles(aPF, 0, aPL, 0, Tol2);
2732 //=======================================================================
2733 //function : IsBzVClosed
2735 //=======================================================================
2736 Standard_Boolean GeomLib::IsBzVClosed (const Handle(Geom_BezierSurface)& S,
2737 const Standard_Real V1,
2738 const Standard_Real V2,
2739 const Standard_Real Tol)
2741 Handle(Geom_Curve) aCVF = S->VIso( V1 );
2742 Handle(Geom_Curve) aCVL = S->VIso( V2 );
2743 if(aCVF.IsNull() || aCVL.IsNull())
2744 return Standard_False;
2745 Standard_Real Tol2 = 2.*Tol;
2746 Handle(Geom_BezierCurve) aBzF = Handle(Geom_BezierCurve)::DownCast(aCVF);
2747 Handle(Geom_BezierCurve) aBzL = Handle(Geom_BezierCurve)::DownCast(aCVL);
2748 const TColgp_Array1OfPnt& aPF = aBzF->Poles();
2749 const TColgp_Array1OfPnt& aPL = aBzL->Poles();
2751 return CompareWeightPoles(aPF, 0, aPL, 0, Tol2);
2754 //=======================================================================
2755 //function : CompareWeightPoles
2756 //purpose : Checks if thePoles1(i)*theW1(i) is equal to thePoles2(i)*theW2(i)
2757 // with tolerance theTol.
2758 // It is necessary for not rational B-splines and Bezier curves
2759 // to set theW1 and theW2 adresses to zero.
2760 //=======================================================================
2761 static Standard_Boolean CompareWeightPoles(const TColgp_Array1OfPnt& thePoles1,
2762 const TColStd_Array1OfReal* const theW1,
2763 const TColgp_Array1OfPnt& thePoles2,
2764 const TColStd_Array1OfReal* const theW2,
2765 const Standard_Real theTol)
2767 if(thePoles1.Length() != thePoles2.Length())
2769 return Standard_False;
2772 Standard_Integer i = 1;
2773 for( i = 1 ; i <= thePoles1.Length(); i++ )
2775 const Standard_Real aW1 = (theW1 == 0) ? 1.0 : theW1->Value(i);
2776 const Standard_Real aW2 = (theW2 == 0) ? 1.0 : theW2->Value(i);
2778 gp_XYZ aPole1 = thePoles1.Value(i).XYZ() * aW1;
2779 gp_XYZ aPole2 = thePoles2.Value(i).XYZ() * aW2;
2780 if(!aPole1.IsEqual(aPole2, theTol))
2781 return Standard_False;
2784 return Standard_True;