0022492: Scaled sphere (Solid with BSplineSurface) is wrongly exported in STEP.
[occt.git] / src / BRepFill / BRepFill_Draft.cxx
1 // File:        BRepFill_Draft.cxx
2 // Created:     Mon Jun  8 15:13:03 1998
3 // Author:      Stephanie HUMEAU
4 //              <shu@sun17>
5
6
7 #include <BRepFill_Draft.ixx>
8
9 #include <BRepFill_DraftLaw.hxx>
10 #include <BRepFill_ShapeLaw.hxx>
11 #include <BRepFill_Sweep.hxx>
12
13 #include <BndLib_Add3dCurve.hxx>
14 #include <BndLib_AddSurface.hxx>
15 #include <Bnd_Box.hxx>
16 #include <gp_Dir.hxx>
17 #include <gp_Pnt.hxx>
18 #include <gp_Trsf.hxx>
19 #include <gp_Ax3.hxx>
20 #include <gp_Lin.hxx>
21 #include <gp_Mat.hxx>
22 #include <TColgp_Array1OfPnt.hxx>
23
24 #include <GeomAdaptor_Surface.hxx>
25 #include <BRepAdaptor_Surface.hxx>
26 #include <Adaptor3d_HCurve.hxx>
27
28 #include <GeomLProp_SLProps.hxx>
29 #include <Geom_Surface.hxx>
30 #include <Geom_Line.hxx>
31 #include <Geom_TrimmedCurve.hxx>
32 #include <Geom_Geometry.hxx>
33 #include <Geom_Plane.hxx>
34 #include <Geom_RectangularTrimmedSurface.hxx>
35
36 #include <GeomAdaptor_HSurface.hxx>
37 #include <Adaptor3d_Surface.hxx>
38 #include <BRepAdaptor_Curve.hxx>
39
40 #include <GeomFill_LocationDraft.hxx>
41
42 #include <TopoDS.hxx>
43 #include <TopoDS_Edge.hxx>
44 #include <TopoDS_Wire.hxx>  
45 #include <TopoDS_Shell.hxx> 
46 #include <TopoDS_Solid.hxx> 
47 #include <TopoDS_Iterator.hxx>
48 #include <TopExp_Explorer.hxx> 
49 #include <TopExp.hxx>
50 #include <TopAbs.hxx>
51 #include <BRepLib_MakeWire.hxx>
52 #include <BRepLib_MakeEdge.hxx>
53 #include <BRepLib_MakeFace.hxx>
54 #include <BRepLib_FindSurface.hxx>
55 #include <BRep_Builder.hxx>
56
57 #include <BRep_Tool.hxx>
58 #include <BRepTools.hxx>
59 #include <BRepAlgo_DSAccess.hxx>
60 #include <BRepBuilderAPI_Sewing.hxx>
61 #include <BRepClass3d_SolidClassifier.hxx>
62
63 #include <TopTools_ListIteratorOfListOfShape.hxx>
64 #include <TopTools_ListOfShape.hxx>
65 #include <BRepExtrema_DistShapeShape.hxx>
66
67 #include <Precision.hxx> 
68 #include <TColStd_Array1OfReal.hxx>
69
70 #include <Standard_NoSuchObject.hxx>
71 #include <StdFail_NotDone.hxx>
72
73 #ifdef DRAW
74 #include <Geom_Circle.hxx>
75 #include <gp.hxx>
76 #include <DBRep.hxx>
77 #include <DrawTrSurf.hxx>
78 static Standard_Boolean Affich = 0;
79 #endif
80
81 //=======================================================================
82 //function : Trsf
83 //purpose  : 
84 //======================================================================
85 static void ComputeTrsf(const TopoDS_Wire& W,
86                         const gp_Dir& D,
87                         Bnd_Box& Box,
88                         gp_Trsf& Tf)
89 {
90   // Calcul d'un barycentre approximatif
91   BRepTools_WireExplorer Exp(W);
92 // Class BRep_Tool without fields and without Constructor :
93 //  BRep_Tool BT;
94   gp_XYZ Bary(0.,0.,0.);
95   Standard_Integer nb;
96
97   for (nb=0; Exp.More(); Exp.Next()) {
98 //    Bary += BT.Pnt(Exp.CurrentVertex()).XYZ();
99     Bary += BRep_Tool::Pnt(Exp.CurrentVertex()).XYZ();
100     nb++;
101   }
102   Bary /= nb;
103
104   // Calcul la Transfo  
105   gp_Ax3 N(Bary, D);
106   Tf.SetTransformation(N);
107   BRepAdaptor_Curve AC;
108 //  BndLib_Add3dCurve BC;  
109
110   // transfo du wire
111   TopoDS_Wire TheW = W;
112   TopLoc_Location Loc(Tf);
113   TheW.Location(Loc);
114
115
116   // Calcul la boite
117   Box.SetVoid();
118   for (Exp.Init(TheW); Exp.More(); Exp.Next()) {
119     AC.Initialize(Exp.Current());
120 //    BC.Add(AC, 0.1, Box);
121     BndLib_Add3dCurve::Add(AC, 0.1, Box);
122   }
123 }
124
125 //=======================================================================
126 //function : Longueur
127 //purpose  : 
128 //======================================================================
129 static Standard_Real Longueur(const Bnd_Box& WBox,
130                               const Bnd_Box& SBox,
131                               gp_Dir& D,
132                               gp_Pnt& P)
133 {
134   // face de la boite la plus eloignee de la face entree dans 
135   //la direction de depouille
136   Standard_Real Xmin,Ymin,Zmin,Xmax,Ymax,Zmax,WZmin,WZmax,L;
137
138   //"coord" de la boite
139   WBox.Get(Xmin,Ymin,Zmin,Xmax,Ymax,Zmax);
140   WZmin = Zmin;
141   WZmax = Zmax;   
142
143   SBox.Get(Xmin,Ymin,Zmin,Xmax,Ymax,Zmax);
144   P.SetCoord( (Xmin+Xmax)/2, (Ymin+Ymax)/2, Zmax);
145
146   if (Zmax < WZmin) {
147     // Depouille dans le mauvais sens. On inverse...
148     D.Reverse();
149     L = WZmax - Zmin;
150     P.SetZ(Zmin);
151   }
152   else {
153     L = Zmax - WZmin;
154   }
155   return L;
156 }
157
158 //=======================================================================
159 //function : GoodOrientation
160 //purpose  : Regarde si la loi est oriente de maniere a avoir une depouille
161 //           "exterieur"
162 //======================================================================
163 static Standard_Boolean GoodOrientation(const Bnd_Box& B,
164                                         const Handle(BRepFill_LocationLaw)& Law,
165                                         const gp_Dir& D)
166 {
167   Standard_Real f, l, r, t;
168   Standard_Real aXmin, aYmin, aZmin, aXmax, aYmax, aZmax;
169
170   B.Get(aXmin, aYmin, aZmin, aXmax, aYmax, aZmax);
171   gp_Pnt P1(aXmin, aYmin, aZmin), P2(aXmax, aYmax, aZmax);
172   gp_Vec V(P1, P2);
173
174   Law->CurvilinearBounds(Law->NbLaw(), f, l);
175   r = V.Magnitude()/l;
176  
177   Standard_Integer ii, Ind;
178 //#ifndef DEB
179   Standard_Integer Nb = (Standard_Integer) (4+(10*r));
180 //#else
181 //  Standard_Integer Nb = 4+(10*r);
182 //#endif
183   r = l/Nb;
184
185   Nb++; // Nombre de points
186
187   TColgp_Array1OfPnt Pnts(1, Nb);
188   Handle(Adaptor3d_HCurve) AC;
189   gp_XYZ Bary(0.,0.,0.);
190   
191   for (ii=1; ii<=Nb; ii++) {
192     Law->Parameter((ii-1)*r, Ind, t);
193     AC = Law->Law(Ind)->GetCurve();
194     AC->D0(t,  Pnts(ii));
195     Bary+= Pnts(ii).XYZ();
196   }
197
198   Bary /= Nb;
199   gp_Pnt Centre(Bary);
200   gp_Vec Normal(D.XYZ());
201   Standard_Real Angle = 0;
202   gp_Vec Ref(Centre,  Pnts(1));
203
204   for (ii=2; ii<=Nb; ii++) {
205     gp_Vec R(Centre, Pnts(ii));
206     Angle += Ref.AngleWithRef(R, Normal);
207     Ref = R;
208   }
209
210   return (Angle >= 0);
211 }
212
213 //=======================================================================
214 //function : Constructeur
215 //purpose  : 
216 //======================================================================
217  BRepFill_Draft::BRepFill_Draft(const TopoDS_Shape& S,
218                                 const gp_Dir& Dir,
219                                 const Standard_Real Angle)
220 {
221   myLoc.Nullify();
222   mySec.Nullify();
223   myFaces.Nullify();
224   mySections.Nullify(); 
225    
226   switch (S.ShapeType()) {
227   case TopAbs_WIRE :
228     {
229       myWire = TopoDS::Wire(S);
230       break;
231     }
232   case TopAbs_FACE :
233     {  
234       TopoDS_Iterator Exp (S);
235       myWire = TopoDS::Wire(Exp.Value());
236       break;
237     }
238   case TopAbs_SHELL :
239     {  
240       TopTools_ListOfShape List;
241       TopTools_IndexedDataMapOfShapeListOfShape edgemap;
242       TopExp::MapShapesAndAncestors(S,TopAbs_EDGE,TopAbs_FACE,edgemap);
243       Standard_Integer iedge, nbf;
244       for (iedge = 1; iedge <= edgemap.Extent(); iedge++) {   
245         const TopoDS_Edge& theEdge = TopoDS::Edge(edgemap.FindKey(iedge));    
246         // skip degenerated edges
247         if (!BRep_Tool::Degenerated(theEdge)) {
248           nbf = edgemap(iedge).Extent();
249           if (nbf==1) List.Append(theEdge);
250         }
251       }
252
253       if( List.Extent()>0) {
254         BRepLib_MakeWire MW;
255         MW.Add(List);
256         BRepLib_WireError Err = MW.Error();
257         if (Err == BRepLib_WireDone) {
258           myWire = MW.Wire();
259         }
260         else {
261 #if DEB
262           cout << "Error in MakeWire" << endl;
263 #endif 
264           Standard_ConstructionError::Raise("BRepFill_Draft");
265         }
266       }
267       else {
268 #if DEB
269           cout << "Pas de Bords Libre !" << endl;
270 #endif 
271           Standard_ConstructionError::Raise("BRepFill_Draft");
272       }
273       break;
274     }
275     default :
276       Standard_ConstructionError::Raise("BRepFill_Draft");
277   }
278
279   // Attention aux wire closed non declare !
280   if (!myWire.Closed()) {
281     TopoDS_Vertex Vf, Vl;
282     TopExp::Vertices(myWire, Vf, Vl);
283     if (Vf.IsSame(Vl)) myWire.Closed(Standard_True);
284   }
285 #if DRAW
286   if (Affich) {
287     DBRep::Set("TheWire", myWire);
288   }
289 #endif
290
291   myAngle = Abs(Angle);
292   myDir = Dir;
293   myTop = S;
294   myDone = Standard_False;
295   myTol = 1.e-4;
296   myCont = GeomAbs_C1;
297   SetOptions();
298   SetDraft();
299 }
300
301 //=======================================================================
302 //function :SetOptions
303 //purpose  : Definit le style
304 //======================================================================
305  void BRepFill_Draft::SetOptions(const BRepFill_TransitionStyle Style,
306                                  const Standard_Real Min,
307                                  const Standard_Real Max)
308 {
309   myStyle =  Style;
310   angmin = Min; 
311   angmax = Max;
312 }
313
314 //=======================================================================
315 //function :SetDraft
316 //purpose  :
317 //======================================================================
318  void BRepFill_Draft::SetDraft(const Standard_Boolean Internal)
319 {
320   IsInternal = Internal;
321 }
322
323
324 //=======================================================================
325 //function :Perform
326 //purpose  : calcul d'une surface de depouille
327 //======================================================================
328  void BRepFill_Draft::Perform(const Standard_Real LengthMax)
329 {
330   Handle(Geom_Surface) S;
331   S.Nullify();
332   Bnd_Box WBox;//, SBox;
333   gp_Trsf Trsf;
334
335
336   ComputeTrsf(myWire, myDir, WBox, Trsf); 
337   Init(S, LengthMax, WBox);
338   BuildShell(S); 
339   Sewing(); 
340 }
341
342 //=======================================================================
343 //function :Perform
344 //purpose  : calcul d'une surface de depouille
345 //======================================================================
346  void BRepFill_Draft::Perform(const Handle(Geom_Surface)& Surface,
347                               const Standard_Boolean KeepInsideSurface)
348 {
349   Bnd_Box WBox, SBox;
350   gp_Trsf Trsf;
351   gp_Pnt Pt;
352   Standard_Real L;
353
354   ComputeTrsf(myWire, myDir, WBox, Trsf);
355
356   // boite englobant la surface d'arret  
357   Handle(Geom_Surface) Surf;
358   Surf =   Handle(Geom_Surface)::DownCast(Surface->Transformed(Trsf));
359   GeomAdaptor_Surface S1 (Surf);   
360 //  BndLib_AddSurface AS; 
361 //  AS.Add(S1, 0.1, SBox);
362   BndLib_AddSurface::Add(S1, 0.1, SBox);
363
364   // on calcule la longueur maximum de la regle.
365   L = Longueur(WBox, SBox, myDir, Pt);
366   L /= Abs(Cos(myAngle));
367
368   // Constructuion
369   Init(Surface, L, WBox);
370   BuildShell(Surface, !KeepInsideSurface);
371   Sewing(); 
372 }
373
374 //=======================================================================
375 //function :Perform
376 //purpose  : calcul de la surface de depouille, arretee par une shape
377 //======================================================================
378  void BRepFill_Draft::Perform(const TopoDS_Shape& StopShape,
379                               const Standard_Boolean KeepOutSide)
380 {
381   Bnd_Box WBox, SBox;
382   gp_Trsf Trsf;
383   gp_Pnt Pt;
384   Standard_Real L;
385
386   ComputeTrsf(myWire, myDir, WBox, Trsf); 
387
388 // boite englobant la shape d'arret
389   Bnd_Box BSurf;//, TheBox;
390   Standard_Real Umin, Umax, Vmin, Vmax;
391 #ifdef DEB
392   Standard_Real Tol = Precision::Confusion()/10;
393 #endif
394 //  BRepTools B;
395 //  BRep_Tool BT;
396   Handle(Geom_Surface) Surf;
397  
398 //  BndLib_AddSurface AS;
399   
400   TopExp_Explorer Ex (StopShape, TopAbs_FACE);
401
402   SBox.SetVoid();
403   while (Ex.More()) { // on parcourt les faces de la shape d'arret
404 //    B.UVBounds(TopoDS::Face(Ex.Current()), Umin,Umax,Vmin,Vmax); 
405     BRepTools::UVBounds(TopoDS::Face(Ex.Current()), Umin,Umax,Vmin,Vmax); 
406     Surf = Handle(Geom_Surface)::DownCast(
407 //     BT.Surface(TopoDS::Face(Ex.Current()))->Transformed(Trsf) ); 
408      BRep_Tool::Surface(TopoDS::Face(Ex.Current()))->Transformed(Trsf) ); 
409     GeomAdaptor_Surface S1 (Surf);
410     // boite englobant la face courante
411 //    AS.Add(S1, Umin, Umax, Vmin, Vmax, 0.1, BSurf); 
412     BndLib_AddSurface::Add(S1, Umin, Umax, Vmin, Vmax, 0.1, BSurf);
413     SBox.Add(BSurf);    // on regroupe les boites
414     Ex.Next();
415   }// while_Ex
416
417   // on calcule la longueur maximum de la regle.
418   L = Longueur(WBox, SBox, myDir, Pt);
419   L /= Abs(Cos(myAngle));
420
421 // surface d'arret
422   gp_Trsf Inv;
423   Inv = Trsf.Inverted(); // transfo inverse
424   Pt.Transform(Inv); // coord dans le repere absolu
425   Handle(Geom_Plane) Plan = new (Geom_Plane)(Pt, myDir);
426   Surf = new (Geom_RectangularTrimmedSurface) (Plan,-L, L, -L, L); 
427
428 #if DRAW
429   if (Affich) {
430     char* Temp = "ThePlan" ;
431     DrawTrSurf::Set(Temp, Surf);
432 //    DrawTrSurf::Set("ThePlan", Surf);
433   }
434 #endif
435
436 // Balayage et restriction
437   Init(Plan,  L*1.01, WBox);
438   BuildShell(Surf, Standard_False);
439   Fuse(StopShape,  KeepOutSide);
440   Sewing();
441 }
442
443 //=======================================================================
444 //function : Init
445 //purpose  : Construction des lois.
446 //======================================================================
447  void BRepFill_Draft::Init(const Handle(Geom_Surface)& ,
448                            const Standard_Real Length,
449                            const Bnd_Box&  Box)
450 {
451   Standard_Boolean B;
452
453 // loi de positionnement  
454   Handle(GeomFill_LocationDraft) Loc
455     = new (GeomFill_LocationDraft) (myDir, myAngle); 
456   myLoc = new (BRepFill_DraftLaw) (myWire, Loc);
457
458   B = GoodOrientation(Box, myLoc, myDir);
459
460   if (IsInternal ^ (!B) )  {
461     myAngle = - myAngle;
462     Loc->SetAngle(myAngle);
463     myLoc = new (BRepFill_DraftLaw) (myWire, Loc);
464   }
465
466   myLoc->CleanLaw(angmin); // Nettoie les petites discontinuites.
467
468 // loi de section
469 // generatrice est une droite // a la binormal.
470   gp_Pnt P(0, 0, 0);
471   gp_Vec D (0., 1., 0.);
472
473 // Controle de l'orientation
474   Standard_Real f,l;
475   myLoc->Law(1)->GetDomain(f,l);
476   gp_Mat M;
477
478   gp_Vec Bid; 
479   myLoc->Law(1)->D0( (f+l)/2, M, Bid);
480   gp_Dir BN(M.Column(2));
481   
482   Standard_Real ang = myDir.Angle(BN);
483   if (ang > PI/2) D.Reverse();    
484   Handle(Geom_Line) L = new (Geom_Line) (P, D);
485
486   Handle(Geom_Curve) TC = new (Geom_TrimmedCurve) (L, 0, Length);
487
488
489 #if DRAW
490   if (Affich > 2) {
491      TC = new (Geom_Circle) (gp::XOY(), Length);
492   }
493 #endif 
494
495   BRepLib_MakeEdge ME(TC);
496   TopoDS_Edge EG = ME.Edge();
497   
498   BRepLib_MakeWire MW(EG);
499   TopoDS_Wire G = MW.Wire();
500
501   mySec = new (BRepFill_ShapeLaw) (G, Standard_True);
502 }
503
504
505 //=======================================================================
506 //function : BuildShell
507 //purpose  : Construction de la surface de depouille
508 //======================================================================
509  void BRepFill_Draft::BuildShell(const Handle(Geom_Surface)& Surf,
510                                  const Standard_Boolean  KeepOutSide) 
511 {
512 // construction de la surface
513   BRepFill_Sweep Sweep(mySec, myLoc, Standard_True);
514   Sweep.SetTolerance(myTol);
515   Sweep.SetAngularControl(angmin, angmax);
516   Sweep.Build(myStyle, GeomFill_Location, myCont);
517   if (Sweep.IsDone()) {
518     myShape = Sweep.Shape();
519     myShell = TopoDS::Shell(myShape);
520     myFaces    = Sweep.SubShape();
521     mySections = Sweep.Sections();    
522     myDone = Standard_True;
523     // Controle de l'orientation
524     Standard_Boolean out=Standard_True;
525     TopExp_Explorer ex(myShell,TopAbs_FACE);
526     TopoDS_Face F;
527     F = TopoDS::Face(ex.Current());
528     BRepAdaptor_Surface SF(F);
529     Standard_Real u, v;
530     gp_Pnt P;
531     gp_Vec V1, V2, V;
532     u = SF.FirstUParameter();
533     v = SF.FirstVParameter();
534     SF.D1(u,v,P,V1,V2);
535     V = V1.Crossed(V2);
536     if (F.Orientation() == TopAbs_REVERSED) V.Reverse();
537     if (V.Magnitude() > 1.e-10) {
538       out = myDir.Angle(V) > PI/2;
539     }
540     if (out == IsInternal) {
541       myShell.Reverse();
542       myShape.Reverse();
543     }    
544   }
545   else {
546     myDone = Standard_False;
547     return;
548   }
549
550   if (!Surf.IsNull()) { // On ajoute la face en bout
551
552   // En attendant une utilisation des traces & retriction dans BRepFill_Sweep
553   // On fait un Fuse.
554     BRepLib_MakeFace MkF;
555     MkF.Init(Surf, Standard_True, Precision::Confusion());
556     Fuse(MkF.Face(), KeepOutSide);
557   }
558 }
559
560
561 //=======================================================================
562 //function : Fuse
563 //purpose  : Operation booleenne entre la depouille et 
564 //           la shape d'arret
565 //======================================================================
566  Standard_Boolean BRepFill_Draft::Fuse(const TopoDS_Shape& StopShape,
567                            const Standard_Boolean KeepOutSide)
568 {
569   BRep_Builder B;
570   Standard_Boolean issolid = Standard_False;
571   TopoDS_Solid Sol1, Sol2;
572   TopAbs_State State1 = TopAbs_OUT,  State2 = TopAbs_OUT;
573
574
575   if (myShape.ShapeType()==TopAbs_SOLID) {
576     Sol1 = TopoDS::Solid(myShape);
577     issolid = Standard_True;
578   }
579   else {
580     B.MakeSolid(Sol1);
581     B.Add(Sol1, myShape); // shell => solid (pour fusion)    
582   }
583
584
585   switch (StopShape.ShapeType()) {
586   case TopAbs_COMPOUND :
587     {
588       TopoDS_Iterator It(StopShape);
589       return Fuse(It.Value(), KeepOutSide);
590     }
591   case TopAbs_SOLID : 
592     {
593       Sol2 = TopoDS::Solid(StopShape);
594       break;
595     }
596  case TopAbs_SHELL :
597     {
598       B.MakeSolid(Sol2);
599       B.Add(Sol2, StopShape); // shell => solid (pour fusion) 
600       break;
601     }
602
603  case TopAbs_FACE :
604     {
605       TopoDS_Shell S;
606       B.MakeShell(S);
607       B.Add(S, StopShape);
608       B.MakeSolid(Sol2);
609       B.Add(Sol2, S); // shell => solid (pour fusion)
610       break;
611     }
612
613   default :
614     {
615       return Standard_False; // On ne sait pas faire
616     }
617   }
618       
619   BRepAlgo_DSAccess DSA;
620   DSA.Load(Sol1, Sol2);
621   DSA.Intersect(Sol1, Sol2); // intersection des 2 solids
622  
623 // suppression des aretes correspondant aux intersections "inutiles"
624   Standard_Integer NbPaquet;
625 // gp_Pnt P1,P2;
626   TopoDS_Vertex V,V1;
627   TopTools_ListOfShape List;
628   List  = DSA.GetSectionEdgeSet();// liste des aretes
629   
630   NbPaquet = List.Extent();
631
632   if (NbPaquet == 0) {
633 #if DRAW
634     cout << "Pas de fusion" << endl;
635     DBRep::Set("DepPart", Sol1);
636     DBRep::Set("StopPart", Sol2);
637 #endif
638     return Standard_False;
639   }
640
641   if (NbPaquet > 1) {
642     // Il faut selectioner les paquets.
643     TColStd_Array1OfReal Dist(1, NbPaquet);
644     TopTools_ListIteratorOfListOfShape it(List);
645     Standard_Real D, Dmin = 1.e10;
646     Standard_Integer ii;
647  
648     //On classe les paquets par eloignement.
649     BRepExtrema_DistShapeShape Dist2;
650     Dist2.LoadS1( myWire );
651     for (ii=1; it.More();it.Next(),ii++){
652       Dist2.LoadS2( it.Value() );
653       Dist2.Perform();
654       if (Dist2.IsDone()) {
655         D = Dist2.Value();
656         Dist(ii) = D;
657         if (D < Dmin) Dmin = D;
658       }
659       else
660         Dist(ii) = 1.e10;
661     }
662
663     // on supprime les edges "plus loin" que Dmin
664     for (ii=1, it.Initialize(List); it.More();it.Next(), ii++){
665       if (Dist(ii) > Dmin) {
666         DSA.SuppressEdgeSet(it.Value());
667       }
668 #if DRAW
669      else if (Affich) {
670         DBRep::Set("KeepEdges", it.Value());
671       }
672 #endif
673     }
674   }
675
676   if (StopShape.ShapeType() != TopAbs_SOLID) {
677     // Il faut choisir le state par la geometrie
678
679     //(1) On recupere une edge de section
680     List  = DSA.GetSectionEdgeSet();// liste des aretes
681     TopTools_ListIteratorOfListOfShape it(List);
682     TopoDS_Iterator iter(it.Value());
683     TopoDS_Edge E = TopoDS::Edge(iter.Value());
684
685     // (2)  On recupere sa geometrie sur StopShape
686 // Class BRep_Tool without fields and without Constructor :
687 //    BRep_Tool BT;
688     Handle(Geom_Surface) S;
689     Handle(Geom2d_Curve) C2d;
690     gp_Pnt2d P2d;
691     Standard_Real f,l;  
692     TopLoc_Location L;
693 //    BT.CurveOnSurface(E, C2d, S, L, f, l, 2);
694     BRep_Tool::CurveOnSurface(E, C2d, S, L, f, l, 2);
695
696     // On Trouve une normale.
697     C2d->D0((f+l)/2,P2d); 
698     GeomLProp_SLProps SP(S, P2d.X(), P2d.Y(), 1, 1.e-12);
699     if (! SP.IsNormalDefined()) {
700       C2d->D0((3*f+l)/4,P2d);
701       SP.SetParameters(P2d.X(), P2d.Y());
702       if ( !SP.IsNormalDefined()) {
703         C2d->D0((f+3*l)/4,P2d);
704         SP.SetParameters(P2d.X(), P2d.Y());
705       }
706     }
707
708     // On en deduit State1
709     if (myDir.Angle(SP.Normal()) < PI/2)  State1 = TopAbs_IN;
710     else  State1 = TopAbs_OUT;
711   }
712
713   if (! KeepOutSide) { // On inverse State2;
714     if (State2 == TopAbs_IN) State2 = TopAbs_OUT;
715     else State2 = TopAbs_IN;
716   }
717  
718 //recalcul de la shape finale
719   TopoDS_Shape result = DSA.Merge(State1, State2); 
720
721   if (issolid) myShape =  result;
722   else {
723     TopExp_Explorer Exp;
724     Exp.Init(result, TopAbs_SHELL);
725     if (Exp.More()) myShape = Exp.Current();
726   }
727
728 // Mise a jour de l'Historique
729   Standard_Integer ii;
730   for (ii=1; ii<=myLoc->NbLaw(); ii++) {
731     const TopTools_ListOfShape& L = DSA.Modified(myFaces->Value(1,ii));
732     if (L.Extent()>0) 
733       myFaces->SetValue(1, ii, L.First());
734   }
735   for (ii=1; ii<=myLoc->NbLaw()+1; ii++) {
736     const TopTools_ListOfShape& L = DSA.Modified(mySections->Value(1,ii));
737     if (L.Extent()>0) 
738       mySections->SetValue(1, ii, L.First());
739   } 
740  
741   return Standard_True;
742 }
743
744 //=======================================================================
745 //function : Sewing 
746 //purpose  : Assemble la depouille avec la face du dessus
747 //======================================================================
748  Standard_Boolean BRepFill_Draft::Sewing()
749 {
750   Standard_Boolean ToAss;
751   Standard_Boolean Ok = Standard_False;
752   ToAss = (myTop.ShapeType() != TopAbs_WIRE);
753
754   if ((!ToAss) || (!myDone)) return Standard_False;
755
756    // Assemblage
757   // on fait un shell a partir des faces de la shape + la shape en entree
758   Handle(BRepBuilderAPI_Sewing) Ass =  new BRepBuilderAPI_Sewing(5*myTol, Standard_True, 
759                                                      Standard_True, Standard_False);
760   Ass->Add(myShape);
761   Ass->Add(myTop);
762   ToAss = Standard_True;
763  
764
765   Standard_Integer NbCE;
766   
767   Ass->Perform();
768   // On verifie que l'assemblage est effectif.
769   NbCE = Ass->NbContigousEdges();
770   
771   if (NbCE > 0) {
772     TopoDS_Shape res;
773     res = Ass->SewedShape();   
774     if ((res.ShapeType() == TopAbs_SHELL)||
775         (res.ShapeType() == TopAbs_SOLID))  {
776       myShape = res;
777       Ok = Standard_True;
778     }
779     else if (res.ShapeType() == TopAbs_COMPOUND) {
780       TopoDS_Iterator It(res);
781       res = It.Value();
782       It.Next();
783       if (!It.More()) {//Une seule partie => c'est bon
784         myShape = res;
785         Ok = Standard_True;
786       }
787     }
788   }
789
790   if (Ok) {
791     // Mise a jour de l'Historique
792     Standard_Integer ii;
793     for (ii=1; ii<=myLoc->NbLaw(); ii++) {
794       if (Ass->IsModified(myFaces->Value(1,ii)))     
795         myFaces->SetValue(1, ii, 
796                           Ass->Modified(myFaces->Value(1,ii)));
797     }
798     for (ii=1; ii<=myLoc->NbLaw()+1; ii++) {
799       if (Ass->IsModified(mySections->Value(1,ii))) 
800         mySections->SetValue(1, ii, 
801                              Ass->Modified(mySections->Value(1,ii)));
802     }   
803
804     if (myShape.Closed()) { // On fait un Solid
805       TopoDS_Solid solid;
806       BRep_Builder BS;
807       BS.MakeSolid(solid); 
808       BS.Add(solid,TopoDS::Shell(myShape));
809       
810       BRepClass3d_SolidClassifier SC(solid);
811       SC.PerformInfinitePoint(Precision::Confusion());
812       if ( SC.State() == TopAbs_IN) {
813         BS.MakeSolid(solid);
814         myShape.Reverse();
815         BS.Add(solid,TopoDS::Shell(myShape));
816       }
817       myShape = solid;
818     }    
819   }
820 #if DEB
821   else cout << "Draft : Pas d'assemblage !" << endl;
822 #endif
823   return Ok;
824 }
825
826 //=======================================================================
827 //function : Generated
828 //purpose  : retourne une sous partie partie generes par balayage
829 //======================================================================
830  const TopTools_ListOfShape& 
831  BRepFill_Draft::Generated(const TopoDS_Shape& S) 
832 {
833   myGenerated.Clear();
834   TopoDS_Edge E;
835   Standard_Integer ii;
836   E = TopoDS::Edge(S);
837   if (E.IsNull()) {
838    for (ii=0; ii<=myLoc->NbLaw(); ii++)
839       if (E.IsSame(myLoc->Vertex(ii))) {
840         myGenerated.Append(mySections->Value(1, ii+1));
841         break;
842       } 
843   }
844   else {
845     for (ii=1; ii<=myLoc->NbLaw(); ii++)
846       if (E.IsSame(myLoc->Edge(ii))) {
847         myGenerated.Append(myFaces->Value(1, ii));
848         break;
849       }
850   }
851   
852   return myGenerated;
853 }
854
855 //=======================================================================
856 //function : Shape
857 //purpose  : retourne la shape complete
858 //======================================================================
859  TopoDS_Shape BRepFill_Draft::Shape()const
860 {
861   return myShape;
862 }
863
864 //=======================================================================
865 //function : Shell
866 //purpose  : surface de depouille avec la face entree (=>shell)
867 //======================================================================
868  TopoDS_Shell BRepFill_Draft::Shell()const
869 {
870   return myShell;
871 }
872
873 //=======================================================================
874 //function : IsDone
875 //purpose  : 
876 //======================================================================
877  Standard_Boolean BRepFill_Draft::IsDone()const
878 {
879   return myDone;
880 }