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