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 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 #include <Adaptor3d_HCurve.hxx>
19 #include <GCPnts_QuasiUniformDeflection.hxx>
20 #include <GeomFill.hxx>
21 #include <GeomFill_CircularBlendFunc.hxx>
23 #include <Precision.hxx>
24 #include <Standard_OutOfRange.hxx>
25 #include <Standard_Type.hxx>
26 #include <TColStd_Array1OfReal.hxx>
27 #include <TColStd_SequenceOfReal.hxx>
29 IMPLEMENT_STANDARD_RTTIEXT(GeomFill_CircularBlendFunc,Approx_SweepFunction)
32 #include <GeomAdaptor_HCurve.hxx>
33 #include <Geom_BSplineCurve.hxx>
34 #include <DrawTrSurf.hxx>
35 static Standard_Integer NbSections = 0;
38 static const Standard_Real TolAng = 1.e-6;
40 static GeomAbs_Shape GeomFillNextShape(const GeomAbs_Shape S)
56 static void GeomFillFusInt(const TColStd_Array1OfReal& I1,
57 const TColStd_Array1OfReal& I2,
58 TColStd_SequenceOfReal& Seq)
60 Standard_Integer ind1=1, ind2=1;
61 Standard_Real Epspar = Precision::PConfusion()*0.99;
62 // en suposant que le positionement fonctionne a PConfusion()/2
64 // Initialisations : les IND1 et IND2 pointent sur le 1er element
65 // de chacune des 2 tables a traiter.
68 //--- On remplit TABSOR en parcourant TABLE1 et TABLE2 simultanement ---
69 //------------------ en eliminant les occurrences multiples ------------
71 while ((ind1<=I1.Upper()) && (ind2<=I2.Upper())) {
74 if (Abs(v1-v2)<= Epspar) {
75 // Ici les elements de I1 et I2 conviennent .
76 Seq.Append((v1+v2)/2);
81 // Ici l' element de I1 convient.
86 // Ici l' element de TABLE2 convient.
92 if (ind1>I1.Upper()) {
93 //----- Ici I1 est epuise, on complete avec la fin de TABLE2 -------
95 for (; ind2<=I2.Upper(); ind2++) {
100 if (ind2>I2.Upper()) {
101 //----- Ici I2 est epuise, on complete avec la fin de I1 -------
103 for (; ind1<=I1.Upper(); ind1++) {
104 Seq.Append(I1(ind1));
110 GeomFill_CircularBlendFunc::
111 GeomFill_CircularBlendFunc(const Handle(Adaptor3d_HCurve)& Path,
112 const Handle(Adaptor3d_HCurve)& Curve1,
113 const Handle(Adaptor3d_HCurve)& Curve2,
114 const Standard_Real Radius,
115 const Standard_Boolean Polynomial)
116 : maxang(RealFirst()),
120 // Recopie des arguments
121 myPath = myTPath = Path;
122 myCurve1 = myTCurve1 = Curve1;
123 myCurve2 = myTCurve2 = Curve2;
126 // Estimations numeriques
129 // Type de convertion ?
130 if (Polynomial) myTConv=Convert_Polynomial;
131 else if(maxang > 0.65*M_PI)
132 myTConv=Convert_QuasiAngular; //car c'est Continue
133 else myTConv = Convert_TgtThetaOver2;
134 //car c'est le plus performant
136 // On en deduit la structure
137 GeomFill::GetShape(maxang,
138 myNbPoles, myNbKnots,
142 void GeomFill_CircularBlendFunc::Discret()
144 Standard_Real TFirst = myPath->FirstParameter();
145 Standard_Real TLast = myPath->LastParameter(), T;
147 Standard_Real L1, L2, L;
148 Handle(Adaptor3d_HCurve) C;
149 gp_Pnt P1, P2, P3, Center;
152 P1 = myCurve1->Value(TFirst);
153 P2 = myCurve1->Value((TFirst+TLast)/2.);
154 P3 = myCurve1->Value(TLast);
155 L1 = P1.Distance(P2) + P2.Distance(P3);
157 P1 = myCurve2->Value(TFirst);
158 P2 = myCurve2->Value((TFirst+TLast)/2.);
159 P3 = myCurve2->Value(TLast);
160 L2 = P1.Distance(P2) + P2.Distance(P3);
171 Standard_Real Fleche = 1.e-2 * L;
172 Standard_Real Angle, Cosa, Percent;
173 GCPnts_QuasiUniformDeflection Samp;
174 Samp.Initialize(C->GetCurve(), Fleche);
175 myBary.SetCoord(0.,0.,0.);
179 Percent = ((Standard_Real)1)/(2*Samp.NbPoints());
181 for (ii=1; ii<=Samp.NbPoints(); ii++) {
182 T = Samp.Parameter(ii);
186 sprintf(name,"PNT_%d",NbSections++);
187 DrawTrSurf::Set(name, P1);
188 sprintf(name,"PNT_%d",NbSections++);
189 DrawTrSurf::Set(name, P2);*/
190 myPath->D0(T, Center);
191 ns1.SetXYZ( Center.XYZ() - P1.XYZ());
192 ns2.SetXYZ( Center.XYZ() - P2.XYZ());
196 if(Cosa > 1.) {Cosa = 1.;}
197 Angle = Abs(ACos(Cosa));
198 if (Angle>maxang) maxang = Angle;
199 if (Angle<minang) minang = Angle;
200 distmin = Min( distmin, P1.Distance(P2));
201 myBary.ChangeCoord() += (P1.XYZ()+P2.XYZ());
205 Standard_Real Delta = (TLast-TFirst)/20;
206 Percent = ((Standard_Real)1)/42;
207 for (ii=0, T=TFirst; ii<=20; ii++, T+=Delta) {
210 myPath->D0(T, Center);
212 ns1.SetXYZ( Center.XYZ() - P1.XYZ());
213 ns2.SetXYZ( Center.XYZ() - P2.XYZ());
217 if(Cosa > 1.) Cosa = 1.;
218 Angle = Abs(ACos(Cosa));
220 if (Angle>maxang) maxang = Angle;
221 if (Angle<minang) minang = Angle;
222 distmin = Min( distmin, P1.Distance(P2));
223 myBary.ChangeCoord() += (P1.XYZ()+P2.XYZ());
226 myBary.ChangeCoord() *= Percent;
228 // Faut il inverser la trajectoire ?
229 T = (TFirst + TLast)/2;
232 myPath->D1(T, Center, DCenter);
234 ns1.SetXYZ( Center.XYZ() - P1.XYZ());
235 ns2.SetXYZ( Center.XYZ() - P2.XYZ());
237 //myreverse = (DCenter.Dot(ns1.Crossed(ns2)) < 0);
238 myreverse = Standard_False;
243 Standard_Boolean GeomFill_CircularBlendFunc::D0(const Standard_Real Param,
246 TColgp_Array1OfPnt& Poles,
247 TColgp_Array1OfPnt2d&,
248 TColStd_Array1OfReal& Weigths)
250 gp_Pnt P1, P2, Center;
251 gp_Vec ns1, ns2, nplan;
255 myTPath->D0(Param, Center);
256 myTCurve1->D0(Param, P1);
257 myTCurve2->D0(Param, P2);
258 ns1.SetXYZ( Center.XYZ() - P1.XYZ());
259 ns2.SetXYZ( Center.XYZ() - P2.XYZ());
260 if (!ns1.IsParallel(ns2, TolAng)) nplan = ns1.Crossed(ns2);
262 myTPath->D1(Param, Center, nplan);
263 if (myreverse) nplan.Reverse();
271 temp.SetLinearForm(myRadius, ns1.XYZ(),
275 Center.ChangeCoord() = 0.5*temp;
278 GeomFill::GetCircle(myTConv,
285 // Handle(Geom_BSplineCurve) BS =
286 // new Geom_BSplineCurve(Poles,Weights,Knots,Mults,Degree);
287 // sprintf(name,"SECT_%d",NbSections++);
288 // DrawTrSurf::Set(name,BS);
290 return Standard_True;
294 Standard_Boolean GeomFill_CircularBlendFunc::D1(const Standard_Real Param,
295 // const Standard_Real First,
296 const Standard_Real ,
297 // const Standard_Real Last,
298 const Standard_Real ,
299 TColgp_Array1OfPnt& Poles,
300 TColgp_Array1OfVec& DPoles,
301 // TColgp_Array1OfPnt2d& Poles2d,
302 TColgp_Array1OfPnt2d& ,
303 // TColgp_Array1OfVec2d& DPoles2d,
304 TColgp_Array1OfVec2d& ,
305 TColStd_Array1OfReal& Weigths,
306 TColStd_Array1OfReal& DWeigths)
308 gp_Pnt P1, P2, Center;
309 Standard_Real invnorm1, invnorm2, invnormp;
310 // gp_Vec DCenter, D2Center, nplan, dnplan, DP1, DP2;
311 gp_Vec DCenter, nplan, dnplan, DP1, DP2;
312 // gp_Vec ns1, ns2, Dns1, Dns2, vtmp;
313 gp_Vec ns1, ns2, Dns1, Dns2;
317 myTPath ->D1(Param, Center, DCenter);
318 myTCurve1->D1(Param, P1, DP1);
319 myTCurve2->D1(Param, P2, DP2);
321 ns1.SetXYZ( Center.XYZ() - P1.XYZ());
322 ns2.SetXYZ( Center.XYZ() - P2.XYZ());
323 Dns1 = DCenter - DP1;
324 Dns2 = DCenter - DP2;
326 if (!ns1.IsParallel(ns2, TolAng)) {
327 nplan = ns1.Crossed(ns2);
328 dnplan = Dns1.Crossed(ns2).Added( ns1.Crossed(Dns2));
331 myTPath->D2(Param, Center, nplan, dnplan);
339 invnorm1 = ((Standard_Real) 1) / ns1.Magnitude();
340 invnorm2 = ((Standard_Real) 1) / ns2.Magnitude();
343 Dns1.SetLinearForm( -Dns1.Dot(ns1), ns1, Dns1);
347 Dns2.SetLinearForm(-Dns2.Dot(ns2), ns2, Dns2);
350 temp.SetLinearForm(myRadius, ns1.XYZ(),
352 1, P1.XYZ(), P2.XYZ());
353 Center.ChangeCoord() = 0.5*temp;
354 DCenter.SetLinearForm(myRadius, Dns1,
359 invnormp = ((Standard_Real)1) / nplan.Magnitude();
361 dnplan.SetLinearForm(-dnplan.Dot(nplan), nplan, dnplan);
364 GeomFill::GetCircle(myTConv,
374 return Standard_True;
377 Standard_Boolean GeomFill_CircularBlendFunc::D2(const Standard_Real Param,
378 // const Standard_Real First,
379 const Standard_Real ,
380 // const Standard_Real Last,
381 const Standard_Real ,
382 TColgp_Array1OfPnt& Poles,
383 TColgp_Array1OfVec& DPoles,
384 TColgp_Array1OfVec& D2Poles,
385 // TColgp_Array1OfPnt2d& Poles2d,
386 TColgp_Array1OfPnt2d& ,
387 // TColgp_Array1OfVec2d& DPoles2d,
388 TColgp_Array1OfVec2d& ,
389 // TColgp_Array1OfVec2d& D2Poles2d,
390 TColgp_Array1OfVec2d& ,
391 TColStd_Array1OfReal& Weigths,
392 TColStd_Array1OfReal& DWeigths,
393 TColStd_Array1OfReal& D2Weigths)
395 gp_Pnt P1, P2, Center;
396 Standard_Real invnorm1, invnorm2, invnormp, sc;
397 gp_Vec DCenter, D2Center, DP1, DP2, D2P1, D2P2;
398 gp_Vec nplan, dnplan, d2nplan;
399 gp_Vec ns1, ns2, Dns1, Dns2, D2ns1, D2ns2;
403 myTPath ->D2(Param, Center, DCenter, D2Center);
404 myTCurve1->D2(Param, P1, DP1, D2P1);
405 myTCurve2->D2(Param, P2, DP2, D2P2);
407 ns1.SetXYZ( Center.XYZ() - P1.XYZ());
408 Dns1 = DCenter - DP1;
409 D2ns1 = D2Center - D2P1;
410 ns2.SetXYZ( Center.XYZ() - P2.XYZ());
411 Dns2 = DCenter - DP2;
412 D2ns2 = D2Center - D2P2;
414 if (!ns1.IsParallel(ns2, TolAng)) {
415 nplan = ns1.Crossed(ns2);
416 dnplan = Dns1.Crossed(ns2).Added( ns1.Crossed(Dns2));
417 d2nplan.SetLinearForm(1, D2ns1.Crossed(ns2),
418 2, Dns1.Crossed(Dns2),
422 myTPath->D3(Param, Center, nplan, dnplan, d2nplan);
431 invnorm1 = ((Standard_Real) 1) / ns1.Magnitude();
432 invnorm2 = ((Standard_Real) 1) / ns2.Magnitude();
436 D2ns1.SetLinearForm( 3*sc*sc*invnorm1 - D2ns1.Dot(ns1)
437 - invnorm1*Dns1.SquareMagnitude(), ns1,
438 -2*sc*invnorm1 , Dns1,
440 Dns1.SetLinearForm( -Dns1.Dot(ns1), ns1, Dns1);
448 D2ns2.SetLinearForm( 3*sc*sc*invnorm2 - D2ns2.Dot(ns2)
449 - invnorm2*Dns2.SquareMagnitude(), ns2,
450 -2*sc*invnorm2 , Dns2,
452 Dns2.SetLinearForm(-sc, ns2, Dns2);
457 temp.SetLinearForm(myRadius, ns1.XYZ(),
459 1, P1.XYZ(), P2.XYZ());
460 Center.ChangeCoord() = 0.5*temp;
461 DCenter.SetLinearForm(myRadius, Dns1,
465 D2Center.SetLinearForm(myRadius, D2ns1,
470 invnormp = ((Standard_Real)1) / nplan.Magnitude();
472 sc = dnplan.Dot(nplan);
473 d2nplan.SetLinearForm( 3*sc*sc*invnormp - d2nplan.Dot(nplan)
474 - invnormp*dnplan.SquareMagnitude(), nplan,
475 -2*sc*invnormp , dnplan,
477 dnplan.SetLinearForm(-sc, nplan, dnplan);
481 GeomFill::GetCircle(myTConv,
485 nplan, dnplan, d2nplan,
490 Center, DCenter, D2Center,
491 Poles, DPoles, D2Poles,
492 Weigths, DWeigths, D2Weigths);
493 return Standard_True;
496 Standard_Integer GeomFill_CircularBlendFunc::Nb2dCurves() const
501 void GeomFill_CircularBlendFunc::SectionShape(Standard_Integer& NbPoles,
502 Standard_Integer& NbKnots,
503 Standard_Integer& Degree) const
510 void GeomFill_CircularBlendFunc::Knots(TColStd_Array1OfReal& TKnots) const
512 GeomFill::Knots(myTConv, TKnots);
515 void GeomFill_CircularBlendFunc::Mults(TColStd_Array1OfInteger& TMults) const
517 GeomFill::Mults(myTConv, TMults);
520 Standard_Boolean GeomFill_CircularBlendFunc::IsRational() const
522 return (myTConv != Convert_Polynomial);
525 Standard_Integer GeomFill_CircularBlendFunc::
526 NbIntervals(const GeomAbs_Shape S) const
528 Standard_Integer NbI_Center, NbI_Cb1, NbI_Cb2, ii;
529 NbI_Center = myPath->NbIntervals(GeomFillNextShape(S));
530 NbI_Cb1 = myCurve1->NbIntervals(S);
531 NbI_Cb2 = myCurve2->NbIntervals(S);
533 TColStd_Array1OfReal ICenter(1, NbI_Center+1);
534 TColStd_Array1OfReal ICb1(1, NbI_Cb1+1);
535 TColStd_Array1OfReal ICb2(1, NbI_Cb2+1);
536 TColStd_SequenceOfReal Inter;
538 myPath->Intervals(ICenter, GeomFillNextShape(S));
539 myCurve1->Intervals(ICb1, S);
540 myCurve2->Intervals(ICb2, S);
541 /* std::cout << "Intervals : " << S << std::endl;
542 std::cout << "-- Center-> " << std::endl;
543 for (ii=1; ii<=ICenter.Length(); ii++) std::cout << " , "<< ICenter(ii);
544 std::cout << std::endl; std::cout << std::endl;
545 std::cout << "-- Cb1-> " << std::endl;
546 for (ii=1; ii<=ICb1.Length(); ii++) std::cout << " , "<< ICb1(ii);
547 std::cout << std::endl; std::cout << std::endl;
548 std::cout << "-- Cb2-> " << std::endl;
549 for (ii=1; ii<=ICb2.Length(); ii++) std::cout << " , "<< ICb1(ii);
550 std::cout << std::endl; std::cout << std::endl;*/
552 GeomFillFusInt(ICb1, ICb2, Inter);
554 TColStd_Array1OfReal ICbs (1, Inter.Length());
555 for (ii=1; ii<=ICbs.Length(); ii++) ICbs(ii) = Inter(ii);
558 GeomFillFusInt(ICenter, ICbs, Inter);
560 return Inter.Length()-1;
563 void GeomFill_CircularBlendFunc::
564 Intervals(TColStd_Array1OfReal& T, const GeomAbs_Shape S) const
566 Standard_Integer NbI_Center, NbI_Cb1, NbI_Cb2, ii;
567 NbI_Center = myPath->NbIntervals(GeomFillNextShape(S));
568 NbI_Cb1 = myCurve1->NbIntervals(S);
569 NbI_Cb2 = myCurve2->NbIntervals(S);
571 TColStd_Array1OfReal ICenter(1, NbI_Center+1);
572 TColStd_Array1OfReal ICb1(1, NbI_Cb1+1);
573 TColStd_Array1OfReal ICb2(1, NbI_Cb2+1);
574 TColStd_SequenceOfReal Inter;
576 myPath->Intervals(ICenter, GeomFillNextShape(S));
577 myCurve1->Intervals(ICb1, S);
578 myCurve2->Intervals(ICb2, S);
580 GeomFillFusInt(ICb1, ICb2, Inter);
582 TColStd_Array1OfReal ICbs (1, Inter.Length());
583 for (ii=1; ii<=ICbs.Length(); ii++) ICbs(ii) = Inter(ii);
586 GeomFillFusInt(ICenter, ICbs, Inter);
588 // Recopie du resultat
589 for (ii=1; ii<=Inter.Length(); ii++) T(ii) = Inter(ii);
592 void GeomFill_CircularBlendFunc::SetInterval(const Standard_Real First,
593 const Standard_Real Last)
595 Standard_Real Eps = Precision::PConfusion();
596 myTPath = myPath->Trim(First, Last, Eps);
597 myTCurve1 = myCurve1->Trim(First, Last, Eps);
598 myTCurve2 = myCurve2->Trim(First, Last, Eps);
602 void GeomFill_CircularBlendFunc::GetTolerance(const Standard_Real BoundTol,
603 const Standard_Real SurfTol,
604 const Standard_Real AngleTol,
605 TColStd_Array1OfReal& Tol3d) const
607 Standard_Integer low = Tol3d.Lower() , up=Tol3d.Upper();
610 Tol= GeomFill::GetTolerance(myTConv, minang,
611 myRadius, AngleTol, SurfTol);
613 Tol3d(low+1) = Tol3d(up-1) = Min(Tol, SurfTol);
614 Tol3d(low) = Tol3d(up) = Min(Tol, BoundTol);
618 void GeomFill_CircularBlendFunc::SetTolerance(const Standard_Real,
624 gp_Pnt GeomFill_CircularBlendFunc::BarycentreOfSurf() const
629 Standard_Real GeomFill_CircularBlendFunc::MaximalSection() const
631 return maxang*myRadius;
634 void GeomFill_CircularBlendFunc::
635 GetMinimalWeight(TColStd_Array1OfReal& Weigths) const
637 GeomFill::GetMinimalWeights(myTConv, minang, maxang, Weigths);