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