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