Salome HOME
PAL17233: Projection 2D doesn't work (bis)
[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
25 #include <GEOMImpl_IShapesOperations.hxx>
26 #include <GEOMImpl_IPipeDiffSect.hxx>
27 #include <GEOMImpl_IPipeShellSect.hxx>
28 #include <GEOMImpl_IPipe.hxx>
29 #include <GEOMImpl_Types.hxx>
30 #include <GEOM_Function.hxx>
31
32 #include <ShapeAnalysis_FreeBounds.hxx>
33 #include <ShapeAnalysis_Edge.hxx>
34
35 #include <BRep_Tool.hxx>
36 #include <BRep_Builder.hxx>
37 #include <BRepBuilderAPI_MakeWire.hxx>
38 #include <BRepBuilderAPI_Sewing.hxx>
39 #include <BRepCheck_Analyzer.hxx>
40 #include <BRepOffsetAPI_MakePipe.hxx>
41 #include <BRepOffsetAPI_MakePipeShell.hxx>
42 #include <GProp_GProps.hxx>
43 #include <BRepGProp.hxx>
44
45 #include <TopAbs.hxx>
46 #include <TopExp.hxx>
47 #include <TopExp_Explorer.hxx>
48 #include <TopoDS.hxx>
49 #include <TopoDS_Wire.hxx>
50 #include <TopoDS_Edge.hxx>
51 #include <TopoDS_Shape.hxx>
52 #include <TopoDS_Solid.hxx>
53 #include <TopoDS_Shell.hxx>
54 #include <TopoDS_Face.hxx>
55 #include <TopoDS_Compound.hxx>
56 #include <TopTools_SequenceOfShape.hxx>
57 #include <TopTools_IndexedDataMapOfShapeShape.hxx>
58 #include <TopTools_IndexedDataMapOfShapeListOfShape.hxx>
59 #include <TopTools_ListIteratorOfListOfShape.hxx>
60
61 #include <GeomAPI_ProjectPointOnCurve.hxx>
62 #include <Geom_TrimmedCurve.hxx>
63
64 #include <TColgp_SequenceOfPnt.hxx>
65 #include <TColStd_HSequenceOfTransient.hxx>
66
67 #include <Precision.hxx>
68 #include <Standard_NullObject.hxx>
69 #include <Standard_TypeMismatch.hxx>
70 #include <Standard_ConstructionError.hxx>
71
72 #include "utilities.h"
73
74 //#include "BRepTools.hxx"
75
76
77 //=======================================================================
78 //function : GetID
79 //purpose  :
80 //=======================================================================
81 const Standard_GUID& GEOMImpl_PipeDriver::GetID()
82 {
83   static Standard_GUID aPipeDriver("FF1BBB19-5D14-4df2-980B-3A668264EA16");
84   return aPipeDriver;
85 }
86
87
88 //=======================================================================
89 //function : GEOMImpl_PipeDriver
90 //purpose  :
91 //=======================================================================
92 GEOMImpl_PipeDriver::GEOMImpl_PipeDriver()
93 {
94 }
95
96
97 //=======================================================================
98 //function : FillForOtherEdges
99 //purpose  : auxilary for CreatePipeForShellSections()
100 //=======================================================================
101 static bool FillForOtherEdges(const TopoDS_Shape& F1,
102                               const TopoDS_Shape& E1,
103                               const TopoDS_Shape& V1,
104                               TopTools_IndexedDataMapOfShapeShape& FF)
105 {
106   //cout<<"FillForOtherEdges"<<endl;
107   // find other pairs for vertexes and edges
108   // creating map of vertex edges for both faces
109   TopTools_IndexedDataMapOfShapeListOfShape aMapVertEdge1;
110   TopExp::MapShapesAndAncestors(F1, TopAbs_VERTEX, TopAbs_EDGE, aMapVertEdge1);
111   const TopoDS_Shape& F2 = FF.FindFromKey(F1);
112   const TopoDS_Shape& E2 = FF.FindFromKey(E1);
113   const TopoDS_Shape& V2 = FF.FindFromKey(V1);
114   TopTools_IndexedDataMapOfShapeListOfShape aMapVertEdge2;
115   TopExp::MapShapesAndAncestors(F2, TopAbs_VERTEX, TopAbs_EDGE, aMapVertEdge2);
116
117   TopoDS_Edge ES1 = TopoDS::Edge(E1);
118   TopoDS_Edge ES2 = TopoDS::Edge(E2);
119   TopoDS_Shape VS1 = V1;
120   TopoDS_Shape VS2 = V2;
121
122   ShapeAnalysis_Edge sae;
123   while(1) {
124     const TopTools_ListOfShape& aList1 = aMapVertEdge1.FindFromKey(VS1);
125     //TopoDS_Shape E1next;
126     TopTools_ListIteratorOfListOfShape anIter1(aList1);
127     if(anIter1.Value().IsSame(ES1)) {
128       anIter1.Next();
129     }
130     //E1next = anIter1.Value();
131     const TopTools_ListOfShape& aList2 = aMapVertEdge2.FindFromKey(VS2);
132     //TopoDS_Shape E2next;
133     TopTools_ListIteratorOfListOfShape anIter2(aList2);
134     if(anIter2.Value().IsSame(ES2)) {
135       anIter2.Next();
136     }
137     //E2next = anIter2.Value();
138     //ES1 = TopoDS::Edge(E1next);
139     //ES2 = TopoDS::Edge(E2next);
140     ES1 = TopoDS::Edge(anIter1.Value());
141     ES2 = TopoDS::Edge(anIter2.Value());
142     if(!FF.Contains(ES1)) {
143       FF.Add(ES1,ES2);
144     }
145     if(VS1.IsSame(sae.FirstVertex(ES1)))
146       VS1 = sae.LastVertex(ES1);
147     else
148       VS1 = sae.FirstVertex(ES1);
149     if(VS2.IsSame(sae.FirstVertex(ES2)))
150       VS2 = sae.LastVertex(ES2);
151     else
152       VS2 = sae.FirstVertex(ES2);
153     if(VS1.IsSame(V1))
154       break;
155     if(!FF.Contains(VS1)) {
156       FF.Add(VS1,VS2);
157     }
158   }
159
160   return true;
161 }
162
163
164 //=======================================================================
165 //function : FillCorrespondingEdges
166 //purpose  : auxilary for CreatePipeForShellSections()
167 //=======================================================================
168 static bool FillCorrespondingEdges(const TopoDS_Shape& FS1,
169                                    const TopoDS_Shape& FS2,
170                                    const TopoDS_Vertex& aLoc1,
171                                    const TopoDS_Vertex& aLoc2,
172                                    const TopoDS_Wire& aWirePath,
173                                    TopTools_IndexedDataMapOfShapeShape& FF)
174 {
175   //cout<<"FillCorrespondingEdges"<<endl;
176   // find corresponding edges
177   TopExp_Explorer expw1(FS1,TopAbs_WIRE);
178   TopoDS_Wire aWire1 = TopoDS::Wire(expw1.Current());
179   //exp = TopExp_Explorer(FS2,TopAbs_WIRE);
180   TopExp_Explorer expw2(FS2,TopAbs_WIRE);
181   TopoDS_Wire aWire2 = TopoDS::Wire(expw2.Current());
182   BRepOffsetAPI_MakePipeShell aBuilder(aWirePath);
183   aBuilder.Add(aWire1, aLoc1);
184   aBuilder.Add(aWire2, aLoc2);
185   if(!aBuilder.IsReady()) {
186     return false;
187   }
188   aBuilder.Build();
189   TopoDS_Shape aShape = aBuilder.Shape();
190   /*
191   TopoDS_Compound C;
192   BRep_Builder B;
193   B.MakeCompound(C);
194   B.Add(C,aShape);
195   B.Add(C,FS1);
196   B.Add(C,FS2);
197   BRepTools::Write(C,"/dn02/users_Linux/skl/work/Bugs/14857/comp.brep");
198   */
199   ShapeAnalysis_Edge sae;
200   double tol = Max( BRep_Tool::Tolerance(TopoDS::Face(FS1)),
201                     BRep_Tool::Tolerance(TopoDS::Face(FS2)) );
202   TopTools_MapOfShape Vs1,Vs2;
203   TopExp_Explorer exp;
204   exp.Init( FS1, TopAbs_EDGE );
205   TopoDS_Edge E1 = TopoDS::Edge(exp.Current());
206   TopoDS_Vertex V11 = sae.FirstVertex(E1);
207   TopoDS_Vertex V21 = sae.LastVertex(E1);
208   gp_Pnt P11 = BRep_Tool::Pnt(V11);
209   gp_Pnt P21 = BRep_Tool::Pnt(V21);
210   //cout<<"P11("<<P11.X()<<","<<P11.Y()<<","<<P11.Z()<<")"<<endl;
211   //cout<<"P21("<<P21.X()<<","<<P21.Y()<<","<<P21.Z()<<")"<<endl;
212   // find corresponding vertexes from created shape
213   TopoDS_Vertex VN11,VN21;
214   for( exp.Init( aShape, TopAbs_VERTEX ); exp.More(); exp.Next() ) {
215     TopoDS_Vertex V = TopoDS::Vertex(exp.Current());
216     gp_Pnt P = BRep_Tool::Pnt(V);
217     if(P.Distance(P11)<tol) {
218       VN11 = V;
219     }
220     if(P.Distance(P21)<tol) {
221       VN21 = V;
222     }
223   }
224   // find edge contains VN11 and VN21 and corresponding vertexes
225   TopoDS_Vertex VN12,VN22;
226   for( exp.Init( aShape, TopAbs_FACE ); exp.More(); exp.Next() ) {
227     TopoDS_Shape F = exp.Current();
228     TopExp_Explorer expe;
229     bool IsFind = false;
230     for( expe.Init( F, TopAbs_EDGE ); expe.More(); expe.Next() ) {
231       TopoDS_Edge E = TopoDS::Edge(expe.Current());
232       TopoDS_Vertex VF = sae.FirstVertex(E);
233       TopoDS_Vertex VL = sae.LastVertex(E);
234       if( (VF.IsSame(VN11) && VL.IsSame(VN21)) || (VF.IsSame(VN21) && VL.IsSame(VN11)) ) {
235         IsFind = true;
236         break;
237       }
238     }
239     if(IsFind) {
240       for( expe.Init( F, TopAbs_EDGE ); expe.More(); expe.Next() ) {
241         TopoDS_Edge E = TopoDS::Edge(expe.Current());
242         TopoDS_Vertex VF = sae.FirstVertex(E);
243         TopoDS_Vertex VL = sae.LastVertex(E);
244         if( VF.IsSame(VN11) && !VL.IsSame(VN21) )
245           VN12 = VL;
246         if( VL.IsSame(VN11) && !VF.IsSame(VN21) )
247           VN12 = VF;
248         if( VF.IsSame(VN21) && !VL.IsSame(VN11) )
249           VN22 = VL;
250         if( VL.IsSame(VN21) && !VF.IsSame(VN11) )
251           VN22 = VF;
252       }
253       break;
254     }
255   }
256   // find vertexes from FS2 corresponded to VN12 and VN22
257   // and find edge from FS2 contains V12 and V22,
258   // this edge will be corresponded to edge E1
259   TopoDS_Vertex V12,V22;
260   gp_Pnt PN12 = BRep_Tool::Pnt(VN12);
261   gp_Pnt PN22 = BRep_Tool::Pnt(VN22);
262   //cout<<"PN12("<<PN12.X()<<","<<PN12.Y()<<","<<PN12.Z()<<")"<<endl;
263   //cout<<"PN22("<<PN22.X()<<","<<PN22.Y()<<","<<PN22.Z()<<")"<<endl;
264   TopoDS_Edge E2;
265   TopExp_Explorer expe;
266   for( expe.Init( FS2, TopAbs_EDGE ); expe.More(); expe.Next() ) {
267     TopoDS_Edge E = TopoDS::Edge(expe.Current());
268     TopoDS_Vertex VF = sae.FirstVertex(E);
269     TopoDS_Vertex VL = sae.LastVertex(E);
270     gp_Pnt PF = BRep_Tool::Pnt(VF);
271     gp_Pnt PL = BRep_Tool::Pnt(VL);
272     if( PF.Distance(PN12)<tol && PL.Distance(PN22)<tol ) {
273       V12 = VF;
274       V22 = VL;
275       E2 = E;
276       break;
277     }
278     if( PF.Distance(PN22)<tol && PL.Distance(PN12)<tol ) {
279       V12 = VL;
280       V22 = VF;
281       E2 = E;
282       break;
283     }
284   }
285   FF.Add(V11,V12);
286   FF.Add(V21,V22);
287   FF.Add(E1,E2);
288
289   // find other pairs for vertexes and edges
290   // creating map of vertex edges for both faces
291   return FillForOtherEdges(FS1,E1,V21,FF);
292
293   //return true;
294 }
295
296
297 //=======================================================================
298 //function : FindNextPairOfFaces
299 //purpose  : auxilary for CreatePipeForShellSections()
300 //=======================================================================
301 static void FindNextPairOfFaces(const TopoDS_Shape& aCurFace,
302                                 TopTools_IndexedDataMapOfShapeListOfShape& aMapEdgeFaces1,
303                                 TopTools_IndexedDataMapOfShapeListOfShape& aMapEdgeFaces2,
304                                 TopTools_IndexedDataMapOfShapeShape& FF,
305                                 GEOMImpl_IPipe* aCI)
306 {
307   //cout<<"FindNextPairOfFaces"<<endl;
308   TopExp_Explorer anExp;
309   for ( anExp.Init( aCurFace, TopAbs_EDGE ); anExp.More(); anExp.Next() ) {
310     TopoDS_Shape E1 = anExp.Current();
311     if(!FF.Contains(E1)) {
312       if(aCI) delete aCI;
313       Standard_ConstructionError::Raise("FindNextPairOfFaces: Can not find edge in map");
314     }
315     const TopoDS_Shape& E2 = FF.FindFromKey(E1);
316     TopExp_Explorer anExpV;
317     anExpV.Init( E1, TopAbs_VERTEX );
318     TopoDS_Shape V1 = anExpV.Current();
319     if(!FF.Contains(V1)) {
320       if(aCI) delete aCI;
321       Standard_ConstructionError::Raise("FindNextPairOfFaces: Can not find vertex in map");
322     }
323
324     const TopTools_ListOfShape& aList1 = aMapEdgeFaces1.FindFromKey(E1);
325     if(aList1.Extent()<2)
326       continue;
327     TopTools_ListIteratorOfListOfShape anIter(aList1);
328     if(anIter.Value().IsEqual(aCurFace)) {
329       anIter.Next();
330     }
331     TopoDS_Shape F1other = anIter.Value();
332     if(FF.Contains(F1other))
333       continue;
334
335     const TopoDS_Shape& F2 = FF.FindFromKey(aCurFace);
336     const TopTools_ListOfShape& aList2 = aMapEdgeFaces2.FindFromKey(E2);
337     if(aList2.Extent()<2) {
338       if(aCI) delete aCI;
339       Standard_ConstructionError::Raise("FindNextPairOfFaces: Can not find corresponding face");
340     }
341     TopTools_ListIteratorOfListOfShape anIter2(aList2);
342     if(anIter2.Value().IsEqual(F2)) {
343       anIter2.Next();
344     }
345     TopoDS_Shape F2other = anIter2.Value();
346     FF.Add(F1other,F2other);
347
348     // add pairs of edges to FF
349     bool stat =  FillForOtherEdges(F1other,E1,V1,FF);
350     if( !stat ) {
351       if(aCI) delete aCI;
352       Standard_ConstructionError::Raise("FindNextPairOfFaces: Can not mapping other egdes");
353     }
354
355     FindNextPairOfFaces(F1other, aMapEdgeFaces1, aMapEdgeFaces2, FF, aCI);
356   }
357 }
358
359
360 //=======================================================================
361 //function : CreatePipeForShellSections
362 //purpose  : auxilary for Execute()
363 //=======================================================================
364 static TopoDS_Shape CreatePipeForShellSections(const TopoDS_Wire& aWirePath,
365                                                GEOMImpl_IPipe* aCI)
366 {
367   //cout<<"CreatePipeForShellSections"<<endl;
368   //TopoDS_Shape res;
369   int i,j;
370   BRep_Builder B;
371
372   GEOMImpl_IPipeShellSect* aCIDS = (GEOMImpl_IPipeShellSect*)aCI;
373   Handle(TColStd_HSequenceOfTransient) aBasesObjs = aCIDS->GetBases();
374   Handle(TColStd_HSequenceOfTransient) aSubBasesObjs = aCIDS->GetSubBases();
375   Handle(TColStd_HSequenceOfTransient) aLocObjs = aCIDS->GetLocations();
376   Standard_Boolean aWithContact = (aCIDS->GetWithContactMode());
377   Standard_Boolean aWithCorrect = (aCIDS->GetWithCorrectionMode());
378
379   Standard_Integer nbBases = aBasesObjs->Length(), 
380     nbSubBases = (aSubBasesObjs.IsNull() ? 0 :aSubBasesObjs->Length()),
381     nbLocs = (aLocObjs.IsNull() ? 0 :aLocObjs->Length());
382     
383   if( nbLocs != nbBases) {
384     if(aCI) delete aCI;
385     Standard_ConstructionError::Raise("Number of sections is not equal to number of locations ");
386   }
387   if( nbSubBases && nbSubBases != nbBases) {
388     if(aCI) delete aCI;
389     Standard_ConstructionError::Raise("Number of sections is not equal to number of subsections ");
390   }
391
392   //BRepOffsetAPI_MakePipeShell aBuilder(aWirePath);
393
394   TopTools_SequenceOfShape VLocs;
395   for(i=1; i<=nbBases; i++) {
396     Handle(Standard_Transient) anItemLoc = aLocObjs->Value(i);
397     if(anItemLoc.IsNull())
398       continue;
399     Handle(GEOM_Function) aRefLoc = Handle(GEOM_Function)::DownCast(anItemLoc);
400     TopoDS_Shape aShapeLoc = aRefLoc->GetValue();
401     if(aShapeLoc.IsNull() || aShapeLoc.ShapeType() != TopAbs_VERTEX)
402       continue;
403     VLocs.Append(aShapeLoc);
404   }
405   nbLocs = VLocs.Length();
406   if( nbLocs != nbBases) {
407     if(aCI) delete aCI;
408     Standard_ConstructionError::Raise("One of location shapes is not a vertex");
409   }
410   // split wire path by location points
411   TColgp_SequenceOfPnt PLocs;
412   for(i=1; i<=nbLocs; i++) {
413     TopoDS_Vertex V = TopoDS::Vertex(VLocs.Value(i));
414     PLocs.Append(BRep_Tool::Pnt(V));
415   }
416   TopTools_SequenceOfShape Edges;
417   TopTools_SequenceOfShape Wires;
418   TopExp_Explorer anExp;
419   for ( anExp.Init( aWirePath, TopAbs_EDGE ); anExp.More(); anExp.Next() ) {
420     Edges.Append(anExp.Current());
421   }
422   ShapeAnalysis_Edge sae;
423   TopoDS_Edge edge = TopoDS::Edge(Edges.First());
424   double tol = BRep_Tool::Tolerance(edge);
425   TopoDS_Vertex VF = sae.FirstVertex(edge);
426   gp_Pnt PF = BRep_Tool::Pnt(VF);
427   //cout<<"PF("<<PF.X()<<","<<PF.Y()<<","<<PF.Z()<<")"<<endl;
428   if( PF.Distance(PLocs.First()) > tol ) {
429     if(aCI) delete aCI;
430     Standard_ConstructionError::Raise
431       ("First location shapes is not coincided with first vertex of aWirePath");
432   }
433   VLocs.ChangeValue(1) = VF;
434   edge = TopoDS::Edge(Edges.Last());
435   tol = BRep_Tool::Tolerance(edge);
436   TopoDS_Vertex VL = sae.LastVertex(edge);
437   gp_Pnt PL = BRep_Tool::Pnt(VL);
438   if( PL.Distance(PLocs.Last()) > tol ) {
439     if(aCI) delete aCI;
440     Standard_ConstructionError::Raise
441       ("Last location shapes is not coincided with last vertex of aWirePath");
442   }
443   VLocs.ChangeValue(nbLocs) = VL;
444   int jcurr = 2;
445   TopTools_SequenceOfShape tmpEdges;
446   for(i=1; i<=Edges.Length() && jcurr<nbLocs; i++) {
447     TopoDS_Edge E = TopoDS::Edge(Edges.Value(i));
448     tol = BRep_Tool::Tolerance(E);
449     TopoDS_Vertex V1 = sae.FirstVertex(E);
450     TopoDS_Vertex V2 = sae.LastVertex(E);
451     gp_Pnt P1 = BRep_Tool::Pnt(V1);
452     gp_Pnt P2 = BRep_Tool::Pnt(V2);
453     if( P2.Distance(PLocs.Value(jcurr)) < tol ) {
454       // make wire from current edge and add created
455       // wire to Wires
456       TopoDS_Wire W;
457       B.MakeWire(W);
458       for(j=1; j<=tmpEdges.Length(); j++)
459         B.Add(W,tmpEdges.Value(j));
460       B.Add(W,E);
461       Wires.Append(W);
462       VLocs.ChangeValue(jcurr) = V2;
463       jcurr++;
464       tmpEdges.Clear();
465     }
466     else {
467       // find distance between E and aLocs(jcurr)
468       double fp,lp;
469       Handle(Geom_Curve) C = BRep_Tool::Curve(E,fp,lp);
470       GeomAPI_ProjectPointOnCurve PPC (PLocs.Value(jcurr),C);
471       if( PPC.NbPoints()>0 &&
472           PLocs.Value(jcurr).Distance(PPC.Point(1)) < tol ) {
473         double param = PPC.Parameter(1);
474         gp_Pnt PC1;
475         C->D0(param,PC1);
476         // split current edge
477         Handle(Geom_TrimmedCurve) tc1 = new Geom_TrimmedCurve(C,fp,param);
478         Handle(Geom_TrimmedCurve) tc2 = new Geom_TrimmedCurve(C,param,lp);
479         TopoDS_Edge E1,E2;
480         gp_Pnt Pfp;
481         C->D0(fp,Pfp);
482         if(Pfp.Distance(P1)<tol) {
483           B.MakeEdge(E1,tc1,tol);
484           B.Add(E1,V1);
485           TopoDS_Shape tmpV = VLocs.Value(jcurr).Oriented(TopAbs_REVERSED);
486           B.Add(E1,TopoDS::Vertex(tmpV));
487           tmpEdges.Append(E1);
488           B.MakeEdge(E2,tc2,tol);
489           tmpV = VLocs.Value(jcurr).Oriented(TopAbs_FORWARD);
490           B.Add(E2,TopoDS::Vertex(tmpV));
491           B.Add(E2,V2);
492         }
493         else {
494           B.MakeEdge(E1,tc2,tol);
495           TopoDS_Shape tmpV = VLocs.Value(jcurr).Oriented(TopAbs_FORWARD);
496           B.Add(E1,TopoDS::Vertex(tmpV));
497           B.Add(E1,V1);
498           E1.Reverse();
499           tmpEdges.Append(E1);
500           B.MakeEdge(E2,tc1,tol);
501           B.Add(E2,V2);
502           tmpV = VLocs.Value(jcurr).Oriented(TopAbs_REVERSED);
503           B.Add(E2,TopoDS::Vertex(tmpV));
504           E2.Reverse();
505         }
506         // create wire from tmpEdges
507         TopoDS_Wire W;
508         B.MakeWire(W);
509         for(j=1; j<=tmpEdges.Length(); j++)
510           B.Add(W,tmpEdges.Value(j));
511         Wires.Append(W);
512         jcurr++;
513         tmpEdges.Clear();
514         Edges.Remove(i);
515         Edges.InsertAfter(i-1,E1);
516         Edges.InsertAfter(i,E2);
517       }
518       else {
519         tmpEdges.Append(E);
520       }
521     }
522   }
523   // create wire from other edges
524   TopoDS_Wire W;
525   B.MakeWire(W);
526   for(; i<=Edges.Length(); i++)
527     B.Add(W,Edges.Value(i));
528   Wires.Append(W);
529   //cout<<"Wires.Length()="<<Wires.Length()<<endl;
530
531   if( Wires.Length() != nbLocs-1 ) {
532     if(aCI) delete aCI;
533     Standard_ConstructionError::Raise
534       ("One of location shapes is not lied on the path");
535   }
536
537   //TopTools_SequenceOfShape aSeqBases;
538   //TopTools_SequenceOfShape aSeqSubBases;
539   //TopTools_SequenceOfShape aSeqFaces;
540   TopoDS_Compound aComp;
541   B.MakeCompound(aComp);
542   for(i=1 ; i<nbBases; i++) {
543     TopoDS_Wire WPath = TopoDS::Wire(Wires.Value(i));
544     // 1 section
545     Handle(Standard_Transient) anItem1 = aBasesObjs->Value(i);
546     if(anItem1.IsNull())
547       continue;
548     Handle(GEOM_Function) aRefBase1 = Handle(GEOM_Function)::DownCast(anItem1);
549     if(aRefBase1.IsNull())
550       continue;
551     TopoDS_Shape aShBase1 = aRefBase1->GetValue();
552     if(aShBase1.IsNull())
553       continue;
554     TopAbs_ShapeEnum aType1 = aShBase1.ShapeType();
555     // 2 section
556     Handle(Standard_Transient) anItem2 = aBasesObjs->Value(i+1);
557     if(anItem2.IsNull())
558       continue;
559     Handle(GEOM_Function) aRefBase2 = Handle(GEOM_Function)::DownCast(anItem2);
560     if(aRefBase2.IsNull())
561       continue;
562     TopoDS_Shape aShBase2 = aRefBase2->GetValue();
563     if(aShBase2.IsNull())
564       continue;
565     TopAbs_ShapeEnum aType2 = aShBase2.ShapeType();
566     
567     //BRepTools::Write(aShBase1,"/dn02/users_Linux/skl/work/Bugs/14857/base1.brep");
568
569     bool OkSec = ( aType1==TopAbs_SHELL || aType1==TopAbs_FACE ) &&
570                  ( aType2==TopAbs_SHELL || aType2==TopAbs_FACE );
571     if( !OkSec ) {
572       if(aCI) delete aCI;
573       Standard_ConstructionError::Raise("One of section shapes has invalid type");
574     }
575
576     bool CreateFewSolids = false;
577     // compare sections
578     TopExp_Explorer anExp;
579     Standard_Integer nbf1 = 0;
580     for ( anExp.Init( aShBase1, TopAbs_FACE ); anExp.More(); anExp.Next() ) {
581       nbf1++;
582     }
583     Standard_Integer nbf2 = 0;
584     for ( anExp.Init( aShBase2, TopAbs_FACE ); anExp.More(); anExp.Next() ) {
585       nbf2++;
586     }
587     if(nbf1==nbf2) {
588       CreateFewSolids = true;
589     }
590
591     /*
592     // check orientation of sections
593     bool NeedReverse = false;
594     {
595       // first section
596       anExp.Init( aShBase1, TopAbs_FACE );
597       TopoDS_Shape aFace = anExp.Current();
598       TColgp_SequenceOfPnt aPnts;
599       double xc=0, yc=0, zc=0;
600       for ( anExp.Init( aFace, TopAbs_VERTEX ); anExp.More(); anExp.Next() ) {
601         TopoDS_Vertex V = TopoDS::Vertex(anExp.Current());
602         aPnts.Append(BRep_Tool::Pnt(V));
603         xc += aPnts.Last().X();
604         yc += aPnts.Last().Y();
605         zc += aPnts.Last().Z();
606       }
607       gp_Pnt PC( xc/aPnts.Length(), yc/aPnts.Length(), zc/aPnts.Length() );
608       gp_Vec V1(PC,aPnts.Value(1));
609       gp_Vec V2(PC,aPnts.Value(2));
610       gp_Vec VN = V1.Crossed(V2);
611       for(int ip=2; ip<aPnts.Length(); ip++) {
612         V1 = gp_Vec(PC,aPnts.Value(ip));
613         V2 = gp_Vec(PC,aPnts.Value(ip+1));
614         VN.Add(V1.Crossed(V2));
615       }
616       gp_Vec PathNorm;
617       gp_Pnt PLoc = BRep_Tool::Pnt(TopoDS::Vertex(VLocs(i)));
618       TopExp_Explorer WE;
619       for ( WE.Init( WPath, TopAbs_EDGE ); WE.More(); WE.Next() ) {
620         TopoDS_Edge edge = TopoDS::Edge(WE.Current());
621         double tol = BRep_Tool::Tolerance(edge);
622         TopoDS_Vertex VF = sae.FirstVertex(edge);
623         gp_Pnt PF = BRep_Tool::Pnt(VF);
624         if( PF.Distance(PLoc) < tol ) {
625           double fp,lp;
626           Handle(Geom_Curve) C = BRep_Tool::Curve(edge,fp,lp);
627           gp_Pnt P1,P2;
628           C->D0(fp,P1);
629           if( P1.Distance(PLoc) < tol ) {
630             C->D0(fp+(lp-fp)/100,P2);
631           }
632           else {
633             C->D0(lp,P1);
634             C->D0(lp+(fp-lp)/100,P2);
635           }
636           PathNorm = gp_Vec(P1,P2);
637           break;
638         }
639         else {
640           TopoDS_Vertex VL = sae.LastVertex(edge);
641           gp_Pnt PL = BRep_Tool::Pnt(VL);
642           if( PL.Distance(PLoc) < tol ) {
643             double fp,lp;
644             Handle(Geom_Curve) C = BRep_Tool::Curve(edge,fp,lp);
645             gp_Pnt P1,P2;
646             C->D0(fp,P1);
647             if( P1.Distance(PLoc) < tol ) {
648               C->D0(fp+(lp-fp)/100,P2);
649             }
650             else {
651               C->D0(lp,P1);
652               C->D0(lp+(fp-lp)/100,P2);
653             }
654             PathNorm = gp_Vec(P2,P1);
655             break;
656           }
657         }
658       }
659       cout<<"VN("<<VN.X()<<","<<VN.Y()<<","<<VN.Z()<<")"<<endl;
660       cout<<"PathNorm("<<PathNorm.X()<<","<<PathNorm.Y()<<","<<PathNorm.Z()<<")"<<endl;
661       if(fabs(VN.Angle(PathNorm))>PI/2.) {
662         NeedReverse = true;
663         aShBase1.Reverse();
664       }
665     }
666     {
667       // second section
668       anExp.Init( aShBase2, TopAbs_FACE );
669       TopoDS_Shape aFace = anExp.Current();
670       TColgp_SequenceOfPnt aPnts;
671       double xc=0, yc=0, zc=0;
672       for ( anExp.Init( aFace, TopAbs_VERTEX ); anExp.More(); anExp.Next() ) {
673         TopoDS_Vertex V = TopoDS::Vertex(anExp.Current());
674         aPnts.Append(BRep_Tool::Pnt(V));
675         xc += aPnts.Last().X();
676         yc += aPnts.Last().Y();
677         zc += aPnts.Last().Z();
678       }
679       gp_Pnt PC( xc/aPnts.Length(), yc/aPnts.Length(), zc/aPnts.Length() );
680       gp_Vec V1(PC,aPnts.Value(1));
681       gp_Vec V2(PC,aPnts.Value(2));
682       gp_Vec VN = V1.Crossed(V2);
683       for(int ip=2; ip<aPnts.Length(); ip++) {
684         V1 = gp_Vec(PC,aPnts.Value(ip));
685         V2 = gp_Vec(PC,aPnts.Value(ip+1));
686         VN.Add(V1.Crossed(V2));
687       }
688       gp_Vec PathNorm;
689       gp_Pnt PLoc = BRep_Tool::Pnt(TopoDS::Vertex(VLocs(i+1)));
690       TopExp_Explorer WE;
691       for ( WE.Init( WPath, TopAbs_EDGE ); WE.More(); WE.Next() ) {
692         TopoDS_Edge edge = TopoDS::Edge(WE.Current());
693         double tol = BRep_Tool::Tolerance(edge);
694         TopoDS_Vertex VF = sae.FirstVertex(edge);
695         gp_Pnt PF = BRep_Tool::Pnt(VF);
696         if( PF.Distance(PLoc) < tol ) {
697           double fp,lp;
698           Handle(Geom_Curve) C = BRep_Tool::Curve(edge,fp,lp);
699           gp_Pnt P1,P2;
700           C->D0(fp,P1);
701           if( P1.Distance(PLoc) < tol ) {
702             C->D0(fp+(lp-fp)/100,P2);
703           }
704           else {
705             C->D0(lp,P1);
706             C->D0(lp+(fp-lp)/100,P2);
707           }
708           PathNorm = gp_Vec(P2,P1);
709           break;
710         }
711         else {
712           TopoDS_Vertex VL = sae.LastVertex(edge);
713           gp_Pnt PL = BRep_Tool::Pnt(VL);
714           if( PL.Distance(PLoc) < tol ) {
715             double fp,lp;
716             Handle(Geom_Curve) C = BRep_Tool::Curve(edge,fp,lp);
717             gp_Pnt P1,P2;
718             C->D0(fp,P1);
719             if( P1.Distance(PLoc) < tol ) {
720               C->D0(fp+(lp-fp)/100,P2);
721             }
722             else {
723               C->D0(lp,P1);
724               C->D0(lp+(fp-lp)/100,P2);
725             }
726             PathNorm = gp_Vec(P2,P1);
727             break;
728           }
729         }
730       }
731       //cout<<"VN("<<VN.X()<<","<<VN.Y()<<","<<VN.Z()<<")"<<endl;
732       //cout<<"PathNorm("<<PathNorm.X()<<","<<PathNorm.Y()<<","<<PathNorm.Z()<<")"<<endl;
733       if(fabs(VN.Angle(PathNorm))>PI/2.)
734         aShBase2.Reverse();
735     }
736     */
737
738     if(!CreateFewSolids) {
739       // we can create only one solid
740       TopoDS_Shape aWire1, aWire2;
741       // prepare aWire1
742       if(aType1==TopAbs_SHELL) {
743         // create wire as boundary contour if shell is no closed
744         // get free boundary shapes
745         ShapeAnalysis_FreeBounds anAnalizer( aShBase1 );
746         TopoDS_Compound aClosed = anAnalizer.GetClosedWires();
747         //TopExp_Explorer anExp;
748         Standard_Integer NbWires = 0;
749         for ( anExp.Init( aClosed, TopAbs_WIRE ); anExp.More(); anExp.Next() ) {
750           NbWires++;
751           aWire1 = anExp.Current();
752         }
753         if(NbWires!=1) {
754           // bad case
755           if(aCI) delete aCI;
756           Standard_ConstructionError::Raise("Bad shell is used as section ");
757         }
758       }
759       else { // aType1==TopAbs_FACE
760         TopExp_Explorer aExpW(aShBase1,TopAbs_WIRE);
761         aWire1 = aExpW.Current();
762       }
763       // prepare aWire2
764       if(aType2==TopAbs_SHELL) {
765         // create wire as boundary contour if shell is no closed
766         // get free boundary shapes
767         ShapeAnalysis_FreeBounds anAnalizer( aShBase2 );
768         TopoDS_Compound aClosed = anAnalizer.GetClosedWires();
769         //TopExp_Explorer anExp;
770         Standard_Integer NbWires = 0;
771         for ( anExp.Init( aClosed, TopAbs_WIRE ); anExp.More(); anExp.Next() ) {
772           NbWires++;
773           aWire2 = anExp.Current();
774         }
775         if(NbWires!=1) {
776           // bad case
777           if(aCI) delete aCI;
778           Standard_ConstructionError::Raise("Bad shell is used as section ");
779         }
780       }
781       else { // aType2==TopAbs_FACE
782         TopExp_Explorer aExpW(aShBase2,TopAbs_WIRE);
783         aWire2 = aExpW.Current();
784       }
785       // make pipe using aWire1 and aWire2
786       if( !aWire1.IsNull() && !aWire2.IsNull() ) {
787         //BRepOffsetAPI_MakePipeShell aBuilder(aWirePath);
788         BRepOffsetAPI_MakePipeShell aBuilder(WPath);
789         aBuilder.Add(aWire1, TopoDS::Vertex(VLocs(i)),
790                      aWithContact, aWithCorrect);
791         aBuilder.Add(aWire2, TopoDS::Vertex(VLocs(i+1)),
792                      aWithContact, aWithCorrect);
793         if(!aBuilder.IsReady()) {
794           if(aCI) delete aCI;
795           Standard_ConstructionError::Raise("Invalid input data for building PIPE: bases are invalid");
796         }
797         aBuilder.Build();
798         TopoDS_Shape aShape = aBuilder.Shape();
799         TopoDS_Shell aShell;
800         B.MakeShell(aShell);
801         for ( anExp.Init( aShape, TopAbs_FACE ); anExp.More(); anExp.Next() ) {
802           B.Add(aShell,anExp.Current());
803         }
804         for ( anExp.Init( aShBase1, TopAbs_FACE ); anExp.More(); anExp.Next() ) {
805           B.Add(aShell,anExp.Current());
806         }
807         for ( anExp.Init( aShBase2, TopAbs_FACE ); anExp.More(); anExp.Next() ) {
808           B.Add(aShell,anExp.Current());
809         }
810         // make sewing for this shell
811         Handle(BRepBuilderAPI_Sewing) aSewing = new BRepBuilderAPI_Sewing;
812         aSewing->SetTolerance(Precision::Confusion());
813         aSewing->SetFaceMode(Standard_True);
814         aSewing->SetFloatingEdgesMode(Standard_False);
815         aSewing->SetNonManifoldMode(Standard_False);
816         for ( anExp.Init( aShell, TopAbs_FACE ); anExp.More(); anExp.Next() ) {
817           aSewing->Add(anExp.Current());
818         }
819         aSewing->Perform();
820         const TopoDS_Shape aSewShape = aSewing->SewedShape();
821         if( aSewShape.ShapeType() == TopAbs_SHELL ) {
822           aShell = TopoDS::Shell(aSewShape);
823           GProp_GProps aSystem;
824           BRepGProp::VolumeProperties(aShell, aSystem);
825           if(aSystem.Mass()<0) {
826             aShell.Reverse();
827           }
828           if(BRep_Tool::IsClosed(aShell)) {
829             TopoDS_Solid aSolid;
830             B.MakeSolid(aSolid);
831             B.Add(aSolid,aShell);
832             B.Add(aComp,aSolid);
833           }
834           else {
835             B.Add(aComp,aShell);
836           }
837         }
838         else {
839           B.Add(aComp,aShell);
840         }
841       }
842     }
843     else {
844       // main block - creation few solids (for each pair of faces)
845       TopTools_MapOfShape aFaces1,aFaces2;
846       for ( anExp.Init( aShBase1, TopAbs_FACE ); anExp.More(); anExp.Next() ) {
847         aFaces1.Add(anExp.Current());
848       }
849       for ( anExp.Init( aShBase2, TopAbs_FACE ); anExp.More(); anExp.Next() ) {
850         aFaces2.Add(anExp.Current());
851       }
852       // creating map of edge faces
853       TopTools_IndexedDataMapOfShapeListOfShape aMapEdgeFaces1;
854       TopExp::MapShapesAndAncestors(aShBase1, TopAbs_EDGE, TopAbs_FACE, aMapEdgeFaces1);
855       TopTools_IndexedDataMapOfShapeListOfShape aMapEdgeFaces2;
856       TopExp::MapShapesAndAncestors(aShBase2, TopAbs_EDGE, TopAbs_FACE, aMapEdgeFaces2);
857   
858       // constuct map face->face
859       TopTools_IndexedDataMapOfShapeShape FF;
860       TopoDS_Shape FS1,FS2;
861       if(nbSubBases==0) {
862         // find edge the most distant from location point
863         // (this edge is not shared by two faces)
864         double maxdist = 0.;
865         TopoDS_Shape E1;
866         TopoDS_Vertex V11,V21;
867         for(j=1; j<=aMapEdgeFaces1.Extent(); j++) {
868           TopoDS_Shape tmp = aMapEdgeFaces1.FindKey(j);
869           const TopTools_ListOfShape& aList = aMapEdgeFaces1.FindFromKey(tmp);
870           if(aList.Extent()>1)
871             continue;
872           TopExp_Explorer expv;
873           expv.Init( tmp, TopAbs_VERTEX );
874           TopoDS_Vertex V1 = TopoDS::Vertex(expv.Current());
875           expv.Next();
876           TopoDS_Vertex V2 = TopoDS::Vertex(expv.Current());
877           gp_Pnt P1 = BRep_Tool::Pnt(V1);
878           gp_Pnt P2 = BRep_Tool::Pnt(V2);
879           double dist = PLocs.Value(i).Distance(P1) + PLocs.Value(i).Distance(P2);
880           if(dist>maxdist) {
881             E1 = tmp;
882             V11 = V1;
883             V21 = V2;
884             TopTools_ListIteratorOfListOfShape anIter(aList);
885             FS1 = anIter.Value();
886             maxdist = dist;
887           }
888         }
889         // main direction for comparing
890         gp_Vec VM(PLocs.Value(i),PLocs.Value(i+1));
891         // find corresponding edge from next section
892         double minang = PI;
893         gp_Pnt P11 = BRep_Tool::Pnt(V11);
894         gp_Pnt P21 = BRep_Tool::Pnt(V21);
895         TopoDS_Shape E2;
896         TopoDS_Vertex V12,V22;
897         for(j=1; j<=aMapEdgeFaces2.Extent(); j++) {
898           TopoDS_Shape tmp = aMapEdgeFaces2.FindKey(j);
899           const TopTools_ListOfShape& aList = aMapEdgeFaces2.FindFromKey(tmp);
900           if(aList.Extent()>1)
901             continue;
902           TopExp_Explorer expv;
903           expv.Init( tmp, TopAbs_VERTEX );
904           TopoDS_Vertex V1tmp = TopoDS::Vertex(expv.Current());
905           expv.Next();
906           TopoDS_Vertex V2tmp = TopoDS::Vertex(expv.Current());
907           gp_Pnt P1tmp = BRep_Tool::Pnt(V1tmp);
908           gp_Pnt P2tmp = BRep_Tool::Pnt(V2tmp);
909           double d1 = P1tmp.Distance(P11) + P2tmp.Distance(P21);
910           double d2 = P1tmp.Distance(P21) + P2tmp.Distance(P11);
911           TopoDS_Vertex V1,V2;
912           gp_Pnt P1,P2;
913           if(d1>d2) {
914             V1 = V2tmp; P1 = P2tmp;
915             V2 = V1tmp; P2 = P1tmp;
916           }
917           else {
918             V1 = V1tmp; P1 = P1tmp;
919             V2 = V2tmp; P2 = P2tmp;
920           }
921           gp_Vec Vec1(P11,P1);
922           gp_Vec Vec2(P21,P2);
923           double ang = fabs(Vec1.Angle(VM)) + fabs(Vec2.Angle(VM));
924           if(ang<minang) {
925             E2 = tmp;
926             V12 = V1;
927             V22 = V2;
928             TopTools_ListIteratorOfListOfShape anIter(aList);
929             FS2 = anIter.Value();
930             minang = ang;
931           }
932         }
933         // put all pairs to map FF
934         FF.Add(FS1,FS2);
935         FF.Add(E1,E2);
936         FF.Add(V11,V12);
937         FF.Add(V21,V22);
938
939         // add pairs of edges to FF
940         bool stat =  FillForOtherEdges(FS1,E1,V11,FF);
941         if( !stat ) {
942           if(aCI) delete aCI;
943           Standard_ConstructionError::Raise("FindForOtherEdges: Can not mapping other egdes");
944         }
945
946       }
947       else {
948         { // 1 section
949           Handle(Standard_Transient) anItem = aSubBasesObjs->Value(i);
950           if(anItem.IsNull()) {
951             if(aCI) delete aCI;
952             Standard_ConstructionError::Raise("Invalid subbase shape");
953           }
954           Handle(GEOM_Function) aRefBase = Handle(GEOM_Function)::DownCast(anItem);
955           if(aRefBase.IsNull()) {
956             if(aCI) delete aCI;
957             Standard_ConstructionError::Raise("Invalid subbase shape");
958           }
959           TopoDS_Shape aSh = aRefBase->GetValue();
960           if(aSh.IsNull()) {
961             if(aCI) delete aCI;
962             Standard_ConstructionError::Raise("Invalid subbase shape");
963           }
964           if(aSh.ShapeType()!=TopAbs_FACE) {
965             if(aCI) delete aCI;
966             Standard_ConstructionError::Raise("Invalid subbase shape");
967           }
968           FS1 = aSh;
969         }       
970         { // 2 section
971           Handle(Standard_Transient) anItem = aSubBasesObjs->Value(i+1);
972           if(anItem.IsNull()) {
973             if(aCI) delete aCI;
974             Standard_ConstructionError::Raise("Invalid subbase shape");
975           }
976           Handle(GEOM_Function) aRefBase = Handle(GEOM_Function)::DownCast(anItem);
977           if(aRefBase.IsNull()) {
978             if(aCI) delete aCI;
979             Standard_ConstructionError::Raise("Invalid subbase shape");
980           }
981           TopoDS_Shape aSh = aRefBase->GetValue();
982           if(aSh.IsNull()) {
983             if(aCI) delete aCI;
984             Standard_ConstructionError::Raise("Invalid subbase shape");
985           }
986           if(aSh.ShapeType()!=TopAbs_FACE) {
987             if(aCI) delete aCI;
988             Standard_ConstructionError::Raise("Invalid subbase shape");
989           }
990           FS2 = aSh;
991         }
992
993         if( !aFaces1.Contains(FS1) || !aFaces2.Contains(FS2) ) {
994           if(aCI) delete aCI;
995           Standard_ConstructionError::Raise("Invalid subbase shape");
996         }
997       
998         FF.Add(FS1,FS2);
999
1000         // add pairs of edges to FF
1001         bool stat =  FillCorrespondingEdges(FS1, FS2, TopoDS::Vertex(VLocs(i)),
1002                                             TopoDS::Vertex(VLocs(i+1)), WPath, FF);
1003         if( !stat ) {
1004           if(aCI) delete aCI;
1005           Standard_ConstructionError::Raise("Can not create correct pipe");
1006         }
1007       }
1008
1009       FindNextPairOfFaces(FS1, aMapEdgeFaces1, aMapEdgeFaces2, FF, aCI);
1010
1011
1012       // make pipe for each pair of faces
1013       for(j=1; j<=FF.Extent(); j++) {
1014         TopoDS_Shape F1 = FF.FindKey(j);
1015         if( F1.ShapeType() != TopAbs_FACE )
1016           continue;
1017         TopoDS_Shape F2 = FF.FindFromIndex(j);
1018         TopExp_Explorer aExpW1(F1,TopAbs_WIRE);
1019         TopoDS_Wire aWire1 = TopoDS::Wire(aExpW1.Current());
1020         TopExp_Explorer aExpW2(F2,TopAbs_WIRE);
1021         TopoDS_Wire aWire2 = TopoDS::Wire(aExpW2.Current());
1022         // make pipe using aWire1 and aWire2
1023         if( !aWire1.IsNull() && !aWire2.IsNull() ) {
1024           BRepOffsetAPI_MakePipeShell aBuilder(WPath);
1025           aBuilder.Add(aWire1, TopoDS::Vertex(VLocs(i)),
1026                        aWithContact, aWithCorrect);
1027           aBuilder.Add(aWire2, TopoDS::Vertex(VLocs(i+1)),
1028                        aWithContact, aWithCorrect);
1029           if(!aBuilder.IsReady()) {
1030             if(aCI) delete aCI;
1031             Standard_ConstructionError::Raise("Invalid input data for building PIPE: bases are invalid");
1032           }
1033           aBuilder.Build();
1034           TopoDS_Shape aShape = aBuilder.Shape();
1035           TopoDS_Shell aShell;
1036           B.MakeShell(aShell);
1037           for ( anExp.Init( aShape, TopAbs_FACE ); anExp.More(); anExp.Next() ) {
1038             B.Add(aShell,anExp.Current());
1039           }
1040
1041           B.Add(aShell,F1);
1042           B.Add(aShell,F2);
1043           // make sewing for this shell
1044           Handle(BRepBuilderAPI_Sewing) aSewing = new BRepBuilderAPI_Sewing;
1045           aSewing->SetTolerance(Precision::Confusion());
1046           aSewing->SetFaceMode(Standard_True);
1047           aSewing->SetFloatingEdgesMode(Standard_False);
1048           aSewing->SetNonManifoldMode(Standard_False);
1049           for ( anExp.Init( aShell, TopAbs_FACE ); anExp.More(); anExp.Next() ) {
1050             aSewing->Add(anExp.Current());
1051           }
1052           aSewing->Perform();
1053           const TopoDS_Shape aSewShape = aSewing->SewedShape();
1054           if( aSewShape.ShapeType() == TopAbs_SHELL ) {
1055             aShell = TopoDS::Shell(aSewShape);
1056             GProp_GProps aSystem;
1057             BRepGProp::VolumeProperties(aShell, aSystem);
1058             if(aSystem.Mass()<0) {
1059               //cout<<"aSewShape is reversed"<<endl;
1060               aShell.Reverse();
1061             }
1062             if(BRep_Tool::IsClosed(aShell)) {
1063               TopoDS_Solid aSolid;
1064               B.MakeSolid(aSolid);
1065               B.Add(aSolid,aShell);
1066               B.Add(aComp,aSolid);
1067             }
1068             else {
1069               B.Add(aComp,aShell);
1070             }
1071           }
1072           else {
1073             B.Add(aComp,aShell);
1074           }
1075         }
1076       }
1077
1078     }
1079   }
1080
1081   //BRepTools::Write(aComp,"/dn02/users_Linux/skl/work/Bugs/14857/comp.brep");
1082   return aComp;
1083 }
1084
1085
1086 //=======================================================================
1087 //function : Execute
1088 //purpose  :
1089 //=======================================================================
1090 Standard_Integer GEOMImpl_PipeDriver::Execute(TFunction_Logbook& log) const
1091 {
1092   if (Label().IsNull()) return 0;
1093   Handle(GEOM_Function) aFunction = GEOM_Function::GetFunction(Label());
1094   GEOMImpl_IPipe* aCI= 0;
1095   Standard_Integer aType = aFunction->GetType();
1096   if(aType == PIPE_BASE_PATH)
1097     aCI = new GEOMImpl_IPipe(aFunction);
1098   else if(aType == PIPE_DIFFERENT_SECTIONS)
1099     aCI = new GEOMImpl_IPipeDiffSect(aFunction);
1100   else if(aType == PIPE_SHELL_SECTIONS)
1101     aCI = new GEOMImpl_IPipeShellSect(aFunction);
1102   else
1103     return 0;
1104
1105   Handle(GEOM_Function) aRefPath = aCI->GetPath();
1106   TopoDS_Shape aShapePath = aRefPath->GetValue();
1107
1108
1109   if (aShapePath.IsNull()) {
1110     cout<<"Driver : path is null"<<endl;
1111     if(aCI) delete aCI;
1112     Standard_NullObject::Raise("MakePipe aborted : null path argument");
1113   }
1114   
1115   // Get path contour
1116   TopoDS_Wire aWirePath;
1117   if (aShapePath.ShapeType() == TopAbs_WIRE) {
1118     aWirePath = TopoDS::Wire(aShapePath);
1119   } 
1120   else {
1121     if (aShapePath.ShapeType() == TopAbs_EDGE) {
1122       TopoDS_Edge anEdge = TopoDS::Edge(aShapePath);
1123       aWirePath = BRepBuilderAPI_MakeWire(anEdge);
1124     } 
1125     else {
1126       if(aCI) delete aCI;
1127       Standard_TypeMismatch::Raise("MakePipe aborted : path shape is neither a wire nor an edge");
1128     } 
1129   }
1130   
1131   TopoDS_Shape aShape;
1132
1133   if (aType == PIPE_BASE_PATH) {
1134      
1135     Handle(GEOM_Function) aRefBase = aCI->GetBase();
1136    
1137     TopoDS_Shape aShapeBase = aRefBase->GetValue();
1138     
1139     if (aShapeBase.IsNull()) {
1140       if(aCI) delete aCI;
1141       Standard_NullObject::Raise("MakePipe aborted : null base argument");
1142     }
1143
1144     // Make pipe
1145     aShape = BRepOffsetAPI_MakePipe(aWirePath, aShapeBase);
1146   }
1147
1148   //building pipe with different sections
1149   else if (aType == PIPE_DIFFERENT_SECTIONS) 
1150   {
1151     GEOMImpl_IPipeDiffSect* aCIDS = (GEOMImpl_IPipeDiffSect*)aCI;
1152     //GEOMImpl_IPipeDiffSect* aCIDS = static_cast<GEOMImpl_IPipeDiffSect*>(aCI);
1153     //BRepOffsetAPI_MakePipeShell aBuilder(aWirePath);
1154     Handle(TColStd_HSequenceOfTransient) aBasesObjs = aCIDS->GetBases ();
1155     Handle(TColStd_HSequenceOfTransient) aLocObjs = aCIDS->GetLocations ();
1156     Standard_Boolean aWithContact = (aCIDS->GetWithContactMode());
1157     Standard_Boolean aWithCorrect = (aCIDS->GetWithCorrectionMode());
1158
1159     Standard_Integer i =1, nbBases = aBasesObjs->Length(), 
1160       nbLocs = (aLocObjs.IsNull() ? 0 :aLocObjs->Length());
1161     
1162     if(nbLocs && nbLocs != nbBases)
1163     {
1164       if(aCI) delete aCI;
1165       Standard_ConstructionError::Raise("Number of sections is not equal to number of locations ");
1166     }
1167     TopTools_SequenceOfShape aSeqBases;
1168     TopTools_SequenceOfShape aSeqLocs;
1169     TopTools_SequenceOfShape aSeqFaces;
1170     for( ; i <= nbBases; i++) 
1171     {
1172       Handle(Standard_Transient) anItem = aBasesObjs->Value(i);
1173       if(anItem.IsNull())
1174         continue;
1175       Handle(GEOM_Function) aRefBase = Handle(GEOM_Function)::DownCast(anItem);
1176       if(aRefBase.IsNull())
1177         continue;
1178       TopoDS_Shape aShapeBase = aRefBase->GetValue();
1179       if(aShapeBase.IsNull())
1180         continue;
1181       TopAbs_ShapeEnum aTypeBase = aShapeBase.ShapeType();
1182
1183       //if for section was specified face with a few wires then a few
1184       //    pipes were build and make solid 
1185       Standard_Boolean NeedCreateSolid = Standard_False;
1186       if(aTypeBase == TopAbs_SHELL) {
1187         // create wire as boundary contour if shell is no closed
1188         // get free boundary shapes
1189         ShapeAnalysis_FreeBounds anAnalizer( aShapeBase );
1190         TopoDS_Compound aClosed = anAnalizer.GetClosedWires();
1191         TopExp_Explorer anExp;
1192         TopoDS_Shape aWire;
1193         Standard_Integer NbWires = 0;
1194         for ( anExp.Init( aClosed, TopAbs_WIRE ); anExp.More(); anExp.Next() ) {
1195           NbWires++;
1196           aWire = anExp.Current();
1197         }
1198         if(NbWires!=1) {
1199           // bad case
1200           if(aCI) delete aCI;
1201           Standard_ConstructionError::Raise("Bad shell is used as section ");
1202         }
1203         NeedCreateSolid = Standard_True;
1204         aSeqFaces.Append(aShapeBase);
1205         aSeqBases.Append(aWire);
1206       }
1207       else if(aTypeBase == TopAbs_FACE)
1208       {
1209         NeedCreateSolid = Standard_True;
1210         //for case one path should be used other type function
1211         aSeqFaces.Append(aShapeBase);
1212         TopExp_Explorer aExpW(aShapeBase,TopAbs_WIRE);
1213         for( ; aExpW.More(); aExpW.Next())
1214         {
1215           TopoDS_Shape aWireProf = aExpW.Current();
1216           aSeqBases.Append(aWireProf);
1217         }
1218       }
1219       else if(aTypeBase == TopAbs_WIRE || aTypeBase == TopAbs_VERTEX) {
1220         aSeqBases.Append(aShapeBase);
1221       }
1222       else if(aTypeBase == TopAbs_EDGE)
1223       {
1224         TopoDS_Edge anEdge = TopoDS::Edge(aShapeBase);
1225         TopoDS_Shape aWireProf = BRepBuilderAPI_MakeWire(anEdge);
1226         aSeqBases.Append(aWireProf);
1227       }
1228       if(nbLocs) 
1229       {
1230         Handle(Standard_Transient) anItemLoc = aLocObjs->Value(i);
1231         if(anItemLoc.IsNull())
1232           continue;
1233         Handle(GEOM_Function) aRefLoc = Handle(GEOM_Function)::DownCast(anItemLoc);
1234         TopoDS_Shape aShapeLoc = aRefLoc->GetValue();
1235         if(aShapeLoc.IsNull() || aShapeLoc.ShapeType() != TopAbs_VERTEX)
1236           continue;
1237         aSeqLocs.Append(aShapeLoc);
1238       }
1239     }
1240     
1241     nbLocs = aSeqLocs.Length();
1242
1243     // skl 02.05.2007
1244     if(nbLocs>0) {
1245       // we have to check that each location shape is a vertex from
1246       // path and update aSeqLocs if it is needed (and possible)
1247       TColgp_SequenceOfPnt PLocs;
1248       for(i=1; i<=nbLocs; i++) {
1249         TopoDS_Vertex V = TopoDS::Vertex(aSeqLocs.Value(i));
1250         PLocs.Append(BRep_Tool::Pnt(V));
1251       }
1252       TopTools_SequenceOfShape Edges;
1253       TopExp_Explorer anExp;
1254       for ( anExp.Init( aWirePath, TopAbs_EDGE ); anExp.More(); anExp.Next() ) {
1255         Edges.Append(anExp.Current());
1256       }
1257       int nbEdges = Edges.Length();
1258       ShapeAnalysis_Edge sae;
1259       TopoDS_Edge edge = TopoDS::Edge(Edges.First());
1260       double tol = BRep_Tool::Tolerance(edge);
1261       TopoDS_Vertex VF = sae.FirstVertex(edge);
1262       gp_Pnt PF = BRep_Tool::Pnt(VF);
1263       //cout<<"PF("<<PF.X()<<","<<PF.Y()<<","<<PF.Z()<<")"<<endl;
1264       if( PF.Distance(PLocs.First()) > tol ) {
1265         if(aCI) delete aCI;
1266         Standard_ConstructionError::Raise
1267           ("First location shapes is not coincided with first vertex of aWirePath");
1268       }
1269       aSeqLocs.ChangeValue(1) = VF;
1270       edge = TopoDS::Edge(Edges.Last());
1271       tol = BRep_Tool::Tolerance(edge);
1272       TopoDS_Vertex VL = sae.LastVertex(edge);
1273       gp_Pnt PL = BRep_Tool::Pnt(VL);
1274       if( PL.Distance(PLocs.Last()) > tol ) {
1275         if(aCI) delete aCI;
1276         Standard_ConstructionError::Raise
1277           ("Last location shapes is not coincided with last vertex of aWirePath");
1278       }
1279       aSeqLocs.ChangeValue(nbLocs) = VL;
1280       int jcurr = 2;
1281       for(i=1; i<=Edges.Length() && jcurr<nbLocs; i++) {
1282         TopoDS_Edge E = TopoDS::Edge(Edges.Value(i));
1283         tol = BRep_Tool::Tolerance(edge);
1284         TopoDS_Vertex V1 = sae.FirstVertex(E);
1285         TopoDS_Vertex V2 = sae.LastVertex(E);
1286         gp_Pnt P1 = BRep_Tool::Pnt(V1);
1287         gp_Pnt P2 = BRep_Tool::Pnt(V2);
1288         if( P2.Distance(PLocs.Value(jcurr)) < tol ) {
1289           aSeqLocs.ChangeValue(jcurr) = V2;
1290           jcurr++;
1291         }
1292         else {
1293           // find distance between E and aLocs(jcurr)
1294           double fp,lp;
1295           Handle(Geom_Curve) C = BRep_Tool::Curve(E,fp,lp);
1296           GeomAPI_ProjectPointOnCurve PPC (PLocs.Value(jcurr),C);
1297           if( PPC.NbPoints()>0 &&
1298               PLocs.Value(jcurr).Distance(PPC.Point(1)) < tol ) {
1299             double param = PPC.Parameter(1);
1300             gp_Pnt PC1;
1301             C->D0(param,PC1);
1302             // split current edge
1303             Handle(Geom_TrimmedCurve) tc1 = new Geom_TrimmedCurve(C,fp,param);
1304             Handle(Geom_TrimmedCurve) tc2 = new Geom_TrimmedCurve(C,param,lp);
1305             TopoDS_Edge E1,E2;
1306             BRep_Builder B;
1307             gp_Pnt Pfp;
1308             C->D0(fp,Pfp);
1309             if(Pfp.Distance(P1)<tol) {
1310               B.MakeEdge(E1,tc1,tol);
1311               B.Add(E1,V1);
1312               TopoDS_Shape tmpV = aSeqLocs.Value(jcurr).Oriented(TopAbs_REVERSED);
1313               B.Add(E1,TopoDS::Vertex(tmpV));
1314               B.MakeEdge(E2,tc2,tol);
1315               tmpV = aSeqLocs.Value(jcurr).Oriented(TopAbs_FORWARD);
1316               B.Add(E2,TopoDS::Vertex(tmpV));
1317               B.Add(E2,V2);
1318             }
1319             else {
1320               B.MakeEdge(E1,tc2,tol);
1321               TopoDS_Shape tmpV = aSeqLocs.Value(jcurr).Oriented(TopAbs_FORWARD);
1322               B.Add(E1,TopoDS::Vertex(tmpV));
1323               B.Add(E1,V1);
1324               E1.Reverse();
1325               B.MakeEdge(E2,tc1,tol);
1326               B.Add(E2,V2);
1327               tmpV = aSeqLocs.Value(jcurr).Oriented(TopAbs_REVERSED);
1328               B.Add(E2,TopoDS::Vertex(tmpV));
1329               E2.Reverse();
1330             }
1331             jcurr++;
1332             Edges.Remove(i);
1333             Edges.InsertAfter(i-1,E1);
1334             Edges.InsertAfter(i,E2);
1335           }
1336         }
1337       }
1338       if(nbEdges<Edges.Length()) {
1339         // one of edges was splitted => we have to update WirePath
1340         BRep_Builder B;
1341         TopoDS_Wire W;
1342         B.MakeWire(W);
1343         for(i=1; i<=Edges.Length(); i++) {
1344           B.Add(W,TopoDS::Edge(Edges.Value(i)));
1345         }
1346         aWirePath = W;
1347       }
1348     }
1349
1350     BRepOffsetAPI_MakePipeShell aBuilder(aWirePath);
1351
1352     Standard_Integer nbShapes = aSeqBases.Length();
1353     Standard_Integer step = nbShapes/nbBases;
1354     
1355     if(nbShapes < nbBases || fmod((double)nbShapes, (double)nbBases))
1356     {
1357       if(aCI) delete aCI;
1358       Standard_ConstructionError::Raise("Invalid sections were specified for building pipe");
1359     }
1360      
1361     Standard_Integer ind =0;     
1362     for( i=1; i  <= nbShapes && ind < nbShapes; i++) //i+nbBases <= nbShapes
1363     {
1364       TopTools_SequenceOfShape usedBases;
1365       Standard_Integer j = 1;
1366       for( ; j <= nbBases ; j++) 
1367       {
1368         ind = i + (j-1)*step;
1369         
1370          TopoDS_Shape aWireProf = aSeqBases.Value(ind);
1371          usedBases.Append(aWireProf);
1372          if(nbLocs) 
1373          {
1374            TopoDS_Shape aShapeLoc = aSeqLocs.Value(j);
1375            TopoDS_Vertex aVert = TopoDS::Vertex(aShapeLoc);
1376            aBuilder.Add(aWireProf,aVert,aWithContact,aWithCorrect);
1377          }
1378          else
1379            aBuilder.Add(aWireProf,aWithContact,aWithCorrect);
1380       }
1381       if(!aBuilder.IsReady())
1382       {
1383         if(aCI) delete aCI;
1384         Standard_ConstructionError::Raise("Invalid input data for building PIPE: bases are invalid");
1385       }
1386       aBuilder.Build();
1387       aShape = aBuilder.Shape();
1388       aSeqFaces.Append(aShape); 
1389       for( j = 1; j <=usedBases.Length(); j++)
1390         aBuilder.Delete(usedBases.Value(j));
1391     }
1392         
1393     //for case if section is face 
1394     if(aSeqFaces.Length() >1)
1395     {
1396       BRep_Builder aB;
1397       TopoDS_Compound aComp;
1398       aB.MakeCompound(aComp);
1399       for( i = 1; i <= aSeqFaces.Length(); i++)
1400         aB.Add(aComp,aSeqFaces.Value(i));
1401       aShape = aComp;
1402     }
1403   }
1404
1405   //building pipe with shell sections
1406   else if (aType == PIPE_SHELL_SECTIONS) {
1407     aShape = CreatePipeForShellSections(aWirePath,aCI);
1408   }
1409
1410   if (aShape.IsNull()) return 0;
1411
1412   BRepCheck_Analyzer ana (aShape, Standard_False);
1413   if (!ana.IsValid()) {
1414     if(aCI) delete aCI;
1415     Standard_ConstructionError::Raise("Algorithm have produced an invalid shape result");
1416   }
1417
1418   TopoDS_Shape aRes = GEOMImpl_IShapesOperations::CompsolidToCompound(aShape);
1419   aFunction->SetValue(aRes);
1420
1421   log.SetTouched(Label());
1422   if(aCI) delete aCI;
1423   return 1;
1424 }
1425
1426
1427 //=======================================================================
1428 //function :  GEOMImpl_PipeDriver_Type_
1429 //purpose  :
1430 //=======================================================================
1431 Standard_EXPORT Handle_Standard_Type& GEOMImpl_PipeDriver_Type_()
1432 {
1433
1434   static Handle_Standard_Type aType1 = STANDARD_TYPE(TFunction_Driver);
1435   if ( aType1.IsNull()) aType1 = STANDARD_TYPE(TFunction_Driver);
1436   static Handle_Standard_Type aType2 = STANDARD_TYPE(MMgt_TShared);
1437   if ( aType2.IsNull()) aType2 = STANDARD_TYPE(MMgt_TShared);
1438   static Handle_Standard_Type aType3 = STANDARD_TYPE(Standard_Transient);
1439   if ( aType3.IsNull()) aType3 = STANDARD_TYPE(Standard_Transient);
1440
1441
1442   static Handle_Standard_Transient _Ancestors[]= {aType1,aType2,aType3,NULL};
1443   static Handle_Standard_Type _aType = new Standard_Type("GEOMImpl_PipeDriver",
1444                                                          sizeof(GEOMImpl_PipeDriver),
1445                                                          1,
1446                                                          (Standard_Address)_Ancestors,
1447                                                          (Standard_Address)NULL);
1448
1449   return _aType;
1450 }
1451
1452 //=======================================================================
1453 //function : DownCast
1454 //purpose  :
1455 //=======================================================================
1456 const Handle(GEOMImpl_PipeDriver) Handle(GEOMImpl_PipeDriver)::DownCast(const Handle(Standard_Transient)& AnObject)
1457 {
1458   Handle(GEOMImpl_PipeDriver) _anOtherObject;
1459
1460   if (!AnObject.IsNull()) {
1461      if (AnObject->IsKind(STANDARD_TYPE(GEOMImpl_PipeDriver))) {
1462        _anOtherObject = Handle(GEOMImpl_PipeDriver)((Handle(GEOMImpl_PipeDriver)&)AnObject);
1463      }
1464   }
1465
1466   return _anOtherObject ;
1467 }
1468