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