Salome HOME
Porting to Qt4.
[modules/geom.git] / src / GEOMImpl / GEOMImpl_PipeDriver.cxx
1 // Copyright (C) 2005  OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
2 // CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
3 // 
4 // This library is free software; you can redistribute it and/or
5 // modify it under the terms of the GNU Lesser General Public
6 // License as published by the Free Software Foundation; either 
7 // version 2.1 of the License.
8 // 
9 // This library is distributed in the hope that it will be useful 
10 // but WITHOUT ANY WARRANTY; without even the implied warranty of 
11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU 
12 // Lesser General Public License for more details.
13 //
14 // You should have received a copy of the GNU Lesser General Public  
15 // License along with this library; if not, write to the Free Software 
16 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
17 //
18 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
19 //
20
21 #include <Standard_Stream.hxx>
22
23 #include <GEOMImpl_PipeDriver.hxx>
24 #include <GEOMImpl_IPipe.hxx>
25 #include <GEOMImpl_Types.hxx>
26 #include <GEOM_Function.hxx>
27
28 #include <BRep_Tool.hxx>
29 #include <BRepCheck_Analyzer.hxx>
30 #include <BRepOffsetAPI_MakePipe.hxx>
31 #include <BRepBuilderAPI_MakeWire.hxx>
32
33 #include <TopAbs.hxx>
34 #include <TopoDS.hxx>
35 #include <TopoDS_Wire.hxx>
36 #include <TopoDS_Edge.hxx>
37 #include <TopoDS_Shape.hxx>
38 #include <TopoDS_Solid.hxx>
39 #include <TopoDS_Shell.hxx>
40 #include <TopoDS_Face.hxx>
41 #include <BRepOffsetAPI_MakePipeShell.hxx>
42 #include <TColStd_HSequenceOfTransient.hxx>
43 #include <GEOMImpl_IPipeDiffSect.hxx>
44 #include <GEOMImpl_IPipeShellSect.hxx>
45
46 #include <Standard_NullObject.hxx>
47 #include <Standard_TypeMismatch.hxx>
48 #include <Standard_ConstructionError.hxx>
49 #include "utilities.h"
50 #include <TopExp_Explorer.hxx>
51 #include <TopTools_SequenceOfShape.hxx>
52 #include <BRep_Builder.hxx>
53 #include <TopoDS_Compound.hxx>
54 #include <ShapeAnalysis_FreeBounds.hxx>
55 #include <TColgp_SequenceOfPnt.hxx>
56 #include <ShapeAnalysis_Edge.hxx>
57 #include <TopTools_IndexedDataMapOfShapeShape.hxx>
58 #include <TopTools_IndexedDataMapOfShapeListOfShape.hxx>
59 #include <TopExp.hxx>
60 #include <TopTools_ListIteratorOfListOfShape.hxx>
61 #include <GeomAPI_ProjectPointOnCurve.hxx>
62 #include <Precision.hxx>
63 #include <Geom_TrimmedCurve.hxx>
64 #include <BRepBuilderAPI_Sewing.hxx>
65
66 //#include <BRepTools.hxx>
67
68
69 //=======================================================================
70 //function : GetID
71 //purpose  :
72 //=======================================================================
73 const Standard_GUID& GEOMImpl_PipeDriver::GetID()
74 {
75   static Standard_GUID aPipeDriver("FF1BBB19-5D14-4df2-980B-3A668264EA16");
76   return aPipeDriver;
77 }
78
79
80 //=======================================================================
81 //function : GEOMImpl_PipeDriver
82 //purpose  :
83 //=======================================================================
84 GEOMImpl_PipeDriver::GEOMImpl_PipeDriver()
85 {
86 }
87
88
89 //=======================================================================
90 //function : FillForOtherEdges
91 //purpose  : auxilary for CreatePipeForShellSections()
92 //=======================================================================
93 static bool FillForOtherEdges(const TopoDS_Shape& F1,
94                               const TopoDS_Shape& E1,
95                               const TopoDS_Shape& V1,
96                               TopTools_IndexedDataMapOfShapeShape& FF)
97 {
98   //cout<<"FillForOtherEdges"<<endl;
99   // find other pairs for vertexes and edges
100   // creating map of vertex edges for both faces
101   TopTools_IndexedDataMapOfShapeListOfShape aMapVertEdge1;
102   TopExp::MapShapesAndAncestors(F1, TopAbs_VERTEX, TopAbs_EDGE, aMapVertEdge1);
103   const TopoDS_Shape& F2 = FF.FindFromKey(F1);
104   const TopoDS_Shape& E2 = FF.FindFromKey(E1);
105   const TopoDS_Shape& V2 = FF.FindFromKey(V1);
106   TopTools_IndexedDataMapOfShapeListOfShape aMapVertEdge2;
107   TopExp::MapShapesAndAncestors(F2, TopAbs_VERTEX, TopAbs_EDGE, aMapVertEdge2);
108
109   TopoDS_Edge ES1 = TopoDS::Edge(E1);
110   TopoDS_Edge ES2 = TopoDS::Edge(E2);
111   TopoDS_Shape VS1 = V1;
112   TopoDS_Shape VS2 = V2;
113
114   ShapeAnalysis_Edge sae;
115   while(1) {
116     const TopTools_ListOfShape& aList1 = aMapVertEdge1.FindFromKey(VS1);
117     //TopoDS_Shape E1next;
118     TopTools_ListIteratorOfListOfShape anIter1(aList1);
119     if(anIter1.Value().IsSame(ES1)) {
120       anIter1.Next();
121     }
122     //E1next = anIter1.Value();
123     const TopTools_ListOfShape& aList2 = aMapVertEdge2.FindFromKey(VS2);
124     //TopoDS_Shape E2next;
125     TopTools_ListIteratorOfListOfShape anIter2(aList2);
126     if(anIter2.Value().IsSame(ES2)) {
127       anIter2.Next();
128     }
129     //E2next = anIter2.Value();
130     //ES1 = TopoDS::Edge(E1next);
131     //ES2 = TopoDS::Edge(E2next);
132     ES1 = TopoDS::Edge(anIter1.Value());
133     ES2 = TopoDS::Edge(anIter2.Value());
134     if(!FF.Contains(ES1)) {
135       FF.Add(ES1,ES2);
136     }
137     if(VS1.IsSame(sae.FirstVertex(ES1)))
138       VS1 = sae.LastVertex(ES1);
139     else
140       VS1 = sae.FirstVertex(ES1);
141     if(VS2.IsSame(sae.FirstVertex(ES2)))
142       VS2 = sae.LastVertex(ES2);
143     else
144       VS2 = sae.FirstVertex(ES2);
145     if(VS1.IsSame(V1))
146       break;
147     if(!FF.Contains(VS1)) {
148       FF.Add(VS1,VS2);
149     }
150   }
151
152   return true;
153 }
154
155
156 //=======================================================================
157 //function : FillCorrespondingEdges
158 //purpose  : auxilary for CreatePipeForShellSections()
159 //=======================================================================
160 static bool FillCorrespondingEdges(const TopoDS_Shape& FS1,
161                                    const TopoDS_Shape& FS2,
162                                    const TopoDS_Vertex& aLoc1,
163                                    const TopoDS_Vertex& aLoc2,
164                                    const TopoDS_Wire& aWirePath,
165                                    TopTools_IndexedDataMapOfShapeShape& FF)
166 {
167   //cout<<"FillCorrespondingEdges"<<endl;
168   // find corresponding edges
169   TopExp_Explorer expw1(FS1,TopAbs_WIRE);
170   TopoDS_Wire aWire1 = TopoDS::Wire(expw1.Current());
171   //exp = TopExp_Explorer(FS2,TopAbs_WIRE);
172   TopExp_Explorer expw2(FS2,TopAbs_WIRE);
173   TopoDS_Wire aWire2 = TopoDS::Wire(expw2.Current());
174   BRepOffsetAPI_MakePipeShell aBuilder(aWirePath);
175   aBuilder.Add(aWire1, aLoc1);
176   aBuilder.Add(aWire2, aLoc2);
177   if(!aBuilder.IsReady()) {
178     return false;
179   }
180   aBuilder.Build();
181   TopoDS_Shape aShape = aBuilder.Shape();
182   /*
183   TopoDS_Compound C;
184   BRep_Builder B;
185   B.MakeCompound(C);
186   B.Add(C,aShape);
187   B.Add(C,FS1);
188   B.Add(C,FS2);
189   BRepTools::Write(C,"/dn02/users_Linux/skl/work/Bugs/14857/comp.brep");
190   */
191   ShapeAnalysis_Edge sae;
192   double tol = Max( BRep_Tool::Tolerance(TopoDS::Face(FS1)),
193                     BRep_Tool::Tolerance(TopoDS::Face(FS2)) );
194   TopTools_MapOfShape Vs1,Vs2;
195   TopExp_Explorer exp;
196   exp.Init( FS1, TopAbs_EDGE );
197   TopoDS_Edge E1 = TopoDS::Edge(exp.Current());
198   TopoDS_Vertex V11 = sae.FirstVertex(E1);
199   TopoDS_Vertex V21 = sae.LastVertex(E1);
200   gp_Pnt P11 = BRep_Tool::Pnt(V11);
201   gp_Pnt P21 = BRep_Tool::Pnt(V21);
202   //cout<<"P11("<<P11.X()<<","<<P11.Y()<<","<<P11.Z()<<")"<<endl;
203   //cout<<"P21("<<P21.X()<<","<<P21.Y()<<","<<P21.Z()<<")"<<endl;
204   // find corresponding vertexes from created shape
205   TopoDS_Vertex VN11,VN21;
206   for( exp.Init( aShape, TopAbs_VERTEX ); exp.More(); exp.Next() ) {
207     TopoDS_Vertex V = TopoDS::Vertex(exp.Current());
208     gp_Pnt P = BRep_Tool::Pnt(V);
209     if(P.Distance(P11)<tol) {
210       VN11 = V;
211     }
212     if(P.Distance(P21)<tol) {
213       VN21 = V;
214     }
215   }
216   // find edge contains VN11 and VN21 and corresponding vertexes
217   TopoDS_Vertex VN12,VN22;
218   for( exp.Init( aShape, TopAbs_FACE ); exp.More(); exp.Next() ) {
219     TopoDS_Shape F = exp.Current();
220     TopExp_Explorer expe;
221     bool IsFind = false;
222     for( expe.Init( F, TopAbs_EDGE ); expe.More(); expe.Next() ) {
223       TopoDS_Edge E = TopoDS::Edge(expe.Current());
224       TopoDS_Vertex VF = sae.FirstVertex(E);
225       TopoDS_Vertex VL = sae.LastVertex(E);
226       if( (VF.IsSame(VN11) && VL.IsSame(VN21)) || (VF.IsSame(VN21) && VL.IsSame(VN11)) ) {
227         IsFind = true;
228         break;
229       }
230     }
231     if(IsFind) {
232       for( expe.Init( F, TopAbs_EDGE ); expe.More(); expe.Next() ) {
233         TopoDS_Edge E = TopoDS::Edge(expe.Current());
234         TopoDS_Vertex VF = sae.FirstVertex(E);
235         TopoDS_Vertex VL = sae.LastVertex(E);
236         if( VF.IsSame(VN11) && !VL.IsSame(VN21) )
237           VN12 = VL;
238         if( VL.IsSame(VN11) && !VF.IsSame(VN21) )
239           VN12 = VF;
240         if( VF.IsSame(VN21) && !VL.IsSame(VN11) )
241           VN22 = VL;
242         if( VL.IsSame(VN21) && !VF.IsSame(VN11) )
243           VN22 = VF;
244       }
245       break;
246     }
247   }
248   // find vertexes from FS2 corresponded to VN12 and VN22
249   // and find edge from FS2 contains V12 and V22,
250   // this edge will be corresponded to edge E1
251   TopoDS_Vertex V12,V22;
252   gp_Pnt PN12 = BRep_Tool::Pnt(VN12);
253   gp_Pnt PN22 = BRep_Tool::Pnt(VN22);
254   //cout<<"PN12("<<PN12.X()<<","<<PN12.Y()<<","<<PN12.Z()<<")"<<endl;
255   //cout<<"PN22("<<PN22.X()<<","<<PN22.Y()<<","<<PN22.Z()<<")"<<endl;
256   TopoDS_Edge E2;
257   TopExp_Explorer expe;
258   for( expe.Init( FS2, TopAbs_EDGE ); expe.More(); expe.Next() ) {
259     TopoDS_Edge E = TopoDS::Edge(expe.Current());
260     TopoDS_Vertex VF = sae.FirstVertex(E);
261     TopoDS_Vertex VL = sae.LastVertex(E);
262     gp_Pnt PF = BRep_Tool::Pnt(VF);
263     gp_Pnt PL = BRep_Tool::Pnt(VL);
264     if( PF.Distance(PN12)<tol && PL.Distance(PN22)<tol ) {
265       V12 = VF;
266       V22 = VL;
267       E2 = E;
268       break;
269     }
270     if( PF.Distance(PN22)<tol && PL.Distance(PN12)<tol ) {
271       V12 = VL;
272       V22 = VF;
273       E2 = E;
274       break;
275     }
276   }
277   FF.Add(V11,V12);
278   FF.Add(V21,V22);
279   FF.Add(E1,E2);
280
281   // find other pairs for vertexes and edges
282   // creating map of vertex edges for both faces
283   return FillForOtherEdges(FS1,E1,V21,FF);
284
285   //return true;
286 }
287
288
289 //=======================================================================
290 //function : FindNextPairOfFaces
291 //purpose  : auxilary for CreatePipeForShellSections()
292 //=======================================================================
293 static void FindNextPairOfFaces(const TopoDS_Shape& aCurFace,
294                                 TopTools_IndexedDataMapOfShapeListOfShape& aMapEdgeFaces1,
295                                 TopTools_IndexedDataMapOfShapeListOfShape& aMapEdgeFaces2,
296                                 TopTools_IndexedDataMapOfShapeShape& FF,
297                                 GEOMImpl_IPipe* aCI)
298 {
299   //cout<<"FindNextPairOfFaces"<<endl;
300   TopExp_Explorer anExp;
301   for ( anExp.Init( aCurFace, TopAbs_EDGE ); anExp.More(); anExp.Next() ) {
302     TopoDS_Shape E1 = anExp.Current();
303     if(!FF.Contains(E1)) {
304       if(aCI) delete aCI;
305       Standard_ConstructionError::Raise("FindNextPairOfFaces: Can not find edge in map");
306     }
307     const TopoDS_Shape& E2 = FF.FindFromKey(E1);
308     TopExp_Explorer anExpV;
309     anExpV.Init( E1, TopAbs_VERTEX );
310     TopoDS_Shape V1 = anExpV.Current();
311     if(!FF.Contains(V1)) {
312       if(aCI) delete aCI;
313       Standard_ConstructionError::Raise("FindNextPairOfFaces: Can not find vertex in map");
314     }
315
316     const TopTools_ListOfShape& aList1 = aMapEdgeFaces1.FindFromKey(E1);
317     if(aList1.Extent()<2)
318       continue;
319     TopTools_ListIteratorOfListOfShape anIter(aList1);
320     if(anIter.Value().IsEqual(aCurFace)) {
321       anIter.Next();
322     }
323     TopoDS_Shape F1other = anIter.Value();
324     if(FF.Contains(F1other))
325       continue;
326
327     const TopoDS_Shape& F2 = FF.FindFromKey(aCurFace);
328     const TopTools_ListOfShape& aList2 = aMapEdgeFaces2.FindFromKey(E2);
329     if(aList2.Extent()<2) {
330       if(aCI) delete aCI;
331       Standard_ConstructionError::Raise("FindNextPairOfFaces: Can not find corresponding face");
332     }
333     TopTools_ListIteratorOfListOfShape anIter2(aList2);
334     if(anIter2.Value().IsEqual(F2)) {
335       anIter2.Next();
336     }
337     TopoDS_Shape F2other = anIter2.Value();
338     FF.Add(F1other,F2other);
339
340     // add pairs of edges to FF
341     bool stat =  FillForOtherEdges(F1other,E1,V1,FF);
342     if( !stat ) {
343       if(aCI) delete aCI;
344       Standard_ConstructionError::Raise("FindNextPairOfFaces: Can not mapping other egdes");
345     }
346
347     FindNextPairOfFaces(F1other, aMapEdgeFaces1, aMapEdgeFaces2, FF, aCI);
348     
349   }
350 }
351
352
353 //=======================================================================
354 //function : CreatePipeForShellSections
355 //purpose  : auxilary for Execute()
356 //=======================================================================
357 static TopoDS_Shape CreatePipeForShellSections(const TopoDS_Wire& aWirePath,
358                                                GEOMImpl_IPipe* aCI)
359 {
360   //cout<<"CreatePipeForShellSections"<<endl;
361   //TopoDS_Shape res;
362   int i,j;
363   BRep_Builder B;
364
365   GEOMImpl_IPipeShellSect* aCIDS = (GEOMImpl_IPipeShellSect*)aCI;
366   Handle(TColStd_HSequenceOfTransient) aBasesObjs = aCIDS->GetBases();
367   Handle(TColStd_HSequenceOfTransient) aSubBasesObjs = aCIDS->GetSubBases();
368   Handle(TColStd_HSequenceOfTransient) aLocObjs = aCIDS->GetLocations();
369   Standard_Boolean aWithContact = (aCIDS->GetWithContactMode());
370   Standard_Boolean aWithCorrect = (aCIDS->GetWithCorrectionMode());
371
372   Standard_Integer nbBases = aBasesObjs->Length(), 
373     nbSubBases = (aSubBasesObjs.IsNull() ? 0 :aSubBasesObjs->Length()),
374     nbLocs = (aLocObjs.IsNull() ? 0 :aLocObjs->Length());
375     
376   if( nbLocs != nbBases) {
377     if(aCI) delete aCI;
378     Standard_ConstructionError::Raise("Number of sections is not equal to number of locations ");
379   }
380   if( nbSubBases && nbSubBases != nbBases) {
381     if(aCI) delete aCI;
382     Standard_ConstructionError::Raise("Number of sections is not equal to number of subsections ");
383   }
384
385   //BRepOffsetAPI_MakePipeShell aBuilder(aWirePath);
386
387   TopTools_SequenceOfShape VLocs;
388   for(i=1; i<=nbBases; i++) {
389     Handle(Standard_Transient) anItemLoc = aLocObjs->Value(i);
390     if(anItemLoc.IsNull())
391       continue;
392     Handle(GEOM_Function) aRefLoc = Handle(GEOM_Function)::DownCast(anItemLoc);
393     TopoDS_Shape aShapeLoc = aRefLoc->GetValue();
394     if(aShapeLoc.IsNull() || aShapeLoc.ShapeType() != TopAbs_VERTEX)
395       continue;
396     VLocs.Append(aShapeLoc);
397   }
398   nbLocs = VLocs.Length();
399   if( nbLocs != nbBases) {
400     if(aCI) delete aCI;
401     Standard_ConstructionError::Raise("One of location shapes is not a vertex");
402   }
403   // split wire path by location points
404   TColgp_SequenceOfPnt PLocs;
405   for(i=1; i<=nbLocs; i++) {
406     TopoDS_Vertex V = TopoDS::Vertex(VLocs.Value(i));
407     PLocs.Append(BRep_Tool::Pnt(V));
408   }
409   TopTools_SequenceOfShape Edges;
410   TopTools_SequenceOfShape Wires;
411   TopExp_Explorer anExp;
412   for ( anExp.Init( aWirePath, TopAbs_EDGE ); anExp.More(); anExp.Next() ) {
413     Edges.Append(anExp.Current());
414   }
415   ShapeAnalysis_Edge sae;
416   TopoDS_Edge edge = TopoDS::Edge(Edges.First());
417   double tol = BRep_Tool::Tolerance(edge);
418   TopoDS_Vertex VF = sae.FirstVertex(edge);
419   gp_Pnt PF = BRep_Tool::Pnt(VF);
420   //cout<<"PF("<<PF.X()<<","<<PF.Y()<<","<<PF.Z()<<")"<<endl;
421   if( PF.Distance(PLocs.First()) > tol ) {
422     if(aCI) delete aCI;
423     Standard_ConstructionError::Raise
424       ("First location shapes is not coincided with first vertex of aWirePath");
425   }
426   edge = TopoDS::Edge(Edges.Last());
427   tol = BRep_Tool::Tolerance(edge);
428   TopoDS_Vertex VL = sae.LastVertex(edge);
429   gp_Pnt PL = BRep_Tool::Pnt(VL);
430   if( PL.Distance(PLocs.Last()) > tol ) {
431     if(aCI) delete aCI;
432     Standard_ConstructionError::Raise
433       ("Last location shapes is not coincided with last vertex of aWirePath");
434   }
435   int jcurr = 2;
436   TopTools_SequenceOfShape tmpEdges;
437   for(i=1; i<=Edges.Length() && jcurr<nbLocs; i++) {
438     TopoDS_Edge E = TopoDS::Edge(Edges.Value(i));
439     tol = BRep_Tool::Tolerance(edge);
440     TopoDS_Vertex V1 = sae.FirstVertex(E);
441     TopoDS_Vertex V2 = sae.LastVertex(E);
442     gp_Pnt P1 = BRep_Tool::Pnt(V1);
443     gp_Pnt P2 = BRep_Tool::Pnt(V2);
444     if( P2.Distance(PLocs.Value(jcurr)) < tol ) {
445       // make wire from current edge and add created
446       // wire to Wires
447       TopoDS_Wire W;
448       B.MakeWire(W);
449       for(j=1; j<=tmpEdges.Length(); j++)
450         B.Add(W,tmpEdges.Value(j));
451       B.Add(W,E);
452       Wires.Append(W);
453       jcurr++;
454       tmpEdges.Clear();
455     }
456     else {
457       // find distance between E and aLocs(icurr)
458       double fp,lp;
459       Handle(Geom_Curve) C = BRep_Tool::Curve(E,fp,lp);
460       GeomAPI_ProjectPointOnCurve PPC (PLocs.Value(jcurr),C);
461       if( PPC.NbPoints()>0 &&
462           PLocs.Value(jcurr).Distance(PPC.Point(1)) < tol ) {
463         double param = PPC.Parameter(1);
464         gp_Pnt PC1;
465         C->D0(param,PC1);
466         // split current edge
467         Handle(Geom_TrimmedCurve) tc1 = new Geom_TrimmedCurve(C,fp,param);
468         Handle(Geom_TrimmedCurve) tc2 = new Geom_TrimmedCurve(C,param,lp);
469         TopoDS_Edge E1,E2;
470         if(PC1.Distance(P1)<tol) {
471           B.MakeEdge(E1,tc1,tol);
472           B.Add(E1,V1);
473           TopoDS_Shape tmpV = VLocs.Value(jcurr).Oriented(TopAbs_REVERSED);
474           B.Add(E1,TopoDS::Vertex(tmpV));
475           tmpEdges.Append(E1);
476           B.MakeEdge(E2,tc2,tol);
477           tmpV = VLocs.Value(jcurr).Oriented(TopAbs_FORWARD);
478           B.Add(E2,TopoDS::Vertex(tmpV));
479           B.Add(E2,V2);
480         }
481         else {
482           B.MakeEdge(E1,tc2,tol);
483           TopoDS_Shape tmpV = VLocs.Value(jcurr).Oriented(TopAbs_FORWARD);
484           B.Add(E1,TopoDS::Vertex(tmpV));
485           B.Add(E1,V1);
486           E1.Reverse();
487           tmpEdges.Append(E1);
488           B.MakeEdge(E2,tc1,tol);
489           B.Add(E2,V2);
490           tmpV = VLocs.Value(jcurr).Oriented(TopAbs_REVERSED);
491           B.Add(E2,TopoDS::Vertex(tmpV));
492           E2.Reverse();
493         }
494         // create wire from tmpEdges
495         TopoDS_Wire W;
496         B.MakeWire(W);
497         for(j=1; j<=tmpEdges.Length(); j++)
498           B.Add(W,tmpEdges.Value(j));
499         Wires.Append(W);
500         jcurr++;
501         tmpEdges.Clear();
502         Edges.Remove(i);
503         Edges.InsertAfter(i-1,E1);
504         Edges.InsertAfter(i,E2);
505       }
506       else {
507         tmpEdges.Append(edge);
508       }
509     }
510   }
511   // create wire from other edges
512   TopoDS_Wire W;
513   B.MakeWire(W);
514   for(; i<=Edges.Length(); i++)
515     B.Add(W,Edges.Value(i));
516   Wires.Append(W);
517   //cout<<"Wires.Length()="<<Wires.Length()<<endl;
518
519   if( Wires.Length() != nbLocs-1 ) {
520     if(aCI) delete aCI;
521     Standard_ConstructionError::Raise
522       ("One of location shapes is not lied on the path");
523   }
524
525   //TopTools_SequenceOfShape aSeqBases;
526   //TopTools_SequenceOfShape aSeqSubBases;
527   //TopTools_SequenceOfShape aSeqFaces;
528   TopoDS_Compound aComp;
529   B.MakeCompound(aComp);
530   for(i=1 ; i<nbBases; i++) {
531     TopoDS_Wire WPath = TopoDS::Wire(Wires.Value(i));
532     // 1 section
533     Handle(Standard_Transient) anItem1 = aBasesObjs->Value(i);
534     if(anItem1.IsNull())
535       continue;
536     Handle(GEOM_Function) aRefBase1 = Handle(GEOM_Function)::DownCast(anItem1);
537     if(aRefBase1.IsNull())
538       continue;
539     TopoDS_Shape aShBase1 = aRefBase1->GetValue();
540     if(aShBase1.IsNull())
541       continue;
542     TopAbs_ShapeEnum aType1 = aShBase1.ShapeType();
543     // 2 section
544     Handle(Standard_Transient) anItem2 = aBasesObjs->Value(i+1);
545     if(anItem2.IsNull())
546       continue;
547     Handle(GEOM_Function) aRefBase2 = Handle(GEOM_Function)::DownCast(anItem2);
548     if(aRefBase2.IsNull())
549       continue;
550     TopoDS_Shape aShBase2 = aRefBase2->GetValue();
551     if(aShBase2.IsNull())
552       continue;
553     TopAbs_ShapeEnum aType2 = aShBase2.ShapeType();
554     
555     //BRepTools::Write(aShBase1,"/dn02/users_Linux/skl/work/Bugs/14857/base1.brep");
556
557     bool OkSec = ( aType1==TopAbs_SHELL || aType1==TopAbs_FACE ) &&
558                  ( aType2==TopAbs_SHELL || aType2==TopAbs_FACE );
559     if( !OkSec ) {
560       if(aCI) delete aCI;
561       Standard_ConstructionError::Raise("One of section shapes has invalid type");
562     }
563
564     bool CreateFewSolids = false;
565     // compare sections
566     TopExp_Explorer anExp;
567     Standard_Integer nbf1 = 0;
568     for ( anExp.Init( aShBase1, TopAbs_FACE ); anExp.More(); anExp.Next() ) {
569       nbf1++;
570     }
571     Standard_Integer nbf2 = 0;
572     for ( anExp.Init( aShBase2, TopAbs_FACE ); anExp.More(); anExp.Next() ) {
573       nbf2++;
574     }
575     if(nbf1==nbf2) {
576       CreateFewSolids = true;
577     }
578
579     if(!CreateFewSolids) {
580       // we can create only one solid
581       TopoDS_Shape aWire1, aWire2;
582       // prepare aWire1
583       if(aType1==TopAbs_SHELL) {
584         // create wire as boundary contour if shell is no closed
585         // get free boundary shapes
586         ShapeAnalysis_FreeBounds anAnalizer( aShBase1 );
587         TopoDS_Compound aClosed = anAnalizer.GetClosedWires();
588         //TopExp_Explorer anExp;
589         Standard_Integer NbWires = 0;
590         for ( anExp.Init( aClosed, TopAbs_WIRE ); anExp.More(); anExp.Next() ) {
591           NbWires++;
592           aWire1 = anExp.Current();
593         }
594         if(NbWires!=1) {
595           // bad case
596           if(aCI) delete aCI;
597           Standard_ConstructionError::Raise("Bad shell is used as section ");
598         }
599       }
600       else { // aType1==TopAbs_FACE
601         TopExp_Explorer aExpW(aShBase1,TopAbs_WIRE);
602         aWire1 = aExpW.Current();
603       }
604       // prepare aWire2
605       if(aType2==TopAbs_SHELL) {
606         // create wire as boundary contour if shell is no closed
607         // get free boundary shapes
608         ShapeAnalysis_FreeBounds anAnalizer( aShBase2 );
609         TopoDS_Compound aClosed = anAnalizer.GetClosedWires();
610         //TopExp_Explorer anExp;
611         Standard_Integer NbWires = 0;
612         for ( anExp.Init( aClosed, TopAbs_WIRE ); anExp.More(); anExp.Next() ) {
613           NbWires++;
614           aWire2 = anExp.Current();
615         }
616         if(NbWires!=1) {
617           // bad case
618           if(aCI) delete aCI;
619           Standard_ConstructionError::Raise("Bad shell is used as section ");
620         }
621       }
622       else { // aType2==TopAbs_FACE
623         TopExp_Explorer aExpW(aShBase2,TopAbs_WIRE);
624         aWire2 = aExpW.Current();
625       }
626       // make pipe using aWire1 and aWire2
627       if( !aWire1.IsNull() && !aWire2.IsNull() ) {
628         //BRepOffsetAPI_MakePipeShell aBuilder(aWirePath);
629         BRepOffsetAPI_MakePipeShell aBuilder(WPath);
630         aBuilder.Add(aWire1, TopoDS::Vertex(VLocs(i)),
631                      aWithContact, aWithCorrect);
632         aBuilder.Add(aWire2, TopoDS::Vertex(VLocs(i+1)),
633                      aWithContact, aWithCorrect);
634         if(!aBuilder.IsReady()) {
635           if(aCI) delete aCI;
636           Standard_ConstructionError::Raise("Invalid input data for building PIPE: bases are invalid");
637         }
638         aBuilder.Build();
639         TopoDS_Shape aShape = aBuilder.Shape();
640         TopoDS_Shell aShell;
641         B.MakeShell(aShell);
642         for ( anExp.Init( aShape, TopAbs_FACE ); anExp.More(); anExp.Next() ) {
643           B.Add(aShell,anExp.Current());
644         }
645         for ( anExp.Init( aShBase1, TopAbs_FACE ); anExp.More(); anExp.Next() ) {
646           B.Add(aShell,anExp.Current());
647         }
648         for ( anExp.Init( aShBase2, TopAbs_FACE ); anExp.More(); anExp.Next() ) {
649           B.Add(aShell,anExp.Current());
650         }
651         // make sewing for this shell
652         Handle(BRepBuilderAPI_Sewing) aSewing = new BRepBuilderAPI_Sewing;
653         aSewing->SetTolerance(Precision::Confusion());
654         aSewing->SetFaceMode(Standard_True);
655         aSewing->SetFloatingEdgesMode(Standard_False);
656         aSewing->SetNonManifoldMode(Standard_False);
657         for ( anExp.Init( aShell, TopAbs_FACE ); anExp.More(); anExp.Next() ) {
658           aSewing->Add(anExp.Current());
659         }
660         aSewing->Perform();
661         const TopoDS_Shape aSewShape = aSewing->SewedShape();
662         if( aSewShape.ShapeType() == TopAbs_SHELL ) {
663           aShell = TopoDS::Shell(aSewShape);
664           if(BRep_Tool::IsClosed(aShell)) {
665             TopoDS_Solid aSolid;
666             B.MakeSolid(aSolid);
667             B.Add(aSolid,aShell);
668             B.Add(aComp,aSolid);
669           }
670           else {
671             B.Add(aComp,aShell);
672           }
673         }
674         else {
675           B.Add(aComp,aShell);
676         }
677       }
678     }
679     else {
680       // main block - creation few solids (for each pair of faces)
681       TopTools_MapOfShape aFaces1,aFaces2;
682       for ( anExp.Init( aShBase1, TopAbs_FACE ); anExp.More(); anExp.Next() )
683         aFaces1.Add(anExp.Current());
684       for ( anExp.Init( aShBase2, TopAbs_FACE ); anExp.More(); anExp.Next() )
685         aFaces2.Add(anExp.Current());
686       // creating map of edge faces
687       TopTools_IndexedDataMapOfShapeListOfShape aMapEdgeFaces1;
688       TopExp::MapShapesAndAncestors(aShBase1, TopAbs_EDGE, TopAbs_FACE, aMapEdgeFaces1);
689       TopTools_IndexedDataMapOfShapeListOfShape aMapEdgeFaces2;
690       TopExp::MapShapesAndAncestors(aShBase2, TopAbs_EDGE, TopAbs_FACE, aMapEdgeFaces2);
691   
692       // constuct map face->face
693       TopTools_IndexedDataMapOfShapeShape FF;
694       TopoDS_Shape FS1,FS2;
695       if(nbSubBases==0) {
696         // find edge the most distant from location point
697         // (this edge is not shared by two faces)
698         double maxdist = 0.;
699         TopoDS_Shape E1;
700         TopoDS_Vertex V11,V21;
701         for(j=1; j<=aMapEdgeFaces1.Extent(); j++) {
702           TopoDS_Shape tmp = aMapEdgeFaces1.FindKey(j);
703           const TopTools_ListOfShape& aList = aMapEdgeFaces1.FindFromKey(tmp);
704           if(aList.Extent()>1)
705             continue;
706           TopExp_Explorer expv;
707           expv.Init( tmp, TopAbs_VERTEX );
708           TopoDS_Vertex V1 = TopoDS::Vertex(expv.Current());
709           expv.Next();
710           TopoDS_Vertex V2 = TopoDS::Vertex(expv.Current());
711           gp_Pnt P1 = BRep_Tool::Pnt(V1);
712           gp_Pnt P2 = BRep_Tool::Pnt(V2);
713           double dist = PLocs.Value(i).Distance(P1) + PLocs.Value(i).Distance(P2);
714           if(dist>maxdist) {
715             E1 = tmp;
716             V11 = V1;
717             V21 = V2;
718             TopTools_ListIteratorOfListOfShape anIter(aList);
719             FS1 = anIter.Value();
720             maxdist = dist;
721           }
722         }
723         // main direction for comparing
724         gp_Vec VM(PLocs.Value(i),PLocs.Value(i+1));
725         // find corresponding edge from next section
726         double minang = PI;
727         gp_Pnt P11 = BRep_Tool::Pnt(V11);
728         gp_Pnt P21 = BRep_Tool::Pnt(V21);
729         TopoDS_Shape E2;
730         TopoDS_Vertex V12,V22;
731         for(j=1; j<=aMapEdgeFaces2.Extent(); j++) {
732           TopoDS_Shape tmp = aMapEdgeFaces2.FindKey(j);
733           const TopTools_ListOfShape& aList = aMapEdgeFaces2.FindFromKey(tmp);
734           if(aList.Extent()>1)
735             continue;
736           TopExp_Explorer expv;
737           expv.Init( tmp, TopAbs_VERTEX );
738           TopoDS_Vertex V1tmp = TopoDS::Vertex(expv.Current());
739           expv.Next();
740           TopoDS_Vertex V2tmp = TopoDS::Vertex(expv.Current());
741           gp_Pnt P1tmp = BRep_Tool::Pnt(V1tmp);
742           gp_Pnt P2tmp = BRep_Tool::Pnt(V2tmp);
743           double d1 = P1tmp.Distance(P11) + P2tmp.Distance(P21);
744           double d2 = P1tmp.Distance(P21) + P2tmp.Distance(P11);
745           TopoDS_Vertex V1,V2;
746           gp_Pnt P1,P2;
747           if(d1>d2) {
748             V1 = V2tmp; P1 = P2tmp;
749             V2 = V1tmp; P2 = P1tmp;
750           }
751           else {
752             V1 = V1tmp; P1 = P1tmp;
753             V2 = V2tmp; P2 = P2tmp;
754           }
755           gp_Vec Vec1(P11,P1);
756           gp_Vec Vec2(P21,P2);
757           double ang = fabs(Vec1.Angle(VM)) + fabs(Vec2.Angle(VM));
758           if(ang<minang) {
759             E2 = tmp;
760             V12 = V1;
761             V22 = V2;
762             TopTools_ListIteratorOfListOfShape anIter(aList);
763             FS2 = anIter.Value();
764             minang = ang;
765           }
766         }
767         // put all pairs to map FF
768         FF.Add(FS1,FS2);
769         FF.Add(E1,E2);
770         FF.Add(V11,V12);
771         FF.Add(V21,V22);
772
773         // add pairs of edges to FF
774         bool stat =  FillForOtherEdges(FS1,E1,V11,FF);
775         if( !stat ) {
776           if(aCI) delete aCI;
777           Standard_ConstructionError::Raise("FindForOtherEdges: Can not mapping other egdes");
778         }
779
780       }
781       else {
782         { // 1 section
783           Handle(Standard_Transient) anItem = aSubBasesObjs->Value(i);
784           if(anItem.IsNull()) {
785             if(aCI) delete aCI;
786             Standard_ConstructionError::Raise("Invalid subbase shape");
787           }
788           Handle(GEOM_Function) aRefBase = Handle(GEOM_Function)::DownCast(anItem);
789           if(aRefBase.IsNull()) {
790             if(aCI) delete aCI;
791             Standard_ConstructionError::Raise("Invalid subbase shape");
792           }
793           TopoDS_Shape aSh = aRefBase->GetValue();
794           if(aSh.IsNull()) {
795             if(aCI) delete aCI;
796             Standard_ConstructionError::Raise("Invalid subbase shape");
797           }
798           if(aSh.ShapeType()!=TopAbs_FACE) {
799             if(aCI) delete aCI;
800             Standard_ConstructionError::Raise("Invalid subbase shape");
801           }
802           FS1 = aSh;
803         }       
804         { // 2 section
805           Handle(Standard_Transient) anItem = aSubBasesObjs->Value(i+1);
806           if(anItem.IsNull()) {
807             if(aCI) delete aCI;
808             Standard_ConstructionError::Raise("Invalid subbase shape");
809           }
810           Handle(GEOM_Function) aRefBase = Handle(GEOM_Function)::DownCast(anItem);
811           if(aRefBase.IsNull()) {
812             if(aCI) delete aCI;
813             Standard_ConstructionError::Raise("Invalid subbase shape");
814           }
815           TopoDS_Shape aSh = aRefBase->GetValue();
816           if(aSh.IsNull()) {
817             if(aCI) delete aCI;
818             Standard_ConstructionError::Raise("Invalid subbase shape");
819           }
820           if(aSh.ShapeType()!=TopAbs_FACE) {
821             if(aCI) delete aCI;
822             Standard_ConstructionError::Raise("Invalid subbase shape");
823           }
824           FS2 = aSh;
825         }
826
827         if( !aFaces1.Contains(FS1) || !aFaces2.Contains(FS2) ) {
828           if(aCI) delete aCI;
829           Standard_ConstructionError::Raise("Invalid subbase shape");
830         }
831       
832         FF.Add(FS1,FS2);
833
834         // add pairs of edges to FF
835         bool stat =  FillCorrespondingEdges(FS1, FS2, TopoDS::Vertex(VLocs(i)),
836                                             TopoDS::Vertex(VLocs(i+1)), WPath, FF);
837         if( !stat ) {
838           if(aCI) delete aCI;
839           Standard_ConstructionError::Raise("Can not create correct pipe");
840         }
841       }
842
843       FindNextPairOfFaces(FS1, aMapEdgeFaces1, aMapEdgeFaces2, FF, aCI);
844
845
846       // make pipe for each pair of faces
847       //BRepTools::Write(WPath,"/dn02/users_Linux/skl/work/Bugs/14857/wpath.brep");
848       for(j=1; j<=FF.Extent(); j++) {
849         TopoDS_Shape F1 = FF.FindKey(j);
850         if( F1.ShapeType() != TopAbs_FACE )
851           continue;
852         TopoDS_Shape F2 = FF.FindFromIndex(j);
853         TopExp_Explorer aExpW1(F1,TopAbs_WIRE);
854         TopoDS_Wire aWire1 = TopoDS::Wire(aExpW1.Current());
855         TopExp_Explorer aExpW2(F2,TopAbs_WIRE);
856         TopoDS_Wire aWire2 = TopoDS::Wire(aExpW2.Current());
857         // make pipe using aWire1 and aWire2
858         if( !aWire1.IsNull() && !aWire2.IsNull() ) {
859           BRepOffsetAPI_MakePipeShell aBuilder(WPath);
860           aBuilder.Add(aWire1, TopoDS::Vertex(VLocs(i)),
861                        aWithContact, aWithCorrect);
862           aBuilder.Add(aWire2, TopoDS::Vertex(VLocs(i+1)),
863                        aWithContact, aWithCorrect);
864           if(!aBuilder.IsReady()) {
865             if(aCI) delete aCI;
866             Standard_ConstructionError::Raise("Invalid input data for building PIPE: bases are invalid");
867           }
868           aBuilder.Build();
869           TopoDS_Shape aShape = aBuilder.Shape();
870           TopoDS_Shell aShell;
871           B.MakeShell(aShell);
872           //int nbf=0;
873           for ( anExp.Init( aShape, TopAbs_FACE ); anExp.More(); anExp.Next() ) {
874             //nbf++;
875             //cout<<"nbf="<<nbf<<endl;
876             B.Add(aShell,anExp.Current());
877           }
878           B.Add(aShell,F1);
879           B.Add(aShell,F2);
880           // make sewing for this shell
881           Handle(BRepBuilderAPI_Sewing) aSewing = new BRepBuilderAPI_Sewing;
882           aSewing->SetTolerance(Precision::Confusion());
883           aSewing->SetFaceMode(Standard_True);
884           aSewing->SetFloatingEdgesMode(Standard_False);
885           aSewing->SetNonManifoldMode(Standard_False);
886           for ( anExp.Init( aShell, TopAbs_FACE ); anExp.More(); anExp.Next() ) {
887             aSewing->Add(anExp.Current());
888           }
889           aSewing->Perform();
890           const TopoDS_Shape aSewShape = aSewing->SewedShape();
891           if( aSewShape.ShapeType() == TopAbs_SHELL ) {
892             aShell = TopoDS::Shell(aSewShape);
893             if(BRep_Tool::IsClosed(aShell)) {
894               TopoDS_Solid aSolid;
895               B.MakeSolid(aSolid);
896               B.Add(aSolid,aShell);
897               B.Add(aComp,aSolid);
898             }
899             else {
900               B.Add(aComp,aShell);
901             }
902           }
903           else {
904             B.Add(aComp,aShell);
905           }
906         }
907       }
908
909     }
910   }
911
912   return aComp;
913 }
914
915
916 //=======================================================================
917 //function : Execute
918 //purpose  :
919 //=======================================================================
920 Standard_Integer GEOMImpl_PipeDriver::Execute(TFunction_Logbook& log) const
921 {
922   if (Label().IsNull()) return 0;
923   Handle(GEOM_Function) aFunction = GEOM_Function::GetFunction(Label());
924   GEOMImpl_IPipe* aCI= 0;
925   Standard_Integer aType = aFunction->GetType();
926   if(aType == PIPE_BASE_PATH)
927     aCI = new GEOMImpl_IPipe(aFunction);
928   else if(aType == PIPE_DIFFERENT_SECTIONS)
929     aCI = new GEOMImpl_IPipeDiffSect(aFunction);
930   else if(aType == PIPE_SHELL_SECTIONS)
931     aCI = new GEOMImpl_IPipeShellSect(aFunction);
932   else
933     return 0;
934
935   Handle(GEOM_Function) aRefPath = aCI->GetPath();
936   TopoDS_Shape aShapePath = aRefPath->GetValue();
937
938
939   if (aShapePath.IsNull()) {
940     cout<<"Driver : path is null"<<endl;
941     if(aCI) delete aCI;
942     Standard_NullObject::Raise("MakePipe aborted : null path argument");
943   }
944   
945   // Get path contour
946   TopoDS_Wire aWirePath;
947   if (aShapePath.ShapeType() == TopAbs_WIRE) {
948     aWirePath = TopoDS::Wire(aShapePath);
949   } 
950   else {
951     if (aShapePath.ShapeType() == TopAbs_EDGE) {
952       TopoDS_Edge anEdge = TopoDS::Edge(aShapePath);
953       aWirePath = BRepBuilderAPI_MakeWire(anEdge);
954     } 
955     else {
956       if(aCI) delete aCI;
957       Standard_TypeMismatch::Raise("MakePipe aborted : path shape is neither a wire nor an edge");
958     } 
959   }
960   
961   TopoDS_Shape aShape;
962
963   if (aType == PIPE_BASE_PATH) {
964      
965     Handle(GEOM_Function) aRefBase = aCI->GetBase();
966    
967     TopoDS_Shape aShapeBase = aRefBase->GetValue();
968     
969     if (aShapeBase.IsNull()) {
970       if(aCI) delete aCI;
971       Standard_NullObject::Raise("MakePipe aborted : null base argument");
972     }
973
974     // Make pipe
975     aShape = BRepOffsetAPI_MakePipe(aWirePath, aShapeBase);
976   }
977
978   //building pipe with different sections
979   else if (aType == PIPE_DIFFERENT_SECTIONS) 
980   {
981     GEOMImpl_IPipeDiffSect* aCIDS = (GEOMImpl_IPipeDiffSect*)aCI;
982     //GEOMImpl_IPipeDiffSect* aCIDS = static_cast<GEOMImpl_IPipeDiffSect*>(aCI);
983     BRepOffsetAPI_MakePipeShell aBuilder(aWirePath);
984     Handle(TColStd_HSequenceOfTransient) aBasesObjs = aCIDS->GetBases ();
985     Handle(TColStd_HSequenceOfTransient) aLocObjs = aCIDS->GetLocations ();
986     Standard_Boolean aWithContact = (aCIDS->GetWithContactMode());
987     Standard_Boolean aWithCorrect = (aCIDS->GetWithCorrectionMode());
988
989     Standard_Integer i =1, nbBases = aBasesObjs->Length(), 
990       nbLocs = (aLocObjs.IsNull() ? 0 :aLocObjs->Length());
991     
992     if(nbLocs && nbLocs != nbBases)
993     {
994       if(aCI) delete aCI;
995       Standard_ConstructionError::Raise("Number of sections is not equal to number of locations ");
996     }
997     TopTools_SequenceOfShape aSeqBases;
998     TopTools_SequenceOfShape aSeqLocs;
999     TopTools_SequenceOfShape aSeqFaces;
1000     for( ; i <= nbBases; i++) 
1001     {
1002       Handle(Standard_Transient) anItem = aBasesObjs->Value(i);
1003       if(anItem.IsNull())
1004         continue;
1005       Handle(GEOM_Function) aRefBase = Handle(GEOM_Function)::DownCast(anItem);
1006       if(aRefBase.IsNull())
1007         continue;
1008       TopoDS_Shape aShapeBase = aRefBase->GetValue();
1009       if(aShapeBase.IsNull())
1010         continue;
1011       TopAbs_ShapeEnum aTypeBase = aShapeBase.ShapeType();
1012
1013       //if for section was specified face with a few wires then a few
1014       //    pipes were build and make solid 
1015       Standard_Boolean NeedCreateSolid = Standard_False;
1016       if(aTypeBase == TopAbs_SHELL) {
1017         // create wire as boundary contour if shell is no closed
1018         // get free boundary shapes
1019         ShapeAnalysis_FreeBounds anAnalizer( aShapeBase );
1020         TopoDS_Compound aClosed = anAnalizer.GetClosedWires();
1021         TopExp_Explorer anExp;
1022         TopoDS_Shape aWire;
1023         Standard_Integer NbWires = 0;
1024         for ( anExp.Init( aClosed, TopAbs_WIRE ); anExp.More(); anExp.Next() ) {
1025           NbWires++;
1026           aWire = anExp.Current();
1027         }
1028         if(NbWires!=1) {
1029           // bad case
1030           if(aCI) delete aCI;
1031           Standard_ConstructionError::Raise("Bad shell is used as section ");
1032         }
1033         NeedCreateSolid = Standard_True;
1034         aSeqFaces.Append(aShapeBase);
1035         aSeqBases.Append(aWire);
1036       }
1037       else if(aTypeBase == TopAbs_FACE)
1038       {
1039         NeedCreateSolid = Standard_True;
1040         //for case one path should be used other type function
1041         aSeqFaces.Append(aShapeBase);
1042         TopExp_Explorer aExpW(aShapeBase,TopAbs_WIRE);
1043         for( ; aExpW.More(); aExpW.Next())
1044         {
1045           TopoDS_Shape aWireProf = aExpW.Current();
1046           aSeqBases.Append(aWireProf);
1047         }
1048       }
1049       else if(aTypeBase == TopAbs_WIRE || aTypeBase == TopAbs_VERTEX) {
1050         aSeqBases.Append(aShapeBase);
1051       }
1052       else if(aTypeBase == TopAbs_EDGE)
1053       {
1054         TopoDS_Edge anEdge = TopoDS::Edge(aShapeBase);
1055         TopoDS_Shape aWireProf = BRepBuilderAPI_MakeWire(anEdge);
1056         aSeqBases.Append(aWireProf);
1057       }
1058       if(nbLocs) 
1059       {
1060         Handle(Standard_Transient) anItemLoc = aLocObjs->Value(i);
1061         if(anItemLoc.IsNull())
1062           continue;
1063         Handle(GEOM_Function) aRefLoc = Handle(GEOM_Function)::DownCast(anItemLoc);
1064         TopoDS_Shape aShapeLoc = aRefLoc->GetValue();
1065         if(aShapeLoc.IsNull() || aShapeLoc.ShapeType() != TopAbs_VERTEX)
1066           continue;
1067         aSeqLocs.Append(aShapeLoc);
1068       }
1069     }
1070     
1071     nbLocs = aSeqLocs.Length();
1072     Standard_Integer nbShapes = aSeqBases.Length();
1073     Standard_Integer step = nbShapes/nbBases;
1074     
1075     if(nbShapes < nbBases || fmod((double)nbShapes, (double)nbBases))
1076     {
1077       if(aCI) delete aCI;
1078       Standard_ConstructionError::Raise("Invalid sections were specified for building pipe");
1079     }
1080      
1081     Standard_Integer ind =0;     
1082     for( i=1; i  <= nbShapes && ind < nbShapes; i++) //i+nbBases <= nbShapes
1083     {
1084       TopTools_SequenceOfShape usedBases;
1085       Standard_Integer j = 1;
1086       for( ; j <= nbBases ; j++) 
1087       {
1088         ind = i + (j-1)*step;
1089         
1090          TopoDS_Shape aWireProf = aSeqBases.Value(ind);
1091          usedBases.Append(aWireProf);
1092          if(nbLocs) 
1093          {
1094            TopoDS_Shape aShapeLoc = aSeqLocs.Value(j);
1095            TopoDS_Vertex aVert = TopoDS::Vertex(aShapeLoc);
1096            aBuilder.Add(aWireProf,aVert,aWithContact,aWithCorrect);
1097          }
1098          else
1099            aBuilder.Add(aWireProf,aWithContact,aWithCorrect);
1100       }
1101       if(!aBuilder.IsReady())
1102       {
1103         if(aCI) delete aCI;
1104         Standard_ConstructionError::Raise("Invalid input data for building PIPE: bases are invalid");
1105       }
1106       aBuilder.Build();
1107       aShape = aBuilder.Shape();
1108       aSeqFaces.Append(aShape); 
1109       for( j = 1; j <=usedBases.Length(); j++)
1110         aBuilder.Delete(usedBases.Value(j));
1111     }
1112         
1113     //for case if section is face 
1114     if(aSeqFaces.Length() >1)
1115     {
1116       BRep_Builder aB;
1117       TopoDS_Compound aComp;
1118       aB.MakeCompound(aComp);
1119       for( i = 1; i <= aSeqFaces.Length(); i++)
1120         aB.Add(aComp,aSeqFaces.Value(i));
1121       aShape = aComp;
1122     }
1123   }
1124
1125   //building pipe with shell sections
1126   else if (aType == PIPE_SHELL_SECTIONS) {
1127     aShape = CreatePipeForShellSections(aWirePath,aCI);
1128   }
1129
1130   if (aShape.IsNull()) return 0;
1131
1132   BRepCheck_Analyzer ana (aShape, Standard_False);
1133   if (!ana.IsValid()) {
1134     if(aCI) delete aCI;
1135     Standard_ConstructionError::Raise("Algorithm have produced an invalid shape result");
1136   }
1137
1138   aFunction->SetValue(aShape);
1139
1140   log.SetTouched(Label());
1141   if(aCI) delete aCI;
1142   return 1;
1143 }
1144
1145
1146 //=======================================================================
1147 //function :  GEOMImpl_PipeDriver_Type_
1148 //purpose  :
1149 //=======================================================================
1150 Standard_EXPORT Handle_Standard_Type& GEOMImpl_PipeDriver_Type_()
1151 {
1152
1153   static Handle_Standard_Type aType1 = STANDARD_TYPE(TFunction_Driver);
1154   if ( aType1.IsNull()) aType1 = STANDARD_TYPE(TFunction_Driver);
1155   static Handle_Standard_Type aType2 = STANDARD_TYPE(MMgt_TShared);
1156   if ( aType2.IsNull()) aType2 = STANDARD_TYPE(MMgt_TShared);
1157   static Handle_Standard_Type aType3 = STANDARD_TYPE(Standard_Transient);
1158   if ( aType3.IsNull()) aType3 = STANDARD_TYPE(Standard_Transient);
1159
1160
1161   static Handle_Standard_Transient _Ancestors[]= {aType1,aType2,aType3,NULL};
1162   static Handle_Standard_Type _aType = new Standard_Type("GEOMImpl_PipeDriver",
1163                                                          sizeof(GEOMImpl_PipeDriver),
1164                                                          1,
1165                                                          (Standard_Address)_Ancestors,
1166                                                          (Standard_Address)NULL);
1167
1168   return _aType;
1169 }
1170
1171 //=======================================================================
1172 //function : DownCast
1173 //purpose  :
1174 //=======================================================================
1175 const Handle(GEOMImpl_PipeDriver) Handle(GEOMImpl_PipeDriver)::DownCast(const Handle(Standard_Transient)& AnObject)
1176 {
1177   Handle(GEOMImpl_PipeDriver) _anOtherObject;
1178
1179   if (!AnObject.IsNull()) {
1180      if (AnObject->IsKind(STANDARD_TYPE(GEOMImpl_PipeDriver))) {
1181        _anOtherObject = Handle(GEOMImpl_PipeDriver)((Handle(GEOMImpl_PipeDriver)&)AnObject);
1182      }
1183   }
1184
1185   return _anOtherObject ;
1186 }
1187