Salome HOME
b339a722368954427beaf1acf75e4902e05e8a42
[modules/geom.git] / src / GEOMImpl / GEOMImpl_PipeDriver.cxx
1 // Copyright (C) 2007-2013  CEA/DEN, EDF R&D, OPEN CASCADE
2 //
3 // Copyright (C) 2003-2007  OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
4 // CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
5 //
6 // This library is free software; you can redistribute it and/or
7 // modify it under the terms of the GNU Lesser General Public
8 // License as published by the Free Software Foundation; either
9 // version 2.1 of the License.
10 //
11 // This library is distributed in the hope that it will be useful,
12 // but WITHOUT ANY WARRANTY; without even the implied warranty of
13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14 // Lesser General Public License for more details.
15 //
16 // You should have received a copy of the GNU Lesser General Public
17 // License along with this library; if not, write to the Free Software
18 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
19 //
20 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
21 //
22
23 #include <GEOMImpl_PipeDriver.hxx>
24
25 #include <GEOMImpl_IPipeDiffSect.hxx>
26 #include <GEOMImpl_IPipeShellSect.hxx>
27 #include <GEOMImpl_IPipeBiNormal.hxx>
28 #include <GEOMImpl_IPipe.hxx>
29 #include <GEOMImpl_IPipePath.hxx>
30 #include <GEOMImpl_GlueDriver.hxx>
31 #include <GEOMImpl_Types.hxx>
32
33 #include <GEOM_Function.hxx>
34
35 #include <GEOMUtils.hxx>
36
37 #include <ShapeAnalysis_FreeBounds.hxx>
38 #include <ShapeAnalysis_Edge.hxx>
39 #include <ShapeFix_Face.hxx>
40 #include <ShapeFix_Shell.hxx>
41 #include <ShapeFix_Shape.hxx>
42 #include <ShapeFix_ShapeTolerance.hxx>
43
44 #include <BRep_Tool.hxx>
45 #include <BRep_Builder.hxx>
46 #include <BRepBuilderAPI_Copy.hxx>
47 #include <BRepBuilderAPI_MakeFace.hxx>
48 #include <BRepBuilderAPI_MakeWire.hxx>
49 #include <BRepBuilderAPI_Sewing.hxx>
50 #include <BRepCheck_Analyzer.hxx>
51 #include <BRepGProp.hxx>
52 #include <GeomFill_Trihedron.hxx>
53 #include <GeomFill_CorrectedFrenet.hxx>
54 #include <BRepOffsetAPI_MakePipe.hxx>
55 #include <BRepOffsetAPI_MakePipeShell.hxx>
56
57 #include <TopAbs.hxx>
58 #include <TopExp.hxx>
59 #include <TopExp_Explorer.hxx>
60 #include <TopoDS.hxx>
61 #include <TopoDS_Wire.hxx>
62 #include <TopoDS_Edge.hxx>
63 #include <TopoDS_Shape.hxx>
64 #include <TopoDS_Solid.hxx>
65 #include <TopoDS_Shell.hxx>
66 #include <TopoDS_Face.hxx>
67 #include <TopoDS_Compound.hxx>
68 #include <TopTools_SequenceOfShape.hxx>
69 #include <TopTools_HSequenceOfShape.hxx>
70 #include <TopTools_IndexedDataMapOfShapeShape.hxx>
71 #include <TopTools_IndexedDataMapOfShapeListOfShape.hxx>
72 #include <TopTools_ListIteratorOfListOfShape.hxx>
73
74 #include <GProp_GProps.hxx>
75
76 #include <GeomAPI_ProjectPointOnCurve.hxx>
77 #include <GeomAPI_Interpolate.hxx>
78 #include <Geom_TrimmedCurve.hxx>
79 #include <Geom_Plane.hxx>
80 #include <Geom_RectangularTrimmedSurface.hxx>
81 #include <Geom_BezierSurface.hxx>
82 #include <Geom_Line.hxx>
83 #include <Geom_Conic.hxx>
84 #include <Geom_BSplineCurve.hxx>
85 #include <Geom_BSplineSurface.hxx>
86 #include <GeomAdaptor_HCurve.hxx>
87 #include <GeomFill_BSplineCurves.hxx>
88 #include <GeomConvert_ApproxCurve.hxx>
89 #include <GeomConvert.hxx>
90
91 #include <TColgp_SequenceOfPnt.hxx>
92 #include <TColgp_HArray1OfPnt.hxx>
93 #include <TColgp_Array2OfPnt.hxx>
94 #include <TColStd_HSequenceOfTransient.hxx>
95
96 #include <Precision.hxx>
97
98 #include <Standard_NullObject.hxx>
99 #include <Standard_TypeMismatch.hxx>
100 #include <Standard_ConstructionError.hxx>
101
102 #include "utilities.h"
103
104
105 //=======================================================================
106 //function : GetID
107 //purpose  :
108 //=======================================================================
109 const Standard_GUID& GEOMImpl_PipeDriver::GetID()
110 {
111   static Standard_GUID aPipeDriver ("FF1BBB19-5D14-4df2-980B-3A668264EA16");
112   return aPipeDriver;
113 }
114
115 //=======================================================================
116 //function : GEOMImpl_PipeDriver
117 //purpose  :
118 //=======================================================================
119 GEOMImpl_PipeDriver::GEOMImpl_PipeDriver()
120 {
121 }
122
123 //=======================================================================
124 //function : EvaluateBestSweepMode
125 //purpose  : auxilary for right call of MakePipe and MakePipeShell
126 //=======================================================================
127 static GeomFill_Trihedron EvaluateBestSweepMode(const TopoDS_Shape& Spine)
128 {
129   GeomFill_Trihedron theMode = GeomFill_IsFrenet;
130   
131   TopExp_Explorer Explo(Spine, TopAbs_EDGE);
132   for (; Explo.More(); Explo.Next())
133   {
134     TopoDS_Edge anEdge = TopoDS::Edge(Explo.Current());
135     Standard_Real fpar, lpar;
136     Handle(Geom_Curve) aCurve = BRep_Tool::Curve(anEdge, fpar, lpar);
137     GeomAdaptor_Curve GAcurve(aCurve, fpar, lpar);
138     Handle(GeomAdaptor_HCurve) GAHcurve = new GeomAdaptor_HCurve(GAcurve);
139
140     Handle(GeomFill_CorrectedFrenet) aCorrFrenet = new GeomFill_CorrectedFrenet(Standard_True); //for evaluation
141     aCorrFrenet->SetCurve(GAHcurve);
142     GeomFill_Trihedron aMode = aCorrFrenet->EvaluateBestMode();
143     if (aMode == GeomFill_IsDiscreteTrihedron)
144     {
145       theMode = aMode;
146       break;
147     }
148     if (aMode == GeomFill_IsCorrectedFrenet)
149       theMode = aMode;
150   }
151
152   return theMode;
153 }
154
155
156 //=======================================================================
157 //function : FillForOtherEdges
158 //purpose  : auxilary for CreatePipeForShellSections()
159 //=======================================================================
160 static bool FillForOtherEdges(const TopoDS_Shape& F1,
161                               const TopoDS_Shape& E1,
162                               const TopoDS_Shape& V1,
163                               TopTools_IndexedDataMapOfShapeShape& FF)
164 {
165   //cout<<"FillForOtherEdges"<<endl;
166   // find other pairs for vertexes and edges
167   // creating map of vertex edges for both faces
168   TopTools_IndexedDataMapOfShapeListOfShape aMapVertEdge1;
169   TopExp::MapShapesAndAncestors(F1, TopAbs_VERTEX, TopAbs_EDGE, aMapVertEdge1);
170   if (!FF.Contains(F1))
171     MESSAGE("    FillForOtherEdges: map FF not contains key F1");
172   if (!FF.Contains(E1))
173     MESSAGE("    FillForOtherEdges: map FF not contains key E1");
174   if (!FF.Contains(V1))
175     MESSAGE("    FillForOtherEdges: map FF not contains key V1");
176   const TopoDS_Shape& F2 = FF.FindFromKey(F1);
177   const TopoDS_Shape& E2 = FF.FindFromKey(E1);
178   const TopoDS_Shape& V2 = FF.FindFromKey(V1);
179   TopTools_IndexedDataMapOfShapeListOfShape aMapVertEdge2;
180   TopExp::MapShapesAndAncestors(F2, TopAbs_VERTEX, TopAbs_EDGE, aMapVertEdge2);
181
182   TopoDS_Edge ES1 = TopoDS::Edge(E1);
183   TopoDS_Edge ES2 = TopoDS::Edge(E2);
184   TopoDS_Shape VS1 = V1;
185   TopoDS_Shape VS2 = V2;
186
187   ShapeAnalysis_Edge sae;
188   while(1) {
189     if (!aMapVertEdge1.Contains(VS1))
190       MESSAGE ("    FillForOtherEdges: map aMapVertEdge1 not contains key VS1");
191     const TopTools_ListOfShape& aList1 = aMapVertEdge1.FindFromKey(VS1);
192     //TopoDS_Shape E1next;
193     TopTools_ListIteratorOfListOfShape anIter1(aList1);
194     if (anIter1.Value().IsSame(ES1)) {
195       anIter1.Next();
196     }
197     //E1next = anIter1.Value();
198     if (!aMapVertEdge2.Contains(VS2))
199       MESSAGE ("    FillForOtherEdges: map aMapVertEdge2 not contains key VS2");
200     const TopTools_ListOfShape& aList2 = aMapVertEdge2.FindFromKey(VS2);
201     //TopoDS_Shape E2next;
202     TopTools_ListIteratorOfListOfShape anIter2(aList2);
203     if (anIter2.Value().IsSame(ES2)) {
204       anIter2.Next();
205     }
206     //E2next = anIter2.Value();
207     //ES1 = TopoDS::Edge(E1next);
208     //ES2 = TopoDS::Edge(E2next);
209     ES1 = TopoDS::Edge(anIter1.Value());
210     ES2 = TopoDS::Edge(anIter2.Value());
211     if (!FF.Contains(ES1)) {
212       FF.Add(ES1,ES2);
213     }
214     if (VS1.IsSame(sae.FirstVertex(ES1)))
215       VS1 = sae.LastVertex(ES1);
216     else
217       VS1 = sae.FirstVertex(ES1);
218     if (VS2.IsSame(sae.FirstVertex(ES2)))
219       VS2 = sae.LastVertex(ES2);
220     else
221       VS2 = sae.FirstVertex(ES2);
222     if (VS1.IsSame(V1))
223       break;
224     if (!FF.Contains(VS1)) {
225       FF.Add(VS1,VS2);
226     }
227   }
228
229   return true;
230 }
231
232 //=======================================================================
233 //function : FillCorrespondingEdges
234 //purpose  : auxilary for CreatePipeForShellSections()
235 //=======================================================================
236 static bool FillCorrespondingEdges(const TopoDS_Shape& FS1,
237                                    const TopoDS_Shape& FS2,
238                                    const TopoDS_Vertex& aLoc1,
239                                    const TopoDS_Vertex& aLoc2,
240                                    const TopoDS_Wire& aWirePath,
241                                    TopTools_IndexedDataMapOfShapeShape& FF)
242 {
243   //cout<<"FillCorrespondingEdges"<<endl;
244   // find corresponding edges
245   TopExp_Explorer expw1(FS1,TopAbs_WIRE);
246   TopoDS_Wire aWire1 = TopoDS::Wire(expw1.Current());
247   //exp = TopExp_Explorer(FS2,TopAbs_WIRE);
248   TopExp_Explorer expw2(FS2,TopAbs_WIRE);
249   TopoDS_Wire aWire2 = TopoDS::Wire(expw2.Current());
250   BRepOffsetAPI_MakePipeShell aBuilder(aWirePath);
251   GeomFill_Trihedron theBestMode = EvaluateBestSweepMode(aWirePath);
252   if (theBestMode == GeomFill_IsDiscreteTrihedron)
253     aBuilder.SetDiscreteMode();
254   aBuilder.Add(aWire1, aLoc1);
255   aBuilder.Add(aWire2, aLoc2);
256   if (!aBuilder.IsReady()) {
257     return false;
258   }
259   aBuilder.Build();
260   TopoDS_Shape aShape = aBuilder.Shape();
261   /*
262   TopoDS_Compound C;
263   BRep_Builder B;
264   B.MakeCompound(C);
265   B.Add(C,aShape);
266   B.Add(C,FS1);
267   B.Add(C,FS2);
268   BRepTools::Write(C,"/dn02/users_Linux/skl/work/Bugs/14857/comp.brep");
269   */
270   ShapeAnalysis_Edge sae;
271   double tol = Max(BRep_Tool::Tolerance(TopoDS::Face(FS1)),
272                     BRep_Tool::Tolerance(TopoDS::Face(FS2)));
273   TopTools_MapOfShape Vs1,Vs2;
274   TopExp_Explorer exp;
275   exp.Init(FS1, TopAbs_EDGE);
276   TopoDS_Edge E1 = TopoDS::Edge(exp.Current());
277   TopoDS_Vertex V11 = sae.FirstVertex(E1);
278   TopoDS_Vertex V21 = sae.LastVertex(E1);
279   gp_Pnt P11 = BRep_Tool::Pnt(V11);
280   gp_Pnt P21 = BRep_Tool::Pnt(V21);
281   //cout<<"P11("<<P11.X()<<","<<P11.Y()<<","<<P11.Z()<<")"<<endl;
282   //cout<<"P21("<<P21.X()<<","<<P21.Y()<<","<<P21.Z()<<")"<<endl;
283   // find corresponding vertexes from created shape
284   TopoDS_Vertex VN11,VN21;
285   for (exp.Init(aShape, TopAbs_VERTEX); exp.More(); exp.Next()) {
286     TopoDS_Vertex V = TopoDS::Vertex(exp.Current());
287     gp_Pnt P = BRep_Tool::Pnt(V);
288     if (P.Distance(P11)<tol) {
289       VN11 = V;
290     }
291     if (P.Distance(P21)<tol) {
292       VN21 = V;
293     }
294   }
295   // find edge contains VN11 and VN21 and corresponding vertexes
296   TopoDS_Vertex VN12,VN22;
297   for (exp.Init(aShape, TopAbs_FACE); exp.More(); exp.Next()) {
298     TopoDS_Shape F = exp.Current();
299     TopExp_Explorer expe;
300     bool IsFind = false;
301     for (expe.Init(F, TopAbs_EDGE); expe.More(); expe.Next()) {
302       TopoDS_Edge E = TopoDS::Edge(expe.Current());
303       TopoDS_Vertex VF = sae.FirstVertex(E);
304       TopoDS_Vertex VL = sae.LastVertex(E);
305       if ((VF.IsSame(VN11) && VL.IsSame(VN21)) || (VF.IsSame(VN21) && VL.IsSame(VN11))) {
306         IsFind = true;
307         break;
308       }
309     }
310     if (IsFind) {
311       for (expe.Init(F, TopAbs_EDGE); expe.More(); expe.Next()) {
312         TopoDS_Edge E = TopoDS::Edge(expe.Current());
313         TopoDS_Vertex VF = sae.FirstVertex(E);
314         TopoDS_Vertex VL = sae.LastVertex(E);
315         if (VF.IsSame(VN11) && !VL.IsSame(VN21))
316           VN12 = VL;
317         if (VL.IsSame(VN11) && !VF.IsSame(VN21))
318           VN12 = VF;
319         if (VF.IsSame(VN21) && !VL.IsSame(VN11))
320           VN22 = VL;
321         if (VL.IsSame(VN21) && !VF.IsSame(VN11))
322           VN22 = VF;
323       }
324       break;
325     }
326   }
327   // find vertexes from FS2 corresponded to VN12 and VN22
328   // and find edge from FS2 contains V12 and V22,
329   // this edge will be corresponded to edge E1
330   TopoDS_Vertex V12,V22;
331   gp_Pnt PN12 = BRep_Tool::Pnt(VN12);
332   gp_Pnt PN22 = BRep_Tool::Pnt(VN22);
333   //cout<<"PN12("<<PN12.X()<<","<<PN12.Y()<<","<<PN12.Z()<<")"<<endl;
334   //cout<<"PN22("<<PN22.X()<<","<<PN22.Y()<<","<<PN22.Z()<<")"<<endl;
335   TopoDS_Edge E2;
336   TopExp_Explorer expe;
337   for (expe.Init(FS2, TopAbs_EDGE); expe.More(); expe.Next()) {
338     TopoDS_Edge E = TopoDS::Edge(expe.Current());
339     TopoDS_Vertex VF = sae.FirstVertex(E);
340     TopoDS_Vertex VL = sae.LastVertex(E);
341     gp_Pnt PF = BRep_Tool::Pnt(VF);
342     gp_Pnt PL = BRep_Tool::Pnt(VL);
343     if (PF.Distance(PN12)<tol && PL.Distance(PN22)<tol) {
344       V12 = VF;
345       V22 = VL;
346       E2 = E;
347       break;
348     }
349     if (PF.Distance(PN22)<tol && PL.Distance(PN12)<tol) {
350       V12 = VL;
351       V22 = VF;
352       E2 = E;
353       break;
354     }
355   }
356   FF.Add(V11,V12);
357   FF.Add(V21,V22);
358   FF.Add(E1,E2);
359
360   // find other pairs for vertexes and edges
361   // creating map of vertex edges for both faces
362   return FillForOtherEdges(FS1,E1,V21,FF);
363
364   //return true;
365 }
366
367 //=======================================================================
368 //function : FillCorrespondingEdges
369 //purpose  : auxilary for CreatePipeShellsWithoutPath()
370 //=======================================================================
371 static bool FillCorrespondingEdges(const TopoDS_Shape& FS1,
372                                    const TopoDS_Shape& FS2,
373                                    const TopoDS_Vertex& aLoc1,
374                                    const TopoDS_Vertex& aLoc2,
375                                    TopTools_IndexedDataMapOfShapeShape& FF)
376 {
377   //cout<<"FillCorrespondingEdges"<<endl;
378
379   gp_Pnt P1 = BRep_Tool::Pnt(aLoc1);
380   gp_Pnt P2 = BRep_Tool::Pnt(aLoc2);
381   gp_Vec aDir(P1,P2);
382
383   ShapeAnalysis_Edge sae;
384   double tol = Max(BRep_Tool::Tolerance(TopoDS::Face(FS1)),
385                     BRep_Tool::Tolerance(TopoDS::Face(FS2)));
386   TopTools_MapOfShape Vs1,Vs2;
387
388   TopoDS_Vertex V11=aLoc1, V12=aLoc2, V21, V22;
389   TopoDS_Edge E1,E2;
390
391   TopExp_Explorer exp1;
392   for (exp1.Init(FS1,TopAbs_EDGE); exp1.More(); exp1.Next()) {
393     E1 = TopoDS::Edge(exp1.Current());
394     TopoDS_Vertex V1 = sae.FirstVertex(E1);
395     TopoDS_Vertex V2 = sae.LastVertex(E1);
396     gp_Pnt Ptmp1 = BRep_Tool::Pnt(V1);
397     gp_Pnt Ptmp2 = BRep_Tool::Pnt(V2);
398     //cout<<"P11("<<P11.X()<<","<<P11.Y()<<","<<P11.Z()<<")"<<endl;
399     //cout<<"P21("<<P21.X()<<","<<P21.Y()<<","<<P21.Z()<<")"<<endl;
400     if (P1.Distance(Ptmp1)<tol) {
401       V21 = V2;
402       break;
403     }
404     if (P1.Distance(Ptmp2)<tol) {
405       V21 = V1;
406       break;
407     }
408   }
409
410   TopoDS_Edge E21,E22;
411   TopoDS_Vertex VE21,VE22;
412   int nbe=0;
413   for (exp1.Init(FS2,TopAbs_EDGE); exp1.More() && nbe<2; exp1.Next()) {
414     TopoDS_Edge E = TopoDS::Edge(exp1.Current());
415     TopoDS_Vertex V1 = sae.FirstVertex(E);
416     TopoDS_Vertex V2 = sae.LastVertex(E);
417     gp_Pnt Ptmp1 = BRep_Tool::Pnt(V1);
418     gp_Pnt Ptmp2 = BRep_Tool::Pnt(V2);
419     if (P2.Distance(Ptmp1)<tol) {
420       if (nbe==0) {
421         E21 = E;
422         VE21 = V2;
423         nbe++;
424       }
425       else if (nbe==1) {
426         E22 = E;
427         VE22 = V2;
428         nbe++;
429       }
430     }
431     if (P2.Distance(Ptmp2)<tol) {
432       if (nbe==0) {
433         E21 = E;
434         VE21 = V1;
435         nbe++;
436       }
437       else if (nbe==1) {
438         E22 = E;
439         VE22 = V1;
440         nbe++;
441       }
442     }
443   }
444
445   gp_Pnt PV21 = BRep_Tool::Pnt(V21);
446   gp_Pnt PE21 = BRep_Tool::Pnt(VE21);
447   gp_Pnt PE22 = BRep_Tool::Pnt(VE22);
448   gp_Vec aDir1(PV21,PE21);
449   gp_Vec aDir2(PV21,PE22);
450   double ang1 = aDir.Angle(aDir1);
451   double ang2 = aDir.Angle(aDir2);
452   if (fabs(ang1)<fabs(ang2)) {
453     E2 = E21;
454     V22 = VE21;
455   }
456   else {
457     E2 = E22;
458     V22 = VE22;
459   }
460
461   FF.Add(V11,V12);
462   FF.Add(V21,V22);
463   FF.Add(E1,E2);
464
465   // find other pairs for vertexes and edges
466   return FillForOtherEdges(FS1,E1,V21,FF);
467 }
468
469 //=======================================================================
470 //function : FindNextPairOfFaces
471 //purpose  : auxilary for CreatePipeForShellSections()
472 //=======================================================================
473 static void FindNextPairOfFaces(const TopoDS_Shape& aCurFace,
474                                 TopTools_IndexedDataMapOfShapeListOfShape& aMapEdgeFaces1,
475                                 TopTools_IndexedDataMapOfShapeListOfShape& aMapEdgeFaces2,
476                                 TopTools_IndexedDataMapOfShapeShape& FF,
477                                 GEOMImpl_IPipe* aCI)
478 {
479   //cout<<"FindNextPairOfFaces"<<endl;
480   TopExp_Explorer anExp;
481   for (anExp.Init(aCurFace, TopAbs_EDGE); anExp.More(); anExp.Next()) {
482     TopoDS_Shape E1 = anExp.Current();
483     if (!FF.Contains(E1)) {
484       if (aCI) delete aCI;
485       Standard_ConstructionError::Raise("FindNextPairOfFaces: Can not find edge in map");
486     }
487     if (!FF.Contains(E1))
488       MESSAGE ("    FindNextPairOfFaces: map FF not contains key E1");
489     const TopoDS_Shape& E2 = FF.FindFromKey(E1);
490     TopExp_Explorer anExpV;
491     anExpV.Init(E1, TopAbs_VERTEX);
492     TopoDS_Shape V1 = anExpV.Current();
493     if (!FF.Contains(V1)) {
494       if (aCI) delete aCI;
495       Standard_ConstructionError::Raise("FindNextPairOfFaces: Can not find vertex in map");
496     }
497
498     if (!aMapEdgeFaces1.Contains(E1))
499       MESSAGE ("    FindNextPairOfFaces: map aMapEdgeFaces1 not contains key E1");
500     const TopTools_ListOfShape& aList1 = aMapEdgeFaces1.FindFromKey(E1);
501     if (aList1.Extent()<2)
502       continue;
503     TopTools_ListIteratorOfListOfShape anIter(aList1);
504     if (anIter.Value().IsEqual(aCurFace)) {
505       anIter.Next();
506     }
507     TopoDS_Shape F1other = anIter.Value();
508     if (FF.Contains(F1other))
509       continue;
510
511     if (!FF.Contains(aCurFace))
512       MESSAGE ("    FindNextPairOfFaces: map FF not contains key aCurFace");
513     const TopoDS_Shape& F2 = FF.FindFromKey(aCurFace);
514     if (!aMapEdgeFaces2.Contains(E2))
515       MESSAGE ("    FindNextPairOfFaces: map aMapEdgeFaces2 not contains key E2");
516     const TopTools_ListOfShape& aList2 = aMapEdgeFaces2.FindFromKey(E2);
517     if (aList2.Extent()<2) {
518       if (aCI) delete aCI;
519       Standard_ConstructionError::Raise("FindNextPairOfFaces: Can not find corresponding face");
520     }
521     TopTools_ListIteratorOfListOfShape anIter2(aList2);
522     if (anIter2.Value().IsEqual(F2)) {
523       anIter2.Next();
524     }
525     TopoDS_Shape F2other = anIter2.Value();
526     FF.Add(F1other,F2other);
527
528     // add pairs of edges to FF
529     bool stat =  FillForOtherEdges(F1other,E1,V1,FF);
530     if (!stat) {
531       if (aCI) delete aCI;
532       Standard_ConstructionError::Raise("FindNextPairOfFaces: Can not mapping other egdes");
533     }
534
535     FindNextPairOfFaces(F1other, aMapEdgeFaces1, aMapEdgeFaces2, FF, aCI);
536   }
537 }
538
539 //=======================================================================
540 //function : FindFirstPairFaces
541 //purpose  : auxilary for Execute()
542 //=======================================================================
543 static void FindFirstPairFaces(const TopoDS_Shape& S1, const TopoDS_Shape& S2,
544                                TopoDS_Vertex& V1, TopoDS_Vertex& V2,
545                                TopoDS_Shape& FS1, TopoDS_Shape& FS2)
546 {
547   //cout<<"FindFirstPairFaces"<<endl;
548
549   // check if vertexes are sub-shapes of sections
550   gp_Pnt P1 = BRep_Tool::Pnt(V1);
551   gp_Pnt P2 = BRep_Tool::Pnt(V2);
552   TopoDS_Vertex V1new,V2new;
553   TopExp_Explorer exp;
554   double mindist = 1.e10;
555   for (exp.Init(S1, TopAbs_VERTEX); exp.More(); exp.Next()) {
556     TopoDS_Vertex V = TopoDS::Vertex(exp.Current());
557     gp_Pnt P = BRep_Tool::Pnt(V);
558     double dist = P1.Distance(P);
559     if (dist<mindist) {
560       mindist = dist;
561       V1new = V;
562     }
563   }
564   mindist = 1.e10;
565   for (exp.Init(S2, TopAbs_VERTEX); exp.More(); exp.Next()) {
566     TopoDS_Vertex V = TopoDS::Vertex(exp.Current());
567     gp_Pnt P = BRep_Tool::Pnt(V);
568     double dist = P2.Distance(P);
569     if (dist<mindist) {
570       mindist = dist;
571       V2new = V;
572     }
573   }
574
575   //gp_Pnt P1new = BRep_Tool::Pnt(V1new);
576   //gp_Pnt P2new = BRep_Tool::Pnt(V2new);
577   //cout<<"  P1("<<P1.X()<<","<<P1.Y()<<","<<P1.Z()<<")"<<endl;
578   //cout<<"  P2("<<P2.X()<<","<<P2.Y()<<","<<P2.Z()<<")"<<endl;
579   //cout<<"  P1new("<<P1new.X()<<","<<P1new.Y()<<","<<P1new.Z()<<")"<<endl;
580   //cout<<"  P2new("<<P2new.X()<<","<<P2new.Y()<<","<<P2new.Z()<<")"<<endl;
581
582   // replace vertexes if it is needed
583   if (!V1.IsSame(V1new)) {
584     V1 = V1new;
585     P1 = BRep_Tool::Pnt(V1);
586     MESSAGE ("  replace V1");
587   }
588   else
589     MESSAGE ("  not replace V1");
590   if (!V2.IsSame(V2new)) {
591     V2 = V2new;
592     P2 = BRep_Tool::Pnt(V2);
593     MESSAGE ("  replace V2");
594   }
595   else
596     MESSAGE ("  not replace V2");
597
598   TopTools_IndexedDataMapOfShapeListOfShape aMapVertFaces1;
599   TopExp::MapShapesAndAncestors(S1, TopAbs_VERTEX, TopAbs_FACE, aMapVertFaces1);
600   TopTools_IndexedDataMapOfShapeListOfShape aMapVertFaces2;
601   TopExp::MapShapesAndAncestors(S2, TopAbs_VERTEX, TopAbs_FACE, aMapVertFaces2);
602
603   if (!aMapVertFaces1.Contains(V1))
604     MESSAGE ("    FindFirstPairFaces: map aMapVertFaces1 not contains key V1");
605   const TopTools_ListOfShape& aList1 = aMapVertFaces1.FindFromKey(V1);
606   TopTools_ListIteratorOfListOfShape anIter1(aList1);
607   FS1 = anIter1.Value();
608   // find middle point
609   double x1=0., y1=0., z1=0.;
610   int nbv1=0;
611   for (exp.Init(FS1, TopAbs_VERTEX); exp.More(); exp.Next()) {
612     TopoDS_Vertex V = TopoDS::Vertex(exp.Current());
613     gp_Pnt P = BRep_Tool::Pnt(V);
614     x1 += P.X();
615     y1 += P.Y();
616     z1 += P.Z();
617     nbv1++;
618   }
619   gp_Pnt PM1(x1/nbv1, y1/nbv1, z1/nbv1);
620
621   TColgp_SequenceOfPnt Ps;
622   TopTools_SequenceOfShape Fs;
623   if (!aMapVertFaces2.Contains(V2))
624     MESSAGE ("    FindFirstPairFaces: map aMapVertFaces2 not contains key V2");
625   const TopTools_ListOfShape& aList2 = aMapVertFaces2.FindFromKey(V2);
626   TopTools_ListIteratorOfListOfShape anIter2(aList2);
627   for (; anIter2.More(); anIter2.Next()) {
628     TopoDS_Shape F = anIter2.Value();
629     double x2=0., y2=0., z2=0.;
630     int nbv2=0;
631     for (exp.Init(F, TopAbs_VERTEX); exp.More(); exp.Next()) {
632       TopoDS_Vertex V = TopoDS::Vertex(exp.Current());
633       gp_Pnt P = BRep_Tool::Pnt(V);
634       x2 += P.X();
635       y2 += P.Y();
636       z2 += P.Z();
637       nbv2++;
638     }
639     gp_Pnt PM(x2/nbv1, y2/nbv1, z2/nbv1);
640     Fs.Append(F);
641     Ps.Append(PM);
642   }
643
644   gp_Vec aDir(P1,P2);
645   int i=1;
646   double MinAng = M_PI;
647   int numface = 0;
648   for (; i<=Fs.Length(); i++) {
649     gp_Vec tmpDir(PM1,Ps(i));
650     double ang = fabs(aDir.Angle(tmpDir));
651     if (ang<MinAng) {
652       MinAng = ang;
653       numface = i;
654     }
655   }
656   FS2 = Fs(numface);
657 }
658
659 //=======================================================================
660 //function : CreatePipeWithDifferentSections
661 //purpose  :
662 //=======================================================================
663 TopoDS_Shape GEOMImpl_PipeDriver::CreatePipeWithDifferentSections
664                                   (const TopoDS_Wire& theWirePath,
665                                    const Handle(TopTools_HSequenceOfShape) theHSeqBases,
666                                    const Handle(TopTools_HSequenceOfShape) theHSeqLocs,
667                                    const Standard_Boolean theWithContact,
668                                    const Standard_Boolean theWithCorrect)
669 {
670   TopoDS_Shape aShape;
671
672   TopoDS_Wire aWirePath = theWirePath;
673
674   Standard_Integer nbBases = theHSeqBases->Length();
675   Standard_Integer nbLocs = (theHSeqLocs.IsNull() ? 0 : theHSeqLocs->Length());
676
677   if (nbLocs && nbLocs != nbBases) {
678     Standard_ConstructionError::Raise("Number of sections is not equal to number of locations ");
679   }
680
681   TopTools_SequenceOfShape aSeqBases;
682   TopTools_SequenceOfShape aSeqLocs;
683   TopTools_SequenceOfShape aSeqFaces;
684
685   Standard_Integer i = 1;
686   for (i = 1; i <= nbBases; i++) {
687     if (theHSeqBases->Value(i).IsNull())
688       continue;
689
690     // Make copy to prevent modifying of base object 0020766 : EDF 1320
691     TopoDS_Shape aShapeBase;
692     BRepBuilderAPI_Copy Copy (theHSeqBases->Value(i));
693     if (Copy.IsDone())
694       aShapeBase = Copy.Shape();
695
696     TopAbs_ShapeEnum aTypeBase = aShapeBase.ShapeType();
697
698     //if for section was specified face with a few wires then a few
699     //    pipes were build and make solid
700     Standard_Boolean NeedCreateSolid = Standard_False;
701     if (aTypeBase == TopAbs_SHELL) {
702       // create wire as boundary contour if shell is no closed
703       // get free boundary shapes
704       ShapeAnalysis_FreeBounds anAnalizer(aShapeBase);
705       TopoDS_Compound aClosed = anAnalizer.GetClosedWires();
706       TopExp_Explorer anExp;
707       TopoDS_Shape aWire;
708       Standard_Integer NbWires = 0;
709       for (anExp.Init(aClosed, TopAbs_WIRE); anExp.More(); anExp.Next()) {
710         NbWires++;
711         aWire = anExp.Current();
712       }
713       if (NbWires != 1) {
714         // bad case
715         Standard_ConstructionError::Raise("Bad shell is used as section ");
716       }
717       NeedCreateSolid = Standard_True;
718       aSeqFaces.Append(aShapeBase);
719       aSeqBases.Append(aWire);
720     }
721     else if (aTypeBase == TopAbs_FACE) {
722       NeedCreateSolid = Standard_True;
723       //for case one path should be used other type function
724       aSeqFaces.Append(aShapeBase);
725       TopExp_Explorer aExpW(aShapeBase,TopAbs_WIRE);
726       for (; aExpW.More(); aExpW.Next()) {
727         TopoDS_Shape aWireProf = aExpW.Current();
728         aSeqBases.Append(aWireProf);
729       }
730     }
731     else if (aTypeBase == TopAbs_WIRE || aTypeBase == TopAbs_VERTEX) {
732       aSeqBases.Append(aShapeBase);
733     }
734     else if (aTypeBase == TopAbs_EDGE) {
735       TopoDS_Edge anEdge = TopoDS::Edge(aShapeBase);
736       TopoDS_Shape aWireProf = BRepBuilderAPI_MakeWire(anEdge);
737       aSeqBases.Append(aWireProf);
738     }
739     if (nbLocs) {
740       TopoDS_Shape aShapeLoc = theHSeqLocs->Value(i);
741       if (aShapeLoc.IsNull() || aShapeLoc.ShapeType() != TopAbs_VERTEX)
742         continue;
743       aSeqLocs.Append(aShapeLoc);
744     }
745   }
746
747   nbLocs = aSeqLocs.Length();
748
749   // skl 02.05.2007
750   TopTools_SequenceOfShape Edges;
751   if (nbLocs > 0) {
752     // we have to check that each location shape is a vertex from
753     // path and update aSeqLocs if it is needed (and possible)
754     TColgp_SequenceOfPnt PLocs;
755     for (i=1; i<=nbLocs; i++) {
756       TopoDS_Vertex V = TopoDS::Vertex(aSeqLocs.Value(i));
757       PLocs.Append(BRep_Tool::Pnt(V));
758     }
759     //TopTools_SequenceOfShape Edges;
760     TopExp_Explorer anExp;
761     for (anExp.Init(aWirePath, TopAbs_EDGE); anExp.More(); anExp.Next()) {
762       Edges.Append(anExp.Current());
763     }
764     int nbEdges = Edges.Length();
765     ShapeAnalysis_Edge sae;
766     TopoDS_Edge edge = TopoDS::Edge(Edges.First());
767     double tol = BRep_Tool::Tolerance(edge);
768     TopoDS_Vertex VF = sae.FirstVertex(edge);
769     gp_Pnt PF = BRep_Tool::Pnt(VF);
770     //cout<<"PF("<<PF.X()<<","<<PF.Y()<<","<<PF.Z()<<")"<<endl;
771     if (PF.Distance(PLocs.First()) > tol) {
772       Standard_ConstructionError::Raise
773         ("First location shapes is not coincided with first vertex of aWirePath");
774     }
775     aSeqLocs.ChangeValue(1) = VF;
776     edge = TopoDS::Edge(Edges.Last());
777     tol = BRep_Tool::Tolerance(edge);
778     TopoDS_Vertex VL = sae.LastVertex(edge);
779     gp_Pnt PL = BRep_Tool::Pnt(VL);
780     if (PL.Distance(PLocs.Last()) > tol) {
781       Standard_ConstructionError::Raise
782         ("Last location shapes is not coincided with last vertex of aWirePath");
783     }
784     aSeqLocs.ChangeValue(nbLocs) = VL;
785     int jcurr = 2;
786     for (i=1; i<=Edges.Length() && jcurr<nbLocs; i++) {
787       TopoDS_Edge E = TopoDS::Edge(Edges.Value(i));
788       tol = BRep_Tool::Tolerance(edge);
789       TopoDS_Vertex V1 = sae.FirstVertex(E);
790       TopoDS_Vertex V2 = sae.LastVertex(E);
791       gp_Pnt P1 = BRep_Tool::Pnt(V1);
792       gp_Pnt P2 = BRep_Tool::Pnt(V2);
793       if (P2.Distance(PLocs.Value(jcurr)) < tol) {
794         aSeqLocs.ChangeValue(jcurr) = V2;
795         jcurr++;
796       }
797       else {
798         // find distance between E and aLocs(jcurr)
799         double fp,lp;
800         Handle(Geom_Curve) C = BRep_Tool::Curve(E,fp,lp);
801         GeomAPI_ProjectPointOnCurve PPCurve (PLocs.Value(jcurr),C);
802         if (PPCurve.NbPoints()>0 &&
803             PLocs.Value(jcurr).Distance(PPCurve.Point(1)) < tol) {
804           double param = PPCurve.Parameter(1);
805           gp_Pnt PC1;
806           C->D0(param,PC1);
807           // split current edge
808           Handle(Geom_TrimmedCurve) tc1 = new Geom_TrimmedCurve(C,fp,param);
809           Handle(Geom_TrimmedCurve) tc2 = new Geom_TrimmedCurve(C,param,lp);
810           TopoDS_Edge E1,E2;
811           BRep_Builder B;
812           gp_Pnt Pfp;
813           C->D0(fp,Pfp);
814           if (Pfp.Distance(P1)<tol) {
815             B.MakeEdge(E1,tc1,tol);
816             B.Add(E1,V1);
817             TopoDS_Shape tmpV = aSeqLocs.Value(jcurr).Oriented(TopAbs_REVERSED);
818             B.Add(E1,TopoDS::Vertex(tmpV));
819             B.MakeEdge(E2,tc2,tol);
820             tmpV = aSeqLocs.Value(jcurr).Oriented(TopAbs_FORWARD);
821             B.Add(E2,TopoDS::Vertex(tmpV));
822             B.Add(E2,V2);
823           }
824           else {
825             B.MakeEdge(E1,tc2,tol);
826             TopoDS_Shape tmpV = aSeqLocs.Value(jcurr).Oriented(TopAbs_FORWARD);
827             B.Add(E1,TopoDS::Vertex(tmpV));
828             B.Add(E1,V1);
829             E1.Reverse();
830             B.MakeEdge(E2,tc1,tol);
831             B.Add(E2,V2);
832             tmpV = aSeqLocs.Value(jcurr).Oriented(TopAbs_REVERSED);
833             B.Add(E2,TopoDS::Vertex(tmpV));
834             E2.Reverse();
835           }
836           jcurr++;
837           Edges.Remove(i);
838           Edges.InsertAfter(i-1,E1);
839           Edges.InsertAfter(i,E2);
840         }
841       }
842     }
843     if (nbEdges<Edges.Length()) {
844         // one of edges was splitted => we have to update WirePath
845         BRep_Builder B;
846         TopoDS_Wire W;
847         B.MakeWire(W);
848         for (i=1; i<=Edges.Length(); i++) {
849           B.Add(W,TopoDS::Edge(Edges.Value(i)));
850         }
851         aWirePath = W;
852     }
853   }
854
855   // check curvature of wire for condition that
856   // max summary angle between directions along
857   // wire path must be < 4*PI. If not - split wire
858   // and seguences of shapes, perform pipe for each
859   // and make sewing after that
860   double fp,lp;
861   gp_Pnt P1,P2;
862   gp_Vec Vec1,Vec2;
863   double SumAng = 0;
864   if ( Edges.Length() > 0 ) {
865     Handle(Geom_Curve) C = BRep_Tool::Curve(TopoDS::Edge(Edges.Value(1)),fp,lp);
866     C->D1(fp,P1,Vec1);
867     C->D1(lp,P2,Vec2);
868     SumAng = fabs(Vec1.Angle(Vec2));
869     Vec1 = Vec2;
870     P1 = P2;
871   }
872   TColStd_SequenceOfInteger SplitEdgeNums,SplitLocNums;
873   int LastLoc = 1;
874   //cout<<"Edges.Length()="<<Edges.Length()<<endl;
875   for (i=2; i<=Edges.Length(); i++) {
876       TopoDS_Edge edge = TopoDS::Edge(Edges.Value(i));
877       double tol = BRep_Tool::Tolerance(edge);
878       Handle(Geom_Curve) C = BRep_Tool::Curve(edge,fp,lp);
879       C->D1(lp,P2,Vec2);
880       double ang = fabs(Vec1.Angle(Vec2));
881       SumAng += ang;
882       if (SumAng>4*M_PI) {
883         SumAng = ang;
884         SplitEdgeNums.Append(i-1);
885         int j;
886         for (j=LastLoc+1; j<=aSeqLocs.Length(); j++) {
887           TopoDS_Vertex aVert = TopoDS::Vertex(aSeqLocs.Value(j));
888           gp_Pnt P = BRep_Tool::Pnt(aVert);
889           if (P1.Distance(P) < tol) {
890             SplitLocNums.Append(j);
891             LastLoc = j;
892             break;
893           }
894         }
895       }
896       Vec1 = Vec2;
897       P1 = P2;
898   }
899
900   if (SplitLocNums.Length()==SplitEdgeNums.Length() && SplitEdgeNums.Length()>0) {
901       TopTools_SequenceOfShape aSeqRes;
902       int nn, num1 = 1, num2 = 1;
903       for (nn=1; nn<=SplitEdgeNums.Length(); nn++) {
904         // create wirepath and sequences of shapes
905         BRep_Builder B;
906         TopoDS_Wire tmpW;
907         B.MakeWire(tmpW);
908         for (i=num1; i<=SplitEdgeNums.Value(nn); i++) {
909           B.Add(tmpW,TopoDS::Edge(Edges.Value(i)));
910         }
911         num1 = SplitEdgeNums.Value(nn) + 1;
912         TopTools_SequenceOfShape aTmpSeqBases;
913         TopTools_SequenceOfShape aTmpSeqLocs;
914         for (i=num2; i<=SplitLocNums.Value(nn); i++) {
915           aTmpSeqBases.Append(aSeqBases.Value(i));
916           aTmpSeqLocs.Append(aSeqLocs.Value(i));
917         }
918         num2 = SplitLocNums.Value(nn);
919         // make pipe
920         BRepOffsetAPI_MakePipeShell aBuilder(tmpW);
921         GeomFill_Trihedron theBestMode = EvaluateBestSweepMode(tmpW);
922         if (theBestMode == GeomFill_IsDiscreteTrihedron)
923           aBuilder.SetDiscreteMode();
924         Standard_Integer nbShapes = aTmpSeqBases.Length();
925         for (i=1; i<=nbShapes; i++) {
926           TopoDS_Shape aShapeLoc = aTmpSeqLocs.Value(i);
927           TopoDS_Vertex aVert = TopoDS::Vertex(aShapeLoc);
928           aBuilder.Add(aTmpSeqBases.Value(i), aVert, theWithContact, theWithCorrect);
929         }
930         if (!aBuilder.IsReady()) {
931           Standard_ConstructionError::Raise("Invalid input data for building PIPE: bases are invalid");
932         }
933         aBuilder.Build();
934         TopoDS_Shape resShape = aBuilder.Shape();
935         aSeqRes.Append(resShape);
936       }
937       // create wirepath and sequences of shapes for last part
938       BRep_Builder B;
939       TopoDS_Wire tmpW;
940       B.MakeWire(tmpW);
941       for (i=num1; i<=Edges.Length(); i++) {
942         B.Add(tmpW,TopoDS::Edge(Edges.Value(i)));
943       }
944       TopTools_SequenceOfShape aTmpSeqBases;
945       TopTools_SequenceOfShape aTmpSeqLocs;
946       for (i=num2; i<=aSeqLocs.Length(); i++) {
947         aTmpSeqBases.Append(aSeqBases.Value(i));
948         aTmpSeqLocs.Append(aSeqLocs.Value(i));
949       }
950       // make pipe for last part
951       BRepOffsetAPI_MakePipeShell aBuilder(tmpW);
952       GeomFill_Trihedron theBestMode = EvaluateBestSweepMode(tmpW);
953       if (theBestMode == GeomFill_IsDiscreteTrihedron)
954         aBuilder.SetDiscreteMode();
955       Standard_Integer nbShapes = aTmpSeqBases.Length();
956       for (i=1; i<=nbShapes; i++) {
957         TopoDS_Shape aShapeLoc = aTmpSeqLocs.Value(i);
958         TopoDS_Vertex aVert = TopoDS::Vertex(aShapeLoc);
959         aBuilder.Add(aTmpSeqBases.Value(i), aVert, theWithContact, theWithCorrect);
960       }
961       if (!aBuilder.IsReady()) {
962         Standard_ConstructionError::Raise("Invalid input data for building PIPE: bases are invalid");
963       }
964       aBuilder.Build();
965       TopoDS_Shape resShape = aBuilder.Shape();
966       aSeqRes.Append(resShape);
967       // make sewing for result
968       Handle(BRepBuilderAPI_Sewing) aSewing = new BRepBuilderAPI_Sewing;
969       aSewing->SetTolerance(Precision::Confusion());
970       aSewing->SetFaceMode(Standard_True);
971       aSewing->SetFloatingEdgesMode(Standard_False);
972       aSewing->SetNonManifoldMode(Standard_False);
973       for (i=1; i<=aSeqRes.Length(); i++) {
974         aSewing->Add(aSeqRes.Value(i));
975       }
976       aSewing->Perform();
977       aShape = aSewing->SewedShape();
978   }
979   else {
980       // old implementation without splitting
981       BRepOffsetAPI_MakePipeShell aBuilder(aWirePath);
982       GeomFill_Trihedron theBestMode = EvaluateBestSweepMode(aWirePath);
983       if (theBestMode == GeomFill_IsDiscreteTrihedron)
984         aBuilder.SetDiscreteMode();
985
986       Standard_Integer nbShapes = aSeqBases.Length();
987       Standard_Integer step = nbShapes/nbBases;
988
989       if (nbShapes < nbBases || fmod((double)nbShapes, (double)nbBases)) {
990         Standard_ConstructionError::Raise("Invalid sections were specified for building pipe");
991       }
992       Standard_Integer ind =0;
993       Standard_Real aTolConf = Precision::Confusion();
994       Standard_Real aTolAng  = Precision::Angular();
995
996       for (i = 1; i <= nbShapes && ind < nbShapes; i++) { //i+nbBases <= nbShapes
997         TopTools_SequenceOfShape usedBases;
998         Standard_Integer j = 1;
999         for (; j <= nbBases; j++) {
1000           ind = i + (j-1)*step;
1001           TopoDS_Shape aWireProf = aSeqBases.Value(ind);
1002           usedBases.Append(aWireProf);
1003           if (nbLocs) {
1004             TopoDS_Shape aShapeLoc = aSeqLocs.Value(j);
1005             TopoDS_Vertex aVert = TopoDS::Vertex(aShapeLoc);
1006             aBuilder.Add(aWireProf, aVert, theWithContact, theWithCorrect);
1007           }
1008           else
1009             aBuilder.Add(aWireProf, theWithContact, theWithCorrect);
1010         }
1011         if (!aBuilder.IsReady()) {
1012           Standard_ConstructionError::Raise("Invalid input data for building PIPE: bases are invalid");
1013         }
1014       
1015         aBuilder.SetTolerance(aTolConf, aTolConf, aTolAng);
1016
1017         aBuilder.Build();
1018         aShape = aBuilder.Shape();
1019         aSeqFaces.Append(aShape);
1020         for (j = 1; j <=usedBases.Length(); j++)
1021           aBuilder.Delete(usedBases.Value(j));
1022       }
1023
1024       //for case if section is face
1025       if (aSeqFaces.Length() >1) {
1026         BRep_Builder aB;
1027         TopoDS_Compound aComp;
1028         aB.MakeCompound(aComp);
1029         for (i = 1; i <= aSeqFaces.Length(); i++)
1030           aB.Add(aComp,aSeqFaces.Value(i));
1031         aShape = aComp;
1032       }
1033   }
1034
1035   return aShape;
1036 }
1037
1038 //=======================================================================
1039 //function : CreatePipeForShellSections
1040 //purpose  : auxilary for Execute()
1041 //=======================================================================
1042 static TopoDS_Shape CreatePipeForShellSections(const TopoDS_Wire& aWirePath,
1043                                                GEOMImpl_IPipe* aCI)
1044 {
1045   //cout<<"CreatePipeForShellSections"<<endl;
1046   //TopoDS_Shape res;
1047   int i,j;
1048   BRep_Builder B;
1049
1050   GEOMImpl_IPipeShellSect* aCIDS = (GEOMImpl_IPipeShellSect*)aCI;
1051   Handle(TColStd_HSequenceOfTransient) aBasesObjs = aCIDS->GetBases();
1052   Handle(TColStd_HSequenceOfTransient) aSubBasesObjs = aCIDS->GetSubBases();
1053   Handle(TColStd_HSequenceOfTransient) aLocObjs = aCIDS->GetLocations();
1054   Standard_Boolean aWithContact = (aCIDS->GetWithContactMode());
1055   Standard_Boolean aWithCorrect = (aCIDS->GetWithCorrectionMode());
1056
1057   Standard_Integer nbBases = aBasesObjs->Length(),
1058     nbSubBases = (aSubBasesObjs.IsNull() ? 0 :aSubBasesObjs->Length()),
1059     nbLocs = (aLocObjs.IsNull() ? 0 :aLocObjs->Length());
1060
1061   if (nbLocs != nbBases) {
1062     if (aCI) delete aCI;
1063     Standard_ConstructionError::Raise("Number of sections is not equal to number of locations ");
1064   }
1065   if (nbSubBases && nbSubBases != nbBases) {
1066     if (aCI) delete aCI;
1067     Standard_ConstructionError::Raise("Number of sections is not equal to number of subsections ");
1068   }
1069
1070   //BRepOffsetAPI_MakePipeShell aBuilder(aWirePath);
1071
1072   TopTools_SequenceOfShape VLocs;
1073   for (i=1; i<=nbBases; i++) {
1074     Handle(Standard_Transient) anItemLoc = aLocObjs->Value(i);
1075     if (anItemLoc.IsNull())
1076       continue;
1077     Handle(GEOM_Function) aRefLoc = Handle(GEOM_Function)::DownCast(anItemLoc);
1078     TopoDS_Shape aShapeLoc = aRefLoc->GetValue();
1079     if (aShapeLoc.IsNull() || aShapeLoc.ShapeType() != TopAbs_VERTEX)
1080       continue;
1081     VLocs.Append(aShapeLoc);
1082   }
1083   nbLocs = VLocs.Length();
1084   if (nbLocs != nbBases) {
1085     if (aCI) delete aCI;
1086     Standard_ConstructionError::Raise("One of location shapes is not a vertex");
1087   }
1088   // split wire path by location points
1089   TColgp_SequenceOfPnt PLocs;
1090   for (i=1; i<=nbLocs; i++) {
1091     TopoDS_Vertex V = TopoDS::Vertex(VLocs.Value(i));
1092     PLocs.Append(BRep_Tool::Pnt(V));
1093   }
1094
1095   TopTools_SequenceOfShape Edges;
1096   TopTools_SequenceOfShape Wires;
1097   ShapeAnalysis_Edge sae;
1098
1099   if (nbLocs==2) {
1100     TopExp_Explorer anExp;
1101     for (anExp.Init(aWirePath, TopAbs_EDGE); anExp.More(); anExp.Next()) {
1102       Edges.Append(anExp.Current());
1103     }
1104     Standard_Integer Num1 = 0;
1105     Standard_Integer Num2 = 0;
1106     for (i=1; i<=Edges.Length(); i++) {
1107       TopoDS_Edge E = TopoDS::Edge(Edges.Value(i));
1108       double tol = BRep_Tool::Tolerance(E);
1109       TopoDS_Vertex V1 = sae.FirstVertex(E);
1110       TopoDS_Vertex V2 = sae.LastVertex(E);
1111       gp_Pnt P1 = BRep_Tool::Pnt(V1);
1112       gp_Pnt P2 = BRep_Tool::Pnt(V2);
1113       if (P1.Distance(PLocs.First()) < tol) {
1114         Num1 = i;
1115       }
1116       if (P2.Distance(PLocs.Last()) < tol) {
1117         Num2 = i;
1118       }
1119     }
1120     if (Num1>0 && Num2>0) {
1121       TopoDS_Wire W;
1122       B.MakeWire(W);
1123       for (i=Num1; i<=Num2; i++) {
1124         B.Add(W,Edges.Value(i));
1125       }
1126       Wires.Append(W);
1127     }
1128     else {
1129       Wires.Append(aWirePath);
1130     }
1131   }
1132   else {
1133     TopExp_Explorer anExp;
1134     for (anExp.Init(aWirePath, TopAbs_EDGE); anExp.More(); anExp.Next()) {
1135       Edges.Append(anExp.Current());
1136     }
1137     TopoDS_Edge edge = TopoDS::Edge(Edges.First());
1138     double tol = BRep_Tool::Tolerance(edge);
1139     TopoDS_Vertex VF = sae.FirstVertex(edge);
1140     gp_Pnt PF = BRep_Tool::Pnt(VF);
1141     //cout<<"PF("<<PF.X()<<","<<PF.Y()<<","<<PF.Z()<<")"<<endl;
1142     if (PF.Distance(PLocs.First()) > tol) {
1143       if (aCI) delete aCI;
1144       Standard_ConstructionError::Raise
1145         ("First location shapes is not coincided with first vertex of aWirePath");
1146     }
1147     VLocs.ChangeValue(1) = VF;
1148     edge = TopoDS::Edge(Edges.Last());
1149     tol = BRep_Tool::Tolerance(edge);
1150     TopoDS_Vertex VL = sae.LastVertex(edge);
1151     gp_Pnt PL = BRep_Tool::Pnt(VL);
1152     if (PL.Distance(PLocs.Last()) > tol) {
1153       if (aCI) delete aCI;
1154       Standard_ConstructionError::Raise
1155         ("Last location shapes is not coincided with last vertex of aWirePath");
1156     }
1157     VLocs.ChangeValue(nbLocs) = VL;
1158     int jcurr = 2;
1159     TopTools_SequenceOfShape tmpEdges;
1160     for (i=1; i<=Edges.Length() && jcurr<nbLocs; i++) {
1161       TopoDS_Edge E = TopoDS::Edge(Edges.Value(i));
1162       tol = BRep_Tool::Tolerance(E);
1163       TopoDS_Vertex V1 = sae.FirstVertex(E);
1164       TopoDS_Vertex V2 = sae.LastVertex(E);
1165       gp_Pnt P1 = BRep_Tool::Pnt(V1);
1166       gp_Pnt P2 = BRep_Tool::Pnt(V2);
1167       if (P2.Distance(PLocs.Value(jcurr)) < tol) {
1168         // make wire from current edge and add created
1169         // wire to Wires
1170         TopoDS_Wire W;
1171         B.MakeWire(W);
1172         for (j=1; j<=tmpEdges.Length(); j++)
1173           B.Add(W,tmpEdges.Value(j));
1174         B.Add(W,E);
1175         Wires.Append(W);
1176         VLocs.ChangeValue(jcurr) = V2;
1177         jcurr++;
1178         tmpEdges.Clear();
1179       }
1180       else {
1181         // find distance between E and aLocs(jcurr)
1182         double fp,lp;
1183         Handle(Geom_Curve) C = BRep_Tool::Curve(E,fp,lp);
1184         GeomAPI_ProjectPointOnCurve PPCurve (PLocs.Value(jcurr),C);
1185         if (PPCurve.NbPoints()>0 &&
1186             PLocs.Value(jcurr).Distance(PPCurve.Point(1)) < tol) {
1187           double param = PPCurve.Parameter(1);
1188           gp_Pnt PC1;
1189           C->D0(param,PC1);
1190           // split current edge
1191           Handle(Geom_TrimmedCurve) tc1 = new Geom_TrimmedCurve(C,fp,param);
1192           Handle(Geom_TrimmedCurve) tc2 = new Geom_TrimmedCurve(C,param,lp);
1193           TopoDS_Edge E1,E2;
1194           gp_Pnt Pfp;
1195           C->D0(fp,Pfp);
1196           if (Pfp.Distance(P1)<tol) {
1197             B.MakeEdge(E1,tc1,tol);
1198             B.Add(E1,V1);
1199             TopoDS_Shape tmpV = VLocs.Value(jcurr).Oriented(TopAbs_REVERSED);
1200             B.Add(E1,TopoDS::Vertex(tmpV));
1201             tmpEdges.Append(E1);
1202             B.MakeEdge(E2,tc2,tol);
1203             tmpV = VLocs.Value(jcurr).Oriented(TopAbs_FORWARD);
1204             B.Add(E2,TopoDS::Vertex(tmpV));
1205             B.Add(E2,V2);
1206           }
1207           else {
1208             B.MakeEdge(E1,tc2,tol);
1209             TopoDS_Shape tmpV = VLocs.Value(jcurr).Oriented(TopAbs_FORWARD);
1210             B.Add(E1,TopoDS::Vertex(tmpV));
1211             B.Add(E1,V1);
1212             E1.Reverse();
1213             tmpEdges.Append(E1);
1214             B.MakeEdge(E2,tc1,tol);
1215             B.Add(E2,V2);
1216             tmpV = VLocs.Value(jcurr).Oriented(TopAbs_REVERSED);
1217             B.Add(E2,TopoDS::Vertex(tmpV));
1218             E2.Reverse();
1219           }
1220           // create wire from tmpEdges
1221           TopoDS_Wire W;
1222           B.MakeWire(W);
1223           for (j=1; j<=tmpEdges.Length(); j++)
1224             B.Add(W,tmpEdges.Value(j));
1225           Wires.Append(W);
1226           jcurr++;
1227           tmpEdges.Clear();
1228           Edges.Remove(i);
1229           Edges.InsertAfter(i-1,E1);
1230           Edges.InsertAfter(i,E2);
1231         }
1232         else {
1233           tmpEdges.Append(E);
1234         }
1235       }
1236     }
1237     // create wire from other edges
1238     TopoDS_Wire W;
1239     B.MakeWire(W);
1240     for (; i<=Edges.Length(); i++)
1241       B.Add(W,Edges.Value(i));
1242     Wires.Append(W);
1243     //cout<<"Wires.Length()="<<Wires.Length()<<endl;
1244   }
1245
1246   if (Wires.Length() != nbLocs-1) {
1247     if (aCI) delete aCI;
1248     Standard_ConstructionError::Raise
1249       ("One of location shapes is not lied on the path");
1250   }
1251
1252   //TopTools_SequenceOfShape aSeqBases;
1253   //TopTools_SequenceOfShape aSeqSubBases;
1254   //TopTools_SequenceOfShape aSeqFaces;
1255   TopoDS_Compound aComp;
1256   B.MakeCompound(aComp);
1257   for (i = 1; i < nbBases; i++) {
1258     TopoDS_Wire WPath = TopoDS::Wire(Wires.Value(i));
1259     // 1 section
1260     Handle(Standard_Transient) anItem1 = aBasesObjs->Value(i);
1261     if (anItem1.IsNull())
1262       continue;
1263     Handle(GEOM_Function) aRefBase1 = Handle(GEOM_Function)::DownCast(anItem1);
1264     if (aRefBase1.IsNull())
1265       continue;
1266     TopoDS_Shape aShBase1 = aRefBase1->GetValue();
1267     if (aShBase1.IsNull())
1268       continue;
1269     TopAbs_ShapeEnum aType1 = aShBase1.ShapeType();
1270     // 2 section
1271     Handle(Standard_Transient) anItem2 = aBasesObjs->Value(i+1);
1272     if (anItem2.IsNull())
1273       continue;
1274     Handle(GEOM_Function) aRefBase2 = Handle(GEOM_Function)::DownCast(anItem2);
1275     if (aRefBase2.IsNull())
1276       continue;
1277     TopoDS_Shape aShBase2 = aRefBase2->GetValue();
1278     if (aShBase2.IsNull())
1279       continue;
1280     TopAbs_ShapeEnum aType2 = aShBase2.ShapeType();
1281
1282     //BRepTools::Write(aShBase1,"/dn02/users_Linux/skl/work/Bugs/14857/base1.brep");
1283
1284     bool OkSec = (aType1==TopAbs_SHELL || aType1==TopAbs_FACE) &&
1285                  (aType2==TopAbs_SHELL || aType2==TopAbs_FACE);
1286     if (!OkSec) {
1287       if (aCI) delete aCI;
1288       Standard_ConstructionError::Raise("One of section shapes has invalid type");
1289     }
1290
1291     bool CreateFewSolids = false;
1292     // compare sections
1293     TopExp_Explorer anExp;
1294     Standard_Integer nbf1 = 0;
1295     for (anExp.Init(aShBase1, TopAbs_FACE); anExp.More(); anExp.Next()) {
1296       nbf1++;
1297     }
1298     Standard_Integer nbf2 = 0;
1299     for (anExp.Init(aShBase2, TopAbs_FACE); anExp.More(); anExp.Next()) {
1300       nbf2++;
1301     }
1302     if (nbf1==nbf2) {
1303       CreateFewSolids = true;
1304     }
1305
1306     /*
1307     // check orientation of sections
1308     bool NeedReverse = false;
1309     {
1310       // first section
1311       anExp.Init(aShBase1, TopAbs_FACE);
1312       TopoDS_Shape aFace = anExp.Current();
1313       TColgp_SequenceOfPnt aPnts;
1314       double xc=0, yc=0, zc=0;
1315       for (anExp.Init(aFace, TopAbs_VERTEX); anExp.More(); anExp.Next()) {
1316         TopoDS_Vertex V = TopoDS::Vertex(anExp.Current());
1317         aPnts.Append(BRep_Tool::Pnt(V));
1318         xc += aPnts.Last().X();
1319         yc += aPnts.Last().Y();
1320         zc += aPnts.Last().Z();
1321       }
1322       gp_Pnt PC(xc/aPnts.Length(), yc/aPnts.Length(), zc/aPnts.Length());
1323       gp_Vec V1(PC,aPnts.Value(1));
1324       gp_Vec V2(PC,aPnts.Value(2));
1325       gp_Vec VN = V1.Crossed(V2);
1326       for (int ip=2; ip<aPnts.Length(); ip++) {
1327         V1 = gp_Vec(PC,aPnts.Value(ip));
1328         V2 = gp_Vec(PC,aPnts.Value(ip+1));
1329         VN.Add(V1.Crossed(V2));
1330       }
1331       gp_Vec PathNorm;
1332       gp_Pnt PLoc = BRep_Tool::Pnt(TopoDS::Vertex(VLocs(i)));
1333       TopExp_Explorer WE;
1334       for (WE.Init(WPath, TopAbs_EDGE); WE.More(); WE.Next()) {
1335         TopoDS_Edge edge = TopoDS::Edge(WE.Current());
1336         double tol = BRep_Tool::Tolerance(edge);
1337         TopoDS_Vertex VF = sae.FirstVertex(edge);
1338         gp_Pnt PF = BRep_Tool::Pnt(VF);
1339         if (PF.Distance(PLoc) < tol) {
1340           double fp,lp;
1341           Handle(Geom_Curve) C = BRep_Tool::Curve(edge,fp,lp);
1342           gp_Pnt P1,P2;
1343           C->D0(fp,P1);
1344           if (P1.Distance(PLoc) < tol) {
1345             C->D0(fp+(lp-fp)/100,P2);
1346           }
1347           else {
1348             C->D0(lp,P1);
1349             C->D0(lp+(fp-lp)/100,P2);
1350           }
1351           PathNorm = gp_Vec(P1,P2);
1352           break;
1353         }
1354         else {
1355           TopoDS_Vertex VL = sae.LastVertex(edge);
1356           gp_Pnt PL = BRep_Tool::Pnt(VL);
1357           if (PL.Distance(PLoc) < tol) {
1358             double fp,lp;
1359             Handle(Geom_Curve) C = BRep_Tool::Curve(edge,fp,lp);
1360             gp_Pnt P1,P2;
1361             C->D0(fp,P1);
1362             if (P1.Distance(PLoc) < tol) {
1363               C->D0(fp+(lp-fp)/100,P2);
1364             }
1365             else {
1366               C->D0(lp,P1);
1367               C->D0(lp+(fp-lp)/100,P2);
1368             }
1369             PathNorm = gp_Vec(P2,P1);
1370             break;
1371           }
1372         }
1373       }
1374       cout<<"VN("<<VN.X()<<","<<VN.Y()<<","<<VN.Z()<<")"<<endl;
1375       cout<<"PathNorm("<<PathNorm.X()<<","<<PathNorm.Y()<<","<<PathNorm.Z()<<")"<<endl;
1376       if (fabs(VN.Angle(PathNorm))>PI/2.) {
1377         NeedReverse = true;
1378         aShBase1.Reverse();
1379       }
1380     }
1381     {
1382       // second section
1383       anExp.Init(aShBase2, TopAbs_FACE);
1384       TopoDS_Shape aFace = anExp.Current();
1385       TColgp_SequenceOfPnt aPnts;
1386       double xc=0, yc=0, zc=0;
1387       for (anExp.Init(aFace, TopAbs_VERTEX); anExp.More(); anExp.Next()) {
1388         TopoDS_Vertex V = TopoDS::Vertex(anExp.Current());
1389         aPnts.Append(BRep_Tool::Pnt(V));
1390         xc += aPnts.Last().X();
1391         yc += aPnts.Last().Y();
1392         zc += aPnts.Last().Z();
1393       }
1394       gp_Pnt PC(xc/aPnts.Length(), yc/aPnts.Length(), zc/aPnts.Length());
1395       gp_Vec V1(PC,aPnts.Value(1));
1396       gp_Vec V2(PC,aPnts.Value(2));
1397       gp_Vec VN = V1.Crossed(V2);
1398       for (int ip=2; ip<aPnts.Length(); ip++) {
1399         V1 = gp_Vec(PC,aPnts.Value(ip));
1400         V2 = gp_Vec(PC,aPnts.Value(ip+1));
1401         VN.Add(V1.Crossed(V2));
1402       }
1403       gp_Vec PathNorm;
1404       gp_Pnt PLoc = BRep_Tool::Pnt(TopoDS::Vertex(VLocs(i+1)));
1405       TopExp_Explorer WE;
1406       for (WE.Init(WPath, TopAbs_EDGE); WE.More(); WE.Next()) {
1407         TopoDS_Edge edge = TopoDS::Edge(WE.Current());
1408         double tol = BRep_Tool::Tolerance(edge);
1409         TopoDS_Vertex VF = sae.FirstVertex(edge);
1410         gp_Pnt PF = BRep_Tool::Pnt(VF);
1411         if (PF.Distance(PLoc) < tol) {
1412           double fp,lp;
1413           Handle(Geom_Curve) C = BRep_Tool::Curve(edge,fp,lp);
1414           gp_Pnt P1,P2;
1415           C->D0(fp,P1);
1416           if (P1.Distance(PLoc) < tol) {
1417             C->D0(fp+(lp-fp)/100,P2);
1418           }
1419           else {
1420             C->D0(lp,P1);
1421             C->D0(lp+(fp-lp)/100,P2);
1422           }
1423           PathNorm = gp_Vec(P2,P1);
1424           break;
1425         }
1426         else {
1427           TopoDS_Vertex VL = sae.LastVertex(edge);
1428           gp_Pnt PL = BRep_Tool::Pnt(VL);
1429           if (PL.Distance(PLoc) < tol) {
1430             double fp,lp;
1431             Handle(Geom_Curve) C = BRep_Tool::Curve(edge,fp,lp);
1432             gp_Pnt P1,P2;
1433             C->D0(fp,P1);
1434             if (P1.Distance(PLoc) < tol) {
1435               C->D0(fp+(lp-fp)/100,P2);
1436             }
1437             else {
1438               C->D0(lp,P1);
1439               C->D0(lp+(fp-lp)/100,P2);
1440             }
1441             PathNorm = gp_Vec(P2,P1);
1442             break;
1443           }
1444         }
1445       }
1446       //cout<<"VN("<<VN.X()<<","<<VN.Y()<<","<<VN.Z()<<")"<<endl;
1447       //cout<<"PathNorm("<<PathNorm.X()<<","<<PathNorm.Y()<<","<<PathNorm.Z()<<")"<<endl;
1448       if (fabs(VN.Angle(PathNorm))>PI/2.)
1449         aShBase2.Reverse();
1450     }
1451     */
1452
1453     if (!CreateFewSolids) {
1454       // we can create only one solid
1455       TopoDS_Shape aWire1, aWire2;
1456       // prepare aWire1
1457       if (aType1==TopAbs_SHELL) {
1458         // create wire as boundary contour if shell is no closed
1459         // get free boundary shapes
1460         ShapeAnalysis_FreeBounds anAnalizer(aShBase1);
1461         TopoDS_Compound aClosed = anAnalizer.GetClosedWires();
1462         //TopExp_Explorer anExp;
1463         Standard_Integer NbWires = 0;
1464         for (anExp.Init(aClosed, TopAbs_WIRE); anExp.More(); anExp.Next()) {
1465           NbWires++;
1466           aWire1 = anExp.Current();
1467         }
1468         if (NbWires!=1) {
1469           // bad case
1470           if (aCI) delete aCI;
1471           Standard_ConstructionError::Raise("Bad shell is used as section ");
1472         }
1473       }
1474       else { // aType1==TopAbs_FACE
1475         TopExp_Explorer aExpW(aShBase1,TopAbs_WIRE);
1476         aWire1 = aExpW.Current();
1477       }
1478       // prepare aWire2
1479       if (aType2==TopAbs_SHELL) {
1480         // create wire as boundary contour if shell is no closed
1481         // get free boundary shapes
1482         ShapeAnalysis_FreeBounds anAnalizer(aShBase2);
1483         TopoDS_Compound aClosed = anAnalizer.GetClosedWires();
1484         //TopExp_Explorer anExp;
1485         Standard_Integer NbWires = 0;
1486         for (anExp.Init(aClosed, TopAbs_WIRE); anExp.More(); anExp.Next()) {
1487           NbWires++;
1488           aWire2 = anExp.Current();
1489         }
1490         if (NbWires!=1) {
1491           // bad case
1492           if (aCI) delete aCI;
1493           Standard_ConstructionError::Raise("Bad shell is used as section ");
1494         }
1495       }
1496       else { // aType2==TopAbs_FACE
1497         TopExp_Explorer aExpW(aShBase2,TopAbs_WIRE);
1498         aWire2 = aExpW.Current();
1499       }
1500       // make pipe using aWire1 and aWire2
1501       if (!aWire1.IsNull() && !aWire2.IsNull()) {
1502         //BRepOffsetAPI_MakePipeShell aBuilder(aWirePath);
1503         BRepOffsetAPI_MakePipeShell aBuilder(WPath);
1504         GeomFill_Trihedron theBestMode = EvaluateBestSweepMode(WPath);
1505         if (theBestMode == GeomFill_IsDiscreteTrihedron)
1506           aBuilder.SetDiscreteMode();
1507         aBuilder.Add(aWire1, TopoDS::Vertex(VLocs(i)),
1508                      aWithContact, aWithCorrect);
1509         aBuilder.Add(aWire2, TopoDS::Vertex(VLocs(i+1)),
1510                      aWithContact, aWithCorrect);
1511         if (!aBuilder.IsReady()) {
1512           if (aCI) delete aCI;
1513           Standard_ConstructionError::Raise("Invalid input data for building PIPE: bases are invalid");
1514         }
1515         aBuilder.Build();
1516         TopoDS_Shape aShape = aBuilder.Shape();
1517         TopoDS_Shell aShell;
1518         B.MakeShell(aShell);
1519         for (anExp.Init(aShape, TopAbs_FACE); anExp.More(); anExp.Next()) {
1520           B.Add(aShell,anExp.Current());
1521         }
1522         for (anExp.Init(aShBase1, TopAbs_FACE); anExp.More(); anExp.Next()) {
1523           B.Add(aShell,anExp.Current());
1524         }
1525         for (anExp.Init(aShBase2, TopAbs_FACE); anExp.More(); anExp.Next()) {
1526           B.Add(aShell,anExp.Current());
1527         }
1528         // make sewing for this shell
1529         Handle(BRepBuilderAPI_Sewing) aSewing = new BRepBuilderAPI_Sewing;
1530         aSewing->SetTolerance(Precision::Confusion());
1531         aSewing->SetFaceMode(Standard_True);
1532         aSewing->SetFloatingEdgesMode(Standard_False);
1533         aSewing->SetNonManifoldMode(Standard_False);
1534         for (anExp.Init(aShell, TopAbs_FACE); anExp.More(); anExp.Next()) {
1535           aSewing->Add(anExp.Current());
1536         }
1537         aSewing->Perform();
1538         const TopoDS_Shape aSewShape = aSewing->SewedShape();
1539         if (aSewShape.ShapeType() == TopAbs_SHELL) {
1540           aShell = TopoDS::Shell(aSewShape);
1541           GProp_GProps aSystem;
1542           BRepGProp::VolumeProperties(aShell, aSystem);
1543           if (aSystem.Mass()<0) {
1544             aShell.Reverse();
1545           }
1546           if (BRep_Tool::IsClosed(aShell)) {
1547             TopoDS_Solid aSolid;
1548             B.MakeSolid(aSolid);
1549             B.Add(aSolid,aShell);
1550             B.Add(aComp,aSolid);
1551           }
1552           else {
1553             B.Add(aComp,aShell);
1554           }
1555         }
1556         else {
1557           B.Add(aComp,aShell);
1558         }
1559       }
1560     }
1561     else {
1562       // main block - creation few solids (for each pair of faces)
1563       TopTools_MapOfShape aFaces1,aFaces2;
1564       for (anExp.Init(aShBase1, TopAbs_FACE); anExp.More(); anExp.Next()) {
1565         aFaces1.Add(anExp.Current());
1566       }
1567       for (anExp.Init(aShBase2, TopAbs_FACE); anExp.More(); anExp.Next()) {
1568         aFaces2.Add(anExp.Current());
1569       }
1570       // creating map of edge faces
1571       TopTools_IndexedDataMapOfShapeListOfShape aMapEdgeFaces1;
1572       TopExp::MapShapesAndAncestors(aShBase1, TopAbs_EDGE, TopAbs_FACE, aMapEdgeFaces1);
1573       TopTools_IndexedDataMapOfShapeListOfShape aMapEdgeFaces2;
1574       TopExp::MapShapesAndAncestors(aShBase2, TopAbs_EDGE, TopAbs_FACE, aMapEdgeFaces2);
1575
1576       // constuct map face->face
1577       TopTools_IndexedDataMapOfShapeShape FF;
1578       TopoDS_Shape FS1,FS2;
1579       if (nbSubBases==0) {
1580         // find edge the most distant from location point
1581         // (this edge is not shared by two faces)
1582         double maxdist = 0.;
1583         TopoDS_Shape E1;
1584         TopoDS_Vertex V11,V21;
1585         for (j=1; j<=aMapEdgeFaces1.Extent(); j++) {
1586           TopoDS_Shape tmp = aMapEdgeFaces1.FindKey(j);
1587           const TopTools_ListOfShape& aList = aMapEdgeFaces1.FindFromKey(tmp);
1588           if (aList.Extent()>1)
1589             continue;
1590           TopExp_Explorer expv;
1591           expv.Init(tmp, TopAbs_VERTEX);
1592           TopoDS_Vertex V1 = TopoDS::Vertex(expv.Current());
1593           expv.Next();
1594           TopoDS_Vertex V2 = TopoDS::Vertex(expv.Current());
1595           gp_Pnt P1 = BRep_Tool::Pnt(V1);
1596           gp_Pnt P2 = BRep_Tool::Pnt(V2);
1597           double dist = PLocs.Value(i).Distance(P1) + PLocs.Value(i).Distance(P2);
1598           if (dist>maxdist) {
1599             E1 = tmp;
1600             V11 = V1;
1601             V21 = V2;
1602             TopTools_ListIteratorOfListOfShape anIter(aList);
1603             FS1 = anIter.Value();
1604             maxdist = dist;
1605           }
1606         }
1607         // main direction for comparing
1608         gp_Vec VM(PLocs.Value(i),PLocs.Value(i+1));
1609         // find corresponding edge from next section
1610         double minang = M_PI;
1611         gp_Pnt P11 = BRep_Tool::Pnt(V11);
1612         gp_Pnt P21 = BRep_Tool::Pnt(V21);
1613         TopoDS_Shape E2;
1614         TopoDS_Vertex V12,V22;
1615         for (j=1; j<=aMapEdgeFaces2.Extent(); j++) {
1616           TopoDS_Shape tmp = aMapEdgeFaces2.FindKey(j);
1617           const TopTools_ListOfShape& aList = aMapEdgeFaces2.FindFromKey(tmp);
1618           if (aList.Extent()>1)
1619             continue;
1620           TopExp_Explorer expv;
1621           expv.Init(tmp, TopAbs_VERTEX);
1622           TopoDS_Vertex V1tmp = TopoDS::Vertex(expv.Current());
1623           expv.Next();
1624           TopoDS_Vertex V2tmp = TopoDS::Vertex(expv.Current());
1625           gp_Pnt P1tmp = BRep_Tool::Pnt(V1tmp);
1626           gp_Pnt P2tmp = BRep_Tool::Pnt(V2tmp);
1627           double d1 = P1tmp.Distance(P11) + P2tmp.Distance(P21);
1628           double d2 = P1tmp.Distance(P21) + P2tmp.Distance(P11);
1629           TopoDS_Vertex V1,V2;
1630           gp_Pnt P1,P2;
1631           if (d1>d2) {
1632             V1 = V2tmp; P1 = P2tmp;
1633             V2 = V1tmp; P2 = P1tmp;
1634           }
1635           else {
1636             V1 = V1tmp; P1 = P1tmp;
1637             V2 = V2tmp; P2 = P2tmp;
1638           }
1639           gp_Vec Vec1(P11,P1);
1640           gp_Vec Vec2(P21,P2);
1641           double ang = fabs(Vec1.Angle(VM)) + fabs(Vec2.Angle(VM));
1642           if (ang<minang) {
1643             E2 = tmp;
1644             V12 = V1;
1645             V22 = V2;
1646             TopTools_ListIteratorOfListOfShape anIter(aList);
1647             FS2 = anIter.Value();
1648             minang = ang;
1649           }
1650         }
1651         // put all pairs to map FF
1652         FF.Add(FS1,FS2);
1653         FF.Add(E1,E2);
1654         FF.Add(V11,V12);
1655         FF.Add(V21,V22);
1656
1657         // add pairs of edges to FF
1658         bool stat =  FillForOtherEdges(FS1,E1,V11,FF);
1659         if (!stat) {
1660           if (aCI) delete aCI;
1661           Standard_ConstructionError::Raise("FindForOtherEdges: Can not mapping other egdes");
1662         }
1663
1664       }
1665       else {
1666         { // 1 section
1667           Handle(Standard_Transient) anItem = aSubBasesObjs->Value(i);
1668           if (anItem.IsNull()) {
1669             if (aCI) delete aCI;
1670             Standard_ConstructionError::Raise("Invalid subbase shape");
1671           }
1672           Handle(GEOM_Function) aRefBase = Handle(GEOM_Function)::DownCast(anItem);
1673           if (aRefBase.IsNull()) {
1674             if (aCI) delete aCI;
1675             Standard_ConstructionError::Raise("Invalid subbase shape");
1676           }
1677           TopoDS_Shape aSh = aRefBase->GetValue();
1678           if (aSh.IsNull()) {
1679             if (aCI) delete aCI;
1680             Standard_ConstructionError::Raise("Invalid subbase shape");
1681           }
1682           if (aSh.ShapeType()!=TopAbs_FACE) {
1683             if (aCI) delete aCI;
1684             Standard_ConstructionError::Raise("Invalid subbase shape");
1685           }
1686           FS1 = aSh;
1687         }
1688         { // 2 section
1689           Handle(Standard_Transient) anItem = aSubBasesObjs->Value(i+1);
1690           if (anItem.IsNull()) {
1691             if (aCI) delete aCI;
1692             Standard_ConstructionError::Raise("Invalid subbase shape");
1693           }
1694           Handle(GEOM_Function) aRefBase = Handle(GEOM_Function)::DownCast(anItem);
1695           if (aRefBase.IsNull()) {
1696             if (aCI) delete aCI;
1697             Standard_ConstructionError::Raise("Invalid subbase shape");
1698           }
1699           TopoDS_Shape aSh = aRefBase->GetValue();
1700           if (aSh.IsNull()) {
1701             if (aCI) delete aCI;
1702             Standard_ConstructionError::Raise("Invalid subbase shape");
1703           }
1704           if (aSh.ShapeType()!=TopAbs_FACE) {
1705             if (aCI) delete aCI;
1706             Standard_ConstructionError::Raise("Invalid subbase shape");
1707           }
1708           FS2 = aSh;
1709         }
1710
1711         if (!aFaces1.Contains(FS1) || !aFaces2.Contains(FS2)) {
1712           if (aCI) delete aCI;
1713           Standard_ConstructionError::Raise("Invalid subbase shape");
1714         }
1715
1716         FF.Add(FS1,FS2);
1717
1718         // add pairs of edges to FF
1719         bool stat =  FillCorrespondingEdges(FS1, FS2, TopoDS::Vertex(VLocs(i)),
1720                                             TopoDS::Vertex(VLocs(i+1)), WPath, FF);
1721         if (!stat) {
1722           if (aCI) delete aCI;
1723           Standard_ConstructionError::Raise("Can not create correct pipe");
1724         }
1725       }
1726
1727       FindNextPairOfFaces(FS1, aMapEdgeFaces1, aMapEdgeFaces2, FF, aCI);
1728
1729       // make pipe for each pair of faces
1730       for (j=1; j<=FF.Extent(); j++) {
1731         TopoDS_Shape F1 = FF.FindKey(j);
1732         if (F1.ShapeType() != TopAbs_FACE)
1733           continue;
1734         TopoDS_Shape F2 = FF.FindFromIndex(j);
1735         TopExp_Explorer aExpW1(F1,TopAbs_WIRE);
1736         TopoDS_Wire aWire1 = TopoDS::Wire(aExpW1.Current());
1737         TopExp_Explorer aExpW2(F2,TopAbs_WIRE);
1738         TopoDS_Wire aWire2 = TopoDS::Wire(aExpW2.Current());
1739         // make pipe using aWire1 and aWire2
1740         if (!aWire1.IsNull() && !aWire2.IsNull()) {
1741           BRepOffsetAPI_MakePipeShell aBuilder(WPath);
1742           GeomFill_Trihedron theBestMode = EvaluateBestSweepMode(WPath);
1743           if (theBestMode == GeomFill_IsDiscreteTrihedron)
1744             aBuilder.SetDiscreteMode();
1745           aBuilder.Add(aWire1, TopoDS::Vertex(VLocs(i)),
1746                        aWithContact, aWithCorrect);
1747           aBuilder.Add(aWire2, TopoDS::Vertex(VLocs(i+1)),
1748                        aWithContact, aWithCorrect);
1749           if (!aBuilder.IsReady()) {
1750             if (aCI) delete aCI;
1751             Standard_ConstructionError::Raise("Invalid input data for building PIPE: bases are invalid");
1752           }
1753           aBuilder.Build();
1754           TopoDS_Shape aShape = aBuilder.Shape();
1755           TopoDS_Shell aShell;
1756           B.MakeShell(aShell);
1757           for (anExp.Init(aShape, TopAbs_FACE); anExp.More(); anExp.Next()) {
1758             B.Add(aShell,anExp.Current());
1759           }
1760
1761           B.Add(aShell,F1);
1762           B.Add(aShell,F2);
1763           // make sewing for this shell
1764           Handle(BRepBuilderAPI_Sewing) aSewing = new BRepBuilderAPI_Sewing;
1765           aSewing->SetTolerance(Precision::Confusion());
1766           aSewing->SetFaceMode(Standard_True);
1767           aSewing->SetFloatingEdgesMode(Standard_False);
1768           aSewing->SetNonManifoldMode(Standard_False);
1769           for (anExp.Init(aShell, TopAbs_FACE); anExp.More(); anExp.Next()) {
1770             aSewing->Add(anExp.Current());
1771           }
1772           aSewing->Perform();
1773           const TopoDS_Shape aSewShape = aSewing->SewedShape();
1774           if (aSewShape.ShapeType() == TopAbs_SHELL) {
1775             aShell = TopoDS::Shell(aSewShape);
1776             GProp_GProps aSystem;
1777             BRepGProp::VolumeProperties(aShell, aSystem);
1778             if (aSystem.Mass()<0) {
1779               //cout<<"aSewShape is reversed"<<endl;
1780               aShell.Reverse();
1781             }
1782             if (BRep_Tool::IsClosed(aShell)) {
1783               TopoDS_Solid aSolid;
1784               B.MakeSolid(aSolid);
1785               B.Add(aSolid,aShell);
1786               B.Add(aComp,aSolid);
1787             }
1788             else {
1789               B.Add(aComp,aShell);
1790             }
1791           }
1792           else {
1793             B.Add(aComp,aShell);
1794           }
1795         }
1796       }
1797
1798     }
1799   }
1800
1801   //BRepTools::Write(aComp,"/dn02/users_Linux/skl/work/Bugs/14857/comp.brep");
1802   return aComp;
1803 }
1804
1805 //=======================================================================
1806 //function : CreatePipeShellsWithoutPath
1807 //purpose  : auxilary for Execute()
1808 //=======================================================================
1809 static TopoDS_Shape CreatePipeShellsWithoutPath(GEOMImpl_IPipe* aCI)
1810 {
1811   //cout<<"CreatePipeShellsWithoutPath"<<endl;
1812   int i,j;
1813   BRep_Builder B;
1814
1815   GEOMImpl_IPipeShellSect* aCIDS = (GEOMImpl_IPipeShellSect*)aCI;
1816   // shell sections
1817   Handle(TColStd_HSequenceOfTransient) aBasesObjs = aCIDS->GetBases();
1818   // vertex for recognition
1819   Handle(TColStd_HSequenceOfTransient) VObjs = aCIDS->GetLocations();
1820
1821   Standard_Integer nbBases = aBasesObjs->Length(),
1822     nbv = (VObjs.IsNull() ? 0 :VObjs->Length());
1823
1824   if (nbv != nbBases) {
1825     if (aCI) delete aCI;
1826     Standard_ConstructionError::Raise("Number of shapes for recognition is invalid");
1827   }
1828
1829   TopTools_SequenceOfShape SecVs,Bases;
1830   for (i=1; i<=nbBases; i++) {
1831     // vertex
1832     Handle(Standard_Transient) anItem = VObjs->Value(i);
1833     if (anItem.IsNull())
1834       continue;
1835     Handle(GEOM_Function) aRef = Handle(GEOM_Function)::DownCast(anItem);
1836     TopoDS_Shape V = aRef->GetValue();
1837     if (V.IsNull() || V.ShapeType() != TopAbs_VERTEX)
1838       continue;
1839     SecVs.Append(V);
1840     // section
1841     anItem = aBasesObjs->Value(i);
1842     if (anItem.IsNull())
1843       continue;
1844     aRef = Handle(GEOM_Function)::DownCast(anItem);
1845     TopoDS_Shape aSh = aRef->GetValue();
1846     if (aSh.IsNull())
1847       continue;
1848     Bases.Append(aSh);
1849   }
1850   nbv = SecVs.Length();
1851   nbBases = Bases.Length();
1852   if (nbv != nbBases) {
1853     if (aCI) delete aCI;
1854     Standard_ConstructionError::Raise("One of shapes for recognition is not a vertex");
1855   }
1856
1857   TopoDS_Compound aComp;
1858   B.MakeCompound(aComp);
1859
1860   for (i = 1; i < nbBases; i++) {
1861     MESSAGE ("Make pipe between sections "<<i<<" and "<<i+1);
1862     TopoDS_Shape aShBase1 = Bases.Value(i);
1863     TopoDS_Shape aShBase2 = Bases.Value(i+1);
1864     TopExp_Explorer anExp;
1865     Standard_Integer nbf1 = 0;
1866     for (anExp.Init(aShBase1, TopAbs_FACE); anExp.More(); anExp.Next()) {
1867       nbf1++;
1868     }
1869     Standard_Integer nbf2 = 0;
1870     for (anExp.Init(aShBase2, TopAbs_FACE); anExp.More(); anExp.Next()) {
1871       nbf2++;
1872     }
1873     //cout<<"nbf1="<<nbf1<<" nbf2="<<nbf2<<endl;
1874     if (nbf1!=nbf2) {
1875       if (aCI) delete aCI;
1876       Standard_ConstructionError::Raise("Different number of faces in the sections");
1877     }
1878
1879     TopTools_MapOfShape aFaces1,aFaces2;
1880     for (anExp.Init(aShBase1, TopAbs_FACE); anExp.More(); anExp.Next()) {
1881       aFaces1.Add(anExp.Current());
1882     }
1883     for (anExp.Init(aShBase2, TopAbs_FACE); anExp.More(); anExp.Next()) {
1884       aFaces2.Add(anExp.Current());
1885     }
1886
1887     // creating map of edge faces
1888     TopTools_IndexedDataMapOfShapeListOfShape aMapEdgeFaces1;
1889     TopExp::MapShapesAndAncestors(aShBase1, TopAbs_EDGE, TopAbs_FACE, aMapEdgeFaces1);
1890     TopTools_IndexedDataMapOfShapeListOfShape aMapEdgeFaces2;
1891     TopExp::MapShapesAndAncestors(aShBase2, TopAbs_EDGE, TopAbs_FACE, aMapEdgeFaces2);
1892
1893     // constuct map face->face (and sub-shapes)
1894     TopTools_IndexedDataMapOfShapeShape FF;
1895     //TopoDS_Shape FS1 = SecFs.Value(i), FS2 = SecFs.Value(i+1);
1896     TopoDS_Shape FS1, FS2;
1897     TopoDS_Vertex V1 = TopoDS::Vertex(SecVs(i));
1898     TopoDS_Vertex V2 = TopoDS::Vertex(SecVs(i+1));
1899     FindFirstPairFaces(aShBase1, aShBase2, V1, V2, FS1, FS2);
1900
1901     FF.Add(FS1,FS2);
1902     MESSAGE ("  first pair of corresponding faces is found");
1903
1904     // add pairs of edges and vertexes to FF
1905     bool stat =  FillCorrespondingEdges(FS1, FS2, V1, V2, FF);
1906     if (!stat) {
1907       if (aCI) delete aCI;
1908       Standard_ConstructionError::Raise("Can not create correct pipe");
1909     }
1910     MESSAGE ("  correspondences for sub-shapes of first pair of faces is found");
1911
1912     FindNextPairOfFaces(FS1, aMapEdgeFaces1, aMapEdgeFaces2, FF, aCI);
1913     MESSAGE ("  other correspondences is found, make pipe for all pairs of faces");
1914
1915     // make pipe for each pair of faces
1916     // auxilary map vertex->edge for created pipe edges
1917     TopTools_IndexedDataMapOfShapeShape VPE;
1918     ShapeAnalysis_Edge sae;
1919     //cout<<"FF.Extent()="<<FF.Extent()<<endl;
1920     int nbff = 0;
1921     for (j=1; j<=FF.Extent(); j++) {
1922       TopoDS_Shape F1 = FF.FindKey(j);
1923       if (F1.ShapeType() != TopAbs_FACE)
1924         continue;
1925       TopoDS_Shape F2 = FF.FindFromIndex(j);
1926       nbff++;
1927
1928       //if (nbff!=3) continue;
1929
1930       MESSAGE ("    make pipe for "<<nbff<<" face");
1931
1932       Handle(Geom_Surface) S1 = BRep_Tool::Surface(TopoDS::Face(F1));
1933       if (S1->IsKind(STANDARD_TYPE(Geom_RectangularTrimmedSurface))) {
1934         Handle(Geom_RectangularTrimmedSurface) RTS =
1935           Handle(Geom_RectangularTrimmedSurface)::DownCast(S1);
1936         S1 = RTS->BasisSurface();
1937       }
1938       Handle(Geom_Plane) Pln1 = Handle(Geom_Plane)::DownCast(S1);
1939       if (Pln1.IsNull()) {
1940         if (aCI) delete aCI;
1941         Standard_ConstructionError::Raise("Surface from face is not plane");
1942       }
1943       gp_Vec aDir1(Pln1->Axis().Direction());
1944
1945       Handle(Geom_Surface) S2 = BRep_Tool::Surface(TopoDS::Face(F2));
1946       if (S2->IsKind(STANDARD_TYPE(Geom_RectangularTrimmedSurface))) {
1947         Handle(Geom_RectangularTrimmedSurface) RTS =
1948           Handle(Geom_RectangularTrimmedSurface)::DownCast(S2);
1949         S2 = RTS->BasisSurface();
1950       }
1951       Handle(Geom_Plane) Pln2 =
1952           Handle(Geom_Plane)::DownCast(S2);
1953       if (Pln2.IsNull()) {
1954         if (aCI) delete aCI;
1955         Standard_ConstructionError::Raise("Surface from face is not plane");
1956       }
1957       gp_Vec aDir2(Pln2->Axis().Direction());
1958
1959       gp_Pnt P1 = BRep_Tool::Pnt(TopoDS::Vertex(SecVs(i)));
1960       gp_Pnt P2 = BRep_Tool::Pnt(TopoDS::Vertex(SecVs(i+1)));
1961       gp_Vec aDir(P1,P2);
1962       if (fabs(aDir.Angle(aDir1)) > M_PI/2.)
1963         aDir1.Reverse();
1964       if (fabs(aDir.Angle(aDir2)) > M_PI/2.)
1965         aDir2.Reverse();
1966
1967       TopExp_Explorer anExpE(F1,TopAbs_EDGE);
1968       TopTools_SequenceOfShape aNewFs;
1969       //int nbee=0;
1970       for (; anExpE.More(); anExpE.Next()) {
1971         TopoDS_Edge E1 = TopoDS::Edge(anExpE.Current());
1972         //nbee++;
1973         if (!FF.Contains(E1))
1974           MESSAGE ("map FF not contains key E1");
1975
1976         if (VPE.Contains(E1)) {
1977           aNewFs.Append(VPE.FindFromKey(E1));
1978 #ifdef _DEBUG_
1979           MESSAGE ("    using existed face");
1980 #endif
1981           continue;
1982         }
1983
1984         TopoDS_Edge E3 = TopoDS::Edge(FF.FindFromKey(E1));
1985         TopoDS_Vertex V1 = sae.FirstVertex(E1);
1986         TopoDS_Vertex V2 = sae.LastVertex(E1);
1987         if (!FF.Contains(V1))
1988           MESSAGE ("map FF not contains key V1");
1989         if (!FF.Contains(V2))
1990           MESSAGE ("map FF not contains key V2");
1991         TopoDS_Vertex V3 = TopoDS::Vertex(FF.FindFromKey(V2));
1992         TopoDS_Vertex V4 = TopoDS::Vertex(FF.FindFromKey(V1));
1993         TopoDS_Vertex Vtmp = sae.FirstVertex(E3);
1994         if (Vtmp.IsSame(V4))
1995           E3.Reverse();
1996         gp_Pnt P1 = BRep_Tool::Pnt(V1);
1997         gp_Pnt P2 = BRep_Tool::Pnt(V2);
1998         gp_Pnt P3 = BRep_Tool::Pnt(V3);
1999         gp_Pnt P4 = BRep_Tool::Pnt(V4);
2000         // make E2
2001         TopoDS_Edge E2;
2002         Handle(Geom_BSplineCurve) C2;
2003         if (VPE.Contains(V2)) {
2004           E2 = TopoDS::Edge(VPE.FindFromKey(V2));
2005           double fp,lp;
2006           C2 = Handle(Geom_BSplineCurve)::DownCast(BRep_Tool::Curve(E2,fp,lp));
2007         }
2008         else {
2009           Handle(TColgp_HArray1OfPnt) HAP = new TColgp_HArray1OfPnt(1,2);
2010           HAP->SetValue(1,P2);
2011           HAP->SetValue(2,P3);
2012           GeomAPI_Interpolate anInt(HAP,Standard_False,1.e-7);
2013           anInt.Load(aDir1,aDir2);
2014           anInt.Perform();
2015           C2 = anInt.Curve();
2016           B.MakeEdge(E2,C2,1.e-7);
2017           B.Add(E2,TopoDS::Vertex(V2.Oriented(TopAbs_FORWARD)));
2018           B.Add(E2,TopoDS::Vertex(V3.Oriented(TopAbs_REVERSED)));
2019           VPE.Add(V2,E2);
2020         }
2021         // make E4
2022         TopoDS_Edge E4;
2023         Handle(Geom_BSplineCurve) C4;
2024         if (VPE.Contains(V1)) {
2025           E4 = TopoDS::Edge(VPE.FindFromKey(V1));
2026           double fp,lp;
2027           C4 = Handle(Geom_BSplineCurve)::DownCast(BRep_Tool::Curve(E4,fp,lp));
2028         }
2029         else {
2030           Handle(TColgp_HArray1OfPnt) HAP = new TColgp_HArray1OfPnt(1,2);
2031           HAP->SetValue(1,P1);
2032           HAP->SetValue(2,P4);
2033           GeomAPI_Interpolate anInt(HAP,Standard_False,1.e-7);
2034           anInt.Load(aDir1,aDir2);
2035           anInt.Perform();
2036           C4 = anInt.Curve();
2037           B.MakeEdge(E4,anInt.Curve(),1.e-7);
2038           B.Add(E4,TopoDS::Vertex(V1.Oriented(TopAbs_FORWARD)));
2039           B.Add(E4,TopoDS::Vertex(V4.Oriented(TopAbs_REVERSED)));
2040           VPE.Add(V1,E4);
2041         }
2042
2043         TopoDS_Wire W;
2044         B.MakeWire(W);
2045         B.Add(W,E1);
2046         B.Add(W,E2);
2047         B.Add(W,E3);
2048         B.Add(W,E4.Reversed());
2049         //cout<<"      wire for edge "<<nbee<<" is created"<<endl;
2050         //BRepTools::Write(W,"/dn02/users_Linux/skl/work/Bugs/14857/w.brep");
2051
2052         // make surface
2053
2054         double fp,lp;
2055         Handle(Geom_Curve) C1 = BRep_Tool::Curve(E1,fp,lp);
2056         //bool IsConicC1 = false;
2057         //if (C1->IsKind(STANDARD_TYPE(Geom_Conic))) {
2058         //  IsConicC1 = true;
2059         //  cout<<"C1 - Geom_Conic"<<endl;
2060         //}
2061         if (C1->IsKind(STANDARD_TYPE(Geom_Line)) || C1->IsKind(STANDARD_TYPE(Geom_Conic))) {
2062           C1 = new Geom_TrimmedCurve(C1,fp,lp);
2063         }
2064         //if (IsConicC1) {
2065         //  double tol = BRep_Tool::Tolerance(E1);
2066         //  GeomConvert_ApproxCurve ApxC1(C1,tol,GeomAbs_C1,10,5);
2067         //  C1 = ApxC1.Curve();
2068         //}
2069         Handle(Geom_Curve) C3 = BRep_Tool::Curve(E3,fp,lp);
2070         if (C3->IsKind(STANDARD_TYPE(Geom_Line)) || C3->IsKind(STANDARD_TYPE(Geom_Conic))) {
2071           C3 = new Geom_TrimmedCurve(C3,fp,lp);
2072         }
2073         //filebuf fic;
2074         //ostream os(&fic);
2075         //os.precision(15);
2076         Handle(Geom_BSplineCurve) CE1 =
2077           GeomConvert::CurveToBSplineCurve(C1,Convert_RationalC1);
2078         if (CE1->Degree()<3)
2079           CE1->IncreaseDegree(3);
2080         Handle(Geom_BSplineCurve) CE2 =
2081           GeomConvert::CurveToBSplineCurve(C2,Convert_RationalC1);
2082         if (CE2->Degree()<3)
2083           CE2->IncreaseDegree(3);
2084         Handle(Geom_BSplineCurve) CE3 =
2085           GeomConvert::CurveToBSplineCurve(C3,Convert_RationalC1);
2086         if (CE3->Degree()<3)
2087           CE3->IncreaseDegree(3);
2088         Handle(Geom_BSplineCurve) CE4 =
2089           GeomConvert::CurveToBSplineCurve(C4,Convert_RationalC1);
2090         if (CE4->Degree()<3)
2091           CE4->IncreaseDegree(3);
2092         //cout<<"CE1->Degree()="<<CE1->Degree()<<" CE2->Degree()="<<CE2->Degree()
2093         //    <<" CE3->Degree()="<<CE3->Degree()<<" CE4->Degree()="<<CE4->Degree()<<endl;
2094         //if (fic.open("/dn02/users_Linux/skl/work/Bugs/14857/ce1.brep",ios::out)) {
2095         //  os<<"DrawTrSurf_BSplineCurve"<<endl;
2096         //  GeomTools::Write(CE1,os);
2097         //  fic.close();
2098         //}
2099
2100         Handle(Geom_Surface) BS;
2101         try {
2102           GeomFill_BSplineCurves GF(CE1,CE2,CE3,CE4,GeomFill_CoonsStyle);
2103           //GeomFill_BSplineCurves GF(CE1,CE2,CE3,CE4,GeomFill_StretchStyle);
2104           BS = GF.Surface();
2105         }
2106         catch(...) {
2107           MESSAGE ("      can not create BSplineSurface - create Bezier");
2108           int NbP=26;
2109           TColgp_Array2OfPnt Points(1,NbP,1,NbP);
2110           double fp1,lp1,fp2,lp2;
2111           Handle(Geom_Curve) C1 = BRep_Tool::Curve(E1,fp1,lp1);
2112           Handle(Geom_Curve) C3 = BRep_Tool::Curve(E3,fp2,lp2);
2113           gp_Pnt P1C1,P2C1;
2114           C1->D0(fp1,P1C1);
2115           C1->D0(lp1,P2C1);
2116           gp_Pnt P1C3,P2C3;
2117           C3->D0(fp2,P1C3);
2118           C3->D0(lp2,P2C3);
2119           int n1,n2;
2120           double fp,lp;
2121           // get points from C1
2122           if (P1.Distance(P1C1)<1.e-6) {
2123             fp = fp1;
2124             lp = lp1;
2125           }
2126           else {
2127             fp = lp1;
2128             lp = fp1;
2129           }
2130           double step = (lp-fp)/(NbP-1);
2131           Points.SetValue(1,1,P1);
2132           double par = fp;
2133           for (n1=2; n1<NbP; n1++) {
2134             gp_Pnt P;
2135             par += step;
2136             C1->D0(par,P);
2137             Points.SetValue(1,n1,P);
2138           }
2139           Points.SetValue(1,NbP,P2);
2140           // get points from C3
2141           if (P4.Distance(P1C3)<1.e-6) {
2142             fp = fp2;
2143             lp = lp2;
2144           }
2145           else {
2146             fp = lp2;
2147             lp = fp2;
2148           }
2149           step = (lp-fp)/(NbP-1);
2150           Points.SetValue(NbP,1,P4);
2151           par = fp;
2152           for (n1=2; n1<NbP; n1++) {
2153             gp_Pnt P;
2154             par += step;
2155             C3->D0(par,P);
2156             Points.SetValue(NbP,n1,P);
2157           }
2158           Points.SetValue(NbP,NbP,P3);
2159           // create isolines and get points from them
2160           for (n1=1; n1<=NbP; n1++) {
2161             gp_Pnt PI1 = Points.Value(1,n1);
2162             gp_Pnt PI2 = Points.Value(NbP,n1);
2163             Handle(TColgp_HArray1OfPnt) HAP = new TColgp_HArray1OfPnt(1,2);
2164             HAP->SetValue(1,PI1);
2165             HAP->SetValue(2,PI2);
2166             GeomAPI_Interpolate anInt(HAP,Standard_False,1.e-7);
2167             anInt.Load(aDir1,aDir2);
2168             anInt.Perform();
2169             Handle(Geom_Curve) iso = anInt.Curve();
2170             fp = iso->FirstParameter();
2171             lp = iso->LastParameter();
2172             step = (lp-fp)/(NbP-1);
2173             par = fp;
2174             TopoDS_Compound VComp;
2175             B.MakeCompound(VComp);
2176             for (n2=2; n2<NbP; n2++) {
2177               gp_Pnt P;
2178               par += step;
2179               iso->D0(par,P);
2180               Points.SetValue(n2,n1,P);
2181             }
2182           }
2183           // create surface and face
2184           //Handle(Geom_BezierSurface) BS = new Geom_BezierSurface(Points);
2185           BS = new Geom_BezierSurface(Points);
2186         }
2187
2188         BRepBuilderAPI_MakeFace BB(BS,W);
2189         TopoDS_Face NewF = BB.Face();
2190         Handle(ShapeFix_Face) sff = new ShapeFix_Face(NewF);
2191         sff->Perform();
2192         sff->FixOrientation();
2193         TopoDS_Face FixedFace = sff->Face();
2194         aNewFs.Append(FixedFace);
2195         VPE.Add(E1,FixedFace);
2196         //cout<<"      face for edge "<<nbee<<" is created"<<endl;
2197         //BRepTools::Write(FixedFace,"/dn02/users_Linux/skl/work/Bugs/14857/f.brep");
2198       }
2199       // make shell
2200       TopoDS_Shell aShell;
2201       B.MakeShell(aShell);
2202       for (int nf=1; nf<=aNewFs.Length(); nf++) {
2203         B.Add(aShell,aNewFs(nf));
2204       }
2205       B.Add(aShell,F1);
2206       B.Add(aShell,F2);
2207
2208       // make sewing for this shell
2209       Handle(BRepBuilderAPI_Sewing) aSewing = new BRepBuilderAPI_Sewing;
2210       aSewing->SetTolerance(Precision::Confusion());
2211       aSewing->SetFaceMode(Standard_True);
2212       aSewing->SetFloatingEdgesMode(Standard_False);
2213       aSewing->SetNonManifoldMode(Standard_False);
2214       for (anExp.Init(aShell, TopAbs_FACE); anExp.More(); anExp.Next()) {
2215         aSewing->Add(anExp.Current());
2216       }
2217       aSewing->Perform();
2218       MESSAGE ("    shell for face "<<nbff<<" is created");
2219       const TopoDS_Shape aSewShape = aSewing->SewedShape();
2220       //BRepTools::Write(aSewShape,"/dn02/users_Linux/skl/work/Bugs/14857/sew.brep");
2221       if (aSewShape.ShapeType() == TopAbs_SHELL) {
2222         aShell = TopoDS::Shell(aSewShape);
2223         GProp_GProps aSystem;
2224         BRepGProp::VolumeProperties(aShell, aSystem);
2225         if (aSystem.Mass()<0) {
2226           //cout<<"aSewShape is reversed"<<endl;
2227           aShell.Reverse();
2228         }
2229         if (BRep_Tool::IsClosed(aShell)) {
2230           TopoDS_Solid aSolid;
2231           B.MakeSolid(aSolid);
2232           B.Add(aSolid,aShell);
2233           B.Add(aComp,aSolid);
2234           MESSAGE ("    solid for face "<<nbff<<" is created");
2235         }
2236         else {
2237           B.Add(aComp,aShell);
2238           MESSAGE ("    solid for face "<<nbff<<" is not created");
2239         }
2240       }
2241       else {
2242         B.Add(aComp,aShell);
2243         MESSAGE ("    solid for face "<<nbff<<" is not created");
2244       }
2245       //cout<<"    solid for face "<<nbff<<" is created"<<endl;
2246
2247       //Handle(ShapeFix_Shell) sfs = new ShapeFix_Shell(aShell);
2248       //sfs->Perform();
2249       //TopoDS_Shell FixedShell = sfs->Shell();
2250       /*
2251       GProp_GProps aSystem;
2252       BRepGProp::VolumeProperties(FixedShell, aSystem);
2253       if (aSystem.Mass()<0) {
2254         //cout<<"aSewShape is reversed"<<endl;
2255         FixedShell.Reverse();
2256       }
2257       if (BRep_Tool::IsClosed(FixedShell)) {
2258         TopoDS_Solid aSolid;
2259         B.MakeSolid(aSolid);
2260         B.Add(aSolid,aShell);
2261         B.Add(aComp,aSolid);
2262       }
2263       else {
2264         B.Add(aComp,FixedShell);
2265       }
2266       */
2267     }
2268   }
2269
2270   //BRepTools::Write(aComp,"/dn02/users_Linux/skl/work/Bugs/14857/comp.brep");
2271   return aComp;
2272 }
2273
2274 //=======================================================================
2275 //function : CreatePipeBiNormalAlongVector
2276 //purpose  : auxilary for Execute()
2277 //=======================================================================
2278 static TopoDS_Shape CreatePipeBiNormalAlongVector(const TopoDS_Wire& aWirePath,
2279                                                   GEOMImpl_IPipe* aCI)
2280 {
2281   GEOMImpl_IPipeBiNormal* aCIBN = (GEOMImpl_IPipeBiNormal*)aCI;
2282
2283   Handle(GEOM_Function) aRefBase = aCIBN->GetBase();
2284   Handle(GEOM_Function) aRefVec = aCIBN->GetVector();
2285   TopoDS_Shape aShapeBase = aRefBase->GetValue();
2286   TopoDS_Shape aShapeVec = aRefVec->GetValue();
2287
2288   if (aShapeBase.IsNull()) {
2289     if (aCIBN) delete aCIBN;
2290     Standard_NullObject::Raise("MakePipe aborted : null base argument");
2291   }
2292
2293   // Make copy to prevent modifying of base object: 0021525
2294   BRepBuilderAPI_Copy Copy (aShapeBase);
2295   if (Copy.IsDone())
2296     aShapeBase = Copy.Shape();
2297
2298   TopoDS_Shape aProf;
2299   if (aShapeBase.ShapeType() == TopAbs_VERTEX) {
2300     aProf = aShapeBase;
2301   }
2302   else if (aShapeBase.ShapeType() == TopAbs_EDGE) {
2303     aProf = BRepBuilderAPI_MakeWire(TopoDS::Edge(aShapeBase)).Shape();
2304   }
2305   else if (aShapeBase.ShapeType() == TopAbs_WIRE) {
2306     aProf = aShapeBase;
2307   }
2308   else if (aShapeBase.ShapeType() == TopAbs_FACE) {
2309     TopExp_Explorer wexp (aShapeBase,TopAbs_WIRE);
2310     aProf = wexp.Current();
2311   }
2312   else {
2313     Standard_TypeMismatch::Raise
2314       ("MakePipe aborted : invalid type of base");
2315   }
2316   BRepOffsetAPI_MakePipeShell PipeBuilder (aWirePath);
2317   PipeBuilder.Add(aProf);
2318
2319   if (aShapeVec.IsNull()) {
2320     if (aCIBN) delete aCIBN;
2321     Standard_NullObject::Raise
2322       ("MakePipe aborted : null vector argument");
2323   }
2324   if (aShapeVec.ShapeType() != TopAbs_EDGE)
2325     Standard_TypeMismatch::Raise
2326       ("MakePipe aborted: invalid type of vector");
2327   TopoDS_Edge anEdge = TopoDS::Edge(aShapeVec);
2328   TopoDS_Vertex V1, V2;
2329   TopExp::Vertices(anEdge, V1, V2, Standard_True);
2330   if (V1.IsNull() || V2.IsNull())
2331     Standard_NullObject::Raise
2332       ("MakePipe aborted: vector is not defined");
2333   gp_Vec aVec(BRep_Tool::Pnt(V1), BRep_Tool::Pnt(V2));
2334   gp_Dir BiNormal(aVec);
2335   PipeBuilder.SetMode(BiNormal);
2336   PipeBuilder.Build();
2337   if (aShapeBase.ShapeType() == TopAbs_FACE) {
2338       PipeBuilder.MakeSolid();
2339   }
2340
2341   return PipeBuilder.Shape();
2342 }
2343
2344 //=======================================================================
2345 //function : Execute
2346 //purpose  :
2347 //=======================================================================
2348 Standard_Integer GEOMImpl_PipeDriver::Execute (TFunction_Logbook& log) const
2349 {
2350   if (Label().IsNull()) return 0;
2351   Handle(GEOM_Function) aFunction = GEOM_Function::GetFunction(Label());
2352   Standard_Integer aType = aFunction->GetType();
2353
2354   GEOMImpl_IPipe* aCI = 0;
2355   if (aType == PIPE_BASE_PATH)
2356     aCI = new GEOMImpl_IPipe (aFunction);
2357   else if (aType == PIPE_DIFFERENT_SECTIONS)
2358     aCI = new GEOMImpl_IPipeDiffSect (aFunction);
2359   else if (aType == PIPE_SHELL_SECTIONS)
2360     aCI = new GEOMImpl_IPipeShellSect (aFunction);
2361   else if (aType == PIPE_SHELLS_WITHOUT_PATH)
2362     aCI = new GEOMImpl_IPipeShellSect (aFunction);
2363   else if (aType == PIPE_BI_NORMAL_ALONG_VECTOR)
2364     aCI = new GEOMImpl_IPipeBiNormal (aFunction);
2365   else
2366     return 0;
2367
2368   TopoDS_Wire aWirePath;
2369   if (aType != PIPE_SHELLS_WITHOUT_PATH) {
2370     // working with path
2371     Handle(GEOM_Function) aRefPath = aCI->GetPath();
2372     TopoDS_Shape aShapePath = aRefPath->GetValue();
2373
2374     if (aShapePath.IsNull()) {
2375       MESSAGE ("Driver : path is null");
2376       if (aCI) delete aCI;
2377       Standard_NullObject::Raise("MakePipe aborted : null path argument");
2378     }
2379
2380     // Get path contour
2381     bool isOk = false;
2382     if (aShapePath.ShapeType() == TopAbs_COMPOUND) {
2383       TopTools_SequenceOfShape anEdges;
2384       TopExp_Explorer anExp;
2385       BRep_Builder B;
2386       TopoDS_Wire W;
2387       B.MakeWire(W);
2388       for (anExp.Init(aShapePath, TopAbs_EDGE); anExp.More(); anExp.Next()) {
2389         B.Add(W, anExp.Current());
2390         isOk = true;
2391       }
2392       if (isOk)
2393         aWirePath = W;
2394     }
2395     else if (aShapePath.ShapeType() == TopAbs_WIRE) {
2396       aWirePath = TopoDS::Wire(aShapePath);
2397       isOk = true;
2398     }
2399     else {
2400       if (aShapePath.ShapeType() == TopAbs_EDGE) {
2401         TopoDS_Edge anEdge = TopoDS::Edge(aShapePath);
2402         aWirePath = BRepBuilderAPI_MakeWire(anEdge);
2403         isOk = true;
2404       }
2405     }
2406     if (!isOk) {
2407       if (aCI) delete aCI;
2408       Standard_TypeMismatch::Raise("MakePipe aborted : path shape is neither a wire nor an edge");
2409     }
2410   }
2411
2412   TopoDS_Shape aShape;
2413
2414   if (aType == PIPE_BASE_PATH) {
2415     Handle(GEOM_Function) aRefBase = aCI->GetBase();
2416     TopoDS_Shape aShapeBase;
2417
2418     // Make copy to prevent modifying of base object 0020766 : EDF 1320
2419     BRepBuilderAPI_Copy Copy(aRefBase->GetValue());
2420     if (Copy.IsDone())
2421       aShapeBase = Copy.Shape();
2422
2423     if (aShapeBase.IsNull()) {
2424       if (aCI) delete aCI;
2425       Standard_NullObject::Raise("MakePipe aborted : null base argument");
2426     }
2427
2428     // Make pipe
2429     if (aShapeBase.ShapeType() == TopAbs_EDGE ||
2430         aShapeBase.ShapeType() == TopAbs_WIRE)
2431     {
2432       TopoDS_Wire Profile;
2433       if (aShapeBase.ShapeType() == TopAbs_WIRE)
2434         Profile = TopoDS::Wire(aShapeBase);
2435       else
2436       {
2437         BRep_Builder BB;
2438         BB.MakeWire(Profile);
2439         BB.Add(Profile, aShapeBase);
2440       }
2441
2442       BRepOffsetAPI_MakePipeShell Sweep (aWirePath);
2443       BRepBuilderAPI_MakeFace FaceBuilder (aWirePath, Standard_True); //to find the plane of spine
2444       if (FaceBuilder.IsDone())
2445         Sweep.SetMode(FaceBuilder.Face());
2446       Sweep.Add(Profile);
2447       Sweep.Build();
2448       
2449       if (!Sweep.IsDone())
2450       {
2451         if (aCI) delete aCI;
2452         Standard_ConstructionError::Raise("MakePipeShell failed");
2453       }
2454       else
2455         aShape = Sweep.Shape(); //result is good
2456       
2457     }
2458     else
2459     {
2460       GeomFill_Trihedron theBestMode = EvaluateBestSweepMode(aWirePath);
2461       aShape = BRepOffsetAPI_MakePipe(aWirePath, aShapeBase, theBestMode);
2462     }
2463   }
2464
2465   //building pipe with different sections
2466   else if (aType == PIPE_DIFFERENT_SECTIONS) {
2467     GEOMImpl_IPipeDiffSect* aCIDS = (GEOMImpl_IPipeDiffSect*)aCI;
2468     Handle(TColStd_HSequenceOfTransient) aBasesObjs = aCIDS->GetBases ();
2469     Handle(TColStd_HSequenceOfTransient) aLocObjs = aCIDS->GetLocations ();
2470     Standard_Boolean aWithContact = (aCIDS->GetWithContactMode());
2471     Standard_Boolean aWithCorrect = (aCIDS->GetWithCorrectionMode());
2472     if (aCI) {
2473       delete aCI;
2474       aCI = 0;
2475     }
2476
2477     Standard_Integer nbBases = aBasesObjs->Length();
2478     Standard_Integer nbLocs  = (aLocObjs.IsNull() ? 0 : aLocObjs->Length());
2479
2480     Handle(TopTools_HSequenceOfShape) aHSeqBases = new TopTools_HSequenceOfShape;
2481     Handle(TopTools_HSequenceOfShape) aHSeqLocs  = new TopTools_HSequenceOfShape;
2482     Standard_Integer i;
2483
2484     for (i = 1; i <= nbBases; i++) {
2485       Handle(Standard_Transient) anItem = aBasesObjs->Value(i);
2486       if (anItem.IsNull())
2487         continue;
2488       Handle(GEOM_Function) aRefBase = Handle(GEOM_Function)::DownCast(anItem);
2489       if (aRefBase.IsNull())
2490         continue;
2491       if (aRefBase->GetValue().IsNull())
2492         continue;
2493
2494       aHSeqBases->Append(aRefBase->GetValue());
2495     }
2496     for (i = 1; i <= nbLocs; i++) {
2497       Handle(Standard_Transient) anItemLoc = aLocObjs->Value(i);
2498       if (anItemLoc.IsNull())
2499         continue;
2500       Handle(GEOM_Function) aRefLoc = Handle(GEOM_Function)::DownCast(anItemLoc);
2501       TopoDS_Shape aShapeLoc = aRefLoc->GetValue();
2502       if (aShapeLoc.IsNull() || aShapeLoc.ShapeType() != TopAbs_VERTEX)
2503         continue;
2504
2505       aHSeqLocs->Append(aShapeLoc);
2506     }
2507
2508     aShape = CreatePipeWithDifferentSections(aWirePath, aHSeqBases, aHSeqLocs, aWithContact, aWithCorrect);
2509   }
2510
2511   //building pipe with shell sections
2512   else if (aType == PIPE_SHELL_SECTIONS) {
2513     aShape = CreatePipeForShellSections(aWirePath,aCI);
2514   }
2515
2516   //building pipe shell sections without path
2517   else if (aType == PIPE_SHELLS_WITHOUT_PATH) {
2518     aShape = CreatePipeShellsWithoutPath(aCI);
2519   }
2520
2521   //building a pipe with constant bi-normal along given vector
2522   else if (aType == PIPE_BI_NORMAL_ALONG_VECTOR) {
2523     aShape = CreatePipeBiNormalAlongVector(aWirePath, aCI);
2524   }
2525
2526   if (aCI) {
2527     delete aCI;
2528     aCI = 0;
2529   }
2530
2531   if (aShape.IsNull()) return 0;
2532
2533   BRepCheck_Analyzer ana (aShape, Standard_False);
2534   if (!ana.IsValid()) {
2535     ShapeFix_ShapeTolerance aSFT;
2536     aSFT.LimitTolerance(aShape,Precision::Confusion(),Precision::Confusion());
2537     Handle(ShapeFix_Shape) aSfs = new ShapeFix_Shape(aShape);
2538     aSfs->SetPrecision(Precision::Confusion());
2539     aSfs->Perform();
2540     aShape = aSfs->Shape();
2541
2542     ana.Init(aShape, Standard_False);
2543     if (!ana.IsValid())
2544       Standard_ConstructionError::Raise("Algorithm have produced an invalid shape result");
2545   }
2546
2547   if (aType != PIPE_BASE_PATH &&
2548       aType != PIPE_SHELLS_WITHOUT_PATH) {
2549     TopExp_Explorer anExpV (aShape, TopAbs_VERTEX);
2550     if (anExpV.More()) {
2551       Standard_Real aVertMaxTol = -RealLast();
2552       for (; anExpV.More(); anExpV.Next()) {
2553         TopoDS_Vertex aVertex = TopoDS::Vertex(anExpV.Current());
2554         Standard_Real aTol = BRep_Tool::Tolerance(aVertex);
2555         if (aTol > aVertMaxTol)
2556           aVertMaxTol = aTol;
2557       }
2558       aVertMaxTol += Precision::Confusion();
2559       aShape = GEOMImpl_GlueDriver::GlueFaces(aShape, aVertMaxTol, Standard_True);
2560       //aShape = GEOMImpl_GlueDriver::GlueFaces(aShape, Precision::Confusion(), Standard_True);
2561     }
2562   }
2563
2564   TopoDS_Shape aRes = GEOMUtils::CompsolidToCompound(aShape);
2565   aFunction->SetValue(aRes);
2566
2567   log.SetTouched(Label());
2568   return 1;
2569 }
2570
2571 //================================================================================
2572 /*!
2573  * \brief Returns a name of creation operation and names and values of creation parameters
2574  */
2575 //================================================================================
2576
2577 bool GEOMImpl_PipeDriver::
2578 GetCreationInformation(std::string&             theOperationName,
2579                        std::vector<GEOM_Param>& theParams)
2580 {
2581   if (Label().IsNull()) return 0;
2582   Handle(GEOM_Function) function = GEOM_Function::GetFunction(Label());
2583   Standard_Integer aType = function->GetType();
2584
2585   switch ( aType ) {
2586   case PIPE_BASE_PATH:
2587   {
2588     theOperationName = "PIPE";
2589     GEOMImpl_IPipe aCI( function );
2590     AddParam( theParams, "Base Object", aCI.GetBase() );
2591     AddParam( theParams, "Path Object", aCI.GetPath() );
2592     break;
2593   }
2594   case PIPE_BI_NORMAL_ALONG_VECTOR:
2595   {
2596     theOperationName = "PIPE";
2597     GEOMImpl_IPipeBiNormal aCI( function );
2598     AddParam( theParams, "Base Object", aCI.GetBase() );
2599     AddParam( theParams, "Path Object", aCI.GetPath() );
2600     AddParam( theParams, "BiNormal", aCI.GetVector() );
2601     break;
2602   }
2603   case PIPE_DIFFERENT_SECTIONS:
2604   {
2605     theOperationName = "PIPE";
2606     GEOMImpl_IPipeDiffSect aCI( function );
2607     AddParam( theParams, "Bases", aCI.GetBases() );
2608     AddParam( theParams, "Locations", aCI.GetLocations() );
2609     AddParam( theParams, "Path", aCI.GetPath() );
2610     AddParam( theParams, "With contact", aCI.GetWithContactMode() );
2611     AddParam( theParams, "With correction", aCI.GetWithCorrectionMode() );
2612     break;
2613   }
2614   case PIPE_SHELL_SECTIONS:
2615   {
2616     theOperationName = "PIPE";
2617     GEOMImpl_IPipeShellSect aCI( function );
2618     AddParam( theParams, "Bases", aCI.GetBases() );
2619     AddParam( theParams, "Sub-Bases", aCI.GetSubBases() );
2620     AddParam( theParams, "Locations", aCI.GetLocations() );
2621     AddParam( theParams, "Path", aCI.GetPath() );
2622     AddParam( theParams, "With contact", aCI.GetWithContactMode() );
2623     AddParam( theParams, "With correction", aCI.GetWithCorrectionMode() );
2624     break;
2625   }
2626   case PIPE_SHELLS_WITHOUT_PATH:
2627   {
2628     theOperationName = "PIPE"; // MakePipeShellsWithoutPath
2629     GEOMImpl_IPipeShellSect aCI( function );
2630     AddParam( theParams, "Bases", aCI.GetBases() );
2631     AddParam( theParams, "Locations", aCI.GetLocations() );
2632     break;
2633   }
2634   default:
2635     return false;
2636   }
2637   
2638   return true;
2639 }
2640
2641 IMPLEMENT_STANDARD_HANDLE (GEOMImpl_PipeDriver,GEOM_BaseDriver);
2642 IMPLEMENT_STANDARD_RTTIEXT (GEOMImpl_PipeDriver,GEOM_BaseDriver);