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