0028966: Coding Rules - remove Adaptor2d_HCurve2d, Adaptor3d_HCurve and Adaptor3d_HSu...
[occt.git] / src / GeomFill / GeomFill_Pipe.cxx
1 // Created on: 1994-04-13
2 // Created by: Joelle CHAUVET
3 // Copyright (c) 1994-1999 Matra Datavision
4 // Copyright (c) 1999-2014 OPEN CASCADE SAS
5 //
6 // This file is part of Open CASCADE Technology software library.
7 //
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.
13 //
14 // Alternatively, this file may be used under the terms of Open CASCADE
15 // commercial license or contractual agreement.
16
17 // Modified 22/09/1997 by PMN : Refonte du a l'introduction de F(t) dans
18 //             le cas des 2 lignes guides
19 // Modified:    Mon Jan 18 11:06:46 1999
20 //              dans Init(Path, Nsections) : 
21 //              les parametres des sections doivent etre strict. croissants
22 //              dans Init(Path, FirstSect, LastSect) :
23 //              il faut placer les 2 sections au debut de la trajectoire
24
25 #include <GeomFill_Pipe.hxx>
26
27 #include <Adaptor3d_CurveOnSurface.hxx>
28 #include <Adaptor3d_Curve.hxx>
29 #include <Approx_SweepApproximation.hxx>
30 #include <ElCLib.hxx>
31 #include <Geom2d_Curve.hxx>
32 #include <Geom2dAdaptor_Curve.hxx>
33 #include <Geom_BSplineCurve.hxx>
34 #include <Geom_BSplineSurface.hxx>
35 #include <Geom_Circle.hxx>
36 #include <Geom_ConicalSurface.hxx>
37 #include <Geom_Curve.hxx>
38 #include <Geom_CylindricalSurface.hxx>
39 #include <Geom_Line.hxx>
40 #include <Geom_Plane.hxx>
41 #include <Geom_RectangularTrimmedSurface.hxx>
42 #include <Geom_SphericalSurface.hxx>
43 #include <Geom_Surface.hxx>
44 #include <Geom_SurfaceOfLinearExtrusion.hxx>
45 #include <Geom_ToroidalSurface.hxx>
46 #include <Geom_TrimmedCurve.hxx>
47 #include <GeomAbs_SurfaceType.hxx>
48 #include <GeomAdaptor_Curve.hxx>
49 #include <GeomAdaptor_Surface.hxx>
50 #include <GeomFill_AppSweep.hxx>
51 #include <GeomFill_CircularBlendFunc.hxx>
52 #include <GeomFill_ConstantBiNormal.hxx>
53 #include <GeomFill_CorrectedFrenet.hxx>
54 #include <GeomFill_CurveAndTrihedron.hxx>
55 #include <GeomFill_Darboux.hxx>
56 #include <GeomFill_Fixed.hxx>
57 #include <GeomFill_Frenet.hxx>
58 #include <GeomFill_GuideTrihedronAC.hxx>
59 #include <GeomFill_GuideTrihedronPlan.hxx>
60 #include <GeomFill_Line.hxx>
61 #include <GeomFill_LocationGuide.hxx>
62 #include <GeomFill_LocationLaw.hxx>
63 #include <GeomFill_NSections.hxx>
64 #include <GeomFill_Profiler.hxx>
65 #include <GeomFill_SectionLaw.hxx>
66 #include <GeomFill_SectionPlacement.hxx>
67 #include <GeomFill_Sweep.hxx>
68 #include <GeomFill_SweepSectionGenerator.hxx>
69 #include <GeomFill_UniformSection.hxx>
70 #include <GeomLib.hxx>
71 #include <GeomLProp_CLProps.hxx>
72 #include <gp_Ax2.hxx>
73 #include <gp_Ax3.hxx>
74 #include <gp_Dir.hxx>
75 #include <gp_Torus.hxx>
76 #include <Precision.hxx>
77 #include <Standard_ConstructionError.hxx>
78 #include <TColGeom_SequenceOfCurve.hxx>
79 #include <TColgp_Array1OfPnt.hxx>
80
81 #include <stdio.h>
82 #ifdef OCCT_DEBUG
83 static Standard_Boolean Affich = Standard_False;
84 static Standard_Integer NbSections = 0;
85 #endif
86
87 #ifdef DRAW
88 #include <DrawTrSurf.hxx>
89 #include <Geom_Curve.hxx>
90 #endif
91
92 static Standard_Boolean CheckSense(const TColGeom_SequenceOfCurve& Seq1,
93                                          TColGeom_SequenceOfCurve& Seq2)
94 {
95   // initialisation
96   Standard_Boolean no_sing = Standard_True;
97   Seq2.Clear();
98
99   Handle(Geom_Curve) C1 = Seq1.Value(1);
100   Standard_Real f = C1->FirstParameter(), l = C1->LastParameter();
101   Standard_Integer iP, NP = 21;
102   TColgp_Array1OfPnt Tab(1,NP);
103   Standard_Real u = f, h = Abs(f-l) / 20.;
104   for (iP=1;iP<=NP;iP++) {
105     C1->D0(u,Tab(iP));
106     u += h;
107     if ((u-f)*(u-l)>0.0) u = l;
108   }
109   gp_Ax2 AxeRef, Axe;
110   gp_Pnt Pos;
111   Standard_Boolean sing;
112   GeomLib::AxeOfInertia(Tab,AxeRef,sing);
113
114   // si la section est une droite, ca ne marche pas
115   if (sing) no_sing = Standard_False;
116
117   Pos = AxeRef.Location();
118   Standard_Real alpha1, alpha2, alpha3;
119   gp_Pnt P1, P2;
120   u = (f+l-h)/2 - h;
121   C1->D0(u,P1);
122   u += h;
123   C1->D0(u,P2);
124   alpha1 = gp_Vec(Pos,P1).AngleWithRef(gp_Vec(Pos,P2),AxeRef.Direction());
125   P1 = P2;
126   u += h;
127   C1->D0(u,P2);
128   alpha2 = gp_Vec(Pos,P1).AngleWithRef(gp_Vec(Pos,P2),AxeRef.Direction());
129   P1 = P2;
130   u += h;
131   C1->D0(u,P2);
132   alpha3 = gp_Vec(Pos,P1).AngleWithRef(gp_Vec(Pos,P2),AxeRef.Direction());
133   Seq2.Append(C1);
134
135   for (Standard_Integer iseq=2; iseq<=Seq1.Length(); iseq++) {
136     // discretisation de C2
137     Handle(Geom_Curve) C2 = Seq1.Value(iseq);
138     f = C2->FirstParameter();
139     l = C2->LastParameter();
140     u = f;
141     for (iP=1;iP<=NP;iP++) {
142       C2->D0(u,Tab(iP));
143       u += h;
144       if ((u-f)*(u-l)>0.0) u = l;
145     }
146     GeomLib::AxeOfInertia(Tab,Axe,sing);  
147
148     // si la section est une droite, ca ne marche pas
149     if (sing) no_sing = Standard_False;
150
151     Pos = Axe.Location();
152     Standard_Real beta1, beta2, beta3;
153     u = (f+l-h)/2 - h;
154     C2->D0(u,P1);
155     u += h;
156     C2->D0(u,P2);
157     beta1 = gp_Vec(Pos,P1).AngleWithRef(gp_Vec(Pos,P2),AxeRef.Direction());
158     P1 = P2;
159     u += h;
160     C2->D0(u,P2);
161     beta2 = gp_Vec(Pos,P1).AngleWithRef(gp_Vec(Pos,P2),AxeRef.Direction());
162     P1 = P2;
163     u += h;
164     C2->D0(u,P2);
165     beta3 = gp_Vec(Pos,P1).AngleWithRef(gp_Vec(Pos,P2),AxeRef.Direction());
166     
167     // meme sens ?
168     Standard_Boolean ok = Standard_True, 
169                 pasnul1 = ( Abs(alpha1) > Precision::Confusion() )
170                           && ( Abs(beta1) > Precision::Confusion() ),
171                 pasnul2 = ( Abs(alpha2) > Precision::Confusion() )
172                           && ( Abs(beta2) > Precision::Confusion() ),
173                 pasnul3 = ( Abs(alpha3) > Precision::Confusion() )
174                           && ( Abs(beta3) > Precision::Confusion() );
175     if (pasnul1 && pasnul2 && pasnul3) {
176       if (alpha1*beta1>0.0) 
177         ok = (alpha2*beta2>0.0) || (alpha3*beta3>0.0);
178       else
179         ok = (alpha2*beta2>0.0) && (alpha3*beta3>0.0);
180     }
181     else if (pasnul1 && pasnul2 && !pasnul3) 
182       ok = (alpha1*beta1>0.0) || (alpha2*beta2>0.0);
183     else if (pasnul1 && !pasnul2 && pasnul3) 
184       ok = (alpha1*beta1>0.0) || (alpha3*beta3>0.0);
185     else if (!pasnul1 && pasnul2 && pasnul3) 
186       ok = (alpha2*beta2>0.0) || (alpha3*beta3>0.0);
187     else if (pasnul1) 
188         ok = (alpha1*beta1>0.0);
189     else if (pasnul2) 
190         ok = (alpha2*beta2>0.0);
191     else if (pasnul3) 
192         ok = (alpha3*beta3>0.0);
193     
194     if (no_sing && !ok) {
195       C2 ->Reverse();
196     }
197     Seq2.Append(C2);
198   }
199
200   return no_sing;
201 }
202
203 //=======================================================================
204 //function : GeomFill_Pipe
205 //purpose  : constructor with no parameters. 
206 //=======================================================================
207
208 GeomFill_Pipe::GeomFill_Pipe() : myIsDone(Standard_False),myExchUV(Standard_False),myKPart(Standard_False)
209 {
210   Init();
211 }
212
213
214 //=======================================================================
215 //function : GeomFill_Pipe
216 //purpose  : 
217 //=======================================================================
218
219 GeomFill_Pipe::GeomFill_Pipe(const Handle(Geom_Curve)& Path, 
220                              const Standard_Real Radius) 
221      : myIsDone(Standard_False),myExchUV(Standard_False),myKPart(Standard_False)
222 {
223   Init();
224   Init(Path, Radius);
225 }
226
227 //=======================================================================
228 //function : GeomFill_Pipe
229 //purpose  : 
230 //=======================================================================
231
232 GeomFill_Pipe::GeomFill_Pipe(const Handle(Geom_Curve)& Path,
233                              const Handle(Geom_Curve)& FirstSect,
234                              const GeomFill_Trihedron Option) 
235      : myIsDone(Standard_False),myExchUV(Standard_False),myKPart(Standard_False)
236 {
237   Init();
238   Init(Path, FirstSect, Option);
239 }
240
241 //=======================================================================
242 //function : GeomFill_Pipe
243 //purpose  : 
244 //=======================================================================
245
246 GeomFill_Pipe::GeomFill_Pipe(const Handle(Geom2d_Curve)& Path,
247                              const Handle(Geom_Surface)& Support,
248                              const Handle(Geom_Curve)& FirstSect) 
249      : myIsDone(Standard_False),myExchUV(Standard_False),myKPart(Standard_False)
250 {
251   Init();
252   Init(Path, Support, FirstSect);
253 }
254
255 //=======================================================================
256 //function : GeomFill_Pipe
257 //purpose  : 
258 //=======================================================================
259
260 GeomFill_Pipe::GeomFill_Pipe(const Handle(Geom_Curve)& Path,
261                              const Handle(Geom_Curve)& FirstSect,
262                              const Handle(Geom_Curve)& LastSect)
263      : myIsDone(Standard_False),myExchUV(Standard_False),myKPart(Standard_False)
264 {
265   Init();
266   Init(Path, FirstSect, LastSect);
267 }
268
269
270 //=======================================================================
271 //function : GeomFill_Pipe
272 //purpose  : 
273 //=======================================================================
274
275 GeomFill_Pipe::GeomFill_Pipe(const Handle(Geom_Curve)& Path,
276                              const TColGeom_SequenceOfCurve& NSections)
277      : myIsDone(Standard_False),myExchUV(Standard_False),myKPart(Standard_False)
278 {
279   Init();
280   Init(Path, NSections);
281 }
282
283 //=======================================================================
284 //function : GeomFill_Pipe
285 //purpose  : 
286 //=======================================================================
287
288 GeomFill_Pipe::GeomFill_Pipe(const Handle(Geom_Curve)& Path,
289                              const Handle(Geom_Curve)& Curve1,
290                              const gp_Dir& Direction)
291      : myIsDone(Standard_False),myExchUV(Standard_False), myKPart(Standard_False)
292 {
293  Init(Path, Curve1, Direction); 
294 }
295 //=======================================================================
296 //function : GeomFill_Pipe
297 //purpose  : 
298 //=======================================================================
299
300 GeomFill_Pipe::GeomFill_Pipe(const Handle(Geom_Curve)& Path,
301                              const Handle(Geom_Curve)& Curve1,
302                              const Handle(Geom_Curve)& Curve2,
303                              const Standard_Real       Radius)
304      : myIsDone(Standard_False),myExchUV(Standard_False),myKPart(Standard_False)
305 {
306   Init();
307   Handle(GeomAdaptor_Curve) AdpPath = 
308     new GeomAdaptor_Curve( Path);
309   Handle(GeomAdaptor_Curve) AdpCurve1 = 
310     new GeomAdaptor_Curve( Curve1);
311   Handle(GeomAdaptor_Curve) AdpCurve2 = 
312     new GeomAdaptor_Curve( Curve2);
313
314   Init(AdpPath, AdpCurve1, AdpCurve2, Radius);
315 }
316
317
318 //=======================================================================
319 //function : GeomFill_Pipe
320 //purpose  : 
321 //=======================================================================
322
323 GeomFill_Pipe::GeomFill_Pipe(const Handle(Adaptor3d_Curve)& Path, 
324                              const Handle(Adaptor3d_Curve)& Curve1,
325                              const Handle(Adaptor3d_Curve)& Curve2,
326                              const Standard_Real Radius)
327      : myIsDone(Standard_False),myExchUV(Standard_False),myKPart(Standard_False)
328 {
329   Init();
330   Init(Path,Curve1,Curve2,Radius);
331 }
332
333
334 //=======================================================================
335
336
337 //=======================================================================
338 //function : GeomFill_Pipe
339 //purpose  : pipe avec courbe guide 
340 //=======================================================================
341
342 GeomFill_Pipe::GeomFill_Pipe(const Handle(Geom_Curve)& Path,
343                              const Handle(Adaptor3d_Curve)& Guide,
344                              const Handle(Geom_Curve)& FirstSect,
345                              const Standard_Boolean byACR,
346                              const Standard_Boolean rotat)
347      : myIsDone(Standard_False),myExchUV(Standard_False),myKPart(Standard_False)
348 // Path : trajectoire
349 // Guide : courbe guide
350 // FirstSect : section
351 // NbPt : nb de points pour le calcul du triedre
352 {
353   Init();
354   Init(Path, Guide, FirstSect, byACR, rotat);
355 }
356
357
358
359 //=======================================================================
360 //function : Init
361 //purpose  : pipe avec courbe guide 
362 //=======================================================================
363
364 void GeomFill_Pipe::Init(const Handle(Geom_Curve)& Path,
365                          const Handle(Adaptor3d_Curve)& Guide,
366                          const Handle(Geom_Curve)& FirstSect,
367                          const Standard_Boolean byACR,
368                          const Standard_Boolean rotat)
369 // Path : trajectoire
370 // Guide : courbe guide
371 // FirstSect : section
372 // rotat : vrai si on veu la rotation false sinon
373 // triedre : AC pour absc. curv. ou P pour plan ortho
374 {
375   Standard_Real angle;
376   myAdpPath = new (GeomAdaptor_Curve) 
377     (Handle(Geom_Curve)::DownCast(Path->Copy()));
378
379   Handle (GeomFill_TrihedronWithGuide) TLaw;
380   
381   // loi de triedre
382   if (byACR) {
383     TLaw = new (GeomFill_GuideTrihedronAC)(Guide);
384     TLaw->SetCurve(myAdpPath);
385   }
386   else {
387     TLaw =  new (GeomFill_GuideTrihedronPlan)(Guide);
388     TLaw->SetCurve(myAdpPath);      
389   }  
390   
391
392 // loi de positionnement
393   Handle(GeomFill_LocationGuide) TheLoc = 
394     new (GeomFill_LocationGuide) (TLaw);
395   TheLoc->SetCurve(myAdpPath);
396
397   GeomFill_SectionPlacement Place(TheLoc, FirstSect);
398   Place.Perform(Precision::Confusion());
399
400 // loi de section
401   mySec = new (GeomFill_UniformSection) (Place.Section(Standard_False),
402                                          myAdpPath->FirstParameter(), 
403                                          myAdpPath->LastParameter());
404
405 #ifdef DRAW
406   if  (Affich) {
407     char* Temp = "TheSect" ;
408     DrawTrSurf::Set(Temp, FirstSect );
409 //    DrawTrSurf::Set("TheSect", FirstSect );
410   }
411 #endif
412
413  if (rotat)  TheLoc->Set(mySec,rotat, 
414                          myAdpPath->FirstParameter(),
415                          myAdpPath->LastParameter(),
416                          0., angle);
417  myLoc = TheLoc;
418 }
419
420
421 //=======================================================================
422 //function : Init
423 //purpose  : 
424 //=======================================================================
425
426 void GeomFill_Pipe::Init()
427 {
428   myType = 0;
429   myError  = 0;
430   myRadius = 0.;
431   myKPart = Standard_True;
432   myPolynomial = Standard_False;
433   myAdpPath.Nullify();
434   myAdpFirstSect.Nullify();
435   myAdpLastSect.Nullify();
436   myLoc.Nullify();
437   mySec.Nullify(); 
438 }
439 //=======================================================================
440 //function : Init
441 //purpose  : 
442 //=======================================================================
443
444 void GeomFill_Pipe::Init(const Handle(Geom_Curve)& Path,
445                          const Standard_Real       Radius)
446 {
447 // Ancienne methode
448   myType   = 1;
449   myError  = 0;
450   myRadius = Radius;
451
452 // Nouvelle methode
453   myAdpPath = new (GeomAdaptor_Curve) (Path);
454   Handle(Geom_Circle) C = new (Geom_Circle) (gp::XOY(), Radius);
455   C->Rotate(gp::OZ(),M_PI/2.);
456   
457   mySec = new (GeomFill_UniformSection) (C, Path->FirstParameter(), 
458                                             Path->LastParameter());
459   Handle (GeomFill_CorrectedFrenet)TLaw = new (GeomFill_CorrectedFrenet) ();
460   myLoc = new (GeomFill_CurveAndTrihedron) (TLaw);
461   myLoc->SetCurve(myAdpPath);
462
463 #ifdef DRAW
464   if  (Affich) {
465     char* Temp = "TheSect" ;
466     DrawTrSurf::Set(Temp, C);   
467 //    DrawTrSurf::Set("TheSect", C);   
468   }
469 #endif
470
471 }
472
473 //=======================================================================
474 //function : Init
475 //purpose  : 
476 //=======================================================================
477
478 void GeomFill_Pipe::Init(const Handle(Geom_Curve)& Path,
479                          const Handle(Geom_Curve)& FirstSect,
480                          const GeomFill_Trihedron Option)
481 {
482   Handle(Geom_Curve) Sect;
483   Handle(GeomFill_TrihedronLaw) TLaw;
484   myAdpPath = new (GeomAdaptor_Curve) 
485     (Handle(Geom_Curve)::DownCast(Path->Copy()));
486   Standard_Real param =  Path->FirstParameter();
487
488 // Construction de la loi de triedre
489   switch (Option) {
490   case GeomFill_IsCorrectedFrenet :
491     {
492       TLaw = new (GeomFill_CorrectedFrenet) ();
493       break;
494     }
495
496   case GeomFill_IsDarboux :
497 #ifdef OCCT_DEBUG
498     {
499       std::cout << "Option Darboux: non realisable" << std::endl; 
500     }
501 #endif
502   case GeomFill_IsFrenet :
503     {
504       TLaw = new (GeomFill_Frenet) ();
505       break; 
506     }
507
508   case GeomFill_IsFixed :
509     {     
510       Standard_Real Eps = 1.e-9;
511       gp_Vec V1(0,0,1), V2(0,1,0);
512       gp_Dir D;
513       GeomLProp_CLProps CP(Path, param, 2, Eps);
514       if (CP.IsTangentDefined()) {
515         CP.Tangent(D);
516         V1.SetXYZ(D.XYZ());
517         V1.Normalize();
518         if (CP.Curvature() > Eps) {
519           CP.Normal(D);
520           V2.SetXYZ(D.XYZ());
521           V2.Normalize();
522         }
523         else {
524           gp_Pnt P0(0., 0., 0.);
525           gp_Ax2 Axe(P0, D);
526           D = Axe.XDirection ();
527           V2.SetXYZ(D.XYZ());
528           V2.Normalize();
529         }
530       }
531       TLaw = new (GeomFill_Fixed) (V1, V2);
532       break;
533     }
534
535   case GeomFill_IsConstantNormal :
536     {     
537       TLaw = new (GeomFill_Frenet) ();
538       myLoc = new (GeomFill_CurveAndTrihedron) (TLaw);
539       myLoc->SetCurve(myAdpPath);
540       GeomFill_SectionPlacement Place(myLoc, FirstSect);
541       Place.Perform(Precision::Confusion());
542       Standard_Real ponsec = Place.ParameterOnSection();
543       
544       Standard_Real Eps = 1.e-9;
545       gp_Vec V(0,1,0);
546       gp_Dir D;
547       GeomLProp_CLProps CP(FirstSect, ponsec, 2, Eps);
548       if (CP.IsTangentDefined()) {
549         CP.Tangent(D);
550         if (CP.Curvature() > Eps) {
551           CP.Normal(D);
552           V.SetXYZ(D.XYZ());
553           V.Normalize();
554         }
555         else {
556           gp_Pnt P0(0., 0., 0.);
557           gp_Ax2 Axe(P0, D);
558           D = Axe.XDirection ();
559           V.SetXYZ(D.XYZ());
560           V.Normalize();
561         }
562       }
563       TLaw = new (GeomFill_ConstantBiNormal) (V);
564       break;
565     }
566
567   default :
568     {
569       throw Standard_ConstructionError("GeomFill::Init : Unknown Option");
570     }
571   }
572  
573   if (!TLaw.IsNull()) {
574     myLoc = new (GeomFill_CurveAndTrihedron) (TLaw);
575     myLoc->SetCurve(myAdpPath);
576     GeomFill_SectionPlacement Place(myLoc, FirstSect);
577     Place.Perform(Precision::Confusion());
578     param =  Place.ParameterOnPath();
579     Sect = Place.Section(Standard_False);
580
581 #ifdef DRAW
582     if  (Affich) {
583       char* Temp = "TheSect" ;
584       DrawTrSurf::Set(Temp,Sect);
585 //      DrawTrSurf::Set("TheSect",Sect);
586       
587     }
588 #endif
589     mySec = new (GeomFill_UniformSection) (Sect, 
590                                            Path->FirstParameter(), 
591                                            Path->LastParameter());
592   }
593 }
594
595 //=======================================================================
596 //function : Init
597 //purpose  : sweep using Darboux's trihedron
598 //=======================================================================
599
600 void GeomFill_Pipe::Init(const Handle(Geom2d_Curve)& Path,
601                          const Handle(Geom_Surface)& Support,
602                          const Handle(Geom_Curve)& FirstSect)
603 {
604   Handle(Geom_Curve) Sect;
605   Handle(GeomFill_TrihedronLaw) TLaw = new (GeomFill_Darboux)();
606   myAdpPath = 
607     new Adaptor3d_CurveOnSurface(Adaptor3d_CurveOnSurface(
608                        new Geom2dAdaptor_Curve(Path), 
609                        new GeomAdaptor_Surface(Support)));
610  
611   myLoc = new (GeomFill_CurveAndTrihedron) (TLaw);
612   myLoc->SetCurve(myAdpPath);
613   GeomFill_SectionPlacement Place(myLoc, FirstSect);
614   Place.Perform(myAdpPath, Precision::Confusion());
615   Sect = Place.Section(Standard_False);
616   
617 #ifdef DRAW
618   if  (Affich) {
619     char* temp = "TheSect" ;
620     DrawTrSurf::Set(temp,Sect);
621 //    DrawTrSurf::Set("TheSect",Sect);
622     
623   }
624 #endif
625   mySec = new (GeomFill_UniformSection) (Sect, 
626                                          myAdpPath->FirstParameter(), 
627                                          myAdpPath->LastParameter());  
628 }
629
630 //=======================================================================
631 //function : Init
632 //purpose  : 
633 //=======================================================================
634
635 void GeomFill_Pipe::Init(const Handle(Geom_Curve)& Path, 
636                          const Handle(Geom_Curve)& FirstSect,
637                          const gp_Dir& Direction)
638 {
639   Init();
640
641   Handle(Geom_Curve) Sect;
642   myAdpPath = new (GeomAdaptor_Curve) 
643     (Handle(Geom_Curve)::DownCast(Path->Copy()));
644   gp_Vec V;
645   V.SetXYZ(Direction.XYZ());
646   Handle (GeomFill_ConstantBiNormal) TLaw = 
647     new (GeomFill_ConstantBiNormal) (V);
648
649   myLoc = new (GeomFill_CurveAndTrihedron) (TLaw);
650   myLoc->SetCurve(myAdpPath);
651   GeomFill_SectionPlacement Place(myLoc, FirstSect);
652   Place.Perform(Precision::Confusion());
653   Sect = Place.Section(Standard_False);
654
655 #ifdef DRAW
656   if  (Affich) {
657     char* temp = "TheSect" ;
658     DrawTrSurf::Set(temp,Sect);    
659 //    DrawTrSurf::Set("TheSect",Sect);    
660   }
661 #endif
662   mySec = new (GeomFill_UniformSection) (Sect, 
663                                          Path->FirstParameter(), 
664                                          Path->LastParameter());
665 }
666
667 //=======================================================================
668 //function : Init
669 //purpose  : 
670 //=======================================================================
671
672 void GeomFill_Pipe::Init(const Handle(Geom_Curve)& Path, 
673                          const TColGeom_SequenceOfCurve& NSections)
674 {
675   myType      = 3;
676   myError  = 0;
677   myRadius    = 0;
678
679   Handle(GeomFill_TrihedronLaw) TLaw;
680   TLaw = new (GeomFill_CorrectedFrenet) ();
681   myAdpPath = new (GeomAdaptor_Curve) 
682     (Handle(Geom_Curve)::DownCast(Path->Copy()));
683   if (!TLaw.IsNull()) {
684     myLoc = new (GeomFill_CurveAndTrihedron) (TLaw);
685     myLoc->SetCurve(myAdpPath);
686     TColGeom_SequenceOfCurve SeqC;
687     TColStd_SequenceOfReal SeqP;
688     SeqC.Clear();
689     SeqP.Clear();
690     Standard_Integer i ;
691     for ( i = 1; i<=NSections.Length(); i++) {
692       GeomFill_SectionPlacement Place(myLoc, NSections(i));
693       Place.Perform(Precision::Confusion());
694       SeqP.Append(Place.ParameterOnPath());
695       SeqC.Append(Place.Section(Standard_False));
696     }
697
698     // verification des orientations
699     TColGeom_SequenceOfCurve NewSeq;
700     if (CheckSense(SeqC,NewSeq)) SeqC = NewSeq;
701
702     // verification des parametres
703     Standard_Boolean play_again = Standard_True;
704     while (play_again) {
705       play_again = Standard_False;
706       for (i = 1; i<=NSections.Length(); i++) {
707         for (Standard_Integer j = i; j<=NSections.Length(); j++) {
708           if (SeqP.Value(i)>SeqP.Value(j)) {
709             SeqP.Exchange(i,j);
710             SeqC.Exchange(i,j);
711             play_again = Standard_True;
712           }
713         }
714       }
715     }
716     for ( i = 1; i<NSections.Length(); i++) {
717       if ( Abs(SeqP.Value(i+1)-SeqP.Value(i)) < Precision::PConfusion()) {
718        throw Standard_ConstructionError("GeomFill_Pipe::Init with NSections : invalid parameters");
719       }
720     }
721     
722     // creation de la NSections
723     Standard_Real first = Path->FirstParameter(),
724                   last = Path->LastParameter();
725     Standard_Real deb,fin;
726     deb = SeqC.First()->FirstParameter();
727     fin = SeqC.First()->LastParameter();
728     mySec = new (GeomFill_NSections) (SeqC,SeqP,deb,fin,first,last);
729   }
730 }
731
732
733 //=======================================================================
734 //function : Init
735 //purpose  : 
736 //=======================================================================
737
738 void GeomFill_Pipe::Init(const Handle(Geom_Curve)& Path, 
739                          const Handle(Geom_Curve)& FirstSect,
740                          const Handle(Geom_Curve)& LastSect)
741 {
742   myType      = 3;
743   myError  = 0;
744   myRadius    = 0;
745   Standard_Real first = Path->FirstParameter(),
746                 last = Path->LastParameter();
747   Handle(GeomFill_TrihedronLaw) TLaw;
748   TLaw = new (GeomFill_CorrectedFrenet) ();
749   myAdpPath = new (GeomAdaptor_Curve) 
750     (Handle(Geom_Curve)::DownCast(Path->Copy()));
751
752   if (!TLaw.IsNull()) {
753     myLoc = new (GeomFill_CurveAndTrihedron) (TLaw);
754     myLoc->SetCurve(myAdpPath);
755     TColGeom_SequenceOfCurve SeqC;
756     TColStd_SequenceOfReal SeqP;
757     SeqC.Clear();
758     SeqP.Clear();
759     // sequence des sections
760     GeomFill_SectionPlacement Pl1(myLoc, FirstSect);
761     Pl1.Perform(first,Precision::Confusion());
762     SeqC.Append(Pl1.Section(Standard_False));
763     GeomFill_SectionPlacement Pl2(myLoc, LastSect);
764     Pl2.Perform(first,Precision::Confusion());
765     SeqC.Append(Pl2.Section(Standard_False));
766     // sequence des parametres associes
767     SeqP.Append(first);
768     SeqP.Append(last);
769
770     // verification de l'orientation
771     TColGeom_SequenceOfCurve NewSeq;
772     if (CheckSense(SeqC,NewSeq)) SeqC = NewSeq;
773
774     // creation de la NSections
775     Standard_Real deb,fin;
776     deb =  SeqC.First()->FirstParameter();
777     fin =  SeqC.First()->LastParameter();
778     mySec = new (GeomFill_NSections) (SeqC,SeqP,deb,fin,first,last);
779   }
780 }
781
782 //=======================================================================
783 //function : Init
784 //purpose  : 
785 //=======================================================================
786
787 void GeomFill_Pipe::Init(const Handle(Adaptor3d_Curve)& Path, 
788                          const Handle(Adaptor3d_Curve)& Curve1,
789                          const Handle(Adaptor3d_Curve)& Curve2,
790                          const Standard_Real           Radius)
791 {
792   myType         = 4;
793   myError        = 0;
794   myRadius       = Radius;
795   myAdpPath      = Path;
796   myAdpFirstSect = Curve1;
797   myAdpLastSect  = Curve2;
798 }
799
800 //=======================================================================
801 //function : Perform
802 //purpose  : 
803 //=======================================================================
804
805 void GeomFill_Pipe::Perform(const Standard_Boolean WithParameters, 
806                             const Standard_Boolean Polynomial) 
807 {
808
809   if ( (! myLoc.IsNull()) && (! mySec.IsNull()) ) {
810     Perform(1.e-4, Polynomial);
811     return;
812   }
813
814   myPolynomial = Polynomial;
815   // on traite la cas tuyau sur arete Type = 4
816   if ( myPolynomial) {
817     ApproxSurf(WithParameters);
818     return;
819   }   
820   if ( !KPartT4() ) ApproxSurf(WithParameters);
821
822 }
823
824 //=======================================================================
825 //function : Perform
826 //purpose  : 
827 //=======================================================================
828 void GeomFill_Pipe::Perform(const Standard_Real Tol,
829                             const Standard_Boolean Polynomial,
830                             const GeomAbs_Shape Conti,
831                             const Standard_Integer DegMax,
832                             const Standard_Integer NbMaxSegment)
833 {
834  GeomAbs_Shape TheConti;
835  switch (Conti) {
836  case GeomAbs_C0:
837    {
838      TheConti = GeomAbs_C0;
839    } 
840    break; 
841  case GeomAbs_G1:
842  case GeomAbs_C1:
843    {
844      TheConti = GeomAbs_C1;
845    } 
846    break;
847  case GeomAbs_G2:
848  case GeomAbs_C2:
849    {
850      TheConti = GeomAbs_C2;
851    } 
852    break;
853  default:
854    TheConti = GeomAbs_C2;// On ne sait pas faire mieux !
855  }
856  Handle (Approx_SweepFunction) Func;
857  Func.Nullify();
858
859  if (myType == 4) { 
860    if (!KPartT4()) {
861      Func = new (GeomFill_CircularBlendFunc)(myAdpPath,  
862                                              myAdpFirstSect,
863                                              myAdpLastSect,
864                                              myRadius,
865                                              Polynomial);
866
867      Approx_SweepApproximation App(Func);
868      App.Perform(myAdpPath->FirstParameter(),
869                  myAdpPath->LastParameter(),
870                  Tol, Tol, 0., 0.01,
871                  TheConti, DegMax, NbMaxSegment);
872 #ifdef OCCT_DEBUG
873    std::cout << "Tuyau : ";
874    App.Dump(std::cout);
875    std::cout << std::endl;
876 #endif
877      if (App.IsDone()) {
878        mySurface = new Geom_BSplineSurface(App.SurfPoles(),
879                                            App.SurfWeights(),
880                                            App.SurfUKnots(),
881                                            App.SurfVKnots(),
882                                            App.SurfUMults(),
883                                            App.SurfVMults(),
884                                            App.UDegree(),
885                                            App.VDegree());
886        myError = App.MaxErrorOnSurf();
887        myIsDone = Standard_True;
888      }
889      //else {
890      //  throw Standard_ConstructionError("GeomFill_Pipe::Perform : Cannot make a surface");
891      //}
892    }
893  }
894  else if ( (! myLoc.IsNull()) && (! mySec.IsNull()) ) {
895    GeomFill_Sweep Sweep(myLoc, myKPart);
896    Sweep.SetTolerance(Tol);
897    Sweep.Build(mySec, GeomFill_Location, TheConti, DegMax, NbMaxSegment);   
898    if (Sweep.IsDone()) {
899       mySurface = Sweep.Surface();
900       myError = Sweep.ErrorOnSurface();
901       myIsDone = Standard_True;
902    }
903    //else {
904    //  throw Standard_ConstructionError("GeomFill_Pipe::Perform : Cannot make a surface");
905    //}
906    }
907  else {
908    Perform(Standard_True, Polynomial);
909  }
910 }    
911    
912    
913 //=======================================================================
914 //function : KPartT4
915 //purpose  : Pour gerer les cas particulier de type 4
916 //=======================================================================
917 Standard_Boolean GeomFill_Pipe::KPartT4()
918 {
919  Standard_Boolean Ok = Standard_False;
920  // -------    Cas du Cylindre  --------------------------
921  if (myAdpPath->GetType() == GeomAbs_Line &&
922      myAdpFirstSect->GetType() == GeomAbs_Line &&
923      myAdpLastSect ->GetType() == GeomAbs_Line   ) {
924      // try to generate a cylinder.
925      gp_Ax1 A0 = myAdpPath     ->Line().Position();
926      gp_Ax1 A1 = myAdpFirstSect->Line().Position();
927      gp_Ax1 A2 = myAdpLastSect ->Line().Position();
928      // direction must be the same.
929      gp_Dir D0 = A0.Direction();
930      gp_Dir D1 = A1.Direction();
931      gp_Dir D2 = A2.Direction();
932      if (!D0.IsEqual(D1,Precision::Angular()) ||
933          !D1.IsEqual(D2,Precision::Angular())   ) {
934        return Ok;
935      }
936
937      // the length of the line must be te same
938      Standard_Real L0 = 
939        myAdpPath->LastParameter() - myAdpPath->FirstParameter();
940      Standard_Real L1 = 
941        myAdpFirstSect->LastParameter() - myAdpFirstSect->FirstParameter();
942      Standard_Real L2 =
943        myAdpLastSect->LastParameter() - myAdpLastSect->FirstParameter();
944      if (Abs(L1-L0) > Precision::Confusion() ||
945          Abs(L2-L0) > Precision::Confusion()   ) {
946        return Ok;
947       }
948
949      // the first points must be normal to the path.
950      gp_Pnt P0 = myAdpPath     ->Value(myAdpPath     ->FirstParameter());
951      gp_Pnt P1 = myAdpFirstSect->Value(myAdpFirstSect->FirstParameter());
952      gp_Pnt P2 = myAdpLastSect ->Value(myAdpLastSect ->FirstParameter());
953      gp_Dir V1(gp_Vec(P0,P1));
954      gp_Dir V2(gp_Vec(P0,P2));
955      if (Abs(V1.Dot(D0)) > Precision::Confusion() ||
956          Abs(V2.Dot(D0)) > Precision::Confusion()   )  return Ok;
957
958      // the result is a cylindrical surface.
959      gp_Dir X(V1), Y(V2), ZRef;
960      ZRef = X.Crossed(Y);
961
962      gp_Ax3 Axis( A0.Location(), D0, X);
963      if ( ZRef.Dot(D0) < 0.)
964        Axis.YReverse();
965
966      // rotate the surface to set the iso U = 0 not in the result.
967      Axis.Rotate(gp_Ax1(P0,ZRef),-M_PI/2.);
968       
969      mySurface = new Geom_CylindricalSurface( Axis, myRadius);
970      Standard_Real Alpha = V1.AngleWithRef(V2,ZRef);
971      mySurface = 
972        new Geom_RectangularTrimmedSurface(mySurface,
973                                           M_PI/2. , 
974                                           M_PI/2. + Alpha,
975                                           myAdpPath->FirstParameter(),
976                                           myAdpPath->LastParameter());
977      Ok = Standard_True; //C'est bien un cylindre
978      myIsDone = Standard_True;
979    }
980  // -----------    Cas du tore  ----------------------------------
981  else if (myAdpPath->GetType()      == GeomAbs_Circle &&
982           myAdpFirstSect->GetType() == GeomAbs_Circle &&
983           myAdpLastSect->GetType()  == GeomAbs_Circle   ) {
984    // try to generate a toroidal surface.    
985    // les 3 cercles doivent avoir meme angle d'ouverture
986    Standard_Real Alp0 =
987      myAdpPath->FirstParameter() - myAdpPath->LastParameter();
988    Standard_Real Alp1 =
989      myAdpFirstSect->FirstParameter() - myAdpFirstSect->LastParameter();
990    Standard_Real Alp2 =
991      myAdpLastSect->FirstParameter() - myAdpLastSect->LastParameter();
992
993    if (Abs(Alp0-Alp1) > Precision::Angular() ||
994        Abs(Alp0-Alp2) > Precision::Angular()   ) return Ok;
995
996    gp_Ax2 A0 = myAdpPath     ->Circle().Position();
997    gp_Ax2 A1 = myAdpFirstSect->Circle().Position();
998    gp_Ax2 A2 = myAdpLastSect ->Circle().Position();
999    gp_Dir D0 = A0.Direction();
1000    gp_Dir D1 = A1.Direction();
1001    gp_Dir D2 = A2.Direction();
1002    gp_Pnt P0 = myAdpPath     ->Value(myAdpPath     ->FirstParameter());
1003    gp_Pnt P1 = myAdpFirstSect->Value(myAdpFirstSect->FirstParameter());
1004    gp_Pnt P2 = myAdpLastSect ->Value(myAdpLastSect ->FirstParameter());
1005
1006    // les 3 directions doivent etre egales.
1007    if (!D0.IsEqual(D1,Precision::Angular()) ||
1008        !D1.IsEqual(D2,Precision::Angular())   )  return Ok;
1009
1010    // les 3 ax1 doivent etre confondus.
1011    gp_Lin L(A0.Axis());
1012    if (!L.Contains(A1.Location(),Precision::Confusion()) ||
1013        !L.Contains(A2.Location(),Precision::Confusion())   )  return Ok;
1014
1015    // les 3 premiers points doivent etre dans la meme section.
1016    gp_Dir V1(gp_Vec(P0,P1));
1017    gp_Dir V2(gp_Vec(P0,P2));
1018    gp_Circ Ci = myAdpPath->Circle();
1019    gp_Vec YRef = 
1020      ElCLib::CircleDN(myAdpPath->FirstParameter(),A0, Ci.Radius(), 1);
1021    if (Abs(V1.Dot(YRef)) > Precision::Confusion() ||
1022        Abs(V2.Dot(YRef)) > Precision::Confusion()   )  return Ok;
1023
1024    // OK it`s a Toroidal Surface !!  OUF !!
1025    gp_Torus T(A0,Ci.Radius(),myRadius);
1026    gp_Vec XRef(A0.Location(),P0);
1027    // au maximum on fait un tore d`ouverture en V = PI
1028    Standard_Real VV1 = V1.AngleWithRef(XRef,YRef);
1029    Standard_Real VV2 = V2.AngleWithRef(XRef,YRef);
1030    Standard_Real deltaV = V2.AngleWithRef(V1,YRef);
1031    if (deltaV < 0.) {
1032      T.VReverse();
1033      VV1 = -VV1;
1034      VV2 = 2*M_PI + VV1 - deltaV;
1035    }
1036    mySurface = new Geom_RectangularTrimmedSurface
1037      (new Geom_ToroidalSurface(T),
1038       myAdpPath->FirstParameter(),myAdpPath->LastParameter(),VV1,VV2);
1039    myExchUV = Standard_True;
1040    Ok = Standard_True;
1041    myIsDone = Standard_True;
1042  }
1043
1044  return Ok;
1045 }
1046
1047 //=======================================================================
1048 //function : ApproxSurf
1049 //purpose  : 
1050 //=======================================================================
1051 void GeomFill_Pipe::ApproxSurf(const Standard_Boolean WithParameters) {
1052
1053   // Traitment of general case. 
1054   // generate a sequence of the section by <SweepSectionGenerator> 
1055   // and approximate this sequence. 
1056   
1057   if (myType != 4) throw Standard_ConstructionError("GeomFill_Pipe");
1058   GeomFill_SweepSectionGenerator Section(myAdpPath, myAdpFirstSect,
1059                                            myAdpLastSect,myRadius);
1060
1061   Section.Perform(myPolynomial);
1062   
1063 #ifdef OCCT_DEBUG
1064   if ( Affich) {
1065     Standard_Integer NbPoles,NbKnots,Degree,NbPoles2d;
1066     Section.GetShape(NbPoles,NbKnots,Degree,NbPoles2d);
1067
1068     TColgp_Array1OfPnt      Poles  (1,NbPoles);
1069     TColgp_Array1OfPnt2d    Poles2d(1,NbPoles);
1070     TColStd_Array1OfReal    Weights(1,NbPoles);
1071     TColStd_Array1OfInteger Mults  (1,NbKnots);
1072     TColStd_Array1OfReal    Knots  (1,NbKnots);
1073     Section.Knots(Knots);
1074     Section.Mults(Mults);
1075
1076     for (Standard_Integer i = 1; i <= Section.NbSections(); i++) {
1077       NbSections++;
1078       Section.Section(i,Poles,Poles2d,Weights);
1079       Handle(Geom_BSplineCurve) BS = 
1080         new Geom_BSplineCurve(Poles,Weights,Knots,Mults,Degree);
1081 #ifdef DRAW
1082       char name[256];
1083       sprintf(name,"SECT_%d",NbSections);
1084       DrawTrSurf::Set(name,BS);
1085 #endif
1086     }
1087   }
1088 #endif
1089
1090   Handle(GeomFill_Line) Line = new GeomFill_Line(Section.NbSections());
1091   Standard_Integer NbIt = 0;
1092   Standard_Real T3d =  Precision::Approximation();
1093   Standard_Real T2d =  Precision::PApproximation();
1094   GeomFill_AppSweep App( 4, 8, T3d, T2d, NbIt, WithParameters);
1095   
1096   App.Perform( Line, Section, 30);
1097
1098   if ( !App.IsDone()) {
1099 #ifdef OCCT_DEBUG
1100     // on affiche les sections sous debug
1101     Standard_Integer NbPoles,NbKnots,Degree,NbPoles2d;
1102     Section.GetShape(NbPoles,NbKnots,Degree,NbPoles2d);
1103
1104     TColgp_Array1OfPnt      Poles  (1,NbPoles);
1105     TColgp_Array1OfPnt2d    Poles2d(1,NbPoles);
1106     TColStd_Array1OfReal    Weights(1,NbPoles);
1107     TColStd_Array1OfInteger Mults  (1,NbKnots);
1108     TColStd_Array1OfReal    Knots  (1,NbKnots);
1109     Section.Knots(Knots);
1110     Section.Mults(Mults);
1111
1112     for (Standard_Integer i = 1; i <= Section.NbSections(); i++) {
1113       Section.Section(i,Poles,Poles2d,Weights);
1114       Handle(Geom_BSplineCurve) BS = 
1115         new Geom_BSplineCurve(Poles,Weights,Knots,Mults,Degree);
1116 #ifdef DRAW
1117       char name[256];
1118       sprintf(name,"sect_%d",i);
1119       DrawTrSurf::Set(name,BS);
1120 #endif
1121     }
1122 #endif
1123     //throw StdFail_NotDone("Pipe : App not done");
1124   }
1125   else {
1126     Standard_Integer UDegree, VDegree, NbUPoles, NbVPoles, NbUKnots, 
1127     NbVKnots;
1128     App.SurfShape(UDegree, VDegree, NbUPoles, NbVPoles, NbUKnots, NbVKnots);
1129     
1130     mySurface = new Geom_BSplineSurface(App.SurfPoles(),
1131                                         App.SurfWeights(),
1132                                         App.SurfUKnots(),
1133                                         App.SurfVKnots(),
1134                                         App.SurfUMults(),
1135                                         App.SurfVMults(),
1136                                         App.UDegree(),
1137                                         App.VDegree());
1138     Standard_Real t2d;
1139     App.TolReached(myError, t2d);
1140     myIsDone = Standard_True;
1141   }
1142 }