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