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