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