Salome HOME
Merge from BR_new_bop4 (porting to new OCCT BOP) 13/09/2013
[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   Handle(Geom_Curve) C = BRep_Tool::Curve(TopoDS::Edge(Edges.Value(1)),fp,lp);
862   gp_Pnt P1,P2;
863   gp_Vec Vec1,Vec2;
864   C->D1(fp,P1,Vec1);
865   C->D1(lp,P2,Vec2);
866   double SumAng = fabs(Vec1.Angle(Vec2));
867   Vec1 = Vec2;
868   P1 = P2;
869   TColStd_SequenceOfInteger SplitEdgeNums,SplitLocNums;
870   int LastLoc = 1;
871   //cout<<"Edges.Length()="<<Edges.Length()<<endl;
872   for (i=2; i<=Edges.Length(); i++) {
873       TopoDS_Edge edge = TopoDS::Edge(Edges.Value(i));
874       double tol = BRep_Tool::Tolerance(edge);
875       Handle(Geom_Curve) C = BRep_Tool::Curve(edge,fp,lp);
876       C->D1(lp,P2,Vec2);
877       double ang = fabs(Vec1.Angle(Vec2));
878       SumAng += ang;
879       if (SumAng>4*M_PI) {
880         SumAng = ang;
881         SplitEdgeNums.Append(i-1);
882         int j;
883         for (j=LastLoc+1; j<=aSeqLocs.Length(); j++) {
884           TopoDS_Vertex aVert = TopoDS::Vertex(aSeqLocs.Value(j));
885           gp_Pnt P = BRep_Tool::Pnt(aVert);
886           if (P1.Distance(P) < tol) {
887             SplitLocNums.Append(j);
888             LastLoc = j;
889             break;
890           }
891         }
892       }
893       Vec1 = Vec2;
894       P1 = P2;
895   }
896
897   if (SplitLocNums.Length()==SplitEdgeNums.Length() && SplitEdgeNums.Length()>0) {
898       TopTools_SequenceOfShape aSeqRes;
899       int nn, num1 = 1, num2 = 1;
900       for (nn=1; nn<=SplitEdgeNums.Length(); nn++) {
901         // create wirepath and sequences of shapes
902         BRep_Builder B;
903         TopoDS_Wire tmpW;
904         B.MakeWire(tmpW);
905         for (i=num1; i<=SplitEdgeNums.Value(nn); i++) {
906           B.Add(tmpW,TopoDS::Edge(Edges.Value(i)));
907         }
908         num1 = SplitEdgeNums.Value(nn) + 1;
909         TopTools_SequenceOfShape aTmpSeqBases;
910         TopTools_SequenceOfShape aTmpSeqLocs;
911         for (i=num2; i<=SplitLocNums.Value(nn); i++) {
912           aTmpSeqBases.Append(aSeqBases.Value(i));
913           aTmpSeqLocs.Append(aSeqLocs.Value(i));
914         }
915         num2 = SplitLocNums.Value(nn);
916         // make pipe
917         BRepOffsetAPI_MakePipeShell aBuilder(tmpW);
918         GeomFill_Trihedron theBestMode = EvaluateBestSweepMode(tmpW);
919         if (theBestMode == GeomFill_IsDiscreteTrihedron)
920           aBuilder.SetDiscreteMode();
921         Standard_Integer nbShapes = aTmpSeqBases.Length();
922         for (i=1; i<=nbShapes; i++) {
923           TopoDS_Shape aShapeLoc = aTmpSeqLocs.Value(i);
924           TopoDS_Vertex aVert = TopoDS::Vertex(aShapeLoc);
925           aBuilder.Add(aTmpSeqBases.Value(i), aVert, theWithContact, theWithCorrect);
926         }
927         if (!aBuilder.IsReady()) {
928           Standard_ConstructionError::Raise("Invalid input data for building PIPE: bases are invalid");
929         }
930         aBuilder.Build();
931         TopoDS_Shape resShape = aBuilder.Shape();
932         aSeqRes.Append(resShape);
933       }
934       // create wirepath and sequences of shapes for last part
935       BRep_Builder B;
936       TopoDS_Wire tmpW;
937       B.MakeWire(tmpW);
938       for (i=num1; i<=Edges.Length(); i++) {
939         B.Add(tmpW,TopoDS::Edge(Edges.Value(i)));
940       }
941       TopTools_SequenceOfShape aTmpSeqBases;
942       TopTools_SequenceOfShape aTmpSeqLocs;
943       for (i=num2; i<=aSeqLocs.Length(); i++) {
944         aTmpSeqBases.Append(aSeqBases.Value(i));
945         aTmpSeqLocs.Append(aSeqLocs.Value(i));
946       }
947       // make pipe for last part
948       BRepOffsetAPI_MakePipeShell aBuilder(tmpW);
949       GeomFill_Trihedron theBestMode = EvaluateBestSweepMode(tmpW);
950       if (theBestMode == GeomFill_IsDiscreteTrihedron)
951         aBuilder.SetDiscreteMode();
952       Standard_Integer nbShapes = aTmpSeqBases.Length();
953       for (i=1; i<=nbShapes; i++) {
954         TopoDS_Shape aShapeLoc = aTmpSeqLocs.Value(i);
955         TopoDS_Vertex aVert = TopoDS::Vertex(aShapeLoc);
956         aBuilder.Add(aTmpSeqBases.Value(i), aVert, theWithContact, theWithCorrect);
957       }
958       if (!aBuilder.IsReady()) {
959         Standard_ConstructionError::Raise("Invalid input data for building PIPE: bases are invalid");
960       }
961       aBuilder.Build();
962       TopoDS_Shape resShape = aBuilder.Shape();
963       aSeqRes.Append(resShape);
964       // make sewing for result
965       Handle(BRepBuilderAPI_Sewing) aSewing = new BRepBuilderAPI_Sewing;
966       aSewing->SetTolerance(Precision::Confusion());
967       aSewing->SetFaceMode(Standard_True);
968       aSewing->SetFloatingEdgesMode(Standard_False);
969       aSewing->SetNonManifoldMode(Standard_False);
970       for (i=1; i<=aSeqRes.Length(); i++) {
971         aSewing->Add(aSeqRes.Value(i));
972       }
973       aSewing->Perform();
974       aShape = aSewing->SewedShape();
975   }
976   else {
977       // old implementation without splitting
978       BRepOffsetAPI_MakePipeShell aBuilder(aWirePath);
979       GeomFill_Trihedron theBestMode = EvaluateBestSweepMode(aWirePath);
980       if (theBestMode == GeomFill_IsDiscreteTrihedron)
981         aBuilder.SetDiscreteMode();
982
983       Standard_Integer nbShapes = aSeqBases.Length();
984       Standard_Integer step = nbShapes/nbBases;
985
986       if (nbShapes < nbBases || fmod((double)nbShapes, (double)nbBases)) {
987         Standard_ConstructionError::Raise("Invalid sections were specified for building pipe");
988       }
989       Standard_Integer ind =0;
990       Standard_Real aTolConf = Precision::Confusion();
991       Standard_Real aTolAng  = Precision::Angular();
992
993       for (i = 1; i <= nbShapes && ind < nbShapes; i++) { //i+nbBases <= nbShapes
994         TopTools_SequenceOfShape usedBases;
995         Standard_Integer j = 1;
996         for (; j <= nbBases; j++) {
997           ind = i + (j-1)*step;
998           TopoDS_Shape aWireProf = aSeqBases.Value(ind);
999           usedBases.Append(aWireProf);
1000           if (nbLocs) {
1001             TopoDS_Shape aShapeLoc = aSeqLocs.Value(j);
1002             TopoDS_Vertex aVert = TopoDS::Vertex(aShapeLoc);
1003             aBuilder.Add(aWireProf, aVert, theWithContact, theWithCorrect);
1004           }
1005           else
1006             aBuilder.Add(aWireProf, theWithContact, theWithCorrect);
1007         }
1008         if (!aBuilder.IsReady()) {
1009           Standard_ConstructionError::Raise("Invalid input data for building PIPE: bases are invalid");
1010         }
1011       
1012         aBuilder.SetTolerance(aTolConf, aTolConf, aTolAng);
1013
1014         aBuilder.Build();
1015         aShape = aBuilder.Shape();
1016         aSeqFaces.Append(aShape);
1017         for (j = 1; j <=usedBases.Length(); j++)
1018           aBuilder.Delete(usedBases.Value(j));
1019       }
1020
1021       //for case if section is face
1022       if (aSeqFaces.Length() >1) {
1023         BRep_Builder aB;
1024         TopoDS_Compound aComp;
1025         aB.MakeCompound(aComp);
1026         for (i = 1; i <= aSeqFaces.Length(); i++)
1027           aB.Add(aComp,aSeqFaces.Value(i));
1028         aShape = aComp;
1029       }
1030   }
1031
1032   return aShape;
1033 }
1034
1035 //=======================================================================
1036 //function : CreatePipeForShellSections
1037 //purpose  : auxilary for Execute()
1038 //=======================================================================
1039 static TopoDS_Shape CreatePipeForShellSections(const TopoDS_Wire& aWirePath,
1040                                                GEOMImpl_IPipe* aCI)
1041 {
1042   //cout<<"CreatePipeForShellSections"<<endl;
1043   //TopoDS_Shape res;
1044   int i,j;
1045   BRep_Builder B;
1046
1047   GEOMImpl_IPipeShellSect* aCIDS = (GEOMImpl_IPipeShellSect*)aCI;
1048   Handle(TColStd_HSequenceOfTransient) aBasesObjs = aCIDS->GetBases();
1049   Handle(TColStd_HSequenceOfTransient) aSubBasesObjs = aCIDS->GetSubBases();
1050   Handle(TColStd_HSequenceOfTransient) aLocObjs = aCIDS->GetLocations();
1051   Standard_Boolean aWithContact = (aCIDS->GetWithContactMode());
1052   Standard_Boolean aWithCorrect = (aCIDS->GetWithCorrectionMode());
1053
1054   Standard_Integer nbBases = aBasesObjs->Length(),
1055     nbSubBases = (aSubBasesObjs.IsNull() ? 0 :aSubBasesObjs->Length()),
1056     nbLocs = (aLocObjs.IsNull() ? 0 :aLocObjs->Length());
1057
1058   if (nbLocs != nbBases) {
1059     if (aCI) delete aCI;
1060     Standard_ConstructionError::Raise("Number of sections is not equal to number of locations ");
1061   }
1062   if (nbSubBases && nbSubBases != nbBases) {
1063     if (aCI) delete aCI;
1064     Standard_ConstructionError::Raise("Number of sections is not equal to number of subsections ");
1065   }
1066
1067   //BRepOffsetAPI_MakePipeShell aBuilder(aWirePath);
1068
1069   TopTools_SequenceOfShape VLocs;
1070   for (i=1; i<=nbBases; i++) {
1071     Handle(Standard_Transient) anItemLoc = aLocObjs->Value(i);
1072     if (anItemLoc.IsNull())
1073       continue;
1074     Handle(GEOM_Function) aRefLoc = Handle(GEOM_Function)::DownCast(anItemLoc);
1075     TopoDS_Shape aShapeLoc = aRefLoc->GetValue();
1076     if (aShapeLoc.IsNull() || aShapeLoc.ShapeType() != TopAbs_VERTEX)
1077       continue;
1078     VLocs.Append(aShapeLoc);
1079   }
1080   nbLocs = VLocs.Length();
1081   if (nbLocs != nbBases) {
1082     if (aCI) delete aCI;
1083     Standard_ConstructionError::Raise("One of location shapes is not a vertex");
1084   }
1085   // split wire path by location points
1086   TColgp_SequenceOfPnt PLocs;
1087   for (i=1; i<=nbLocs; i++) {
1088     TopoDS_Vertex V = TopoDS::Vertex(VLocs.Value(i));
1089     PLocs.Append(BRep_Tool::Pnt(V));
1090   }
1091
1092   TopTools_SequenceOfShape Edges;
1093   TopTools_SequenceOfShape Wires;
1094   ShapeAnalysis_Edge sae;
1095
1096   if (nbLocs==2) {
1097     TopExp_Explorer anExp;
1098     for (anExp.Init(aWirePath, TopAbs_EDGE); anExp.More(); anExp.Next()) {
1099       Edges.Append(anExp.Current());
1100     }
1101     Standard_Integer Num1 = 0;
1102     Standard_Integer Num2 = 0;
1103     for (i=1; i<=Edges.Length(); i++) {
1104       TopoDS_Edge E = TopoDS::Edge(Edges.Value(i));
1105       double tol = BRep_Tool::Tolerance(E);
1106       TopoDS_Vertex V1 = sae.FirstVertex(E);
1107       TopoDS_Vertex V2 = sae.LastVertex(E);
1108       gp_Pnt P1 = BRep_Tool::Pnt(V1);
1109       gp_Pnt P2 = BRep_Tool::Pnt(V2);
1110       if (P1.Distance(PLocs.First()) < tol) {
1111         Num1 = i;
1112       }
1113       if (P2.Distance(PLocs.Last()) < tol) {
1114         Num2 = i;
1115       }
1116     }
1117     if (Num1>0 && Num2>0) {
1118       TopoDS_Wire W;
1119       B.MakeWire(W);
1120       for (i=Num1; i<=Num2; i++) {
1121         B.Add(W,Edges.Value(i));
1122       }
1123       Wires.Append(W);
1124     }
1125     else {
1126       Wires.Append(aWirePath);
1127     }
1128   }
1129   else {
1130     TopExp_Explorer anExp;
1131     for (anExp.Init(aWirePath, TopAbs_EDGE); anExp.More(); anExp.Next()) {
1132       Edges.Append(anExp.Current());
1133     }
1134     TopoDS_Edge edge = TopoDS::Edge(Edges.First());
1135     double tol = BRep_Tool::Tolerance(edge);
1136     TopoDS_Vertex VF = sae.FirstVertex(edge);
1137     gp_Pnt PF = BRep_Tool::Pnt(VF);
1138     //cout<<"PF("<<PF.X()<<","<<PF.Y()<<","<<PF.Z()<<")"<<endl;
1139     if (PF.Distance(PLocs.First()) > tol) {
1140       if (aCI) delete aCI;
1141       Standard_ConstructionError::Raise
1142         ("First location shapes is not coincided with first vertex of aWirePath");
1143     }
1144     VLocs.ChangeValue(1) = VF;
1145     edge = TopoDS::Edge(Edges.Last());
1146     tol = BRep_Tool::Tolerance(edge);
1147     TopoDS_Vertex VL = sae.LastVertex(edge);
1148     gp_Pnt PL = BRep_Tool::Pnt(VL);
1149     if (PL.Distance(PLocs.Last()) > tol) {
1150       if (aCI) delete aCI;
1151       Standard_ConstructionError::Raise
1152         ("Last location shapes is not coincided with last vertex of aWirePath");
1153     }
1154     VLocs.ChangeValue(nbLocs) = VL;
1155     int jcurr = 2;
1156     TopTools_SequenceOfShape tmpEdges;
1157     for (i=1; i<=Edges.Length() && jcurr<nbLocs; i++) {
1158       TopoDS_Edge E = TopoDS::Edge(Edges.Value(i));
1159       tol = BRep_Tool::Tolerance(E);
1160       TopoDS_Vertex V1 = sae.FirstVertex(E);
1161       TopoDS_Vertex V2 = sae.LastVertex(E);
1162       gp_Pnt P1 = BRep_Tool::Pnt(V1);
1163       gp_Pnt P2 = BRep_Tool::Pnt(V2);
1164       if (P2.Distance(PLocs.Value(jcurr)) < tol) {
1165         // make wire from current edge and add created
1166         // wire to Wires
1167         TopoDS_Wire W;
1168         B.MakeWire(W);
1169         for (j=1; j<=tmpEdges.Length(); j++)
1170           B.Add(W,tmpEdges.Value(j));
1171         B.Add(W,E);
1172         Wires.Append(W);
1173         VLocs.ChangeValue(jcurr) = V2;
1174         jcurr++;
1175         tmpEdges.Clear();
1176       }
1177       else {
1178         // find distance between E and aLocs(jcurr)
1179         double fp,lp;
1180         Handle(Geom_Curve) C = BRep_Tool::Curve(E,fp,lp);
1181         GeomAPI_ProjectPointOnCurve PPCurve (PLocs.Value(jcurr),C);
1182         if (PPCurve.NbPoints()>0 &&
1183             PLocs.Value(jcurr).Distance(PPCurve.Point(1)) < tol) {
1184           double param = PPCurve.Parameter(1);
1185           gp_Pnt PC1;
1186           C->D0(param,PC1);
1187           // split current edge
1188           Handle(Geom_TrimmedCurve) tc1 = new Geom_TrimmedCurve(C,fp,param);
1189           Handle(Geom_TrimmedCurve) tc2 = new Geom_TrimmedCurve(C,param,lp);
1190           TopoDS_Edge E1,E2;
1191           gp_Pnt Pfp;
1192           C->D0(fp,Pfp);
1193           if (Pfp.Distance(P1)<tol) {
1194             B.MakeEdge(E1,tc1,tol);
1195             B.Add(E1,V1);
1196             TopoDS_Shape tmpV = VLocs.Value(jcurr).Oriented(TopAbs_REVERSED);
1197             B.Add(E1,TopoDS::Vertex(tmpV));
1198             tmpEdges.Append(E1);
1199             B.MakeEdge(E2,tc2,tol);
1200             tmpV = VLocs.Value(jcurr).Oriented(TopAbs_FORWARD);
1201             B.Add(E2,TopoDS::Vertex(tmpV));
1202             B.Add(E2,V2);
1203           }
1204           else {
1205             B.MakeEdge(E1,tc2,tol);
1206             TopoDS_Shape tmpV = VLocs.Value(jcurr).Oriented(TopAbs_FORWARD);
1207             B.Add(E1,TopoDS::Vertex(tmpV));
1208             B.Add(E1,V1);
1209             E1.Reverse();
1210             tmpEdges.Append(E1);
1211             B.MakeEdge(E2,tc1,tol);
1212             B.Add(E2,V2);
1213             tmpV = VLocs.Value(jcurr).Oriented(TopAbs_REVERSED);
1214             B.Add(E2,TopoDS::Vertex(tmpV));
1215             E2.Reverse();
1216           }
1217           // create wire from tmpEdges
1218           TopoDS_Wire W;
1219           B.MakeWire(W);
1220           for (j=1; j<=tmpEdges.Length(); j++)
1221             B.Add(W,tmpEdges.Value(j));
1222           Wires.Append(W);
1223           jcurr++;
1224           tmpEdges.Clear();
1225           Edges.Remove(i);
1226           Edges.InsertAfter(i-1,E1);
1227           Edges.InsertAfter(i,E2);
1228         }
1229         else {
1230           tmpEdges.Append(E);
1231         }
1232       }
1233     }
1234     // create wire from other edges
1235     TopoDS_Wire W;
1236     B.MakeWire(W);
1237     for (; i<=Edges.Length(); i++)
1238       B.Add(W,Edges.Value(i));
1239     Wires.Append(W);
1240     //cout<<"Wires.Length()="<<Wires.Length()<<endl;
1241   }
1242
1243   if (Wires.Length() != nbLocs-1) {
1244     if (aCI) delete aCI;
1245     Standard_ConstructionError::Raise
1246       ("One of location shapes is not lied on the path");
1247   }
1248
1249   //TopTools_SequenceOfShape aSeqBases;
1250   //TopTools_SequenceOfShape aSeqSubBases;
1251   //TopTools_SequenceOfShape aSeqFaces;
1252   TopoDS_Compound aComp;
1253   B.MakeCompound(aComp);
1254   for (i = 1; i < nbBases; i++) {
1255     TopoDS_Wire WPath = TopoDS::Wire(Wires.Value(i));
1256     // 1 section
1257     Handle(Standard_Transient) anItem1 = aBasesObjs->Value(i);
1258     if (anItem1.IsNull())
1259       continue;
1260     Handle(GEOM_Function) aRefBase1 = Handle(GEOM_Function)::DownCast(anItem1);
1261     if (aRefBase1.IsNull())
1262       continue;
1263     TopoDS_Shape aShBase1 = aRefBase1->GetValue();
1264     if (aShBase1.IsNull())
1265       continue;
1266     TopAbs_ShapeEnum aType1 = aShBase1.ShapeType();
1267     // 2 section
1268     Handle(Standard_Transient) anItem2 = aBasesObjs->Value(i+1);
1269     if (anItem2.IsNull())
1270       continue;
1271     Handle(GEOM_Function) aRefBase2 = Handle(GEOM_Function)::DownCast(anItem2);
1272     if (aRefBase2.IsNull())
1273       continue;
1274     TopoDS_Shape aShBase2 = aRefBase2->GetValue();
1275     if (aShBase2.IsNull())
1276       continue;
1277     TopAbs_ShapeEnum aType2 = aShBase2.ShapeType();
1278
1279     //BRepTools::Write(aShBase1,"/dn02/users_Linux/skl/work/Bugs/14857/base1.brep");
1280
1281     bool OkSec = (aType1==TopAbs_SHELL || aType1==TopAbs_FACE) &&
1282                  (aType2==TopAbs_SHELL || aType2==TopAbs_FACE);
1283     if (!OkSec) {
1284       if (aCI) delete aCI;
1285       Standard_ConstructionError::Raise("One of section shapes has invalid type");
1286     }
1287
1288     bool CreateFewSolids = false;
1289     // compare sections
1290     TopExp_Explorer anExp;
1291     Standard_Integer nbf1 = 0;
1292     for (anExp.Init(aShBase1, TopAbs_FACE); anExp.More(); anExp.Next()) {
1293       nbf1++;
1294     }
1295     Standard_Integer nbf2 = 0;
1296     for (anExp.Init(aShBase2, TopAbs_FACE); anExp.More(); anExp.Next()) {
1297       nbf2++;
1298     }
1299     if (nbf1==nbf2) {
1300       CreateFewSolids = true;
1301     }
1302
1303     /*
1304     // check orientation of sections
1305     bool NeedReverse = false;
1306     {
1307       // first section
1308       anExp.Init(aShBase1, TopAbs_FACE);
1309       TopoDS_Shape aFace = anExp.Current();
1310       TColgp_SequenceOfPnt aPnts;
1311       double xc=0, yc=0, zc=0;
1312       for (anExp.Init(aFace, TopAbs_VERTEX); anExp.More(); anExp.Next()) {
1313         TopoDS_Vertex V = TopoDS::Vertex(anExp.Current());
1314         aPnts.Append(BRep_Tool::Pnt(V));
1315         xc += aPnts.Last().X();
1316         yc += aPnts.Last().Y();
1317         zc += aPnts.Last().Z();
1318       }
1319       gp_Pnt PC(xc/aPnts.Length(), yc/aPnts.Length(), zc/aPnts.Length());
1320       gp_Vec V1(PC,aPnts.Value(1));
1321       gp_Vec V2(PC,aPnts.Value(2));
1322       gp_Vec VN = V1.Crossed(V2);
1323       for (int ip=2; ip<aPnts.Length(); ip++) {
1324         V1 = gp_Vec(PC,aPnts.Value(ip));
1325         V2 = gp_Vec(PC,aPnts.Value(ip+1));
1326         VN.Add(V1.Crossed(V2));
1327       }
1328       gp_Vec PathNorm;
1329       gp_Pnt PLoc = BRep_Tool::Pnt(TopoDS::Vertex(VLocs(i)));
1330       TopExp_Explorer WE;
1331       for (WE.Init(WPath, TopAbs_EDGE); WE.More(); WE.Next()) {
1332         TopoDS_Edge edge = TopoDS::Edge(WE.Current());
1333         double tol = BRep_Tool::Tolerance(edge);
1334         TopoDS_Vertex VF = sae.FirstVertex(edge);
1335         gp_Pnt PF = BRep_Tool::Pnt(VF);
1336         if (PF.Distance(PLoc) < tol) {
1337           double fp,lp;
1338           Handle(Geom_Curve) C = BRep_Tool::Curve(edge,fp,lp);
1339           gp_Pnt P1,P2;
1340           C->D0(fp,P1);
1341           if (P1.Distance(PLoc) < tol) {
1342             C->D0(fp+(lp-fp)/100,P2);
1343           }
1344           else {
1345             C->D0(lp,P1);
1346             C->D0(lp+(fp-lp)/100,P2);
1347           }
1348           PathNorm = gp_Vec(P1,P2);
1349           break;
1350         }
1351         else {
1352           TopoDS_Vertex VL = sae.LastVertex(edge);
1353           gp_Pnt PL = BRep_Tool::Pnt(VL);
1354           if (PL.Distance(PLoc) < tol) {
1355             double fp,lp;
1356             Handle(Geom_Curve) C = BRep_Tool::Curve(edge,fp,lp);
1357             gp_Pnt P1,P2;
1358             C->D0(fp,P1);
1359             if (P1.Distance(PLoc) < tol) {
1360               C->D0(fp+(lp-fp)/100,P2);
1361             }
1362             else {
1363               C->D0(lp,P1);
1364               C->D0(lp+(fp-lp)/100,P2);
1365             }
1366             PathNorm = gp_Vec(P2,P1);
1367             break;
1368           }
1369         }
1370       }
1371       cout<<"VN("<<VN.X()<<","<<VN.Y()<<","<<VN.Z()<<")"<<endl;
1372       cout<<"PathNorm("<<PathNorm.X()<<","<<PathNorm.Y()<<","<<PathNorm.Z()<<")"<<endl;
1373       if (fabs(VN.Angle(PathNorm))>PI/2.) {
1374         NeedReverse = true;
1375         aShBase1.Reverse();
1376       }
1377     }
1378     {
1379       // second section
1380       anExp.Init(aShBase2, TopAbs_FACE);
1381       TopoDS_Shape aFace = anExp.Current();
1382       TColgp_SequenceOfPnt aPnts;
1383       double xc=0, yc=0, zc=0;
1384       for (anExp.Init(aFace, TopAbs_VERTEX); anExp.More(); anExp.Next()) {
1385         TopoDS_Vertex V = TopoDS::Vertex(anExp.Current());
1386         aPnts.Append(BRep_Tool::Pnt(V));
1387         xc += aPnts.Last().X();
1388         yc += aPnts.Last().Y();
1389         zc += aPnts.Last().Z();
1390       }
1391       gp_Pnt PC(xc/aPnts.Length(), yc/aPnts.Length(), zc/aPnts.Length());
1392       gp_Vec V1(PC,aPnts.Value(1));
1393       gp_Vec V2(PC,aPnts.Value(2));
1394       gp_Vec VN = V1.Crossed(V2);
1395       for (int ip=2; ip<aPnts.Length(); ip++) {
1396         V1 = gp_Vec(PC,aPnts.Value(ip));
1397         V2 = gp_Vec(PC,aPnts.Value(ip+1));
1398         VN.Add(V1.Crossed(V2));
1399       }
1400       gp_Vec PathNorm;
1401       gp_Pnt PLoc = BRep_Tool::Pnt(TopoDS::Vertex(VLocs(i+1)));
1402       TopExp_Explorer WE;
1403       for (WE.Init(WPath, TopAbs_EDGE); WE.More(); WE.Next()) {
1404         TopoDS_Edge edge = TopoDS::Edge(WE.Current());
1405         double tol = BRep_Tool::Tolerance(edge);
1406         TopoDS_Vertex VF = sae.FirstVertex(edge);
1407         gp_Pnt PF = BRep_Tool::Pnt(VF);
1408         if (PF.Distance(PLoc) < tol) {
1409           double fp,lp;
1410           Handle(Geom_Curve) C = BRep_Tool::Curve(edge,fp,lp);
1411           gp_Pnt P1,P2;
1412           C->D0(fp,P1);
1413           if (P1.Distance(PLoc) < tol) {
1414             C->D0(fp+(lp-fp)/100,P2);
1415           }
1416           else {
1417             C->D0(lp,P1);
1418             C->D0(lp+(fp-lp)/100,P2);
1419           }
1420           PathNorm = gp_Vec(P2,P1);
1421           break;
1422         }
1423         else {
1424           TopoDS_Vertex VL = sae.LastVertex(edge);
1425           gp_Pnt PL = BRep_Tool::Pnt(VL);
1426           if (PL.Distance(PLoc) < tol) {
1427             double fp,lp;
1428             Handle(Geom_Curve) C = BRep_Tool::Curve(edge,fp,lp);
1429             gp_Pnt P1,P2;
1430             C->D0(fp,P1);
1431             if (P1.Distance(PLoc) < tol) {
1432               C->D0(fp+(lp-fp)/100,P2);
1433             }
1434             else {
1435               C->D0(lp,P1);
1436               C->D0(lp+(fp-lp)/100,P2);
1437             }
1438             PathNorm = gp_Vec(P2,P1);
1439             break;
1440           }
1441         }
1442       }
1443       //cout<<"VN("<<VN.X()<<","<<VN.Y()<<","<<VN.Z()<<")"<<endl;
1444       //cout<<"PathNorm("<<PathNorm.X()<<","<<PathNorm.Y()<<","<<PathNorm.Z()<<")"<<endl;
1445       if (fabs(VN.Angle(PathNorm))>PI/2.)
1446         aShBase2.Reverse();
1447     }
1448     */
1449
1450     if (!CreateFewSolids) {
1451       // we can create only one solid
1452       TopoDS_Shape aWire1, aWire2;
1453       // prepare aWire1
1454       if (aType1==TopAbs_SHELL) {
1455         // create wire as boundary contour if shell is no closed
1456         // get free boundary shapes
1457         ShapeAnalysis_FreeBounds anAnalizer(aShBase1);
1458         TopoDS_Compound aClosed = anAnalizer.GetClosedWires();
1459         //TopExp_Explorer anExp;
1460         Standard_Integer NbWires = 0;
1461         for (anExp.Init(aClosed, TopAbs_WIRE); anExp.More(); anExp.Next()) {
1462           NbWires++;
1463           aWire1 = anExp.Current();
1464         }
1465         if (NbWires!=1) {
1466           // bad case
1467           if (aCI) delete aCI;
1468           Standard_ConstructionError::Raise("Bad shell is used as section ");
1469         }
1470       }
1471       else { // aType1==TopAbs_FACE
1472         TopExp_Explorer aExpW(aShBase1,TopAbs_WIRE);
1473         aWire1 = aExpW.Current();
1474       }
1475       // prepare aWire2
1476       if (aType2==TopAbs_SHELL) {
1477         // create wire as boundary contour if shell is no closed
1478         // get free boundary shapes
1479         ShapeAnalysis_FreeBounds anAnalizer(aShBase2);
1480         TopoDS_Compound aClosed = anAnalizer.GetClosedWires();
1481         //TopExp_Explorer anExp;
1482         Standard_Integer NbWires = 0;
1483         for (anExp.Init(aClosed, TopAbs_WIRE); anExp.More(); anExp.Next()) {
1484           NbWires++;
1485           aWire2 = anExp.Current();
1486         }
1487         if (NbWires!=1) {
1488           // bad case
1489           if (aCI) delete aCI;
1490           Standard_ConstructionError::Raise("Bad shell is used as section ");
1491         }
1492       }
1493       else { // aType2==TopAbs_FACE
1494         TopExp_Explorer aExpW(aShBase2,TopAbs_WIRE);
1495         aWire2 = aExpW.Current();
1496       }
1497       // make pipe using aWire1 and aWire2
1498       if (!aWire1.IsNull() && !aWire2.IsNull()) {
1499         //BRepOffsetAPI_MakePipeShell aBuilder(aWirePath);
1500         BRepOffsetAPI_MakePipeShell aBuilder(WPath);
1501         GeomFill_Trihedron theBestMode = EvaluateBestSweepMode(WPath);
1502         if (theBestMode == GeomFill_IsDiscreteTrihedron)
1503           aBuilder.SetDiscreteMode();
1504         aBuilder.Add(aWire1, TopoDS::Vertex(VLocs(i)),
1505                      aWithContact, aWithCorrect);
1506         aBuilder.Add(aWire2, TopoDS::Vertex(VLocs(i+1)),
1507                      aWithContact, aWithCorrect);
1508         if (!aBuilder.IsReady()) {
1509           if (aCI) delete aCI;
1510           Standard_ConstructionError::Raise("Invalid input data for building PIPE: bases are invalid");
1511         }
1512         aBuilder.Build();
1513         TopoDS_Shape aShape = aBuilder.Shape();
1514         TopoDS_Shell aShell;
1515         B.MakeShell(aShell);
1516         for (anExp.Init(aShape, TopAbs_FACE); anExp.More(); anExp.Next()) {
1517           B.Add(aShell,anExp.Current());
1518         }
1519         for (anExp.Init(aShBase1, TopAbs_FACE); anExp.More(); anExp.Next()) {
1520           B.Add(aShell,anExp.Current());
1521         }
1522         for (anExp.Init(aShBase2, TopAbs_FACE); anExp.More(); anExp.Next()) {
1523           B.Add(aShell,anExp.Current());
1524         }
1525         // make sewing for this shell
1526         Handle(BRepBuilderAPI_Sewing) aSewing = new BRepBuilderAPI_Sewing;
1527         aSewing->SetTolerance(Precision::Confusion());
1528         aSewing->SetFaceMode(Standard_True);
1529         aSewing->SetFloatingEdgesMode(Standard_False);
1530         aSewing->SetNonManifoldMode(Standard_False);
1531         for (anExp.Init(aShell, TopAbs_FACE); anExp.More(); anExp.Next()) {
1532           aSewing->Add(anExp.Current());
1533         }
1534         aSewing->Perform();
1535         const TopoDS_Shape aSewShape = aSewing->SewedShape();
1536         if (aSewShape.ShapeType() == TopAbs_SHELL) {
1537           aShell = TopoDS::Shell(aSewShape);
1538           GProp_GProps aSystem;
1539           BRepGProp::VolumeProperties(aShell, aSystem);
1540           if (aSystem.Mass()<0) {
1541             aShell.Reverse();
1542           }
1543           if (BRep_Tool::IsClosed(aShell)) {
1544             TopoDS_Solid aSolid;
1545             B.MakeSolid(aSolid);
1546             B.Add(aSolid,aShell);
1547             B.Add(aComp,aSolid);
1548           }
1549           else {
1550             B.Add(aComp,aShell);
1551           }
1552         }
1553         else {
1554           B.Add(aComp,aShell);
1555         }
1556       }
1557     }
1558     else {
1559       // main block - creation few solids (for each pair of faces)
1560       TopTools_MapOfShape aFaces1,aFaces2;
1561       for (anExp.Init(aShBase1, TopAbs_FACE); anExp.More(); anExp.Next()) {
1562         aFaces1.Add(anExp.Current());
1563       }
1564       for (anExp.Init(aShBase2, TopAbs_FACE); anExp.More(); anExp.Next()) {
1565         aFaces2.Add(anExp.Current());
1566       }
1567       // creating map of edge faces
1568       TopTools_IndexedDataMapOfShapeListOfShape aMapEdgeFaces1;
1569       TopExp::MapShapesAndAncestors(aShBase1, TopAbs_EDGE, TopAbs_FACE, aMapEdgeFaces1);
1570       TopTools_IndexedDataMapOfShapeListOfShape aMapEdgeFaces2;
1571       TopExp::MapShapesAndAncestors(aShBase2, TopAbs_EDGE, TopAbs_FACE, aMapEdgeFaces2);
1572
1573       // constuct map face->face
1574       TopTools_IndexedDataMapOfShapeShape FF;
1575       TopoDS_Shape FS1,FS2;
1576       if (nbSubBases==0) {
1577         // find edge the most distant from location point
1578         // (this edge is not shared by two faces)
1579         double maxdist = 0.;
1580         TopoDS_Shape E1;
1581         TopoDS_Vertex V11,V21;
1582         for (j=1; j<=aMapEdgeFaces1.Extent(); j++) {
1583           TopoDS_Shape tmp = aMapEdgeFaces1.FindKey(j);
1584           const TopTools_ListOfShape& aList = aMapEdgeFaces1.FindFromKey(tmp);
1585           if (aList.Extent()>1)
1586             continue;
1587           TopExp_Explorer expv;
1588           expv.Init(tmp, TopAbs_VERTEX);
1589           TopoDS_Vertex V1 = TopoDS::Vertex(expv.Current());
1590           expv.Next();
1591           TopoDS_Vertex V2 = TopoDS::Vertex(expv.Current());
1592           gp_Pnt P1 = BRep_Tool::Pnt(V1);
1593           gp_Pnt P2 = BRep_Tool::Pnt(V2);
1594           double dist = PLocs.Value(i).Distance(P1) + PLocs.Value(i).Distance(P2);
1595           if (dist>maxdist) {
1596             E1 = tmp;
1597             V11 = V1;
1598             V21 = V2;
1599             TopTools_ListIteratorOfListOfShape anIter(aList);
1600             FS1 = anIter.Value();
1601             maxdist = dist;
1602           }
1603         }
1604         // main direction for comparing
1605         gp_Vec VM(PLocs.Value(i),PLocs.Value(i+1));
1606         // find corresponding edge from next section
1607         double minang = M_PI;
1608         gp_Pnt P11 = BRep_Tool::Pnt(V11);
1609         gp_Pnt P21 = BRep_Tool::Pnt(V21);
1610         TopoDS_Shape E2;
1611         TopoDS_Vertex V12,V22;
1612         for (j=1; j<=aMapEdgeFaces2.Extent(); j++) {
1613           TopoDS_Shape tmp = aMapEdgeFaces2.FindKey(j);
1614           const TopTools_ListOfShape& aList = aMapEdgeFaces2.FindFromKey(tmp);
1615           if (aList.Extent()>1)
1616             continue;
1617           TopExp_Explorer expv;
1618           expv.Init(tmp, TopAbs_VERTEX);
1619           TopoDS_Vertex V1tmp = TopoDS::Vertex(expv.Current());
1620           expv.Next();
1621           TopoDS_Vertex V2tmp = TopoDS::Vertex(expv.Current());
1622           gp_Pnt P1tmp = BRep_Tool::Pnt(V1tmp);
1623           gp_Pnt P2tmp = BRep_Tool::Pnt(V2tmp);
1624           double d1 = P1tmp.Distance(P11) + P2tmp.Distance(P21);
1625           double d2 = P1tmp.Distance(P21) + P2tmp.Distance(P11);
1626           TopoDS_Vertex V1,V2;
1627           gp_Pnt P1,P2;
1628           if (d1>d2) {
1629             V1 = V2tmp; P1 = P2tmp;
1630             V2 = V1tmp; P2 = P1tmp;
1631           }
1632           else {
1633             V1 = V1tmp; P1 = P1tmp;
1634             V2 = V2tmp; P2 = P2tmp;
1635           }
1636           gp_Vec Vec1(P11,P1);
1637           gp_Vec Vec2(P21,P2);
1638           double ang = fabs(Vec1.Angle(VM)) + fabs(Vec2.Angle(VM));
1639           if (ang<minang) {
1640             E2 = tmp;
1641             V12 = V1;
1642             V22 = V2;
1643             TopTools_ListIteratorOfListOfShape anIter(aList);
1644             FS2 = anIter.Value();
1645             minang = ang;
1646           }
1647         }
1648         // put all pairs to map FF
1649         FF.Add(FS1,FS2);
1650         FF.Add(E1,E2);
1651         FF.Add(V11,V12);
1652         FF.Add(V21,V22);
1653
1654         // add pairs of edges to FF
1655         bool stat =  FillForOtherEdges(FS1,E1,V11,FF);
1656         if (!stat) {
1657           if (aCI) delete aCI;
1658           Standard_ConstructionError::Raise("FindForOtherEdges: Can not mapping other egdes");
1659         }
1660
1661       }
1662       else {
1663         { // 1 section
1664           Handle(Standard_Transient) anItem = aSubBasesObjs->Value(i);
1665           if (anItem.IsNull()) {
1666             if (aCI) delete aCI;
1667             Standard_ConstructionError::Raise("Invalid subbase shape");
1668           }
1669           Handle(GEOM_Function) aRefBase = Handle(GEOM_Function)::DownCast(anItem);
1670           if (aRefBase.IsNull()) {
1671             if (aCI) delete aCI;
1672             Standard_ConstructionError::Raise("Invalid subbase shape");
1673           }
1674           TopoDS_Shape aSh = aRefBase->GetValue();
1675           if (aSh.IsNull()) {
1676             if (aCI) delete aCI;
1677             Standard_ConstructionError::Raise("Invalid subbase shape");
1678           }
1679           if (aSh.ShapeType()!=TopAbs_FACE) {
1680             if (aCI) delete aCI;
1681             Standard_ConstructionError::Raise("Invalid subbase shape");
1682           }
1683           FS1 = aSh;
1684         }
1685         { // 2 section
1686           Handle(Standard_Transient) anItem = aSubBasesObjs->Value(i+1);
1687           if (anItem.IsNull()) {
1688             if (aCI) delete aCI;
1689             Standard_ConstructionError::Raise("Invalid subbase shape");
1690           }
1691           Handle(GEOM_Function) aRefBase = Handle(GEOM_Function)::DownCast(anItem);
1692           if (aRefBase.IsNull()) {
1693             if (aCI) delete aCI;
1694             Standard_ConstructionError::Raise("Invalid subbase shape");
1695           }
1696           TopoDS_Shape aSh = aRefBase->GetValue();
1697           if (aSh.IsNull()) {
1698             if (aCI) delete aCI;
1699             Standard_ConstructionError::Raise("Invalid subbase shape");
1700           }
1701           if (aSh.ShapeType()!=TopAbs_FACE) {
1702             if (aCI) delete aCI;
1703             Standard_ConstructionError::Raise("Invalid subbase shape");
1704           }
1705           FS2 = aSh;
1706         }
1707
1708         if (!aFaces1.Contains(FS1) || !aFaces2.Contains(FS2)) {
1709           if (aCI) delete aCI;
1710           Standard_ConstructionError::Raise("Invalid subbase shape");
1711         }
1712
1713         FF.Add(FS1,FS2);
1714
1715         // add pairs of edges to FF
1716         bool stat =  FillCorrespondingEdges(FS1, FS2, TopoDS::Vertex(VLocs(i)),
1717                                             TopoDS::Vertex(VLocs(i+1)), WPath, FF);
1718         if (!stat) {
1719           if (aCI) delete aCI;
1720           Standard_ConstructionError::Raise("Can not create correct pipe");
1721         }
1722       }
1723
1724       FindNextPairOfFaces(FS1, aMapEdgeFaces1, aMapEdgeFaces2, FF, aCI);
1725
1726       // make pipe for each pair of faces
1727       for (j=1; j<=FF.Extent(); j++) {
1728         TopoDS_Shape F1 = FF.FindKey(j);
1729         if (F1.ShapeType() != TopAbs_FACE)
1730           continue;
1731         TopoDS_Shape F2 = FF.FindFromIndex(j);
1732         TopExp_Explorer aExpW1(F1,TopAbs_WIRE);
1733         TopoDS_Wire aWire1 = TopoDS::Wire(aExpW1.Current());
1734         TopExp_Explorer aExpW2(F2,TopAbs_WIRE);
1735         TopoDS_Wire aWire2 = TopoDS::Wire(aExpW2.Current());
1736         // make pipe using aWire1 and aWire2
1737         if (!aWire1.IsNull() && !aWire2.IsNull()) {
1738           BRepOffsetAPI_MakePipeShell aBuilder(WPath);
1739           GeomFill_Trihedron theBestMode = EvaluateBestSweepMode(WPath);
1740           if (theBestMode == GeomFill_IsDiscreteTrihedron)
1741             aBuilder.SetDiscreteMode();
1742           aBuilder.Add(aWire1, TopoDS::Vertex(VLocs(i)),
1743                        aWithContact, aWithCorrect);
1744           aBuilder.Add(aWire2, TopoDS::Vertex(VLocs(i+1)),
1745                        aWithContact, aWithCorrect);
1746           if (!aBuilder.IsReady()) {
1747             if (aCI) delete aCI;
1748             Standard_ConstructionError::Raise("Invalid input data for building PIPE: bases are invalid");
1749           }
1750           aBuilder.Build();
1751           TopoDS_Shape aShape = aBuilder.Shape();
1752           TopoDS_Shell aShell;
1753           B.MakeShell(aShell);
1754           for (anExp.Init(aShape, TopAbs_FACE); anExp.More(); anExp.Next()) {
1755             B.Add(aShell,anExp.Current());
1756           }
1757
1758           B.Add(aShell,F1);
1759           B.Add(aShell,F2);
1760           // make sewing for this shell
1761           Handle(BRepBuilderAPI_Sewing) aSewing = new BRepBuilderAPI_Sewing;
1762           aSewing->SetTolerance(Precision::Confusion());
1763           aSewing->SetFaceMode(Standard_True);
1764           aSewing->SetFloatingEdgesMode(Standard_False);
1765           aSewing->SetNonManifoldMode(Standard_False);
1766           for (anExp.Init(aShell, TopAbs_FACE); anExp.More(); anExp.Next()) {
1767             aSewing->Add(anExp.Current());
1768           }
1769           aSewing->Perform();
1770           const TopoDS_Shape aSewShape = aSewing->SewedShape();
1771           if (aSewShape.ShapeType() == TopAbs_SHELL) {
1772             aShell = TopoDS::Shell(aSewShape);
1773             GProp_GProps aSystem;
1774             BRepGProp::VolumeProperties(aShell, aSystem);
1775             if (aSystem.Mass()<0) {
1776               //cout<<"aSewShape is reversed"<<endl;
1777               aShell.Reverse();
1778             }
1779             if (BRep_Tool::IsClosed(aShell)) {
1780               TopoDS_Solid aSolid;
1781               B.MakeSolid(aSolid);
1782               B.Add(aSolid,aShell);
1783               B.Add(aComp,aSolid);
1784             }
1785             else {
1786               B.Add(aComp,aShell);
1787             }
1788           }
1789           else {
1790             B.Add(aComp,aShell);
1791           }
1792         }
1793       }
1794
1795     }
1796   }
1797
1798   //BRepTools::Write(aComp,"/dn02/users_Linux/skl/work/Bugs/14857/comp.brep");
1799   return aComp;
1800 }
1801
1802 //=======================================================================
1803 //function : CreatePipeShellsWithoutPath
1804 //purpose  : auxilary for Execute()
1805 //=======================================================================
1806 static TopoDS_Shape CreatePipeShellsWithoutPath(GEOMImpl_IPipe* aCI)
1807 {
1808   //cout<<"CreatePipeShellsWithoutPath"<<endl;
1809   int i,j;
1810   BRep_Builder B;
1811
1812   GEOMImpl_IPipeShellSect* aCIDS = (GEOMImpl_IPipeShellSect*)aCI;
1813   // shell sections
1814   Handle(TColStd_HSequenceOfTransient) aBasesObjs = aCIDS->GetBases();
1815   // vertex for recognition
1816   Handle(TColStd_HSequenceOfTransient) VObjs = aCIDS->GetLocations();
1817
1818   Standard_Integer nbBases = aBasesObjs->Length(),
1819     nbv = (VObjs.IsNull() ? 0 :VObjs->Length());
1820
1821   if (nbv != nbBases) {
1822     if (aCI) delete aCI;
1823     Standard_ConstructionError::Raise("Number of shapes for recognition is invalid");
1824   }
1825
1826   TopTools_SequenceOfShape SecVs,Bases;
1827   for (i=1; i<=nbBases; i++) {
1828     // vertex
1829     Handle(Standard_Transient) anItem = VObjs->Value(i);
1830     if (anItem.IsNull())
1831       continue;
1832     Handle(GEOM_Function) aRef = Handle(GEOM_Function)::DownCast(anItem);
1833     TopoDS_Shape V = aRef->GetValue();
1834     if (V.IsNull() || V.ShapeType() != TopAbs_VERTEX)
1835       continue;
1836     SecVs.Append(V);
1837     // section
1838     anItem = aBasesObjs->Value(i);
1839     if (anItem.IsNull())
1840       continue;
1841     aRef = Handle(GEOM_Function)::DownCast(anItem);
1842     TopoDS_Shape aSh = aRef->GetValue();
1843     if (aSh.IsNull())
1844       continue;
1845     Bases.Append(aSh);
1846   }
1847   nbv = SecVs.Length();
1848   nbBases = Bases.Length();
1849   if (nbv != nbBases) {
1850     if (aCI) delete aCI;
1851     Standard_ConstructionError::Raise("One of shapes for recognition is not a vertex");
1852   }
1853
1854   TopoDS_Compound aComp;
1855   B.MakeCompound(aComp);
1856
1857   for (i = 1; i < nbBases; i++) {
1858     MESSAGE ("Make pipe between sections "<<i<<" and "<<i+1);
1859     TopoDS_Shape aShBase1 = Bases.Value(i);
1860     TopoDS_Shape aShBase2 = Bases.Value(i+1);
1861     TopExp_Explorer anExp;
1862     Standard_Integer nbf1 = 0;
1863     for (anExp.Init(aShBase1, TopAbs_FACE); anExp.More(); anExp.Next()) {
1864       nbf1++;
1865     }
1866     Standard_Integer nbf2 = 0;
1867     for (anExp.Init(aShBase2, TopAbs_FACE); anExp.More(); anExp.Next()) {
1868       nbf2++;
1869     }
1870     //cout<<"nbf1="<<nbf1<<" nbf2="<<nbf2<<endl;
1871     if (nbf1!=nbf2) {
1872       if (aCI) delete aCI;
1873       Standard_ConstructionError::Raise("Different number of faces in the sections");
1874     }
1875
1876     TopTools_MapOfShape aFaces1,aFaces2;
1877     for (anExp.Init(aShBase1, TopAbs_FACE); anExp.More(); anExp.Next()) {
1878       aFaces1.Add(anExp.Current());
1879     }
1880     for (anExp.Init(aShBase2, TopAbs_FACE); anExp.More(); anExp.Next()) {
1881       aFaces2.Add(anExp.Current());
1882     }
1883
1884     // creating map of edge faces
1885     TopTools_IndexedDataMapOfShapeListOfShape aMapEdgeFaces1;
1886     TopExp::MapShapesAndAncestors(aShBase1, TopAbs_EDGE, TopAbs_FACE, aMapEdgeFaces1);
1887     TopTools_IndexedDataMapOfShapeListOfShape aMapEdgeFaces2;
1888     TopExp::MapShapesAndAncestors(aShBase2, TopAbs_EDGE, TopAbs_FACE, aMapEdgeFaces2);
1889
1890     // constuct map face->face (and sub-shapes)
1891     TopTools_IndexedDataMapOfShapeShape FF;
1892     //TopoDS_Shape FS1 = SecFs.Value(i), FS2 = SecFs.Value(i+1);
1893     TopoDS_Shape FS1, FS2;
1894     TopoDS_Vertex V1 = TopoDS::Vertex(SecVs(i));
1895     TopoDS_Vertex V2 = TopoDS::Vertex(SecVs(i+1));
1896     FindFirstPairFaces(aShBase1, aShBase2, V1, V2, FS1, FS2);
1897
1898     FF.Add(FS1,FS2);
1899     MESSAGE ("  first pair of corresponding faces is found");
1900
1901     // add pairs of edges and vertexes to FF
1902     bool stat =  FillCorrespondingEdges(FS1, FS2, V1, V2, FF);
1903     if (!stat) {
1904       if (aCI) delete aCI;
1905       Standard_ConstructionError::Raise("Can not create correct pipe");
1906     }
1907     MESSAGE ("  correspondences for sub-shapes of first pair of faces is found");
1908
1909     FindNextPairOfFaces(FS1, aMapEdgeFaces1, aMapEdgeFaces2, FF, aCI);
1910     MESSAGE ("  other correspondences is found, make pipe for all pairs of faces");
1911
1912     // make pipe for each pair of faces
1913     // auxilary map vertex->edge for created pipe edges
1914     TopTools_IndexedDataMapOfShapeShape VPE;
1915     ShapeAnalysis_Edge sae;
1916     //cout<<"FF.Extent()="<<FF.Extent()<<endl;
1917     int nbff = 0;
1918     for (j=1; j<=FF.Extent(); j++) {
1919       TopoDS_Shape F1 = FF.FindKey(j);
1920       if (F1.ShapeType() != TopAbs_FACE)
1921         continue;
1922       TopoDS_Shape F2 = FF.FindFromIndex(j);
1923       nbff++;
1924
1925       //if (nbff!=3) continue;
1926
1927       MESSAGE ("    make pipe for "<<nbff<<" face");
1928
1929       Handle(Geom_Surface) S1 = BRep_Tool::Surface(TopoDS::Face(F1));
1930       if (S1->IsKind(STANDARD_TYPE(Geom_RectangularTrimmedSurface))) {
1931         Handle(Geom_RectangularTrimmedSurface) RTS =
1932           Handle(Geom_RectangularTrimmedSurface)::DownCast(S1);
1933         S1 = RTS->BasisSurface();
1934       }
1935       Handle(Geom_Plane) Pln1 = Handle(Geom_Plane)::DownCast(S1);
1936       if (Pln1.IsNull()) {
1937         if (aCI) delete aCI;
1938         Standard_ConstructionError::Raise("Surface from face is not plane");
1939       }
1940       gp_Vec aDir1(Pln1->Axis().Direction());
1941
1942       Handle(Geom_Surface) S2 = BRep_Tool::Surface(TopoDS::Face(F2));
1943       if (S2->IsKind(STANDARD_TYPE(Geom_RectangularTrimmedSurface))) {
1944         Handle(Geom_RectangularTrimmedSurface) RTS =
1945           Handle(Geom_RectangularTrimmedSurface)::DownCast(S2);
1946         S2 = RTS->BasisSurface();
1947       }
1948       Handle(Geom_Plane) Pln2 =
1949           Handle(Geom_Plane)::DownCast(S2);
1950       if (Pln2.IsNull()) {
1951         if (aCI) delete aCI;
1952         Standard_ConstructionError::Raise("Surface from face is not plane");
1953       }
1954       gp_Vec aDir2(Pln2->Axis().Direction());
1955
1956       gp_Pnt P1 = BRep_Tool::Pnt(TopoDS::Vertex(SecVs(i)));
1957       gp_Pnt P2 = BRep_Tool::Pnt(TopoDS::Vertex(SecVs(i+1)));
1958       gp_Vec aDir(P1,P2);
1959       if (fabs(aDir.Angle(aDir1)) > M_PI/2.)
1960         aDir1.Reverse();
1961       if (fabs(aDir.Angle(aDir2)) > M_PI/2.)
1962         aDir2.Reverse();
1963
1964       TopExp_Explorer anExpE(F1,TopAbs_EDGE);
1965       TopTools_SequenceOfShape aNewFs;
1966       //int nbee=0;
1967       for (; anExpE.More(); anExpE.Next()) {
1968         TopoDS_Edge E1 = TopoDS::Edge(anExpE.Current());
1969         //nbee++;
1970         if (!FF.Contains(E1))
1971           MESSAGE ("map FF not contains key E1");
1972
1973         if (VPE.Contains(E1)) {
1974           aNewFs.Append(VPE.FindFromKey(E1));
1975 #ifdef _DEBUG_
1976           MESSAGE ("    using existed face");
1977 #endif
1978           continue;
1979         }
1980
1981         TopoDS_Edge E3 = TopoDS::Edge(FF.FindFromKey(E1));
1982         TopoDS_Vertex V1 = sae.FirstVertex(E1);
1983         TopoDS_Vertex V2 = sae.LastVertex(E1);
1984         if (!FF.Contains(V1))
1985           MESSAGE ("map FF not contains key V1");
1986         if (!FF.Contains(V2))
1987           MESSAGE ("map FF not contains key V2");
1988         TopoDS_Vertex V3 = TopoDS::Vertex(FF.FindFromKey(V2));
1989         TopoDS_Vertex V4 = TopoDS::Vertex(FF.FindFromKey(V1));
1990         TopoDS_Vertex Vtmp = sae.FirstVertex(E3);
1991         if (Vtmp.IsSame(V4))
1992           E3.Reverse();
1993         gp_Pnt P1 = BRep_Tool::Pnt(V1);
1994         gp_Pnt P2 = BRep_Tool::Pnt(V2);
1995         gp_Pnt P3 = BRep_Tool::Pnt(V3);
1996         gp_Pnt P4 = BRep_Tool::Pnt(V4);
1997         // make E2
1998         TopoDS_Edge E2;
1999         Handle(Geom_BSplineCurve) C2;
2000         if (VPE.Contains(V2)) {
2001           E2 = TopoDS::Edge(VPE.FindFromKey(V2));
2002           double fp,lp;
2003           C2 = Handle(Geom_BSplineCurve)::DownCast(BRep_Tool::Curve(E2,fp,lp));
2004         }
2005         else {
2006           Handle(TColgp_HArray1OfPnt) HAP = new TColgp_HArray1OfPnt(1,2);
2007           HAP->SetValue(1,P2);
2008           HAP->SetValue(2,P3);
2009           GeomAPI_Interpolate anInt(HAP,Standard_False,1.e-7);
2010           anInt.Load(aDir1,aDir2);
2011           anInt.Perform();
2012           C2 = anInt.Curve();
2013           B.MakeEdge(E2,C2,1.e-7);
2014           B.Add(E2,TopoDS::Vertex(V2.Oriented(TopAbs_FORWARD)));
2015           B.Add(E2,TopoDS::Vertex(V3.Oriented(TopAbs_REVERSED)));
2016           VPE.Add(V2,E2);
2017         }
2018         // make E4
2019         TopoDS_Edge E4;
2020         Handle(Geom_BSplineCurve) C4;
2021         if (VPE.Contains(V1)) {
2022           E4 = TopoDS::Edge(VPE.FindFromKey(V1));
2023           double fp,lp;
2024           C4 = Handle(Geom_BSplineCurve)::DownCast(BRep_Tool::Curve(E4,fp,lp));
2025         }
2026         else {
2027           Handle(TColgp_HArray1OfPnt) HAP = new TColgp_HArray1OfPnt(1,2);
2028           HAP->SetValue(1,P1);
2029           HAP->SetValue(2,P4);
2030           GeomAPI_Interpolate anInt(HAP,Standard_False,1.e-7);
2031           anInt.Load(aDir1,aDir2);
2032           anInt.Perform();
2033           C4 = anInt.Curve();
2034           B.MakeEdge(E4,anInt.Curve(),1.e-7);
2035           B.Add(E4,TopoDS::Vertex(V1.Oriented(TopAbs_FORWARD)));
2036           B.Add(E4,TopoDS::Vertex(V4.Oriented(TopAbs_REVERSED)));
2037           VPE.Add(V1,E4);
2038         }
2039
2040         TopoDS_Wire W;
2041         B.MakeWire(W);
2042         B.Add(W,E1);
2043         B.Add(W,E2);
2044         B.Add(W,E3);
2045         B.Add(W,E4.Reversed());
2046         //cout<<"      wire for edge "<<nbee<<" is created"<<endl;
2047         //BRepTools::Write(W,"/dn02/users_Linux/skl/work/Bugs/14857/w.brep");
2048
2049         // make surface
2050
2051         double fp,lp;
2052         Handle(Geom_Curve) C1 = BRep_Tool::Curve(E1,fp,lp);
2053         //bool IsConicC1 = false;
2054         //if (C1->IsKind(STANDARD_TYPE(Geom_Conic))) {
2055         //  IsConicC1 = true;
2056         //  cout<<"C1 - Geom_Conic"<<endl;
2057         //}
2058         if (C1->IsKind(STANDARD_TYPE(Geom_Line)) || C1->IsKind(STANDARD_TYPE(Geom_Conic))) {
2059           C1 = new Geom_TrimmedCurve(C1,fp,lp);
2060         }
2061         //if (IsConicC1) {
2062         //  double tol = BRep_Tool::Tolerance(E1);
2063         //  GeomConvert_ApproxCurve ApxC1(C1,tol,GeomAbs_C1,10,5);
2064         //  C1 = ApxC1.Curve();
2065         //}
2066         Handle(Geom_Curve) C3 = BRep_Tool::Curve(E3,fp,lp);
2067         if (C3->IsKind(STANDARD_TYPE(Geom_Line)) || C3->IsKind(STANDARD_TYPE(Geom_Conic))) {
2068           C3 = new Geom_TrimmedCurve(C3,fp,lp);
2069         }
2070         //filebuf fic;
2071         //ostream os(&fic);
2072         //os.precision(15);
2073         Handle(Geom_BSplineCurve) CE1 =
2074           GeomConvert::CurveToBSplineCurve(C1,Convert_RationalC1);
2075         if (CE1->Degree()<3)
2076           CE1->IncreaseDegree(3);
2077         Handle(Geom_BSplineCurve) CE2 =
2078           GeomConvert::CurveToBSplineCurve(C2,Convert_RationalC1);
2079         if (CE2->Degree()<3)
2080           CE2->IncreaseDegree(3);
2081         Handle(Geom_BSplineCurve) CE3 =
2082           GeomConvert::CurveToBSplineCurve(C3,Convert_RationalC1);
2083         if (CE3->Degree()<3)
2084           CE3->IncreaseDegree(3);
2085         Handle(Geom_BSplineCurve) CE4 =
2086           GeomConvert::CurveToBSplineCurve(C4,Convert_RationalC1);
2087         if (CE4->Degree()<3)
2088           CE4->IncreaseDegree(3);
2089         //cout<<"CE1->Degree()="<<CE1->Degree()<<" CE2->Degree()="<<CE2->Degree()
2090         //    <<" CE3->Degree()="<<CE3->Degree()<<" CE4->Degree()="<<CE4->Degree()<<endl;
2091         //if (fic.open("/dn02/users_Linux/skl/work/Bugs/14857/ce1.brep",ios::out)) {
2092         //  os<<"DrawTrSurf_BSplineCurve"<<endl;
2093         //  GeomTools::Write(CE1,os);
2094         //  fic.close();
2095         //}
2096
2097         Handle(Geom_Surface) BS;
2098         try {
2099           GeomFill_BSplineCurves GF(CE1,CE2,CE3,CE4,GeomFill_CoonsStyle);
2100           //GeomFill_BSplineCurves GF(CE1,CE2,CE3,CE4,GeomFill_StretchStyle);
2101           BS = GF.Surface();
2102         }
2103         catch(...) {
2104           MESSAGE ("      can not create BSplineSurface - create Bezier");
2105           int NbP=26;
2106           TColgp_Array2OfPnt Points(1,NbP,1,NbP);
2107           double fp1,lp1,fp2,lp2;
2108           Handle(Geom_Curve) C1 = BRep_Tool::Curve(E1,fp1,lp1);
2109           Handle(Geom_Curve) C3 = BRep_Tool::Curve(E3,fp2,lp2);
2110           gp_Pnt P1C1,P2C1;
2111           C1->D0(fp1,P1C1);
2112           C1->D0(lp1,P2C1);
2113           gp_Pnt P1C3,P2C3;
2114           C3->D0(fp2,P1C3);
2115           C3->D0(lp2,P2C3);
2116           int n1,n2;
2117           double fp,lp;
2118           // get points from C1
2119           if (P1.Distance(P1C1)<1.e-6) {
2120             fp = fp1;
2121             lp = lp1;
2122           }
2123           else {
2124             fp = lp1;
2125             lp = fp1;
2126           }
2127           double step = (lp-fp)/(NbP-1);
2128           Points.SetValue(1,1,P1);
2129           double par = fp;
2130           for (n1=2; n1<NbP; n1++) {
2131             gp_Pnt P;
2132             par += step;
2133             C1->D0(par,P);
2134             Points.SetValue(1,n1,P);
2135           }
2136           Points.SetValue(1,NbP,P2);
2137           // get points from C3
2138           if (P4.Distance(P1C3)<1.e-6) {
2139             fp = fp2;
2140             lp = lp2;
2141           }
2142           else {
2143             fp = lp2;
2144             lp = fp2;
2145           }
2146           step = (lp-fp)/(NbP-1);
2147           Points.SetValue(NbP,1,P4);
2148           par = fp;
2149           for (n1=2; n1<NbP; n1++) {
2150             gp_Pnt P;
2151             par += step;
2152             C3->D0(par,P);
2153             Points.SetValue(NbP,n1,P);
2154           }
2155           Points.SetValue(NbP,NbP,P3);
2156           // create isolines and get points from them
2157           for (n1=1; n1<=NbP; n1++) {
2158             gp_Pnt PI1 = Points.Value(1,n1);
2159             gp_Pnt PI2 = Points.Value(NbP,n1);
2160             Handle(TColgp_HArray1OfPnt) HAP = new TColgp_HArray1OfPnt(1,2);
2161             HAP->SetValue(1,PI1);
2162             HAP->SetValue(2,PI2);
2163             GeomAPI_Interpolate anInt(HAP,Standard_False,1.e-7);
2164             anInt.Load(aDir1,aDir2);
2165             anInt.Perform();
2166             Handle(Geom_Curve) iso = anInt.Curve();
2167             fp = iso->FirstParameter();
2168             lp = iso->LastParameter();
2169             step = (lp-fp)/(NbP-1);
2170             par = fp;
2171             TopoDS_Compound VComp;
2172             B.MakeCompound(VComp);
2173             for (n2=2; n2<NbP; n2++) {
2174               gp_Pnt P;
2175               par += step;
2176               iso->D0(par,P);
2177               Points.SetValue(n2,n1,P);
2178             }
2179           }
2180           // create surface and face
2181           //Handle(Geom_BezierSurface) BS = new Geom_BezierSurface(Points);
2182           BS = new Geom_BezierSurface(Points);
2183         }
2184
2185         BRepBuilderAPI_MakeFace BB(BS,W);
2186         TopoDS_Face NewF = BB.Face();
2187         Handle(ShapeFix_Face) sff = new ShapeFix_Face(NewF);
2188         sff->Perform();
2189         sff->FixOrientation();
2190         TopoDS_Face FixedFace = sff->Face();
2191         aNewFs.Append(FixedFace);
2192         VPE.Add(E1,FixedFace);
2193         //cout<<"      face for edge "<<nbee<<" is created"<<endl;
2194         //BRepTools::Write(FixedFace,"/dn02/users_Linux/skl/work/Bugs/14857/f.brep");
2195       }
2196       // make shell
2197       TopoDS_Shell aShell;
2198       B.MakeShell(aShell);
2199       for (int nf=1; nf<=aNewFs.Length(); nf++) {
2200         B.Add(aShell,aNewFs(nf));
2201       }
2202       B.Add(aShell,F1);
2203       B.Add(aShell,F2);
2204
2205       // make sewing for this shell
2206       Handle(BRepBuilderAPI_Sewing) aSewing = new BRepBuilderAPI_Sewing;
2207       aSewing->SetTolerance(Precision::Confusion());
2208       aSewing->SetFaceMode(Standard_True);
2209       aSewing->SetFloatingEdgesMode(Standard_False);
2210       aSewing->SetNonManifoldMode(Standard_False);
2211       for (anExp.Init(aShell, TopAbs_FACE); anExp.More(); anExp.Next()) {
2212         aSewing->Add(anExp.Current());
2213       }
2214       aSewing->Perform();
2215       MESSAGE ("    shell for face "<<nbff<<" is created");
2216       const TopoDS_Shape aSewShape = aSewing->SewedShape();
2217       //BRepTools::Write(aSewShape,"/dn02/users_Linux/skl/work/Bugs/14857/sew.brep");
2218       if (aSewShape.ShapeType() == TopAbs_SHELL) {
2219         aShell = TopoDS::Shell(aSewShape);
2220         GProp_GProps aSystem;
2221         BRepGProp::VolumeProperties(aShell, aSystem);
2222         if (aSystem.Mass()<0) {
2223           //cout<<"aSewShape is reversed"<<endl;
2224           aShell.Reverse();
2225         }
2226         if (BRep_Tool::IsClosed(aShell)) {
2227           TopoDS_Solid aSolid;
2228           B.MakeSolid(aSolid);
2229           B.Add(aSolid,aShell);
2230           B.Add(aComp,aSolid);
2231           MESSAGE ("    solid for face "<<nbff<<" is created");
2232         }
2233         else {
2234           B.Add(aComp,aShell);
2235           MESSAGE ("    solid for face "<<nbff<<" is not created");
2236         }
2237       }
2238       else {
2239         B.Add(aComp,aShell);
2240         MESSAGE ("    solid for face "<<nbff<<" is not created");
2241       }
2242       //cout<<"    solid for face "<<nbff<<" is created"<<endl;
2243
2244       //Handle(ShapeFix_Shell) sfs = new ShapeFix_Shell(aShell);
2245       //sfs->Perform();
2246       //TopoDS_Shell FixedShell = sfs->Shell();
2247       /*
2248       GProp_GProps aSystem;
2249       BRepGProp::VolumeProperties(FixedShell, aSystem);
2250       if (aSystem.Mass()<0) {
2251         //cout<<"aSewShape is reversed"<<endl;
2252         FixedShell.Reverse();
2253       }
2254       if (BRep_Tool::IsClosed(FixedShell)) {
2255         TopoDS_Solid aSolid;
2256         B.MakeSolid(aSolid);
2257         B.Add(aSolid,aShell);
2258         B.Add(aComp,aSolid);
2259       }
2260       else {
2261         B.Add(aComp,FixedShell);
2262       }
2263       */
2264     }
2265   }
2266
2267   //BRepTools::Write(aComp,"/dn02/users_Linux/skl/work/Bugs/14857/comp.brep");
2268   return aComp;
2269 }
2270
2271 //=======================================================================
2272 //function : CreatePipeBiNormalAlongVector
2273 //purpose  : auxilary for Execute()
2274 //=======================================================================
2275 static TopoDS_Shape CreatePipeBiNormalAlongVector(const TopoDS_Wire& aWirePath,
2276                                                   GEOMImpl_IPipe* aCI)
2277 {
2278   GEOMImpl_IPipeBiNormal* aCIBN = (GEOMImpl_IPipeBiNormal*)aCI;
2279
2280   Handle(GEOM_Function) aRefBase = aCIBN->GetBase();
2281   Handle(GEOM_Function) aRefVec = aCIBN->GetVector();
2282   TopoDS_Shape aShapeBase = aRefBase->GetValue();
2283   TopoDS_Shape aShapeVec = aRefVec->GetValue();
2284
2285   if (aShapeBase.IsNull()) {
2286     if (aCIBN) delete aCIBN;
2287     Standard_NullObject::Raise("MakePipe aborted : null base argument");
2288   }
2289
2290   // Make copy to prevent modifying of base object: 0021525
2291   BRepBuilderAPI_Copy Copy (aShapeBase);
2292   if (Copy.IsDone())
2293     aShapeBase = Copy.Shape();
2294
2295   TopoDS_Shape aProf;
2296   if (aShapeBase.ShapeType() == TopAbs_VERTEX) {
2297     aProf = aShapeBase;
2298   }
2299   else if (aShapeBase.ShapeType() == TopAbs_EDGE) {
2300     aProf = BRepBuilderAPI_MakeWire(TopoDS::Edge(aShapeBase)).Shape();
2301   }
2302   else if (aShapeBase.ShapeType() == TopAbs_WIRE) {
2303     aProf = aShapeBase;
2304   }
2305   else if (aShapeBase.ShapeType() == TopAbs_FACE) {
2306     TopExp_Explorer wexp (aShapeBase,TopAbs_WIRE);
2307     aProf = wexp.Current();
2308   }
2309   else {
2310     Standard_TypeMismatch::Raise
2311       ("MakePipe aborted : invalid type of base");
2312   }
2313   BRepOffsetAPI_MakePipeShell PipeBuilder (aWirePath);
2314   PipeBuilder.Add(aProf);
2315
2316   if (aShapeVec.IsNull()) {
2317     if (aCIBN) delete aCIBN;
2318     Standard_NullObject::Raise
2319       ("MakePipe aborted : null vector argument");
2320   }
2321   if (aShapeVec.ShapeType() != TopAbs_EDGE)
2322     Standard_TypeMismatch::Raise
2323       ("MakePipe aborted: invalid type of vector");
2324   TopoDS_Edge anEdge = TopoDS::Edge(aShapeVec);
2325   TopoDS_Vertex V1, V2;
2326   TopExp::Vertices(anEdge, V1, V2, Standard_True);
2327   if (V1.IsNull() || V2.IsNull())
2328     Standard_NullObject::Raise
2329       ("MakePipe aborted: vector is not defined");
2330   gp_Vec aVec(BRep_Tool::Pnt(V1), BRep_Tool::Pnt(V2));
2331   gp_Dir BiNormal(aVec);
2332   PipeBuilder.SetMode(BiNormal);
2333   PipeBuilder.Build();
2334   if (aShapeBase.ShapeType() == TopAbs_FACE) {
2335       PipeBuilder.MakeSolid();
2336   }
2337
2338   return PipeBuilder.Shape();
2339 }
2340
2341 //=======================================================================
2342 //function : Execute
2343 //purpose  :
2344 //=======================================================================
2345 Standard_Integer GEOMImpl_PipeDriver::Execute (TFunction_Logbook& log) const
2346 {
2347   if (Label().IsNull()) return 0;
2348   Handle(GEOM_Function) aFunction = GEOM_Function::GetFunction(Label());
2349   Standard_Integer aType = aFunction->GetType();
2350
2351   GEOMImpl_IPipe* aCI = 0;
2352   if (aType == PIPE_BASE_PATH)
2353     aCI = new GEOMImpl_IPipe (aFunction);
2354   else if (aType == PIPE_DIFFERENT_SECTIONS)
2355     aCI = new GEOMImpl_IPipeDiffSect (aFunction);
2356   else if (aType == PIPE_SHELL_SECTIONS)
2357     aCI = new GEOMImpl_IPipeShellSect (aFunction);
2358   else if (aType == PIPE_SHELLS_WITHOUT_PATH)
2359     aCI = new GEOMImpl_IPipeShellSect (aFunction);
2360   else if (aType == PIPE_BI_NORMAL_ALONG_VECTOR)
2361     aCI = new GEOMImpl_IPipeBiNormal (aFunction);
2362   else
2363     return 0;
2364
2365   TopoDS_Wire aWirePath;
2366   if (aType != PIPE_SHELLS_WITHOUT_PATH) {
2367     // working with path
2368     Handle(GEOM_Function) aRefPath = aCI->GetPath();
2369     TopoDS_Shape aShapePath = aRefPath->GetValue();
2370
2371     if (aShapePath.IsNull()) {
2372       MESSAGE ("Driver : path is null");
2373       if (aCI) delete aCI;
2374       Standard_NullObject::Raise("MakePipe aborted : null path argument");
2375     }
2376
2377     // Get path contour
2378     bool isOk = false;
2379     if (aShapePath.ShapeType() == TopAbs_COMPOUND) {
2380       TopTools_SequenceOfShape anEdges;
2381       TopExp_Explorer anExp;
2382       BRep_Builder B;
2383       TopoDS_Wire W;
2384       B.MakeWire(W);
2385       for (anExp.Init(aShapePath, TopAbs_EDGE); anExp.More(); anExp.Next()) {
2386         B.Add(W, anExp.Current());
2387         isOk = true;
2388       }
2389       if (isOk)
2390         aWirePath = W;
2391     }
2392     else if (aShapePath.ShapeType() == TopAbs_WIRE) {
2393       aWirePath = TopoDS::Wire(aShapePath);
2394       isOk = true;
2395     }
2396     else {
2397       if (aShapePath.ShapeType() == TopAbs_EDGE) {
2398         TopoDS_Edge anEdge = TopoDS::Edge(aShapePath);
2399         aWirePath = BRepBuilderAPI_MakeWire(anEdge);
2400         isOk = true;
2401       }
2402     }
2403     if (!isOk) {
2404       if (aCI) delete aCI;
2405       Standard_TypeMismatch::Raise("MakePipe aborted : path shape is neither a wire nor an edge");
2406     }
2407   }
2408
2409   TopoDS_Shape aShape;
2410
2411   if (aType == PIPE_BASE_PATH) {
2412     Handle(GEOM_Function) aRefBase = aCI->GetBase();
2413     TopoDS_Shape aShapeBase;
2414
2415     // Make copy to prevent modifying of base object 0020766 : EDF 1320
2416     BRepBuilderAPI_Copy Copy(aRefBase->GetValue());
2417     if (Copy.IsDone())
2418       aShapeBase = Copy.Shape();
2419
2420     if (aShapeBase.IsNull()) {
2421       if (aCI) delete aCI;
2422       Standard_NullObject::Raise("MakePipe aborted : null base argument");
2423     }
2424
2425     // Make pipe
2426     if (aShapeBase.ShapeType() == TopAbs_EDGE ||
2427         aShapeBase.ShapeType() == TopAbs_WIRE)
2428     {
2429       TopoDS_Wire Profile;
2430       if (aShapeBase.ShapeType() == TopAbs_WIRE)
2431         Profile = TopoDS::Wire(aShapeBase);
2432       else
2433       {
2434         BRep_Builder BB;
2435         BB.MakeWire(Profile);
2436         BB.Add(Profile, aShapeBase);
2437       }
2438
2439       BRepOffsetAPI_MakePipeShell Sweep (aWirePath);
2440       BRepBuilderAPI_MakeFace FaceBuilder (aWirePath, Standard_True); //to find the plane of spine
2441       if (FaceBuilder.IsDone())
2442         Sweep.SetMode(FaceBuilder.Face());
2443       Sweep.Add(Profile);
2444       Sweep.Build();
2445       
2446       if (!Sweep.IsDone())
2447       {
2448         if (aCI) delete aCI;
2449         Standard_ConstructionError::Raise("MakePipeShell failed");
2450       }
2451       else
2452         aShape = Sweep.Shape(); //result is good
2453       
2454     }
2455     else
2456     {
2457       GeomFill_Trihedron theBestMode = EvaluateBestSweepMode(aWirePath);
2458       aShape = BRepOffsetAPI_MakePipe(aWirePath, aShapeBase, theBestMode);
2459     }
2460   }
2461
2462   //building pipe with different sections
2463   else if (aType == PIPE_DIFFERENT_SECTIONS) {
2464     GEOMImpl_IPipeDiffSect* aCIDS = (GEOMImpl_IPipeDiffSect*)aCI;
2465     Handle(TColStd_HSequenceOfTransient) aBasesObjs = aCIDS->GetBases ();
2466     Handle(TColStd_HSequenceOfTransient) aLocObjs = aCIDS->GetLocations ();
2467     Standard_Boolean aWithContact = (aCIDS->GetWithContactMode());
2468     Standard_Boolean aWithCorrect = (aCIDS->GetWithCorrectionMode());
2469     if (aCI) {
2470       delete aCI;
2471       aCI = 0;
2472     }
2473
2474     Standard_Integer nbBases = aBasesObjs->Length();
2475     Standard_Integer nbLocs  = (aLocObjs.IsNull() ? 0 : aLocObjs->Length());
2476
2477     Handle(TopTools_HSequenceOfShape) aHSeqBases = new TopTools_HSequenceOfShape;
2478     Handle(TopTools_HSequenceOfShape) aHSeqLocs  = new TopTools_HSequenceOfShape;
2479     Standard_Integer i;
2480
2481     for (i = 1; i <= nbBases; i++) {
2482       Handle(Standard_Transient) anItem = aBasesObjs->Value(i);
2483       if (anItem.IsNull())
2484         continue;
2485       Handle(GEOM_Function) aRefBase = Handle(GEOM_Function)::DownCast(anItem);
2486       if (aRefBase.IsNull())
2487         continue;
2488       if (aRefBase->GetValue().IsNull())
2489         continue;
2490
2491       aHSeqBases->Append(aRefBase->GetValue());
2492     }
2493     for (i = 1; i <= nbLocs; i++) {
2494       Handle(Standard_Transient) anItemLoc = aLocObjs->Value(i);
2495       if (anItemLoc.IsNull())
2496         continue;
2497       Handle(GEOM_Function) aRefLoc = Handle(GEOM_Function)::DownCast(anItemLoc);
2498       TopoDS_Shape aShapeLoc = aRefLoc->GetValue();
2499       if (aShapeLoc.IsNull() || aShapeLoc.ShapeType() != TopAbs_VERTEX)
2500         continue;
2501
2502       aHSeqLocs->Append(aShapeLoc);
2503     }
2504
2505     aShape = CreatePipeWithDifferentSections(aWirePath, aHSeqBases, aHSeqLocs, aWithContact, aWithCorrect);
2506   }
2507
2508   //building pipe with shell sections
2509   else if (aType == PIPE_SHELL_SECTIONS) {
2510     aShape = CreatePipeForShellSections(aWirePath,aCI);
2511   }
2512
2513   //building pipe shell sections without path
2514   else if (aType == PIPE_SHELLS_WITHOUT_PATH) {
2515     aShape = CreatePipeShellsWithoutPath(aCI);
2516   }
2517
2518   //building a pipe with constant bi-normal along given vector
2519   else if (aType == PIPE_BI_NORMAL_ALONG_VECTOR) {
2520     aShape = CreatePipeBiNormalAlongVector(aWirePath, aCI);
2521   }
2522
2523   if (aCI) {
2524     delete aCI;
2525     aCI = 0;
2526   }
2527
2528   if (aShape.IsNull()) return 0;
2529
2530   BRepCheck_Analyzer ana (aShape, Standard_False);
2531   if (!ana.IsValid()) {
2532     ShapeFix_ShapeTolerance aSFT;
2533     aSFT.LimitTolerance(aShape,Precision::Confusion(),Precision::Confusion());
2534     Handle(ShapeFix_Shape) aSfs = new ShapeFix_Shape(aShape);
2535     aSfs->SetPrecision(Precision::Confusion());
2536     aSfs->Perform();
2537     aShape = aSfs->Shape();
2538
2539     ana.Init(aShape, Standard_False);
2540     if (!ana.IsValid())
2541       Standard_ConstructionError::Raise("Algorithm have produced an invalid shape result");
2542   }
2543
2544   if (aType != PIPE_BASE_PATH &&
2545       aType != PIPE_SHELLS_WITHOUT_PATH) {
2546     TopExp_Explorer anExpV (aShape, TopAbs_VERTEX);
2547     if (anExpV.More()) {
2548       Standard_Real aVertMaxTol = -RealLast();
2549       for (; anExpV.More(); anExpV.Next()) {
2550         TopoDS_Vertex aVertex = TopoDS::Vertex(anExpV.Current());
2551         Standard_Real aTol = BRep_Tool::Tolerance(aVertex);
2552         if (aTol > aVertMaxTol)
2553           aVertMaxTol = aTol;
2554       }
2555       aVertMaxTol += Precision::Confusion();
2556       aShape = GEOMImpl_GlueDriver::GlueFaces(aShape, aVertMaxTol, Standard_True);
2557       //aShape = GEOMImpl_GlueDriver::GlueFaces(aShape, Precision::Confusion(), Standard_True);
2558     }
2559   }
2560
2561   TopoDS_Shape aRes = GEOMUtils::CompsolidToCompound(aShape);
2562   aFunction->SetValue(aRes);
2563
2564   log.SetTouched(Label());
2565   return 1;
2566 }
2567
2568 //================================================================================
2569 /*!
2570  * \brief Returns a name of creation operation and names and values of creation parameters
2571  */
2572 //================================================================================
2573
2574 bool GEOMImpl_PipeDriver::
2575 GetCreationInformation(std::string&             theOperationName,
2576                        std::vector<GEOM_Param>& theParams)
2577 {
2578   if (Label().IsNull()) return 0;
2579   Handle(GEOM_Function) function = GEOM_Function::GetFunction(Label());
2580   Standard_Integer aType = function->GetType();
2581
2582   switch ( aType ) {
2583   case PIPE_BASE_PATH:
2584   {
2585     theOperationName = "PIPE";
2586     GEOMImpl_IPipe aCI( function );
2587     AddParam( theParams, "Base Object", aCI.GetBase() );
2588     AddParam( theParams, "Path Object", aCI.GetPath() );
2589     break;
2590   }
2591   case PIPE_BI_NORMAL_ALONG_VECTOR:
2592   {
2593     theOperationName = "PIPE";
2594     GEOMImpl_IPipeBiNormal aCI( function );
2595     AddParam( theParams, "Base Object", aCI.GetBase() );
2596     AddParam( theParams, "Path Object", aCI.GetPath() );
2597     AddParam( theParams, "BiNormal", aCI.GetVector() );
2598     break;
2599   }
2600   case PIPE_DIFFERENT_SECTIONS:
2601   {
2602     theOperationName = "PIPE";
2603     GEOMImpl_IPipeDiffSect aCI( function );
2604     AddParam( theParams, "Bases", aCI.GetBases() );
2605     AddParam( theParams, "Locations", aCI.GetLocations() );
2606     AddParam( theParams, "Path", aCI.GetPath() );
2607     AddParam( theParams, "With contact", aCI.GetWithContactMode() );
2608     AddParam( theParams, "With correction", aCI.GetWithCorrectionMode() );
2609     break;
2610   }
2611   case PIPE_SHELL_SECTIONS:
2612   {
2613     theOperationName = "PIPE";
2614     GEOMImpl_IPipeShellSect aCI( function );
2615     AddParam( theParams, "Bases", aCI.GetBases() );
2616     AddParam( theParams, "Sub-Bases", aCI.GetSubBases() );
2617     AddParam( theParams, "Locations", aCI.GetLocations() );
2618     AddParam( theParams, "Path", aCI.GetPath() );
2619     AddParam( theParams, "With contact", aCI.GetWithContactMode() );
2620     AddParam( theParams, "With correction", aCI.GetWithCorrectionMode() );
2621     break;
2622   }
2623   case PIPE_SHELLS_WITHOUT_PATH:
2624   {
2625     theOperationName = "PIPE"; // MakePipeShellsWithoutPath
2626     GEOMImpl_IPipeShellSect aCI( function );
2627     AddParam( theParams, "Bases", aCI.GetBases() );
2628     AddParam( theParams, "Locations", aCI.GetLocations() );
2629     break;
2630   }
2631   default:
2632     return false;
2633   }
2634   
2635   return true;
2636 }
2637
2638 IMPLEMENT_STANDARD_HANDLE (GEOMImpl_PipeDriver,GEOM_BaseDriver);
2639 IMPLEMENT_STANDARD_RTTIEXT (GEOMImpl_PipeDriver,GEOM_BaseDriver);