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