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