1 // Created on: 1994-02-28
2 // Created by: Bruno DUMORTIER
3 // Copyright (c) 1994-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.
17 #include <GeomFill_SweepSectionGenerator.ixx>
19 #include <GeomFill_Profiler.hxx>
23 #include <gp_Trsf.hxx>
27 #include <Geom_TrimmedCurve.hxx>
28 #include <Geom_Circle.hxx>
29 #include <GeomConvert.hxx>
30 #include <Precision.hxx>
32 #include <GeomAdaptor.hxx>
33 #include <GeomAdaptor_Curve.hxx>
34 #include <GCPnts_QuasiUniformDeflection.hxx>
35 #include <TColStd_Array1OfReal.hxx>
40 #include <DrawTrSurf.hxx>
41 static Standard_Boolean Affich = Standard_False;
42 static Standard_Integer NbSECTIONS = 0;
46 //=======================================================================
47 //function : GeomFill_SweepSectionGenerator
49 //=======================================================================
51 GeomFill_SweepSectionGenerator::GeomFill_SweepSectionGenerator()
53 myIsDone = Standard_False;
57 //=======================================================================
58 //function : GeomFill_SweepSectionGenerator
60 //=======================================================================
62 GeomFill_SweepSectionGenerator::GeomFill_SweepSectionGenerator
63 (const Handle(Geom_Curve)& Path,
64 const Standard_Real Radius)
70 //=======================================================================
71 //function : GeomFill_SweepSectionGenerator
73 //=======================================================================
75 GeomFill_SweepSectionGenerator::GeomFill_SweepSectionGenerator
76 (const Handle(Geom_Curve)& Path,
77 const Handle(Geom_Curve)& FirstSect)
83 //=======================================================================
84 //function : GeomFill_SweepSectionGenerator
86 //=======================================================================
88 GeomFill_SweepSectionGenerator::GeomFill_SweepSectionGenerator
89 (const Handle(Geom_Curve)& Path,
90 const Handle(Geom_Curve)& FirstSect,
91 const Handle(Geom_Curve)& LastSect )
93 Init(Path,FirstSect,LastSect);
97 //=======================================================================
98 //function : GeomFill_SweepSectionGenerator
100 //=======================================================================
102 GeomFill_SweepSectionGenerator::GeomFill_SweepSectionGenerator
103 (const Handle(Adaptor3d_HCurve)& Path,
104 const Handle(Adaptor3d_HCurve)& Curve1,
105 const Handle(Adaptor3d_HCurve)& Curve2,
106 const Standard_Real Radius)
108 Init(Path,Curve1,Curve2,Radius);
112 //=======================================================================
115 //=======================================================================
117 void GeomFill_SweepSectionGenerator::Init(const Handle(Geom_Curve)& Path,
118 const Standard_Real Radius)
120 myIsDone = Standard_False;
122 GeomAdaptor_Curve ThePath(Path);
124 if (ThePath.GetType() == GeomAbs_Circle) {
126 myCircPathAxis = ThePath.Circle().Axis();
130 if ( Path->IsKind(STANDARD_TYPE(Geom_BSplineCurve))) {
131 myPath = Handle(Geom_BSplineCurve)::DownCast(Path->Copy());
134 myPath = GeomConvert::CurveToBSplineCurve(Path);
139 //=======================================================================
142 //=======================================================================
143 void GeomFill_SweepSectionGenerator::Init
144 (const Handle(Geom_Curve)& Path,
145 const Handle(Geom_Curve)& FirstSect)
147 myIsDone = Standard_False;
149 GeomAdaptor_Curve ThePath(Path);
151 if (ThePath.GetType() == GeomAbs_Circle) {
152 myCircPathAxis = ThePath.Circle().Axis();
158 if ( Path->IsKind(STANDARD_TYPE(Geom_BSplineCurve))) {
159 myPath = Handle(Geom_BSplineCurve)::DownCast(Path->Copy());
162 myPath = GeomConvert::CurveToBSplineCurve(Path);
164 if ( FirstSect->IsKind(STANDARD_TYPE(Geom_BSplineCurve))) {
165 myFirstSect = Handle(Geom_BSplineCurve)::DownCast(FirstSect->Copy());
169 myFirstSect = GeomConvert::CurveToBSplineCurve(FirstSect,
170 Convert_QuasiAngular);
172 if ( myFirstSect->IsPeriodic()) myFirstSect->SetNotPeriodic();
176 //=======================================================================
179 //=======================================================================
181 void GeomFill_SweepSectionGenerator::Init
182 (const Handle(Geom_Curve)& Path,
183 const Handle(Geom_Curve)& FirstSect,
184 const Handle(Geom_Curve)& LastSect )
186 myIsDone = Standard_False;
188 GeomAdaptor_Curve ThePath(Path);
190 if (ThePath.GetType() == GeomAbs_Circle) {
192 myCircPathAxis = ThePath.Circle().Axis();
197 if ( Path->IsKind(STANDARD_TYPE(Geom_BSplineCurve))) {
198 myPath = Handle(Geom_BSplineCurve)::DownCast(Path->Copy());
201 myPath = GeomConvert::CurveToBSplineCurve(Path);
205 if ( FirstSect->IsKind(STANDARD_TYPE(Geom_BSplineCurve))) {
206 myFirstSect = Handle(Geom_BSplineCurve)::DownCast(FirstSect->Copy());
209 myFirstSect = GeomConvert::CurveToBSplineCurve(FirstSect,
210 Convert_QuasiAngular);
212 if ( LastSect->IsKind(STANDARD_TYPE(Geom_BSplineCurve))) {
213 myLastSect = Handle(Geom_BSplineCurve)::DownCast(LastSect->Copy());
216 myLastSect = GeomConvert::CurveToBSplineCurve(LastSect,
217 Convert_QuasiAngular);
220 if ( myFirstSect->IsPeriodic()) myFirstSect->SetNotPeriodic();
221 if ( myLastSect->IsPeriodic()) myLastSect->SetNotPeriodic();
226 GeomFill_Profiler Profil;
227 Profil.AddCurve(myFirstSect);
228 Profil.AddCurve(myLastSect);
229 Profil.Perform(Precision::Confusion());
231 myFirstSect = Handle(Geom_BSplineCurve)::DownCast(Profil.Curve(1));
232 myLastSect = Handle(Geom_BSplineCurve)::DownCast(Profil.Curve(2));
236 //=======================================================================
239 //=======================================================================
241 void GeomFill_SweepSectionGenerator::Init
242 (const Handle(Adaptor3d_HCurve)& Path,
243 const Handle(Adaptor3d_HCurve)& Curve1,
244 const Handle(Adaptor3d_HCurve)& Curve2,
245 const Standard_Real Radius)
247 myIsDone = Standard_False;
251 Handle(Geom_Curve) CC = GeomAdaptor::MakeCurve(Path->Curve());
252 myPath = GeomConvert::CurveToBSplineCurve(CC);
254 myAdpFirstSect = Curve1;
255 myAdpLastSect = Curve2;
259 //=======================================================================
262 //=======================================================================
264 void GeomFill_SweepSectionGenerator::Perform(const Standard_Boolean Polynomial)
266 myPolynomial = Polynomial;
268 // eval myNbSections.
269 Standard_Integer NSpans = myPath->NbKnots()-1;
271 myNbSections = 21 * NSpans;
275 Standard_Real U1 = myPath->FirstParameter();
276 Standard_Real U2 = myPath->LastParameter();
278 GCPnts_QuasiUniformDeflection Samp;
279 // Calcul de la longueur approximative de la courbe
280 GeomAdaptor_Curve AdpPath(myPath);
281 gp_Pnt P1 = AdpPath.Value(U1);
282 gp_Pnt P2 = AdpPath.Value((U1+U2)/2.);
283 gp_Pnt P3 = AdpPath.Value(U2);
284 Standard_Real Length =
285 P1.Distance(P2) + P2.Distance(P3);
286 Standard_Real Fleche = 1.e-5 * Length;
287 Samp.Initialize(AdpPath,Fleche);
289 if ( Samp.IsDone() && (Samp.NbPoints() > myNbSections) ) {
290 myNbSections = Samp.NbPoints();
292 // the transformations are calculate on differents points of <myPath>
293 // corresponding to the path parameter uniformly reparted.
294 Standard_Real DeltaU = (U2-U1)/(Standard_Real)(myNbSections-1);
295 TColStd_Array1OfReal Parameters(1,myNbSections);
296 // Parameters(1) = U1;
297 // for (Standard_Integer i = 2; i < myNbSections; i++) {
298 // Parameters(i) = U1 + (i-1) * DeltaU;
300 // Parameters(myNbSections) = U2;
303 for (Standard_Integer i = 2; i < myNbSections; i++) {
304 Parameters(i) = (i-1) * DeltaU;
306 Parameters(myNbSections) = U2 - U1;
310 gp_Trsf TR, cumulTR, Trans;
312 myPath->D1( U1, PRef, D1Ref);
314 if ( ( myType == 1) || (myType == 4) ) {
315 // We create a circle with radius <myRadius>. This axis is create with
316 // main direction <DRef> (first derivate vector of <myPath> on the first
317 // point <PRef> ). This circle is, after transform to BSpline curve,
318 // put in <myFirstSect>.
320 gp_Ax2 CircleAxis (PRef,D1Ref);
322 Handle(Geom_Circle) Circ = new Geom_Circle( CircleAxis, myRadius);
324 myFirstSect = GeomConvert::CurveToBSplineCurve(Circ);
325 // le cercle est segmente car AppBlend_AppSurf ne gere
326 // pas les courbes periodiques.
327 myFirstSect->Segment(0., 2.*M_PI);
329 Handle(Geom_TrimmedCurve) Circ =
330 new Geom_TrimmedCurve(new Geom_Circle( CircleAxis, myRadius),
333 myFirstSect = GeomConvert::CurveToBSplineCurve(Circ,Convert_QuasiAngular);
336 if (myType <= 3 && myType >=1 ) {
338 for (Standard_Integer i = 2; i <= myNbSections; i++) {
340 U = Parameters(i) + U1;
341 if (i == myNbSections) U = U2;
343 myPath->D1( U, P, D1);
345 // Eval the translation between the (i-1) section and the i-th.
346 Trans.SetTranslation(PRef, P);
349 if (! D1Ref.IsParallel(D1, Precision::Angular())) {
350 // Eval the Rotation between (i-1) section and the i-th.
351 Rot.SetRotation(gp_Ax1(P, gp_Dir(D1Ref^D1)),
352 D1Ref.AngleWithRef(D1, D1Ref^D1));
355 if (D1Ref.IsOpposite(D1, Precision::Angular()))
357 cout <<"Que fais-je ???? " << endl;
360 // TR is the transformation between (i-1) section and the i-th.
362 // cumulTR is the transformation between <myFirstSec> and
364 cumulTR = TR * cumulTR;
366 myTrsfs.Append(cumulTR);
372 else if ( myType != 0) {
373 for (Standard_Integer i = 2; i<= myNbSections; i++) {
374 cumulTR.SetRotation(myCircPathAxis, Parameters(i));
375 myTrsfs.Append(cumulTR);
379 myIsDone = Standard_True;
382 //=======================================================================
383 //function : GetShape
385 //=======================================================================
387 void GeomFill_SweepSectionGenerator::GetShape
388 (Standard_Integer& NbPoles,
389 Standard_Integer& NbKnots,
390 Standard_Integer& Degree,
391 Standard_Integer& NbPoles2d) const
402 NbPoles = myFirstSect->NbPoles();
403 NbKnots = myFirstSect->NbKnots();
404 Degree = myFirstSect->Degree();
406 else { // myType == 0
415 //=======================================================================
418 //=======================================================================
420 void GeomFill_SweepSectionGenerator::Knots(TColStd_Array1OfReal& TKnots) const
424 Standard_Real U = 2.*M_PI/3.;
425 for ( Standard_Integer i = 1; i <= 4; i++)
426 TKnots(i) = ( i-1) * U;
431 myFirstSect->Knots(TKnots);
441 //=======================================================================
444 //=======================================================================
446 void GeomFill_SweepSectionGenerator::Mults(TColStd_Array1OfInteger& TMults)
451 TMults( 1) = TMults( 4) = 3;
452 TMults( 2) = TMults( 3) = 2;
457 myFirstSect->Multiplicities(TMults);
460 TMults( 1) = TMults( 2) = 7;
466 //=======================================================================
469 //=======================================================================
471 Standard_Boolean GeomFill_SweepSectionGenerator::Section
472 (const Standard_Integer P,
473 TColgp_Array1OfPnt& Poles,
474 TColgp_Array1OfVec& DPoles,
475 TColgp_Array1OfPnt2d& Poles2d,
476 TColgp_Array1OfVec2d& , //DPoles2d,
477 TColStd_Array1OfReal& Weigths,
478 TColStd_Array1OfReal& DWeigths
481 Section( P, Poles, Poles2d, Weigths);
483 // pour les tuyaux sur aretes pour l'instant on ne calcule pas les derivees
484 if ( myType == 0 ) return Standard_False; // a voir pour mieux.
486 // calcul des derivees sur la surface
487 // on calcule les derivees en approximant le path au voisinage du point
488 // P(u) par le cercle osculateur au path .
490 // calcul du cercle osculateur.
494 U = myPath->FirstParameter();
496 else if ( P == myNbSections ) {
497 U = myPath->LastParameter();
500 return Standard_False;
505 myPath->D2(U,Pt,D1,D2);
506 Standard_Real l = D1.Magnitude();
508 if ( l < Epsilon(1.))
509 return Standard_False;
512 Standard_Real m = D2.Dot(T);
513 gp_Vec D = D2 - m * T;
514 Standard_Real c = D.Magnitude() / (l*l);
516 if ( c < Epsilon(1.)) {
517 // null curvature : equivalent to a translation of the section
518 for (Standard_Integer i = 1; i <= myFirstSect->NbPoles(); i++) {
524 gp_Pnt Q = Pt.Translated( (1./c) * gp_Vec(N));
527 for ( Standard_Integer i = 1; i <= myFirstSect->NbPoles(); i++) {
528 V = gp_Vec(Q, Poles(i));
531 DPoles(i) = x * gp_Vec(N) - y * gp_Vec(T);
532 if ( DPoles(i).Magnitude() > Epsilon(1.)) {
533 DPoles(i).Normalize();
534 DPoles(i) *= Sqrt( x*x + y*y);
539 for ( Standard_Integer i = 1; i <= myFirstSect->NbPoles(); i++) {
543 return Standard_True;
547 //=======================================================================
550 //=======================================================================
552 void GeomFill_SweepSectionGenerator::Section
553 (const Standard_Integer P,
554 TColgp_Array1OfPnt& Poles,
555 TColgp_Array1OfPnt2d& , //Poles2d,
556 TColStd_Array1OfReal& Weigths) const
559 myFirstSect->Poles(Poles);
560 myFirstSect->Weights(Weigths);
563 cumulTR = myTrsfs(P - 1);
564 // <cumulTR> transform <myFirstSect> to the P ieme Section. In fact
565 // each points of the array <poles> will be transformed.
567 if ( (myType == 3 ) || (myType == 6) ){
568 for (Standard_Integer i = 1; i <= myFirstSect->NbPoles(); i++) {
569 Poles(i).SetXYZ( (myNbSections - P) * myFirstSect->Pole(i).XYZ() +
570 (P - 1) * myLastSect->Pole(i).XYZ() );
571 Poles(i).SetXYZ( Poles(i).XYZ() / (myNbSections - 1));
573 Weigths(i) = (myNbSections - P) * myFirstSect->Weight(i) +
574 (P - 1) * myLastSect->Weight(i);
575 Weigths(i) /= myNbSections - 1;
579 for (Standard_Integer i = 1; i<=Poles.Length(); i++)
580 Poles(i).Transform(cumulTR);
585 sprintf(name,"SECTION_%d",++NbSECTIONS);
586 DrawTrSurf::Set(name,myFirstSect->Transformed(cumulTR));
592 Standard_Real Coef = (P -1. ) / ( myNbSections - 1.);
594 ( 1- Coef) * myAdpPath->FirstParameter() +
595 Coef * myAdpPath->LastParameter();
597 gp_Pnt PPath = myAdpPath->Value(U);
599 Standard_Real Alpha = U - myAdpPath->FirstParameter();
600 Alpha /= myAdpPath->LastParameter() - myAdpPath->FirstParameter();
603 ( 1- Alpha) * myAdpFirstSect->FirstParameter() +
604 Alpha * myAdpFirstSect->LastParameter();
606 gp_Pnt P1 = myAdpFirstSect->Value(U1);
609 ( 1- Alpha) * myAdpLastSect->FirstParameter() +
610 Alpha * myAdpLastSect->LastParameter();
612 gp_Pnt P2 = myAdpLastSect->Value(U2);
616 if ( P1.Distance(P2) < Precision::Confusion()) {
621 gp_Vec(PPath,P1) ^ gp_Vec(PPath,P2),
623 Angle = ElCLib::CircleParameter(Axis,P2);
627 if (Standard_False) {
628 gp_Vec dummyD1 = myAdpPath->DN(U,1);
629 gp_Vec dummyTg = Axis.Direction();
630 Standard_Real Cos = dummyD1.Dot(dummyTg);
631 if ( Cos > 0.) cout << "+" ;
636 if ( Angle < Precision::Angular()) {
637 for ( Standard_Integer i = 1; i <= Poles.Upper(); i++) {
643 Handle(Geom_Circle) Circ =
644 new Geom_Circle( Axis, myRadius);
645 Handle(Geom_TrimmedCurve) CT =
646 new Geom_TrimmedCurve(Circ, 0., Angle);
647 Handle(Geom_BSplineCurve) BS;
649 BS = GeomConvert::CurveToBSplineCurve( CT, Convert_Polynomial);
651 BS = GeomConvert::CurveToBSplineCurve( CT, Convert_QuasiAngular);
656 sprintf(name,"SECTION_%d",++NbSECTIONS);
657 DrawTrSurf::Set(name,BS);
662 BS->Weights(Weigths);
667 //=======================================================================
668 //function : Transformation
670 //=======================================================================
671 const gp_Trsf& GeomFill_SweepSectionGenerator::Transformation
672 (const Standard_Integer Index) const
674 if (Index > myTrsfs.Length())
675 Standard_RangeError::Raise
676 ("GeomFill_SweepSectionGenerator::Transformation");
678 return myTrsfs(Index);
682 //=======================================================================
683 //function : Parameter
685 //=======================================================================
687 Standard_Real GeomFill_SweepSectionGenerator::Parameter
688 (const Standard_Integer P) const
691 return myPath->FirstParameter();
693 else if (P == myNbSections) {
694 return myPath->LastParameter();
697 Standard_Real U1 = myPath->FirstParameter();
698 Standard_Real U2 = myPath->LastParameter();
699 Standard_Real prm = ((myNbSections-P)*U1 + (P-1)*U2)/
700 (Standard_Real)(myNbSections-1);