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