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