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