1 // File: GeomFill_CircularBlendFunc.cxx
2 // Created: Fri Jul 11 15:54:00 1997
3 // Author: Philippe MANGIN
7 #include <GeomFill_CircularBlendFunc.ixx>
8 #include <GeomFill.hxx>
10 #include <GCPnts_QuasiUniformDeflection.hxx>
11 #include <Precision.hxx>
12 #include <Adaptor3d_HCurve.hxx>
14 #include <TColStd_SequenceOfReal.hxx>
15 #include <TColStd_Array1OfReal.hxx>
18 #include <GeomAdaptor_HCurve.hxx>
19 #include <Geom_BSplineCurve.hxx>
20 #include <DrawTrSurf.hxx>
21 static Standard_Integer NbSections = 0;
24 GeomAbs_Shape GeomFillNextShape(const GeomAbs_Shape S)
40 void GeomFillFusInt(const TColStd_Array1OfReal& I1,
41 const TColStd_Array1OfReal& I2,
42 TColStd_SequenceOfReal& Seq)
44 Standard_Integer ind1=1, ind2=1;
45 Standard_Real Epspar = Precision::PConfusion()*0.99;
46 // en suposant que le positionement fonctionne a PConfusion()/2
48 // Initialisations : les IND1 et IND2 pointent sur le 1er element
49 // de chacune des 2 tables a traiter.
52 //--- On remplit TABSOR en parcourant TABLE1 et TABLE2 simultanement ---
53 //------------------ en eliminant les occurrences multiples ------------
55 while ((ind1<=I1.Upper()) && (ind2<=I2.Upper())) {
58 if (Abs(v1-v2)<= Epspar) {
59 // Ici les elements de I1 et I2 conviennent .
60 Seq.Append((v1+v2)/2);
65 // Ici l' element de I1 convient.
70 // Ici l' element de TABLE2 convient.
76 if (ind1>I1.Upper()) {
77 //----- Ici I1 est epuise, on complete avec la fin de TABLE2 -------
79 for (; ind2<=I2.Upper(); ind2++) {
84 if (ind2>I2.Upper()) {
85 //----- Ici I2 est epuise, on complete avec la fin de I1 -------
87 for (; ind1<=I1.Upper(); ind1++) {
94 GeomFill_CircularBlendFunc::
95 GeomFill_CircularBlendFunc(const Handle(Adaptor3d_HCurve)& Path,
96 const Handle(Adaptor3d_HCurve)& Curve1,
97 const Handle(Adaptor3d_HCurve)& Curve2,
98 const Standard_Real Radius,
99 const Standard_Boolean Polynomial)
100 : maxang(RealFirst()),
104 // Recopie des arguments
105 myPath = myTPath = Path;
106 myCurve1 = myTCurve1 = Curve1;
107 myCurve2 = myTCurve2 = Curve2;
110 // Estimations numeriques
113 // Type de convertion ?
114 if (Polynomial) myTConv=Convert_Polynomial;
115 else if(maxang > 0.65*PI)
116 myTConv=Convert_QuasiAngular; //car c'est Continue
117 else myTConv = Convert_TgtThetaOver2;
118 //car c'est le plus performant
120 // On en deduit la structure
121 GeomFill::GetShape(maxang,
122 myNbPoles, myNbKnots,
126 void GeomFill_CircularBlendFunc::Discret()
128 Standard_Real TFirst = myPath->FirstParameter();
129 Standard_Real TLast = myPath->LastParameter(), T;
131 Standard_Real L1, L2, L;
132 Handle(Adaptor3d_HCurve) C;
133 gp_Pnt P1, P2, P3, Center;
136 P1 = myCurve1->Value(TFirst);
137 P2 = myCurve1->Value((TFirst+TLast)/2.);
138 P3 = myCurve1->Value(TLast);
139 L1 = P1.Distance(P2) + P2.Distance(P3);
141 P1 = myCurve2->Value(TFirst);
142 P2 = myCurve2->Value((TFirst+TLast)/2.);
143 P3 = myCurve2->Value(TLast);
144 L2 = P1.Distance(P2) + P2.Distance(P3);
155 Standard_Real Fleche = 1.e-2 * L;
156 Standard_Real Angle, Cosa, Percent;
157 GCPnts_QuasiUniformDeflection Samp;
158 Samp.Initialize(C->GetCurve(), Fleche);
159 myBary.SetCoord(0.,0.,0.);
163 Percent = ((Standard_Real)1)/(2*Samp.NbPoints());
165 for (ii=1; ii<=Samp.NbPoints(); ii++) {
166 T = Samp.Parameter(ii);
170 sprintf(name,"PNT_%d",NbSections++);
171 DrawTrSurf::Set(name, P1);
172 sprintf(name,"PNT_%d",NbSections++);
173 DrawTrSurf::Set(name, P2);*/
174 myPath->D0(T, Center);
175 ns1.SetXYZ( Center.XYZ() - P1.XYZ());
176 ns2.SetXYZ( Center.XYZ() - P2.XYZ());
180 if(Cosa > 1.) {Cosa = 1.;}
181 Angle = Abs(ACos(Cosa));
182 if (Angle>maxang) maxang = Angle;
183 if (Angle<minang) minang = Angle;
184 distmin = Min( distmin, P1.Distance(P2));
185 myBary.ChangeCoord() += (P1.XYZ()+P2.XYZ());
189 Standard_Real Delta = (TLast-TFirst)/20;
190 Percent = ((Standard_Real)1)/42;
191 for (ii=0, T=TFirst; ii<=20; ii++, T+=Delta) {
194 myPath->D0(T, Center);
196 ns1.SetXYZ( Center.XYZ() - P1.XYZ());
197 ns2.SetXYZ( Center.XYZ() - P2.XYZ());
201 if(Cosa > 1.) Cosa = 1.;
202 Angle = Abs(ACos(Cosa));
204 if (Angle>maxang) maxang = Angle;
205 if (Angle<minang) minang = Angle;
206 distmin = Min( distmin, P1.Distance(P2));
207 myBary.ChangeCoord() += (P1.XYZ()+P2.XYZ());
210 myBary.ChangeCoord() *= Percent;
212 // Faut il inverser la trajectoire ?
213 T = (TFirst + TLast)/2;
216 myPath->D1(T, Center, DCenter);
218 ns1.SetXYZ( Center.XYZ() - P1.XYZ());
219 ns2.SetXYZ( Center.XYZ() - P2.XYZ());
221 myreverse = (DCenter.Dot(ns1.Crossed(ns2)) < 0);
226 Standard_Boolean GeomFill_CircularBlendFunc::D0(const Standard_Real Param,
229 TColgp_Array1OfPnt& Poles,
230 TColgp_Array1OfPnt2d&,
231 TColStd_Array1OfReal& Weigths)
233 gp_Pnt P1, P2, Center;
234 gp_Vec ns1, ns2, nplan;
238 myTPath->D0(Param, Center);
239 myTCurve1->D0(Param, P1);
240 myTCurve2->D0(Param, P2);
241 ns1.SetXYZ( Center.XYZ() - P1.XYZ());
242 ns2.SetXYZ( Center.XYZ() - P2.XYZ());
243 if (!ns1.IsParallel(ns2,1.e-9)) nplan = ns1.Crossed(ns2);
245 myTPath->D1(Param, Center, nplan);
246 if (myreverse) nplan.Reverse();
254 temp.SetLinearForm(myRadius, ns1.XYZ(),
258 Center.ChangeCoord() = 0.5*temp;
261 GeomFill::GetCircle(myTConv,
268 // Handle(Geom_BSplineCurve) BS =
269 // new Geom_BSplineCurve(Poles,Weights,Knots,Mults,Degree);
270 // sprintf(name,"SECT_%d",NbSections++);
271 // DrawTrSurf::Set(name,BS);
273 return Standard_True;
277 Standard_Boolean GeomFill_CircularBlendFunc::D1(const Standard_Real Param,
278 // const Standard_Real First,
279 const Standard_Real ,
280 // const Standard_Real Last,
281 const Standard_Real ,
282 TColgp_Array1OfPnt& Poles,
283 TColgp_Array1OfVec& DPoles,
284 // TColgp_Array1OfPnt2d& Poles2d,
285 TColgp_Array1OfPnt2d& ,
286 // TColgp_Array1OfVec2d& DPoles2d,
287 TColgp_Array1OfVec2d& ,
288 TColStd_Array1OfReal& Weigths,
289 TColStd_Array1OfReal& DWeigths)
291 gp_Pnt P1, P2, Center;
292 Standard_Real invnorm1, invnorm2, invnormp;
293 // gp_Vec DCenter, D2Center, nplan, dnplan, DP1, DP2;
294 gp_Vec DCenter, nplan, dnplan, DP1, DP2;
295 // gp_Vec ns1, ns2, Dns1, Dns2, vtmp;
296 gp_Vec ns1, ns2, Dns1, Dns2;
300 myTPath ->D1(Param, Center, DCenter);
301 myTCurve1->D1(Param, P1, DP1);
302 myTCurve2->D1(Param, P2, DP2);
304 ns1.SetXYZ( Center.XYZ() - P1.XYZ());
305 ns2.SetXYZ( Center.XYZ() - P2.XYZ());
306 Dns1 = DCenter - DP1;
307 Dns2 = DCenter - DP2;
309 if (!ns1.IsParallel(ns2,1.e-9)) {
310 nplan = ns1.Crossed(ns2);
311 dnplan = Dns1.Crossed(ns2).Added( ns1.Crossed(Dns2));
314 myTPath->D2(Param, Center, nplan, dnplan);
322 invnorm1 = ((Standard_Real) 1) / ns1.Magnitude();
323 invnorm2 = ((Standard_Real) 1) / ns2.Magnitude();
326 Dns1.SetLinearForm( -Dns1.Dot(ns1), ns1, Dns1);
330 Dns2.SetLinearForm(-Dns2.Dot(ns2), ns2, Dns2);
333 temp.SetLinearForm(myRadius, ns1.XYZ(),
335 1, P1.XYZ(), P2.XYZ());
336 Center.ChangeCoord() = 0.5*temp;
337 DCenter.SetLinearForm(myRadius, Dns1,
342 invnormp = ((Standard_Real)1) / nplan.Magnitude();
344 dnplan.SetLinearForm(-dnplan.Dot(nplan), nplan, dnplan);
347 GeomFill::GetCircle(myTConv,
357 return Standard_True;
360 Standard_Boolean GeomFill_CircularBlendFunc::D2(const Standard_Real Param,
361 // const Standard_Real First,
362 const Standard_Real ,
363 // const Standard_Real Last,
364 const Standard_Real ,
365 TColgp_Array1OfPnt& Poles,
366 TColgp_Array1OfVec& DPoles,
367 TColgp_Array1OfVec& D2Poles,
368 // TColgp_Array1OfPnt2d& Poles2d,
369 TColgp_Array1OfPnt2d& ,
370 // TColgp_Array1OfVec2d& DPoles2d,
371 TColgp_Array1OfVec2d& ,
372 // TColgp_Array1OfVec2d& D2Poles2d,
373 TColgp_Array1OfVec2d& ,
374 TColStd_Array1OfReal& Weigths,
375 TColStd_Array1OfReal& DWeigths,
376 TColStd_Array1OfReal& D2Weigths)
378 gp_Pnt P1, P2, Center;
379 Standard_Real invnorm1, invnorm2, invnormp, sc;
380 gp_Vec DCenter, D2Center, DP1, DP2, D2P1, D2P2;
381 gp_Vec nplan, dnplan, d2nplan;
382 gp_Vec ns1, ns2, Dns1, Dns2, D2ns1, D2ns2;
386 myTPath ->D2(Param, Center, DCenter, D2Center);
387 myTCurve1->D2(Param, P1, DP1, D2P1);
388 myTCurve2->D2(Param, P2, DP2, D2P2);
390 ns1.SetXYZ( Center.XYZ() - P1.XYZ());
391 Dns1 = DCenter - DP1;
392 D2ns1 = D2Center - D2P1;
393 ns2.SetXYZ( Center.XYZ() - P2.XYZ());
394 Dns2 = DCenter - DP2;
395 D2ns2 = D2Center - D2P2;
397 if (!ns1.IsParallel(ns2,1.e-9)) {
398 nplan = ns1.Crossed(ns2);
399 dnplan = Dns1.Crossed(ns2).Added( ns1.Crossed(Dns2));
400 d2nplan.SetLinearForm(1, D2ns1.Crossed(ns2),
401 2, Dns1.Crossed(Dns2),
405 myTPath->D3(Param, Center, nplan, dnplan, d2nplan);
414 invnorm1 = ((Standard_Real) 1) / ns1.Magnitude();
415 invnorm2 = ((Standard_Real) 1) / ns2.Magnitude();
419 D2ns1.SetLinearForm( 3*sc*sc*invnorm1 - D2ns1.Dot(ns1)
420 - invnorm1*Dns1.SquareMagnitude(), ns1,
421 -2*sc*invnorm1 , Dns1,
423 Dns1.SetLinearForm( -Dns1.Dot(ns1), ns1, Dns1);
431 D2ns2.SetLinearForm( 3*sc*sc*invnorm2 - D2ns2.Dot(ns2)
432 - invnorm2*Dns2.SquareMagnitude(), ns2,
433 -2*sc*invnorm2 , Dns2,
435 Dns2.SetLinearForm(-sc, ns2, Dns2);
440 temp.SetLinearForm(myRadius, ns1.XYZ(),
442 1, P1.XYZ(), P2.XYZ());
443 Center.ChangeCoord() = 0.5*temp;
444 DCenter.SetLinearForm(myRadius, Dns1,
448 D2Center.SetLinearForm(myRadius, D2ns1,
453 invnormp = ((Standard_Real)1) / nplan.Magnitude();
455 sc = dnplan.Dot(nplan);
456 d2nplan.SetLinearForm( 3*sc*sc*invnormp - d2nplan.Dot(nplan)
457 - invnormp*dnplan.SquareMagnitude(), nplan,
458 -2*sc*invnormp , dnplan,
460 dnplan.SetLinearForm(-sc, nplan, dnplan);
464 GeomFill::GetCircle(myTConv,
468 nplan, dnplan, d2nplan,
473 Center, DCenter, D2Center,
474 Poles, DPoles, D2Poles,
475 Weigths, DWeigths, D2Weigths);
476 return Standard_True;
479 Standard_Integer GeomFill_CircularBlendFunc::Nb2dCurves() const
484 void GeomFill_CircularBlendFunc::SectionShape(Standard_Integer& NbPoles,
485 Standard_Integer& NbKnots,
486 Standard_Integer& Degree) const
493 void GeomFill_CircularBlendFunc::Knots(TColStd_Array1OfReal& TKnots) const
495 GeomFill::Knots(myTConv, TKnots);
498 void GeomFill_CircularBlendFunc::Mults(TColStd_Array1OfInteger& TMults) const
500 GeomFill::Mults(myTConv, TMults);
503 Standard_Boolean GeomFill_CircularBlendFunc::IsRational() const
505 return (myTConv != Convert_Polynomial);
508 Standard_Integer GeomFill_CircularBlendFunc::
509 NbIntervals(const GeomAbs_Shape S) const
511 Standard_Integer NbI_Center, NbI_Cb1, NbI_Cb2, ii;
512 NbI_Center = myPath->NbIntervals(GeomFillNextShape(S));
513 NbI_Cb1 = myCurve1->NbIntervals(S);
514 NbI_Cb2 = myCurve2->NbIntervals(S);
516 TColStd_Array1OfReal ICenter(1, NbI_Center+1);
517 TColStd_Array1OfReal ICb1(1, NbI_Cb1+1);
518 TColStd_Array1OfReal ICb2(1, NbI_Cb2+1);
519 TColStd_SequenceOfReal Inter;
521 myPath->Intervals(ICenter, GeomFillNextShape(S));
522 myCurve1->Intervals(ICb1, S);
523 myCurve2->Intervals(ICb2, S);
524 /* cout << "Intervals : " << S << endl;
525 cout << "-- Center-> " << endl;
526 for (ii=1; ii<=ICenter.Length(); ii++) cout << " , "<< ICenter(ii);
527 cout << endl; cout << endl;
528 cout << "-- Cb1-> " << endl;
529 for (ii=1; ii<=ICb1.Length(); ii++) cout << " , "<< ICb1(ii);
530 cout << endl; cout << endl;
531 cout << "-- Cb2-> " << endl;
532 for (ii=1; ii<=ICb2.Length(); ii++) cout << " , "<< ICb1(ii);
533 cout << endl; cout << endl;*/
535 GeomFillFusInt(ICb1, ICb2, Inter);
537 TColStd_Array1OfReal ICbs (1, Inter.Length());
538 for (ii=1; ii<=ICbs.Length(); ii++) ICbs(ii) = Inter(ii);
541 GeomFillFusInt(ICenter, ICbs, Inter);
543 return Inter.Length()-1;
546 void GeomFill_CircularBlendFunc::
547 Intervals(TColStd_Array1OfReal& T, const GeomAbs_Shape S) const
549 Standard_Integer NbI_Center, NbI_Cb1, NbI_Cb2, ii;
550 NbI_Center = myPath->NbIntervals(GeomFillNextShape(S));
551 NbI_Cb1 = myCurve1->NbIntervals(S);
552 NbI_Cb2 = myCurve2->NbIntervals(S);
554 TColStd_Array1OfReal ICenter(1, NbI_Center+1);
555 TColStd_Array1OfReal ICb1(1, NbI_Cb1+1);
556 TColStd_Array1OfReal ICb2(1, NbI_Cb2+1);
557 TColStd_SequenceOfReal Inter;
559 myPath->Intervals(ICenter, GeomFillNextShape(S));
560 myCurve1->Intervals(ICb1, S);
561 myCurve2->Intervals(ICb2, S);
563 GeomFillFusInt(ICb1, ICb2, Inter);
565 TColStd_Array1OfReal ICbs (1, Inter.Length());
566 for (ii=1; ii<=ICbs.Length(); ii++) ICbs(ii) = Inter(ii);
569 GeomFillFusInt(ICenter, ICbs, Inter);
571 // Recopie du resultat
572 for (ii=1; ii<=Inter.Length(); ii++) T(ii) = Inter(ii);
575 void GeomFill_CircularBlendFunc::SetInterval(const Standard_Real First,
576 const Standard_Real Last)
578 Standard_Real Eps = Precision::PConfusion();
579 myTPath = myPath->Trim(First, Last, Eps);
580 myTCurve1 = myCurve1->Trim(First, Last, Eps);
581 myTCurve2 = myCurve2->Trim(First, Last, Eps);
585 void GeomFill_CircularBlendFunc::GetTolerance(const Standard_Real BoundTol,
586 const Standard_Real SurfTol,
587 const Standard_Real AngleTol,
588 TColStd_Array1OfReal& Tol3d) const
590 Standard_Integer low = Tol3d.Lower() , up=Tol3d.Upper();
593 Tol= GeomFill::GetTolerance(myTConv, minang,
594 myRadius, AngleTol, SurfTol);
596 Tol3d(low+1) = Tol3d(up-1) = Min(Tol, SurfTol);
597 Tol3d(low) = Tol3d(up) = Min(Tol, BoundTol);
601 void GeomFill_CircularBlendFunc::SetTolerance(const Standard_Real,
607 gp_Pnt GeomFill_CircularBlendFunc::BarycentreOfSurf() const
612 Standard_Real GeomFill_CircularBlendFunc::MaximalSection() const
614 return maxang*myRadius;
617 void GeomFill_CircularBlendFunc::
618 GetMinimalWeight(TColStd_Array1OfReal& Weigths) const
620 GeomFill::GetMinimalWeights(myTConv, minang, maxang, Weigths);