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.
18 #include <Adaptor3d_HCurve.hxx>
20 #include <GCPnts_QuasiUniformDeflection.hxx>
21 #include <Geom_BSplineCurve.hxx>
22 #include <Geom_Circle.hxx>
23 #include <Geom_Curve.hxx>
24 #include <Geom_TrimmedCurve.hxx>
25 #include <GeomAdaptor.hxx>
26 #include <GeomAdaptor_Curve.hxx>
27 #include <GeomConvert.hxx>
28 #include <GeomFill_Profiler.hxx>
29 #include <GeomFill_SweepSectionGenerator.hxx>
34 #include <gp_Trsf.hxx>
36 #include <Precision.hxx>
37 #include <Standard_RangeError.hxx>
38 #include <TColStd_Array1OfReal.hxx>
42 #include <DrawTrSurf.hxx>
43 #include <Geom_BSplineCurve.hxx>
44 static Standard_Boolean Affich = Standard_False;
45 static Standard_Integer NbSECTIONS = 0;
48 //=======================================================================
49 //function : GeomFill_SweepSectionGenerator
51 //=======================================================================
53 GeomFill_SweepSectionGenerator::GeomFill_SweepSectionGenerator()
55 myIsDone(Standard_False),
58 myPolynomial(Standard_False)
63 //=======================================================================
64 //function : GeomFill_SweepSectionGenerator
66 //=======================================================================
68 GeomFill_SweepSectionGenerator::GeomFill_SweepSectionGenerator
69 (const Handle(Geom_Curve)& Path,
70 const Standard_Real Radius)
76 //=======================================================================
77 //function : GeomFill_SweepSectionGenerator
79 //=======================================================================
81 GeomFill_SweepSectionGenerator::GeomFill_SweepSectionGenerator
82 (const Handle(Geom_Curve)& Path,
83 const Handle(Geom_Curve)& FirstSect)
89 //=======================================================================
90 //function : GeomFill_SweepSectionGenerator
92 //=======================================================================
94 GeomFill_SweepSectionGenerator::GeomFill_SweepSectionGenerator
95 (const Handle(Geom_Curve)& Path,
96 const Handle(Geom_Curve)& FirstSect,
97 const Handle(Geom_Curve)& LastSect )
99 Init(Path,FirstSect,LastSect);
103 //=======================================================================
104 //function : GeomFill_SweepSectionGenerator
106 //=======================================================================
108 GeomFill_SweepSectionGenerator::GeomFill_SweepSectionGenerator
109 (const Handle(Adaptor3d_HCurve)& Path,
110 const Handle(Adaptor3d_HCurve)& Curve1,
111 const Handle(Adaptor3d_HCurve)& Curve2,
112 const Standard_Real Radius)
114 Init(Path,Curve1,Curve2,Radius);
118 //=======================================================================
121 //=======================================================================
123 void GeomFill_SweepSectionGenerator::Init(const Handle(Geom_Curve)& Path,
124 const Standard_Real Radius)
126 myIsDone = Standard_False;
128 GeomAdaptor_Curve ThePath(Path);
130 if (ThePath.GetType() == GeomAbs_Circle) {
132 myCircPathAxis = ThePath.Circle().Axis();
136 if ( Path->IsKind(STANDARD_TYPE(Geom_BSplineCurve))) {
137 myPath = Handle(Geom_BSplineCurve)::DownCast(Path->Copy());
140 myPath = GeomConvert::CurveToBSplineCurve(Path);
145 //=======================================================================
148 //=======================================================================
149 void GeomFill_SweepSectionGenerator::Init
150 (const Handle(Geom_Curve)& Path,
151 const Handle(Geom_Curve)& FirstSect)
153 myIsDone = Standard_False;
155 GeomAdaptor_Curve ThePath(Path);
157 if (ThePath.GetType() == GeomAbs_Circle) {
158 myCircPathAxis = ThePath.Circle().Axis();
164 if ( Path->IsKind(STANDARD_TYPE(Geom_BSplineCurve))) {
165 myPath = Handle(Geom_BSplineCurve)::DownCast(Path->Copy());
168 myPath = GeomConvert::CurveToBSplineCurve(Path);
170 if ( FirstSect->IsKind(STANDARD_TYPE(Geom_BSplineCurve))) {
171 myFirstSect = Handle(Geom_BSplineCurve)::DownCast(FirstSect->Copy());
175 myFirstSect = GeomConvert::CurveToBSplineCurve(FirstSect,
176 Convert_QuasiAngular);
178 if ( myFirstSect->IsPeriodic()) myFirstSect->SetNotPeriodic();
182 //=======================================================================
185 //=======================================================================
187 void GeomFill_SweepSectionGenerator::Init
188 (const Handle(Geom_Curve)& Path,
189 const Handle(Geom_Curve)& FirstSect,
190 const Handle(Geom_Curve)& LastSect )
192 myIsDone = Standard_False;
194 GeomAdaptor_Curve ThePath(Path);
196 if (ThePath.GetType() == GeomAbs_Circle) {
198 myCircPathAxis = ThePath.Circle().Axis();
203 if ( Path->IsKind(STANDARD_TYPE(Geom_BSplineCurve))) {
204 myPath = Handle(Geom_BSplineCurve)::DownCast(Path->Copy());
207 myPath = GeomConvert::CurveToBSplineCurve(Path);
211 if ( FirstSect->IsKind(STANDARD_TYPE(Geom_BSplineCurve))) {
212 myFirstSect = Handle(Geom_BSplineCurve)::DownCast(FirstSect->Copy());
215 myFirstSect = GeomConvert::CurveToBSplineCurve(FirstSect,
216 Convert_QuasiAngular);
218 if ( LastSect->IsKind(STANDARD_TYPE(Geom_BSplineCurve))) {
219 myLastSect = Handle(Geom_BSplineCurve)::DownCast(LastSect->Copy());
222 myLastSect = GeomConvert::CurveToBSplineCurve(LastSect,
223 Convert_QuasiAngular);
226 if ( myFirstSect->IsPeriodic()) myFirstSect->SetNotPeriodic();
227 if ( myLastSect->IsPeriodic()) myLastSect->SetNotPeriodic();
232 GeomFill_Profiler Profil;
233 Profil.AddCurve(myFirstSect);
234 Profil.AddCurve(myLastSect);
235 Profil.Perform(Precision::Confusion());
237 myFirstSect = Handle(Geom_BSplineCurve)::DownCast(Profil.Curve(1));
238 myLastSect = Handle(Geom_BSplineCurve)::DownCast(Profil.Curve(2));
242 //=======================================================================
245 //=======================================================================
247 void GeomFill_SweepSectionGenerator::Init
248 (const Handle(Adaptor3d_HCurve)& Path,
249 const Handle(Adaptor3d_HCurve)& Curve1,
250 const Handle(Adaptor3d_HCurve)& Curve2,
251 const Standard_Real Radius)
253 myIsDone = Standard_False;
257 Handle(Geom_Curve) CC = GeomAdaptor::MakeCurve(Path->Curve());
258 myPath = GeomConvert::CurveToBSplineCurve(CC);
260 myAdpFirstSect = Curve1;
261 myAdpLastSect = Curve2;
265 //=======================================================================
268 //=======================================================================
270 void GeomFill_SweepSectionGenerator::Perform(const Standard_Boolean Polynomial)
272 myPolynomial = Polynomial;
274 // eval myNbSections.
275 Standard_Integer NSpans = myPath->NbKnots()-1;
277 myNbSections = 21 * NSpans;
281 Standard_Real U1 = myPath->FirstParameter();
282 Standard_Real U2 = myPath->LastParameter();
284 GCPnts_QuasiUniformDeflection Samp;
285 // Calcul de la longueur approximative de la courbe
286 GeomAdaptor_Curve AdpPath(myPath);
287 gp_Pnt P1 = AdpPath.Value(U1);
288 gp_Pnt P2 = AdpPath.Value((U1+U2)/2.);
289 gp_Pnt P3 = AdpPath.Value(U2);
290 Standard_Real Length =
291 P1.Distance(P2) + P2.Distance(P3);
292 Standard_Real Fleche = 1.e-5 * Length;
293 Samp.Initialize(AdpPath,Fleche);
295 if ( Samp.IsDone() && (Samp.NbPoints() > myNbSections) ) {
296 myNbSections = Samp.NbPoints();
298 // the transformations are calculate on differents points of <myPath>
299 // corresponding to the path parameter uniformly reparted.
300 Standard_Real DeltaU = (U2-U1)/(Standard_Real)(myNbSections-1);
301 TColStd_Array1OfReal Parameters(1,myNbSections);
302 // Parameters(1) = U1;
303 // for (Standard_Integer i = 2; i < myNbSections; i++) {
304 // Parameters(i) = U1 + (i-1) * DeltaU;
306 // Parameters(myNbSections) = U2;
309 for (Standard_Integer i = 2; i < myNbSections; i++) {
310 Parameters(i) = (i-1) * DeltaU;
312 Parameters(myNbSections) = U2 - U1;
316 gp_Trsf TR, cumulTR, Trans;
318 myPath->D1( U1, PRef, D1Ref);
320 if ( ( myType == 1) || (myType == 4) ) {
321 // We create a circle with radius <myRadius>. This axis is create with
322 // main direction <DRef> (first derivate vector of <myPath> on the first
323 // point <PRef> ). This circle is, after transform to BSpline curve,
324 // put in <myFirstSect>.
326 gp_Ax2 CircleAxis (PRef,D1Ref);
328 Handle(Geom_Circle) Circ = new Geom_Circle( CircleAxis, myRadius);
330 myFirstSect = GeomConvert::CurveToBSplineCurve(Circ);
331 // le cercle est segmente car AppBlend_AppSurf ne gere
332 // pas les courbes periodiques.
333 myFirstSect->Segment(0., 2.*M_PI);
335 Handle(Geom_TrimmedCurve) Circ =
336 new Geom_TrimmedCurve(new Geom_Circle( CircleAxis, myRadius),
339 myFirstSect = GeomConvert::CurveToBSplineCurve(Circ,Convert_QuasiAngular);
342 if (myType <= 3 && myType >=1 ) {
344 for (Standard_Integer i = 2; i <= myNbSections; i++) {
346 U = Parameters(i) + U1;
347 if (i == myNbSections) U = U2;
349 myPath->D1( U, P, D1);
351 // Eval the translation between the (i-1) section and the i-th.
352 Trans.SetTranslation(PRef, P);
355 if (! D1Ref.IsParallel(D1, Precision::Angular())) {
356 // Eval the Rotation between (i-1) section and the i-th.
357 Rot.SetRotation(gp_Ax1(P, gp_Dir(D1Ref^D1)),
358 D1Ref.AngleWithRef(D1, D1Ref^D1));
361 if (D1Ref.IsOpposite(D1, Precision::Angular()))
363 std::cout <<"Que fais-je ???? " << std::endl;
366 // TR is the transformation between (i-1) section and the i-th.
368 // cumulTR is the transformation between <myFirstSec> and
370 cumulTR = TR * cumulTR;
372 myTrsfs.Append(cumulTR);
378 else if ( myType != 0) {
379 for (Standard_Integer i = 2; i<= myNbSections; i++) {
380 cumulTR.SetRotation(myCircPathAxis, Parameters(i));
381 myTrsfs.Append(cumulTR);
385 myIsDone = Standard_True;
388 //=======================================================================
389 //function : GetShape
391 //=======================================================================
393 void GeomFill_SweepSectionGenerator::GetShape
394 (Standard_Integer& NbPoles,
395 Standard_Integer& NbKnots,
396 Standard_Integer& Degree,
397 Standard_Integer& NbPoles2d) const
408 NbPoles = myFirstSect->NbPoles();
409 NbKnots = myFirstSect->NbKnots();
410 Degree = myFirstSect->Degree();
412 else { // myType == 0
421 //=======================================================================
424 //=======================================================================
426 void GeomFill_SweepSectionGenerator::Knots(TColStd_Array1OfReal& TKnots) const
430 Standard_Real U = 2.*M_PI/3.;
431 for ( Standard_Integer i = 1; i <= 4; i++)
432 TKnots(i) = ( i-1) * U;
437 myFirstSect->Knots(TKnots);
447 //=======================================================================
450 //=======================================================================
452 void GeomFill_SweepSectionGenerator::Mults(TColStd_Array1OfInteger& TMults)
457 TMults( 1) = TMults( 4) = 3;
458 TMults( 2) = TMults( 3) = 2;
463 myFirstSect->Multiplicities(TMults);
466 TMults( 1) = TMults( 2) = 7;
472 //=======================================================================
475 //=======================================================================
477 Standard_Boolean GeomFill_SweepSectionGenerator::Section
478 (const Standard_Integer P,
479 TColgp_Array1OfPnt& Poles,
480 TColgp_Array1OfVec& DPoles,
481 TColgp_Array1OfPnt2d& Poles2d,
482 TColgp_Array1OfVec2d& , //DPoles2d,
483 TColStd_Array1OfReal& Weigths,
484 TColStd_Array1OfReal& DWeigths
487 Section( P, Poles, Poles2d, Weigths);
489 // pour les tuyaux sur aretes pour l'instant on ne calcule pas les derivees
490 if ( myType == 0 ) return Standard_False; // a voir pour mieux.
492 // calcul des derivees sur la surface
493 // on calcule les derivees en approximant le path au voisinage du point
494 // P(u) par le cercle osculateur au path .
496 // calcul du cercle osculateur.
500 U = myPath->FirstParameter();
502 else if ( P == myNbSections ) {
503 U = myPath->LastParameter();
506 return Standard_False;
511 myPath->D2(U,Pt,D1,D2);
512 Standard_Real l = D1.Magnitude();
514 if ( l < Epsilon(1.))
515 return Standard_False;
518 Standard_Real m = D2.Dot(T);
519 gp_Vec D = D2 - m * T;
520 Standard_Real c = D.Magnitude() / (l*l);
522 if ( c < Epsilon(1.)) {
523 // null curvature : equivalent to a translation of the section
524 for (Standard_Integer i = 1; i <= myFirstSect->NbPoles(); i++) {
530 gp_Pnt Q = Pt.Translated( (1./c) * gp_Vec(N));
533 for ( Standard_Integer i = 1; i <= myFirstSect->NbPoles(); i++) {
534 V = gp_Vec(Q, Poles(i));
537 DPoles(i) = x * gp_Vec(N) - y * gp_Vec(T);
538 if ( DPoles(i).Magnitude() > Epsilon(1.)) {
539 DPoles(i).Normalize();
540 DPoles(i) *= Sqrt( x*x + y*y);
545 for ( Standard_Integer i = 1; i <= myFirstSect->NbPoles(); i++) {
549 return Standard_True;
553 //=======================================================================
556 //=======================================================================
558 void GeomFill_SweepSectionGenerator::Section
559 (const Standard_Integer P,
560 TColgp_Array1OfPnt& Poles,
561 TColgp_Array1OfPnt2d& , //Poles2d,
562 TColStd_Array1OfReal& Weigths) const
565 myFirstSect->Poles(Poles);
566 myFirstSect->Weights(Weigths);
569 cumulTR = myTrsfs(P - 1);
570 // <cumulTR> transform <myFirstSect> to the P ieme Section. In fact
571 // each points of the array <poles> will be transformed.
573 if ( (myType == 3 ) || (myType == 6) ){
574 for (Standard_Integer i = 1; i <= myFirstSect->NbPoles(); i++) {
575 Poles(i).SetXYZ( (myNbSections - P) * myFirstSect->Pole(i).XYZ() +
576 (P - 1) * myLastSect->Pole(i).XYZ() );
577 Poles(i).SetXYZ( Poles(i).XYZ() / (myNbSections - 1));
579 Weigths(i) = (myNbSections - P) * myFirstSect->Weight(i) +
580 (P - 1) * myLastSect->Weight(i);
581 Weigths(i) /= myNbSections - 1;
585 for (Standard_Integer i = 1; i<=Poles.Length(); i++)
586 Poles(i).Transform(cumulTR);
591 sprintf(name,"SECTION_%d",++NbSECTIONS);
592 DrawTrSurf::Set(name,myFirstSect->Transformed(cumulTR));
598 Standard_Real Coef = (P -1. ) / ( myNbSections - 1.);
600 ( 1- Coef) * myAdpPath->FirstParameter() +
601 Coef * myAdpPath->LastParameter();
603 gp_Pnt PPath = myAdpPath->Value(U);
605 Standard_Real Alpha = U - myAdpPath->FirstParameter();
606 Alpha /= myAdpPath->LastParameter() - myAdpPath->FirstParameter();
609 ( 1- Alpha) * myAdpFirstSect->FirstParameter() +
610 Alpha * myAdpFirstSect->LastParameter();
612 gp_Pnt P1 = myAdpFirstSect->Value(U1);
615 ( 1- Alpha) * myAdpLastSect->FirstParameter() +
616 Alpha * myAdpLastSect->LastParameter();
618 gp_Pnt P2 = myAdpLastSect->Value(U2);
622 if ( P1.Distance(P2) < Precision::Confusion()) {
627 gp_Vec(PPath,P1) ^ gp_Vec(PPath,P2),
629 Angle = ElCLib::CircleParameter(Axis,P2);
633 if (Standard_False) {
634 gp_Vec dummyD1 = myAdpPath->DN(U,1);
635 gp_Vec dummyTg = Axis.Direction();
636 Standard_Real Cos = dummyD1.Dot(dummyTg);
637 if ( Cos > 0.) std::cout << "+" ;
638 else std::cout << "-" ;
642 if ( Angle < Precision::Angular()) {
643 for ( Standard_Integer i = 1; i <= Poles.Upper(); i++) {
649 Handle(Geom_Circle) Circ =
650 new Geom_Circle( Axis, myRadius);
651 Handle(Geom_TrimmedCurve) CT =
652 new Geom_TrimmedCurve(Circ, 0., Angle);
653 Handle(Geom_BSplineCurve) BS;
655 BS = GeomConvert::CurveToBSplineCurve( CT, Convert_Polynomial);
657 BS = GeomConvert::CurveToBSplineCurve( CT, Convert_QuasiAngular);
662 sprintf(name,"SECTION_%d",++NbSECTIONS);
663 DrawTrSurf::Set(name,BS);
668 BS->Weights(Weigths);
673 //=======================================================================
674 //function : Transformation
676 //=======================================================================
677 const gp_Trsf& GeomFill_SweepSectionGenerator::Transformation
678 (const Standard_Integer Index) const
680 if (Index > myTrsfs.Length())
681 throw Standard_RangeError("GeomFill_SweepSectionGenerator::Transformation");
683 return myTrsfs(Index);
687 //=======================================================================
688 //function : Parameter
690 //=======================================================================
692 Standard_Real GeomFill_SweepSectionGenerator::Parameter
693 (const Standard_Integer P) const
696 return myPath->FirstParameter();
698 else if (P == myNbSections) {
699 return myPath->LastParameter();
702 Standard_Real U1 = myPath->FirstParameter();
703 Standard_Real U2 = myPath->LastParameter();
704 Standard_Real prm = ((myNbSections-P)*U1 + (P-1)*U2)/
705 (Standard_Real)(myNbSections-1);