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