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