Back to index

salome-geom  6.5.0
GEOMImpl_PipeDriver.cxx
Go to the documentation of this file.
00001 // Copyright (C) 2007-2012  CEA/DEN, EDF R&D, OPEN CASCADE
00002 //
00003 // Copyright (C) 2003-2007  OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
00004 // CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
00005 //
00006 // This library is free software; you can redistribute it and/or
00007 // modify it under the terms of the GNU Lesser General Public
00008 // License as published by the Free Software Foundation; either
00009 // version 2.1 of the License.
00010 //
00011 // This library is distributed in the hope that it will be useful,
00012 // but WITHOUT ANY WARRANTY; without even the implied warranty of
00013 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00014 // Lesser General Public License for more details.
00015 //
00016 // You should have received a copy of the GNU Lesser General Public
00017 // License along with this library; if not, write to the Free Software
00018 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
00019 //
00020 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
00021 
00022 #include <Standard_Stream.hxx>
00023 
00024 #include <GEOMImpl_PipeDriver.hxx>
00025 
00026 #include <GEOMImpl_IShapesOperations.hxx>
00027 #include <GEOMImpl_IPipeDiffSect.hxx>
00028 #include <GEOMImpl_IPipeShellSect.hxx>
00029 #include <GEOMImpl_IPipeBiNormal.hxx>
00030 #include <GEOMImpl_IPipe.hxx>
00031 #include <GEOMImpl_GlueDriver.hxx>
00032 #include <GEOMImpl_Types.hxx>
00033 #include <GEOM_Function.hxx>
00034 
00035 #include <ShapeAnalysis_FreeBounds.hxx>
00036 #include <ShapeAnalysis_Edge.hxx>
00037 #include <ShapeFix_Face.hxx>
00038 #include <ShapeFix_Shell.hxx>
00039 #include <ShapeFix_Shape.hxx>
00040 #include <ShapeFix_ShapeTolerance.hxx>
00041 
00042 #include <BRep_Tool.hxx>
00043 #include <BRep_Builder.hxx>
00044 #include <BRepBuilderAPI_MakeWire.hxx>
00045 #include <BRepBuilderAPI_Sewing.hxx>
00046 #include <BRepCheck_Analyzer.hxx>
00047 #include <BRepOffsetAPI_MakePipe.hxx>
00048 #include <BRepOffsetAPI_MakePipeShell.hxx>
00049 #include <GProp_GProps.hxx>
00050 #include <BRepGProp.hxx>
00051 #include <BRepBuilderAPI_MakeFace.hxx>
00052 #include <BRepBuilderAPI_Copy.hxx>
00053 
00054 #include <TopAbs.hxx>
00055 #include <TopExp.hxx>
00056 #include <TopExp_Explorer.hxx>
00057 #include <TopoDS.hxx>
00058 #include <TopoDS_Wire.hxx>
00059 #include <TopoDS_Edge.hxx>
00060 #include <TopoDS_Shape.hxx>
00061 #include <TopoDS_Solid.hxx>
00062 #include <TopoDS_Shell.hxx>
00063 #include <TopoDS_Face.hxx>
00064 #include <TopoDS_Compound.hxx>
00065 #include <TopTools_SequenceOfShape.hxx>
00066 #include <TopTools_HSequenceOfShape.hxx>
00067 #include <TopTools_IndexedDataMapOfShapeShape.hxx>
00068 #include <TopTools_IndexedDataMapOfShapeListOfShape.hxx>
00069 #include <TopTools_ListIteratorOfListOfShape.hxx>
00070 
00071 #include <GeomAPI_ProjectPointOnCurve.hxx>
00072 #include <GeomAPI_Interpolate.hxx>
00073 #include <Geom_TrimmedCurve.hxx>
00074 #include <Geom_Plane.hxx>
00075 #include <Geom_RectangularTrimmedSurface.hxx>
00076 #include <Geom_BezierSurface.hxx>
00077 #include <Geom_Line.hxx>
00078 #include <Geom_Conic.hxx>
00079 #include <Geom_BSplineCurve.hxx>
00080 #include <Geom_BSplineSurface.hxx>
00081 #include <GeomFill_BSplineCurves.hxx>
00082 #include <GeomConvert_ApproxCurve.hxx>
00083 #include <GeomConvert.hxx>
00084 
00085 #include <TColgp_SequenceOfPnt.hxx>
00086 #include <TColgp_HArray1OfPnt.hxx>
00087 #include <TColgp_Array2OfPnt.hxx>
00088 #include <TColStd_HSequenceOfTransient.hxx>
00089 
00090 #include <Precision.hxx>
00091 #include <Standard_NullObject.hxx>
00092 #include <Standard_TypeMismatch.hxx>
00093 #include <Standard_ConstructionError.hxx>
00094 
00095 #include "utilities.h"
00096 
00097 //=======================================================================
00098 //function : GetID
00099 //purpose  :
00100 //=======================================================================
00101 const Standard_GUID& GEOMImpl_PipeDriver::GetID()
00102 {
00103   static Standard_GUID aPipeDriver("FF1BBB19-5D14-4df2-980B-3A668264EA16");
00104   return aPipeDriver;
00105 }
00106 
00107 //=======================================================================
00108 //function : GEOMImpl_PipeDriver
00109 //purpose  :
00110 //=======================================================================
00111 GEOMImpl_PipeDriver::GEOMImpl_PipeDriver()
00112 {
00113 }
00114 
00115 //=======================================================================
00116 //function : FillForOtherEdges
00117 //purpose  : auxilary for CreatePipeForShellSections()
00118 //=======================================================================
00119 static bool FillForOtherEdges(const TopoDS_Shape& F1,
00120                               const TopoDS_Shape& E1,
00121                               const TopoDS_Shape& V1,
00122                               TopTools_IndexedDataMapOfShapeShape& FF)
00123 {
00124   //cout<<"FillForOtherEdges"<<endl;
00125   // find other pairs for vertexes and edges
00126   // creating map of vertex edges for both faces
00127   TopTools_IndexedDataMapOfShapeListOfShape aMapVertEdge1;
00128   TopExp::MapShapesAndAncestors(F1, TopAbs_VERTEX, TopAbs_EDGE, aMapVertEdge1);
00129   if (!FF.Contains(F1))
00130     MESSAGE("    FillForOtherEdges: map FF not contains key F1");
00131   if (!FF.Contains(E1))
00132     MESSAGE("    FillForOtherEdges: map FF not contains key E1");
00133   if (!FF.Contains(V1))
00134     MESSAGE("    FillForOtherEdges: map FF not contains key V1");
00135   const TopoDS_Shape& F2 = FF.FindFromKey(F1);
00136   const TopoDS_Shape& E2 = FF.FindFromKey(E1);
00137   const TopoDS_Shape& V2 = FF.FindFromKey(V1);
00138   TopTools_IndexedDataMapOfShapeListOfShape aMapVertEdge2;
00139   TopExp::MapShapesAndAncestors(F2, TopAbs_VERTEX, TopAbs_EDGE, aMapVertEdge2);
00140 
00141   TopoDS_Edge ES1 = TopoDS::Edge(E1);
00142   TopoDS_Edge ES2 = TopoDS::Edge(E2);
00143   TopoDS_Shape VS1 = V1;
00144   TopoDS_Shape VS2 = V2;
00145 
00146   ShapeAnalysis_Edge sae;
00147   while(1) {
00148     if (!aMapVertEdge1.Contains(VS1))
00149       MESSAGE ("    FillForOtherEdges: map aMapVertEdge1 not contains key VS1");
00150     const TopTools_ListOfShape& aList1 = aMapVertEdge1.FindFromKey(VS1);
00151     //TopoDS_Shape E1next;
00152     TopTools_ListIteratorOfListOfShape anIter1(aList1);
00153     if (anIter1.Value().IsSame(ES1)) {
00154       anIter1.Next();
00155     }
00156     //E1next = anIter1.Value();
00157     if (!aMapVertEdge2.Contains(VS2))
00158       MESSAGE ("    FillForOtherEdges: map aMapVertEdge2 not contains key VS2");
00159     const TopTools_ListOfShape& aList2 = aMapVertEdge2.FindFromKey(VS2);
00160     //TopoDS_Shape E2next;
00161     TopTools_ListIteratorOfListOfShape anIter2(aList2);
00162     if (anIter2.Value().IsSame(ES2)) {
00163       anIter2.Next();
00164     }
00165     //E2next = anIter2.Value();
00166     //ES1 = TopoDS::Edge(E1next);
00167     //ES2 = TopoDS::Edge(E2next);
00168     ES1 = TopoDS::Edge(anIter1.Value());
00169     ES2 = TopoDS::Edge(anIter2.Value());
00170     if (!FF.Contains(ES1)) {
00171       FF.Add(ES1,ES2);
00172     }
00173     if (VS1.IsSame(sae.FirstVertex(ES1)))
00174       VS1 = sae.LastVertex(ES1);
00175     else
00176       VS1 = sae.FirstVertex(ES1);
00177     if (VS2.IsSame(sae.FirstVertex(ES2)))
00178       VS2 = sae.LastVertex(ES2);
00179     else
00180       VS2 = sae.FirstVertex(ES2);
00181     if (VS1.IsSame(V1))
00182       break;
00183     if (!FF.Contains(VS1)) {
00184       FF.Add(VS1,VS2);
00185     }
00186   }
00187 
00188   return true;
00189 }
00190 
00191 //=======================================================================
00192 //function : FillCorrespondingEdges
00193 //purpose  : auxilary for CreatePipeForShellSections()
00194 //=======================================================================
00195 static bool FillCorrespondingEdges(const TopoDS_Shape& FS1,
00196                                    const TopoDS_Shape& FS2,
00197                                    const TopoDS_Vertex& aLoc1,
00198                                    const TopoDS_Vertex& aLoc2,
00199                                    const TopoDS_Wire& aWirePath,
00200                                    TopTools_IndexedDataMapOfShapeShape& FF)
00201 {
00202   //cout<<"FillCorrespondingEdges"<<endl;
00203   // find corresponding edges
00204   TopExp_Explorer expw1(FS1,TopAbs_WIRE);
00205   TopoDS_Wire aWire1 = TopoDS::Wire(expw1.Current());
00206   //exp = TopExp_Explorer(FS2,TopAbs_WIRE);
00207   TopExp_Explorer expw2(FS2,TopAbs_WIRE);
00208   TopoDS_Wire aWire2 = TopoDS::Wire(expw2.Current());
00209   BRepOffsetAPI_MakePipeShell aBuilder(aWirePath);
00210   aBuilder.Add(aWire1, aLoc1);
00211   aBuilder.Add(aWire2, aLoc2);
00212   if (!aBuilder.IsReady()) {
00213     return false;
00214   }
00215   aBuilder.Build();
00216   TopoDS_Shape aShape = aBuilder.Shape();
00217   /*
00218   TopoDS_Compound C;
00219   BRep_Builder B;
00220   B.MakeCompound(C);
00221   B.Add(C,aShape);
00222   B.Add(C,FS1);
00223   B.Add(C,FS2);
00224   BRepTools::Write(C,"/dn02/users_Linux/skl/work/Bugs/14857/comp.brep");
00225   */
00226   ShapeAnalysis_Edge sae;
00227   double tol = Max(BRep_Tool::Tolerance(TopoDS::Face(FS1)),
00228                     BRep_Tool::Tolerance(TopoDS::Face(FS2)));
00229   TopTools_MapOfShape Vs1,Vs2;
00230   TopExp_Explorer exp;
00231   exp.Init(FS1, TopAbs_EDGE);
00232   TopoDS_Edge E1 = TopoDS::Edge(exp.Current());
00233   TopoDS_Vertex V11 = sae.FirstVertex(E1);
00234   TopoDS_Vertex V21 = sae.LastVertex(E1);
00235   gp_Pnt P11 = BRep_Tool::Pnt(V11);
00236   gp_Pnt P21 = BRep_Tool::Pnt(V21);
00237   //cout<<"P11("<<P11.X()<<","<<P11.Y()<<","<<P11.Z()<<")"<<endl;
00238   //cout<<"P21("<<P21.X()<<","<<P21.Y()<<","<<P21.Z()<<")"<<endl;
00239   // find corresponding vertexes from created shape
00240   TopoDS_Vertex VN11,VN21;
00241   for (exp.Init(aShape, TopAbs_VERTEX); exp.More(); exp.Next()) {
00242     TopoDS_Vertex V = TopoDS::Vertex(exp.Current());
00243     gp_Pnt P = BRep_Tool::Pnt(V);
00244     if (P.Distance(P11)<tol) {
00245       VN11 = V;
00246     }
00247     if (P.Distance(P21)<tol) {
00248       VN21 = V;
00249     }
00250   }
00251   // find edge contains VN11 and VN21 and corresponding vertexes
00252   TopoDS_Vertex VN12,VN22;
00253   for (exp.Init(aShape, TopAbs_FACE); exp.More(); exp.Next()) {
00254     TopoDS_Shape F = exp.Current();
00255     TopExp_Explorer expe;
00256     bool IsFind = false;
00257     for (expe.Init(F, TopAbs_EDGE); expe.More(); expe.Next()) {
00258       TopoDS_Edge E = TopoDS::Edge(expe.Current());
00259       TopoDS_Vertex VF = sae.FirstVertex(E);
00260       TopoDS_Vertex VL = sae.LastVertex(E);
00261       if ((VF.IsSame(VN11) && VL.IsSame(VN21)) || (VF.IsSame(VN21) && VL.IsSame(VN11))) {
00262         IsFind = true;
00263         break;
00264       }
00265     }
00266     if (IsFind) {
00267       for (expe.Init(F, TopAbs_EDGE); expe.More(); expe.Next()) {
00268         TopoDS_Edge E = TopoDS::Edge(expe.Current());
00269         TopoDS_Vertex VF = sae.FirstVertex(E);
00270         TopoDS_Vertex VL = sae.LastVertex(E);
00271         if (VF.IsSame(VN11) && !VL.IsSame(VN21))
00272           VN12 = VL;
00273         if (VL.IsSame(VN11) && !VF.IsSame(VN21))
00274           VN12 = VF;
00275         if (VF.IsSame(VN21) && !VL.IsSame(VN11))
00276           VN22 = VL;
00277         if (VL.IsSame(VN21) && !VF.IsSame(VN11))
00278           VN22 = VF;
00279       }
00280       break;
00281     }
00282   }
00283   // find vertexes from FS2 corresponded to VN12 and VN22
00284   // and find edge from FS2 contains V12 and V22,
00285   // this edge will be corresponded to edge E1
00286   TopoDS_Vertex V12,V22;
00287   gp_Pnt PN12 = BRep_Tool::Pnt(VN12);
00288   gp_Pnt PN22 = BRep_Tool::Pnt(VN22);
00289   //cout<<"PN12("<<PN12.X()<<","<<PN12.Y()<<","<<PN12.Z()<<")"<<endl;
00290   //cout<<"PN22("<<PN22.X()<<","<<PN22.Y()<<","<<PN22.Z()<<")"<<endl;
00291   TopoDS_Edge E2;
00292   TopExp_Explorer expe;
00293   for (expe.Init(FS2, TopAbs_EDGE); expe.More(); expe.Next()) {
00294     TopoDS_Edge E = TopoDS::Edge(expe.Current());
00295     TopoDS_Vertex VF = sae.FirstVertex(E);
00296     TopoDS_Vertex VL = sae.LastVertex(E);
00297     gp_Pnt PF = BRep_Tool::Pnt(VF);
00298     gp_Pnt PL = BRep_Tool::Pnt(VL);
00299     if (PF.Distance(PN12)<tol && PL.Distance(PN22)<tol) {
00300       V12 = VF;
00301       V22 = VL;
00302       E2 = E;
00303       break;
00304     }
00305     if (PF.Distance(PN22)<tol && PL.Distance(PN12)<tol) {
00306       V12 = VL;
00307       V22 = VF;
00308       E2 = E;
00309       break;
00310     }
00311   }
00312   FF.Add(V11,V12);
00313   FF.Add(V21,V22);
00314   FF.Add(E1,E2);
00315 
00316   // find other pairs for vertexes and edges
00317   // creating map of vertex edges for both faces
00318   return FillForOtherEdges(FS1,E1,V21,FF);
00319 
00320   //return true;
00321 }
00322 
00323 //=======================================================================
00324 //function : FillCorrespondingEdges
00325 //purpose  : auxilary for CreatePipeShellsWithoutPath()
00326 //=======================================================================
00327 static bool FillCorrespondingEdges(const TopoDS_Shape& FS1,
00328                                    const TopoDS_Shape& FS2,
00329                                    const TopoDS_Vertex& aLoc1,
00330                                    const TopoDS_Vertex& aLoc2,
00331                                    TopTools_IndexedDataMapOfShapeShape& FF)
00332 {
00333   //cout<<"FillCorrespondingEdges"<<endl;
00334 
00335   gp_Pnt P1 = BRep_Tool::Pnt(aLoc1);
00336   gp_Pnt P2 = BRep_Tool::Pnt(aLoc2);
00337   gp_Vec aDir(P1,P2);
00338 
00339   ShapeAnalysis_Edge sae;
00340   double tol = Max(BRep_Tool::Tolerance(TopoDS::Face(FS1)),
00341                     BRep_Tool::Tolerance(TopoDS::Face(FS2)));
00342   TopTools_MapOfShape Vs1,Vs2;
00343 
00344   TopoDS_Vertex V11=aLoc1, V12=aLoc2, V21, V22;
00345   TopoDS_Edge E1,E2;
00346 
00347   TopExp_Explorer exp1;
00348   for (exp1.Init(FS1,TopAbs_EDGE); exp1.More(); exp1.Next()) {
00349     E1 = TopoDS::Edge(exp1.Current());
00350     TopoDS_Vertex V1 = sae.FirstVertex(E1);
00351     TopoDS_Vertex V2 = sae.LastVertex(E1);
00352     gp_Pnt Ptmp1 = BRep_Tool::Pnt(V1);
00353     gp_Pnt Ptmp2 = BRep_Tool::Pnt(V2);
00354     //cout<<"P11("<<P11.X()<<","<<P11.Y()<<","<<P11.Z()<<")"<<endl;
00355     //cout<<"P21("<<P21.X()<<","<<P21.Y()<<","<<P21.Z()<<")"<<endl;
00356     if (P1.Distance(Ptmp1)<tol) {
00357       V21 = V2;
00358       break;
00359     }
00360     if (P1.Distance(Ptmp2)<tol) {
00361       V21 = V1;
00362       break;
00363     }
00364   }
00365 
00366   TopoDS_Edge E21,E22;
00367   TopoDS_Vertex VE21,VE22;
00368   int nbe=0;
00369   for (exp1.Init(FS2,TopAbs_EDGE); exp1.More() && nbe<2; exp1.Next()) {
00370     TopoDS_Edge E = TopoDS::Edge(exp1.Current());
00371     TopoDS_Vertex V1 = sae.FirstVertex(E);
00372     TopoDS_Vertex V2 = sae.LastVertex(E);
00373     gp_Pnt Ptmp1 = BRep_Tool::Pnt(V1);
00374     gp_Pnt Ptmp2 = BRep_Tool::Pnt(V2);
00375     if (P2.Distance(Ptmp1)<tol) {
00376       if (nbe==0) {
00377         E21 = E;
00378         VE21 = V2;
00379         nbe++;
00380       }
00381       else if (nbe==1) {
00382         E22 = E;
00383         VE22 = V2;
00384         nbe++;
00385       }
00386     }
00387     if (P2.Distance(Ptmp2)<tol) {
00388       if (nbe==0) {
00389         E21 = E;
00390         VE21 = V1;
00391         nbe++;
00392       }
00393       else if (nbe==1) {
00394         E22 = E;
00395         VE22 = V1;
00396         nbe++;
00397       }
00398     }
00399   }
00400 
00401   gp_Pnt PV21 = BRep_Tool::Pnt(V21);
00402   gp_Pnt PE21 = BRep_Tool::Pnt(VE21);
00403   gp_Pnt PE22 = BRep_Tool::Pnt(VE22);
00404   gp_Vec aDir1(PV21,PE21);
00405   gp_Vec aDir2(PV21,PE22);
00406   double ang1 = aDir.Angle(aDir1);
00407   double ang2 = aDir.Angle(aDir2);
00408   if (fabs(ang1)<fabs(ang2)) {
00409     E2 = E21;
00410     V22 = VE21;
00411   }
00412   else {
00413     E2 = E22;
00414     V22 = VE22;
00415   }
00416 
00417   FF.Add(V11,V12);
00418   FF.Add(V21,V22);
00419   FF.Add(E1,E2);
00420 
00421   // find other pairs for vertexes and edges
00422   return FillForOtherEdges(FS1,E1,V21,FF);
00423 }
00424 
00425 //=======================================================================
00426 //function : FindNextPairOfFaces
00427 //purpose  : auxilary for CreatePipeForShellSections()
00428 //=======================================================================
00429 static void FindNextPairOfFaces(const TopoDS_Shape& aCurFace,
00430                                 TopTools_IndexedDataMapOfShapeListOfShape& aMapEdgeFaces1,
00431                                 TopTools_IndexedDataMapOfShapeListOfShape& aMapEdgeFaces2,
00432                                 TopTools_IndexedDataMapOfShapeShape& FF,
00433                                 GEOMImpl_IPipe* aCI)
00434 {
00435   //cout<<"FindNextPairOfFaces"<<endl;
00436   TopExp_Explorer anExp;
00437   for (anExp.Init(aCurFace, TopAbs_EDGE); anExp.More(); anExp.Next()) {
00438     TopoDS_Shape E1 = anExp.Current();
00439     if (!FF.Contains(E1)) {
00440       if (aCI) delete aCI;
00441       Standard_ConstructionError::Raise("FindNextPairOfFaces: Can not find edge in map");
00442     }
00443     if (!FF.Contains(E1))
00444       MESSAGE ("    FindNextPairOfFaces: map FF not contains key E1");
00445     const TopoDS_Shape& E2 = FF.FindFromKey(E1);
00446     TopExp_Explorer anExpV;
00447     anExpV.Init(E1, TopAbs_VERTEX);
00448     TopoDS_Shape V1 = anExpV.Current();
00449     if (!FF.Contains(V1)) {
00450       if (aCI) delete aCI;
00451       Standard_ConstructionError::Raise("FindNextPairOfFaces: Can not find vertex in map");
00452     }
00453 
00454     if (!aMapEdgeFaces1.Contains(E1))
00455       MESSAGE ("    FindNextPairOfFaces: map aMapEdgeFaces1 not contains key E1");
00456     const TopTools_ListOfShape& aList1 = aMapEdgeFaces1.FindFromKey(E1);
00457     if (aList1.Extent()<2)
00458       continue;
00459     TopTools_ListIteratorOfListOfShape anIter(aList1);
00460     if (anIter.Value().IsEqual(aCurFace)) {
00461       anIter.Next();
00462     }
00463     TopoDS_Shape F1other = anIter.Value();
00464     if (FF.Contains(F1other))
00465       continue;
00466 
00467     if (!FF.Contains(aCurFace))
00468       MESSAGE ("    FindNextPairOfFaces: map FF not contains key aCurFace");
00469     const TopoDS_Shape& F2 = FF.FindFromKey(aCurFace);
00470     if (!aMapEdgeFaces2.Contains(E2))
00471       MESSAGE ("    FindNextPairOfFaces: map aMapEdgeFaces2 not contains key E2");
00472     const TopTools_ListOfShape& aList2 = aMapEdgeFaces2.FindFromKey(E2);
00473     if (aList2.Extent()<2) {
00474       if (aCI) delete aCI;
00475       Standard_ConstructionError::Raise("FindNextPairOfFaces: Can not find corresponding face");
00476     }
00477     TopTools_ListIteratorOfListOfShape anIter2(aList2);
00478     if (anIter2.Value().IsEqual(F2)) {
00479       anIter2.Next();
00480     }
00481     TopoDS_Shape F2other = anIter2.Value();
00482     FF.Add(F1other,F2other);
00483 
00484     // add pairs of edges to FF
00485     bool stat =  FillForOtherEdges(F1other,E1,V1,FF);
00486     if (!stat) {
00487       if (aCI) delete aCI;
00488       Standard_ConstructionError::Raise("FindNextPairOfFaces: Can not mapping other egdes");
00489     }
00490 
00491     FindNextPairOfFaces(F1other, aMapEdgeFaces1, aMapEdgeFaces2, FF, aCI);
00492   }
00493 }
00494 
00495 //=======================================================================
00496 //function : FindFirstPairFaces
00497 //purpose  : auxilary for Execute()
00498 //=======================================================================
00499 static void FindFirstPairFaces(const TopoDS_Shape& S1, const TopoDS_Shape& S2,
00500                                TopoDS_Vertex& V1, TopoDS_Vertex& V2,
00501                                TopoDS_Shape& FS1, TopoDS_Shape& FS2)
00502 {
00503   //cout<<"FindFirstPairFaces"<<endl;
00504 
00505   // check if vertexes are sub-shapes of sections
00506   gp_Pnt P1 = BRep_Tool::Pnt(V1);
00507   gp_Pnt P2 = BRep_Tool::Pnt(V2);
00508   TopoDS_Vertex V1new,V2new;
00509   TopExp_Explorer exp;
00510   double mindist = 1.e10;
00511   for (exp.Init(S1, TopAbs_VERTEX); exp.More(); exp.Next()) {
00512     TopoDS_Vertex V = TopoDS::Vertex(exp.Current());
00513     gp_Pnt P = BRep_Tool::Pnt(V);
00514     double dist = P1.Distance(P);
00515     if (dist<mindist) {
00516       mindist = dist;
00517       V1new = V;
00518     }
00519   }
00520   mindist = 1.e10;
00521   for (exp.Init(S2, TopAbs_VERTEX); exp.More(); exp.Next()) {
00522     TopoDS_Vertex V = TopoDS::Vertex(exp.Current());
00523     gp_Pnt P = BRep_Tool::Pnt(V);
00524     double dist = P2.Distance(P);
00525     if (dist<mindist) {
00526       mindist = dist;
00527       V2new = V;
00528     }
00529   }
00530 
00531   //gp_Pnt P1new = BRep_Tool::Pnt(V1new);
00532   //gp_Pnt P2new = BRep_Tool::Pnt(V2new);
00533   //cout<<"  P1("<<P1.X()<<","<<P1.Y()<<","<<P1.Z()<<")"<<endl;
00534   //cout<<"  P2("<<P2.X()<<","<<P2.Y()<<","<<P2.Z()<<")"<<endl;
00535   //cout<<"  P1new("<<P1new.X()<<","<<P1new.Y()<<","<<P1new.Z()<<")"<<endl;
00536   //cout<<"  P2new("<<P2new.X()<<","<<P2new.Y()<<","<<P2new.Z()<<")"<<endl;
00537 
00538   // replace vertexes if it is needed
00539   if (!V1.IsSame(V1new)) {
00540     V1 = V1new;
00541     P1 = BRep_Tool::Pnt(V1);
00542     MESSAGE ("  replace V1");
00543   }
00544   else
00545     MESSAGE ("  not replace V1");
00546   if (!V2.IsSame(V2new)) {
00547     V2 = V2new;
00548     P2 = BRep_Tool::Pnt(V2);
00549     MESSAGE ("  replace V2");
00550   }
00551   else
00552     MESSAGE ("  not replace V2");
00553 
00554   TopTools_IndexedDataMapOfShapeListOfShape aMapVertFaces1;
00555   TopExp::MapShapesAndAncestors(S1, TopAbs_VERTEX, TopAbs_FACE, aMapVertFaces1);
00556   TopTools_IndexedDataMapOfShapeListOfShape aMapVertFaces2;
00557   TopExp::MapShapesAndAncestors(S2, TopAbs_VERTEX, TopAbs_FACE, aMapVertFaces2);
00558 
00559   if (!aMapVertFaces1.Contains(V1))
00560     MESSAGE ("    FindFirstPairFaces: map aMapVertFaces1 not contains key V1");
00561   const TopTools_ListOfShape& aList1 = aMapVertFaces1.FindFromKey(V1);
00562   TopTools_ListIteratorOfListOfShape anIter1(aList1);
00563   FS1 = anIter1.Value();
00564   // find middle point
00565   double x1=0., y1=0., z1=0.;
00566   int nbv1=0;
00567   for (exp.Init(FS1, TopAbs_VERTEX); exp.More(); exp.Next()) {
00568     TopoDS_Vertex V = TopoDS::Vertex(exp.Current());
00569     gp_Pnt P = BRep_Tool::Pnt(V);
00570     x1 += P.X();
00571     y1 += P.Y();
00572     z1 += P.Z();
00573     nbv1++;
00574   }
00575   gp_Pnt PM1(x1/nbv1, y1/nbv1, z1/nbv1);
00576 
00577   TColgp_SequenceOfPnt Ps;
00578   TopTools_SequenceOfShape Fs;
00579   if (!aMapVertFaces2.Contains(V2))
00580     MESSAGE ("    FindFirstPairFaces: map aMapVertFaces2 not contains key V2");
00581   const TopTools_ListOfShape& aList2 = aMapVertFaces2.FindFromKey(V2);
00582   TopTools_ListIteratorOfListOfShape anIter2(aList2);
00583   for (; anIter2.More(); anIter2.Next()) {
00584     TopoDS_Shape F = anIter2.Value();
00585     double x2=0., y2=0., z2=0.;
00586     int nbv2=0;
00587     for (exp.Init(F, TopAbs_VERTEX); exp.More(); exp.Next()) {
00588       TopoDS_Vertex V = TopoDS::Vertex(exp.Current());
00589       gp_Pnt P = BRep_Tool::Pnt(V);
00590       x2 += P.X();
00591       y2 += P.Y();
00592       z2 += P.Z();
00593       nbv2++;
00594     }
00595     gp_Pnt PM(x2/nbv1, y2/nbv1, z2/nbv1);
00596     Fs.Append(F);
00597     Ps.Append(PM);
00598   }
00599 
00600   gp_Vec aDir(P1,P2);
00601   int i=1;
00602   double MinAng = M_PI;
00603   int numface = 0;
00604   for (; i<=Fs.Length(); i++) {
00605     gp_Vec tmpDir(PM1,Ps(i));
00606     double ang = fabs(aDir.Angle(tmpDir));
00607     if (ang<MinAng) {
00608       MinAng = ang;
00609       numface = i;
00610     }
00611   }
00612   FS2 = Fs(numface);
00613 }
00614 
00615 //=======================================================================
00616 //function : CreatePipeWithDifferentSections
00617 //purpose  :
00618 //=======================================================================
00619 TopoDS_Shape GEOMImpl_PipeDriver::CreatePipeWithDifferentSections
00620                                   (const TopoDS_Wire& theWirePath,
00621                                    const Handle(TopTools_HSequenceOfShape) theHSeqBases,
00622                                    const Handle(TopTools_HSequenceOfShape) theHSeqLocs,
00623                                    const Standard_Boolean theWithContact,
00624                                    const Standard_Boolean theWithCorrect)
00625 {
00626   TopoDS_Shape aShape;
00627 
00628   TopoDS_Wire aWirePath = theWirePath;
00629 
00630   Standard_Integer nbBases = theHSeqBases->Length();
00631   Standard_Integer nbLocs = (theHSeqLocs.IsNull() ? 0 : theHSeqLocs->Length());
00632 
00633   if (nbLocs && nbLocs != nbBases) {
00634     Standard_ConstructionError::Raise("Number of sections is not equal to number of locations ");
00635   }
00636 
00637   TopTools_SequenceOfShape aSeqBases;
00638   TopTools_SequenceOfShape aSeqLocs;
00639   TopTools_SequenceOfShape aSeqFaces;
00640 
00641   Standard_Integer i = 1;
00642   for (i = 1; i <= nbBases; i++) {
00643     if (theHSeqBases->Value(i).IsNull())
00644       continue;
00645 
00646     // Make copy to prevent modifying of base object 0020766 : EDF 1320
00647     TopoDS_Shape aShapeBase;
00648     BRepBuilderAPI_Copy Copy (theHSeqBases->Value(i));
00649     if (Copy.IsDone())
00650       aShapeBase = Copy.Shape();
00651 
00652     TopAbs_ShapeEnum aTypeBase = aShapeBase.ShapeType();
00653 
00654     //if for section was specified face with a few wires then a few
00655     //    pipes were build and make solid
00656     Standard_Boolean NeedCreateSolid = Standard_False;
00657     if (aTypeBase == TopAbs_SHELL) {
00658       // create wire as boundary contour if shell is no closed
00659       // get free boundary shapes
00660       ShapeAnalysis_FreeBounds anAnalizer(aShapeBase);
00661       TopoDS_Compound aClosed = anAnalizer.GetClosedWires();
00662       TopExp_Explorer anExp;
00663       TopoDS_Shape aWire;
00664       Standard_Integer NbWires = 0;
00665       for (anExp.Init(aClosed, TopAbs_WIRE); anExp.More(); anExp.Next()) {
00666         NbWires++;
00667         aWire = anExp.Current();
00668       }
00669       if (NbWires != 1) {
00670         // bad case
00671         Standard_ConstructionError::Raise("Bad shell is used as section ");
00672       }
00673       NeedCreateSolid = Standard_True;
00674       aSeqFaces.Append(aShapeBase);
00675       aSeqBases.Append(aWire);
00676     }
00677     else if (aTypeBase == TopAbs_FACE) {
00678       NeedCreateSolid = Standard_True;
00679       //for case one path should be used other type function
00680       aSeqFaces.Append(aShapeBase);
00681       TopExp_Explorer aExpW(aShapeBase,TopAbs_WIRE);
00682       for (; aExpW.More(); aExpW.Next()) {
00683         TopoDS_Shape aWireProf = aExpW.Current();
00684         aSeqBases.Append(aWireProf);
00685       }
00686     }
00687     else if (aTypeBase == TopAbs_WIRE || aTypeBase == TopAbs_VERTEX) {
00688       aSeqBases.Append(aShapeBase);
00689     }
00690     else if (aTypeBase == TopAbs_EDGE) {
00691       TopoDS_Edge anEdge = TopoDS::Edge(aShapeBase);
00692       TopoDS_Shape aWireProf = BRepBuilderAPI_MakeWire(anEdge);
00693       aSeqBases.Append(aWireProf);
00694     }
00695     if (nbLocs) {
00696       TopoDS_Shape aShapeLoc = theHSeqLocs->Value(i);
00697       if (aShapeLoc.IsNull() || aShapeLoc.ShapeType() != TopAbs_VERTEX)
00698         continue;
00699       aSeqLocs.Append(aShapeLoc);
00700     }
00701   }
00702 
00703   nbLocs = aSeqLocs.Length();
00704 
00705   // skl 02.05.2007
00706   TopTools_SequenceOfShape Edges;
00707   if (nbLocs > 0) {
00708     // we have to check that each location shape is a vertex from
00709     // path and update aSeqLocs if it is needed (and possible)
00710     TColgp_SequenceOfPnt PLocs;
00711     for (i=1; i<=nbLocs; i++) {
00712       TopoDS_Vertex V = TopoDS::Vertex(aSeqLocs.Value(i));
00713       PLocs.Append(BRep_Tool::Pnt(V));
00714     }
00715     //TopTools_SequenceOfShape Edges;
00716     TopExp_Explorer anExp;
00717     for (anExp.Init(aWirePath, TopAbs_EDGE); anExp.More(); anExp.Next()) {
00718       Edges.Append(anExp.Current());
00719     }
00720     int nbEdges = Edges.Length();
00721     ShapeAnalysis_Edge sae;
00722     TopoDS_Edge edge = TopoDS::Edge(Edges.First());
00723     double tol = BRep_Tool::Tolerance(edge);
00724     TopoDS_Vertex VF = sae.FirstVertex(edge);
00725     gp_Pnt PF = BRep_Tool::Pnt(VF);
00726     //cout<<"PF("<<PF.X()<<","<<PF.Y()<<","<<PF.Z()<<")"<<endl;
00727     if (PF.Distance(PLocs.First()) > tol) {
00728       Standard_ConstructionError::Raise
00729         ("First location shapes is not coincided with first vertex of aWirePath");
00730     }
00731     aSeqLocs.ChangeValue(1) = VF;
00732     edge = TopoDS::Edge(Edges.Last());
00733     tol = BRep_Tool::Tolerance(edge);
00734     TopoDS_Vertex VL = sae.LastVertex(edge);
00735     gp_Pnt PL = BRep_Tool::Pnt(VL);
00736     if (PL.Distance(PLocs.Last()) > tol) {
00737       Standard_ConstructionError::Raise
00738         ("Last location shapes is not coincided with last vertex of aWirePath");
00739     }
00740     aSeqLocs.ChangeValue(nbLocs) = VL;
00741     int jcurr = 2;
00742     for (i=1; i<=Edges.Length() && jcurr<nbLocs; i++) {
00743       TopoDS_Edge E = TopoDS::Edge(Edges.Value(i));
00744       tol = BRep_Tool::Tolerance(edge);
00745       TopoDS_Vertex V1 = sae.FirstVertex(E);
00746       TopoDS_Vertex V2 = sae.LastVertex(E);
00747       gp_Pnt P1 = BRep_Tool::Pnt(V1);
00748       gp_Pnt P2 = BRep_Tool::Pnt(V2);
00749       if (P2.Distance(PLocs.Value(jcurr)) < tol) {
00750         aSeqLocs.ChangeValue(jcurr) = V2;
00751         jcurr++;
00752       }
00753       else {
00754         // find distance between E and aLocs(jcurr)
00755         double fp,lp;
00756         Handle(Geom_Curve) C = BRep_Tool::Curve(E,fp,lp);
00757         GeomAPI_ProjectPointOnCurve PPCurve (PLocs.Value(jcurr),C);
00758         if (PPCurve.NbPoints()>0 &&
00759             PLocs.Value(jcurr).Distance(PPCurve.Point(1)) < tol) {
00760           double param = PPCurve.Parameter(1);
00761           gp_Pnt PC1;
00762           C->D0(param,PC1);
00763           // split current edge
00764           Handle(Geom_TrimmedCurve) tc1 = new Geom_TrimmedCurve(C,fp,param);
00765           Handle(Geom_TrimmedCurve) tc2 = new Geom_TrimmedCurve(C,param,lp);
00766           TopoDS_Edge E1,E2;
00767           BRep_Builder B;
00768           gp_Pnt Pfp;
00769           C->D0(fp,Pfp);
00770           if (Pfp.Distance(P1)<tol) {
00771             B.MakeEdge(E1,tc1,tol);
00772             B.Add(E1,V1);
00773             TopoDS_Shape tmpV = aSeqLocs.Value(jcurr).Oriented(TopAbs_REVERSED);
00774             B.Add(E1,TopoDS::Vertex(tmpV));
00775             B.MakeEdge(E2,tc2,tol);
00776             tmpV = aSeqLocs.Value(jcurr).Oriented(TopAbs_FORWARD);
00777             B.Add(E2,TopoDS::Vertex(tmpV));
00778             B.Add(E2,V2);
00779           }
00780           else {
00781             B.MakeEdge(E1,tc2,tol);
00782             TopoDS_Shape tmpV = aSeqLocs.Value(jcurr).Oriented(TopAbs_FORWARD);
00783             B.Add(E1,TopoDS::Vertex(tmpV));
00784             B.Add(E1,V1);
00785             E1.Reverse();
00786             B.MakeEdge(E2,tc1,tol);
00787             B.Add(E2,V2);
00788             tmpV = aSeqLocs.Value(jcurr).Oriented(TopAbs_REVERSED);
00789             B.Add(E2,TopoDS::Vertex(tmpV));
00790             E2.Reverse();
00791           }
00792           jcurr++;
00793           Edges.Remove(i);
00794           Edges.InsertAfter(i-1,E1);
00795           Edges.InsertAfter(i,E2);
00796         }
00797       }
00798     }
00799     if (nbEdges<Edges.Length()) {
00800         // one of edges was splitted => we have to update WirePath
00801         BRep_Builder B;
00802         TopoDS_Wire W;
00803         B.MakeWire(W);
00804         for (i=1; i<=Edges.Length(); i++) {
00805           B.Add(W,TopoDS::Edge(Edges.Value(i)));
00806         }
00807         aWirePath = W;
00808     }
00809   }
00810 
00811   // check curvature of wire for condition that
00812   // max summary angle between directions along
00813   // wire path must be < 4*PI. If not - split wire
00814   // and seguences of shapes, perform pipe for each
00815   // and make sewing after that
00816   double fp,lp;
00817   Handle(Geom_Curve) C = BRep_Tool::Curve(TopoDS::Edge(Edges.Value(1)),fp,lp);
00818   gp_Pnt P1,P2;
00819   gp_Vec Vec1,Vec2;
00820   C->D1(fp,P1,Vec1);
00821   C->D1(lp,P2,Vec2);
00822   double SumAng = fabs(Vec1.Angle(Vec2));
00823   Vec1 = Vec2;
00824   P1 = P2;
00825   TColStd_SequenceOfInteger SplitEdgeNums,SplitLocNums;
00826   int LastLoc = 1;
00827   //cout<<"Edges.Length()="<<Edges.Length()<<endl;
00828   for (i=2; i<=Edges.Length(); i++) {
00829       TopoDS_Edge edge = TopoDS::Edge(Edges.Value(i));
00830       double tol = BRep_Tool::Tolerance(edge);
00831       Handle(Geom_Curve) C = BRep_Tool::Curve(edge,fp,lp);
00832       C->D1(lp,P2,Vec2);
00833       double ang = fabs(Vec1.Angle(Vec2));
00834       SumAng += ang;
00835       if (SumAng>4*M_PI) {
00836         SumAng = ang;
00837         SplitEdgeNums.Append(i-1);
00838         int j;
00839         for (j=LastLoc+1; j<=aSeqLocs.Length(); j++) {
00840           TopoDS_Vertex aVert = TopoDS::Vertex(aSeqLocs.Value(j));
00841           gp_Pnt P = BRep_Tool::Pnt(aVert);
00842           if (P1.Distance(P) < tol) {
00843             SplitLocNums.Append(j);
00844             LastLoc = j;
00845             break;
00846           }
00847         }
00848       }
00849       Vec1 = Vec2;
00850       P1 = P2;
00851   }
00852 
00853   if (SplitLocNums.Length()==SplitEdgeNums.Length() && SplitEdgeNums.Length()>0) {
00854       TopTools_SequenceOfShape aSeqRes;
00855       int nn, num1 = 1, num2 = 1;
00856       for (nn=1; nn<=SplitEdgeNums.Length(); nn++) {
00857         // create wirepath and sequences of shapes
00858         BRep_Builder B;
00859         TopoDS_Wire tmpW;
00860         B.MakeWire(tmpW);
00861         for (i=num1; i<=SplitEdgeNums.Value(nn); i++) {
00862           B.Add(tmpW,TopoDS::Edge(Edges.Value(i)));
00863         }
00864         num1 = SplitEdgeNums.Value(nn) + 1;
00865         TopTools_SequenceOfShape aTmpSeqBases;
00866         TopTools_SequenceOfShape aTmpSeqLocs;
00867         for (i=num2; i<=SplitLocNums.Value(nn); i++) {
00868           aTmpSeqBases.Append(aSeqBases.Value(i));
00869           aTmpSeqLocs.Append(aSeqLocs.Value(i));
00870         }
00871         num2 = SplitLocNums.Value(nn);
00872         // make pipe
00873         BRepOffsetAPI_MakePipeShell aBuilder(tmpW);
00874         Standard_Integer nbShapes = aTmpSeqBases.Length();
00875         for (i=1; i<=nbShapes; i++) {
00876           TopoDS_Shape aShapeLoc = aTmpSeqLocs.Value(i);
00877           TopoDS_Vertex aVert = TopoDS::Vertex(aShapeLoc);
00878           aBuilder.Add(aTmpSeqBases.Value(i), aVert, theWithContact, theWithCorrect);
00879         }
00880         if (!aBuilder.IsReady()) {
00881           Standard_ConstructionError::Raise("Invalid input data for building PIPE: bases are invalid");
00882         }
00883         aBuilder.Build();
00884         TopoDS_Shape resShape = aBuilder.Shape();
00885         aSeqRes.Append(resShape);
00886       }
00887       // create wirepath and sequences of shapes for last part
00888       BRep_Builder B;
00889       TopoDS_Wire tmpW;
00890       B.MakeWire(tmpW);
00891       for (i=num1; i<=Edges.Length(); i++) {
00892         B.Add(tmpW,TopoDS::Edge(Edges.Value(i)));
00893       }
00894       TopTools_SequenceOfShape aTmpSeqBases;
00895       TopTools_SequenceOfShape aTmpSeqLocs;
00896       for (i=num2; i<=aSeqLocs.Length(); i++) {
00897         aTmpSeqBases.Append(aSeqBases.Value(i));
00898         aTmpSeqLocs.Append(aSeqLocs.Value(i));
00899       }
00900       // make pipe for last part
00901       BRepOffsetAPI_MakePipeShell aBuilder(tmpW);
00902       Standard_Integer nbShapes = aTmpSeqBases.Length();
00903       for (i=1; i<=nbShapes; i++) {
00904         TopoDS_Shape aShapeLoc = aTmpSeqLocs.Value(i);
00905         TopoDS_Vertex aVert = TopoDS::Vertex(aShapeLoc);
00906         aBuilder.Add(aTmpSeqBases.Value(i), aVert, theWithContact, theWithCorrect);
00907       }
00908       if (!aBuilder.IsReady()) {
00909         Standard_ConstructionError::Raise("Invalid input data for building PIPE: bases are invalid");
00910       }
00911       aBuilder.Build();
00912       TopoDS_Shape resShape = aBuilder.Shape();
00913       aSeqRes.Append(resShape);
00914       // make sewing for result
00915       Handle(BRepBuilderAPI_Sewing) aSewing = new BRepBuilderAPI_Sewing;
00916       aSewing->SetTolerance(Precision::Confusion());
00917       aSewing->SetFaceMode(Standard_True);
00918       aSewing->SetFloatingEdgesMode(Standard_False);
00919       aSewing->SetNonManifoldMode(Standard_False);
00920       for (i=1; i<=aSeqRes.Length(); i++) {
00921         aSewing->Add(aSeqRes.Value(i));
00922       }
00923       aSewing->Perform();
00924       aShape = aSewing->SewedShape();
00925   }
00926   else {
00927       // old implementation without splitting
00928       BRepOffsetAPI_MakePipeShell aBuilder(aWirePath);
00929 
00930       Standard_Integer nbShapes = aSeqBases.Length();
00931       Standard_Integer step = nbShapes/nbBases;
00932 
00933       if (nbShapes < nbBases || fmod((double)nbShapes, (double)nbBases)) {
00934         Standard_ConstructionError::Raise("Invalid sections were specified for building pipe");
00935       }
00936       Standard_Integer ind =0;
00937       for (i = 1; i <= nbShapes && ind < nbShapes; i++) { //i+nbBases <= nbShapes
00938         TopTools_SequenceOfShape usedBases;
00939         Standard_Integer j = 1;
00940         for (; j <= nbBases; j++) {
00941           ind = i + (j-1)*step;
00942           TopoDS_Shape aWireProf = aSeqBases.Value(ind);
00943           usedBases.Append(aWireProf);
00944           if (nbLocs) {
00945             TopoDS_Shape aShapeLoc = aSeqLocs.Value(j);
00946             TopoDS_Vertex aVert = TopoDS::Vertex(aShapeLoc);
00947             aBuilder.Add(aWireProf, aVert, theWithContact, theWithCorrect);
00948           }
00949           else
00950             aBuilder.Add(aWireProf, theWithContact, theWithCorrect);
00951         }
00952         if (!aBuilder.IsReady()) {
00953           Standard_ConstructionError::Raise("Invalid input data for building PIPE: bases are invalid");
00954         }
00955         aBuilder.Build();
00956         aShape = aBuilder.Shape();
00957         aSeqFaces.Append(aShape);
00958         for (j = 1; j <=usedBases.Length(); j++)
00959           aBuilder.Delete(usedBases.Value(j));
00960       }
00961 
00962       //for case if section is face
00963       if (aSeqFaces.Length() >1) {
00964         BRep_Builder aB;
00965         TopoDS_Compound aComp;
00966         aB.MakeCompound(aComp);
00967         for (i = 1; i <= aSeqFaces.Length(); i++)
00968           aB.Add(aComp,aSeqFaces.Value(i));
00969         aShape = aComp;
00970       }
00971   }
00972 
00973   return aShape;
00974 }
00975 
00976 //=======================================================================
00977 //function : CreatePipeForShellSections
00978 //purpose  : auxilary for Execute()
00979 //=======================================================================
00980 static TopoDS_Shape CreatePipeForShellSections(const TopoDS_Wire& aWirePath,
00981                                                GEOMImpl_IPipe* aCI)
00982 {
00983   //cout<<"CreatePipeForShellSections"<<endl;
00984   //TopoDS_Shape res;
00985   int i,j;
00986   BRep_Builder B;
00987 
00988   GEOMImpl_IPipeShellSect* aCIDS = (GEOMImpl_IPipeShellSect*)aCI;
00989   Handle(TColStd_HSequenceOfTransient) aBasesObjs = aCIDS->GetBases();
00990   Handle(TColStd_HSequenceOfTransient) aSubBasesObjs = aCIDS->GetSubBases();
00991   Handle(TColStd_HSequenceOfTransient) aLocObjs = aCIDS->GetLocations();
00992   Standard_Boolean aWithContact = (aCIDS->GetWithContactMode());
00993   Standard_Boolean aWithCorrect = (aCIDS->GetWithCorrectionMode());
00994 
00995   Standard_Integer nbBases = aBasesObjs->Length(),
00996     nbSubBases = (aSubBasesObjs.IsNull() ? 0 :aSubBasesObjs->Length()),
00997     nbLocs = (aLocObjs.IsNull() ? 0 :aLocObjs->Length());
00998 
00999   if (nbLocs != nbBases) {
01000     if (aCI) delete aCI;
01001     Standard_ConstructionError::Raise("Number of sections is not equal to number of locations ");
01002   }
01003   if (nbSubBases && nbSubBases != nbBases) {
01004     if (aCI) delete aCI;
01005     Standard_ConstructionError::Raise("Number of sections is not equal to number of subsections ");
01006   }
01007 
01008   //BRepOffsetAPI_MakePipeShell aBuilder(aWirePath);
01009 
01010   TopTools_SequenceOfShape VLocs;
01011   for (i=1; i<=nbBases; i++) {
01012     Handle(Standard_Transient) anItemLoc = aLocObjs->Value(i);
01013     if (anItemLoc.IsNull())
01014       continue;
01015     Handle(GEOM_Function) aRefLoc = Handle(GEOM_Function)::DownCast(anItemLoc);
01016     TopoDS_Shape aShapeLoc = aRefLoc->GetValue();
01017     if (aShapeLoc.IsNull() || aShapeLoc.ShapeType() != TopAbs_VERTEX)
01018       continue;
01019     VLocs.Append(aShapeLoc);
01020   }
01021   nbLocs = VLocs.Length();
01022   if (nbLocs != nbBases) {
01023     if (aCI) delete aCI;
01024     Standard_ConstructionError::Raise("One of location shapes is not a vertex");
01025   }
01026   // split wire path by location points
01027   TColgp_SequenceOfPnt PLocs;
01028   for (i=1; i<=nbLocs; i++) {
01029     TopoDS_Vertex V = TopoDS::Vertex(VLocs.Value(i));
01030     PLocs.Append(BRep_Tool::Pnt(V));
01031   }
01032 
01033   TopTools_SequenceOfShape Edges;
01034   TopTools_SequenceOfShape Wires;
01035   ShapeAnalysis_Edge sae;
01036 
01037   if (nbLocs==2) {
01038     TopExp_Explorer anExp;
01039     for (anExp.Init(aWirePath, TopAbs_EDGE); anExp.More(); anExp.Next()) {
01040       Edges.Append(anExp.Current());
01041     }
01042     Standard_Integer Num1 = 0;
01043     Standard_Integer Num2 = 0;
01044     for (i=1; i<=Edges.Length(); i++) {
01045       TopoDS_Edge E = TopoDS::Edge(Edges.Value(i));
01046       double tol = BRep_Tool::Tolerance(E);
01047       TopoDS_Vertex V1 = sae.FirstVertex(E);
01048       TopoDS_Vertex V2 = sae.LastVertex(E);
01049       gp_Pnt P1 = BRep_Tool::Pnt(V1);
01050       gp_Pnt P2 = BRep_Tool::Pnt(V2);
01051       if (P1.Distance(PLocs.First()) < tol) {
01052         Num1 = i;
01053       }
01054       if (P2.Distance(PLocs.Last()) < tol) {
01055         Num2 = i;
01056       }
01057     }
01058     if (Num1>0 && Num2>0) {
01059       TopoDS_Wire W;
01060       B.MakeWire(W);
01061       for (i=Num1; i<=Num2; i++) {
01062         B.Add(W,Edges.Value(i));
01063       }
01064       Wires.Append(W);
01065     }
01066     else {
01067       Wires.Append(aWirePath);
01068     }
01069   }
01070   else {
01071     TopExp_Explorer anExp;
01072     for (anExp.Init(aWirePath, TopAbs_EDGE); anExp.More(); anExp.Next()) {
01073       Edges.Append(anExp.Current());
01074     }
01075     TopoDS_Edge edge = TopoDS::Edge(Edges.First());
01076     double tol = BRep_Tool::Tolerance(edge);
01077     TopoDS_Vertex VF = sae.FirstVertex(edge);
01078     gp_Pnt PF = BRep_Tool::Pnt(VF);
01079     //cout<<"PF("<<PF.X()<<","<<PF.Y()<<","<<PF.Z()<<")"<<endl;
01080     if (PF.Distance(PLocs.First()) > tol) {
01081       if (aCI) delete aCI;
01082       Standard_ConstructionError::Raise
01083         ("First location shapes is not coincided with first vertex of aWirePath");
01084     }
01085     VLocs.ChangeValue(1) = VF;
01086     edge = TopoDS::Edge(Edges.Last());
01087     tol = BRep_Tool::Tolerance(edge);
01088     TopoDS_Vertex VL = sae.LastVertex(edge);
01089     gp_Pnt PL = BRep_Tool::Pnt(VL);
01090     if (PL.Distance(PLocs.Last()) > tol) {
01091       if (aCI) delete aCI;
01092       Standard_ConstructionError::Raise
01093         ("Last location shapes is not coincided with last vertex of aWirePath");
01094     }
01095     VLocs.ChangeValue(nbLocs) = VL;
01096     int jcurr = 2;
01097     TopTools_SequenceOfShape tmpEdges;
01098     for (i=1; i<=Edges.Length() && jcurr<nbLocs; i++) {
01099       TopoDS_Edge E = TopoDS::Edge(Edges.Value(i));
01100       tol = BRep_Tool::Tolerance(E);
01101       TopoDS_Vertex V1 = sae.FirstVertex(E);
01102       TopoDS_Vertex V2 = sae.LastVertex(E);
01103       gp_Pnt P1 = BRep_Tool::Pnt(V1);
01104       gp_Pnt P2 = BRep_Tool::Pnt(V2);
01105       if (P2.Distance(PLocs.Value(jcurr)) < tol) {
01106         // make wire from current edge and add created
01107         // wire to Wires
01108         TopoDS_Wire W;
01109         B.MakeWire(W);
01110         for (j=1; j<=tmpEdges.Length(); j++)
01111           B.Add(W,tmpEdges.Value(j));
01112         B.Add(W,E);
01113         Wires.Append(W);
01114         VLocs.ChangeValue(jcurr) = V2;
01115         jcurr++;
01116         tmpEdges.Clear();
01117       }
01118       else {
01119         // find distance between E and aLocs(jcurr)
01120         double fp,lp;
01121         Handle(Geom_Curve) C = BRep_Tool::Curve(E,fp,lp);
01122         GeomAPI_ProjectPointOnCurve PPCurve (PLocs.Value(jcurr),C);
01123         if (PPCurve.NbPoints()>0 &&
01124             PLocs.Value(jcurr).Distance(PPCurve.Point(1)) < tol) {
01125           double param = PPCurve.Parameter(1);
01126           gp_Pnt PC1;
01127           C->D0(param,PC1);
01128           // split current edge
01129           Handle(Geom_TrimmedCurve) tc1 = new Geom_TrimmedCurve(C,fp,param);
01130           Handle(Geom_TrimmedCurve) tc2 = new Geom_TrimmedCurve(C,param,lp);
01131           TopoDS_Edge E1,E2;
01132           gp_Pnt Pfp;
01133           C->D0(fp,Pfp);
01134           if (Pfp.Distance(P1)<tol) {
01135             B.MakeEdge(E1,tc1,tol);
01136             B.Add(E1,V1);
01137             TopoDS_Shape tmpV = VLocs.Value(jcurr).Oriented(TopAbs_REVERSED);
01138             B.Add(E1,TopoDS::Vertex(tmpV));
01139             tmpEdges.Append(E1);
01140             B.MakeEdge(E2,tc2,tol);
01141             tmpV = VLocs.Value(jcurr).Oriented(TopAbs_FORWARD);
01142             B.Add(E2,TopoDS::Vertex(tmpV));
01143             B.Add(E2,V2);
01144           }
01145           else {
01146             B.MakeEdge(E1,tc2,tol);
01147             TopoDS_Shape tmpV = VLocs.Value(jcurr).Oriented(TopAbs_FORWARD);
01148             B.Add(E1,TopoDS::Vertex(tmpV));
01149             B.Add(E1,V1);
01150             E1.Reverse();
01151             tmpEdges.Append(E1);
01152             B.MakeEdge(E2,tc1,tol);
01153             B.Add(E2,V2);
01154             tmpV = VLocs.Value(jcurr).Oriented(TopAbs_REVERSED);
01155             B.Add(E2,TopoDS::Vertex(tmpV));
01156             E2.Reverse();
01157           }
01158           // create wire from tmpEdges
01159           TopoDS_Wire W;
01160           B.MakeWire(W);
01161           for (j=1; j<=tmpEdges.Length(); j++)
01162             B.Add(W,tmpEdges.Value(j));
01163           Wires.Append(W);
01164           jcurr++;
01165           tmpEdges.Clear();
01166           Edges.Remove(i);
01167           Edges.InsertAfter(i-1,E1);
01168           Edges.InsertAfter(i,E2);
01169         }
01170         else {
01171           tmpEdges.Append(E);
01172         }
01173       }
01174     }
01175     // create wire from other edges
01176     TopoDS_Wire W;
01177     B.MakeWire(W);
01178     for (; i<=Edges.Length(); i++)
01179       B.Add(W,Edges.Value(i));
01180     Wires.Append(W);
01181     //cout<<"Wires.Length()="<<Wires.Length()<<endl;
01182   }
01183 
01184   if (Wires.Length() != nbLocs-1) {
01185     if (aCI) delete aCI;
01186     Standard_ConstructionError::Raise
01187       ("One of location shapes is not lied on the path");
01188   }
01189 
01190   //TopTools_SequenceOfShape aSeqBases;
01191   //TopTools_SequenceOfShape aSeqSubBases;
01192   //TopTools_SequenceOfShape aSeqFaces;
01193   TopoDS_Compound aComp;
01194   B.MakeCompound(aComp);
01195   for (i = 1; i < nbBases; i++) {
01196     TopoDS_Wire WPath = TopoDS::Wire(Wires.Value(i));
01197     // 1 section
01198     Handle(Standard_Transient) anItem1 = aBasesObjs->Value(i);
01199     if (anItem1.IsNull())
01200       continue;
01201     Handle(GEOM_Function) aRefBase1 = Handle(GEOM_Function)::DownCast(anItem1);
01202     if (aRefBase1.IsNull())
01203       continue;
01204     TopoDS_Shape aShBase1 = aRefBase1->GetValue();
01205     if (aShBase1.IsNull())
01206       continue;
01207     TopAbs_ShapeEnum aType1 = aShBase1.ShapeType();
01208     // 2 section
01209     Handle(Standard_Transient) anItem2 = aBasesObjs->Value(i+1);
01210     if (anItem2.IsNull())
01211       continue;
01212     Handle(GEOM_Function) aRefBase2 = Handle(GEOM_Function)::DownCast(anItem2);
01213     if (aRefBase2.IsNull())
01214       continue;
01215     TopoDS_Shape aShBase2 = aRefBase2->GetValue();
01216     if (aShBase2.IsNull())
01217       continue;
01218     TopAbs_ShapeEnum aType2 = aShBase2.ShapeType();
01219 
01220     //BRepTools::Write(aShBase1,"/dn02/users_Linux/skl/work/Bugs/14857/base1.brep");
01221 
01222     bool OkSec = (aType1==TopAbs_SHELL || aType1==TopAbs_FACE) &&
01223                  (aType2==TopAbs_SHELL || aType2==TopAbs_FACE);
01224     if (!OkSec) {
01225       if (aCI) delete aCI;
01226       Standard_ConstructionError::Raise("One of section shapes has invalid type");
01227     }
01228 
01229     bool CreateFewSolids = false;
01230     // compare sections
01231     TopExp_Explorer anExp;
01232     Standard_Integer nbf1 = 0;
01233     for (anExp.Init(aShBase1, TopAbs_FACE); anExp.More(); anExp.Next()) {
01234       nbf1++;
01235     }
01236     Standard_Integer nbf2 = 0;
01237     for (anExp.Init(aShBase2, TopAbs_FACE); anExp.More(); anExp.Next()) {
01238       nbf2++;
01239     }
01240     if (nbf1==nbf2) {
01241       CreateFewSolids = true;
01242     }
01243 
01244     /*
01245     // check orientation of sections
01246     bool NeedReverse = false;
01247     {
01248       // first section
01249       anExp.Init(aShBase1, TopAbs_FACE);
01250       TopoDS_Shape aFace = anExp.Current();
01251       TColgp_SequenceOfPnt aPnts;
01252       double xc=0, yc=0, zc=0;
01253       for (anExp.Init(aFace, TopAbs_VERTEX); anExp.More(); anExp.Next()) {
01254         TopoDS_Vertex V = TopoDS::Vertex(anExp.Current());
01255         aPnts.Append(BRep_Tool::Pnt(V));
01256         xc += aPnts.Last().X();
01257         yc += aPnts.Last().Y();
01258         zc += aPnts.Last().Z();
01259       }
01260       gp_Pnt PC(xc/aPnts.Length(), yc/aPnts.Length(), zc/aPnts.Length());
01261       gp_Vec V1(PC,aPnts.Value(1));
01262       gp_Vec V2(PC,aPnts.Value(2));
01263       gp_Vec VN = V1.Crossed(V2);
01264       for (int ip=2; ip<aPnts.Length(); ip++) {
01265         V1 = gp_Vec(PC,aPnts.Value(ip));
01266         V2 = gp_Vec(PC,aPnts.Value(ip+1));
01267         VN.Add(V1.Crossed(V2));
01268       }
01269       gp_Vec PathNorm;
01270       gp_Pnt PLoc = BRep_Tool::Pnt(TopoDS::Vertex(VLocs(i)));
01271       TopExp_Explorer WE;
01272       for (WE.Init(WPath, TopAbs_EDGE); WE.More(); WE.Next()) {
01273         TopoDS_Edge edge = TopoDS::Edge(WE.Current());
01274         double tol = BRep_Tool::Tolerance(edge);
01275         TopoDS_Vertex VF = sae.FirstVertex(edge);
01276         gp_Pnt PF = BRep_Tool::Pnt(VF);
01277         if (PF.Distance(PLoc) < tol) {
01278           double fp,lp;
01279           Handle(Geom_Curve) C = BRep_Tool::Curve(edge,fp,lp);
01280           gp_Pnt P1,P2;
01281           C->D0(fp,P1);
01282           if (P1.Distance(PLoc) < tol) {
01283             C->D0(fp+(lp-fp)/100,P2);
01284           }
01285           else {
01286             C->D0(lp,P1);
01287             C->D0(lp+(fp-lp)/100,P2);
01288           }
01289           PathNorm = gp_Vec(P1,P2);
01290           break;
01291         }
01292         else {
01293           TopoDS_Vertex VL = sae.LastVertex(edge);
01294           gp_Pnt PL = BRep_Tool::Pnt(VL);
01295           if (PL.Distance(PLoc) < tol) {
01296             double fp,lp;
01297             Handle(Geom_Curve) C = BRep_Tool::Curve(edge,fp,lp);
01298             gp_Pnt P1,P2;
01299             C->D0(fp,P1);
01300             if (P1.Distance(PLoc) < tol) {
01301               C->D0(fp+(lp-fp)/100,P2);
01302             }
01303             else {
01304               C->D0(lp,P1);
01305               C->D0(lp+(fp-lp)/100,P2);
01306             }
01307             PathNorm = gp_Vec(P2,P1);
01308             break;
01309           }
01310         }
01311       }
01312       cout<<"VN("<<VN.X()<<","<<VN.Y()<<","<<VN.Z()<<")"<<endl;
01313       cout<<"PathNorm("<<PathNorm.X()<<","<<PathNorm.Y()<<","<<PathNorm.Z()<<")"<<endl;
01314       if (fabs(VN.Angle(PathNorm))>PI/2.) {
01315         NeedReverse = true;
01316         aShBase1.Reverse();
01317       }
01318     }
01319     {
01320       // second section
01321       anExp.Init(aShBase2, TopAbs_FACE);
01322       TopoDS_Shape aFace = anExp.Current();
01323       TColgp_SequenceOfPnt aPnts;
01324       double xc=0, yc=0, zc=0;
01325       for (anExp.Init(aFace, TopAbs_VERTEX); anExp.More(); anExp.Next()) {
01326         TopoDS_Vertex V = TopoDS::Vertex(anExp.Current());
01327         aPnts.Append(BRep_Tool::Pnt(V));
01328         xc += aPnts.Last().X();
01329         yc += aPnts.Last().Y();
01330         zc += aPnts.Last().Z();
01331       }
01332       gp_Pnt PC(xc/aPnts.Length(), yc/aPnts.Length(), zc/aPnts.Length());
01333       gp_Vec V1(PC,aPnts.Value(1));
01334       gp_Vec V2(PC,aPnts.Value(2));
01335       gp_Vec VN = V1.Crossed(V2);
01336       for (int ip=2; ip<aPnts.Length(); ip++) {
01337         V1 = gp_Vec(PC,aPnts.Value(ip));
01338         V2 = gp_Vec(PC,aPnts.Value(ip+1));
01339         VN.Add(V1.Crossed(V2));
01340       }
01341       gp_Vec PathNorm;
01342       gp_Pnt PLoc = BRep_Tool::Pnt(TopoDS::Vertex(VLocs(i+1)));
01343       TopExp_Explorer WE;
01344       for (WE.Init(WPath, TopAbs_EDGE); WE.More(); WE.Next()) {
01345         TopoDS_Edge edge = TopoDS::Edge(WE.Current());
01346         double tol = BRep_Tool::Tolerance(edge);
01347         TopoDS_Vertex VF = sae.FirstVertex(edge);
01348         gp_Pnt PF = BRep_Tool::Pnt(VF);
01349         if (PF.Distance(PLoc) < tol) {
01350           double fp,lp;
01351           Handle(Geom_Curve) C = BRep_Tool::Curve(edge,fp,lp);
01352           gp_Pnt P1,P2;
01353           C->D0(fp,P1);
01354           if (P1.Distance(PLoc) < tol) {
01355             C->D0(fp+(lp-fp)/100,P2);
01356           }
01357           else {
01358             C->D0(lp,P1);
01359             C->D0(lp+(fp-lp)/100,P2);
01360           }
01361           PathNorm = gp_Vec(P2,P1);
01362           break;
01363         }
01364         else {
01365           TopoDS_Vertex VL = sae.LastVertex(edge);
01366           gp_Pnt PL = BRep_Tool::Pnt(VL);
01367           if (PL.Distance(PLoc) < tol) {
01368             double fp,lp;
01369             Handle(Geom_Curve) C = BRep_Tool::Curve(edge,fp,lp);
01370             gp_Pnt P1,P2;
01371             C->D0(fp,P1);
01372             if (P1.Distance(PLoc) < tol) {
01373               C->D0(fp+(lp-fp)/100,P2);
01374             }
01375             else {
01376               C->D0(lp,P1);
01377               C->D0(lp+(fp-lp)/100,P2);
01378             }
01379             PathNorm = gp_Vec(P2,P1);
01380             break;
01381           }
01382         }
01383       }
01384       //cout<<"VN("<<VN.X()<<","<<VN.Y()<<","<<VN.Z()<<")"<<endl;
01385       //cout<<"PathNorm("<<PathNorm.X()<<","<<PathNorm.Y()<<","<<PathNorm.Z()<<")"<<endl;
01386       if (fabs(VN.Angle(PathNorm))>PI/2.)
01387         aShBase2.Reverse();
01388     }
01389     */
01390 
01391     if (!CreateFewSolids) {
01392       // we can create only one solid
01393       TopoDS_Shape aWire1, aWire2;
01394       // prepare aWire1
01395       if (aType1==TopAbs_SHELL) {
01396         // create wire as boundary contour if shell is no closed
01397         // get free boundary shapes
01398         ShapeAnalysis_FreeBounds anAnalizer(aShBase1);
01399         TopoDS_Compound aClosed = anAnalizer.GetClosedWires();
01400         //TopExp_Explorer anExp;
01401         Standard_Integer NbWires = 0;
01402         for (anExp.Init(aClosed, TopAbs_WIRE); anExp.More(); anExp.Next()) {
01403           NbWires++;
01404           aWire1 = anExp.Current();
01405         }
01406         if (NbWires!=1) {
01407           // bad case
01408           if (aCI) delete aCI;
01409           Standard_ConstructionError::Raise("Bad shell is used as section ");
01410         }
01411       }
01412       else { // aType1==TopAbs_FACE
01413         TopExp_Explorer aExpW(aShBase1,TopAbs_WIRE);
01414         aWire1 = aExpW.Current();
01415       }
01416       // prepare aWire2
01417       if (aType2==TopAbs_SHELL) {
01418         // create wire as boundary contour if shell is no closed
01419         // get free boundary shapes
01420         ShapeAnalysis_FreeBounds anAnalizer(aShBase2);
01421         TopoDS_Compound aClosed = anAnalizer.GetClosedWires();
01422         //TopExp_Explorer anExp;
01423         Standard_Integer NbWires = 0;
01424         for (anExp.Init(aClosed, TopAbs_WIRE); anExp.More(); anExp.Next()) {
01425           NbWires++;
01426           aWire2 = anExp.Current();
01427         }
01428         if (NbWires!=1) {
01429           // bad case
01430           if (aCI) delete aCI;
01431           Standard_ConstructionError::Raise("Bad shell is used as section ");
01432         }
01433       }
01434       else { // aType2==TopAbs_FACE
01435         TopExp_Explorer aExpW(aShBase2,TopAbs_WIRE);
01436         aWire2 = aExpW.Current();
01437       }
01438       // make pipe using aWire1 and aWire2
01439       if (!aWire1.IsNull() && !aWire2.IsNull()) {
01440         //BRepOffsetAPI_MakePipeShell aBuilder(aWirePath);
01441         BRepOffsetAPI_MakePipeShell aBuilder(WPath);
01442         aBuilder.Add(aWire1, TopoDS::Vertex(VLocs(i)),
01443                      aWithContact, aWithCorrect);
01444         aBuilder.Add(aWire2, TopoDS::Vertex(VLocs(i+1)),
01445                      aWithContact, aWithCorrect);
01446         if (!aBuilder.IsReady()) {
01447           if (aCI) delete aCI;
01448           Standard_ConstructionError::Raise("Invalid input data for building PIPE: bases are invalid");
01449         }
01450         aBuilder.Build();
01451         TopoDS_Shape aShape = aBuilder.Shape();
01452         TopoDS_Shell aShell;
01453         B.MakeShell(aShell);
01454         for (anExp.Init(aShape, TopAbs_FACE); anExp.More(); anExp.Next()) {
01455           B.Add(aShell,anExp.Current());
01456         }
01457         for (anExp.Init(aShBase1, TopAbs_FACE); anExp.More(); anExp.Next()) {
01458           B.Add(aShell,anExp.Current());
01459         }
01460         for (anExp.Init(aShBase2, TopAbs_FACE); anExp.More(); anExp.Next()) {
01461           B.Add(aShell,anExp.Current());
01462         }
01463         // make sewing for this shell
01464         Handle(BRepBuilderAPI_Sewing) aSewing = new BRepBuilderAPI_Sewing;
01465         aSewing->SetTolerance(Precision::Confusion());
01466         aSewing->SetFaceMode(Standard_True);
01467         aSewing->SetFloatingEdgesMode(Standard_False);
01468         aSewing->SetNonManifoldMode(Standard_False);
01469         for (anExp.Init(aShell, TopAbs_FACE); anExp.More(); anExp.Next()) {
01470           aSewing->Add(anExp.Current());
01471         }
01472         aSewing->Perform();
01473         const TopoDS_Shape aSewShape = aSewing->SewedShape();
01474         if (aSewShape.ShapeType() == TopAbs_SHELL) {
01475           aShell = TopoDS::Shell(aSewShape);
01476           GProp_GProps aSystem;
01477           BRepGProp::VolumeProperties(aShell, aSystem);
01478           if (aSystem.Mass()<0) {
01479             aShell.Reverse();
01480           }
01481           if (BRep_Tool::IsClosed(aShell)) {
01482             TopoDS_Solid aSolid;
01483             B.MakeSolid(aSolid);
01484             B.Add(aSolid,aShell);
01485             B.Add(aComp,aSolid);
01486           }
01487           else {
01488             B.Add(aComp,aShell);
01489           }
01490         }
01491         else {
01492           B.Add(aComp,aShell);
01493         }
01494       }
01495     }
01496     else {
01497       // main block - creation few solids (for each pair of faces)
01498       TopTools_MapOfShape aFaces1,aFaces2;
01499       for (anExp.Init(aShBase1, TopAbs_FACE); anExp.More(); anExp.Next()) {
01500         aFaces1.Add(anExp.Current());
01501       }
01502       for (anExp.Init(aShBase2, TopAbs_FACE); anExp.More(); anExp.Next()) {
01503         aFaces2.Add(anExp.Current());
01504       }
01505       // creating map of edge faces
01506       TopTools_IndexedDataMapOfShapeListOfShape aMapEdgeFaces1;
01507       TopExp::MapShapesAndAncestors(aShBase1, TopAbs_EDGE, TopAbs_FACE, aMapEdgeFaces1);
01508       TopTools_IndexedDataMapOfShapeListOfShape aMapEdgeFaces2;
01509       TopExp::MapShapesAndAncestors(aShBase2, TopAbs_EDGE, TopAbs_FACE, aMapEdgeFaces2);
01510 
01511       // constuct map face->face
01512       TopTools_IndexedDataMapOfShapeShape FF;
01513       TopoDS_Shape FS1,FS2;
01514       if (nbSubBases==0) {
01515         // find edge the most distant from location point
01516         // (this edge is not shared by two faces)
01517         double maxdist = 0.;
01518         TopoDS_Shape E1;
01519         TopoDS_Vertex V11,V21;
01520         for (j=1; j<=aMapEdgeFaces1.Extent(); j++) {
01521           TopoDS_Shape tmp = aMapEdgeFaces1.FindKey(j);
01522           const TopTools_ListOfShape& aList = aMapEdgeFaces1.FindFromKey(tmp);
01523           if (aList.Extent()>1)
01524             continue;
01525           TopExp_Explorer expv;
01526           expv.Init(tmp, TopAbs_VERTEX);
01527           TopoDS_Vertex V1 = TopoDS::Vertex(expv.Current());
01528           expv.Next();
01529           TopoDS_Vertex V2 = TopoDS::Vertex(expv.Current());
01530           gp_Pnt P1 = BRep_Tool::Pnt(V1);
01531           gp_Pnt P2 = BRep_Tool::Pnt(V2);
01532           double dist = PLocs.Value(i).Distance(P1) + PLocs.Value(i).Distance(P2);
01533           if (dist>maxdist) {
01534             E1 = tmp;
01535             V11 = V1;
01536             V21 = V2;
01537             TopTools_ListIteratorOfListOfShape anIter(aList);
01538             FS1 = anIter.Value();
01539             maxdist = dist;
01540           }
01541         }
01542         // main direction for comparing
01543         gp_Vec VM(PLocs.Value(i),PLocs.Value(i+1));
01544         // find corresponding edge from next section
01545         double minang = M_PI;
01546         gp_Pnt P11 = BRep_Tool::Pnt(V11);
01547         gp_Pnt P21 = BRep_Tool::Pnt(V21);
01548         TopoDS_Shape E2;
01549         TopoDS_Vertex V12,V22;
01550         for (j=1; j<=aMapEdgeFaces2.Extent(); j++) {
01551           TopoDS_Shape tmp = aMapEdgeFaces2.FindKey(j);
01552           const TopTools_ListOfShape& aList = aMapEdgeFaces2.FindFromKey(tmp);
01553           if (aList.Extent()>1)
01554             continue;
01555           TopExp_Explorer expv;
01556           expv.Init(tmp, TopAbs_VERTEX);
01557           TopoDS_Vertex V1tmp = TopoDS::Vertex(expv.Current());
01558           expv.Next();
01559           TopoDS_Vertex V2tmp = TopoDS::Vertex(expv.Current());
01560           gp_Pnt P1tmp = BRep_Tool::Pnt(V1tmp);
01561           gp_Pnt P2tmp = BRep_Tool::Pnt(V2tmp);
01562           double d1 = P1tmp.Distance(P11) + P2tmp.Distance(P21);
01563           double d2 = P1tmp.Distance(P21) + P2tmp.Distance(P11);
01564           TopoDS_Vertex V1,V2;
01565           gp_Pnt P1,P2;
01566           if (d1>d2) {
01567             V1 = V2tmp; P1 = P2tmp;
01568             V2 = V1tmp; P2 = P1tmp;
01569           }
01570           else {
01571             V1 = V1tmp; P1 = P1tmp;
01572             V2 = V2tmp; P2 = P2tmp;
01573           }
01574           gp_Vec Vec1(P11,P1);
01575           gp_Vec Vec2(P21,P2);
01576           double ang = fabs(Vec1.Angle(VM)) + fabs(Vec2.Angle(VM));
01577           if (ang<minang) {
01578             E2 = tmp;
01579             V12 = V1;
01580             V22 = V2;
01581             TopTools_ListIteratorOfListOfShape anIter(aList);
01582             FS2 = anIter.Value();
01583             minang = ang;
01584           }
01585         }
01586         // put all pairs to map FF
01587         FF.Add(FS1,FS2);
01588         FF.Add(E1,E2);
01589         FF.Add(V11,V12);
01590         FF.Add(V21,V22);
01591 
01592         // add pairs of edges to FF
01593         bool stat =  FillForOtherEdges(FS1,E1,V11,FF);
01594         if (!stat) {
01595           if (aCI) delete aCI;
01596           Standard_ConstructionError::Raise("FindForOtherEdges: Can not mapping other egdes");
01597         }
01598 
01599       }
01600       else {
01601         { // 1 section
01602           Handle(Standard_Transient) anItem = aSubBasesObjs->Value(i);
01603           if (anItem.IsNull()) {
01604             if (aCI) delete aCI;
01605             Standard_ConstructionError::Raise("Invalid subbase shape");
01606           }
01607           Handle(GEOM_Function) aRefBase = Handle(GEOM_Function)::DownCast(anItem);
01608           if (aRefBase.IsNull()) {
01609             if (aCI) delete aCI;
01610             Standard_ConstructionError::Raise("Invalid subbase shape");
01611           }
01612           TopoDS_Shape aSh = aRefBase->GetValue();
01613           if (aSh.IsNull()) {
01614             if (aCI) delete aCI;
01615             Standard_ConstructionError::Raise("Invalid subbase shape");
01616           }
01617           if (aSh.ShapeType()!=TopAbs_FACE) {
01618             if (aCI) delete aCI;
01619             Standard_ConstructionError::Raise("Invalid subbase shape");
01620           }
01621           FS1 = aSh;
01622         }
01623         { // 2 section
01624           Handle(Standard_Transient) anItem = aSubBasesObjs->Value(i+1);
01625           if (anItem.IsNull()) {
01626             if (aCI) delete aCI;
01627             Standard_ConstructionError::Raise("Invalid subbase shape");
01628           }
01629           Handle(GEOM_Function) aRefBase = Handle(GEOM_Function)::DownCast(anItem);
01630           if (aRefBase.IsNull()) {
01631             if (aCI) delete aCI;
01632             Standard_ConstructionError::Raise("Invalid subbase shape");
01633           }
01634           TopoDS_Shape aSh = aRefBase->GetValue();
01635           if (aSh.IsNull()) {
01636             if (aCI) delete aCI;
01637             Standard_ConstructionError::Raise("Invalid subbase shape");
01638           }
01639           if (aSh.ShapeType()!=TopAbs_FACE) {
01640             if (aCI) delete aCI;
01641             Standard_ConstructionError::Raise("Invalid subbase shape");
01642           }
01643           FS2 = aSh;
01644         }
01645 
01646         if (!aFaces1.Contains(FS1) || !aFaces2.Contains(FS2)) {
01647           if (aCI) delete aCI;
01648           Standard_ConstructionError::Raise("Invalid subbase shape");
01649         }
01650 
01651         FF.Add(FS1,FS2);
01652 
01653         // add pairs of edges to FF
01654         bool stat =  FillCorrespondingEdges(FS1, FS2, TopoDS::Vertex(VLocs(i)),
01655                                             TopoDS::Vertex(VLocs(i+1)), WPath, FF);
01656         if (!stat) {
01657           if (aCI) delete aCI;
01658           Standard_ConstructionError::Raise("Can not create correct pipe");
01659         }
01660       }
01661 
01662       FindNextPairOfFaces(FS1, aMapEdgeFaces1, aMapEdgeFaces2, FF, aCI);
01663 
01664       // make pipe for each pair of faces
01665       for (j=1; j<=FF.Extent(); j++) {
01666         TopoDS_Shape F1 = FF.FindKey(j);
01667         if (F1.ShapeType() != TopAbs_FACE)
01668           continue;
01669         TopoDS_Shape F2 = FF.FindFromIndex(j);
01670         TopExp_Explorer aExpW1(F1,TopAbs_WIRE);
01671         TopoDS_Wire aWire1 = TopoDS::Wire(aExpW1.Current());
01672         TopExp_Explorer aExpW2(F2,TopAbs_WIRE);
01673         TopoDS_Wire aWire2 = TopoDS::Wire(aExpW2.Current());
01674         // make pipe using aWire1 and aWire2
01675         if (!aWire1.IsNull() && !aWire2.IsNull()) {
01676           BRepOffsetAPI_MakePipeShell aBuilder(WPath);
01677           aBuilder.Add(aWire1, TopoDS::Vertex(VLocs(i)),
01678                        aWithContact, aWithCorrect);
01679           aBuilder.Add(aWire2, TopoDS::Vertex(VLocs(i+1)),
01680                        aWithContact, aWithCorrect);
01681           if (!aBuilder.IsReady()) {
01682             if (aCI) delete aCI;
01683             Standard_ConstructionError::Raise("Invalid input data for building PIPE: bases are invalid");
01684           }
01685           aBuilder.Build();
01686           TopoDS_Shape aShape = aBuilder.Shape();
01687           TopoDS_Shell aShell;
01688           B.MakeShell(aShell);
01689           for (anExp.Init(aShape, TopAbs_FACE); anExp.More(); anExp.Next()) {
01690             B.Add(aShell,anExp.Current());
01691           }
01692 
01693           B.Add(aShell,F1);
01694           B.Add(aShell,F2);
01695           // make sewing for this shell
01696           Handle(BRepBuilderAPI_Sewing) aSewing = new BRepBuilderAPI_Sewing;
01697           aSewing->SetTolerance(Precision::Confusion());
01698           aSewing->SetFaceMode(Standard_True);
01699           aSewing->SetFloatingEdgesMode(Standard_False);
01700           aSewing->SetNonManifoldMode(Standard_False);
01701           for (anExp.Init(aShell, TopAbs_FACE); anExp.More(); anExp.Next()) {
01702             aSewing->Add(anExp.Current());
01703           }
01704           aSewing->Perform();
01705           const TopoDS_Shape aSewShape = aSewing->SewedShape();
01706           if (aSewShape.ShapeType() == TopAbs_SHELL) {
01707             aShell = TopoDS::Shell(aSewShape);
01708             GProp_GProps aSystem;
01709             BRepGProp::VolumeProperties(aShell, aSystem);
01710             if (aSystem.Mass()<0) {
01711               //cout<<"aSewShape is reversed"<<endl;
01712               aShell.Reverse();
01713             }
01714             if (BRep_Tool::IsClosed(aShell)) {
01715               TopoDS_Solid aSolid;
01716               B.MakeSolid(aSolid);
01717               B.Add(aSolid,aShell);
01718               B.Add(aComp,aSolid);
01719             }
01720             else {
01721               B.Add(aComp,aShell);
01722             }
01723           }
01724           else {
01725             B.Add(aComp,aShell);
01726           }
01727         }
01728       }
01729 
01730     }
01731   }
01732 
01733   //BRepTools::Write(aComp,"/dn02/users_Linux/skl/work/Bugs/14857/comp.brep");
01734   return aComp;
01735 }
01736 
01737 //=======================================================================
01738 //function : CreatePipeShellsWithoutPath
01739 //purpose  : auxilary for Execute()
01740 //=======================================================================
01741 static TopoDS_Shape CreatePipeShellsWithoutPath(GEOMImpl_IPipe* aCI)
01742 {
01743   //cout<<"CreatePipeShellsWithoutPath"<<endl;
01744   int i,j;
01745   BRep_Builder B;
01746 
01747   GEOMImpl_IPipeShellSect* aCIDS = (GEOMImpl_IPipeShellSect*)aCI;
01748   // shell sections
01749   Handle(TColStd_HSequenceOfTransient) aBasesObjs = aCIDS->GetBases();
01750   // vertex for recognition
01751   Handle(TColStd_HSequenceOfTransient) VObjs = aCIDS->GetLocations();
01752 
01753   Standard_Integer nbBases = aBasesObjs->Length(),
01754     nbv = (VObjs.IsNull() ? 0 :VObjs->Length());
01755 
01756   if (nbv != nbBases) {
01757     if (aCI) delete aCI;
01758     Standard_ConstructionError::Raise("Number of shapes for recognition is invalid");
01759   }
01760 
01761   TopTools_SequenceOfShape SecVs,Bases;
01762   for (i=1; i<=nbBases; i++) {
01763     // vertex
01764     Handle(Standard_Transient) anItem = VObjs->Value(i);
01765     if (anItem.IsNull())
01766       continue;
01767     Handle(GEOM_Function) aRef = Handle(GEOM_Function)::DownCast(anItem);
01768     TopoDS_Shape V = aRef->GetValue();
01769     if (V.IsNull() || V.ShapeType() != TopAbs_VERTEX)
01770       continue;
01771     SecVs.Append(V);
01772     // section
01773     anItem = aBasesObjs->Value(i);
01774     if (anItem.IsNull())
01775       continue;
01776     aRef = Handle(GEOM_Function)::DownCast(anItem);
01777     TopoDS_Shape aSh = aRef->GetValue();
01778     if (aSh.IsNull())
01779       continue;
01780     Bases.Append(aSh);
01781   }
01782   nbv = SecVs.Length();
01783   nbBases = Bases.Length();
01784   if (nbv != nbBases) {
01785     if (aCI) delete aCI;
01786     Standard_ConstructionError::Raise("One of shapes for recognition is not a vertex");
01787   }
01788 
01789   TopoDS_Compound aComp;
01790   B.MakeCompound(aComp);
01791 
01792   for (i = 1; i < nbBases; i++) {
01793     MESSAGE ("Make pipe between sections "<<i<<" and "<<i+1);
01794     TopoDS_Shape aShBase1 = Bases.Value(i);
01795     TopoDS_Shape aShBase2 = Bases.Value(i+1);
01796     TopExp_Explorer anExp;
01797     Standard_Integer nbf1 = 0;
01798     for (anExp.Init(aShBase1, TopAbs_FACE); anExp.More(); anExp.Next()) {
01799       nbf1++;
01800     }
01801     Standard_Integer nbf2 = 0;
01802     for (anExp.Init(aShBase2, TopAbs_FACE); anExp.More(); anExp.Next()) {
01803       nbf2++;
01804     }
01805     //cout<<"nbf1="<<nbf1<<" nbf2="<<nbf2<<endl;
01806     if (nbf1!=nbf2) {
01807       if (aCI) delete aCI;
01808       Standard_ConstructionError::Raise("Different number of faces in the sections");
01809     }
01810 
01811     TopTools_MapOfShape aFaces1,aFaces2;
01812     for (anExp.Init(aShBase1, TopAbs_FACE); anExp.More(); anExp.Next()) {
01813       aFaces1.Add(anExp.Current());
01814     }
01815     for (anExp.Init(aShBase2, TopAbs_FACE); anExp.More(); anExp.Next()) {
01816       aFaces2.Add(anExp.Current());
01817     }
01818 
01819     // creating map of edge faces
01820     TopTools_IndexedDataMapOfShapeListOfShape aMapEdgeFaces1;
01821     TopExp::MapShapesAndAncestors(aShBase1, TopAbs_EDGE, TopAbs_FACE, aMapEdgeFaces1);
01822     TopTools_IndexedDataMapOfShapeListOfShape aMapEdgeFaces2;
01823     TopExp::MapShapesAndAncestors(aShBase2, TopAbs_EDGE, TopAbs_FACE, aMapEdgeFaces2);
01824 
01825     // constuct map face->face (and sub-shapes)
01826     TopTools_IndexedDataMapOfShapeShape FF;
01827     //TopoDS_Shape FS1 = SecFs.Value(i), FS2 = SecFs.Value(i+1);
01828     TopoDS_Shape FS1, FS2;
01829     TopoDS_Vertex V1 = TopoDS::Vertex(SecVs(i));
01830     TopoDS_Vertex V2 = TopoDS::Vertex(SecVs(i+1));
01831     FindFirstPairFaces(aShBase1, aShBase2, V1, V2, FS1, FS2);
01832 
01833     FF.Add(FS1,FS2);
01834     MESSAGE ("  first pair of corresponding faces is found");
01835 
01836     // add pairs of edges and vertexes to FF
01837     bool stat =  FillCorrespondingEdges(FS1, FS2, V1, V2, FF);
01838     if (!stat) {
01839       if (aCI) delete aCI;
01840       Standard_ConstructionError::Raise("Can not create correct pipe");
01841     }
01842     MESSAGE ("  correspondences for sub-shapes of first pair of faces is found");
01843 
01844     FindNextPairOfFaces(FS1, aMapEdgeFaces1, aMapEdgeFaces2, FF, aCI);
01845     MESSAGE ("  other correspondences is found, make pipe for all pairs of faces");
01846 
01847     // make pipe for each pair of faces
01848     // auxilary map vertex->edge for created pipe edges
01849     TopTools_IndexedDataMapOfShapeShape VPE;
01850     ShapeAnalysis_Edge sae;
01851     //cout<<"FF.Extent()="<<FF.Extent()<<endl;
01852     int nbff = 0;
01853     for (j=1; j<=FF.Extent(); j++) {
01854       TopoDS_Shape F1 = FF.FindKey(j);
01855       if (F1.ShapeType() != TopAbs_FACE)
01856         continue;
01857       TopoDS_Shape F2 = FF.FindFromIndex(j);
01858       nbff++;
01859 
01860       //if (nbff!=3) continue;
01861 
01862       MESSAGE ("    make pipe for "<<nbff<<" face");
01863 
01864       Handle(Geom_Surface) S1 = BRep_Tool::Surface(TopoDS::Face(F1));
01865       if (S1->IsKind(STANDARD_TYPE(Geom_RectangularTrimmedSurface))) {
01866         Handle(Geom_RectangularTrimmedSurface) RTS =
01867           Handle(Geom_RectangularTrimmedSurface)::DownCast(S1);
01868         S1 = RTS->BasisSurface();
01869       }
01870       Handle(Geom_Plane) Pln1 = Handle(Geom_Plane)::DownCast(S1);
01871       if (Pln1.IsNull()) {
01872         if (aCI) delete aCI;
01873         Standard_ConstructionError::Raise("Surface from face is not plane");
01874       }
01875       gp_Vec aDir1(Pln1->Axis().Direction());
01876 
01877       Handle(Geom_Surface) S2 = BRep_Tool::Surface(TopoDS::Face(F2));
01878       if (S2->IsKind(STANDARD_TYPE(Geom_RectangularTrimmedSurface))) {
01879         Handle(Geom_RectangularTrimmedSurface) RTS =
01880           Handle(Geom_RectangularTrimmedSurface)::DownCast(S2);
01881         S2 = RTS->BasisSurface();
01882       }
01883       Handle(Geom_Plane) Pln2 =
01884           Handle(Geom_Plane)::DownCast(S2);
01885       if (Pln2.IsNull()) {
01886         if (aCI) delete aCI;
01887         Standard_ConstructionError::Raise("Surface from face is not plane");
01888       }
01889       gp_Vec aDir2(Pln2->Axis().Direction());
01890 
01891       gp_Pnt P1 = BRep_Tool::Pnt(TopoDS::Vertex(SecVs(i)));
01892       gp_Pnt P2 = BRep_Tool::Pnt(TopoDS::Vertex(SecVs(i+1)));
01893       gp_Vec aDir(P1,P2);
01894       if (fabs(aDir.Angle(aDir1)) > M_PI/2.)
01895         aDir1.Reverse();
01896       if (fabs(aDir.Angle(aDir2)) > M_PI/2.)
01897         aDir2.Reverse();
01898 
01899       TopExp_Explorer anExpE(F1,TopAbs_EDGE);
01900       TopTools_SequenceOfShape aNewFs;
01901       //int nbee=0;
01902       for (; anExpE.More(); anExpE.Next()) {
01903         TopoDS_Edge E1 = TopoDS::Edge(anExpE.Current());
01904         //nbee++;
01905         if (!FF.Contains(E1))
01906           MESSAGE ("map FF not contains key E1");
01907 
01908         if (VPE.Contains(E1)) {
01909           aNewFs.Append(VPE.FindFromKey(E1));
01910 #ifdef _DEBUG_
01911           MESSAGE ("    using existed face");
01912 #endif
01913           continue;
01914         }
01915 
01916         TopoDS_Edge E3 = TopoDS::Edge(FF.FindFromKey(E1));
01917         TopoDS_Vertex V1 = sae.FirstVertex(E1);
01918         TopoDS_Vertex V2 = sae.LastVertex(E1);
01919         if (!FF.Contains(V1))
01920           MESSAGE ("map FF not contains key V1");
01921         if (!FF.Contains(V2))
01922           MESSAGE ("map FF not contains key V2");
01923         TopoDS_Vertex V3 = TopoDS::Vertex(FF.FindFromKey(V2));
01924         TopoDS_Vertex V4 = TopoDS::Vertex(FF.FindFromKey(V1));
01925         TopoDS_Vertex Vtmp = sae.FirstVertex(E3);
01926         if (Vtmp.IsSame(V4))
01927           E3.Reverse();
01928         gp_Pnt P1 = BRep_Tool::Pnt(V1);
01929         gp_Pnt P2 = BRep_Tool::Pnt(V2);
01930         gp_Pnt P3 = BRep_Tool::Pnt(V3);
01931         gp_Pnt P4 = BRep_Tool::Pnt(V4);
01932         // make E2
01933         TopoDS_Edge E2;
01934         Handle(Geom_BSplineCurve) C2;
01935         if (VPE.Contains(V2)) {
01936           E2 = TopoDS::Edge(VPE.FindFromKey(V2));
01937           double fp,lp;
01938           C2 = Handle(Geom_BSplineCurve)::DownCast(BRep_Tool::Curve(E2,fp,lp));
01939         }
01940         else {
01941           Handle(TColgp_HArray1OfPnt) HAP = new TColgp_HArray1OfPnt(1,2);
01942           HAP->SetValue(1,P2);
01943           HAP->SetValue(2,P3);
01944           GeomAPI_Interpolate anInt(HAP,Standard_False,1.e-7);
01945           anInt.Load(aDir1,aDir2);
01946           anInt.Perform();
01947           C2 = anInt.Curve();
01948           B.MakeEdge(E2,C2,1.e-7);
01949           B.Add(E2,TopoDS::Vertex(V2.Oriented(TopAbs_FORWARD)));
01950           B.Add(E2,TopoDS::Vertex(V3.Oriented(TopAbs_REVERSED)));
01951           VPE.Add(V2,E2);
01952         }
01953         // make E4
01954         TopoDS_Edge E4;
01955         Handle(Geom_BSplineCurve) C4;
01956         if (VPE.Contains(V1)) {
01957           E4 = TopoDS::Edge(VPE.FindFromKey(V1));
01958           double fp,lp;
01959           C4 = Handle(Geom_BSplineCurve)::DownCast(BRep_Tool::Curve(E4,fp,lp));
01960         }
01961         else {
01962           Handle(TColgp_HArray1OfPnt) HAP = new TColgp_HArray1OfPnt(1,2);
01963           HAP->SetValue(1,P1);
01964           HAP->SetValue(2,P4);
01965           GeomAPI_Interpolate anInt(HAP,Standard_False,1.e-7);
01966           anInt.Load(aDir1,aDir2);
01967           anInt.Perform();
01968           C4 = anInt.Curve();
01969           B.MakeEdge(E4,anInt.Curve(),1.e-7);
01970           B.Add(E4,TopoDS::Vertex(V1.Oriented(TopAbs_FORWARD)));
01971           B.Add(E4,TopoDS::Vertex(V4.Oriented(TopAbs_REVERSED)));
01972           VPE.Add(V1,E4);
01973         }
01974 
01975         TopoDS_Wire W;
01976         B.MakeWire(W);
01977         B.Add(W,E1);
01978         B.Add(W,E2);
01979         B.Add(W,E3);
01980         B.Add(W,E4.Reversed());
01981         //cout<<"      wire for edge "<<nbee<<" is created"<<endl;
01982         //BRepTools::Write(W,"/dn02/users_Linux/skl/work/Bugs/14857/w.brep");
01983 
01984         // make surface
01985 
01986         double fp,lp;
01987         Handle(Geom_Curve) C1 = BRep_Tool::Curve(E1,fp,lp);
01988         //bool IsConicC1 = false;
01989         //if (C1->IsKind(STANDARD_TYPE(Geom_Conic))) {
01990         //  IsConicC1 = true;
01991         //  cout<<"C1 - Geom_Conic"<<endl;
01992         //}
01993         if (C1->IsKind(STANDARD_TYPE(Geom_Line)) || C1->IsKind(STANDARD_TYPE(Geom_Conic))) {
01994           C1 = new Geom_TrimmedCurve(C1,fp,lp);
01995         }
01996         //if (IsConicC1) {
01997         //  double tol = BRep_Tool::Tolerance(E1);
01998         //  GeomConvert_ApproxCurve ApxC1(C1,tol,GeomAbs_C1,10,5);
01999         //  C1 = ApxC1.Curve();
02000         //}
02001         Handle(Geom_Curve) C3 = BRep_Tool::Curve(E3,fp,lp);
02002         if (C3->IsKind(STANDARD_TYPE(Geom_Line)) || C3->IsKind(STANDARD_TYPE(Geom_Conic))) {
02003           C3 = new Geom_TrimmedCurve(C3,fp,lp);
02004         }
02005         //filebuf fic;
02006         //ostream os(&fic);
02007         //os.precision(15);
02008         Handle(Geom_BSplineCurve) CE1 =
02009           GeomConvert::CurveToBSplineCurve(C1,Convert_RationalC1);
02010         if (CE1->Degree()<3)
02011           CE1->IncreaseDegree(3);
02012         Handle(Geom_BSplineCurve) CE2 =
02013           GeomConvert::CurveToBSplineCurve(C2,Convert_RationalC1);
02014         if (CE2->Degree()<3)
02015           CE2->IncreaseDegree(3);
02016         Handle(Geom_BSplineCurve) CE3 =
02017           GeomConvert::CurveToBSplineCurve(C3,Convert_RationalC1);
02018         if (CE3->Degree()<3)
02019           CE3->IncreaseDegree(3);
02020         Handle(Geom_BSplineCurve) CE4 =
02021           GeomConvert::CurveToBSplineCurve(C4,Convert_RationalC1);
02022         if (CE4->Degree()<3)
02023           CE4->IncreaseDegree(3);
02024         //cout<<"CE1->Degree()="<<CE1->Degree()<<" CE2->Degree()="<<CE2->Degree()
02025         //    <<" CE3->Degree()="<<CE3->Degree()<<" CE4->Degree()="<<CE4->Degree()<<endl;
02026         //if (fic.open("/dn02/users_Linux/skl/work/Bugs/14857/ce1.brep",ios::out)) {
02027         //  os<<"DrawTrSurf_BSplineCurve"<<endl;
02028         //  GeomTools::Write(CE1,os);
02029         //  fic.close();
02030         //}
02031 
02032         Handle(Geom_Surface) BS;
02033         try {
02034           GeomFill_BSplineCurves GF(CE1,CE2,CE3,CE4,GeomFill_CoonsStyle);
02035           //GeomFill_BSplineCurves GF(CE1,CE2,CE3,CE4,GeomFill_StretchStyle);
02036           BS = GF.Surface();
02037         }
02038         catch(...) {
02039           MESSAGE ("      can not create BSplineSurface - create Bezier");
02040           int NbP=26;
02041           TColgp_Array2OfPnt Points(1,NbP,1,NbP);
02042           double fp1,lp1,fp2,lp2;
02043           Handle(Geom_Curve) C1 = BRep_Tool::Curve(E1,fp1,lp1);
02044           Handle(Geom_Curve) C3 = BRep_Tool::Curve(E3,fp2,lp2);
02045           gp_Pnt P1C1,P2C1;
02046           C1->D0(fp1,P1C1);
02047           C1->D0(lp1,P2C1);
02048           gp_Pnt P1C3,P2C3;
02049           C3->D0(fp2,P1C3);
02050           C3->D0(lp2,P2C3);
02051           int n1,n2;
02052           double fp,lp;
02053           // get points from C1
02054           if (P1.Distance(P1C1)<1.e-6) {
02055             fp = fp1;
02056             lp = lp1;
02057           }
02058           else {
02059             fp = lp1;
02060             lp = fp1;
02061           }
02062           double step = (lp-fp)/(NbP-1);
02063           Points.SetValue(1,1,P1);
02064           double par = fp;
02065           for (n1=2; n1<NbP; n1++) {
02066             gp_Pnt P;
02067             par += step;
02068             C1->D0(par,P);
02069             Points.SetValue(1,n1,P);
02070           }
02071           Points.SetValue(1,NbP,P2);
02072           // get points from C3
02073           if (P4.Distance(P1C3)<1.e-6) {
02074             fp = fp2;
02075             lp = lp2;
02076           }
02077           else {
02078             fp = lp2;
02079             lp = fp2;
02080           }
02081           step = (lp-fp)/(NbP-1);
02082           Points.SetValue(NbP,1,P4);
02083           par = fp;
02084           for (n1=2; n1<NbP; n1++) {
02085             gp_Pnt P;
02086             par += step;
02087             C3->D0(par,P);
02088             Points.SetValue(NbP,n1,P);
02089           }
02090           Points.SetValue(NbP,NbP,P3);
02091           // create isolines and get points from them
02092           for (n1=1; n1<=NbP; n1++) {
02093             gp_Pnt PI1 = Points.Value(1,n1);
02094             gp_Pnt PI2 = Points.Value(NbP,n1);
02095             Handle(TColgp_HArray1OfPnt) HAP = new TColgp_HArray1OfPnt(1,2);
02096             HAP->SetValue(1,PI1);
02097             HAP->SetValue(2,PI2);
02098             GeomAPI_Interpolate anInt(HAP,Standard_False,1.e-7);
02099             anInt.Load(aDir1,aDir2);
02100             anInt.Perform();
02101             Handle(Geom_Curve) iso = anInt.Curve();
02102             fp = iso->FirstParameter();
02103             lp = iso->LastParameter();
02104             step = (lp-fp)/(NbP-1);
02105             par = fp;
02106             TopoDS_Compound VComp;
02107             B.MakeCompound(VComp);
02108             for (n2=2; n2<NbP; n2++) {
02109               gp_Pnt P;
02110               par += step;
02111               iso->D0(par,P);
02112               Points.SetValue(n2,n1,P);
02113             }
02114           }
02115           // create surface and face
02116           //Handle(Geom_BezierSurface) BS = new Geom_BezierSurface(Points);
02117           BS = new Geom_BezierSurface(Points);
02118         }
02119 
02120         BRepBuilderAPI_MakeFace BB(BS,W);
02121         TopoDS_Face NewF = BB.Face();
02122         Handle(ShapeFix_Face) sff = new ShapeFix_Face(NewF);
02123         sff->Perform();
02124         sff->FixOrientation();
02125         TopoDS_Face FixedFace = sff->Face();
02126         aNewFs.Append(FixedFace);
02127         VPE.Add(E1,FixedFace);
02128         //cout<<"      face for edge "<<nbee<<" is created"<<endl;
02129         //BRepTools::Write(FixedFace,"/dn02/users_Linux/skl/work/Bugs/14857/f.brep");
02130       }
02131       // make shell
02132       TopoDS_Shell aShell;
02133       B.MakeShell(aShell);
02134       for (int nf=1; nf<=aNewFs.Length(); nf++) {
02135         B.Add(aShell,aNewFs(nf));
02136       }
02137       B.Add(aShell,F1);
02138       B.Add(aShell,F2);
02139 
02140       // make sewing for this shell
02141       Handle(BRepBuilderAPI_Sewing) aSewing = new BRepBuilderAPI_Sewing;
02142       aSewing->SetTolerance(Precision::Confusion());
02143       aSewing->SetFaceMode(Standard_True);
02144       aSewing->SetFloatingEdgesMode(Standard_False);
02145       aSewing->SetNonManifoldMode(Standard_False);
02146       for (anExp.Init(aShell, TopAbs_FACE); anExp.More(); anExp.Next()) {
02147         aSewing->Add(anExp.Current());
02148       }
02149       aSewing->Perform();
02150       MESSAGE ("    shell for face "<<nbff<<" is created");
02151       const TopoDS_Shape aSewShape = aSewing->SewedShape();
02152       //BRepTools::Write(aSewShape,"/dn02/users_Linux/skl/work/Bugs/14857/sew.brep");
02153       if (aSewShape.ShapeType() == TopAbs_SHELL) {
02154         aShell = TopoDS::Shell(aSewShape);
02155         GProp_GProps aSystem;
02156         BRepGProp::VolumeProperties(aShell, aSystem);
02157         if (aSystem.Mass()<0) {
02158           //cout<<"aSewShape is reversed"<<endl;
02159           aShell.Reverse();
02160         }
02161         if (BRep_Tool::IsClosed(aShell)) {
02162           TopoDS_Solid aSolid;
02163           B.MakeSolid(aSolid);
02164           B.Add(aSolid,aShell);
02165           B.Add(aComp,aSolid);
02166           MESSAGE ("    solid for face "<<nbff<<" is created");
02167         }
02168         else {
02169           B.Add(aComp,aShell);
02170           MESSAGE ("    solid for face "<<nbff<<" is not created");
02171         }
02172       }
02173       else {
02174         B.Add(aComp,aShell);
02175         MESSAGE ("    solid for face "<<nbff<<" is not created");
02176       }
02177       //cout<<"    solid for face "<<nbff<<" is created"<<endl;
02178 
02179       //Handle(ShapeFix_Shell) sfs = new ShapeFix_Shell(aShell);
02180       //sfs->Perform();
02181       //TopoDS_Shell FixedShell = sfs->Shell();
02182       /*
02183       GProp_GProps aSystem;
02184       BRepGProp::VolumeProperties(FixedShell, aSystem);
02185       if (aSystem.Mass()<0) {
02186         //cout<<"aSewShape is reversed"<<endl;
02187         FixedShell.Reverse();
02188       }
02189       if (BRep_Tool::IsClosed(FixedShell)) {
02190         TopoDS_Solid aSolid;
02191         B.MakeSolid(aSolid);
02192         B.Add(aSolid,aShell);
02193         B.Add(aComp,aSolid);
02194       }
02195       else {
02196         B.Add(aComp,FixedShell);
02197       }
02198       */
02199     }
02200   }
02201 
02202   //BRepTools::Write(aComp,"/dn02/users_Linux/skl/work/Bugs/14857/comp.brep");
02203   return aComp;
02204 }
02205 
02206 //=======================================================================
02207 //function : CreatePipeBiNormalAlongVector
02208 //purpose  : auxilary for Execute()
02209 //=======================================================================
02210 static TopoDS_Shape CreatePipeBiNormalAlongVector(const TopoDS_Wire& aWirePath,
02211                                                   GEOMImpl_IPipe* aCI)
02212 {
02213   GEOMImpl_IPipeBiNormal* aCIBN = (GEOMImpl_IPipeBiNormal*)aCI;
02214 
02215   Handle(GEOM_Function) aRefBase = aCIBN->GetBase();
02216   Handle(GEOM_Function) aRefVec = aCIBN->GetVector();
02217   TopoDS_Shape aShapeBase = aRefBase->GetValue();
02218   TopoDS_Shape aShapeVec = aRefVec->GetValue();
02219 
02220   if (aShapeBase.IsNull()) {
02221     if (aCIBN) delete aCIBN;
02222     Standard_NullObject::Raise("MakePipe aborted : null base argument");
02223   }
02224 
02225   TopoDS_Shape aProf;
02226   if (aShapeBase.ShapeType() == TopAbs_VERTEX) {
02227     aProf = aShapeBase;
02228   }
02229   else if (aShapeBase.ShapeType() == TopAbs_EDGE) {
02230     aProf = BRepBuilderAPI_MakeWire(TopoDS::Edge(aShapeBase)).Shape();
02231   }
02232   else if (aShapeBase.ShapeType() == TopAbs_WIRE) {
02233     aProf = aShapeBase;
02234   }
02235   else if (aShapeBase.ShapeType() == TopAbs_FACE) {
02236     TopExp_Explorer wexp(aShapeBase,TopAbs_WIRE);
02237     aProf = wexp.Current();
02238   }
02239   else {
02240     Standard_TypeMismatch::Raise
02241       ("MakePipe aborted : invalid type of base");
02242   }
02243   BRepOffsetAPI_MakePipeShell PipeBuilder(aWirePath);
02244   PipeBuilder.Add(aProf);
02245 
02246   if (aShapeVec.IsNull()) {
02247     if (aCIBN) delete aCIBN;
02248     Standard_NullObject::Raise
02249       ("MakePipe aborted : null vector argument");
02250   }
02251   if (aShapeVec.ShapeType() != TopAbs_EDGE)
02252     Standard_TypeMismatch::Raise
02253       ("MakePipe aborted: invalid type of vector");
02254   TopoDS_Edge anEdge = TopoDS::Edge(aShapeVec);
02255   TopoDS_Vertex V1, V2;
02256   TopExp::Vertices(anEdge, V1, V2, Standard_True);
02257   if (V1.IsNull() || V2.IsNull())
02258     Standard_NullObject::Raise
02259       ("MakePipe aborted: vector is not defined");
02260   gp_Vec aVec(BRep_Tool::Pnt(V1), BRep_Tool::Pnt(V2));
02261   gp_Dir BiNormal(aVec);
02262   PipeBuilder.SetMode(BiNormal);
02263   PipeBuilder.Build();
02264   if (aShapeBase.ShapeType() == TopAbs_FACE) {
02265       PipeBuilder.MakeSolid();
02266   }
02267 
02268   return PipeBuilder.Shape();
02269 }
02270 
02271 //=======================================================================
02272 //function : Execute
02273 //purpose  :
02274 //=======================================================================
02275 Standard_Integer GEOMImpl_PipeDriver::Execute(TFunction_Logbook& log) const
02276 {
02277   //cout<<"PipeDriver::Execute"<<endl;
02278   if (Label().IsNull()) return 0;
02279   Handle(GEOM_Function) aFunction = GEOM_Function::GetFunction(Label());
02280   GEOMImpl_IPipe* aCI= 0;
02281   Standard_Integer aType = aFunction->GetType();
02282   if (aType == PIPE_BASE_PATH)
02283     aCI = new GEOMImpl_IPipe(aFunction);
02284   else if (aType == PIPE_DIFFERENT_SECTIONS)
02285     aCI = new GEOMImpl_IPipeDiffSect(aFunction);
02286   else if (aType == PIPE_SHELL_SECTIONS)
02287     aCI = new GEOMImpl_IPipeShellSect(aFunction);
02288   else if (aType == PIPE_SHELLS_WITHOUT_PATH)
02289     aCI = new GEOMImpl_IPipeShellSect(aFunction);
02290   else if (aType == PIPE_BI_NORMAL_ALONG_VECTOR)
02291     aCI = new GEOMImpl_IPipeBiNormal(aFunction);
02292   else
02293     return 0;
02294 
02295   TopoDS_Wire aWirePath;
02296   if (aType != PIPE_SHELLS_WITHOUT_PATH) {
02297     // working with path
02298     Handle(GEOM_Function) aRefPath = aCI->GetPath();
02299     TopoDS_Shape aShapePath = aRefPath->GetValue();
02300 
02301     if (aShapePath.IsNull()) {
02302       MESSAGE ("Driver : path is null");
02303       if (aCI) delete aCI;
02304       Standard_NullObject::Raise("MakePipe aborted : null path argument");
02305     }
02306 
02307     // Get path contour
02308     bool isOk = false;
02309     if (aShapePath.ShapeType() == TopAbs_COMPOUND) {
02310       TopTools_SequenceOfShape anEdges;
02311       TopExp_Explorer anExp;
02312       BRep_Builder B;
02313       TopoDS_Wire W;
02314       B.MakeWire(W);
02315       for (anExp.Init(aShapePath, TopAbs_EDGE); anExp.More(); anExp.Next()) {
02316         B.Add(W, anExp.Current());
02317         isOk = true;
02318       }
02319       if (isOk)
02320         aWirePath = W;
02321     }
02322     else if (aShapePath.ShapeType() == TopAbs_WIRE) {
02323       aWirePath = TopoDS::Wire(aShapePath);
02324       isOk = true;
02325     }
02326     else {
02327       if (aShapePath.ShapeType() == TopAbs_EDGE) {
02328         TopoDS_Edge anEdge = TopoDS::Edge(aShapePath);
02329         aWirePath = BRepBuilderAPI_MakeWire(anEdge);
02330         isOk = true;
02331       }
02332     }
02333     if (!isOk) {
02334       if (aCI) delete aCI;
02335       Standard_TypeMismatch::Raise("MakePipe aborted : path shape is neither a wire nor an edge");
02336     }
02337   }
02338 
02339   TopoDS_Shape aShape;
02340 
02341   if (aType == PIPE_BASE_PATH) {
02342     Handle(GEOM_Function) aRefBase = aCI->GetBase();
02343     TopoDS_Shape aShapeBase;
02344 
02345     // Make copy to prevent modifying of base object 0020766 : EDF 1320
02346     BRepBuilderAPI_Copy Copy(aRefBase->GetValue());
02347     if (Copy.IsDone())
02348       aShapeBase = Copy.Shape();
02349 
02350     if (aShapeBase.IsNull()) {
02351       if (aCI) delete aCI;
02352       Standard_NullObject::Raise("MakePipe aborted : null base argument");
02353     }
02354 
02355     // Make pipe
02356     if (aShapeBase.ShapeType() == TopAbs_EDGE ||
02357         aShapeBase.ShapeType() == TopAbs_WIRE)
02358     {
02359       TopoDS_Wire Profile;
02360       if (aShapeBase.ShapeType() == TopAbs_WIRE)
02361         Profile = TopoDS::Wire(aShapeBase);
02362       else
02363       {
02364         BRep_Builder BB;
02365         BB.MakeWire(Profile);
02366         BB.Add(Profile, aShapeBase);
02367       }
02368 
02369       BRepOffsetAPI_MakePipeShell Sweep (aWirePath);
02370       BRepBuilderAPI_MakeFace FaceBuilder (aWirePath, Standard_True); //to find the plane of spine
02371       if (FaceBuilder.IsDone())
02372         Sweep.SetMode(FaceBuilder.Face());
02373       Sweep.Add(Profile);
02374       Sweep.Build();
02375       
02376       if (!Sweep.IsDone())
02377       {
02378         if (aCI) delete aCI;
02379         Standard_ConstructionError::Raise("MakePipeShell failed");
02380       }
02381       else
02382         aShape = Sweep.Shape(); //result is good
02383       
02384     }
02385     else
02386       aShape = BRepOffsetAPI_MakePipe(aWirePath, aShapeBase);
02387   }
02388 
02389   //building pipe with different sections
02390   else if (aType == PIPE_DIFFERENT_SECTIONS) {
02391     GEOMImpl_IPipeDiffSect* aCIDS = (GEOMImpl_IPipeDiffSect*)aCI;
02392     Handle(TColStd_HSequenceOfTransient) aBasesObjs = aCIDS->GetBases ();
02393     Handle(TColStd_HSequenceOfTransient) aLocObjs = aCIDS->GetLocations ();
02394     Standard_Boolean aWithContact = (aCIDS->GetWithContactMode());
02395     Standard_Boolean aWithCorrect = (aCIDS->GetWithCorrectionMode());
02396     if (aCI) {
02397       delete aCI;
02398       aCI = 0;
02399     }
02400 
02401     Standard_Integer nbBases = aBasesObjs->Length();
02402     Standard_Integer nbLocs  = (aLocObjs.IsNull() ? 0 : aLocObjs->Length());
02403 
02404     Handle(TopTools_HSequenceOfShape) aHSeqBases = new TopTools_HSequenceOfShape;
02405     Handle(TopTools_HSequenceOfShape) aHSeqLocs  = new TopTools_HSequenceOfShape;
02406     Standard_Integer i;
02407 
02408     for (i = 1; i <= nbBases; i++) {
02409       Handle(Standard_Transient) anItem = aBasesObjs->Value(i);
02410       if (anItem.IsNull())
02411         continue;
02412       Handle(GEOM_Function) aRefBase = Handle(GEOM_Function)::DownCast(anItem);
02413       if (aRefBase.IsNull())
02414         continue;
02415       if (aRefBase->GetValue().IsNull())
02416         continue;
02417 
02418       aHSeqBases->Append(aRefBase->GetValue());
02419     }
02420     for (i = 1; i <= nbLocs; i++) {
02421       Handle(Standard_Transient) anItemLoc = aLocObjs->Value(i);
02422       if (anItemLoc.IsNull())
02423         continue;
02424       Handle(GEOM_Function) aRefLoc = Handle(GEOM_Function)::DownCast(anItemLoc);
02425       TopoDS_Shape aShapeLoc = aRefLoc->GetValue();
02426       if (aShapeLoc.IsNull() || aShapeLoc.ShapeType() != TopAbs_VERTEX)
02427         continue;
02428 
02429       aHSeqLocs->Append(aShapeLoc);
02430     }
02431 
02432     aShape = CreatePipeWithDifferentSections(aWirePath, aHSeqBases, aHSeqLocs, aWithContact, aWithCorrect);
02433   }
02434 
02435   //building pipe with shell sections
02436   else if (aType == PIPE_SHELL_SECTIONS) {
02437     aShape = CreatePipeForShellSections(aWirePath,aCI);
02438   }
02439 
02440   //building pipe shell sections without path
02441   else if (aType == PIPE_SHELLS_WITHOUT_PATH) {
02442     aShape = CreatePipeShellsWithoutPath(aCI);
02443   }
02444 
02445   //building a pipe with constant bi-normal along given vector
02446   else if (aType == PIPE_BI_NORMAL_ALONG_VECTOR) {
02447     aShape = CreatePipeBiNormalAlongVector(aWirePath, aCI);
02448   }
02449 
02450   if (aCI) {
02451     delete aCI;
02452     aCI = 0;
02453   }
02454 
02455   if (aShape.IsNull()) return 0;
02456 
02457   BRepCheck_Analyzer ana (aShape, Standard_False);
02458   if (!ana.IsValid()) {
02459     ShapeFix_ShapeTolerance aSFT;
02460     aSFT.LimitTolerance(aShape,Precision::Confusion(),Precision::Confusion());
02461     Handle(ShapeFix_Shape) aSfs = new ShapeFix_Shape(aShape);
02462     aSfs->SetPrecision(Precision::Confusion());
02463     aSfs->Perform();
02464     aShape = aSfs->Shape();
02465 
02466     ana.Init(aShape, Standard_False);
02467     if (!ana.IsValid())
02468       Standard_ConstructionError::Raise("Algorithm have produced an invalid shape result");
02469   }
02470 
02471   // Glue (for bug 0020207)
02472   TopExp_Explorer anExpV (aShape, TopAbs_VERTEX);
02473   if (anExpV.More()) {
02474     Standard_Real aVertMaxTol = -RealLast();
02475     for (; anExpV.More(); anExpV.Next()) {
02476       TopoDS_Vertex aVertex = TopoDS::Vertex(anExpV.Current());
02477       Standard_Real aTol = BRep_Tool::Tolerance(aVertex);
02478       if (aTol > aVertMaxTol)
02479         aVertMaxTol = aTol;
02480     }
02481     aVertMaxTol += Precision::Confusion();
02482     aShape = GEOMImpl_GlueDriver::GlueFaces(aShape, aVertMaxTol, Standard_True);
02483     //aShape = GEOMImpl_GlueDriver::GlueFaces(aShape, Precision::Confusion(), Standard_True);
02484   }
02485 
02486   TopoDS_Shape aRes = GEOMImpl_IShapesOperations::CompsolidToCompound(aShape);
02487   aFunction->SetValue(aRes);
02488 
02489   log.SetTouched(Label());
02490   return 1;
02491 }
02492 
02493 //=======================================================================
02494 //function :  GEOMImpl_PipeDriver_Type_
02495 //purpose  :
02496 //=======================================================================
02497 Standard_EXPORT Handle_Standard_Type& GEOMImpl_PipeDriver_Type_()
02498 {
02499   static Handle_Standard_Type aType1 = STANDARD_TYPE(TFunction_Driver);
02500   if (aType1.IsNull()) aType1 = STANDARD_TYPE(TFunction_Driver);
02501   static Handle_Standard_Type aType2 = STANDARD_TYPE(MMgt_TShared);
02502   if (aType2.IsNull()) aType2 = STANDARD_TYPE(MMgt_TShared);
02503   static Handle_Standard_Type aType3 = STANDARD_TYPE(Standard_Transient);
02504   if (aType3.IsNull()) aType3 = STANDARD_TYPE(Standard_Transient);
02505 
02506   static Handle_Standard_Transient _Ancestors[]= {aType1,aType2,aType3,NULL};
02507   static Handle_Standard_Type _aType = new Standard_Type("GEOMImpl_PipeDriver",
02508                                                          sizeof(GEOMImpl_PipeDriver),
02509                                                          1,
02510                                                          (Standard_Address)_Ancestors,
02511                                                          (Standard_Address)NULL);
02512 
02513   return _aType;
02514 }
02515 
02516 //=======================================================================
02517 //function : DownCast
02518 //purpose  :
02519 //=======================================================================
02520 const Handle(GEOMImpl_PipeDriver) Handle(GEOMImpl_PipeDriver)::DownCast(const Handle(Standard_Transient)& AnObject)
02521 {
02522   Handle(GEOMImpl_PipeDriver) _anOtherObject;
02523 
02524   if (!AnObject.IsNull()) {
02525      if (AnObject->IsKind(STANDARD_TYPE(GEOMImpl_PipeDriver))) {
02526        _anOtherObject = Handle(GEOMImpl_PipeDriver)((Handle(GEOMImpl_PipeDriver)&)AnObject);
02527      }
02528   }
02529 
02530   return _anOtherObject;
02531 }