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