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