1 // Created on: 1997-07-11
2 // Created by: Philippe MANGIN
3 // Copyright (c) 1997-1999 Matra Datavision
4 // Copyright (c) 1999-2014 OPEN CASCADE SAS
6 // This file is part of Open CASCADE Technology software library.
8 // This library is free software; you can redistribute it and / or modify it
9 // under the terms of the GNU Lesser General Public 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.
17 #include <GeomFill_CircularBlendFunc.ixx>
18 #include <GeomFill.hxx>
20 #include <GCPnts_QuasiUniformDeflection.hxx>
21 #include <Precision.hxx>
22 #include <Adaptor3d_HCurve.hxx>
24 #include <TColStd_SequenceOfReal.hxx>
25 #include <TColStd_Array1OfReal.hxx>
28 #include <GeomAdaptor_HCurve.hxx>
29 #include <Geom_BSplineCurve.hxx>
30 #include <DrawTrSurf.hxx>
31 static Standard_Integer NbSections = 0;
34 GeomAbs_Shape GeomFillNextShape(const GeomAbs_Shape S)
50 void GeomFillFusInt(const TColStd_Array1OfReal& I1,
51 const TColStd_Array1OfReal& I2,
52 TColStd_SequenceOfReal& Seq)
54 Standard_Integer ind1=1, ind2=1;
55 Standard_Real Epspar = Precision::PConfusion()*0.99;
56 // en suposant que le positionement fonctionne a PConfusion()/2
58 // Initialisations : les IND1 et IND2 pointent sur le 1er element
59 // de chacune des 2 tables a traiter.
62 //--- On remplit TABSOR en parcourant TABLE1 et TABLE2 simultanement ---
63 //------------------ en eliminant les occurrences multiples ------------
65 while ((ind1<=I1.Upper()) && (ind2<=I2.Upper())) {
68 if (Abs(v1-v2)<= Epspar) {
69 // Ici les elements de I1 et I2 conviennent .
70 Seq.Append((v1+v2)/2);
75 // Ici l' element de I1 convient.
80 // Ici l' element de TABLE2 convient.
86 if (ind1>I1.Upper()) {
87 //----- Ici I1 est epuise, on complete avec la fin de TABLE2 -------
89 for (; ind2<=I2.Upper(); ind2++) {
94 if (ind2>I2.Upper()) {
95 //----- Ici I2 est epuise, on complete avec la fin de I1 -------
97 for (; ind1<=I1.Upper(); ind1++) {
104 GeomFill_CircularBlendFunc::
105 GeomFill_CircularBlendFunc(const Handle(Adaptor3d_HCurve)& Path,
106 const Handle(Adaptor3d_HCurve)& Curve1,
107 const Handle(Adaptor3d_HCurve)& Curve2,
108 const Standard_Real Radius,
109 const Standard_Boolean Polynomial)
110 : maxang(RealFirst()),
114 // Recopie des arguments
115 myPath = myTPath = Path;
116 myCurve1 = myTCurve1 = Curve1;
117 myCurve2 = myTCurve2 = Curve2;
120 // Estimations numeriques
123 // Type de convertion ?
124 if (Polynomial) myTConv=Convert_Polynomial;
125 else if(maxang > 0.65*M_PI)
126 myTConv=Convert_QuasiAngular; //car c'est Continue
127 else myTConv = Convert_TgtThetaOver2;
128 //car c'est le plus performant
130 // On en deduit la structure
131 GeomFill::GetShape(maxang,
132 myNbPoles, myNbKnots,
136 void GeomFill_CircularBlendFunc::Discret()
138 Standard_Real TFirst = myPath->FirstParameter();
139 Standard_Real TLast = myPath->LastParameter(), T;
141 Standard_Real L1, L2, L;
142 Handle(Adaptor3d_HCurve) C;
143 gp_Pnt P1, P2, P3, Center;
146 P1 = myCurve1->Value(TFirst);
147 P2 = myCurve1->Value((TFirst+TLast)/2.);
148 P3 = myCurve1->Value(TLast);
149 L1 = P1.Distance(P2) + P2.Distance(P3);
151 P1 = myCurve2->Value(TFirst);
152 P2 = myCurve2->Value((TFirst+TLast)/2.);
153 P3 = myCurve2->Value(TLast);
154 L2 = P1.Distance(P2) + P2.Distance(P3);
165 Standard_Real Fleche = 1.e-2 * L;
166 Standard_Real Angle, Cosa, Percent;
167 GCPnts_QuasiUniformDeflection Samp;
168 Samp.Initialize(C->GetCurve(), Fleche);
169 myBary.SetCoord(0.,0.,0.);
173 Percent = ((Standard_Real)1)/(2*Samp.NbPoints());
175 for (ii=1; ii<=Samp.NbPoints(); ii++) {
176 T = Samp.Parameter(ii);
180 sprintf(name,"PNT_%d",NbSections++);
181 DrawTrSurf::Set(name, P1);
182 sprintf(name,"PNT_%d",NbSections++);
183 DrawTrSurf::Set(name, P2);*/
184 myPath->D0(T, Center);
185 ns1.SetXYZ( Center.XYZ() - P1.XYZ());
186 ns2.SetXYZ( Center.XYZ() - P2.XYZ());
190 if(Cosa > 1.) {Cosa = 1.;}
191 Angle = Abs(ACos(Cosa));
192 if (Angle>maxang) maxang = Angle;
193 if (Angle<minang) minang = Angle;
194 distmin = Min( distmin, P1.Distance(P2));
195 myBary.ChangeCoord() += (P1.XYZ()+P2.XYZ());
199 Standard_Real Delta = (TLast-TFirst)/20;
200 Percent = ((Standard_Real)1)/42;
201 for (ii=0, T=TFirst; ii<=20; ii++, T+=Delta) {
204 myPath->D0(T, Center);
206 ns1.SetXYZ( Center.XYZ() - P1.XYZ());
207 ns2.SetXYZ( Center.XYZ() - P2.XYZ());
211 if(Cosa > 1.) Cosa = 1.;
212 Angle = Abs(ACos(Cosa));
214 if (Angle>maxang) maxang = Angle;
215 if (Angle<minang) minang = Angle;
216 distmin = Min( distmin, P1.Distance(P2));
217 myBary.ChangeCoord() += (P1.XYZ()+P2.XYZ());
220 myBary.ChangeCoord() *= Percent;
222 // Faut il inverser la trajectoire ?
223 T = (TFirst + TLast)/2;
226 myPath->D1(T, Center, DCenter);
228 ns1.SetXYZ( Center.XYZ() - P1.XYZ());
229 ns2.SetXYZ( Center.XYZ() - P2.XYZ());
231 myreverse = (DCenter.Dot(ns1.Crossed(ns2)) < 0);
236 Standard_Boolean GeomFill_CircularBlendFunc::D0(const Standard_Real Param,
239 TColgp_Array1OfPnt& Poles,
240 TColgp_Array1OfPnt2d&,
241 TColStd_Array1OfReal& Weigths)
243 gp_Pnt P1, P2, Center;
244 gp_Vec ns1, ns2, nplan;
248 myTPath->D0(Param, Center);
249 myTCurve1->D0(Param, P1);
250 myTCurve2->D0(Param, P2);
251 ns1.SetXYZ( Center.XYZ() - P1.XYZ());
252 ns2.SetXYZ( Center.XYZ() - P2.XYZ());
253 if (!ns1.IsParallel(ns2,1.e-9)) nplan = ns1.Crossed(ns2);
255 myTPath->D1(Param, Center, nplan);
256 if (myreverse) nplan.Reverse();
264 temp.SetLinearForm(myRadius, ns1.XYZ(),
268 Center.ChangeCoord() = 0.5*temp;
271 GeomFill::GetCircle(myTConv,
278 // Handle(Geom_BSplineCurve) BS =
279 // new Geom_BSplineCurve(Poles,Weights,Knots,Mults,Degree);
280 // sprintf(name,"SECT_%d",NbSections++);
281 // DrawTrSurf::Set(name,BS);
283 return Standard_True;
287 Standard_Boolean GeomFill_CircularBlendFunc::D1(const Standard_Real Param,
288 // const Standard_Real First,
289 const Standard_Real ,
290 // const Standard_Real Last,
291 const Standard_Real ,
292 TColgp_Array1OfPnt& Poles,
293 TColgp_Array1OfVec& DPoles,
294 // TColgp_Array1OfPnt2d& Poles2d,
295 TColgp_Array1OfPnt2d& ,
296 // TColgp_Array1OfVec2d& DPoles2d,
297 TColgp_Array1OfVec2d& ,
298 TColStd_Array1OfReal& Weigths,
299 TColStd_Array1OfReal& DWeigths)
301 gp_Pnt P1, P2, Center;
302 Standard_Real invnorm1, invnorm2, invnormp;
303 // gp_Vec DCenter, D2Center, nplan, dnplan, DP1, DP2;
304 gp_Vec DCenter, nplan, dnplan, DP1, DP2;
305 // gp_Vec ns1, ns2, Dns1, Dns2, vtmp;
306 gp_Vec ns1, ns2, Dns1, Dns2;
310 myTPath ->D1(Param, Center, DCenter);
311 myTCurve1->D1(Param, P1, DP1);
312 myTCurve2->D1(Param, P2, DP2);
314 ns1.SetXYZ( Center.XYZ() - P1.XYZ());
315 ns2.SetXYZ( Center.XYZ() - P2.XYZ());
316 Dns1 = DCenter - DP1;
317 Dns2 = DCenter - DP2;
319 if (!ns1.IsParallel(ns2,1.e-9)) {
320 nplan = ns1.Crossed(ns2);
321 dnplan = Dns1.Crossed(ns2).Added( ns1.Crossed(Dns2));
324 myTPath->D2(Param, Center, nplan, dnplan);
332 invnorm1 = ((Standard_Real) 1) / ns1.Magnitude();
333 invnorm2 = ((Standard_Real) 1) / ns2.Magnitude();
336 Dns1.SetLinearForm( -Dns1.Dot(ns1), ns1, Dns1);
340 Dns2.SetLinearForm(-Dns2.Dot(ns2), ns2, Dns2);
343 temp.SetLinearForm(myRadius, ns1.XYZ(),
345 1, P1.XYZ(), P2.XYZ());
346 Center.ChangeCoord() = 0.5*temp;
347 DCenter.SetLinearForm(myRadius, Dns1,
352 invnormp = ((Standard_Real)1) / nplan.Magnitude();
354 dnplan.SetLinearForm(-dnplan.Dot(nplan), nplan, dnplan);
357 GeomFill::GetCircle(myTConv,
367 return Standard_True;
370 Standard_Boolean GeomFill_CircularBlendFunc::D2(const Standard_Real Param,
371 // const Standard_Real First,
372 const Standard_Real ,
373 // const Standard_Real Last,
374 const Standard_Real ,
375 TColgp_Array1OfPnt& Poles,
376 TColgp_Array1OfVec& DPoles,
377 TColgp_Array1OfVec& D2Poles,
378 // TColgp_Array1OfPnt2d& Poles2d,
379 TColgp_Array1OfPnt2d& ,
380 // TColgp_Array1OfVec2d& DPoles2d,
381 TColgp_Array1OfVec2d& ,
382 // TColgp_Array1OfVec2d& D2Poles2d,
383 TColgp_Array1OfVec2d& ,
384 TColStd_Array1OfReal& Weigths,
385 TColStd_Array1OfReal& DWeigths,
386 TColStd_Array1OfReal& D2Weigths)
388 gp_Pnt P1, P2, Center;
389 Standard_Real invnorm1, invnorm2, invnormp, sc;
390 gp_Vec DCenter, D2Center, DP1, DP2, D2P1, D2P2;
391 gp_Vec nplan, dnplan, d2nplan;
392 gp_Vec ns1, ns2, Dns1, Dns2, D2ns1, D2ns2;
396 myTPath ->D2(Param, Center, DCenter, D2Center);
397 myTCurve1->D2(Param, P1, DP1, D2P1);
398 myTCurve2->D2(Param, P2, DP2, D2P2);
400 ns1.SetXYZ( Center.XYZ() - P1.XYZ());
401 Dns1 = DCenter - DP1;
402 D2ns1 = D2Center - D2P1;
403 ns2.SetXYZ( Center.XYZ() - P2.XYZ());
404 Dns2 = DCenter - DP2;
405 D2ns2 = D2Center - D2P2;
407 if (!ns1.IsParallel(ns2,1.e-9)) {
408 nplan = ns1.Crossed(ns2);
409 dnplan = Dns1.Crossed(ns2).Added( ns1.Crossed(Dns2));
410 d2nplan.SetLinearForm(1, D2ns1.Crossed(ns2),
411 2, Dns1.Crossed(Dns2),
415 myTPath->D3(Param, Center, nplan, dnplan, d2nplan);
424 invnorm1 = ((Standard_Real) 1) / ns1.Magnitude();
425 invnorm2 = ((Standard_Real) 1) / ns2.Magnitude();
429 D2ns1.SetLinearForm( 3*sc*sc*invnorm1 - D2ns1.Dot(ns1)
430 - invnorm1*Dns1.SquareMagnitude(), ns1,
431 -2*sc*invnorm1 , Dns1,
433 Dns1.SetLinearForm( -Dns1.Dot(ns1), ns1, Dns1);
441 D2ns2.SetLinearForm( 3*sc*sc*invnorm2 - D2ns2.Dot(ns2)
442 - invnorm2*Dns2.SquareMagnitude(), ns2,
443 -2*sc*invnorm2 , Dns2,
445 Dns2.SetLinearForm(-sc, ns2, Dns2);
450 temp.SetLinearForm(myRadius, ns1.XYZ(),
452 1, P1.XYZ(), P2.XYZ());
453 Center.ChangeCoord() = 0.5*temp;
454 DCenter.SetLinearForm(myRadius, Dns1,
458 D2Center.SetLinearForm(myRadius, D2ns1,
463 invnormp = ((Standard_Real)1) / nplan.Magnitude();
465 sc = dnplan.Dot(nplan);
466 d2nplan.SetLinearForm( 3*sc*sc*invnormp - d2nplan.Dot(nplan)
467 - invnormp*dnplan.SquareMagnitude(), nplan,
468 -2*sc*invnormp , dnplan,
470 dnplan.SetLinearForm(-sc, nplan, dnplan);
474 GeomFill::GetCircle(myTConv,
478 nplan, dnplan, d2nplan,
483 Center, DCenter, D2Center,
484 Poles, DPoles, D2Poles,
485 Weigths, DWeigths, D2Weigths);
486 return Standard_True;
489 Standard_Integer GeomFill_CircularBlendFunc::Nb2dCurves() const
494 void GeomFill_CircularBlendFunc::SectionShape(Standard_Integer& NbPoles,
495 Standard_Integer& NbKnots,
496 Standard_Integer& Degree) const
503 void GeomFill_CircularBlendFunc::Knots(TColStd_Array1OfReal& TKnots) const
505 GeomFill::Knots(myTConv, TKnots);
508 void GeomFill_CircularBlendFunc::Mults(TColStd_Array1OfInteger& TMults) const
510 GeomFill::Mults(myTConv, TMults);
513 Standard_Boolean GeomFill_CircularBlendFunc::IsRational() const
515 return (myTConv != Convert_Polynomial);
518 Standard_Integer GeomFill_CircularBlendFunc::
519 NbIntervals(const GeomAbs_Shape S) const
521 Standard_Integer NbI_Center, NbI_Cb1, NbI_Cb2, ii;
522 NbI_Center = myPath->NbIntervals(GeomFillNextShape(S));
523 NbI_Cb1 = myCurve1->NbIntervals(S);
524 NbI_Cb2 = myCurve2->NbIntervals(S);
526 TColStd_Array1OfReal ICenter(1, NbI_Center+1);
527 TColStd_Array1OfReal ICb1(1, NbI_Cb1+1);
528 TColStd_Array1OfReal ICb2(1, NbI_Cb2+1);
529 TColStd_SequenceOfReal Inter;
531 myPath->Intervals(ICenter, GeomFillNextShape(S));
532 myCurve1->Intervals(ICb1, S);
533 myCurve2->Intervals(ICb2, S);
534 /* cout << "Intervals : " << S << endl;
535 cout << "-- Center-> " << endl;
536 for (ii=1; ii<=ICenter.Length(); ii++) cout << " , "<< ICenter(ii);
537 cout << endl; cout << endl;
538 cout << "-- Cb1-> " << endl;
539 for (ii=1; ii<=ICb1.Length(); ii++) cout << " , "<< ICb1(ii);
540 cout << endl; cout << endl;
541 cout << "-- Cb2-> " << endl;
542 for (ii=1; ii<=ICb2.Length(); ii++) cout << " , "<< ICb1(ii);
543 cout << endl; cout << endl;*/
545 GeomFillFusInt(ICb1, ICb2, Inter);
547 TColStd_Array1OfReal ICbs (1, Inter.Length());
548 for (ii=1; ii<=ICbs.Length(); ii++) ICbs(ii) = Inter(ii);
551 GeomFillFusInt(ICenter, ICbs, Inter);
553 return Inter.Length()-1;
556 void GeomFill_CircularBlendFunc::
557 Intervals(TColStd_Array1OfReal& T, const GeomAbs_Shape S) const
559 Standard_Integer NbI_Center, NbI_Cb1, NbI_Cb2, ii;
560 NbI_Center = myPath->NbIntervals(GeomFillNextShape(S));
561 NbI_Cb1 = myCurve1->NbIntervals(S);
562 NbI_Cb2 = myCurve2->NbIntervals(S);
564 TColStd_Array1OfReal ICenter(1, NbI_Center+1);
565 TColStd_Array1OfReal ICb1(1, NbI_Cb1+1);
566 TColStd_Array1OfReal ICb2(1, NbI_Cb2+1);
567 TColStd_SequenceOfReal Inter;
569 myPath->Intervals(ICenter, GeomFillNextShape(S));
570 myCurve1->Intervals(ICb1, S);
571 myCurve2->Intervals(ICb2, S);
573 GeomFillFusInt(ICb1, ICb2, Inter);
575 TColStd_Array1OfReal ICbs (1, Inter.Length());
576 for (ii=1; ii<=ICbs.Length(); ii++) ICbs(ii) = Inter(ii);
579 GeomFillFusInt(ICenter, ICbs, Inter);
581 // Recopie du resultat
582 for (ii=1; ii<=Inter.Length(); ii++) T(ii) = Inter(ii);
585 void GeomFill_CircularBlendFunc::SetInterval(const Standard_Real First,
586 const Standard_Real Last)
588 Standard_Real Eps = Precision::PConfusion();
589 myTPath = myPath->Trim(First, Last, Eps);
590 myTCurve1 = myCurve1->Trim(First, Last, Eps);
591 myTCurve2 = myCurve2->Trim(First, Last, Eps);
595 void GeomFill_CircularBlendFunc::GetTolerance(const Standard_Real BoundTol,
596 const Standard_Real SurfTol,
597 const Standard_Real AngleTol,
598 TColStd_Array1OfReal& Tol3d) const
600 Standard_Integer low = Tol3d.Lower() , up=Tol3d.Upper();
603 Tol= GeomFill::GetTolerance(myTConv, minang,
604 myRadius, AngleTol, SurfTol);
606 Tol3d(low+1) = Tol3d(up-1) = Min(Tol, SurfTol);
607 Tol3d(low) = Tol3d(up) = Min(Tol, BoundTol);
611 void GeomFill_CircularBlendFunc::SetTolerance(const Standard_Real,
617 gp_Pnt GeomFill_CircularBlendFunc::BarycentreOfSurf() const
622 Standard_Real GeomFill_CircularBlendFunc::MaximalSection() const
624 return maxang*myRadius;
627 void GeomFill_CircularBlendFunc::
628 GetMinimalWeight(TColStd_Array1OfReal& Weigths) const
630 GeomFill::GetMinimalWeights(myTConv, minang, maxang, Weigths);