]> SALOME platform Git repositories - modules/geom.git/blob - src/GEOMImpl/GEOMImpl_PipeDriver.cxx
Salome HOME
Merge from BR_siman_phase1 14/02/2013
[modules/geom.git] / src / GEOMImpl / GEOMImpl_PipeDriver.cxx
1 // Copyright (C) 2007-2012  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.
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 #include <GEOMImpl_PipeDriver.hxx>
23
24 #include <GEOMImpl_IPipeDiffSect.hxx>
25 #include <GEOMImpl_IPipeShellSect.hxx>
26 #include <GEOMImpl_IPipeBiNormal.hxx>
27 #include <GEOMImpl_IPipe.hxx>
28 #include <GEOMImpl_IPipePath.hxx>
29 #include <GEOMImpl_GlueDriver.hxx>
30 #include <GEOMImpl_Types.hxx>
31
32 #include <GEOM_Function.hxx>
33
34 #include <GEOMUtils.hxx>
35
36 #include <ShapeAnalysis_FreeBounds.hxx>
37 #include <ShapeAnalysis_Edge.hxx>
38 #include <ShapeFix_Face.hxx>
39 #include <ShapeFix_Shell.hxx>
40 #include <ShapeFix_Shape.hxx>
41 #include <ShapeFix_ShapeTolerance.hxx>
42
43 #include <BRep_Tool.hxx>
44 #include <BRep_Builder.hxx>
45 #include <BRepBuilderAPI_Copy.hxx>
46 #include <BRepBuilderAPI_MakeFace.hxx>
47 #include <BRepBuilderAPI_MakeWire.hxx>
48 #include <BRepBuilderAPI_Sewing.hxx>
49 #include <BRepCheck_Analyzer.hxx>
50 #include <BRepGProp.hxx>
51 #include <BRepOffsetAPI_MakePipe.hxx>
52 #include <BRepOffsetAPI_MakePipeShell.hxx>
53
54 #include <TopAbs.hxx>
55 #include <TopExp.hxx>
56 #include <TopExp_Explorer.hxx>
57 #include <TopoDS.hxx>
58 #include <TopoDS_Wire.hxx>
59 #include <TopoDS_Edge.hxx>
60 #include <TopoDS_Shape.hxx>
61 #include <TopoDS_Solid.hxx>
62 #include <TopoDS_Shell.hxx>
63 #include <TopoDS_Face.hxx>
64 #include <TopoDS_Compound.hxx>
65 #include <TopTools_SequenceOfShape.hxx>
66 #include <TopTools_HSequenceOfShape.hxx>
67 #include <TopTools_IndexedDataMapOfShapeShape.hxx>
68 #include <TopTools_IndexedDataMapOfShapeListOfShape.hxx>
69 #include <TopTools_ListIteratorOfListOfShape.hxx>
70
71 #include <GProp_GProps.hxx>
72
73 #include <GeomAPI_ProjectPointOnCurve.hxx>
74 #include <GeomAPI_Interpolate.hxx>
75 #include <Geom_TrimmedCurve.hxx>
76 #include <Geom_Plane.hxx>
77 #include <Geom_RectangularTrimmedSurface.hxx>
78 #include <Geom_BezierSurface.hxx>
79 #include <Geom_Line.hxx>
80 #include <Geom_Conic.hxx>
81 #include <Geom_BSplineCurve.hxx>
82 #include <Geom_BSplineSurface.hxx>
83 #include <GeomFill_BSplineCurves.hxx>
84 #include <GeomConvert_ApproxCurve.hxx>
85 #include <GeomConvert.hxx>
86
87 #include <TColgp_SequenceOfPnt.hxx>
88 #include <TColgp_HArray1OfPnt.hxx>
89 #include <TColgp_Array2OfPnt.hxx>
90 #include <TColStd_HSequenceOfTransient.hxx>
91
92 #include <Precision.hxx>
93
94 #include <Standard_NullObject.hxx>
95 #include <Standard_TypeMismatch.hxx>
96 #include <Standard_ConstructionError.hxx>
97
98 #include "utilities.h"
99
100 //////////////////////////////////////////////////////////////////////////
101 // Uncomment below macro to perform gluing in the end of MakePipe operation
102 // as fix of issue 0020207.
103 //////////////////////////////////////////////////////////////////////////
104 //#define GLUE_0020207
105
106
107 //=======================================================================
108 //function : GetID
109 //purpose  :
110 //=======================================================================
111 const Standard_GUID& GEOMImpl_PipeDriver::GetID()
112 {
113   static Standard_GUID aPipeDriver ("FF1BBB19-5D14-4df2-980B-3A668264EA16");
114   return aPipeDriver;
115 }
116
117 //=======================================================================
118 //function : GEOMImpl_PipeDriver
119 //purpose  :
120 //=======================================================================
121 GEOMImpl_PipeDriver::GEOMImpl_PipeDriver()
122 {
123 }
124
125 //=======================================================================
126 //function : FillForOtherEdges
127 //purpose  : auxilary for CreatePipeForShellSections()
128 //=======================================================================
129 static bool FillForOtherEdges(const TopoDS_Shape& F1,
130                               const TopoDS_Shape& E1,
131                               const TopoDS_Shape& V1,
132                               TopTools_IndexedDataMapOfShapeShape& FF)
133 {
134   //cout<<"FillForOtherEdges"<<endl;
135   // find other pairs for vertexes and edges
136   // creating map of vertex edges for both faces
137   TopTools_IndexedDataMapOfShapeListOfShape aMapVertEdge1;
138   TopExp::MapShapesAndAncestors(F1, TopAbs_VERTEX, TopAbs_EDGE, aMapVertEdge1);
139   if (!FF.Contains(F1))
140     MESSAGE("    FillForOtherEdges: map FF not contains key F1");
141   if (!FF.Contains(E1))
142     MESSAGE("    FillForOtherEdges: map FF not contains key E1");
143   if (!FF.Contains(V1))
144     MESSAGE("    FillForOtherEdges: map FF not contains key V1");
145   const TopoDS_Shape& F2 = FF.FindFromKey(F1);
146   const TopoDS_Shape& E2 = FF.FindFromKey(E1);
147   const TopoDS_Shape& V2 = FF.FindFromKey(V1);
148   TopTools_IndexedDataMapOfShapeListOfShape aMapVertEdge2;
149   TopExp::MapShapesAndAncestors(F2, TopAbs_VERTEX, TopAbs_EDGE, aMapVertEdge2);
150
151   TopoDS_Edge ES1 = TopoDS::Edge(E1);
152   TopoDS_Edge ES2 = TopoDS::Edge(E2);
153   TopoDS_Shape VS1 = V1;
154   TopoDS_Shape VS2 = V2;
155
156   ShapeAnalysis_Edge sae;
157   while(1) {
158     if (!aMapVertEdge1.Contains(VS1))
159       MESSAGE ("    FillForOtherEdges: map aMapVertEdge1 not contains key VS1");
160     const TopTools_ListOfShape& aList1 = aMapVertEdge1.FindFromKey(VS1);
161     //TopoDS_Shape E1next;
162     TopTools_ListIteratorOfListOfShape anIter1(aList1);
163     if (anIter1.Value().IsSame(ES1)) {
164       anIter1.Next();
165     }
166     //E1next = anIter1.Value();
167     if (!aMapVertEdge2.Contains(VS2))
168       MESSAGE ("    FillForOtherEdges: map aMapVertEdge2 not contains key VS2");
169     const TopTools_ListOfShape& aList2 = aMapVertEdge2.FindFromKey(VS2);
170     //TopoDS_Shape E2next;
171     TopTools_ListIteratorOfListOfShape anIter2(aList2);
172     if (anIter2.Value().IsSame(ES2)) {
173       anIter2.Next();
174     }
175     //E2next = anIter2.Value();
176     //ES1 = TopoDS::Edge(E1next);
177     //ES2 = TopoDS::Edge(E2next);
178     ES1 = TopoDS::Edge(anIter1.Value());
179     ES2 = TopoDS::Edge(anIter2.Value());
180     if (!FF.Contains(ES1)) {
181       FF.Add(ES1,ES2);
182     }
183     if (VS1.IsSame(sae.FirstVertex(ES1)))
184       VS1 = sae.LastVertex(ES1);
185     else
186       VS1 = sae.FirstVertex(ES1);
187     if (VS2.IsSame(sae.FirstVertex(ES2)))
188       VS2 = sae.LastVertex(ES2);
189     else
190       VS2 = sae.FirstVertex(ES2);
191     if (VS1.IsSame(V1))
192       break;
193     if (!FF.Contains(VS1)) {
194       FF.Add(VS1,VS2);
195     }
196   }
197
198   return true;
199 }
200
201 //=======================================================================
202 //function : FillCorrespondingEdges
203 //purpose  : auxilary for CreatePipeForShellSections()
204 //=======================================================================
205 static bool FillCorrespondingEdges(const TopoDS_Shape& FS1,
206                                    const TopoDS_Shape& FS2,
207                                    const TopoDS_Vertex& aLoc1,
208                                    const TopoDS_Vertex& aLoc2,
209                                    const TopoDS_Wire& aWirePath,
210                                    TopTools_IndexedDataMapOfShapeShape& FF)
211 {
212   //cout<<"FillCorrespondingEdges"<<endl;
213   // find corresponding edges
214   TopExp_Explorer expw1(FS1,TopAbs_WIRE);
215   TopoDS_Wire aWire1 = TopoDS::Wire(expw1.Current());
216   //exp = TopExp_Explorer(FS2,TopAbs_WIRE);
217   TopExp_Explorer expw2(FS2,TopAbs_WIRE);
218   TopoDS_Wire aWire2 = TopoDS::Wire(expw2.Current());
219   BRepOffsetAPI_MakePipeShell aBuilder(aWirePath);
220   aBuilder.Add(aWire1, aLoc1);
221   aBuilder.Add(aWire2, aLoc2);
222   if (!aBuilder.IsReady()) {
223     return false;
224   }
225   aBuilder.Build();
226   TopoDS_Shape aShape = aBuilder.Shape();
227   /*
228   TopoDS_Compound C;
229   BRep_Builder B;
230   B.MakeCompound(C);
231   B.Add(C,aShape);
232   B.Add(C,FS1);
233   B.Add(C,FS2);
234   BRepTools::Write(C,"/dn02/users_Linux/skl/work/Bugs/14857/comp.brep");
235   */
236   ShapeAnalysis_Edge sae;
237   double tol = Max(BRep_Tool::Tolerance(TopoDS::Face(FS1)),
238                     BRep_Tool::Tolerance(TopoDS::Face(FS2)));
239   TopTools_MapOfShape Vs1,Vs2;
240   TopExp_Explorer exp;
241   exp.Init(FS1, TopAbs_EDGE);
242   TopoDS_Edge E1 = TopoDS::Edge(exp.Current());
243   TopoDS_Vertex V11 = sae.FirstVertex(E1);
244   TopoDS_Vertex V21 = sae.LastVertex(E1);
245   gp_Pnt P11 = BRep_Tool::Pnt(V11);
246   gp_Pnt P21 = BRep_Tool::Pnt(V21);
247   //cout<<"P11("<<P11.X()<<","<<P11.Y()<<","<<P11.Z()<<")"<<endl;
248   //cout<<"P21("<<P21.X()<<","<<P21.Y()<<","<<P21.Z()<<")"<<endl;
249   // find corresponding vertexes from created shape
250   TopoDS_Vertex VN11,VN21;
251   for (exp.Init(aShape, TopAbs_VERTEX); exp.More(); exp.Next()) {
252     TopoDS_Vertex V = TopoDS::Vertex(exp.Current());
253     gp_Pnt P = BRep_Tool::Pnt(V);
254     if (P.Distance(P11)<tol) {
255       VN11 = V;
256     }
257     if (P.Distance(P21)<tol) {
258       VN21 = V;
259     }
260   }
261   // find edge contains VN11 and VN21 and corresponding vertexes
262   TopoDS_Vertex VN12,VN22;
263   for (exp.Init(aShape, TopAbs_FACE); exp.More(); exp.Next()) {
264     TopoDS_Shape F = exp.Current();
265     TopExp_Explorer expe;
266     bool IsFind = false;
267     for (expe.Init(F, TopAbs_EDGE); expe.More(); expe.Next()) {
268       TopoDS_Edge E = TopoDS::Edge(expe.Current());
269       TopoDS_Vertex VF = sae.FirstVertex(E);
270       TopoDS_Vertex VL = sae.LastVertex(E);
271       if ((VF.IsSame(VN11) && VL.IsSame(VN21)) || (VF.IsSame(VN21) && VL.IsSame(VN11))) {
272         IsFind = true;
273         break;
274       }
275     }
276     if (IsFind) {
277       for (expe.Init(F, TopAbs_EDGE); expe.More(); expe.Next()) {
278         TopoDS_Edge E = TopoDS::Edge(expe.Current());
279         TopoDS_Vertex VF = sae.FirstVertex(E);
280         TopoDS_Vertex VL = sae.LastVertex(E);
281         if (VF.IsSame(VN11) && !VL.IsSame(VN21))
282           VN12 = VL;
283         if (VL.IsSame(VN11) && !VF.IsSame(VN21))
284           VN12 = VF;
285         if (VF.IsSame(VN21) && !VL.IsSame(VN11))
286           VN22 = VL;
287         if (VL.IsSame(VN21) && !VF.IsSame(VN11))
288           VN22 = VF;
289       }
290       break;
291     }
292   }
293   // find vertexes from FS2 corresponded to VN12 and VN22
294   // and find edge from FS2 contains V12 and V22,
295   // this edge will be corresponded to edge E1
296   TopoDS_Vertex V12,V22;
297   gp_Pnt PN12 = BRep_Tool::Pnt(VN12);
298   gp_Pnt PN22 = BRep_Tool::Pnt(VN22);
299   //cout<<"PN12("<<PN12.X()<<","<<PN12.Y()<<","<<PN12.Z()<<")"<<endl;
300   //cout<<"PN22("<<PN22.X()<<","<<PN22.Y()<<","<<PN22.Z()<<")"<<endl;
301   TopoDS_Edge E2;
302   TopExp_Explorer expe;
303   for (expe.Init(FS2, TopAbs_EDGE); expe.More(); expe.Next()) {
304     TopoDS_Edge E = TopoDS::Edge(expe.Current());
305     TopoDS_Vertex VF = sae.FirstVertex(E);
306     TopoDS_Vertex VL = sae.LastVertex(E);
307     gp_Pnt PF = BRep_Tool::Pnt(VF);
308     gp_Pnt PL = BRep_Tool::Pnt(VL);
309     if (PF.Distance(PN12)<tol && PL.Distance(PN22)<tol) {
310       V12 = VF;
311       V22 = VL;
312       E2 = E;
313       break;
314     }
315     if (PF.Distance(PN22)<tol && PL.Distance(PN12)<tol) {
316       V12 = VL;
317       V22 = VF;
318       E2 = E;
319       break;
320     }
321   }
322   FF.Add(V11,V12);
323   FF.Add(V21,V22);
324   FF.Add(E1,E2);
325
326   // find other pairs for vertexes and edges
327   // creating map of vertex edges for both faces
328   return FillForOtherEdges(FS1,E1,V21,FF);
329
330   //return true;
331 }
332
333 //=======================================================================
334 //function : FillCorrespondingEdges
335 //purpose  : auxilary for CreatePipeShellsWithoutPath()
336 //=======================================================================
337 static bool FillCorrespondingEdges(const TopoDS_Shape& FS1,
338                                    const TopoDS_Shape& FS2,
339                                    const TopoDS_Vertex& aLoc1,
340                                    const TopoDS_Vertex& aLoc2,
341                                    TopTools_IndexedDataMapOfShapeShape& FF)
342 {
343   //cout<<"FillCorrespondingEdges"<<endl;
344
345   gp_Pnt P1 = BRep_Tool::Pnt(aLoc1);
346   gp_Pnt P2 = BRep_Tool::Pnt(aLoc2);
347   gp_Vec aDir(P1,P2);
348
349   ShapeAnalysis_Edge sae;
350   double tol = Max(BRep_Tool::Tolerance(TopoDS::Face(FS1)),
351                     BRep_Tool::Tolerance(TopoDS::Face(FS2)));
352   TopTools_MapOfShape Vs1,Vs2;
353
354   TopoDS_Vertex V11=aLoc1, V12=aLoc2, V21, V22;
355   TopoDS_Edge E1,E2;
356
357   TopExp_Explorer exp1;
358   for (exp1.Init(FS1,TopAbs_EDGE); exp1.More(); exp1.Next()) {
359     E1 = TopoDS::Edge(exp1.Current());
360     TopoDS_Vertex V1 = sae.FirstVertex(E1);
361     TopoDS_Vertex V2 = sae.LastVertex(E1);
362     gp_Pnt Ptmp1 = BRep_Tool::Pnt(V1);
363     gp_Pnt Ptmp2 = BRep_Tool::Pnt(V2);
364     //cout<<"P11("<<P11.X()<<","<<P11.Y()<<","<<P11.Z()<<")"<<endl;
365     //cout<<"P21("<<P21.X()<<","<<P21.Y()<<","<<P21.Z()<<")"<<endl;
366     if (P1.Distance(Ptmp1)<tol) {
367       V21 = V2;
368       break;
369     }
370     if (P1.Distance(Ptmp2)<tol) {
371       V21 = V1;
372       break;
373     }
374   }
375
376   TopoDS_Edge E21,E22;
377   TopoDS_Vertex VE21,VE22;
378   int nbe=0;
379   for (exp1.Init(FS2,TopAbs_EDGE); exp1.More() && nbe<2; exp1.Next()) {
380     TopoDS_Edge E = TopoDS::Edge(exp1.Current());
381     TopoDS_Vertex V1 = sae.FirstVertex(E);
382     TopoDS_Vertex V2 = sae.LastVertex(E);
383     gp_Pnt Ptmp1 = BRep_Tool::Pnt(V1);
384     gp_Pnt Ptmp2 = BRep_Tool::Pnt(V2);
385     if (P2.Distance(Ptmp1)<tol) {
386       if (nbe==0) {
387         E21 = E;
388         VE21 = V2;
389         nbe++;
390       }
391       else if (nbe==1) {
392         E22 = E;
393         VE22 = V2;
394         nbe++;
395       }
396     }
397     if (P2.Distance(Ptmp2)<tol) {
398       if (nbe==0) {
399         E21 = E;
400         VE21 = V1;
401         nbe++;
402       }
403       else if (nbe==1) {
404         E22 = E;
405         VE22 = V1;
406         nbe++;
407       }
408     }
409   }
410
411   gp_Pnt PV21 = BRep_Tool::Pnt(V21);
412   gp_Pnt PE21 = BRep_Tool::Pnt(VE21);
413   gp_Pnt PE22 = BRep_Tool::Pnt(VE22);
414   gp_Vec aDir1(PV21,PE21);
415   gp_Vec aDir2(PV21,PE22);
416   double ang1 = aDir.Angle(aDir1);
417   double ang2 = aDir.Angle(aDir2);
418   if (fabs(ang1)<fabs(ang2)) {
419     E2 = E21;
420     V22 = VE21;
421   }
422   else {
423     E2 = E22;
424     V22 = VE22;
425   }
426
427   FF.Add(V11,V12);
428   FF.Add(V21,V22);
429   FF.Add(E1,E2);
430
431   // find other pairs for vertexes and edges
432   return FillForOtherEdges(FS1,E1,V21,FF);
433 }
434
435 //=======================================================================
436 //function : FindNextPairOfFaces
437 //purpose  : auxilary for CreatePipeForShellSections()
438 //=======================================================================
439 static void FindNextPairOfFaces(const TopoDS_Shape& aCurFace,
440                                 TopTools_IndexedDataMapOfShapeListOfShape& aMapEdgeFaces1,
441                                 TopTools_IndexedDataMapOfShapeListOfShape& aMapEdgeFaces2,
442                                 TopTools_IndexedDataMapOfShapeShape& FF,
443                                 GEOMImpl_IPipe* aCI)
444 {
445   //cout<<"FindNextPairOfFaces"<<endl;
446   TopExp_Explorer anExp;
447   for (anExp.Init(aCurFace, TopAbs_EDGE); anExp.More(); anExp.Next()) {
448     TopoDS_Shape E1 = anExp.Current();
449     if (!FF.Contains(E1)) {
450       if (aCI) delete aCI;
451       Standard_ConstructionError::Raise("FindNextPairOfFaces: Can not find edge in map");
452     }
453     if (!FF.Contains(E1))
454       MESSAGE ("    FindNextPairOfFaces: map FF not contains key E1");
455     const TopoDS_Shape& E2 = FF.FindFromKey(E1);
456     TopExp_Explorer anExpV;
457     anExpV.Init(E1, TopAbs_VERTEX);
458     TopoDS_Shape V1 = anExpV.Current();
459     if (!FF.Contains(V1)) {
460       if (aCI) delete aCI;
461       Standard_ConstructionError::Raise("FindNextPairOfFaces: Can not find vertex in map");
462     }
463
464     if (!aMapEdgeFaces1.Contains(E1))
465       MESSAGE ("    FindNextPairOfFaces: map aMapEdgeFaces1 not contains key E1");
466     const TopTools_ListOfShape& aList1 = aMapEdgeFaces1.FindFromKey(E1);
467     if (aList1.Extent()<2)
468       continue;
469     TopTools_ListIteratorOfListOfShape anIter(aList1);
470     if (anIter.Value().IsEqual(aCurFace)) {
471       anIter.Next();
472     }
473     TopoDS_Shape F1other = anIter.Value();
474     if (FF.Contains(F1other))
475       continue;
476
477     if (!FF.Contains(aCurFace))
478       MESSAGE ("    FindNextPairOfFaces: map FF not contains key aCurFace");
479     const TopoDS_Shape& F2 = FF.FindFromKey(aCurFace);
480     if (!aMapEdgeFaces2.Contains(E2))
481       MESSAGE ("    FindNextPairOfFaces: map aMapEdgeFaces2 not contains key E2");
482     const TopTools_ListOfShape& aList2 = aMapEdgeFaces2.FindFromKey(E2);
483     if (aList2.Extent()<2) {
484       if (aCI) delete aCI;
485       Standard_ConstructionError::Raise("FindNextPairOfFaces: Can not find corresponding face");
486     }
487     TopTools_ListIteratorOfListOfShape anIter2(aList2);
488     if (anIter2.Value().IsEqual(F2)) {
489       anIter2.Next();
490     }
491     TopoDS_Shape F2other = anIter2.Value();
492     FF.Add(F1other,F2other);
493
494     // add pairs of edges to FF
495     bool stat =  FillForOtherEdges(F1other,E1,V1,FF);
496     if (!stat) {
497       if (aCI) delete aCI;
498       Standard_ConstructionError::Raise("FindNextPairOfFaces: Can not mapping other egdes");
499     }
500
501     FindNextPairOfFaces(F1other, aMapEdgeFaces1, aMapEdgeFaces2, FF, aCI);
502   }
503 }
504
505 //=======================================================================
506 //function : FindFirstPairFaces
507 //purpose  : auxilary for Execute()
508 //=======================================================================
509 static void FindFirstPairFaces(const TopoDS_Shape& S1, const TopoDS_Shape& S2,
510                                TopoDS_Vertex& V1, TopoDS_Vertex& V2,
511                                TopoDS_Shape& FS1, TopoDS_Shape& FS2)
512 {
513   //cout<<"FindFirstPairFaces"<<endl;
514
515   // check if vertexes are sub-shapes of sections
516   gp_Pnt P1 = BRep_Tool::Pnt(V1);
517   gp_Pnt P2 = BRep_Tool::Pnt(V2);
518   TopoDS_Vertex V1new,V2new;
519   TopExp_Explorer exp;
520   double mindist = 1.e10;
521   for (exp.Init(S1, TopAbs_VERTEX); exp.More(); exp.Next()) {
522     TopoDS_Vertex V = TopoDS::Vertex(exp.Current());
523     gp_Pnt P = BRep_Tool::Pnt(V);
524     double dist = P1.Distance(P);
525     if (dist<mindist) {
526       mindist = dist;
527       V1new = V;
528     }
529   }
530   mindist = 1.e10;
531   for (exp.Init(S2, TopAbs_VERTEX); exp.More(); exp.Next()) {
532     TopoDS_Vertex V = TopoDS::Vertex(exp.Current());
533     gp_Pnt P = BRep_Tool::Pnt(V);
534     double dist = P2.Distance(P);
535     if (dist<mindist) {
536       mindist = dist;
537       V2new = V;
538     }
539   }
540
541   //gp_Pnt P1new = BRep_Tool::Pnt(V1new);
542   //gp_Pnt P2new = BRep_Tool::Pnt(V2new);
543   //cout<<"  P1("<<P1.X()<<","<<P1.Y()<<","<<P1.Z()<<")"<<endl;
544   //cout<<"  P2("<<P2.X()<<","<<P2.Y()<<","<<P2.Z()<<")"<<endl;
545   //cout<<"  P1new("<<P1new.X()<<","<<P1new.Y()<<","<<P1new.Z()<<")"<<endl;
546   //cout<<"  P2new("<<P2new.X()<<","<<P2new.Y()<<","<<P2new.Z()<<")"<<endl;
547
548   // replace vertexes if it is needed
549   if (!V1.IsSame(V1new)) {
550     V1 = V1new;
551     P1 = BRep_Tool::Pnt(V1);
552     MESSAGE ("  replace V1");
553   }
554   else
555     MESSAGE ("  not replace V1");
556   if (!V2.IsSame(V2new)) {
557     V2 = V2new;
558     P2 = BRep_Tool::Pnt(V2);
559     MESSAGE ("  replace V2");
560   }
561   else
562     MESSAGE ("  not replace V2");
563
564   TopTools_IndexedDataMapOfShapeListOfShape aMapVertFaces1;
565   TopExp::MapShapesAndAncestors(S1, TopAbs_VERTEX, TopAbs_FACE, aMapVertFaces1);
566   TopTools_IndexedDataMapOfShapeListOfShape aMapVertFaces2;
567   TopExp::MapShapesAndAncestors(S2, TopAbs_VERTEX, TopAbs_FACE, aMapVertFaces2);
568
569   if (!aMapVertFaces1.Contains(V1))
570     MESSAGE ("    FindFirstPairFaces: map aMapVertFaces1 not contains key V1");
571   const TopTools_ListOfShape& aList1 = aMapVertFaces1.FindFromKey(V1);
572   TopTools_ListIteratorOfListOfShape anIter1(aList1);
573   FS1 = anIter1.Value();
574   // find middle point
575   double x1=0., y1=0., z1=0.;
576   int nbv1=0;
577   for (exp.Init(FS1, TopAbs_VERTEX); exp.More(); exp.Next()) {
578     TopoDS_Vertex V = TopoDS::Vertex(exp.Current());
579     gp_Pnt P = BRep_Tool::Pnt(V);
580     x1 += P.X();
581     y1 += P.Y();
582     z1 += P.Z();
583     nbv1++;
584   }
585   gp_Pnt PM1(x1/nbv1, y1/nbv1, z1/nbv1);
586
587   TColgp_SequenceOfPnt Ps;
588   TopTools_SequenceOfShape Fs;
589   if (!aMapVertFaces2.Contains(V2))
590     MESSAGE ("    FindFirstPairFaces: map aMapVertFaces2 not contains key V2");
591   const TopTools_ListOfShape& aList2 = aMapVertFaces2.FindFromKey(V2);
592   TopTools_ListIteratorOfListOfShape anIter2(aList2);
593   for (; anIter2.More(); anIter2.Next()) {
594     TopoDS_Shape F = anIter2.Value();
595     double x2=0., y2=0., z2=0.;
596     int nbv2=0;
597     for (exp.Init(F, TopAbs_VERTEX); exp.More(); exp.Next()) {
598       TopoDS_Vertex V = TopoDS::Vertex(exp.Current());
599       gp_Pnt P = BRep_Tool::Pnt(V);
600       x2 += P.X();
601       y2 += P.Y();
602       z2 += P.Z();
603       nbv2++;
604     }
605     gp_Pnt PM(x2/nbv1, y2/nbv1, z2/nbv1);
606     Fs.Append(F);
607     Ps.Append(PM);
608   }
609
610   gp_Vec aDir(P1,P2);
611   int i=1;
612   double MinAng = M_PI;
613   int numface = 0;
614   for (; i<=Fs.Length(); i++) {
615     gp_Vec tmpDir(PM1,Ps(i));
616     double ang = fabs(aDir.Angle(tmpDir));
617     if (ang<MinAng) {
618       MinAng = ang;
619       numface = i;
620     }
621   }
622   FS2 = Fs(numface);
623 }
624
625 //=======================================================================
626 //function : CreatePipeWithDifferentSections
627 //purpose  :
628 //=======================================================================
629 TopoDS_Shape GEOMImpl_PipeDriver::CreatePipeWithDifferentSections
630                                   (const TopoDS_Wire& theWirePath,
631                                    const Handle(TopTools_HSequenceOfShape) theHSeqBases,
632                                    const Handle(TopTools_HSequenceOfShape) theHSeqLocs,
633                                    const Standard_Boolean theWithContact,
634                                    const Standard_Boolean theWithCorrect)
635 {
636   TopoDS_Shape aShape;
637
638   TopoDS_Wire aWirePath = theWirePath;
639
640   Standard_Integer nbBases = theHSeqBases->Length();
641   Standard_Integer nbLocs = (theHSeqLocs.IsNull() ? 0 : theHSeqLocs->Length());
642
643   if (nbLocs && nbLocs != nbBases) {
644     Standard_ConstructionError::Raise("Number of sections is not equal to number of locations ");
645   }
646
647   TopTools_SequenceOfShape aSeqBases;
648   TopTools_SequenceOfShape aSeqLocs;
649   TopTools_SequenceOfShape aSeqFaces;
650
651   Standard_Integer i = 1;
652   for (i = 1; i <= nbBases; i++) {
653     if (theHSeqBases->Value(i).IsNull())
654       continue;
655
656     // Make copy to prevent modifying of base object 0020766 : EDF 1320
657     TopoDS_Shape aShapeBase;
658     BRepBuilderAPI_Copy Copy (theHSeqBases->Value(i));
659     if (Copy.IsDone())
660       aShapeBase = Copy.Shape();
661
662     TopAbs_ShapeEnum aTypeBase = aShapeBase.ShapeType();
663
664     //if for section was specified face with a few wires then a few
665     //    pipes were build and make solid
666     Standard_Boolean NeedCreateSolid = Standard_False;
667     if (aTypeBase == TopAbs_SHELL) {
668       // create wire as boundary contour if shell is no closed
669       // get free boundary shapes
670       ShapeAnalysis_FreeBounds anAnalizer(aShapeBase);
671       TopoDS_Compound aClosed = anAnalizer.GetClosedWires();
672       TopExp_Explorer anExp;
673       TopoDS_Shape aWire;
674       Standard_Integer NbWires = 0;
675       for (anExp.Init(aClosed, TopAbs_WIRE); anExp.More(); anExp.Next()) {
676         NbWires++;
677         aWire = anExp.Current();
678       }
679       if (NbWires != 1) {
680         // bad case
681         Standard_ConstructionError::Raise("Bad shell is used as section ");
682       }
683       NeedCreateSolid = Standard_True;
684       aSeqFaces.Append(aShapeBase);
685       aSeqBases.Append(aWire);
686     }
687     else if (aTypeBase == TopAbs_FACE) {
688       NeedCreateSolid = Standard_True;
689       //for case one path should be used other type function
690       aSeqFaces.Append(aShapeBase);
691       TopExp_Explorer aExpW(aShapeBase,TopAbs_WIRE);
692       for (; aExpW.More(); aExpW.Next()) {
693         TopoDS_Shape aWireProf = aExpW.Current();
694         aSeqBases.Append(aWireProf);
695       }
696     }
697     else if (aTypeBase == TopAbs_WIRE || aTypeBase == TopAbs_VERTEX) {
698       aSeqBases.Append(aShapeBase);
699     }
700     else if (aTypeBase == TopAbs_EDGE) {
701       TopoDS_Edge anEdge = TopoDS::Edge(aShapeBase);
702       TopoDS_Shape aWireProf = BRepBuilderAPI_MakeWire(anEdge);
703       aSeqBases.Append(aWireProf);
704     }
705     if (nbLocs) {
706       TopoDS_Shape aShapeLoc = theHSeqLocs->Value(i);
707       if (aShapeLoc.IsNull() || aShapeLoc.ShapeType() != TopAbs_VERTEX)
708         continue;
709       aSeqLocs.Append(aShapeLoc);
710     }
711   }
712
713   nbLocs = aSeqLocs.Length();
714
715   // skl 02.05.2007
716   TopTools_SequenceOfShape Edges;
717   if (nbLocs > 0) {
718     // we have to check that each location shape is a vertex from
719     // path and update aSeqLocs if it is needed (and possible)
720     TColgp_SequenceOfPnt PLocs;
721     for (i=1; i<=nbLocs; i++) {
722       TopoDS_Vertex V = TopoDS::Vertex(aSeqLocs.Value(i));
723       PLocs.Append(BRep_Tool::Pnt(V));
724     }
725     //TopTools_SequenceOfShape Edges;
726     TopExp_Explorer anExp;
727     for (anExp.Init(aWirePath, TopAbs_EDGE); anExp.More(); anExp.Next()) {
728       Edges.Append(anExp.Current());
729     }
730     int nbEdges = Edges.Length();
731     ShapeAnalysis_Edge sae;
732     TopoDS_Edge edge = TopoDS::Edge(Edges.First());
733     double tol = BRep_Tool::Tolerance(edge);
734     TopoDS_Vertex VF = sae.FirstVertex(edge);
735     gp_Pnt PF = BRep_Tool::Pnt(VF);
736     //cout<<"PF("<<PF.X()<<","<<PF.Y()<<","<<PF.Z()<<")"<<endl;
737     if (PF.Distance(PLocs.First()) > tol) {
738       Standard_ConstructionError::Raise
739         ("First location shapes is not coincided with first vertex of aWirePath");
740     }
741     aSeqLocs.ChangeValue(1) = VF;
742     edge = TopoDS::Edge(Edges.Last());
743     tol = BRep_Tool::Tolerance(edge);
744     TopoDS_Vertex VL = sae.LastVertex(edge);
745     gp_Pnt PL = BRep_Tool::Pnt(VL);
746     if (PL.Distance(PLocs.Last()) > tol) {
747       Standard_ConstructionError::Raise
748         ("Last location shapes is not coincided with last vertex of aWirePath");
749     }
750     aSeqLocs.ChangeValue(nbLocs) = VL;
751     int jcurr = 2;
752     for (i=1; i<=Edges.Length() && jcurr<nbLocs; i++) {
753       TopoDS_Edge E = TopoDS::Edge(Edges.Value(i));
754       tol = BRep_Tool::Tolerance(edge);
755       TopoDS_Vertex V1 = sae.FirstVertex(E);
756       TopoDS_Vertex V2 = sae.LastVertex(E);
757       gp_Pnt P1 = BRep_Tool::Pnt(V1);
758       gp_Pnt P2 = BRep_Tool::Pnt(V2);
759       if (P2.Distance(PLocs.Value(jcurr)) < tol) {
760         aSeqLocs.ChangeValue(jcurr) = V2;
761         jcurr++;
762       }
763       else {
764         // find distance between E and aLocs(jcurr)
765         double fp,lp;
766         Handle(Geom_Curve) C = BRep_Tool::Curve(E,fp,lp);
767         GeomAPI_ProjectPointOnCurve PPCurve (PLocs.Value(jcurr),C);
768         if (PPCurve.NbPoints()>0 &&
769             PLocs.Value(jcurr).Distance(PPCurve.Point(1)) < tol) {
770           double param = PPCurve.Parameter(1);
771           gp_Pnt PC1;
772           C->D0(param,PC1);
773           // split current edge
774           Handle(Geom_TrimmedCurve) tc1 = new Geom_TrimmedCurve(C,fp,param);
775           Handle(Geom_TrimmedCurve) tc2 = new Geom_TrimmedCurve(C,param,lp);
776           TopoDS_Edge E1,E2;
777           BRep_Builder B;
778           gp_Pnt Pfp;
779           C->D0(fp,Pfp);
780           if (Pfp.Distance(P1)<tol) {
781             B.MakeEdge(E1,tc1,tol);
782             B.Add(E1,V1);
783             TopoDS_Shape tmpV = aSeqLocs.Value(jcurr).Oriented(TopAbs_REVERSED);
784             B.Add(E1,TopoDS::Vertex(tmpV));
785             B.MakeEdge(E2,tc2,tol);
786             tmpV = aSeqLocs.Value(jcurr).Oriented(TopAbs_FORWARD);
787             B.Add(E2,TopoDS::Vertex(tmpV));
788             B.Add(E2,V2);
789           }
790           else {
791             B.MakeEdge(E1,tc2,tol);
792             TopoDS_Shape tmpV = aSeqLocs.Value(jcurr).Oriented(TopAbs_FORWARD);
793             B.Add(E1,TopoDS::Vertex(tmpV));
794             B.Add(E1,V1);
795             E1.Reverse();
796             B.MakeEdge(E2,tc1,tol);
797             B.Add(E2,V2);
798             tmpV = aSeqLocs.Value(jcurr).Oriented(TopAbs_REVERSED);
799             B.Add(E2,TopoDS::Vertex(tmpV));
800             E2.Reverse();
801           }
802           jcurr++;
803           Edges.Remove(i);
804           Edges.InsertAfter(i-1,E1);
805           Edges.InsertAfter(i,E2);
806         }
807       }
808     }
809     if (nbEdges<Edges.Length()) {
810         // one of edges was splitted => we have to update WirePath
811         BRep_Builder B;
812         TopoDS_Wire W;
813         B.MakeWire(W);
814         for (i=1; i<=Edges.Length(); i++) {
815           B.Add(W,TopoDS::Edge(Edges.Value(i)));
816         }
817         aWirePath = W;
818     }
819   }
820
821   // check curvature of wire for condition that
822   // max summary angle between directions along
823   // wire path must be < 4*PI. If not - split wire
824   // and seguences of shapes, perform pipe for each
825   // and make sewing after that
826   double fp,lp;
827   Handle(Geom_Curve) C = BRep_Tool::Curve(TopoDS::Edge(Edges.Value(1)),fp,lp);
828   gp_Pnt P1,P2;
829   gp_Vec Vec1,Vec2;
830   C->D1(fp,P1,Vec1);
831   C->D1(lp,P2,Vec2);
832   double SumAng = fabs(Vec1.Angle(Vec2));
833   Vec1 = Vec2;
834   P1 = P2;
835   TColStd_SequenceOfInteger SplitEdgeNums,SplitLocNums;
836   int LastLoc = 1;
837   //cout<<"Edges.Length()="<<Edges.Length()<<endl;
838   for (i=2; i<=Edges.Length(); i++) {
839       TopoDS_Edge edge = TopoDS::Edge(Edges.Value(i));
840       double tol = BRep_Tool::Tolerance(edge);
841       Handle(Geom_Curve) C = BRep_Tool::Curve(edge,fp,lp);
842       C->D1(lp,P2,Vec2);
843       double ang = fabs(Vec1.Angle(Vec2));
844       SumAng += ang;
845       if (SumAng>4*M_PI) {
846         SumAng = ang;
847         SplitEdgeNums.Append(i-1);
848         int j;
849         for (j=LastLoc+1; j<=aSeqLocs.Length(); j++) {
850           TopoDS_Vertex aVert = TopoDS::Vertex(aSeqLocs.Value(j));
851           gp_Pnt P = BRep_Tool::Pnt(aVert);
852           if (P1.Distance(P) < tol) {
853             SplitLocNums.Append(j);
854             LastLoc = j;
855             break;
856           }
857         }
858       }
859       Vec1 = Vec2;
860       P1 = P2;
861   }
862
863   if (SplitLocNums.Length()==SplitEdgeNums.Length() && SplitEdgeNums.Length()>0) {
864       TopTools_SequenceOfShape aSeqRes;
865       int nn, num1 = 1, num2 = 1;
866       for (nn=1; nn<=SplitEdgeNums.Length(); nn++) {
867         // create wirepath and sequences of shapes
868         BRep_Builder B;
869         TopoDS_Wire tmpW;
870         B.MakeWire(tmpW);
871         for (i=num1; i<=SplitEdgeNums.Value(nn); i++) {
872           B.Add(tmpW,TopoDS::Edge(Edges.Value(i)));
873         }
874         num1 = SplitEdgeNums.Value(nn) + 1;
875         TopTools_SequenceOfShape aTmpSeqBases;
876         TopTools_SequenceOfShape aTmpSeqLocs;
877         for (i=num2; i<=SplitLocNums.Value(nn); i++) {
878           aTmpSeqBases.Append(aSeqBases.Value(i));
879           aTmpSeqLocs.Append(aSeqLocs.Value(i));
880         }
881         num2 = SplitLocNums.Value(nn);
882         // make pipe
883         BRepOffsetAPI_MakePipeShell aBuilder(tmpW);
884         Standard_Integer nbShapes = aTmpSeqBases.Length();
885         for (i=1; i<=nbShapes; i++) {
886           TopoDS_Shape aShapeLoc = aTmpSeqLocs.Value(i);
887           TopoDS_Vertex aVert = TopoDS::Vertex(aShapeLoc);
888           aBuilder.Add(aTmpSeqBases.Value(i), aVert, theWithContact, theWithCorrect);
889         }
890         if (!aBuilder.IsReady()) {
891           Standard_ConstructionError::Raise("Invalid input data for building PIPE: bases are invalid");
892         }
893         aBuilder.Build();
894         TopoDS_Shape resShape = aBuilder.Shape();
895         aSeqRes.Append(resShape);
896       }
897       // create wirepath and sequences of shapes for last part
898       BRep_Builder B;
899       TopoDS_Wire tmpW;
900       B.MakeWire(tmpW);
901       for (i=num1; i<=Edges.Length(); i++) {
902         B.Add(tmpW,TopoDS::Edge(Edges.Value(i)));
903       }
904       TopTools_SequenceOfShape aTmpSeqBases;
905       TopTools_SequenceOfShape aTmpSeqLocs;
906       for (i=num2; i<=aSeqLocs.Length(); i++) {
907         aTmpSeqBases.Append(aSeqBases.Value(i));
908         aTmpSeqLocs.Append(aSeqLocs.Value(i));
909       }
910       // make pipe for last part
911       BRepOffsetAPI_MakePipeShell aBuilder(tmpW);
912       Standard_Integer nbShapes = aTmpSeqBases.Length();
913       for (i=1; i<=nbShapes; i++) {
914         TopoDS_Shape aShapeLoc = aTmpSeqLocs.Value(i);
915         TopoDS_Vertex aVert = TopoDS::Vertex(aShapeLoc);
916         aBuilder.Add(aTmpSeqBases.Value(i), aVert, theWithContact, theWithCorrect);
917       }
918       if (!aBuilder.IsReady()) {
919         Standard_ConstructionError::Raise("Invalid input data for building PIPE: bases are invalid");
920       }
921       aBuilder.Build();
922       TopoDS_Shape resShape = aBuilder.Shape();
923       aSeqRes.Append(resShape);
924       // make sewing for result
925       Handle(BRepBuilderAPI_Sewing) aSewing = new BRepBuilderAPI_Sewing;
926       aSewing->SetTolerance(Precision::Confusion());
927       aSewing->SetFaceMode(Standard_True);
928       aSewing->SetFloatingEdgesMode(Standard_False);
929       aSewing->SetNonManifoldMode(Standard_False);
930       for (i=1; i<=aSeqRes.Length(); i++) {
931         aSewing->Add(aSeqRes.Value(i));
932       }
933       aSewing->Perform();
934       aShape = aSewing->SewedShape();
935   }
936   else {
937       // old implementation without splitting
938       BRepOffsetAPI_MakePipeShell aBuilder(aWirePath);
939
940       Standard_Integer nbShapes = aSeqBases.Length();
941       Standard_Integer step = nbShapes/nbBases;
942
943       if (nbShapes < nbBases || fmod((double)nbShapes, (double)nbBases)) {
944         Standard_ConstructionError::Raise("Invalid sections were specified for building pipe");
945       }
946       Standard_Integer ind =0;
947       for (i = 1; i <= nbShapes && ind < nbShapes; i++) { //i+nbBases <= nbShapes
948         TopTools_SequenceOfShape usedBases;
949         Standard_Integer j = 1;
950         for (; j <= nbBases; j++) {
951           ind = i + (j-1)*step;
952           TopoDS_Shape aWireProf = aSeqBases.Value(ind);
953           usedBases.Append(aWireProf);
954           if (nbLocs) {
955             TopoDS_Shape aShapeLoc = aSeqLocs.Value(j);
956             TopoDS_Vertex aVert = TopoDS::Vertex(aShapeLoc);
957             aBuilder.Add(aWireProf, aVert, theWithContact, theWithCorrect);
958           }
959           else
960             aBuilder.Add(aWireProf, theWithContact, theWithCorrect);
961         }
962         if (!aBuilder.IsReady()) {
963           Standard_ConstructionError::Raise("Invalid input data for building PIPE: bases are invalid");
964         }
965         aBuilder.Build();
966         aShape = aBuilder.Shape();
967         aSeqFaces.Append(aShape);
968         for (j = 1; j <=usedBases.Length(); j++)
969           aBuilder.Delete(usedBases.Value(j));
970       }
971
972       //for case if section is face
973       if (aSeqFaces.Length() >1) {
974         BRep_Builder aB;
975         TopoDS_Compound aComp;
976         aB.MakeCompound(aComp);
977         for (i = 1; i <= aSeqFaces.Length(); i++)
978           aB.Add(aComp,aSeqFaces.Value(i));
979         aShape = aComp;
980       }
981   }
982
983   return aShape;
984 }
985
986 //=======================================================================
987 //function : CreatePipeForShellSections
988 //purpose  : auxilary for Execute()
989 //=======================================================================
990 static TopoDS_Shape CreatePipeForShellSections(const TopoDS_Wire& aWirePath,
991                                                GEOMImpl_IPipe* aCI)
992 {
993   //cout<<"CreatePipeForShellSections"<<endl;
994   //TopoDS_Shape res;
995   int i,j;
996   BRep_Builder B;
997
998   GEOMImpl_IPipeShellSect* aCIDS = (GEOMImpl_IPipeShellSect*)aCI;
999   Handle(TColStd_HSequenceOfTransient) aBasesObjs = aCIDS->GetBases();
1000   Handle(TColStd_HSequenceOfTransient) aSubBasesObjs = aCIDS->GetSubBases();
1001   Handle(TColStd_HSequenceOfTransient) aLocObjs = aCIDS->GetLocations();
1002   Standard_Boolean aWithContact = (aCIDS->GetWithContactMode());
1003   Standard_Boolean aWithCorrect = (aCIDS->GetWithCorrectionMode());
1004
1005   Standard_Integer nbBases = aBasesObjs->Length(),
1006     nbSubBases = (aSubBasesObjs.IsNull() ? 0 :aSubBasesObjs->Length()),
1007     nbLocs = (aLocObjs.IsNull() ? 0 :aLocObjs->Length());
1008
1009   if (nbLocs != nbBases) {
1010     if (aCI) delete aCI;
1011     Standard_ConstructionError::Raise("Number of sections is not equal to number of locations ");
1012   }
1013   if (nbSubBases && nbSubBases != nbBases) {
1014     if (aCI) delete aCI;
1015     Standard_ConstructionError::Raise("Number of sections is not equal to number of subsections ");
1016   }
1017
1018   //BRepOffsetAPI_MakePipeShell aBuilder(aWirePath);
1019
1020   TopTools_SequenceOfShape VLocs;
1021   for (i=1; i<=nbBases; i++) {
1022     Handle(Standard_Transient) anItemLoc = aLocObjs->Value(i);
1023     if (anItemLoc.IsNull())
1024       continue;
1025     Handle(GEOM_Function) aRefLoc = Handle(GEOM_Function)::DownCast(anItemLoc);
1026     TopoDS_Shape aShapeLoc = aRefLoc->GetValue();
1027     if (aShapeLoc.IsNull() || aShapeLoc.ShapeType() != TopAbs_VERTEX)
1028       continue;
1029     VLocs.Append(aShapeLoc);
1030   }
1031   nbLocs = VLocs.Length();
1032   if (nbLocs != nbBases) {
1033     if (aCI) delete aCI;
1034     Standard_ConstructionError::Raise("One of location shapes is not a vertex");
1035   }
1036   // split wire path by location points
1037   TColgp_SequenceOfPnt PLocs;
1038   for (i=1; i<=nbLocs; i++) {
1039     TopoDS_Vertex V = TopoDS::Vertex(VLocs.Value(i));
1040     PLocs.Append(BRep_Tool::Pnt(V));
1041   }
1042
1043   TopTools_SequenceOfShape Edges;
1044   TopTools_SequenceOfShape Wires;
1045   ShapeAnalysis_Edge sae;
1046
1047   if (nbLocs==2) {
1048     TopExp_Explorer anExp;
1049     for (anExp.Init(aWirePath, TopAbs_EDGE); anExp.More(); anExp.Next()) {
1050       Edges.Append(anExp.Current());
1051     }
1052     Standard_Integer Num1 = 0;
1053     Standard_Integer Num2 = 0;
1054     for (i=1; i<=Edges.Length(); i++) {
1055       TopoDS_Edge E = TopoDS::Edge(Edges.Value(i));
1056       double tol = BRep_Tool::Tolerance(E);
1057       TopoDS_Vertex V1 = sae.FirstVertex(E);
1058       TopoDS_Vertex V2 = sae.LastVertex(E);
1059       gp_Pnt P1 = BRep_Tool::Pnt(V1);
1060       gp_Pnt P2 = BRep_Tool::Pnt(V2);
1061       if (P1.Distance(PLocs.First()) < tol) {
1062         Num1 = i;
1063       }
1064       if (P2.Distance(PLocs.Last()) < tol) {
1065         Num2 = i;
1066       }
1067     }
1068     if (Num1>0 && Num2>0) {
1069       TopoDS_Wire W;
1070       B.MakeWire(W);
1071       for (i=Num1; i<=Num2; i++) {
1072         B.Add(W,Edges.Value(i));
1073       }
1074       Wires.Append(W);
1075     }
1076     else {
1077       Wires.Append(aWirePath);
1078     }
1079   }
1080   else {
1081     TopExp_Explorer anExp;
1082     for (anExp.Init(aWirePath, TopAbs_EDGE); anExp.More(); anExp.Next()) {
1083       Edges.Append(anExp.Current());
1084     }
1085     TopoDS_Edge edge = TopoDS::Edge(Edges.First());
1086     double tol = BRep_Tool::Tolerance(edge);
1087     TopoDS_Vertex VF = sae.FirstVertex(edge);
1088     gp_Pnt PF = BRep_Tool::Pnt(VF);
1089     //cout<<"PF("<<PF.X()<<","<<PF.Y()<<","<<PF.Z()<<")"<<endl;
1090     if (PF.Distance(PLocs.First()) > tol) {
1091       if (aCI) delete aCI;
1092       Standard_ConstructionError::Raise
1093         ("First location shapes is not coincided with first vertex of aWirePath");
1094     }
1095     VLocs.ChangeValue(1) = VF;
1096     edge = TopoDS::Edge(Edges.Last());
1097     tol = BRep_Tool::Tolerance(edge);
1098     TopoDS_Vertex VL = sae.LastVertex(edge);
1099     gp_Pnt PL = BRep_Tool::Pnt(VL);
1100     if (PL.Distance(PLocs.Last()) > tol) {
1101       if (aCI) delete aCI;
1102       Standard_ConstructionError::Raise
1103         ("Last location shapes is not coincided with last vertex of aWirePath");
1104     }
1105     VLocs.ChangeValue(nbLocs) = VL;
1106     int jcurr = 2;
1107     TopTools_SequenceOfShape tmpEdges;
1108     for (i=1; i<=Edges.Length() && jcurr<nbLocs; i++) {
1109       TopoDS_Edge E = TopoDS::Edge(Edges.Value(i));
1110       tol = BRep_Tool::Tolerance(E);
1111       TopoDS_Vertex V1 = sae.FirstVertex(E);
1112       TopoDS_Vertex V2 = sae.LastVertex(E);
1113       gp_Pnt P1 = BRep_Tool::Pnt(V1);
1114       gp_Pnt P2 = BRep_Tool::Pnt(V2);
1115       if (P2.Distance(PLocs.Value(jcurr)) < tol) {
1116         // make wire from current edge and add created
1117         // wire to Wires
1118         TopoDS_Wire W;
1119         B.MakeWire(W);
1120         for (j=1; j<=tmpEdges.Length(); j++)
1121           B.Add(W,tmpEdges.Value(j));
1122         B.Add(W,E);
1123         Wires.Append(W);
1124         VLocs.ChangeValue(jcurr) = V2;
1125         jcurr++;
1126         tmpEdges.Clear();
1127       }
1128       else {
1129         // find distance between E and aLocs(jcurr)
1130         double fp,lp;
1131         Handle(Geom_Curve) C = BRep_Tool::Curve(E,fp,lp);
1132         GeomAPI_ProjectPointOnCurve PPCurve (PLocs.Value(jcurr),C);
1133         if (PPCurve.NbPoints()>0 &&
1134             PLocs.Value(jcurr).Distance(PPCurve.Point(1)) < tol) {
1135           double param = PPCurve.Parameter(1);
1136           gp_Pnt PC1;
1137           C->D0(param,PC1);
1138           // split current edge
1139           Handle(Geom_TrimmedCurve) tc1 = new Geom_TrimmedCurve(C,fp,param);
1140           Handle(Geom_TrimmedCurve) tc2 = new Geom_TrimmedCurve(C,param,lp);
1141           TopoDS_Edge E1,E2;
1142           gp_Pnt Pfp;
1143           C->D0(fp,Pfp);
1144           if (Pfp.Distance(P1)<tol) {
1145             B.MakeEdge(E1,tc1,tol);
1146             B.Add(E1,V1);
1147             TopoDS_Shape tmpV = VLocs.Value(jcurr).Oriented(TopAbs_REVERSED);
1148             B.Add(E1,TopoDS::Vertex(tmpV));
1149             tmpEdges.Append(E1);
1150             B.MakeEdge(E2,tc2,tol);
1151             tmpV = VLocs.Value(jcurr).Oriented(TopAbs_FORWARD);
1152             B.Add(E2,TopoDS::Vertex(tmpV));
1153             B.Add(E2,V2);
1154           }
1155           else {
1156             B.MakeEdge(E1,tc2,tol);
1157             TopoDS_Shape tmpV = VLocs.Value(jcurr).Oriented(TopAbs_FORWARD);
1158             B.Add(E1,TopoDS::Vertex(tmpV));
1159             B.Add(E1,V1);
1160             E1.Reverse();
1161             tmpEdges.Append(E1);
1162             B.MakeEdge(E2,tc1,tol);
1163             B.Add(E2,V2);
1164             tmpV = VLocs.Value(jcurr).Oriented(TopAbs_REVERSED);
1165             B.Add(E2,TopoDS::Vertex(tmpV));
1166             E2.Reverse();
1167           }
1168           // create wire from tmpEdges
1169           TopoDS_Wire W;
1170           B.MakeWire(W);
1171           for (j=1; j<=tmpEdges.Length(); j++)
1172             B.Add(W,tmpEdges.Value(j));
1173           Wires.Append(W);
1174           jcurr++;
1175           tmpEdges.Clear();
1176           Edges.Remove(i);
1177           Edges.InsertAfter(i-1,E1);
1178           Edges.InsertAfter(i,E2);
1179         }
1180         else {
1181           tmpEdges.Append(E);
1182         }
1183       }
1184     }
1185     // create wire from other edges
1186     TopoDS_Wire W;
1187     B.MakeWire(W);
1188     for (; i<=Edges.Length(); i++)
1189       B.Add(W,Edges.Value(i));
1190     Wires.Append(W);
1191     //cout<<"Wires.Length()="<<Wires.Length()<<endl;
1192   }
1193
1194   if (Wires.Length() != nbLocs-1) {
1195     if (aCI) delete aCI;
1196     Standard_ConstructionError::Raise
1197       ("One of location shapes is not lied on the path");
1198   }
1199
1200   //TopTools_SequenceOfShape aSeqBases;
1201   //TopTools_SequenceOfShape aSeqSubBases;
1202   //TopTools_SequenceOfShape aSeqFaces;
1203   TopoDS_Compound aComp;
1204   B.MakeCompound(aComp);
1205   for (i = 1; i < nbBases; i++) {
1206     TopoDS_Wire WPath = TopoDS::Wire(Wires.Value(i));
1207     // 1 section
1208     Handle(Standard_Transient) anItem1 = aBasesObjs->Value(i);
1209     if (anItem1.IsNull())
1210       continue;
1211     Handle(GEOM_Function) aRefBase1 = Handle(GEOM_Function)::DownCast(anItem1);
1212     if (aRefBase1.IsNull())
1213       continue;
1214     TopoDS_Shape aShBase1 = aRefBase1->GetValue();
1215     if (aShBase1.IsNull())
1216       continue;
1217     TopAbs_ShapeEnum aType1 = aShBase1.ShapeType();
1218     // 2 section
1219     Handle(Standard_Transient) anItem2 = aBasesObjs->Value(i+1);
1220     if (anItem2.IsNull())
1221       continue;
1222     Handle(GEOM_Function) aRefBase2 = Handle(GEOM_Function)::DownCast(anItem2);
1223     if (aRefBase2.IsNull())
1224       continue;
1225     TopoDS_Shape aShBase2 = aRefBase2->GetValue();
1226     if (aShBase2.IsNull())
1227       continue;
1228     TopAbs_ShapeEnum aType2 = aShBase2.ShapeType();
1229
1230     //BRepTools::Write(aShBase1,"/dn02/users_Linux/skl/work/Bugs/14857/base1.brep");
1231
1232     bool OkSec = (aType1==TopAbs_SHELL || aType1==TopAbs_FACE) &&
1233                  (aType2==TopAbs_SHELL || aType2==TopAbs_FACE);
1234     if (!OkSec) {
1235       if (aCI) delete aCI;
1236       Standard_ConstructionError::Raise("One of section shapes has invalid type");
1237     }
1238
1239     bool CreateFewSolids = false;
1240     // compare sections
1241     TopExp_Explorer anExp;
1242     Standard_Integer nbf1 = 0;
1243     for (anExp.Init(aShBase1, TopAbs_FACE); anExp.More(); anExp.Next()) {
1244       nbf1++;
1245     }
1246     Standard_Integer nbf2 = 0;
1247     for (anExp.Init(aShBase2, TopAbs_FACE); anExp.More(); anExp.Next()) {
1248       nbf2++;
1249     }
1250     if (nbf1==nbf2) {
1251       CreateFewSolids = true;
1252     }
1253
1254     /*
1255     // check orientation of sections
1256     bool NeedReverse = false;
1257     {
1258       // first section
1259       anExp.Init(aShBase1, TopAbs_FACE);
1260       TopoDS_Shape aFace = anExp.Current();
1261       TColgp_SequenceOfPnt aPnts;
1262       double xc=0, yc=0, zc=0;
1263       for (anExp.Init(aFace, TopAbs_VERTEX); anExp.More(); anExp.Next()) {
1264         TopoDS_Vertex V = TopoDS::Vertex(anExp.Current());
1265         aPnts.Append(BRep_Tool::Pnt(V));
1266         xc += aPnts.Last().X();
1267         yc += aPnts.Last().Y();
1268         zc += aPnts.Last().Z();
1269       }
1270       gp_Pnt PC(xc/aPnts.Length(), yc/aPnts.Length(), zc/aPnts.Length());
1271       gp_Vec V1(PC,aPnts.Value(1));
1272       gp_Vec V2(PC,aPnts.Value(2));
1273       gp_Vec VN = V1.Crossed(V2);
1274       for (int ip=2; ip<aPnts.Length(); ip++) {
1275         V1 = gp_Vec(PC,aPnts.Value(ip));
1276         V2 = gp_Vec(PC,aPnts.Value(ip+1));
1277         VN.Add(V1.Crossed(V2));
1278       }
1279       gp_Vec PathNorm;
1280       gp_Pnt PLoc = BRep_Tool::Pnt(TopoDS::Vertex(VLocs(i)));
1281       TopExp_Explorer WE;
1282       for (WE.Init(WPath, TopAbs_EDGE); WE.More(); WE.Next()) {
1283         TopoDS_Edge edge = TopoDS::Edge(WE.Current());
1284         double tol = BRep_Tool::Tolerance(edge);
1285         TopoDS_Vertex VF = sae.FirstVertex(edge);
1286         gp_Pnt PF = BRep_Tool::Pnt(VF);
1287         if (PF.Distance(PLoc) < tol) {
1288           double fp,lp;
1289           Handle(Geom_Curve) C = BRep_Tool::Curve(edge,fp,lp);
1290           gp_Pnt P1,P2;
1291           C->D0(fp,P1);
1292           if (P1.Distance(PLoc) < tol) {
1293             C->D0(fp+(lp-fp)/100,P2);
1294           }
1295           else {
1296             C->D0(lp,P1);
1297             C->D0(lp+(fp-lp)/100,P2);
1298           }
1299           PathNorm = gp_Vec(P1,P2);
1300           break;
1301         }
1302         else {
1303           TopoDS_Vertex VL = sae.LastVertex(edge);
1304           gp_Pnt PL = BRep_Tool::Pnt(VL);
1305           if (PL.Distance(PLoc) < tol) {
1306             double fp,lp;
1307             Handle(Geom_Curve) C = BRep_Tool::Curve(edge,fp,lp);
1308             gp_Pnt P1,P2;
1309             C->D0(fp,P1);
1310             if (P1.Distance(PLoc) < tol) {
1311               C->D0(fp+(lp-fp)/100,P2);
1312             }
1313             else {
1314               C->D0(lp,P1);
1315               C->D0(lp+(fp-lp)/100,P2);
1316             }
1317             PathNorm = gp_Vec(P2,P1);
1318             break;
1319           }
1320         }
1321       }
1322       cout<<"VN("<<VN.X()<<","<<VN.Y()<<","<<VN.Z()<<")"<<endl;
1323       cout<<"PathNorm("<<PathNorm.X()<<","<<PathNorm.Y()<<","<<PathNorm.Z()<<")"<<endl;
1324       if (fabs(VN.Angle(PathNorm))>PI/2.) {
1325         NeedReverse = true;
1326         aShBase1.Reverse();
1327       }
1328     }
1329     {
1330       // second section
1331       anExp.Init(aShBase2, TopAbs_FACE);
1332       TopoDS_Shape aFace = anExp.Current();
1333       TColgp_SequenceOfPnt aPnts;
1334       double xc=0, yc=0, zc=0;
1335       for (anExp.Init(aFace, TopAbs_VERTEX); anExp.More(); anExp.Next()) {
1336         TopoDS_Vertex V = TopoDS::Vertex(anExp.Current());
1337         aPnts.Append(BRep_Tool::Pnt(V));
1338         xc += aPnts.Last().X();
1339         yc += aPnts.Last().Y();
1340         zc += aPnts.Last().Z();
1341       }
1342       gp_Pnt PC(xc/aPnts.Length(), yc/aPnts.Length(), zc/aPnts.Length());
1343       gp_Vec V1(PC,aPnts.Value(1));
1344       gp_Vec V2(PC,aPnts.Value(2));
1345       gp_Vec VN = V1.Crossed(V2);
1346       for (int ip=2; ip<aPnts.Length(); ip++) {
1347         V1 = gp_Vec(PC,aPnts.Value(ip));
1348         V2 = gp_Vec(PC,aPnts.Value(ip+1));
1349         VN.Add(V1.Crossed(V2));
1350       }
1351       gp_Vec PathNorm;
1352       gp_Pnt PLoc = BRep_Tool::Pnt(TopoDS::Vertex(VLocs(i+1)));
1353       TopExp_Explorer WE;
1354       for (WE.Init(WPath, TopAbs_EDGE); WE.More(); WE.Next()) {
1355         TopoDS_Edge edge = TopoDS::Edge(WE.Current());
1356         double tol = BRep_Tool::Tolerance(edge);
1357         TopoDS_Vertex VF = sae.FirstVertex(edge);
1358         gp_Pnt PF = BRep_Tool::Pnt(VF);
1359         if (PF.Distance(PLoc) < tol) {
1360           double fp,lp;
1361           Handle(Geom_Curve) C = BRep_Tool::Curve(edge,fp,lp);
1362           gp_Pnt P1,P2;
1363           C->D0(fp,P1);
1364           if (P1.Distance(PLoc) < tol) {
1365             C->D0(fp+(lp-fp)/100,P2);
1366           }
1367           else {
1368             C->D0(lp,P1);
1369             C->D0(lp+(fp-lp)/100,P2);
1370           }
1371           PathNorm = gp_Vec(P2,P1);
1372           break;
1373         }
1374         else {
1375           TopoDS_Vertex VL = sae.LastVertex(edge);
1376           gp_Pnt PL = BRep_Tool::Pnt(VL);
1377           if (PL.Distance(PLoc) < tol) {
1378             double fp,lp;
1379             Handle(Geom_Curve) C = BRep_Tool::Curve(edge,fp,lp);
1380             gp_Pnt P1,P2;
1381             C->D0(fp,P1);
1382             if (P1.Distance(PLoc) < tol) {
1383               C->D0(fp+(lp-fp)/100,P2);
1384             }
1385             else {
1386               C->D0(lp,P1);
1387               C->D0(lp+(fp-lp)/100,P2);
1388             }
1389             PathNorm = gp_Vec(P2,P1);
1390             break;
1391           }
1392         }
1393       }
1394       //cout<<"VN("<<VN.X()<<","<<VN.Y()<<","<<VN.Z()<<")"<<endl;
1395       //cout<<"PathNorm("<<PathNorm.X()<<","<<PathNorm.Y()<<","<<PathNorm.Z()<<")"<<endl;
1396       if (fabs(VN.Angle(PathNorm))>PI/2.)
1397         aShBase2.Reverse();
1398     }
1399     */
1400
1401     if (!CreateFewSolids) {
1402       // we can create only one solid
1403       TopoDS_Shape aWire1, aWire2;
1404       // prepare aWire1
1405       if (aType1==TopAbs_SHELL) {
1406         // create wire as boundary contour if shell is no closed
1407         // get free boundary shapes
1408         ShapeAnalysis_FreeBounds anAnalizer(aShBase1);
1409         TopoDS_Compound aClosed = anAnalizer.GetClosedWires();
1410         //TopExp_Explorer anExp;
1411         Standard_Integer NbWires = 0;
1412         for (anExp.Init(aClosed, TopAbs_WIRE); anExp.More(); anExp.Next()) {
1413           NbWires++;
1414           aWire1 = anExp.Current();
1415         }
1416         if (NbWires!=1) {
1417           // bad case
1418           if (aCI) delete aCI;
1419           Standard_ConstructionError::Raise("Bad shell is used as section ");
1420         }
1421       }
1422       else { // aType1==TopAbs_FACE
1423         TopExp_Explorer aExpW(aShBase1,TopAbs_WIRE);
1424         aWire1 = aExpW.Current();
1425       }
1426       // prepare aWire2
1427       if (aType2==TopAbs_SHELL) {
1428         // create wire as boundary contour if shell is no closed
1429         // get free boundary shapes
1430         ShapeAnalysis_FreeBounds anAnalizer(aShBase2);
1431         TopoDS_Compound aClosed = anAnalizer.GetClosedWires();
1432         //TopExp_Explorer anExp;
1433         Standard_Integer NbWires = 0;
1434         for (anExp.Init(aClosed, TopAbs_WIRE); anExp.More(); anExp.Next()) {
1435           NbWires++;
1436           aWire2 = anExp.Current();
1437         }
1438         if (NbWires!=1) {
1439           // bad case
1440           if (aCI) delete aCI;
1441           Standard_ConstructionError::Raise("Bad shell is used as section ");
1442         }
1443       }
1444       else { // aType2==TopAbs_FACE
1445         TopExp_Explorer aExpW(aShBase2,TopAbs_WIRE);
1446         aWire2 = aExpW.Current();
1447       }
1448       // make pipe using aWire1 and aWire2
1449       if (!aWire1.IsNull() && !aWire2.IsNull()) {
1450         //BRepOffsetAPI_MakePipeShell aBuilder(aWirePath);
1451         BRepOffsetAPI_MakePipeShell aBuilder(WPath);
1452         aBuilder.Add(aWire1, TopoDS::Vertex(VLocs(i)),
1453                      aWithContact, aWithCorrect);
1454         aBuilder.Add(aWire2, TopoDS::Vertex(VLocs(i+1)),
1455                      aWithContact, aWithCorrect);
1456         if (!aBuilder.IsReady()) {
1457           if (aCI) delete aCI;
1458           Standard_ConstructionError::Raise("Invalid input data for building PIPE: bases are invalid");
1459         }
1460         aBuilder.Build();
1461         TopoDS_Shape aShape = aBuilder.Shape();
1462         TopoDS_Shell aShell;
1463         B.MakeShell(aShell);
1464         for (anExp.Init(aShape, TopAbs_FACE); anExp.More(); anExp.Next()) {
1465           B.Add(aShell,anExp.Current());
1466         }
1467         for (anExp.Init(aShBase1, TopAbs_FACE); anExp.More(); anExp.Next()) {
1468           B.Add(aShell,anExp.Current());
1469         }
1470         for (anExp.Init(aShBase2, TopAbs_FACE); anExp.More(); anExp.Next()) {
1471           B.Add(aShell,anExp.Current());
1472         }
1473         // make sewing for this shell
1474         Handle(BRepBuilderAPI_Sewing) aSewing = new BRepBuilderAPI_Sewing;
1475         aSewing->SetTolerance(Precision::Confusion());
1476         aSewing->SetFaceMode(Standard_True);
1477         aSewing->SetFloatingEdgesMode(Standard_False);
1478         aSewing->SetNonManifoldMode(Standard_False);
1479         for (anExp.Init(aShell, TopAbs_FACE); anExp.More(); anExp.Next()) {
1480           aSewing->Add(anExp.Current());
1481         }
1482         aSewing->Perform();
1483         const TopoDS_Shape aSewShape = aSewing->SewedShape();
1484         if (aSewShape.ShapeType() == TopAbs_SHELL) {
1485           aShell = TopoDS::Shell(aSewShape);
1486           GProp_GProps aSystem;
1487           BRepGProp::VolumeProperties(aShell, aSystem);
1488           if (aSystem.Mass()<0) {
1489             aShell.Reverse();
1490           }
1491           if (BRep_Tool::IsClosed(aShell)) {
1492             TopoDS_Solid aSolid;
1493             B.MakeSolid(aSolid);
1494             B.Add(aSolid,aShell);
1495             B.Add(aComp,aSolid);
1496           }
1497           else {
1498             B.Add(aComp,aShell);
1499           }
1500         }
1501         else {
1502           B.Add(aComp,aShell);
1503         }
1504       }
1505     }
1506     else {
1507       // main block - creation few solids (for each pair of faces)
1508       TopTools_MapOfShape aFaces1,aFaces2;
1509       for (anExp.Init(aShBase1, TopAbs_FACE); anExp.More(); anExp.Next()) {
1510         aFaces1.Add(anExp.Current());
1511       }
1512       for (anExp.Init(aShBase2, TopAbs_FACE); anExp.More(); anExp.Next()) {
1513         aFaces2.Add(anExp.Current());
1514       }
1515       // creating map of edge faces
1516       TopTools_IndexedDataMapOfShapeListOfShape aMapEdgeFaces1;
1517       TopExp::MapShapesAndAncestors(aShBase1, TopAbs_EDGE, TopAbs_FACE, aMapEdgeFaces1);
1518       TopTools_IndexedDataMapOfShapeListOfShape aMapEdgeFaces2;
1519       TopExp::MapShapesAndAncestors(aShBase2, TopAbs_EDGE, TopAbs_FACE, aMapEdgeFaces2);
1520
1521       // constuct map face->face
1522       TopTools_IndexedDataMapOfShapeShape FF;
1523       TopoDS_Shape FS1,FS2;
1524       if (nbSubBases==0) {
1525         // find edge the most distant from location point
1526         // (this edge is not shared by two faces)
1527         double maxdist = 0.;
1528         TopoDS_Shape E1;
1529         TopoDS_Vertex V11,V21;
1530         for (j=1; j<=aMapEdgeFaces1.Extent(); j++) {
1531           TopoDS_Shape tmp = aMapEdgeFaces1.FindKey(j);
1532           const TopTools_ListOfShape& aList = aMapEdgeFaces1.FindFromKey(tmp);
1533           if (aList.Extent()>1)
1534             continue;
1535           TopExp_Explorer expv;
1536           expv.Init(tmp, TopAbs_VERTEX);
1537           TopoDS_Vertex V1 = TopoDS::Vertex(expv.Current());
1538           expv.Next();
1539           TopoDS_Vertex V2 = TopoDS::Vertex(expv.Current());
1540           gp_Pnt P1 = BRep_Tool::Pnt(V1);
1541           gp_Pnt P2 = BRep_Tool::Pnt(V2);
1542           double dist = PLocs.Value(i).Distance(P1) + PLocs.Value(i).Distance(P2);
1543           if (dist>maxdist) {
1544             E1 = tmp;
1545             V11 = V1;
1546             V21 = V2;
1547             TopTools_ListIteratorOfListOfShape anIter(aList);
1548             FS1 = anIter.Value();
1549             maxdist = dist;
1550           }
1551         }
1552         // main direction for comparing
1553         gp_Vec VM(PLocs.Value(i),PLocs.Value(i+1));
1554         // find corresponding edge from next section
1555         double minang = M_PI;
1556         gp_Pnt P11 = BRep_Tool::Pnt(V11);
1557         gp_Pnt P21 = BRep_Tool::Pnt(V21);
1558         TopoDS_Shape E2;
1559         TopoDS_Vertex V12,V22;
1560         for (j=1; j<=aMapEdgeFaces2.Extent(); j++) {
1561           TopoDS_Shape tmp = aMapEdgeFaces2.FindKey(j);
1562           const TopTools_ListOfShape& aList = aMapEdgeFaces2.FindFromKey(tmp);
1563           if (aList.Extent()>1)
1564             continue;
1565           TopExp_Explorer expv;
1566           expv.Init(tmp, TopAbs_VERTEX);
1567           TopoDS_Vertex V1tmp = TopoDS::Vertex(expv.Current());
1568           expv.Next();
1569           TopoDS_Vertex V2tmp = TopoDS::Vertex(expv.Current());
1570           gp_Pnt P1tmp = BRep_Tool::Pnt(V1tmp);
1571           gp_Pnt P2tmp = BRep_Tool::Pnt(V2tmp);
1572           double d1 = P1tmp.Distance(P11) + P2tmp.Distance(P21);
1573           double d2 = P1tmp.Distance(P21) + P2tmp.Distance(P11);
1574           TopoDS_Vertex V1,V2;
1575           gp_Pnt P1,P2;
1576           if (d1>d2) {
1577             V1 = V2tmp; P1 = P2tmp;
1578             V2 = V1tmp; P2 = P1tmp;
1579           }
1580           else {
1581             V1 = V1tmp; P1 = P1tmp;
1582             V2 = V2tmp; P2 = P2tmp;
1583           }
1584           gp_Vec Vec1(P11,P1);
1585           gp_Vec Vec2(P21,P2);
1586           double ang = fabs(Vec1.Angle(VM)) + fabs(Vec2.Angle(VM));
1587           if (ang<minang) {
1588             E2 = tmp;
1589             V12 = V1;
1590             V22 = V2;
1591             TopTools_ListIteratorOfListOfShape anIter(aList);
1592             FS2 = anIter.Value();
1593             minang = ang;
1594           }
1595         }
1596         // put all pairs to map FF
1597         FF.Add(FS1,FS2);
1598         FF.Add(E1,E2);
1599         FF.Add(V11,V12);
1600         FF.Add(V21,V22);
1601
1602         // add pairs of edges to FF
1603         bool stat =  FillForOtherEdges(FS1,E1,V11,FF);
1604         if (!stat) {
1605           if (aCI) delete aCI;
1606           Standard_ConstructionError::Raise("FindForOtherEdges: Can not mapping other egdes");
1607         }
1608
1609       }
1610       else {
1611         { // 1 section
1612           Handle(Standard_Transient) anItem = aSubBasesObjs->Value(i);
1613           if (anItem.IsNull()) {
1614             if (aCI) delete aCI;
1615             Standard_ConstructionError::Raise("Invalid subbase shape");
1616           }
1617           Handle(GEOM_Function) aRefBase = Handle(GEOM_Function)::DownCast(anItem);
1618           if (aRefBase.IsNull()) {
1619             if (aCI) delete aCI;
1620             Standard_ConstructionError::Raise("Invalid subbase shape");
1621           }
1622           TopoDS_Shape aSh = aRefBase->GetValue();
1623           if (aSh.IsNull()) {
1624             if (aCI) delete aCI;
1625             Standard_ConstructionError::Raise("Invalid subbase shape");
1626           }
1627           if (aSh.ShapeType()!=TopAbs_FACE) {
1628             if (aCI) delete aCI;
1629             Standard_ConstructionError::Raise("Invalid subbase shape");
1630           }
1631           FS1 = aSh;
1632         }
1633         { // 2 section
1634           Handle(Standard_Transient) anItem = aSubBasesObjs->Value(i+1);
1635           if (anItem.IsNull()) {
1636             if (aCI) delete aCI;
1637             Standard_ConstructionError::Raise("Invalid subbase shape");
1638           }
1639           Handle(GEOM_Function) aRefBase = Handle(GEOM_Function)::DownCast(anItem);
1640           if (aRefBase.IsNull()) {
1641             if (aCI) delete aCI;
1642             Standard_ConstructionError::Raise("Invalid subbase shape");
1643           }
1644           TopoDS_Shape aSh = aRefBase->GetValue();
1645           if (aSh.IsNull()) {
1646             if (aCI) delete aCI;
1647             Standard_ConstructionError::Raise("Invalid subbase shape");
1648           }
1649           if (aSh.ShapeType()!=TopAbs_FACE) {
1650             if (aCI) delete aCI;
1651             Standard_ConstructionError::Raise("Invalid subbase shape");
1652           }
1653           FS2 = aSh;
1654         }
1655
1656         if (!aFaces1.Contains(FS1) || !aFaces2.Contains(FS2)) {
1657           if (aCI) delete aCI;
1658           Standard_ConstructionError::Raise("Invalid subbase shape");
1659         }
1660
1661         FF.Add(FS1,FS2);
1662
1663         // add pairs of edges to FF
1664         bool stat =  FillCorrespondingEdges(FS1, FS2, TopoDS::Vertex(VLocs(i)),
1665                                             TopoDS::Vertex(VLocs(i+1)), WPath, FF);
1666         if (!stat) {
1667           if (aCI) delete aCI;
1668           Standard_ConstructionError::Raise("Can not create correct pipe");
1669         }
1670       }
1671
1672       FindNextPairOfFaces(FS1, aMapEdgeFaces1, aMapEdgeFaces2, FF, aCI);
1673
1674       // make pipe for each pair of faces
1675       for (j=1; j<=FF.Extent(); j++) {
1676         TopoDS_Shape F1 = FF.FindKey(j);
1677         if (F1.ShapeType() != TopAbs_FACE)
1678           continue;
1679         TopoDS_Shape F2 = FF.FindFromIndex(j);
1680         TopExp_Explorer aExpW1(F1,TopAbs_WIRE);
1681         TopoDS_Wire aWire1 = TopoDS::Wire(aExpW1.Current());
1682         TopExp_Explorer aExpW2(F2,TopAbs_WIRE);
1683         TopoDS_Wire aWire2 = TopoDS::Wire(aExpW2.Current());
1684         // make pipe using aWire1 and aWire2
1685         if (!aWire1.IsNull() && !aWire2.IsNull()) {
1686           BRepOffsetAPI_MakePipeShell aBuilder(WPath);
1687           aBuilder.Add(aWire1, TopoDS::Vertex(VLocs(i)),
1688                        aWithContact, aWithCorrect);
1689           aBuilder.Add(aWire2, TopoDS::Vertex(VLocs(i+1)),
1690                        aWithContact, aWithCorrect);
1691           if (!aBuilder.IsReady()) {
1692             if (aCI) delete aCI;
1693             Standard_ConstructionError::Raise("Invalid input data for building PIPE: bases are invalid");
1694           }
1695           aBuilder.Build();
1696           TopoDS_Shape aShape = aBuilder.Shape();
1697           TopoDS_Shell aShell;
1698           B.MakeShell(aShell);
1699           for (anExp.Init(aShape, TopAbs_FACE); anExp.More(); anExp.Next()) {
1700             B.Add(aShell,anExp.Current());
1701           }
1702
1703           B.Add(aShell,F1);
1704           B.Add(aShell,F2);
1705           // make sewing for this shell
1706           Handle(BRepBuilderAPI_Sewing) aSewing = new BRepBuilderAPI_Sewing;
1707           aSewing->SetTolerance(Precision::Confusion());
1708           aSewing->SetFaceMode(Standard_True);
1709           aSewing->SetFloatingEdgesMode(Standard_False);
1710           aSewing->SetNonManifoldMode(Standard_False);
1711           for (anExp.Init(aShell, TopAbs_FACE); anExp.More(); anExp.Next()) {
1712             aSewing->Add(anExp.Current());
1713           }
1714           aSewing->Perform();
1715           const TopoDS_Shape aSewShape = aSewing->SewedShape();
1716           if (aSewShape.ShapeType() == TopAbs_SHELL) {
1717             aShell = TopoDS::Shell(aSewShape);
1718             GProp_GProps aSystem;
1719             BRepGProp::VolumeProperties(aShell, aSystem);
1720             if (aSystem.Mass()<0) {
1721               //cout<<"aSewShape is reversed"<<endl;
1722               aShell.Reverse();
1723             }
1724             if (BRep_Tool::IsClosed(aShell)) {
1725               TopoDS_Solid aSolid;
1726               B.MakeSolid(aSolid);
1727               B.Add(aSolid,aShell);
1728               B.Add(aComp,aSolid);
1729             }
1730             else {
1731               B.Add(aComp,aShell);
1732             }
1733           }
1734           else {
1735             B.Add(aComp,aShell);
1736           }
1737         }
1738       }
1739
1740     }
1741   }
1742
1743   //BRepTools::Write(aComp,"/dn02/users_Linux/skl/work/Bugs/14857/comp.brep");
1744   return aComp;
1745 }
1746
1747 //=======================================================================
1748 //function : CreatePipeShellsWithoutPath
1749 //purpose  : auxilary for Execute()
1750 //=======================================================================
1751 static TopoDS_Shape CreatePipeShellsWithoutPath(GEOMImpl_IPipe* aCI)
1752 {
1753   //cout<<"CreatePipeShellsWithoutPath"<<endl;
1754   int i,j;
1755   BRep_Builder B;
1756
1757   GEOMImpl_IPipeShellSect* aCIDS = (GEOMImpl_IPipeShellSect*)aCI;
1758   // shell sections
1759   Handle(TColStd_HSequenceOfTransient) aBasesObjs = aCIDS->GetBases();
1760   // vertex for recognition
1761   Handle(TColStd_HSequenceOfTransient) VObjs = aCIDS->GetLocations();
1762
1763   Standard_Integer nbBases = aBasesObjs->Length(),
1764     nbv = (VObjs.IsNull() ? 0 :VObjs->Length());
1765
1766   if (nbv != nbBases) {
1767     if (aCI) delete aCI;
1768     Standard_ConstructionError::Raise("Number of shapes for recognition is invalid");
1769   }
1770
1771   TopTools_SequenceOfShape SecVs,Bases;
1772   for (i=1; i<=nbBases; i++) {
1773     // vertex
1774     Handle(Standard_Transient) anItem = VObjs->Value(i);
1775     if (anItem.IsNull())
1776       continue;
1777     Handle(GEOM_Function) aRef = Handle(GEOM_Function)::DownCast(anItem);
1778     TopoDS_Shape V = aRef->GetValue();
1779     if (V.IsNull() || V.ShapeType() != TopAbs_VERTEX)
1780       continue;
1781     SecVs.Append(V);
1782     // section
1783     anItem = aBasesObjs->Value(i);
1784     if (anItem.IsNull())
1785       continue;
1786     aRef = Handle(GEOM_Function)::DownCast(anItem);
1787     TopoDS_Shape aSh = aRef->GetValue();
1788     if (aSh.IsNull())
1789       continue;
1790     Bases.Append(aSh);
1791   }
1792   nbv = SecVs.Length();
1793   nbBases = Bases.Length();
1794   if (nbv != nbBases) {
1795     if (aCI) delete aCI;
1796     Standard_ConstructionError::Raise("One of shapes for recognition is not a vertex");
1797   }
1798
1799   TopoDS_Compound aComp;
1800   B.MakeCompound(aComp);
1801
1802   for (i = 1; i < nbBases; i++) {
1803     MESSAGE ("Make pipe between sections "<<i<<" and "<<i+1);
1804     TopoDS_Shape aShBase1 = Bases.Value(i);
1805     TopoDS_Shape aShBase2 = Bases.Value(i+1);
1806     TopExp_Explorer anExp;
1807     Standard_Integer nbf1 = 0;
1808     for (anExp.Init(aShBase1, TopAbs_FACE); anExp.More(); anExp.Next()) {
1809       nbf1++;
1810     }
1811     Standard_Integer nbf2 = 0;
1812     for (anExp.Init(aShBase2, TopAbs_FACE); anExp.More(); anExp.Next()) {
1813       nbf2++;
1814     }
1815     //cout<<"nbf1="<<nbf1<<" nbf2="<<nbf2<<endl;
1816     if (nbf1!=nbf2) {
1817       if (aCI) delete aCI;
1818       Standard_ConstructionError::Raise("Different number of faces in the sections");
1819     }
1820
1821     TopTools_MapOfShape aFaces1,aFaces2;
1822     for (anExp.Init(aShBase1, TopAbs_FACE); anExp.More(); anExp.Next()) {
1823       aFaces1.Add(anExp.Current());
1824     }
1825     for (anExp.Init(aShBase2, TopAbs_FACE); anExp.More(); anExp.Next()) {
1826       aFaces2.Add(anExp.Current());
1827     }
1828
1829     // creating map of edge faces
1830     TopTools_IndexedDataMapOfShapeListOfShape aMapEdgeFaces1;
1831     TopExp::MapShapesAndAncestors(aShBase1, TopAbs_EDGE, TopAbs_FACE, aMapEdgeFaces1);
1832     TopTools_IndexedDataMapOfShapeListOfShape aMapEdgeFaces2;
1833     TopExp::MapShapesAndAncestors(aShBase2, TopAbs_EDGE, TopAbs_FACE, aMapEdgeFaces2);
1834
1835     // constuct map face->face (and sub-shapes)
1836     TopTools_IndexedDataMapOfShapeShape FF;
1837     //TopoDS_Shape FS1 = SecFs.Value(i), FS2 = SecFs.Value(i+1);
1838     TopoDS_Shape FS1, FS2;
1839     TopoDS_Vertex V1 = TopoDS::Vertex(SecVs(i));
1840     TopoDS_Vertex V2 = TopoDS::Vertex(SecVs(i+1));
1841     FindFirstPairFaces(aShBase1, aShBase2, V1, V2, FS1, FS2);
1842
1843     FF.Add(FS1,FS2);
1844     MESSAGE ("  first pair of corresponding faces is found");
1845
1846     // add pairs of edges and vertexes to FF
1847     bool stat =  FillCorrespondingEdges(FS1, FS2, V1, V2, FF);
1848     if (!stat) {
1849       if (aCI) delete aCI;
1850       Standard_ConstructionError::Raise("Can not create correct pipe");
1851     }
1852     MESSAGE ("  correspondences for sub-shapes of first pair of faces is found");
1853
1854     FindNextPairOfFaces(FS1, aMapEdgeFaces1, aMapEdgeFaces2, FF, aCI);
1855     MESSAGE ("  other correspondences is found, make pipe for all pairs of faces");
1856
1857     // make pipe for each pair of faces
1858     // auxilary map vertex->edge for created pipe edges
1859     TopTools_IndexedDataMapOfShapeShape VPE;
1860     ShapeAnalysis_Edge sae;
1861     //cout<<"FF.Extent()="<<FF.Extent()<<endl;
1862     int nbff = 0;
1863     for (j=1; j<=FF.Extent(); j++) {
1864       TopoDS_Shape F1 = FF.FindKey(j);
1865       if (F1.ShapeType() != TopAbs_FACE)
1866         continue;
1867       TopoDS_Shape F2 = FF.FindFromIndex(j);
1868       nbff++;
1869
1870       //if (nbff!=3) continue;
1871
1872       MESSAGE ("    make pipe for "<<nbff<<" face");
1873
1874       Handle(Geom_Surface) S1 = BRep_Tool::Surface(TopoDS::Face(F1));
1875       if (S1->IsKind(STANDARD_TYPE(Geom_RectangularTrimmedSurface))) {
1876         Handle(Geom_RectangularTrimmedSurface) RTS =
1877           Handle(Geom_RectangularTrimmedSurface)::DownCast(S1);
1878         S1 = RTS->BasisSurface();
1879       }
1880       Handle(Geom_Plane) Pln1 = Handle(Geom_Plane)::DownCast(S1);
1881       if (Pln1.IsNull()) {
1882         if (aCI) delete aCI;
1883         Standard_ConstructionError::Raise("Surface from face is not plane");
1884       }
1885       gp_Vec aDir1(Pln1->Axis().Direction());
1886
1887       Handle(Geom_Surface) S2 = BRep_Tool::Surface(TopoDS::Face(F2));
1888       if (S2->IsKind(STANDARD_TYPE(Geom_RectangularTrimmedSurface))) {
1889         Handle(Geom_RectangularTrimmedSurface) RTS =
1890           Handle(Geom_RectangularTrimmedSurface)::DownCast(S2);
1891         S2 = RTS->BasisSurface();
1892       }
1893       Handle(Geom_Plane) Pln2 =
1894           Handle(Geom_Plane)::DownCast(S2);
1895       if (Pln2.IsNull()) {
1896         if (aCI) delete aCI;
1897         Standard_ConstructionError::Raise("Surface from face is not plane");
1898       }
1899       gp_Vec aDir2(Pln2->Axis().Direction());
1900
1901       gp_Pnt P1 = BRep_Tool::Pnt(TopoDS::Vertex(SecVs(i)));
1902       gp_Pnt P2 = BRep_Tool::Pnt(TopoDS::Vertex(SecVs(i+1)));
1903       gp_Vec aDir(P1,P2);
1904       if (fabs(aDir.Angle(aDir1)) > M_PI/2.)
1905         aDir1.Reverse();
1906       if (fabs(aDir.Angle(aDir2)) > M_PI/2.)
1907         aDir2.Reverse();
1908
1909       TopExp_Explorer anExpE(F1,TopAbs_EDGE);
1910       TopTools_SequenceOfShape aNewFs;
1911       //int nbee=0;
1912       for (; anExpE.More(); anExpE.Next()) {
1913         TopoDS_Edge E1 = TopoDS::Edge(anExpE.Current());
1914         //nbee++;
1915         if (!FF.Contains(E1))
1916           MESSAGE ("map FF not contains key E1");
1917
1918         if (VPE.Contains(E1)) {
1919           aNewFs.Append(VPE.FindFromKey(E1));
1920 #ifdef _DEBUG_
1921           MESSAGE ("    using existed face");
1922 #endif
1923           continue;
1924         }
1925
1926         TopoDS_Edge E3 = TopoDS::Edge(FF.FindFromKey(E1));
1927         TopoDS_Vertex V1 = sae.FirstVertex(E1);
1928         TopoDS_Vertex V2 = sae.LastVertex(E1);
1929         if (!FF.Contains(V1))
1930           MESSAGE ("map FF not contains key V1");
1931         if (!FF.Contains(V2))
1932           MESSAGE ("map FF not contains key V2");
1933         TopoDS_Vertex V3 = TopoDS::Vertex(FF.FindFromKey(V2));
1934         TopoDS_Vertex V4 = TopoDS::Vertex(FF.FindFromKey(V1));
1935         TopoDS_Vertex Vtmp = sae.FirstVertex(E3);
1936         if (Vtmp.IsSame(V4))
1937           E3.Reverse();
1938         gp_Pnt P1 = BRep_Tool::Pnt(V1);
1939         gp_Pnt P2 = BRep_Tool::Pnt(V2);
1940         gp_Pnt P3 = BRep_Tool::Pnt(V3);
1941         gp_Pnt P4 = BRep_Tool::Pnt(V4);
1942         // make E2
1943         TopoDS_Edge E2;
1944         Handle(Geom_BSplineCurve) C2;
1945         if (VPE.Contains(V2)) {
1946           E2 = TopoDS::Edge(VPE.FindFromKey(V2));
1947           double fp,lp;
1948           C2 = Handle(Geom_BSplineCurve)::DownCast(BRep_Tool::Curve(E2,fp,lp));
1949         }
1950         else {
1951           Handle(TColgp_HArray1OfPnt) HAP = new TColgp_HArray1OfPnt(1,2);
1952           HAP->SetValue(1,P2);
1953           HAP->SetValue(2,P3);
1954           GeomAPI_Interpolate anInt(HAP,Standard_False,1.e-7);
1955           anInt.Load(aDir1,aDir2);
1956           anInt.Perform();
1957           C2 = anInt.Curve();
1958           B.MakeEdge(E2,C2,1.e-7);
1959           B.Add(E2,TopoDS::Vertex(V2.Oriented(TopAbs_FORWARD)));
1960           B.Add(E2,TopoDS::Vertex(V3.Oriented(TopAbs_REVERSED)));
1961           VPE.Add(V2,E2);
1962         }
1963         // make E4
1964         TopoDS_Edge E4;
1965         Handle(Geom_BSplineCurve) C4;
1966         if (VPE.Contains(V1)) {
1967           E4 = TopoDS::Edge(VPE.FindFromKey(V1));
1968           double fp,lp;
1969           C4 = Handle(Geom_BSplineCurve)::DownCast(BRep_Tool::Curve(E4,fp,lp));
1970         }
1971         else {
1972           Handle(TColgp_HArray1OfPnt) HAP = new TColgp_HArray1OfPnt(1,2);
1973           HAP->SetValue(1,P1);
1974           HAP->SetValue(2,P4);
1975           GeomAPI_Interpolate anInt(HAP,Standard_False,1.e-7);
1976           anInt.Load(aDir1,aDir2);
1977           anInt.Perform();
1978           C4 = anInt.Curve();
1979           B.MakeEdge(E4,anInt.Curve(),1.e-7);
1980           B.Add(E4,TopoDS::Vertex(V1.Oriented(TopAbs_FORWARD)));
1981           B.Add(E4,TopoDS::Vertex(V4.Oriented(TopAbs_REVERSED)));
1982           VPE.Add(V1,E4);
1983         }
1984
1985         TopoDS_Wire W;
1986         B.MakeWire(W);
1987         B.Add(W,E1);
1988         B.Add(W,E2);
1989         B.Add(W,E3);
1990         B.Add(W,E4.Reversed());
1991         //cout<<"      wire for edge "<<nbee<<" is created"<<endl;
1992         //BRepTools::Write(W,"/dn02/users_Linux/skl/work/Bugs/14857/w.brep");
1993
1994         // make surface
1995
1996         double fp,lp;
1997         Handle(Geom_Curve) C1 = BRep_Tool::Curve(E1,fp,lp);
1998         //bool IsConicC1 = false;
1999         //if (C1->IsKind(STANDARD_TYPE(Geom_Conic))) {
2000         //  IsConicC1 = true;
2001         //  cout<<"C1 - Geom_Conic"<<endl;
2002         //}
2003         if (C1->IsKind(STANDARD_TYPE(Geom_Line)) || C1->IsKind(STANDARD_TYPE(Geom_Conic))) {
2004           C1 = new Geom_TrimmedCurve(C1,fp,lp);
2005         }
2006         //if (IsConicC1) {
2007         //  double tol = BRep_Tool::Tolerance(E1);
2008         //  GeomConvert_ApproxCurve ApxC1(C1,tol,GeomAbs_C1,10,5);
2009         //  C1 = ApxC1.Curve();
2010         //}
2011         Handle(Geom_Curve) C3 = BRep_Tool::Curve(E3,fp,lp);
2012         if (C3->IsKind(STANDARD_TYPE(Geom_Line)) || C3->IsKind(STANDARD_TYPE(Geom_Conic))) {
2013           C3 = new Geom_TrimmedCurve(C3,fp,lp);
2014         }
2015         //filebuf fic;
2016         //ostream os(&fic);
2017         //os.precision(15);
2018         Handle(Geom_BSplineCurve) CE1 =
2019           GeomConvert::CurveToBSplineCurve(C1,Convert_RationalC1);
2020         if (CE1->Degree()<3)
2021           CE1->IncreaseDegree(3);
2022         Handle(Geom_BSplineCurve) CE2 =
2023           GeomConvert::CurveToBSplineCurve(C2,Convert_RationalC1);
2024         if (CE2->Degree()<3)
2025           CE2->IncreaseDegree(3);
2026         Handle(Geom_BSplineCurve) CE3 =
2027           GeomConvert::CurveToBSplineCurve(C3,Convert_RationalC1);
2028         if (CE3->Degree()<3)
2029           CE3->IncreaseDegree(3);
2030         Handle(Geom_BSplineCurve) CE4 =
2031           GeomConvert::CurveToBSplineCurve(C4,Convert_RationalC1);
2032         if (CE4->Degree()<3)
2033           CE4->IncreaseDegree(3);
2034         //cout<<"CE1->Degree()="<<CE1->Degree()<<" CE2->Degree()="<<CE2->Degree()
2035         //    <<" CE3->Degree()="<<CE3->Degree()<<" CE4->Degree()="<<CE4->Degree()<<endl;
2036         //if (fic.open("/dn02/users_Linux/skl/work/Bugs/14857/ce1.brep",ios::out)) {
2037         //  os<<"DrawTrSurf_BSplineCurve"<<endl;
2038         //  GeomTools::Write(CE1,os);
2039         //  fic.close();
2040         //}
2041
2042         Handle(Geom_Surface) BS;
2043         try {
2044           GeomFill_BSplineCurves GF(CE1,CE2,CE3,CE4,GeomFill_CoonsStyle);
2045           //GeomFill_BSplineCurves GF(CE1,CE2,CE3,CE4,GeomFill_StretchStyle);
2046           BS = GF.Surface();
2047         }
2048         catch(...) {
2049           MESSAGE ("      can not create BSplineSurface - create Bezier");
2050           int NbP=26;
2051           TColgp_Array2OfPnt Points(1,NbP,1,NbP);
2052           double fp1,lp1,fp2,lp2;
2053           Handle(Geom_Curve) C1 = BRep_Tool::Curve(E1,fp1,lp1);
2054           Handle(Geom_Curve) C3 = BRep_Tool::Curve(E3,fp2,lp2);
2055           gp_Pnt P1C1,P2C1;
2056           C1->D0(fp1,P1C1);
2057           C1->D0(lp1,P2C1);
2058           gp_Pnt P1C3,P2C3;
2059           C3->D0(fp2,P1C3);
2060           C3->D0(lp2,P2C3);
2061           int n1,n2;
2062           double fp,lp;
2063           // get points from C1
2064           if (P1.Distance(P1C1)<1.e-6) {
2065             fp = fp1;
2066             lp = lp1;
2067           }
2068           else {
2069             fp = lp1;
2070             lp = fp1;
2071           }
2072           double step = (lp-fp)/(NbP-1);
2073           Points.SetValue(1,1,P1);
2074           double par = fp;
2075           for (n1=2; n1<NbP; n1++) {
2076             gp_Pnt P;
2077             par += step;
2078             C1->D0(par,P);
2079             Points.SetValue(1,n1,P);
2080           }
2081           Points.SetValue(1,NbP,P2);
2082           // get points from C3
2083           if (P4.Distance(P1C3)<1.e-6) {
2084             fp = fp2;
2085             lp = lp2;
2086           }
2087           else {
2088             fp = lp2;
2089             lp = fp2;
2090           }
2091           step = (lp-fp)/(NbP-1);
2092           Points.SetValue(NbP,1,P4);
2093           par = fp;
2094           for (n1=2; n1<NbP; n1++) {
2095             gp_Pnt P;
2096             par += step;
2097             C3->D0(par,P);
2098             Points.SetValue(NbP,n1,P);
2099           }
2100           Points.SetValue(NbP,NbP,P3);
2101           // create isolines and get points from them
2102           for (n1=1; n1<=NbP; n1++) {
2103             gp_Pnt PI1 = Points.Value(1,n1);
2104             gp_Pnt PI2 = Points.Value(NbP,n1);
2105             Handle(TColgp_HArray1OfPnt) HAP = new TColgp_HArray1OfPnt(1,2);
2106             HAP->SetValue(1,PI1);
2107             HAP->SetValue(2,PI2);
2108             GeomAPI_Interpolate anInt(HAP,Standard_False,1.e-7);
2109             anInt.Load(aDir1,aDir2);
2110             anInt.Perform();
2111             Handle(Geom_Curve) iso = anInt.Curve();
2112             fp = iso->FirstParameter();
2113             lp = iso->LastParameter();
2114             step = (lp-fp)/(NbP-1);
2115             par = fp;
2116             TopoDS_Compound VComp;
2117             B.MakeCompound(VComp);
2118             for (n2=2; n2<NbP; n2++) {
2119               gp_Pnt P;
2120               par += step;
2121               iso->D0(par,P);
2122               Points.SetValue(n2,n1,P);
2123             }
2124           }
2125           // create surface and face
2126           //Handle(Geom_BezierSurface) BS = new Geom_BezierSurface(Points);
2127           BS = new Geom_BezierSurface(Points);
2128         }
2129
2130         BRepBuilderAPI_MakeFace BB(BS,W);
2131         TopoDS_Face NewF = BB.Face();
2132         Handle(ShapeFix_Face) sff = new ShapeFix_Face(NewF);
2133         sff->Perform();
2134         sff->FixOrientation();
2135         TopoDS_Face FixedFace = sff->Face();
2136         aNewFs.Append(FixedFace);
2137         VPE.Add(E1,FixedFace);
2138         //cout<<"      face for edge "<<nbee<<" is created"<<endl;
2139         //BRepTools::Write(FixedFace,"/dn02/users_Linux/skl/work/Bugs/14857/f.brep");
2140       }
2141       // make shell
2142       TopoDS_Shell aShell;
2143       B.MakeShell(aShell);
2144       for (int nf=1; nf<=aNewFs.Length(); nf++) {
2145         B.Add(aShell,aNewFs(nf));
2146       }
2147       B.Add(aShell,F1);
2148       B.Add(aShell,F2);
2149
2150       // make sewing for this shell
2151       Handle(BRepBuilderAPI_Sewing) aSewing = new BRepBuilderAPI_Sewing;
2152       aSewing->SetTolerance(Precision::Confusion());
2153       aSewing->SetFaceMode(Standard_True);
2154       aSewing->SetFloatingEdgesMode(Standard_False);
2155       aSewing->SetNonManifoldMode(Standard_False);
2156       for (anExp.Init(aShell, TopAbs_FACE); anExp.More(); anExp.Next()) {
2157         aSewing->Add(anExp.Current());
2158       }
2159       aSewing->Perform();
2160       MESSAGE ("    shell for face "<<nbff<<" is created");
2161       const TopoDS_Shape aSewShape = aSewing->SewedShape();
2162       //BRepTools::Write(aSewShape,"/dn02/users_Linux/skl/work/Bugs/14857/sew.brep");
2163       if (aSewShape.ShapeType() == TopAbs_SHELL) {
2164         aShell = TopoDS::Shell(aSewShape);
2165         GProp_GProps aSystem;
2166         BRepGProp::VolumeProperties(aShell, aSystem);
2167         if (aSystem.Mass()<0) {
2168           //cout<<"aSewShape is reversed"<<endl;
2169           aShell.Reverse();
2170         }
2171         if (BRep_Tool::IsClosed(aShell)) {
2172           TopoDS_Solid aSolid;
2173           B.MakeSolid(aSolid);
2174           B.Add(aSolid,aShell);
2175           B.Add(aComp,aSolid);
2176           MESSAGE ("    solid for face "<<nbff<<" is created");
2177         }
2178         else {
2179           B.Add(aComp,aShell);
2180           MESSAGE ("    solid for face "<<nbff<<" is not created");
2181         }
2182       }
2183       else {
2184         B.Add(aComp,aShell);
2185         MESSAGE ("    solid for face "<<nbff<<" is not created");
2186       }
2187       //cout<<"    solid for face "<<nbff<<" is created"<<endl;
2188
2189       //Handle(ShapeFix_Shell) sfs = new ShapeFix_Shell(aShell);
2190       //sfs->Perform();
2191       //TopoDS_Shell FixedShell = sfs->Shell();
2192       /*
2193       GProp_GProps aSystem;
2194       BRepGProp::VolumeProperties(FixedShell, aSystem);
2195       if (aSystem.Mass()<0) {
2196         //cout<<"aSewShape is reversed"<<endl;
2197         FixedShell.Reverse();
2198       }
2199       if (BRep_Tool::IsClosed(FixedShell)) {
2200         TopoDS_Solid aSolid;
2201         B.MakeSolid(aSolid);
2202         B.Add(aSolid,aShell);
2203         B.Add(aComp,aSolid);
2204       }
2205       else {
2206         B.Add(aComp,FixedShell);
2207       }
2208       */
2209     }
2210   }
2211
2212   //BRepTools::Write(aComp,"/dn02/users_Linux/skl/work/Bugs/14857/comp.brep");
2213   return aComp;
2214 }
2215
2216 //=======================================================================
2217 //function : CreatePipeBiNormalAlongVector
2218 //purpose  : auxilary for Execute()
2219 //=======================================================================
2220 static TopoDS_Shape CreatePipeBiNormalAlongVector(const TopoDS_Wire& aWirePath,
2221                                                   GEOMImpl_IPipe* aCI)
2222 {
2223   GEOMImpl_IPipeBiNormal* aCIBN = (GEOMImpl_IPipeBiNormal*)aCI;
2224
2225   Handle(GEOM_Function) aRefBase = aCIBN->GetBase();
2226   Handle(GEOM_Function) aRefVec = aCIBN->GetVector();
2227   TopoDS_Shape aShapeBase = aRefBase->GetValue();
2228   TopoDS_Shape aShapeVec = aRefVec->GetValue();
2229
2230   if (aShapeBase.IsNull()) {
2231     if (aCIBN) delete aCIBN;
2232     Standard_NullObject::Raise("MakePipe aborted : null base argument");
2233   }
2234
2235   // Make copy to prevent modifying of base object: 0021525
2236   BRepBuilderAPI_Copy Copy (aShapeBase);
2237   if (Copy.IsDone())
2238     aShapeBase = Copy.Shape();
2239
2240   TopoDS_Shape aProf;
2241   if (aShapeBase.ShapeType() == TopAbs_VERTEX) {
2242     aProf = aShapeBase;
2243   }
2244   else if (aShapeBase.ShapeType() == TopAbs_EDGE) {
2245     aProf = BRepBuilderAPI_MakeWire(TopoDS::Edge(aShapeBase)).Shape();
2246   }
2247   else if (aShapeBase.ShapeType() == TopAbs_WIRE) {
2248     aProf = aShapeBase;
2249   }
2250   else if (aShapeBase.ShapeType() == TopAbs_FACE) {
2251     TopExp_Explorer wexp (aShapeBase,TopAbs_WIRE);
2252     aProf = wexp.Current();
2253   }
2254   else {
2255     Standard_TypeMismatch::Raise
2256       ("MakePipe aborted : invalid type of base");
2257   }
2258   BRepOffsetAPI_MakePipeShell PipeBuilder (aWirePath);
2259   PipeBuilder.Add(aProf);
2260
2261   if (aShapeVec.IsNull()) {
2262     if (aCIBN) delete aCIBN;
2263     Standard_NullObject::Raise
2264       ("MakePipe aborted : null vector argument");
2265   }
2266   if (aShapeVec.ShapeType() != TopAbs_EDGE)
2267     Standard_TypeMismatch::Raise
2268       ("MakePipe aborted: invalid type of vector");
2269   TopoDS_Edge anEdge = TopoDS::Edge(aShapeVec);
2270   TopoDS_Vertex V1, V2;
2271   TopExp::Vertices(anEdge, V1, V2, Standard_True);
2272   if (V1.IsNull() || V2.IsNull())
2273     Standard_NullObject::Raise
2274       ("MakePipe aborted: vector is not defined");
2275   gp_Vec aVec(BRep_Tool::Pnt(V1), BRep_Tool::Pnt(V2));
2276   gp_Dir BiNormal(aVec);
2277   PipeBuilder.SetMode(BiNormal);
2278   PipeBuilder.Build();
2279   if (aShapeBase.ShapeType() == TopAbs_FACE) {
2280       PipeBuilder.MakeSolid();
2281   }
2282
2283   return PipeBuilder.Shape();
2284 }
2285
2286 //=======================================================================
2287 //function : Execute
2288 //purpose  :
2289 //=======================================================================
2290 Standard_Integer GEOMImpl_PipeDriver::Execute (TFunction_Logbook& log) const
2291 {
2292   if (Label().IsNull()) return 0;
2293   Handle(GEOM_Function) aFunction = GEOM_Function::GetFunction(Label());
2294   Standard_Integer aType = aFunction->GetType();
2295
2296   GEOMImpl_IPipe* aCI = 0;
2297   if (aType == PIPE_BASE_PATH)
2298     aCI = new GEOMImpl_IPipe (aFunction);
2299   else if (aType == PIPE_DIFFERENT_SECTIONS)
2300     aCI = new GEOMImpl_IPipeDiffSect (aFunction);
2301   else if (aType == PIPE_SHELL_SECTIONS)
2302     aCI = new GEOMImpl_IPipeShellSect (aFunction);
2303   else if (aType == PIPE_SHELLS_WITHOUT_PATH)
2304     aCI = new GEOMImpl_IPipeShellSect (aFunction);
2305   else if (aType == PIPE_BI_NORMAL_ALONG_VECTOR)
2306     aCI = new GEOMImpl_IPipeBiNormal (aFunction);
2307   else
2308     return 0;
2309
2310   TopoDS_Wire aWirePath;
2311   if (aType != PIPE_SHELLS_WITHOUT_PATH) {
2312     // working with path
2313     Handle(GEOM_Function) aRefPath = aCI->GetPath();
2314     TopoDS_Shape aShapePath = aRefPath->GetValue();
2315
2316     if (aShapePath.IsNull()) {
2317       MESSAGE ("Driver : path is null");
2318       if (aCI) delete aCI;
2319       Standard_NullObject::Raise("MakePipe aborted : null path argument");
2320     }
2321
2322     // Get path contour
2323     bool isOk = false;
2324     if (aShapePath.ShapeType() == TopAbs_COMPOUND) {
2325       TopTools_SequenceOfShape anEdges;
2326       TopExp_Explorer anExp;
2327       BRep_Builder B;
2328       TopoDS_Wire W;
2329       B.MakeWire(W);
2330       for (anExp.Init(aShapePath, TopAbs_EDGE); anExp.More(); anExp.Next()) {
2331         B.Add(W, anExp.Current());
2332         isOk = true;
2333       }
2334       if (isOk)
2335         aWirePath = W;
2336     }
2337     else if (aShapePath.ShapeType() == TopAbs_WIRE) {
2338       aWirePath = TopoDS::Wire(aShapePath);
2339       isOk = true;
2340     }
2341     else {
2342       if (aShapePath.ShapeType() == TopAbs_EDGE) {
2343         TopoDS_Edge anEdge = TopoDS::Edge(aShapePath);
2344         aWirePath = BRepBuilderAPI_MakeWire(anEdge);
2345         isOk = true;
2346       }
2347     }
2348     if (!isOk) {
2349       if (aCI) delete aCI;
2350       Standard_TypeMismatch::Raise("MakePipe aborted : path shape is neither a wire nor an edge");
2351     }
2352   }
2353
2354   TopoDS_Shape aShape;
2355
2356   if (aType == PIPE_BASE_PATH) {
2357     Handle(GEOM_Function) aRefBase = aCI->GetBase();
2358     TopoDS_Shape aShapeBase;
2359
2360     // Make copy to prevent modifying of base object 0020766 : EDF 1320
2361     BRepBuilderAPI_Copy Copy(aRefBase->GetValue());
2362     if (Copy.IsDone())
2363       aShapeBase = Copy.Shape();
2364
2365     if (aShapeBase.IsNull()) {
2366       if (aCI) delete aCI;
2367       Standard_NullObject::Raise("MakePipe aborted : null base argument");
2368     }
2369
2370     // Make pipe
2371     if (aShapeBase.ShapeType() == TopAbs_EDGE ||
2372         aShapeBase.ShapeType() == TopAbs_WIRE)
2373     {
2374       TopoDS_Wire Profile;
2375       if (aShapeBase.ShapeType() == TopAbs_WIRE)
2376         Profile = TopoDS::Wire(aShapeBase);
2377       else
2378       {
2379         BRep_Builder BB;
2380         BB.MakeWire(Profile);
2381         BB.Add(Profile, aShapeBase);
2382       }
2383
2384       BRepOffsetAPI_MakePipeShell Sweep (aWirePath);
2385       BRepBuilderAPI_MakeFace FaceBuilder (aWirePath, Standard_True); //to find the plane of spine
2386       if (FaceBuilder.IsDone())
2387         Sweep.SetMode(FaceBuilder.Face());
2388       Sweep.Add(Profile);
2389       Sweep.Build();
2390       
2391       if (!Sweep.IsDone())
2392       {
2393         if (aCI) delete aCI;
2394         Standard_ConstructionError::Raise("MakePipeShell failed");
2395       }
2396       else
2397         aShape = Sweep.Shape(); //result is good
2398       
2399     }
2400     else
2401       aShape = BRepOffsetAPI_MakePipe(aWirePath, aShapeBase);
2402   }
2403
2404   //building pipe with different sections
2405   else if (aType == PIPE_DIFFERENT_SECTIONS) {
2406     GEOMImpl_IPipeDiffSect* aCIDS = (GEOMImpl_IPipeDiffSect*)aCI;
2407     Handle(TColStd_HSequenceOfTransient) aBasesObjs = aCIDS->GetBases ();
2408     Handle(TColStd_HSequenceOfTransient) aLocObjs = aCIDS->GetLocations ();
2409     Standard_Boolean aWithContact = (aCIDS->GetWithContactMode());
2410     Standard_Boolean aWithCorrect = (aCIDS->GetWithCorrectionMode());
2411     if (aCI) {
2412       delete aCI;
2413       aCI = 0;
2414     }
2415
2416     Standard_Integer nbBases = aBasesObjs->Length();
2417     Standard_Integer nbLocs  = (aLocObjs.IsNull() ? 0 : aLocObjs->Length());
2418
2419     Handle(TopTools_HSequenceOfShape) aHSeqBases = new TopTools_HSequenceOfShape;
2420     Handle(TopTools_HSequenceOfShape) aHSeqLocs  = new TopTools_HSequenceOfShape;
2421     Standard_Integer i;
2422
2423     for (i = 1; i <= nbBases; i++) {
2424       Handle(Standard_Transient) anItem = aBasesObjs->Value(i);
2425       if (anItem.IsNull())
2426         continue;
2427       Handle(GEOM_Function) aRefBase = Handle(GEOM_Function)::DownCast(anItem);
2428       if (aRefBase.IsNull())
2429         continue;
2430       if (aRefBase->GetValue().IsNull())
2431         continue;
2432
2433       aHSeqBases->Append(aRefBase->GetValue());
2434     }
2435     for (i = 1; i <= nbLocs; i++) {
2436       Handle(Standard_Transient) anItemLoc = aLocObjs->Value(i);
2437       if (anItemLoc.IsNull())
2438         continue;
2439       Handle(GEOM_Function) aRefLoc = Handle(GEOM_Function)::DownCast(anItemLoc);
2440       TopoDS_Shape aShapeLoc = aRefLoc->GetValue();
2441       if (aShapeLoc.IsNull() || aShapeLoc.ShapeType() != TopAbs_VERTEX)
2442         continue;
2443
2444       aHSeqLocs->Append(aShapeLoc);
2445     }
2446
2447     aShape = CreatePipeWithDifferentSections(aWirePath, aHSeqBases, aHSeqLocs, aWithContact, aWithCorrect);
2448   }
2449
2450   //building pipe with shell sections
2451   else if (aType == PIPE_SHELL_SECTIONS) {
2452     aShape = CreatePipeForShellSections(aWirePath,aCI);
2453   }
2454
2455   //building pipe shell sections without path
2456   else if (aType == PIPE_SHELLS_WITHOUT_PATH) {
2457     aShape = CreatePipeShellsWithoutPath(aCI);
2458   }
2459
2460   //building a pipe with constant bi-normal along given vector
2461   else if (aType == PIPE_BI_NORMAL_ALONG_VECTOR) {
2462     aShape = CreatePipeBiNormalAlongVector(aWirePath, aCI);
2463   }
2464
2465   if (aCI) {
2466     delete aCI;
2467     aCI = 0;
2468   }
2469
2470   if (aShape.IsNull()) return 0;
2471
2472   BRepCheck_Analyzer ana (aShape, Standard_False);
2473   if (!ana.IsValid()) {
2474     ShapeFix_ShapeTolerance aSFT;
2475     aSFT.LimitTolerance(aShape,Precision::Confusion(),Precision::Confusion());
2476     Handle(ShapeFix_Shape) aSfs = new ShapeFix_Shape(aShape);
2477     aSfs->SetPrecision(Precision::Confusion());
2478     aSfs->Perform();
2479     aShape = aSfs->Shape();
2480
2481     ana.Init(aShape, Standard_False);
2482     if (!ana.IsValid())
2483       Standard_ConstructionError::Raise("Algorithm have produced an invalid shape result");
2484   }
2485
2486   // Glue (for bug 0020207)
2487   // No gluing is needed as the bug 0020207 is fixed in OCCT.
2488 #ifdef GLUE_0020207
2489   TopExp_Explorer anExpV (aShape, TopAbs_VERTEX);
2490   if (anExpV.More()) {
2491     Standard_Real aVertMaxTol = -RealLast();
2492     for (; anExpV.More(); anExpV.Next()) {
2493       TopoDS_Vertex aVertex = TopoDS::Vertex(anExpV.Current());
2494       Standard_Real aTol = BRep_Tool::Tolerance(aVertex);
2495       if (aTol > aVertMaxTol)
2496         aVertMaxTol = aTol;
2497     }
2498     aVertMaxTol += Precision::Confusion();
2499     aShape = GEOMImpl_GlueDriver::GlueFaces(aShape, aVertMaxTol, Standard_True);
2500     //aShape = GEOMImpl_GlueDriver::GlueFaces(aShape, Precision::Confusion(), Standard_True);
2501   }
2502 #endif
2503
2504   TopoDS_Shape aRes = GEOMUtils::CompsolidToCompound(aShape);
2505   aFunction->SetValue(aRes);
2506
2507   log.SetTouched(Label());
2508   return 1;
2509 }
2510
2511 //=======================================================================
2512 //function :  GEOMImpl_PipeDriver_Type_
2513 //purpose  :
2514 //=======================================================================
2515 Standard_EXPORT Handle_Standard_Type& GEOMImpl_PipeDriver_Type_()
2516 {
2517   static Handle_Standard_Type aType1 = STANDARD_TYPE(TFunction_Driver);
2518   if (aType1.IsNull()) aType1 = STANDARD_TYPE(TFunction_Driver);
2519   static Handle_Standard_Type aType2 = STANDARD_TYPE(MMgt_TShared);
2520   if (aType2.IsNull()) aType2 = STANDARD_TYPE(MMgt_TShared);
2521   static Handle_Standard_Type aType3 = STANDARD_TYPE(Standard_Transient);
2522   if (aType3.IsNull()) aType3 = STANDARD_TYPE(Standard_Transient);
2523
2524   static Handle_Standard_Transient _Ancestors[]= {aType1,aType2,aType3,NULL};
2525   static Handle_Standard_Type _aType = new Standard_Type("GEOMImpl_PipeDriver",
2526                                                          sizeof(GEOMImpl_PipeDriver),
2527                                                          1,
2528                                                          (Standard_Address)_Ancestors,
2529                                                          (Standard_Address)NULL);
2530
2531   return _aType;
2532 }
2533
2534 //=======================================================================
2535 //function : DownCast
2536 //purpose  :
2537 //=======================================================================
2538 const Handle(GEOMImpl_PipeDriver) Handle(GEOMImpl_PipeDriver)::DownCast(const Handle(Standard_Transient)& AnObject)
2539 {
2540   Handle(GEOMImpl_PipeDriver) _anOtherObject;
2541
2542   if (!AnObject.IsNull()) {
2543      if (AnObject->IsKind(STANDARD_TYPE(GEOMImpl_PipeDriver))) {
2544        _anOtherObject = Handle(GEOMImpl_PipeDriver)((Handle(GEOMImpl_PipeDriver)&)AnObject);
2545      }
2546   }
2547
2548   return _anOtherObject;
2549 }