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