Integration of OCCT 6.5.0 from SVN
[occt.git] / src / BRepOffsetAPI / BRepOffsetAPI_ThruSections.cxx
1 // File:        BRepOffsetAPI_ThruSections.cxx
2 // Created:     Tue Jul 18 16:18:09 1995
3 // Author:      Jing Cheng MEI
4 //              <mei@junon>
5 // Modified:    Mon Jan 12 10:50:10 1998
6 // Author:      Joelle CHAUVET
7 //              <jct@sgi64>
8 //              gestion automatique de l'origine et de l'orientation
9 //              avec la methode ArrangeWires
10 // Modified:    Mon Jan 19 10:11:56 1998
11 // Author:      Joelle CHAUVET
12 //              <jct@sgi64>
13 //              traitement des cas particuliers cylindre, cone, plan 
14 //              (methodes DetectKPart et CreateKPart)
15 // Modified:    Mon Feb 23 09:28:46 1998
16 // Author:      Joelle CHAUVET
17 //              <jct@sgi64>
18 //              traitement des sections avec nombre d'elements different
19 //              + quelques ameliorations pour les cas particuliers
20 //              + cas de la derniere section ponctuelle
21 // Modified:    Mon Apr  6 15:47:44 1998
22 // Author:      Joelle CHAUVET
23 //              <jct@sgi64>
24 //              traitement des cas particuliers deplace dans BRepFill 
25 // Modified:    Thu Apr 30 15:24:17 1998
26 // Author:      Joelle CHAUVET
27 //              <jct@sgi64>
28 //              separation sections fermees / sections ouvertes + debug 
29 // Modified:    Fri Jul 10 11:23:35 1998
30 // Author:      Joelle CHAUVET
31 //              <jct@sgi64>
32 //              surface de CreateSmoothed par concatenation,approximation
33 //              et segmentation (PRO13924, CTS21295)
34 // Modified:    Tue Jul 21 16:48:35 1998
35 // Author:      Joelle CHAUVET
36 //              <jct@sgi64>
37 //              pb de ratio (BUC60281) 
38 // Modified:    Thu Jul 23 11:38:36 1998
39 // Author:      Joelle CHAUVET
40 //              <jct@sgi64>
41 //              sections bouclantes
42 // Modified:    Fri Aug 28 10:13:44 1998
43 // Author:      Joelle CHAUVET
44 //              <jct@sgi64>
45 //              traitement des sections ponctuelles
46 //              dans l'historique (cf. loft06 et loft09)
47 //              et dans le cas des solides
48 // Modified:    Tue Nov  3 10:06:15 1998
49 // Author:      Joelle CHAUVET
50 //              <jct@sgi64>
51 //              utilisation de BRepFill_CompatibleWires
52  
53
54 #include <BRepOffsetAPI_ThruSections.ixx>
55
56 #include <Precision.hxx>
57 #include <Standard_DomainError.hxx>
58
59 #include <gp_Pnt.hxx>
60 #include <gp_Pnt2d.hxx>
61 #include <gp_Dir2d.hxx>
62 #include <TColgp_Array1OfPnt.hxx>
63
64 #include <GeomAbs_Shape.hxx>
65 #include <Geom_Curve.hxx>
66 #include <Geom_BSplineSurface.hxx>
67 #include <Geom_TrimmedCurve.hxx>
68 #include <Geom_BezierCurve.hxx>
69 #include <Geom_Conic.hxx>
70 #include <Geom2d_Line.hxx>
71 #include <GeomFill_Line.hxx>
72 #include <GeomFill_AppSurf.hxx>
73 #include <GeomFill_SectionGenerator.hxx>
74 #include <GeomConvert_CompCurveToBSplineCurve.hxx>
75 #include <GeomConvert.hxx>
76 #include <GeomConvert_ApproxCurve.hxx>
77 #include <Geom_BSplineCurve.hxx>
78 #include <BSplCLib.hxx>
79
80 #include <TopAbs.hxx>
81 #include <TopoDS.hxx>
82 #include <TopoDS_Solid.hxx>
83 #include <TopoDS_Face.hxx>
84 #include <TopoDS_Edge.hxx>
85 #include <TopoDS_Vertex.hxx>
86 #include <TopoDS_Wire.hxx>
87 #include <TopLoc_Location.hxx>
88 #include <TopTools_Array1OfShape.hxx>
89 #include <TopTools_ListIteratorOfListOfShape.hxx>
90 #include <TopTools_IndexedDataMapOfShapeListOfShape.hxx>
91 #include <TopExp.hxx>
92 #include <TopoDS_Iterator.hxx>
93
94
95 #include <BRep_Builder.hxx>
96 #include <BRep_Tool.hxx>
97 #include <BRepTools_WireExplorer.hxx>
98
99 #include <BRepLib.hxx>
100 #include <BRepClass3d_SolidClassifier.hxx>
101
102 #include <BRepFill_Generator.hxx>
103 #include <BRepFill_CompatibleWires.hxx>
104
105 #include <BRepBuilderAPI_MakeFace.hxx>
106 #include <BRepBuilderAPI_FindPlane.hxx>
107
108
109
110
111 //=======================================================================
112 //function :  PerformPlan
113 //purpose  : Construit s'il existe un plan de remplissage
114 //=======================================================================
115
116 static Standard_Boolean PerformPlan(const TopoDS_Wire& W,
117                                     const Standard_Real presPln,
118                                     TopoDS_Face& theFace)
119 {
120   Standard_Boolean isDegen = Standard_True;
121   TopoDS_Iterator iter(W);
122   for (; iter.More(); iter.Next())
123     {
124       const TopoDS_Edge& anEdge = TopoDS::Edge(iter.Value());
125       if (!BRep_Tool::Degenerated(anEdge))
126         isDegen = Standard_False;
127     }
128   if (isDegen)
129     return Standard_True;
130
131   Standard_Boolean Ok = Standard_False;
132   if (!W.IsNull()) {
133     BRepBuilderAPI_FindPlane Searcher( W, presPln );
134     if (Searcher.Found())
135       {
136         theFace = BRepBuilderAPI_MakeFace(Searcher.Plane(), W);
137         Ok = Standard_True;
138       }
139     else // try to find another surface
140       {
141         BRepBuilderAPI_MakeFace MF( W );
142         if (MF.IsDone())
143           {
144             theFace = MF.Face();
145             Ok = Standard_True;
146           }
147       }
148   }
149
150  return Ok;
151 }
152
153 //=============================================================================
154 //function :  IsSameOriented
155 //purpose  : Checks whether aFace is oriented to the same side as aShell or not
156 //=============================================================================
157
158 static Standard_Boolean IsSameOriented(const TopoDS_Shape& aFace,
159                                        const TopoDS_Shape& aShell)
160 {
161   TopExp_Explorer Explo(aFace, TopAbs_EDGE);
162   TopoDS_Shape anEdge = Explo.Current();
163   TopAbs_Orientation Or1 = anEdge.Orientation();
164
165   TopTools_IndexedDataMapOfShapeListOfShape EFmap;
166   TopExp::MapShapesAndAncestors( aShell, TopAbs_EDGE, TopAbs_FACE, EFmap );
167
168   const TopoDS_Shape& AdjacentFace = EFmap.FindFromKey(anEdge).First();
169   TopoDS_Shape theEdge;
170   for (Explo.Init(AdjacentFace, TopAbs_EDGE); Explo.More(); Explo.Next())
171     {
172       theEdge = Explo.Current();
173       if (theEdge.IsSame(anEdge))
174         break;
175     }
176
177   TopAbs_Orientation Or2 = theEdge.Orientation();
178   if (Or1 == Or2)
179     return Standard_False;
180   return Standard_True;
181 }
182
183 //=======================================================================
184 //function : MakeSolid
185 //purpose  : 
186 //=======================================================================
187
188 static TopoDS_Solid MakeSolid(TopoDS_Shell& shell, const TopoDS_Wire& wire1,
189                               const TopoDS_Wire& wire2, const Standard_Real presPln,
190                               TopoDS_Face& face1, TopoDS_Face& face2)
191 {
192   if (shell.IsNull())
193     StdFail_NotDone::Raise("Thrusections is not build");
194   Standard_Boolean B = shell.Closed();
195   BRep_Builder BB;
196
197   if (!B)
198     {
199       // Il faut boucher les extremites 
200       B =  PerformPlan(wire1, presPln, face1);
201       if (B) {
202         B =  PerformPlan(wire2, presPln, face2);
203         if (B) {
204           if (!face1.IsNull() && !IsSameOriented( face1, shell ))
205             face1.Reverse();
206           if (!face2.IsNull() && !IsSameOriented( face2, shell ))
207             face2.Reverse();
208           
209           if (!face1.IsNull())
210             BB.Add(shell, face1);
211           if (!face2.IsNull())
212             BB.Add(shell, face2);
213           
214           shell.Closed(Standard_True);
215         }
216       }
217     }
218
219   TopoDS_Solid solid;
220   BB.MakeSolid(solid); 
221   BB.Add(solid, shell);
222   
223   // verify the orientation the solid
224   BRepClass3d_SolidClassifier clas3d(solid);
225   clas3d.PerformInfinitePoint(Precision::Confusion());
226   if (clas3d.State() == TopAbs_IN) {
227     BB.MakeSolid(solid); 
228     TopoDS_Shape aLocalShape = shell.Reversed();
229     BB.Add(solid, TopoDS::Shell(aLocalShape));
230 //    B.Add(solid, TopoDS::Shell(newShell.Reversed()));
231   }
232
233   solid.Closed(Standard_True);
234   return solid;
235 }
236
237
238 //=======================================================================
239 //function : BRepOffsetAPI_ThruSections
240 //purpose  : 
241 //=======================================================================
242
243 BRepOffsetAPI_ThruSections::BRepOffsetAPI_ThruSections(const Standard_Boolean isSolid, const Standard_Boolean ruled,
244                                              const Standard_Real pres3d):
245                                              myIsSolid(isSolid), myIsRuled(ruled), myPres3d(pres3d)
246 {
247   myWCheck = Standard_True;
248 //----------------------------
249   myParamType = Approx_ChordLength; 
250   myDegMax    = 8; 
251   myContinuity = GeomAbs_C2;
252   myCritWeights[0] = .4; 
253   myCritWeights[1] = .2; 
254   myCritWeights[2] = .4; 
255   myUseSmoothing = Standard_False;
256 }
257
258
259 //=======================================================================
260 //function : Init
261 //purpose  : 
262 //=======================================================================
263
264 void BRepOffsetAPI_ThruSections::Init(const Standard_Boolean isSolid, const Standard_Boolean ruled,
265                                  const Standard_Real pres3d)
266 {
267   myIsSolid = isSolid;
268   myIsRuled = ruled;
269   myPres3d = pres3d;
270   myWCheck = Standard_True;
271 //----------------------------
272   myParamType = Approx_ChordLength; 
273   myDegMax    = 6; 
274   myContinuity = GeomAbs_C2;
275   myCritWeights[0] = .4; 
276   myCritWeights[1] = .2; 
277   myCritWeights[2] = .4; 
278   myUseSmoothing = Standard_False;
279
280 }
281
282
283 //=======================================================================
284 //function : AddWire
285 //purpose  : 
286 //=======================================================================
287
288 void BRepOffsetAPI_ThruSections::AddWire(const TopoDS_Wire& wire)
289 {
290   myWires.Append(wire);
291 }
292
293 //=======================================================================
294 //function : AddVertex
295 //purpose  : 
296 //=======================================================================
297
298 void BRepOffsetAPI_ThruSections::AddVertex(const TopoDS_Vertex& aVertex)
299 {
300   BRep_Builder BB;
301
302   TopoDS_Edge DegEdge;
303   BB.MakeEdge( DegEdge );
304   BB.Add( DegEdge, aVertex.Oriented(TopAbs_FORWARD) );
305   BB.Add( DegEdge, aVertex.Oriented(TopAbs_REVERSED) );
306   BB.Degenerated( DegEdge, Standard_True );
307   DegEdge.Closed( Standard_True );
308
309   TopoDS_Wire DegWire;
310   BB.MakeWire( DegWire );
311   BB.Add( DegWire, DegEdge );
312   DegWire.Closed( Standard_True );
313
314   myWires.Append( DegWire );
315 }
316
317 //=======================================================================
318 //function : CheckCompatibility
319 //purpose  : 
320 //=======================================================================
321
322 void BRepOffsetAPI_ThruSections::CheckCompatibility(const Standard_Boolean check)
323 {
324   myWCheck = check;
325 }
326
327
328 //=======================================================================
329 //function : Build
330 //purpose  : 
331 //=======================================================================
332
333 void BRepOffsetAPI_ThruSections::Build()
334 {
335   //Check set of section for right configuration of punctual sections
336   Standard_Integer i;
337   TopExp_Explorer explo;
338   for (i = 2; i <= myWires.Length()-1; i++)
339     {
340       Standard_Boolean wdeg = Standard_True;
341       for (explo.Init(myWires(i), TopAbs_EDGE); explo.More(); explo.Next())
342         {
343           const TopoDS_Edge& anEdge = TopoDS::Edge(explo.Current());
344           wdeg = wdeg && (BRep_Tool::Degenerated(anEdge));
345         }
346       if (wdeg)
347         Standard_Failure::Raise("Wrong usage of punctual sections");
348     }
349   if (myWires.Length() <= 2)
350     {
351       Standard_Boolean wdeg = Standard_True;
352       for (i = 1; i <= myWires.Length(); i++)
353         for (explo.Init(myWires(i), TopAbs_EDGE); explo.More(); explo.Next())
354           {
355             const TopoDS_Edge& anEdge = TopoDS::Edge(explo.Current());
356             wdeg = wdeg && (BRep_Tool::Degenerated(anEdge));
357           }
358       if (wdeg)
359         Standard_Failure::Raise("Wrong usage of punctual sections");
360     }
361
362   if (myWCheck) {
363     // compute origin and orientation on wires to avoid twisted results
364     // and update wires to have same number of edges
365     
366     // on utilise BRepFill_CompatibleWires
367     TopTools_SequenceOfShape WorkingSections;
368     WorkingSections.Clear();
369     TopTools_DataMapOfShapeListOfShape WorkingMap;
370     WorkingMap.Clear();
371     
372     // Calcul des sections de travail
373     BRepFill_CompatibleWires Georges(myWires);
374     Georges.Perform();
375     if (Georges.IsDone()) {
376       WorkingSections = Georges.Shape();
377       WorkingMap = Georges.Generated();
378     }
379     myWires = WorkingSections;
380   }
381
382   // Calcul de la shape resultat
383   if (myWires.Length() == 2 || myIsRuled) {
384     // create a ruled shell
385     CreateRuled();
386   }
387   else {
388     // create a smoothed shell
389     CreateSmoothed();
390   }
391   // Encode the Regularities
392   BRepLib::EncodeRegularity(myShape);
393   
394 }
395
396
397 //=======================================================================
398 //function : CreateRuled
399 //purpose  : 
400 //=======================================================================
401
402 void BRepOffsetAPI_ThruSections::CreateRuled()
403 {
404   Standard_Integer nbSects = myWires.Length();
405   BRepFill_Generator aGene;
406 //  for (Standard_Integer i=1; i<=nbSects; i++) {
407   Standard_Integer i;
408   for (i=1; i<=nbSects; i++) {
409     aGene.AddWire(TopoDS::Wire(myWires(i)));
410   }
411   aGene.Perform();
412   TopoDS_Shell shell = aGene.Shell();
413
414   if (myIsSolid) {
415
416     // on regarde si le premier wire est identique au dernier
417     Standard_Boolean vClosed = (myWires(1).IsSame(myWires(nbSects))) ;
418
419     if (vClosed) {
420
421       TopoDS_Solid solid;      
422       BRep_Builder B;
423       B.MakeSolid(solid); 
424       B.Add(solid, shell);
425       
426       // verify the orientation the solid
427       BRepClass3d_SolidClassifier clas3d(solid);
428       clas3d.PerformInfinitePoint(Precision::Confusion());
429       if (clas3d.State() == TopAbs_IN) {
430         B.MakeSolid(solid); 
431         TopoDS_Shape aLocalShape = shell.Reversed();
432         B.Add(solid, TopoDS::Shell(aLocalShape));
433 //      B.Add(solid, TopoDS::Shell(shell.Reversed()));
434       }
435       myShape = solid;
436
437     }
438
439     else {
440
441       TopoDS_Wire wire1 = TopoDS::Wire(myWires.First());
442       TopoDS_Wire wire2 = TopoDS::Wire(myWires.Last());
443       myShape = MakeSolid(shell, wire1, wire2, myPres3d, myFirst, myLast);
444
445     }
446
447     Done();
448   }
449
450   else {
451     myShape = shell;
452     Done();
453   }
454
455   // history
456   BRepTools_WireExplorer anExp1, anExp2;
457   TopTools_IndexedDataMapOfShapeListOfShape M;
458   TopExp::MapShapesAndAncestors(shell, TopAbs_EDGE, TopAbs_FACE, M);
459   TopTools_ListIteratorOfListOfShape it;
460
461   TopTools_IndexedDataMapOfShapeListOfShape MV;
462   TopExp::MapShapesAndAncestors(shell, TopAbs_VERTEX, TopAbs_FACE, MV);
463   
464   for (i=1; i<=nbSects-1; i++) {
465     
466     const TopoDS_Wire& wire1 = TopoDS::Wire(myWires(i));
467     const TopoDS_Wire& wire2 = TopoDS::Wire(myWires(i+1));
468     
469     anExp1.Init(wire1);
470     anExp2.Init(wire2);
471
472     Standard_Boolean tantque = anExp1.More() && anExp2.More();
473
474     while (tantque) {
475
476       const TopoDS_Shape& edge1 = anExp1.Current();
477       const TopoDS_Shape& edge2 = anExp2.Current();
478       Standard_Boolean degen1 = BRep_Tool::Degenerated(anExp1.Current());
479       Standard_Boolean degen2 = BRep_Tool::Degenerated(anExp2.Current());
480       
481       TopTools_MapOfShape MapFaces;
482       if (degen2){
483         TopoDS_Vertex Vdegen = TopExp::FirstVertex(TopoDS::Edge(edge2));
484         for (it.Initialize(MV.FindFromKey(Vdegen)); it.More(); it.Next()) {
485           MapFaces.Add(it.Value());
486         }
487       }
488       else {
489         for (it.Initialize(M.FindFromKey(edge2)); it.More(); it.Next()) {
490           MapFaces.Add(it.Value());
491         }
492       }
493       
494       if (degen1) {
495         TopoDS_Vertex Vdegen = TopExp::FirstVertex(TopoDS::Edge(edge1));
496         for (it.Initialize(MV.FindFromKey(Vdegen)); it.More(); it.Next()) {
497           const TopoDS_Shape& Face = it.Value();
498           if (MapFaces.Contains(Face)) {
499             myGenerated.Bind(edge1, Face);
500             break;
501           }
502         }
503       }
504       else {
505         for (it.Initialize(M.FindFromKey(edge1)); it.More(); it.Next()) {
506           const TopoDS_Shape& Face = it.Value();
507           if (MapFaces.Contains(Face)) {
508             myGenerated.Bind(edge1, Face);
509             break;
510           }
511         }
512       }
513       
514       if (!degen1) anExp1.Next();
515       if (!degen2) anExp2.Next();
516       
517       tantque = anExp1.More() && anExp2.More();
518       if (degen1) tantque = anExp2.More();
519       if (degen2) tantque = anExp1.More();
520       
521     }
522       
523   }
524       
525 }
526
527 //=======================================================================
528 //function : CreateSmoothed
529 //purpose  : 
530 //=======================================================================
531
532 void BRepOffsetAPI_ThruSections::CreateSmoothed()
533 {
534   // initialisation
535   Standard_Integer nbSects = myWires.Length();
536   BRepTools_WireExplorer anExp;
537
538   Standard_Boolean w1Point = Standard_True;
539   // on regarde si le premier wire est ponctuel
540   for(anExp.Init(TopoDS::Wire(myWires(1))); anExp.More(); anExp.Next()) {
541     w1Point = w1Point && (BRep_Tool::Degenerated(anExp.Current()));
542   }
543
544   Standard_Boolean w2Point = Standard_True;
545   // on regarde si le dernier wire est ponctuel
546   for(anExp.Init(TopoDS::Wire(myWires(nbSects))); anExp.More(); anExp.Next()) {
547     w2Point = w2Point && (BRep_Tool::Degenerated(anExp.Current()));
548   }
549
550   Standard_Boolean vClosed = Standard_False;
551   // on regarde si le premier wire est identique au dernier
552   if (myWires(1).IsSame(myWires(myWires.Length()))) vClosed = Standard_True;
553
554   // find the dimension
555   Standard_Integer nbEdges=0;
556   if (!w1Point) {
557     for(anExp.Init(TopoDS::Wire(myWires(1))); anExp.More(); anExp.Next()) {
558       nbEdges++;
559     }
560   }
561   else {
562     for(anExp.Init(TopoDS::Wire(myWires(2))); anExp.More(); anExp.Next()) {
563       nbEdges++;
564     }
565   }
566
567   // recover the shapes
568   Standard_Boolean uClosed = Standard_True;
569   TopTools_Array1OfShape shapes(1, nbSects*nbEdges);
570   Standard_Integer nb=0, i, j;
571
572   for (i=1; i<=nbSects; i++) {
573     const TopoDS_Wire& wire = TopoDS::Wire(myWires(i));
574     if (!wire.Closed()) {
575       // on regarde quand meme si les vertex sont les memes.
576       TopoDS_Vertex V1, V2;
577       TopExp::Vertices(wire,V1,V2);
578       if ( !V1.IsSame(V2)) uClosed = Standard_False;
579     }
580     if ( (i==1 && w1Point) || (i==nbSects && w2Point) ) {
581       // si le wire est ponctuel
582       anExp.Init(TopoDS::Wire(wire));
583       for(j=1; j<=nbEdges; j++) {
584         nb++;
585         shapes(nb) = anExp.Current();
586       }
587     }
588     else {
589       // sinon
590       for(anExp.Init(TopoDS::Wire(wire)); anExp.More(); anExp.Next()) {
591         nb++;
592         shapes(nb) = anExp.Current();
593       }
594     }
595   }
596
597   // create the new surface
598   TopoDS_Shell shell;
599   TopoDS_Face face;
600   TopoDS_Wire W;
601   TopoDS_Edge edge, edge1, edge2, edge3, edge4, couture;
602   TopTools_Array1OfShape vcouture(1, nbEdges);
603
604   BRep_Builder B;
605   B.MakeShell(shell);
606
607   TopoDS_Wire newW1, newW2;
608   BRep_Builder BW1, BW2;
609   BW1.MakeWire(newW1);
610   BW2.MakeWire(newW2);
611
612   TopLoc_Location loc;
613   TopoDS_Vertex v1f,v1l,v2f,v2l;
614
615   GeomFill_SectionGenerator section;
616   Standard_Integer nbPnts = 21;
617   TColgp_Array2OfPnt points(1, nbPnts, 1, nbSects);
618
619   // on concatene chaque section pour obtenir une surface totale que
620   // l'on va segmenter
621   Handle(Geom_BSplineSurface) TS;
622   TS = TotalSurf(shapes,nbSects,nbEdges,w1Point,w2Point,vClosed);
623
624   if(TS.IsNull()) {
625     return;
626   }
627
628   TopoDS_Shape firstEdge;
629   for (i=1; i<=nbEdges; i++) {  
630
631     // segmentation de TS
632     Handle(Geom_BSplineSurface) surface;
633     surface = Handle(Geom_BSplineSurface)::DownCast(TS->Copy());
634     Standard_Real Ui1,Ui2,V0,V1;
635     Ui1 = i-1;
636     Ui2 = i;
637     V0  = surface->VKnot(surface->FirstVKnotIndex());
638     V1  = surface->VKnot(surface->LastVKnotIndex());
639     surface->Segment(Ui1,Ui2,V0,V1);
640
641     // recuperation des vertices
642     edge =  TopoDS::Edge(shapes(i));
643     TopExp::Vertices(edge,v1f,v1l);
644     if (edge.Orientation() == TopAbs_REVERSED)
645       TopExp::Vertices(edge,v1l,v1f);
646     firstEdge = edge;
647
648     edge =  TopoDS::Edge(shapes((nbSects-1)*nbEdges+i));
649     TopExp::Vertices(edge,v2f,v2l);
650     if (edge.Orientation() == TopAbs_REVERSED)
651       TopExp::Vertices(edge,v2l,v2f);
652
653     // make the face
654     B.MakeFace(face, surface, Precision::Confusion());
655
656     // make the wire
657     B.MakeWire(W);
658     
659     // make the missing edges
660     Standard_Real f1, f2, l1, l2;
661     surface->Bounds(f1,l1,f2,l2);
662   
663     // --- edge 1
664     if ( w1Point ) {
665       // copie de l'edge degeneree
666       TopoDS_Shape aLocalShape = shapes(1).EmptyCopied();
667       edge1 =  TopoDS::Edge(aLocalShape);
668 //      edge1 =  TopoDS::Edge(shapes(1).EmptyCopied());
669       edge1.Orientation(TopAbs_FORWARD);
670     }
671     else {
672       B.MakeEdge(edge1, surface->VIso(f2), Precision::Confusion());
673     }
674     v1f.Orientation(TopAbs_FORWARD);
675     B.Add(edge1, v1f);
676     v1l.Orientation(TopAbs_REVERSED);
677     B.Add(edge1, v1l);
678     B.Range(edge1, f1, l1);
679     // traitement des sections bouclantes
680     // on stocke les edges de la 1ere section
681     if (vClosed)
682       vcouture(i) = edge1;
683     
684
685     // --- edge 2
686     if (vClosed)
687       edge2 = TopoDS::Edge(vcouture(i));
688     else {
689       if ( w2Point ) {
690         // copie de l'edge degeneree
691         TopoDS_Shape aLocalShape = shapes(nbSects*nbEdges).EmptyCopied();
692         edge2 =  TopoDS::Edge(aLocalShape);
693 //      edge2 =  TopoDS::Edge(shapes(nbSects*nbEdges).EmptyCopied());
694         edge2.Orientation(TopAbs_FORWARD);
695       }
696       else {
697         B.MakeEdge(edge2, surface->VIso(l2), Precision::Confusion());
698       }
699       v2f.Orientation(TopAbs_FORWARD);
700       B.Add(edge2, v2f);
701       v2l.Orientation(TopAbs_REVERSED);
702       B.Add(edge2, v2l);
703       B.Range(edge2, f1, l1);
704     }
705     edge2.Reverse();
706
707
708     // --- edge 3
709     if (i==1) {
710       B.MakeEdge(edge3, surface->UIso(f1), Precision::Confusion());
711       v1f.Orientation(TopAbs_FORWARD);
712       B.Add(edge3, v1f);
713       v2f.Orientation(TopAbs_REVERSED);
714       B.Add(edge3, v2f);
715       B.Range(edge3, f2, l2);
716       if (uClosed) {
717         couture = edge3;
718       }
719     }
720     else {
721       edge3 = edge4;
722     }
723     edge3.Reverse();
724
725     // --- edge 4
726     if ( uClosed && i==nbEdges) {
727       edge4 = couture;
728     }
729     else {
730       B.MakeEdge(edge4, surface->UIso(l1), Precision::Confusion());
731       v1l.Orientation(TopAbs_FORWARD);
732       B.Add(edge4, v1l);
733       v2l.Orientation(TopAbs_REVERSED);
734       B.Add(edge4, v2l);
735       B.Range(edge4, f2, l2);
736     }
737
738     B.Add(W,edge1);
739     B.Add(W,edge4);
740     B.Add(W,edge2);
741     B.Add(W,edge3);
742
743     // set PCurve
744     if (vClosed) {
745       B.UpdateEdge(edge1,
746                    new Geom2d_Line(gp_Pnt2d(0,f2),gp_Dir2d(1,0)),
747                    new Geom2d_Line(gp_Pnt2d(0,l2),gp_Dir2d(1,0)),face,
748                    Precision::Confusion());
749       B.Range(edge1,face,f1,l1);
750     }
751     else {
752       B.UpdateEdge(edge1,new Geom2d_Line(gp_Pnt2d(0,f2),gp_Dir2d(1,0)),face,
753                    Precision::Confusion());
754       B.Range(edge1,face,f1,l1);
755       B.UpdateEdge(edge2,new Geom2d_Line(gp_Pnt2d(0,l2),gp_Dir2d(1,0)),face,
756                    Precision::Confusion());
757       B.Range(edge2,face,f1,l1);
758     }
759
760     if ( uClosed && nbEdges ==1 )  {
761       B.UpdateEdge(edge3,
762                    new Geom2d_Line(gp_Pnt2d(l1,0),gp_Dir2d(0,1)),
763                    new Geom2d_Line(gp_Pnt2d(f1,0),gp_Dir2d(0,1)),face,
764                    Precision::Confusion());
765       B.Range(edge3,face,f2,l2);
766
767     }
768     else {
769       B.UpdateEdge(edge3,new Geom2d_Line(gp_Pnt2d(f1,0),gp_Dir2d(0,1)),face,
770                    Precision::Confusion());
771       B.Range(edge3,face,f2,l2);
772       B.UpdateEdge(edge4,new Geom2d_Line(gp_Pnt2d(l1,0),gp_Dir2d(0,1)),face,
773                    Precision::Confusion());
774       B.Range(edge4,face,f2,l2);
775     }
776     B.Add(face,W);
777     B.Add(shell, face);
778
779     // complete newW1 newW2
780     TopoDS_Edge edge12 = edge1;
781     TopoDS_Edge edge22 = edge2;
782     edge12.Reverse();
783     edge22.Reverse();
784     BW1.Add(newW1, edge12);
785     BW2.Add(newW2, edge22);
786
787     // history
788     myGenerated.Bind(firstEdge, face);
789   }
790
791   if (uClosed && w1Point && w2Point)
792     shell.Closed(Standard_True);
793
794   if (myIsSolid) {
795
796     if (vClosed) {
797
798       TopoDS_Solid solid;
799       BRep_Builder B;
800       B.MakeSolid(solid); 
801       B.Add(solid, shell);
802       
803       // verify the orientation the solid
804       BRepClass3d_SolidClassifier clas3d(solid);
805       clas3d.PerformInfinitePoint(Precision::Confusion());
806       if (clas3d.State() == TopAbs_IN) {
807         B.MakeSolid(solid); 
808         TopoDS_Shape aLocalShape = shell.Reversed();
809         B.Add(solid, TopoDS::Shell(aLocalShape));
810 //      B.Add(solid, TopoDS::Shell(shell.Reversed()));
811       }
812       myShape = solid;
813
814     }
815
816     else {
817       myShape = MakeSolid(shell, newW1, newW2, myPres3d, myFirst, myLast);
818     }
819
820     Done();
821   }
822
823   else {
824     myShape = shell;
825     Done();
826   }
827   
828   TopExp_Explorer ex(myShape,TopAbs_EDGE);
829   while (ex.More()) {
830     const TopoDS_Edge& CurE = TopoDS::Edge(ex.Current());
831     B.SameRange(CurE, Standard_False);
832     B.SameParameter(CurE, Standard_False);
833     Standard_Real tol = BRep_Tool::Tolerance(CurE);
834     BRepLib::SameParameter(CurE,tol);
835     ex.Next();
836   }
837 }
838
839 //=======================================================================
840 //function : TotalSurf
841 //purpose  : 
842 //=======================================================================
843
844 Handle(Geom_BSplineSurface) BRepOffsetAPI_ThruSections::
845                                    TotalSurf(const TopTools_Array1OfShape& shapes,
846                                              const Standard_Integer NbSects,
847                                              const Standard_Integer NbEdges,
848                                              const Standard_Boolean w1Point,
849                                              const Standard_Boolean w2Point,
850                                              const Standard_Boolean vClosed) const
851 {
852   Standard_Integer i,j,jdeb=1,jfin=NbSects;
853   TopoDS_Edge edge;
854   TopLoc_Location loc;
855   Standard_Real first, last;
856   TopoDS_Vertex vf,vl;
857
858   GeomFill_SectionGenerator section;
859   Handle(Geom_BSplineSurface) surface;
860   Handle(Geom_BSplineCurve) BS, BS1;
861   Handle(Geom_TrimmedCurve) curvTrim;
862   Handle(Geom_BSplineCurve) curvBS;
863
864   if (w1Point) {
865     jdeb++;
866     edge =  TopoDS::Edge(shapes(1));
867     TopExp::Vertices(edge,vl,vf);
868     TColgp_Array1OfPnt Extremities(1,2);
869     Extremities(1) = BRep_Tool::Pnt(vf);
870     Extremities(2) = BRep_Tool::Pnt(vl);
871     TColStd_Array1OfReal Bounds(1,2);
872     Bounds(1) = 0.;
873     Bounds(2) = 1.;
874     Standard_Integer Deg = 1;
875     TColStd_Array1OfInteger Mult(1,2);
876     Mult(1) = Deg+1;
877     Mult(2) = Deg+1;
878     Handle(Geom_BSplineCurve) BSPoint
879       = new Geom_BSplineCurve(Extremities,Bounds,Mult,Deg);
880     section.AddCurve(BSPoint);
881   }
882
883   if (w2Point) {
884     jfin--;
885   }
886
887   for (j=jdeb; j<=jfin; j++) {
888
889     // cas des sections bouclantes
890     if (j==jfin && vClosed) {
891       section.AddCurve(BS1);
892     }
893
894     else {
895       // read the first edge to initialise CompBS;
896       edge =  TopoDS::Edge(shapes((j-1)*NbEdges+1));
897       if (BRep_Tool::Degenerated(edge)) {
898         // edge degeneree : construction d'une courbe ponctuelle
899         TopExp::Vertices(edge,vl,vf);
900         TColgp_Array1OfPnt Extremities(1,2);
901         Extremities(1) = BRep_Tool::Pnt(vf);
902         Extremities(2) = BRep_Tool::Pnt(vl);
903         Handle(Geom_Curve) curv = new Geom_BezierCurve(Extremities);
904         curvTrim = new Geom_TrimmedCurve(curv,
905                                          curv->FirstParameter(),
906                                          curv->LastParameter());
907       }
908       else {
909         // recuperation de la courbe sur l'edge
910         Handle(Geom_Curve) curv = BRep_Tool::Curve(edge, loc, first, last);
911         curvTrim = new Geom_TrimmedCurve(curv, first, last);
912         curvTrim->Transform(loc.Transformation());
913       }
914       if (edge.Orientation() == TopAbs_REVERSED) {
915         curvTrim->Reverse();
916       }
917
918       // transformation en BSpline reparametree sur [i-1,i]
919       curvBS = Handle(Geom_BSplineCurve)::DownCast(curvTrim);
920       if (curvBS.IsNull()) { 
921         Handle(Geom_Curve) theCurve = curvTrim->BasisCurve();
922         if (theCurve->IsKind(STANDARD_TYPE(Geom_Conic)))
923           {
924             GeomConvert_ApproxCurve appr(curvTrim, Precision::Confusion(), GeomAbs_C1, 16, 14);
925             if (appr.HasResult())
926               curvBS = appr.Curve();
927           }
928         if (curvBS.IsNull())
929           curvBS = GeomConvert::CurveToBSplineCurve(curvTrim);
930       }
931       TColStd_Array1OfReal BSK(1,curvBS->NbKnots());
932       curvBS->Knots(BSK);
933       BSplCLib::Reparametrize(0.,1.,BSK);
934       curvBS->SetKnots(BSK);
935       
936       // initialisation
937       GeomConvert_CompCurveToBSplineCurve CompBS(curvBS);
938
939       for (i=2; i<=NbEdges; i++) {  
940         // read the edge
941         edge =  TopoDS::Edge(shapes((j-1)*NbEdges+i));
942         if (BRep_Tool::Degenerated(edge)) {
943           // edge degeneree : construction d'une courbe ponctuelle
944           TopExp::Vertices(edge,vl,vf);
945           TColgp_Array1OfPnt Extremities(1,2);
946           Extremities(1) = BRep_Tool::Pnt(vf);
947           Extremities(2) = BRep_Tool::Pnt(vl);
948           Handle(Geom_Curve) curv = new Geom_BezierCurve(Extremities);
949           curvTrim = new Geom_TrimmedCurve(curv,
950                                            curv->FirstParameter(),
951                                            curv->LastParameter());
952         }
953         else {
954           // recuperation de la courbe sur l'edge
955           Handle(Geom_Curve) curv = BRep_Tool::Curve(edge, loc, first, last);
956           curvTrim = new Geom_TrimmedCurve(curv, first, last);
957           curvTrim->Transform(loc.Transformation());
958         }
959         if (edge.Orientation() == TopAbs_REVERSED) {
960           curvTrim->Reverse();
961         }
962
963         // transformation en BSpline reparametree sur [i-1,i]
964         curvBS = Handle(Geom_BSplineCurve)::DownCast(curvTrim);
965         if (curvBS.IsNull()) { 
966           Handle(Geom_Curve) theCurve = curvTrim->BasisCurve();
967           if (theCurve->IsKind(STANDARD_TYPE(Geom_Conic)))
968             {
969               GeomConvert_ApproxCurve appr(curvTrim, Precision::Confusion(), GeomAbs_C1, 16, 14);
970               if (appr.HasResult())
971                 curvBS = appr.Curve();
972             }
973           if (curvBS.IsNull())
974             curvBS = GeomConvert::CurveToBSplineCurve(curvTrim);
975         }
976         TColStd_Array1OfReal BSK(1,curvBS->NbKnots());
977         curvBS->Knots(BSK);
978         BSplCLib::Reparametrize(i-1,i,BSK);
979         curvBS->SetKnots(BSK);
980
981         // concatenation
982         CompBS.Add(curvBS, 
983                    Precision::Confusion(),
984                    Standard_True,
985                    Standard_False,
986                    1);
987       }
988
989       // recuperation de la section finale
990       BS = CompBS.BSplineCurve();
991       section.AddCurve(BS);
992
993       // cas des sections bouclantes
994       if (j==jdeb && vClosed) {
995         BS1 = BS;
996       }
997
998     }
999   }
1000
1001   if (w2Point) {
1002     edge =  TopoDS::Edge(shapes(NbSects*NbEdges));
1003     TopExp::Vertices(edge,vl,vf);
1004     TColgp_Array1OfPnt Extremities(1,2);
1005     Extremities(1) = BRep_Tool::Pnt(vf);
1006     Extremities(2) = BRep_Tool::Pnt(vl);
1007     TColStd_Array1OfReal Bounds(1,2);
1008     Bounds(1) = 0.;
1009     Bounds(2) = 1.;
1010     Standard_Integer Deg = 1;
1011     TColStd_Array1OfInteger Mult(1,2);
1012     Mult(1) = Deg+1;
1013     Mult(2) = Deg+1;
1014     Handle(Geom_BSplineCurve) BSPoint
1015       = new Geom_BSplineCurve(Extremities,Bounds,Mult,Deg);
1016     section.AddCurve(BSPoint);
1017   }
1018
1019   section.Perform(Precision::PConfusion());
1020   Handle(GeomFill_Line) line = new GeomFill_Line(NbSects);
1021
1022   Standard_Integer nbIt = 3;
1023   if(myPres3d <= 1.e-3) nbIt = 0;
1024
1025   Standard_Integer degmin = 2, degmax = Max(myDegMax, degmin);
1026   Standard_Boolean SpApprox = Standard_True;
1027
1028   GeomFill_AppSurf anApprox(degmin, degmax, myPres3d, myPres3d, nbIt);
1029   anApprox.SetContinuity(myContinuity);
1030
1031   if(myUseSmoothing) {
1032     anApprox.SetCriteriumWeight(myCritWeights[0], myCritWeights[1], myCritWeights[2]);
1033     anApprox.PerformSmoothing(line, section);
1034   } 
1035   else {
1036     anApprox.SetParType(myParamType);
1037     anApprox.Perform(line, section, SpApprox);
1038   }
1039
1040   if(anApprox.IsDone()) {
1041     surface = 
1042       new Geom_BSplineSurface(anApprox.SurfPoles(), anApprox.SurfWeights(),
1043                             anApprox.SurfUKnots(), anApprox.SurfVKnots(),
1044                             anApprox.SurfUMults(), anApprox.SurfVMults(),
1045                             anApprox.UDegree(), anApprox.VDegree());
1046   }
1047
1048   return surface;
1049   
1050 }
1051
1052 //=======================================================================
1053 //function : FirstShape
1054 //purpose  : 
1055 //=======================================================================
1056
1057 const TopoDS_Shape& BRepOffsetAPI_ThruSections::FirstShape() const
1058 {
1059   return myFirst;
1060 }
1061
1062 //=======================================================================
1063 //function : LastShape
1064 //purpose  : 
1065 //=======================================================================
1066
1067 const TopoDS_Shape& BRepOffsetAPI_ThruSections::LastShape() const
1068 {
1069   return myLast;
1070 }
1071
1072 //=======================================================================
1073 //function : GeneratedFace
1074 //purpose  : 
1075 //=======================================================================
1076
1077 TopoDS_Shape BRepOffsetAPI_ThruSections::GeneratedFace(const TopoDS_Shape& edge) const
1078 {
1079   TopoDS_Shape bid;
1080   if (myGenerated.IsBound(edge)) {
1081     return myGenerated(edge);
1082   }
1083   else {
1084     return bid;
1085   }
1086 }
1087
1088
1089 //=======================================================================
1090 //function : CriteriumWeight
1091 //purpose  : returns the Weights associed  to the criterium used in
1092 //           the  optimization.
1093 //=======================================================================
1094 //
1095 void BRepOffsetAPI_ThruSections::CriteriumWeight(Standard_Real& W1, Standard_Real& W2, Standard_Real& W3) const 
1096 {
1097   W1 = myCritWeights[0];
1098   W2 = myCritWeights[1];
1099   W3 = myCritWeights[2];
1100 }
1101 //=======================================================================
1102 //function : SetCriteriumWeight
1103 //purpose  : 
1104 //=======================================================================
1105
1106 void BRepOffsetAPI_ThruSections::SetCriteriumWeight(const Standard_Real W1, const Standard_Real W2, const Standard_Real W3)
1107 {
1108   if (W1 < 0 || W2 < 0 || W3 < 0 ) Standard_DomainError::Raise();
1109   myCritWeights[0] = W1;
1110   myCritWeights[1] = W2;
1111   myCritWeights[2] = W3;
1112 }
1113 //=======================================================================
1114 //function : SetContinuity
1115 //purpose  : 
1116 //=======================================================================
1117
1118 void BRepOffsetAPI_ThruSections::SetContinuity (const GeomAbs_Shape TheCont)
1119 {
1120   myContinuity = TheCont;
1121 }
1122
1123 //=======================================================================
1124 //function : Continuity
1125 //purpose  : 
1126 //=======================================================================
1127
1128 GeomAbs_Shape BRepOffsetAPI_ThruSections::Continuity () const
1129 {
1130   return myContinuity;
1131 }
1132
1133 //=======================================================================
1134 //function : SetParType
1135 //purpose  : 
1136 //=======================================================================
1137
1138 void BRepOffsetAPI_ThruSections::SetParType (const Approx_ParametrizationType ParType)
1139 {
1140   myParamType = ParType;
1141 }
1142
1143 //=======================================================================
1144 //function : ParType
1145 //purpose  : 
1146 //=======================================================================
1147
1148 Approx_ParametrizationType BRepOffsetAPI_ThruSections::ParType () const
1149 {
1150   return myParamType;
1151 }
1152
1153 //=======================================================================
1154 //function : SetMaxDegree
1155 //purpose  : 
1156 //=======================================================================
1157
1158 void BRepOffsetAPI_ThruSections:: SetMaxDegree(const Standard_Integer MaxDeg)
1159 {
1160   myDegMax = MaxDeg;
1161 }
1162
1163 //=======================================================================
1164 //function : MaxDegree
1165 //purpose  : 
1166 //=======================================================================
1167
1168 Standard_Integer  BRepOffsetAPI_ThruSections::MaxDegree () const
1169 {
1170   return myDegMax;
1171 }
1172
1173 //=======================================================================
1174 //function : SetSmoothing
1175 //purpose  : 
1176 //=======================================================================
1177
1178 void BRepOffsetAPI_ThruSections::SetSmoothing(const Standard_Boolean UseVar)
1179 {
1180   myUseSmoothing = UseVar;
1181 }
1182
1183 //=======================================================================
1184 //function : UseSmoothing
1185 //purpose  : 
1186 //=======================================================================
1187
1188 Standard_Boolean BRepOffsetAPI_ThruSections::UseSmoothing () const
1189 {
1190   return myUseSmoothing;
1191 }
1192
1193
1194
1195
1196