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