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