2b4d5b990dd27194b7c991e42b9f78f23cad1d6b
[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
846           // Compute jj index of edges.
847           Standard_Integer je = (i == 1 ? 1 : myEdges->RowLength());
848
849           for (Standard_Integer j = 0; j < 2; j++) {
850             if (aMapUsedVtx.Contains(aV[j])) {
851               // This vertex is treated.
852               continue;
853             }
854   
855             // Find old index.
856             Standard_Integer iEOld = -1;
857             TopoDS_Vertex aVE[2];
858        
859             for (ie = 1; ie <= theInitialEdgesLen; ie++) {
860               const TopoDS_Shape &anEdge = myEdges->Value(ie, je);
861        
862               TopExp::Vertices(TopoDS::Edge(anEdge), aVE[0], aVE[1]);
863        
864               if (aV[j].IsSame(aVE[0]) || aV[j].IsSame(aVE[1])) {
865                 iEOld = ie;
866                 break;
867               }
868             }
869        
870             if (iEOld > 0) {
871               // Find new index.
872               for (ie = theInitialEdgesLen+1; ie <= myEdges->ColLength(); ie++) {
873                 const TopoDS_Shape &anEdge = myEdges->Value(ie, je);
874        
875                 TopExp::Vertices(TopoDS::Edge(anEdge), aVE[0], aVE[1]);
876        
877                 if (aV[j].IsSame(aVE[0]) || aV[j].IsSame(aVE[1])) {
878                   // This row should be replaced.
879                   aMapNewOldEIndex.Bind(ie, iEOld);
880                   aMapUsedVtx.Add(aV[j]);
881                   break;
882                 }
883               }
884             }
885           }
886
887           break;
888         }
889       }
890     }
891   }
892
893   if (!aMapNewOldFIndex.IsEmpty()) {
894     TColStd_DataMapIteratorOfDataMapOfIntegerInteger anIter(aMapNewOldFIndex);
895     TopTools_ListOfShape   aListShape;
896     BRepTools_Substitution aSubstitute;
897
898     for (; anIter.More(); anIter.Next()) {
899       const Standard_Integer aNewIndex  = anIter.Key();
900       const Standard_Integer anOldIndex = anIter.Value();
901
902       // Change new faces by old ones.
903       for (jj = 1; jj <= myFaces->RowLength(); jj++) {
904         const TopoDS_Shape &aNewFace  = myFaces->Value(aNewIndex, jj);
905         const TopoDS_Shape &anOldFace = myFaces->Value(anOldIndex, jj);
906
907         if (!aSubstitute.IsCopied(aNewFace)) {
908           aListShape.Append(anOldFace.Oriented(TopAbs_REVERSED));
909           aSubstitute.Substitute(aNewFace, aListShape);
910           aListShape.Clear();
911         }
912       }
913     }
914
915     // Change new edges by old ones.
916     for (anIter.Initialize(aMapNewOldEIndex); anIter.More(); anIter.Next()) {
917       const Standard_Integer aNewIndex  = anIter.Key();
918       const Standard_Integer anOldIndex = anIter.Value();
919
920       for (jj = 1; jj <= myEdges->RowLength(); jj++) {
921         const TopoDS_Shape &aNewEdge  = myEdges->Value(aNewIndex, jj);
922         const TopoDS_Shape &anOldEdge = myEdges->Value(anOldIndex, jj);
923
924         if (!aSubstitute.IsCopied(aNewEdge)) {
925           aListShape.Append(anOldEdge.Oriented(TopAbs_FORWARD));
926           aSubstitute.Substitute(aNewEdge, aListShape);
927           aListShape.Clear();
928
929           // Change new vertices by old ones.
930           TopoDS_Iterator aNewIt(aNewEdge);
931           TopoDS_Iterator anOldIt(anOldEdge);
932
933           for (; aNewIt.More() && anOldIt.More();
934                                   aNewIt.Next(), anOldIt.Next()) {
935             if (!aNewIt.Value().IsSame(anOldIt.Value())) {
936               if (!aSubstitute.IsCopied(aNewIt.Value())) {
937                 aListShape.Append(anOldIt.Value().Oriented(TopAbs_FORWARD));
938                 aSubstitute.Substitute(aNewIt.Value(), aListShape);
939                 aListShape.Clear();
940               }
941             }
942           }
943         }
944       }
945     }
946
947     // Perform substitution.
948     aSubstitute.Build(aResult);
949
950     if (aSubstitute.IsCopied(aResult)) {
951       // Get copied shape.
952       const TopTools_ListOfShape& listSh = aSubstitute.Copy(aResult);
953
954       aResult = listSh.First();
955
956       // Update original faces with copied ones.
957       for (ii = theInitialFacesLen + 1; ii <= myFaces->ColLength(); ii++) {
958         for (jj = 1; jj <= myFaces->RowLength(); jj++) {
959           TopoDS_Shape anOldFace = myFaces->Value(ii, jj); // Copy
960
961           if (aSubstitute.IsCopied(anOldFace)) {
962             const TopTools_ListOfShape& aList = aSubstitute.Copy(anOldFace);
963
964             if(!aList.IsEmpty()) {
965               // Store copied face.
966               const TopoDS_Shape &aCopyFace = aList.First();
967               TopAbs_Orientation anOri = anOldFace.Orientation();
968               const Standard_Boolean isShared = aMapNewOldFIndex.IsBound(ii);
969
970               if (isShared) {
971                 // Reverse the orientation for shared face.
972                 anOri = TopAbs::Reverse(anOri);
973               }
974
975               myFaces->SetValue(ii, jj, aCopyFace.Oriented(anOri));
976
977               // Check if it is necessary to update PCurves on this face.
978               if (!isShared) {
979                 TopoDS_Face anOldF = TopoDS::Face(anOldFace);
980                 TopoDS_Face aCopyF = TopoDS::Face(aCopyFace);
981
982                 anOldF.Orientation(TopAbs_FORWARD);
983                 anExp.Init(anOldF, TopAbs_EDGE);
984
985                 for (; anExp.More(); anExp.Next()) {
986                   const TopoDS_Shape &anOldEdge = anExp.Current();
987
988                   if (aSubstitute.IsCopied(anOldEdge)) {
989                     const TopTools_ListOfShape& aListE =
990                       aSubstitute.Copy(anOldEdge);
991
992                     if(!aListE.IsEmpty()) {
993                       // This edge is copied. Check if there is a PCurve
994                       // on the face.
995                       TopoDS_Edge aCopyE = TopoDS::Edge(aListE.First());
996                       Standard_Real aFirst;
997                       Standard_Real aLast;
998                       Handle(Geom2d_Curve) aPCurve = BRep_Tool::CurveOnSurface
999                           (aCopyE, aCopyF, aFirst, aLast);
1000
1001                       if (aPCurve.IsNull()) {
1002                         // There is no pcurve copy it from the old edge.
1003                         TopoDS_Edge anOldE = TopoDS::Edge(anOldEdge);
1004
1005                         aPCurve = BRep_Tool::CurveOnSurface
1006                           (anOldE, anOldF, aFirst, aLast);
1007
1008                         if (aPCurve.IsNull() == Standard_False) {
1009                           // Update the shared edge with PCurve from new Face.
1010                           Standard_Real aTol = Max(BRep_Tool::Tolerance(anOldE),
1011                                BRep_Tool::Tolerance(aCopyE));
1012
1013                           aBuilder.UpdateEdge(aCopyE, aPCurve, aCopyF, aTol);
1014                         }
1015                       }
1016                     }
1017                   }
1018                 }
1019               }
1020             }
1021           }
1022         }
1023       }
1024
1025       // Update new edges with shared ones.
1026       for (ii = theInitialEdgesLen + 1; ii <= myEdges->ColLength(); ii++) {
1027         for (jj = 1; jj <= myEdges->RowLength(); jj++) {
1028           const TopoDS_Shape &aLocalShape = myEdges->Value(ii, jj);
1029
1030           if (aSubstitute.IsCopied(aLocalShape)) {
1031             const TopTools_ListOfShape& aList = aSubstitute.Copy(aLocalShape);
1032
1033             if(!aList.IsEmpty()) {
1034               const TopAbs_Orientation anOri = TopAbs_FORWARD;
1035
1036               myEdges->SetValue(ii, jj, aList.First().Oriented(anOri));
1037             }
1038           }
1039         }
1040       }
1041
1042       // Update new sections with shared ones.
1043       for (ii = theInitialSectionsLen+1; ii <= mySections->ColLength(); ii++) {
1044         for (jj = 1; jj <= mySections->RowLength(); jj++) {
1045           const TopoDS_Shape &aLocalShape = mySections->Value(ii, jj);
1046
1047           if (aSubstitute.IsCopied(aLocalShape)) {
1048             const TopTools_ListOfShape& aList = aSubstitute.Copy(aLocalShape);
1049
1050             if(!aList.IsEmpty()) {
1051               const TopAbs_Orientation anOri = TopAbs_FORWARD;
1052
1053               mySections->SetValue(ii, jj, aList.First().Oriented(anOri));
1054             }
1055           }
1056         }
1057       }
1058     }
1059   }
1060
1061   return aResult;
1062 }