0024180: Eliminate CLang / GCC compiler warning -Wswitch
[occt.git] / src / BRepFill / BRepFill_Pipe.cxx
1 // Created on: 1994-06-07
2 // Created by: Bruno DUMORTIER
3 // Copyright (c) 1994-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
22 #include <BRepFill_Pipe.ixx>
23
24 #include <Standard_ErrorHandler.hxx>
25
26 #include <BRep_Tool.hxx>
27 #include <BRep_Builder.hxx>
28 #include <BRepClass3d_SolidClassifier.hxx>
29 #include <BRepLib_MakeVertex.hxx>
30 #include <BRepTools_Substitution.hxx>
31
32 #include <GeomFill_CorrectedFrenet.hxx>
33 #include <GeomFill_Frenet.hxx>
34 #include <GeomFill_DiscreteTrihedron.hxx>
35 #include <GeomFill_CurveAndTrihedron.hxx>
36
37 #include <BRepFill_SectionPlacement.hxx>
38 #include <BRepFill_ShapeLaw.hxx>
39 #include <BRepFill_Edge3DLaw.hxx>
40 #include <BRepFill_Sweep.hxx>
41
42 #include <GeomAbs_Shape.hxx>
43 #include <TopExp.hxx>
44 #include <TopAbs_ShapeEnum.hxx>
45 #include <TopoDS.hxx>
46 #include <TopoDS_Shell.hxx>
47 #include <TopoDS_Solid.hxx>
48 #include <TopoDS_Compound.hxx>
49 #include <TopoDS_Iterator.hxx>
50 #include <TopTools_DataMapOfShapeInteger.hxx>
51 #include <TColStd_DataMapOfIntegerInteger.hxx>
52 #include <TColStd_DataMapIteratorOfDataMapOfIntegerInteger.hxx>
53
54 #include <Precision.hxx>
55 #include <Standard_NotImplemented.hxx>
56
57 #include <Geom_TrimmedCurve.hxx>
58 #include <Geom_OffsetCurve.hxx>
59 #include <Geom_BSplineCurve.hxx>
60
61 #ifdef DRAW
62 #include <DBRep.hxx>
63 static Standard_Boolean Affich = 0;
64 #endif
65
66 //=======================================================================
67 //function : BRepFill_Pipe
68 //purpose  : 
69 //=======================================================================
70
71 BRepFill_Pipe::BRepFill_Pipe()
72 {
73   myDegmax = 11;
74   mySegmax = 100;
75   myContinuity = GeomAbs_C2;
76   myMode = GeomFill_IsCorrectedFrenet;
77   myForceApproxC1 = Standard_False;
78 }
79
80
81 //=======================================================================
82 //function : BRepFill_Pipe
83 //purpose  : 
84 //=======================================================================
85
86 BRepFill_Pipe::BRepFill_Pipe(const TopoDS_Wire&  Spine,
87                              const TopoDS_Shape& Profile,
88                              const GeomFill_Trihedron aMode,
89                              const Standard_Boolean ForceApproxC1,
90                              const Standard_Boolean KPart)
91                              
92 {
93   myDegmax = 11;
94   mySegmax = 100;
95   
96   myMode = GeomFill_IsCorrectedFrenet;
97   if (aMode == GeomFill_IsFrenet ||
98       aMode == GeomFill_IsCorrectedFrenet ||
99       aMode == GeomFill_IsDiscreteTrihedron)
100     myMode = aMode;
101
102   myContinuity = GeomAbs_C2;
103   if (myMode == GeomFill_IsDiscreteTrihedron)
104     myContinuity = GeomAbs_C0;
105   
106   myForceApproxC1 = ForceApproxC1;
107   Perform(Spine, Profile, KPart);
108 }
109
110
111 //=======================================================================
112 //function : Perform
113 //purpose  : 
114 //=======================================================================
115
116 void BRepFill_Pipe::Perform(const TopoDS_Wire&  Spine,
117                             const TopoDS_Shape& Profile,
118                             const Standard_Boolean /*KPart*/)
119
120 {
121   mySections.Nullify();
122   myFaces.Nullify();
123   myEdges.Nullify();
124
125   mySpine   = Spine;
126   myProfile = Profile;
127
128   DefineRealSegmax();
129
130   BRepTools_WireExplorer wexp;
131   TopoDS_Shape TheProf; 
132
133   Handle(GeomFill_TrihedronLaw) TLaw;
134   switch (myMode)
135   {
136   case GeomFill_IsFrenet:
137     TLaw = new GeomFill_Frenet();
138     break;
139   case GeomFill_IsCorrectedFrenet:
140     TLaw = new GeomFill_CorrectedFrenet();
141     break;
142   case GeomFill_IsDiscreteTrihedron:
143     TLaw = new GeomFill_DiscreteTrihedron();
144     break;
145   default:
146     break;
147   }
148   Handle(GeomFill_CurveAndTrihedron) Loc = 
149     new (GeomFill_CurveAndTrihedron) (TLaw);
150   myLoc = new (BRepFill_Edge3DLaw) (mySpine, Loc);
151   if (myLoc->NbLaw() == 0) {
152     return; // Degenerated case
153   }
154   myLoc->TransformInG0Law(); // Set into continuity
155     
156   BRepFill_SectionPlacement Place(myLoc, Profile);
157   myTrsf = Place.Transformation();
158
159   TopLoc_Location Loc2(myTrsf), Loc1;
160   Loc1 = Profile.Location();
161   TopoDS_Shape aux;
162   TheProf =  myProfile;
163   TheProf.Location(Loc2.Multiplied(Loc1));
164  
165   // Construct First && Last Shape
166   Handle(GeomFill_LocationLaw) law;
167
168   gp_Mat M;
169   gp_Vec V;
170   gp_Trsf fila;
171   Standard_Real first, last;
172   myLoc->Law(1)->GetDomain(first, last);
173   myLoc->Law(1)->D0(first, M, V);
174     fila.SetValues(M(1,1), M(1,2), M(1,3), V.X(),
175                    M(2,1), M(2,2), M(2,3), V.Y(),
176                    M(3,1), M(3,2), M(3,3), V.Z(),
177                    1.e-12, 1.e-14);
178
179   fila.Multiply(myTrsf);
180   TopLoc_Location LocFirst(fila);
181   myFirst = myProfile;
182   if ( ! LocFirst.IsIdentity()) {
183     myFirst.Location( LocFirst.Multiplied(myProfile.Location()) );
184   }
185
186   myLoc->Law(myLoc->NbLaw())->GetDomain(first, last);
187   myLoc->Law(myLoc->NbLaw())->D0(last,M, V);
188 //    try { // Not good, but there are no other means to test SetValues
189   fila.SetValues(M(1,1), M(1,2), M(1,3), V.X(),
190                  M(2,1), M(2,2), M(2,3), V.Y(),
191                  M(3,1), M(3,2), M(3,3), V.Z(),
192                  1.e-12, 1.e-14);
193   fila.Multiply(myTrsf);
194   TopLoc_Location LocLast(fila);
195   if (! myLoc->IsClosed() || LocFirst != LocLast) {
196     myLast = myProfile;
197     if ( ! LocLast.IsIdentity()) {
198       myLast.Location(LocLast.Multiplied(myProfile.Location()) );
199     }
200   }
201   else {
202     myLast = myFirst;
203   }
204 #if DRAW
205   if (Affich) {
206     DBRep::Set("theprof",  TheProf);
207     DBRep::Set("thefirst", myFirst);
208     DBRep::Set("thelast" , myLast);
209  }
210 #endif
211  
212   myShape = MakeShape(TheProf, myFirst, myLast);
213 }
214
215
216 //=======================================================================
217 //function : Spine
218 //purpose  : 
219 //=======================================================================
220
221 const TopoDS_Shape& BRepFill_Pipe::Spine() const 
222 {
223   return mySpine;
224 }
225
226 //=======================================================================
227 //function : Profile
228 //purpose  : 
229 //=======================================================================
230
231 const TopoDS_Shape& BRepFill_Pipe::Profile() const 
232 {
233   return myProfile;
234 }
235
236 //=======================================================================
237 //function : Shape
238 //purpose  : 
239 //=======================================================================
240
241 const TopoDS_Shape& BRepFill_Pipe::Shape() const 
242 {
243   return myShape;
244 }
245
246
247 //=======================================================================
248 //function : FirstShape
249 //purpose  : 
250 //=======================================================================
251
252 const TopoDS_Shape& BRepFill_Pipe::FirstShape() const 
253 {
254   return myFirst;
255 }
256
257
258 //=======================================================================
259 //function : LastShape
260 //purpose  : 
261 //=======================================================================
262
263 const TopoDS_Shape& BRepFill_Pipe::LastShape() const 
264 {
265   return myLast;
266 }
267
268
269 //=======================================================================
270 //function : Face
271 //purpose  : 
272 //=======================================================================
273
274 TopoDS_Face BRepFill_Pipe::Face(const TopoDS_Edge& ESpine,
275                                 const TopoDS_Edge& EProfile)
276 {
277   TopoDS_Face theFace;
278
279   if ( BRep_Tool::Degenerated(EProfile))
280     return theFace;
281
282   Standard_Integer ii, ispin = 0, iprof = 0, count = 0;
283
284   // *************************************************
285   // Search if EProfile is an edge of myProfile
286   // *************************************************
287   iprof = FindEdge(myProfile, EProfile, count);
288
289   if (!iprof) Standard_DomainError::Raise(
290               "BRepFill_Pipe::Face : Edge not in the Profile");
291
292
293   // *************************************************
294   // Search if ESpine  is an edge of mySpine and find 
295   // the index of the corresponding Filler
296   // *************************************************
297  for (ii=1; ii<=myLoc->NbLaw() && (!ispin); ii++) 
298     if  (ESpine.IsSame(myLoc->Edge(ii))) ispin = ii;
299
300   if (!ispin) Standard_DomainError::Raise(
301     "BRepFill_Pipe::Edge  : Edge not in the Spine");
302
303   theFace = TopoDS::Face(myFaces->Value(iprof, ispin));
304   return theFace;
305
306 }
307
308 //=======================================================================
309 //function : Edge
310 //purpose  : 
311 //=======================================================================
312 TopoDS_Edge BRepFill_Pipe::Edge(const TopoDS_Edge&   ESpine,
313                                 const TopoDS_Vertex& VProfile)
314 {
315   Standard_Integer ii, ispin = 0, iprof = 0, count = 0;;
316
317   // *************************************************
318   // Search if VProfile is a Vertex of myProfile
319   // *************************************************
320   iprof = FindVertex(myProfile, VProfile, count);
321   if (!iprof) Standard_DomainError::Raise(
322         "BRepFill_Pipe::Edge : Vertex not in the Profile");
323
324
325   // *************************************************
326   // Search if ESpine  is an edge of mySpine and find 
327   // the index of the corresponding Filler
328   // *************************************************
329    
330   for (ii=1; ii<=myLoc->NbLaw() && (!ispin); ii++) 
331     if  (ESpine.IsSame(myLoc->Edge(ii))) ispin = ii;
332
333   if (!ispin) Standard_DomainError::Raise(
334     "BRepFill_Pipe::Edge  : Edge not in the Spine");
335
336
337   // *************************************************
338   // Generate the corresponding Shape
339   // *************************************************  
340   TopoDS_Edge theEdge;
341   theEdge = TopoDS::Edge(myEdges->Value(iprof, ispin));
342
343   return theEdge;
344
345 }
346
347
348 //=======================================================================
349 //function : Section
350 //purpose  : 
351 //=======================================================================
352
353 TopoDS_Shape BRepFill_Pipe::Section(const TopoDS_Vertex& VSpine) const 
354 {
355   TopoDS_Iterator it, itv;
356
357   Standard_Integer ii, ispin = 0;
358
359   TopoDS_Shape curSect = myProfile;
360
361   // *************************************************
362   // Search if ESpine  is an edge of mySpine and find 
363   // the index of the corresponding Filler
364   // *************************************************
365
366   // iterate on all the edges of mySpine
367  for (ii=1; ii<=myLoc->NbLaw()+1 && (!ispin); ii++) 
368     if  (VSpine.IsSame(myLoc->Vertex(ii))) ispin = ii;
369
370   if (!ispin) Standard_DomainError::Raise(
371     "BRepFill_Pipe::Section  : Vertex not in the Spine");
372
373   BRep_Builder B;
374   TopoDS_Compound Comp; 
375   B.MakeCompound(Comp);
376   for (ii=1; ii<=mySections->ColLength(); ii++)
377     B.Add(Comp, mySections->Value(ii, ispin));
378   
379   return Comp;
380 }
381
382 //=======================================================================
383 //function : PipeLine
384 //purpose  : Construct a wire by sweeping of a point
385 //=======================================================================
386
387 TopoDS_Wire BRepFill_Pipe::PipeLine(const gp_Pnt& Point) const
388 {
389  // Postioning 
390  gp_Pnt P;
391  P = Point;
392  P.Transform(myTrsf);
393
394  BRepLib_MakeVertex MkV(P); 
395  Handle(BRepFill_ShapeLaw) Section = 
396         new (BRepFill_ShapeLaw) (MkV.Vertex());
397
398  // Sweeping
399  BRepFill_Sweep MkSw(Section, myLoc, Standard_True);
400  MkSw.SetForceApproxC1(myForceApproxC1);
401  MkSw.Build( BRepFill_Modified, myContinuity, GeomFill_Location, myDegmax, mySegmax );
402  TopoDS_Shape aLocalShape = MkSw.Shape();
403  return TopoDS::Wire(aLocalShape);
404 // return TopoDS::Wire(MkSw.Shape());
405 }
406
407 //=======================================================================
408 //function : MakeShape
409 //purpose  : 
410 //=======================================================================
411
412 TopoDS_Shape BRepFill_Pipe::MakeShape(const TopoDS_Shape& S,
413                                       const TopoDS_Shape& FirstShape,
414                                       const TopoDS_Shape& LastShape)
415 {
416   TopoDS_Shape result;
417   BRep_Builder B;
418   Standard_Boolean explode = Standard_False; 
419   TopoDS_Shape TheS, TheFirst, TheLast;
420   Standard_Integer InitialLength = 0;
421   TheS = S;
422   TheFirst = FirstShape;
423   TheLast = LastShape;
424   if (! myFaces.IsNull()) InitialLength = myFaces->ColLength();
425
426   // there are two kinds of generation
427   //  1. generate with S from each Filler (Vertex, Edge)
428   //  2. call MakeShape recursively on the subshapes of S
429   //
430   // explode is True in the second case
431
432   // create the result empty
433
434   switch (S.ShapeType()) {
435
436   case TopAbs_VERTEX :
437     {
438       B.MakeWire(TopoDS::Wire(result));
439       break;
440     }
441           
442   case TopAbs_EDGE :
443     {
444       TopoDS_Wire W;
445       B.MakeShell(TopoDS::Shell(result));
446       B.MakeWire(W);
447       B.Add(W, S);
448       W.Closed(S.Closed());
449       TheS = W;
450       if (!FirstShape.IsNull()) {
451         B.MakeWire(W);
452         B.Add(W, FirstShape);
453         W.Closed(FirstShape.Closed());
454         TheFirst = W;
455       }
456       if (!LastShape.IsNull()) {
457         B.MakeWire(W);
458         B.Add(W, LastShape);
459         W.Closed(LastShape.Closed());
460         TheLast = W;
461       }
462       break;
463     }
464           
465   case TopAbs_WIRE :
466     B.MakeShell(TopoDS::Shell(result));
467     break;
468
469   case TopAbs_FACE :
470     {
471       B.MakeShell(TopoDS::Shell(result));
472       explode = Standard_True;
473       if ( !mySpine.Closed() && !TheFirst.IsNull()) {
474          B.Add(result, TheFirst.Reversed());
475       }
476       break;
477     }
478
479   case TopAbs_SHELL :
480     {
481       B.MakeCompSolid(TopoDS::CompSolid(result));
482       explode = Standard_True;
483       break;
484     }
485
486   case TopAbs_SOLID :
487   case TopAbs_COMPSOLID :
488     Standard_DomainError::Raise("BRepFill_Pipe::SOLID or COMPSOLID");
489     break;
490
491   case TopAbs_COMPOUND :
492     {
493       B.MakeCompound(TopoDS::Compound(result));
494       explode = Standard_True;
495       break;
496     }
497   default:
498     break;
499   }
500
501   if (explode) {
502     // add the subshapes
503     TopoDS_Iterator itFirst, itLast;
504     TopoDS_Shape first, last;
505     if (!TheFirst.IsNull()) itFirst.Initialize(TheFirst);
506     if (!TheLast.IsNull()) itLast.Initialize(TheLast);
507
508     for (TopoDS_Iterator it(S); it.More(); it.Next()) {
509       if (!TheFirst.IsNull()) first = itFirst.Value();
510       if (!TheLast.IsNull())  last = itLast.Value();
511       if (TheS.ShapeType() == TopAbs_FACE ) 
512         MakeShape(it.Value(), first, last);
513       else
514         B.Add(result,MakeShape(it.Value(), first, last));
515
516       if (!TheFirst.IsNull()) itFirst.Next();
517       if (!TheLast.IsNull())  itLast.Next();
518     }
519   }
520   
521   else {
522     if (TheS.ShapeType() == TopAbs_VERTEX ) {
523      Handle(BRepFill_ShapeLaw) Section = 
524         new (BRepFill_ShapeLaw) (TopoDS::Vertex(TheS));
525       BRepFill_Sweep MkSw(Section, myLoc, Standard_True);
526       MkSw.SetForceApproxC1(myForceApproxC1);
527       MkSw.Build( BRepFill_Modified, myContinuity, GeomFill_Location, myDegmax, mySegmax );
528       result = MkSw.Shape();
529     }
530
531     if (TheS.ShapeType() == TopAbs_WIRE ) {
532       Handle(BRepFill_ShapeLaw) Section = 
533         new (BRepFill_ShapeLaw) (TopoDS::Wire(TheS));
534       BRepFill_Sweep MkSw(Section, myLoc, Standard_True);
535       MkSw.SetBounds(TopoDS::Wire(TheFirst), 
536                      TopoDS::Wire(TheLast));
537       MkSw.SetForceApproxC1(myForceApproxC1);
538       MkSw.Build( BRepFill_Modified, myContinuity, GeomFill_Location, myDegmax, mySegmax );
539       result = MkSw.Shape();
540
541       // Labeling of elements
542       if (mySections.IsNull()) {
543         myFaces    = MkSw.SubShape();
544         mySections = MkSw.Sections();
545         myEdges    = MkSw.InterFaces();
546       }
547       else {
548         Handle(TopTools_HArray2OfShape) Aux, Somme;
549         Standard_Integer length;
550         Standard_Integer ii, jj, kk;
551         const Standard_Integer aNbFaces    = myFaces->ColLength();
552         const Standard_Integer aNbEdges    = myEdges->ColLength();
553         const Standard_Integer aNbSections = mySections->ColLength();
554
555         Aux = MkSw.SubShape();
556         length = Aux->ColLength() + myFaces->ColLength(); 
557         Somme = new (TopTools_HArray2OfShape) (1, length, 1, 
558                                                Aux->RowLength());
559         for (jj=1; jj<=myFaces->RowLength(); jj++) {
560           for (ii=1; ii<=myFaces->ColLength(); ii++)
561             Somme->SetValue(ii, jj, myFaces->Value(ii, jj));
562  
563           for (kk=1, ii=myFaces->ColLength()+1; 
564                kk <=Aux->ColLength(); kk++, ii++)
565             Somme->SetValue(ii, jj, Aux->Value(kk, jj));
566         }
567         myFaces = Somme;    
568
569         Aux = MkSw.Sections();
570         length = Aux->ColLength() + mySections->ColLength(); 
571         Somme = new (TopTools_HArray2OfShape) (1, length, 1, 
572                                                Aux->RowLength());
573         for (jj=1; jj<=mySections->RowLength(); jj++) {
574           for (ii=1; ii<=mySections->ColLength(); ii++)
575             Somme->SetValue(ii, jj, mySections->Value(ii, jj));
576  
577           for (kk=1, ii=mySections->ColLength()+1; 
578                kk <=Aux->ColLength(); kk++, ii++)
579             Somme->SetValue(ii, jj, Aux->Value(kk, jj));   
580         }
581         mySections = Somme;
582
583         Aux = MkSw.InterFaces();
584         length = Aux->ColLength() + myEdges->ColLength(); 
585         Somme = new (TopTools_HArray2OfShape) (1, length, 1, 
586                                                Aux->RowLength());
587         for (jj=1; jj<=myEdges->RowLength(); jj++) {
588           for (ii=1; ii<=myEdges->ColLength(); ii++)
589             Somme->SetValue(ii, jj, myEdges->Value(ii, jj));
590  
591           for (kk=1, ii=myEdges->ColLength()+1; 
592                kk <=Aux->ColLength(); kk++, ii++)
593             Somme->SetValue(ii, jj, Aux->Value(kk, jj));   
594         }
595
596         myEdges = Somme;
597
598         // Perform sharing faces
599         result = ShareFaces(result, aNbFaces, aNbEdges, aNbSections);
600       }
601     }
602   }
603       
604   if ( TheS.ShapeType() == TopAbs_FACE ) {
605     Standard_Integer ii, jj;
606     TopoDS_Face F;
607     for (ii=InitialLength+1; ii<=myFaces->ColLength(); ii++) {
608       for (jj=1; jj<=myFaces->RowLength(); jj++) {
609         F = TopoDS::Face(myFaces->Value(ii, jj));
610         if (!F.IsNull()) B.Add(result, F);
611       }
612     }
613
614     if ( !mySpine.Closed()) {
615       // if Spine is not closed 
616       // add the last face of the solid
617       B.Add(result, TopoDS::Face(TheLast));
618     }
619
620     TopoDS_Solid solid;
621     BRep_Builder BS;
622     BS.MakeSolid(solid);
623
624     result.Closed(Standard_True);
625     BS.Add(solid,TopoDS::Shell(result));
626
627     BRepClass3d_SolidClassifier SC(solid);
628     SC.PerformInfinitePoint(Precision::Confusion());
629     if ( SC.State() == TopAbs_IN) {
630       BS.MakeSolid(solid);
631       TopoDS_Shape aLocalShape = result.Reversed();
632       BS.Add(solid,TopoDS::Shell(aLocalShape));
633 //      BS.Add(solid,TopoDS::Shell(result.Reversed()));
634     }
635     return solid;
636   }
637   else {
638     return result;
639   }
640 }
641
642 //============================================================================
643 //function : FindEdge
644 //purpose  : Find the number of edge corresponding to the edge of the profile.
645 //============================================================================
646
647 Standard_Integer BRepFill_Pipe::FindEdge(const TopoDS_Shape& S,
648                                          const TopoDS_Edge& E,
649                                          Standard_Integer& InitialLength) const
650 {
651   Standard_Integer result = 0;
652
653   switch (S.ShapeType()) {
654           
655   case TopAbs_EDGE :
656     {
657       InitialLength++;
658       if (S.IsSame(E)) result = InitialLength;
659       break;
660     }
661           
662   case TopAbs_WIRE :
663     {
664       Standard_Integer ii = InitialLength+1;
665       Handle(BRepFill_ShapeLaw) Section = 
666         new (BRepFill_ShapeLaw) (TopoDS::Wire(S), Standard_False);
667       InitialLength += Section->NbLaw();
668      
669       for (; (ii<=InitialLength) && (!result); ii++) {
670         if (E.IsSame(Section->Edge(ii)) ) result = ii;
671       }
672       break;
673     }
674
675   case TopAbs_FACE :
676   case TopAbs_SHELL :
677   case TopAbs_COMPOUND :
678     {
679      for (TopoDS_Iterator it(S); it.More() && (!result); it.Next())
680        result = FindEdge(it.Value(), E, InitialLength );
681      break;
682     }
683
684   case TopAbs_SOLID :
685   case TopAbs_COMPSOLID :
686     Standard_DomainError::Raise("BRepFill_Pipe::SOLID or COMPSOLID");
687     break;
688   default:
689     break;
690   }
691
692   return result; 
693 }
694
695 //=======================================================================
696 //function : FindVertex
697 //purpose  : Find the number of edge corresponding to an edge of the profile.
698 //=======================================================================
699
700 Standard_Integer BRepFill_Pipe::FindVertex(const TopoDS_Shape& S,
701                                            const TopoDS_Vertex& V,
702                                            Standard_Integer& InitialLength) const
703 {
704   Standard_Integer result = 0;
705
706   switch (S.ShapeType()) {
707   case TopAbs_VERTEX :
708     {
709       InitialLength++;
710       if (S.IsSame(V)) result = InitialLength;
711       break;
712     }
713           
714   case TopAbs_EDGE :
715     {
716       TopoDS_Vertex VF, VL;
717       TopExp::Vertices(TopoDS::Edge(S), VF, VL);
718       if (S.Orientation() == TopAbs_REVERSED) {
719         TopoDS_Vertex aux;
720         aux = VF; VF = VL; VL = aux;
721       }
722       if (VF.IsSame(V)) result = InitialLength+1;
723       else if (VL.IsSame(V)) result = InitialLength+2;
724       InitialLength += 2;
725       break;
726     }
727           
728   case TopAbs_WIRE :
729     {
730       Standard_Integer ii = InitialLength+1;
731       Handle(BRepFill_ShapeLaw) Section = 
732         new (BRepFill_ShapeLaw) (TopoDS::Wire(S), Standard_False);
733       InitialLength += Section->NbLaw()+1;
734      
735       for (; (ii<=InitialLength) && (!result); ii++) {
736         if (V.IsSame(Section->Vertex(ii, 0.)) ) result = ii;
737       }
738       break;
739     }
740
741   case TopAbs_FACE :
742   case TopAbs_SHELL :
743   case TopAbs_COMPOUND :
744     {
745      for (TopoDS_Iterator it(S); it.More() && (!result); it.Next())
746        result = FindVertex(it.Value(), V, InitialLength);
747      break;
748     }
749
750   case TopAbs_SOLID :
751   case TopAbs_COMPSOLID :
752     Standard_DomainError::Raise("BRepFill_Pipe::SOLID or COMPSOLID");
753     break;
754   default:
755     break;
756   }
757
758   return result; 
759 }
760
761 //=======================================================================
762 //function : DefineRealSegmax
763 //purpose  : Defines the real number of segments
764 //           required in the case of bspline spine
765 //=======================================================================
766
767 void BRepFill_Pipe::DefineRealSegmax()
768 {
769   Standard_Integer RealSegmax = 0;
770
771   TopoDS_Iterator iter(mySpine);
772   for (; iter.More(); iter.Next())
773     {
774       TopoDS_Edge E = TopoDS::Edge(iter.Value());
775       Standard_Real first, last;
776       Handle(Geom_Curve) C = BRep_Tool::Curve( E, first, last );
777       if (C.IsNull())
778         continue;
779       while (C->DynamicType() == STANDARD_TYPE(Geom_TrimmedCurve) ||
780              C->DynamicType() == STANDARD_TYPE(Geom_OffsetCurve))
781         {
782           if (C->DynamicType() == STANDARD_TYPE(Geom_TrimmedCurve))
783             C = (*((Handle(Geom_TrimmedCurve)*)&C))->BasisCurve();
784           if (C->DynamicType() == STANDARD_TYPE(Geom_OffsetCurve))
785             C = (*((Handle(Geom_OffsetCurve)*)&C))->BasisCurve();
786         }
787       if (C->DynamicType() == STANDARD_TYPE(Geom_BSplineCurve))
788         {
789           const Handle(Geom_BSplineCurve)& BC = *((Handle(Geom_BSplineCurve)*)&C);
790           Standard_Integer NbKnots = BC->NbKnots();
791           Standard_Integer RealNbKnots = NbKnots;
792           if (first > BC->FirstParameter())
793             {
794               Standard_Integer I1, I2;
795               BC->LocateU( first, Precision::PConfusion(), I1, I2 );
796               RealNbKnots -= I1-1;
797             }
798           if (last < BC->LastParameter())
799             {
800               Standard_Integer I1, I2;
801               BC->LocateU( last, Precision::PConfusion(), I1, I2 );
802               RealNbKnots -= NbKnots-I2;
803             }
804           RealSegmax += RealNbKnots-1;
805         }
806     }
807
808   if (mySegmax < RealSegmax)
809     mySegmax = RealSegmax;
810 }
811
812 //=======================================================================
813 //function : ShareFaces
814 //purpose  : 
815 //=======================================================================
816
817 TopoDS_Shape BRepFill_Pipe::ShareFaces
818                 (const TopoDS_Shape &theShape,
819                  const Standard_Integer theInitialFacesLen,
820                  const Standard_Integer theInitialEdgesLen,
821                  const Standard_Integer theInitialSectionsLen)
822 {
823   TopoDS_Shape aResult = theShape;
824   // Check if there are shapes to be shared.
825   TopTools_DataMapOfShapeInteger aMapBndEdgeIndex;
826   TColStd_DataMapOfIntegerInteger aMapNewOldFIndex;
827   TColStd_DataMapOfIntegerInteger aMapNewOldEIndex;
828   TopTools_MapOfShape aMapUsedVtx;
829   TopExp_Explorer anExp;
830   Standard_Integer i;
831   Standard_Integer ii;
832   Standard_Integer jj;
833   BRep_Builder aBuilder;
834
835   // Check the first and last J index of myFaces.
836   for (i = 1; i <= 2; i++) {
837     // Compute jj index of faces.
838     if (i == 1) {
839       jj = 1;
840     } else {
841       jj = myFaces->RowLength();
842
843       if (jj == 1) {
844         break;
845       }
846     }
847
848     // Fill the map of boundary edges on initial faces.
849     for (ii = 1; ii <= theInitialFacesLen; ii++) {
850       anExp.Init(myFaces->Value(ii, jj), TopAbs_EDGE);
851   
852       for (; anExp.More(); anExp.Next()) {
853         aMapBndEdgeIndex.Bind(anExp.Current(), ii);
854       }
855     }
856
857     // Check if edges of newly created faces are shared with old ones.
858     for (ii = theInitialFacesLen + 1; ii <= myFaces->ColLength(); ii++) {
859       anExp.Init(myFaces->Value(ii, jj), TopAbs_EDGE);
860   
861       for (; anExp.More(); anExp.Next()) {
862         if (aMapBndEdgeIndex.IsBound(anExp.Current())) {
863           // This row should be replaced.
864           Standard_Integer anOldIndex = aMapBndEdgeIndex.Find(anExp.Current());
865
866           aMapNewOldFIndex.Bind(ii, anOldIndex);
867
868           // Find corresponding new and old edges indices.
869           TopoDS_Vertex aV[2];
870           TopExp::Vertices(TopoDS::Edge(anExp.Current()), aV[0], aV[1]);
871           Standard_Integer ie;
872
873           // Compute jj index of edges.
874           Standard_Integer je = (i == 1 ? 1 : myEdges->RowLength());
875
876           for (Standard_Integer j = 0; j < 2; j++) {
877             if (aMapUsedVtx.Contains(aV[j])) {
878               // This vertex is treated.
879               continue;
880             }
881   
882             // Find old index.
883             Standard_Integer iEOld = -1;
884             TopoDS_Vertex aVE[2];
885        
886             for (ie = 1; ie <= theInitialEdgesLen; ie++) {
887               const TopoDS_Shape &anEdge = myEdges->Value(ie, je);
888        
889               TopExp::Vertices(TopoDS::Edge(anEdge), aVE[0], aVE[1]);
890        
891               if (aV[j].IsSame(aVE[0]) || aV[j].IsSame(aVE[1])) {
892                 iEOld = ie;
893                 break;
894               }
895             }
896        
897             if (iEOld > 0) {
898               // Find new index.
899               for (ie = theInitialEdgesLen+1; ie <= myEdges->ColLength(); ie++) {
900                 const TopoDS_Shape &anEdge = myEdges->Value(ie, je);
901        
902                 TopExp::Vertices(TopoDS::Edge(anEdge), aVE[0], aVE[1]);
903        
904                 if (aV[j].IsSame(aVE[0]) || aV[j].IsSame(aVE[1])) {
905                   // This row should be replaced.
906                   aMapNewOldEIndex.Bind(ie, iEOld);
907                   aMapUsedVtx.Add(aV[j]);
908                   break;
909                 }
910               }
911             }
912           }
913
914           break;
915         }
916       }
917     }
918   }
919
920   if (!aMapNewOldFIndex.IsEmpty()) {
921     TColStd_DataMapIteratorOfDataMapOfIntegerInteger anIter(aMapNewOldFIndex);
922     TopTools_ListOfShape   aListShape;
923     BRepTools_Substitution aSubstitute;
924
925     for (; anIter.More(); anIter.Next()) {
926       const Standard_Integer aNewIndex  = anIter.Key();
927       const Standard_Integer anOldIndex = anIter.Value();
928
929       // Change new faces by old ones.
930       for (jj = 1; jj <= myFaces->RowLength(); jj++) {
931         const TopoDS_Shape &aNewFace  = myFaces->Value(aNewIndex, jj);
932         const TopoDS_Shape &anOldFace = myFaces->Value(anOldIndex, jj);
933
934         if (!aSubstitute.IsCopied(aNewFace)) {
935           aListShape.Append(anOldFace.Oriented(TopAbs_REVERSED));
936           aSubstitute.Substitute(aNewFace, aListShape);
937           aListShape.Clear();
938         }
939       }
940     }
941
942     // Change new edges by old ones.
943     for (anIter.Initialize(aMapNewOldEIndex); anIter.More(); anIter.Next()) {
944       const Standard_Integer aNewIndex  = anIter.Key();
945       const Standard_Integer anOldIndex = anIter.Value();
946
947       for (jj = 1; jj <= myEdges->RowLength(); jj++) {
948         const TopoDS_Shape &aNewEdge  = myEdges->Value(aNewIndex, jj);
949         const TopoDS_Shape &anOldEdge = myEdges->Value(anOldIndex, jj);
950
951         if (!aSubstitute.IsCopied(aNewEdge)) {
952           aListShape.Append(anOldEdge.Oriented(TopAbs_FORWARD));
953           aSubstitute.Substitute(aNewEdge, aListShape);
954           aListShape.Clear();
955
956           // Change new vertices by old ones.
957           TopoDS_Iterator aNewIt(aNewEdge);
958           TopoDS_Iterator anOldIt(anOldEdge);
959
960           for (; aNewIt.More() && anOldIt.More();
961                                   aNewIt.Next(), anOldIt.Next()) {
962             if (!aNewIt.Value().IsSame(anOldIt.Value())) {
963               if (!aSubstitute.IsCopied(aNewIt.Value())) {
964                 aListShape.Append(anOldIt.Value().Oriented(TopAbs_FORWARD));
965                 aSubstitute.Substitute(aNewIt.Value(), aListShape);
966                 aListShape.Clear();
967               }
968             }
969           }
970         }
971       }
972     }
973
974     // Perform substitution.
975     aSubstitute.Build(aResult);
976
977     if (aSubstitute.IsCopied(aResult)) {
978       // Get copied shape.
979       const TopTools_ListOfShape& listSh = aSubstitute.Copy(aResult);
980
981       aResult = listSh.First();
982
983       // Update original faces with copied ones.
984       for (ii = theInitialFacesLen + 1; ii <= myFaces->ColLength(); ii++) {
985         for (jj = 1; jj <= myFaces->RowLength(); jj++) {
986           TopoDS_Shape anOldFace = myFaces->Value(ii, jj); // Copy
987
988           if (aSubstitute.IsCopied(anOldFace)) {
989             const TopTools_ListOfShape& aList = aSubstitute.Copy(anOldFace);
990
991             if(!aList.IsEmpty()) {
992               // Store copied face.
993               const TopoDS_Shape &aCopyFace = aList.First();
994               TopAbs_Orientation anOri = anOldFace.Orientation();
995               const Standard_Boolean isShared = aMapNewOldFIndex.IsBound(ii);
996
997               if (isShared) {
998                 // Reverse the orientation for shared face.
999                 anOri = TopAbs::Reverse(anOri);
1000               }
1001
1002               myFaces->SetValue(ii, jj, aCopyFace.Oriented(anOri));
1003
1004               // Check if it is necessary to update PCurves on this face.
1005               if (!isShared) {
1006                 TopoDS_Face anOldF = TopoDS::Face(anOldFace);
1007                 TopoDS_Face aCopyF = TopoDS::Face(aCopyFace);
1008
1009                 anOldF.Orientation(TopAbs_FORWARD);
1010                 anExp.Init(anOldF, TopAbs_EDGE);
1011
1012                 for (; anExp.More(); anExp.Next()) {
1013                   const TopoDS_Shape &anOldEdge = anExp.Current();
1014
1015                   if (aSubstitute.IsCopied(anOldEdge)) {
1016                     const TopTools_ListOfShape& aListE =
1017                       aSubstitute.Copy(anOldEdge);
1018
1019                     if(!aListE.IsEmpty()) {
1020                       // This edge is copied. Check if there is a PCurve
1021                       // on the face.
1022                       TopoDS_Edge aCopyE = TopoDS::Edge(aListE.First());
1023                       Standard_Real aFirst;
1024                       Standard_Real aLast;
1025                       Handle(Geom2d_Curve) aPCurve = BRep_Tool::CurveOnSurface
1026                           (aCopyE, aCopyF, aFirst, aLast);
1027
1028                       if (aPCurve.IsNull()) {
1029                         // There is no pcurve copy it from the old edge.
1030                         TopoDS_Edge anOldE = TopoDS::Edge(anOldEdge);
1031
1032                         aPCurve = BRep_Tool::CurveOnSurface
1033                           (anOldE, anOldF, aFirst, aLast);
1034
1035                         if (aPCurve.IsNull() == Standard_False) {
1036                           // Update the shared edge with PCurve from new Face.
1037                           Standard_Real aTol = Max(BRep_Tool::Tolerance(anOldE),
1038                                BRep_Tool::Tolerance(aCopyE));
1039
1040                           aBuilder.UpdateEdge(aCopyE, aPCurve, aCopyF, aTol);
1041                         }
1042                       }
1043                     }
1044                   }
1045                 }
1046               }
1047             }
1048           }
1049         }
1050       }
1051
1052       // Update new edges with shared ones.
1053       for (ii = theInitialEdgesLen + 1; ii <= myEdges->ColLength(); ii++) {
1054         for (jj = 1; jj <= myEdges->RowLength(); jj++) {
1055           const TopoDS_Shape &aLocalShape = myEdges->Value(ii, jj);
1056
1057           if (aSubstitute.IsCopied(aLocalShape)) {
1058             const TopTools_ListOfShape& aList = aSubstitute.Copy(aLocalShape);
1059
1060             if(!aList.IsEmpty()) {
1061               const TopAbs_Orientation anOri = TopAbs_FORWARD;
1062
1063               myEdges->SetValue(ii, jj, aList.First().Oriented(anOri));
1064             }
1065           }
1066         }
1067       }
1068
1069       // Update new sections with shared ones.
1070       for (ii = theInitialSectionsLen+1; ii <= mySections->ColLength(); ii++) {
1071         for (jj = 1; jj <= mySections->RowLength(); jj++) {
1072           const TopoDS_Shape &aLocalShape = mySections->Value(ii, jj);
1073
1074           if (aSubstitute.IsCopied(aLocalShape)) {
1075             const TopTools_ListOfShape& aList = aSubstitute.Copy(aLocalShape);
1076
1077             if(!aList.IsEmpty()) {
1078               const TopAbs_Orientation anOri = TopAbs_FORWARD;
1079
1080               mySections->SetValue(ii, jj, aList.First().Oriented(anOri));
1081             }
1082           }
1083         }
1084       }
1085     }
1086   }
1087
1088   return aResult;
1089 }