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