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