// Copyright (C) 2005 OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN, // CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public // License as published by the Free Software Foundation; either // version 2.1 of the License. // // This library is distributed in the hope that it will be useful // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU // Lesser General Public License for more details. // // You should have received a copy of the GNU Lesser General Public // License along with this library; if not, write to the Free Software // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA // // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com // #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "utilities.h" //======================================================================= //function : GetID //purpose : //======================================================================= const Standard_GUID& GEOMImpl_PipeDriver::GetID() { static Standard_GUID aPipeDriver("FF1BBB19-5D14-4df2-980B-3A668264EA16"); return aPipeDriver; } //======================================================================= //function : GEOMImpl_PipeDriver //purpose : //======================================================================= GEOMImpl_PipeDriver::GEOMImpl_PipeDriver() { } //======================================================================= //function : FillForOtherEdges //purpose : auxilary for CreatePipeForShellSections() //======================================================================= static bool FillForOtherEdges(const TopoDS_Shape& F1, const TopoDS_Shape& E1, const TopoDS_Shape& V1, TopTools_IndexedDataMapOfShapeShape& FF) { //cout<<"FillForOtherEdges"<GetBases(); Handle(TColStd_HSequenceOfTransient) aSubBasesObjs = aCIDS->GetSubBases(); Handle(TColStd_HSequenceOfTransient) aLocObjs = aCIDS->GetLocations(); Standard_Boolean aWithContact = (aCIDS->GetWithContactMode()); Standard_Boolean aWithCorrect = (aCIDS->GetWithCorrectionMode()); Standard_Integer nbBases = aBasesObjs->Length(), nbSubBases = (aSubBasesObjs.IsNull() ? 0 :aSubBasesObjs->Length()), nbLocs = (aLocObjs.IsNull() ? 0 :aLocObjs->Length()); if( nbLocs != nbBases) { if(aCI) delete aCI; Standard_ConstructionError::Raise("Number of sections is not equal to number of locations "); } if( nbSubBases && nbSubBases != nbBases) { if(aCI) delete aCI; Standard_ConstructionError::Raise("Number of sections is not equal to number of subsections "); } //BRepOffsetAPI_MakePipeShell aBuilder(aWirePath); TopTools_SequenceOfShape VLocs; for(i=1; i<=nbBases; i++) { Handle(Standard_Transient) anItemLoc = aLocObjs->Value(i); if(anItemLoc.IsNull()) continue; Handle(GEOM_Function) aRefLoc = Handle(GEOM_Function)::DownCast(anItemLoc); TopoDS_Shape aShapeLoc = aRefLoc->GetValue(); if(aShapeLoc.IsNull() || aShapeLoc.ShapeType() != TopAbs_VERTEX) continue; VLocs.Append(aShapeLoc); } nbLocs = VLocs.Length(); if( nbLocs != nbBases) { if(aCI) delete aCI; Standard_ConstructionError::Raise("One of location shapes is not a vertex"); } // split wire path by location points TColgp_SequenceOfPnt PLocs; for(i=1; i<=nbLocs; i++) { TopoDS_Vertex V = TopoDS::Vertex(VLocs.Value(i)); PLocs.Append(BRep_Tool::Pnt(V)); } TopTools_SequenceOfShape Edges; TopTools_SequenceOfShape Wires; ShapeAnalysis_Edge sae; if(nbLocs==2) { TopExp_Explorer anExp; for ( anExp.Init( aWirePath, TopAbs_EDGE ); anExp.More(); anExp.Next() ) { Edges.Append(anExp.Current()); } Standard_Integer Num1 = 0; Standard_Integer Num2 = 0; for(i=1; i<=Edges.Length(); i++) { TopoDS_Edge E = TopoDS::Edge(Edges.Value(i)); double tol = BRep_Tool::Tolerance(E); TopoDS_Vertex V1 = sae.FirstVertex(E); TopoDS_Vertex V2 = sae.LastVertex(E); gp_Pnt P1 = BRep_Tool::Pnt(V1); gp_Pnt P2 = BRep_Tool::Pnt(V2); if( P1.Distance(PLocs.First()) < tol ) { Num1 = i; } if( P2.Distance(PLocs.Last()) < tol ) { Num2 = i; } } if( Num1>0 && Num2>0 ) { TopoDS_Wire W; B.MakeWire(W); for(i=Num1; i<=Num2; i++) { B.Add(W,Edges.Value(i)); } Wires.Append(W); } else { Wires.Append(aWirePath); } } else { TopExp_Explorer anExp; for ( anExp.Init( aWirePath, TopAbs_EDGE ); anExp.More(); anExp.Next() ) { Edges.Append(anExp.Current()); } TopoDS_Edge edge = TopoDS::Edge(Edges.First()); double tol = BRep_Tool::Tolerance(edge); TopoDS_Vertex VF = sae.FirstVertex(edge); gp_Pnt PF = BRep_Tool::Pnt(VF); //cout<<"PF("< tol ) { if(aCI) delete aCI; Standard_ConstructionError::Raise ("First location shapes is not coincided with first vertex of aWirePath"); } VLocs.ChangeValue(1) = VF; edge = TopoDS::Edge(Edges.Last()); tol = BRep_Tool::Tolerance(edge); TopoDS_Vertex VL = sae.LastVertex(edge); gp_Pnt PL = BRep_Tool::Pnt(VL); if( PL.Distance(PLocs.Last()) > tol ) { if(aCI) delete aCI; Standard_ConstructionError::Raise ("Last location shapes is not coincided with last vertex of aWirePath"); } VLocs.ChangeValue(nbLocs) = VL; int jcurr = 2; TopTools_SequenceOfShape tmpEdges; for(i=1; i<=Edges.Length() && jcurr0 && PLocs.Value(jcurr).Distance(PPC.Point(1)) < tol ) { double param = PPC.Parameter(1); gp_Pnt PC1; C->D0(param,PC1); // split current edge Handle(Geom_TrimmedCurve) tc1 = new Geom_TrimmedCurve(C,fp,param); Handle(Geom_TrimmedCurve) tc2 = new Geom_TrimmedCurve(C,param,lp); TopoDS_Edge E1,E2; gp_Pnt Pfp; C->D0(fp,Pfp); if(Pfp.Distance(P1)Value(i); if(anItem1.IsNull()) continue; Handle(GEOM_Function) aRefBase1 = Handle(GEOM_Function)::DownCast(anItem1); if(aRefBase1.IsNull()) continue; TopoDS_Shape aShBase1 = aRefBase1->GetValue(); if(aShBase1.IsNull()) continue; TopAbs_ShapeEnum aType1 = aShBase1.ShapeType(); // 2 section Handle(Standard_Transient) anItem2 = aBasesObjs->Value(i+1); if(anItem2.IsNull()) continue; Handle(GEOM_Function) aRefBase2 = Handle(GEOM_Function)::DownCast(anItem2); if(aRefBase2.IsNull()) continue; TopoDS_Shape aShBase2 = aRefBase2->GetValue(); if(aShBase2.IsNull()) continue; TopAbs_ShapeEnum aType2 = aShBase2.ShapeType(); //BRepTools::Write(aShBase1,"/dn02/users_Linux/skl/work/Bugs/14857/base1.brep"); bool OkSec = ( aType1==TopAbs_SHELL || aType1==TopAbs_FACE ) && ( aType2==TopAbs_SHELL || aType2==TopAbs_FACE ); if( !OkSec ) { if(aCI) delete aCI; Standard_ConstructionError::Raise("One of section shapes has invalid type"); } bool CreateFewSolids = false; // compare sections TopExp_Explorer anExp; Standard_Integer nbf1 = 0; for ( anExp.Init( aShBase1, TopAbs_FACE ); anExp.More(); anExp.Next() ) { nbf1++; } Standard_Integer nbf2 = 0; for ( anExp.Init( aShBase2, TopAbs_FACE ); anExp.More(); anExp.Next() ) { nbf2++; } if(nbf1==nbf2) { CreateFewSolids = true; } /* // check orientation of sections bool NeedReverse = false; { // first section anExp.Init( aShBase1, TopAbs_FACE ); TopoDS_Shape aFace = anExp.Current(); TColgp_SequenceOfPnt aPnts; double xc=0, yc=0, zc=0; for ( anExp.Init( aFace, TopAbs_VERTEX ); anExp.More(); anExp.Next() ) { TopoDS_Vertex V = TopoDS::Vertex(anExp.Current()); aPnts.Append(BRep_Tool::Pnt(V)); xc += aPnts.Last().X(); yc += aPnts.Last().Y(); zc += aPnts.Last().Z(); } gp_Pnt PC( xc/aPnts.Length(), yc/aPnts.Length(), zc/aPnts.Length() ); gp_Vec V1(PC,aPnts.Value(1)); gp_Vec V2(PC,aPnts.Value(2)); gp_Vec VN = V1.Crossed(V2); for(int ip=2; ipD0(fp,P1); if( P1.Distance(PLoc) < tol ) { C->D0(fp+(lp-fp)/100,P2); } else { C->D0(lp,P1); C->D0(lp+(fp-lp)/100,P2); } PathNorm = gp_Vec(P1,P2); break; } else { TopoDS_Vertex VL = sae.LastVertex(edge); gp_Pnt PL = BRep_Tool::Pnt(VL); if( PL.Distance(PLoc) < tol ) { double fp,lp; Handle(Geom_Curve) C = BRep_Tool::Curve(edge,fp,lp); gp_Pnt P1,P2; C->D0(fp,P1); if( P1.Distance(PLoc) < tol ) { C->D0(fp+(lp-fp)/100,P2); } else { C->D0(lp,P1); C->D0(lp+(fp-lp)/100,P2); } PathNorm = gp_Vec(P2,P1); break; } } } cout<<"VN("<PI/2.) { NeedReverse = true; aShBase1.Reverse(); } } { // second section anExp.Init( aShBase2, TopAbs_FACE ); TopoDS_Shape aFace = anExp.Current(); TColgp_SequenceOfPnt aPnts; double xc=0, yc=0, zc=0; for ( anExp.Init( aFace, TopAbs_VERTEX ); anExp.More(); anExp.Next() ) { TopoDS_Vertex V = TopoDS::Vertex(anExp.Current()); aPnts.Append(BRep_Tool::Pnt(V)); xc += aPnts.Last().X(); yc += aPnts.Last().Y(); zc += aPnts.Last().Z(); } gp_Pnt PC( xc/aPnts.Length(), yc/aPnts.Length(), zc/aPnts.Length() ); gp_Vec V1(PC,aPnts.Value(1)); gp_Vec V2(PC,aPnts.Value(2)); gp_Vec VN = V1.Crossed(V2); for(int ip=2; ipD0(fp,P1); if( P1.Distance(PLoc) < tol ) { C->D0(fp+(lp-fp)/100,P2); } else { C->D0(lp,P1); C->D0(lp+(fp-lp)/100,P2); } PathNorm = gp_Vec(P2,P1); break; } else { TopoDS_Vertex VL = sae.LastVertex(edge); gp_Pnt PL = BRep_Tool::Pnt(VL); if( PL.Distance(PLoc) < tol ) { double fp,lp; Handle(Geom_Curve) C = BRep_Tool::Curve(edge,fp,lp); gp_Pnt P1,P2; C->D0(fp,P1); if( P1.Distance(PLoc) < tol ) { C->D0(fp+(lp-fp)/100,P2); } else { C->D0(lp,P1); C->D0(lp+(fp-lp)/100,P2); } PathNorm = gp_Vec(P2,P1); break; } } } //cout<<"VN("<PI/2.) aShBase2.Reverse(); } */ if(!CreateFewSolids) { // we can create only one solid TopoDS_Shape aWire1, aWire2; // prepare aWire1 if(aType1==TopAbs_SHELL) { // create wire as boundary contour if shell is no closed // get free boundary shapes ShapeAnalysis_FreeBounds anAnalizer( aShBase1 ); TopoDS_Compound aClosed = anAnalizer.GetClosedWires(); //TopExp_Explorer anExp; Standard_Integer NbWires = 0; for ( anExp.Init( aClosed, TopAbs_WIRE ); anExp.More(); anExp.Next() ) { NbWires++; aWire1 = anExp.Current(); } if(NbWires!=1) { // bad case if(aCI) delete aCI; Standard_ConstructionError::Raise("Bad shell is used as section "); } } else { // aType1==TopAbs_FACE TopExp_Explorer aExpW(aShBase1,TopAbs_WIRE); aWire1 = aExpW.Current(); } // prepare aWire2 if(aType2==TopAbs_SHELL) { // create wire as boundary contour if shell is no closed // get free boundary shapes ShapeAnalysis_FreeBounds anAnalizer( aShBase2 ); TopoDS_Compound aClosed = anAnalizer.GetClosedWires(); //TopExp_Explorer anExp; Standard_Integer NbWires = 0; for ( anExp.Init( aClosed, TopAbs_WIRE ); anExp.More(); anExp.Next() ) { NbWires++; aWire2 = anExp.Current(); } if(NbWires!=1) { // bad case if(aCI) delete aCI; Standard_ConstructionError::Raise("Bad shell is used as section "); } } else { // aType2==TopAbs_FACE TopExp_Explorer aExpW(aShBase2,TopAbs_WIRE); aWire2 = aExpW.Current(); } // make pipe using aWire1 and aWire2 if( !aWire1.IsNull() && !aWire2.IsNull() ) { //BRepOffsetAPI_MakePipeShell aBuilder(aWirePath); BRepOffsetAPI_MakePipeShell aBuilder(WPath); aBuilder.Add(aWire1, TopoDS::Vertex(VLocs(i)), aWithContact, aWithCorrect); aBuilder.Add(aWire2, TopoDS::Vertex(VLocs(i+1)), aWithContact, aWithCorrect); if(!aBuilder.IsReady()) { if(aCI) delete aCI; Standard_ConstructionError::Raise("Invalid input data for building PIPE: bases are invalid"); } aBuilder.Build(); TopoDS_Shape aShape = aBuilder.Shape(); TopoDS_Shell aShell; B.MakeShell(aShell); for ( anExp.Init( aShape, TopAbs_FACE ); anExp.More(); anExp.Next() ) { B.Add(aShell,anExp.Current()); } for ( anExp.Init( aShBase1, TopAbs_FACE ); anExp.More(); anExp.Next() ) { B.Add(aShell,anExp.Current()); } for ( anExp.Init( aShBase2, TopAbs_FACE ); anExp.More(); anExp.Next() ) { B.Add(aShell,anExp.Current()); } // make sewing for this shell Handle(BRepBuilderAPI_Sewing) aSewing = new BRepBuilderAPI_Sewing; aSewing->SetTolerance(Precision::Confusion()); aSewing->SetFaceMode(Standard_True); aSewing->SetFloatingEdgesMode(Standard_False); aSewing->SetNonManifoldMode(Standard_False); for ( anExp.Init( aShell, TopAbs_FACE ); anExp.More(); anExp.Next() ) { aSewing->Add(anExp.Current()); } aSewing->Perform(); const TopoDS_Shape aSewShape = aSewing->SewedShape(); if( aSewShape.ShapeType() == TopAbs_SHELL ) { aShell = TopoDS::Shell(aSewShape); GProp_GProps aSystem; BRepGProp::VolumeProperties(aShell, aSystem); if(aSystem.Mass()<0) { aShell.Reverse(); } if(BRep_Tool::IsClosed(aShell)) { TopoDS_Solid aSolid; B.MakeSolid(aSolid); B.Add(aSolid,aShell); B.Add(aComp,aSolid); } else { B.Add(aComp,aShell); } } else { B.Add(aComp,aShell); } } } else { // main block - creation few solids (for each pair of faces) TopTools_MapOfShape aFaces1,aFaces2; for ( anExp.Init( aShBase1, TopAbs_FACE ); anExp.More(); anExp.Next() ) { aFaces1.Add(anExp.Current()); } for ( anExp.Init( aShBase2, TopAbs_FACE ); anExp.More(); anExp.Next() ) { aFaces2.Add(anExp.Current()); } // creating map of edge faces TopTools_IndexedDataMapOfShapeListOfShape aMapEdgeFaces1; TopExp::MapShapesAndAncestors(aShBase1, TopAbs_EDGE, TopAbs_FACE, aMapEdgeFaces1); TopTools_IndexedDataMapOfShapeListOfShape aMapEdgeFaces2; TopExp::MapShapesAndAncestors(aShBase2, TopAbs_EDGE, TopAbs_FACE, aMapEdgeFaces2); // constuct map face->face TopTools_IndexedDataMapOfShapeShape FF; TopoDS_Shape FS1,FS2; if(nbSubBases==0) { // find edge the most distant from location point // (this edge is not shared by two faces) double maxdist = 0.; TopoDS_Shape E1; TopoDS_Vertex V11,V21; for(j=1; j<=aMapEdgeFaces1.Extent(); j++) { TopoDS_Shape tmp = aMapEdgeFaces1.FindKey(j); const TopTools_ListOfShape& aList = aMapEdgeFaces1.FindFromKey(tmp); if(aList.Extent()>1) continue; TopExp_Explorer expv; expv.Init( tmp, TopAbs_VERTEX ); TopoDS_Vertex V1 = TopoDS::Vertex(expv.Current()); expv.Next(); TopoDS_Vertex V2 = TopoDS::Vertex(expv.Current()); gp_Pnt P1 = BRep_Tool::Pnt(V1); gp_Pnt P2 = BRep_Tool::Pnt(V2); double dist = PLocs.Value(i).Distance(P1) + PLocs.Value(i).Distance(P2); if(dist>maxdist) { E1 = tmp; V11 = V1; V21 = V2; TopTools_ListIteratorOfListOfShape anIter(aList); FS1 = anIter.Value(); maxdist = dist; } } // main direction for comparing gp_Vec VM(PLocs.Value(i),PLocs.Value(i+1)); // find corresponding edge from next section double minang = PI; gp_Pnt P11 = BRep_Tool::Pnt(V11); gp_Pnt P21 = BRep_Tool::Pnt(V21); TopoDS_Shape E2; TopoDS_Vertex V12,V22; for(j=1; j<=aMapEdgeFaces2.Extent(); j++) { TopoDS_Shape tmp = aMapEdgeFaces2.FindKey(j); const TopTools_ListOfShape& aList = aMapEdgeFaces2.FindFromKey(tmp); if(aList.Extent()>1) continue; TopExp_Explorer expv; expv.Init( tmp, TopAbs_VERTEX ); TopoDS_Vertex V1tmp = TopoDS::Vertex(expv.Current()); expv.Next(); TopoDS_Vertex V2tmp = TopoDS::Vertex(expv.Current()); gp_Pnt P1tmp = BRep_Tool::Pnt(V1tmp); gp_Pnt P2tmp = BRep_Tool::Pnt(V2tmp); double d1 = P1tmp.Distance(P11) + P2tmp.Distance(P21); double d2 = P1tmp.Distance(P21) + P2tmp.Distance(P11); TopoDS_Vertex V1,V2; gp_Pnt P1,P2; if(d1>d2) { V1 = V2tmp; P1 = P2tmp; V2 = V1tmp; P2 = P1tmp; } else { V1 = V1tmp; P1 = P1tmp; V2 = V2tmp; P2 = P2tmp; } gp_Vec Vec1(P11,P1); gp_Vec Vec2(P21,P2); double ang = fabs(Vec1.Angle(VM)) + fabs(Vec2.Angle(VM)); if(angValue(i); if(anItem.IsNull()) { if(aCI) delete aCI; Standard_ConstructionError::Raise("Invalid subbase shape"); } Handle(GEOM_Function) aRefBase = Handle(GEOM_Function)::DownCast(anItem); if(aRefBase.IsNull()) { if(aCI) delete aCI; Standard_ConstructionError::Raise("Invalid subbase shape"); } TopoDS_Shape aSh = aRefBase->GetValue(); if(aSh.IsNull()) { if(aCI) delete aCI; Standard_ConstructionError::Raise("Invalid subbase shape"); } if(aSh.ShapeType()!=TopAbs_FACE) { if(aCI) delete aCI; Standard_ConstructionError::Raise("Invalid subbase shape"); } FS1 = aSh; } { // 2 section Handle(Standard_Transient) anItem = aSubBasesObjs->Value(i+1); if(anItem.IsNull()) { if(aCI) delete aCI; Standard_ConstructionError::Raise("Invalid subbase shape"); } Handle(GEOM_Function) aRefBase = Handle(GEOM_Function)::DownCast(anItem); if(aRefBase.IsNull()) { if(aCI) delete aCI; Standard_ConstructionError::Raise("Invalid subbase shape"); } TopoDS_Shape aSh = aRefBase->GetValue(); if(aSh.IsNull()) { if(aCI) delete aCI; Standard_ConstructionError::Raise("Invalid subbase shape"); } if(aSh.ShapeType()!=TopAbs_FACE) { if(aCI) delete aCI; Standard_ConstructionError::Raise("Invalid subbase shape"); } FS2 = aSh; } if( !aFaces1.Contains(FS1) || !aFaces2.Contains(FS2) ) { if(aCI) delete aCI; Standard_ConstructionError::Raise("Invalid subbase shape"); } FF.Add(FS1,FS2); // add pairs of edges to FF bool stat = FillCorrespondingEdges(FS1, FS2, TopoDS::Vertex(VLocs(i)), TopoDS::Vertex(VLocs(i+1)), WPath, FF); if( !stat ) { if(aCI) delete aCI; Standard_ConstructionError::Raise("Can not create correct pipe"); } } FindNextPairOfFaces(FS1, aMapEdgeFaces1, aMapEdgeFaces2, FF, aCI); // make pipe for each pair of faces for(j=1; j<=FF.Extent(); j++) { TopoDS_Shape F1 = FF.FindKey(j); if( F1.ShapeType() != TopAbs_FACE ) continue; TopoDS_Shape F2 = FF.FindFromIndex(j); TopExp_Explorer aExpW1(F1,TopAbs_WIRE); TopoDS_Wire aWire1 = TopoDS::Wire(aExpW1.Current()); TopExp_Explorer aExpW2(F2,TopAbs_WIRE); TopoDS_Wire aWire2 = TopoDS::Wire(aExpW2.Current()); // make pipe using aWire1 and aWire2 if( !aWire1.IsNull() && !aWire2.IsNull() ) { BRepOffsetAPI_MakePipeShell aBuilder(WPath); aBuilder.Add(aWire1, TopoDS::Vertex(VLocs(i)), aWithContact, aWithCorrect); aBuilder.Add(aWire2, TopoDS::Vertex(VLocs(i+1)), aWithContact, aWithCorrect); if(!aBuilder.IsReady()) { if(aCI) delete aCI; Standard_ConstructionError::Raise("Invalid input data for building PIPE: bases are invalid"); } aBuilder.Build(); TopoDS_Shape aShape = aBuilder.Shape(); TopoDS_Shell aShell; B.MakeShell(aShell); for ( anExp.Init( aShape, TopAbs_FACE ); anExp.More(); anExp.Next() ) { B.Add(aShell,anExp.Current()); } B.Add(aShell,F1); B.Add(aShell,F2); // make sewing for this shell Handle(BRepBuilderAPI_Sewing) aSewing = new BRepBuilderAPI_Sewing; aSewing->SetTolerance(Precision::Confusion()); aSewing->SetFaceMode(Standard_True); aSewing->SetFloatingEdgesMode(Standard_False); aSewing->SetNonManifoldMode(Standard_False); for ( anExp.Init( aShell, TopAbs_FACE ); anExp.More(); anExp.Next() ) { aSewing->Add(anExp.Current()); } aSewing->Perform(); const TopoDS_Shape aSewShape = aSewing->SewedShape(); if( aSewShape.ShapeType() == TopAbs_SHELL ) { aShell = TopoDS::Shell(aSewShape); GProp_GProps aSystem; BRepGProp::VolumeProperties(aShell, aSystem); if(aSystem.Mass()<0) { //cout<<"aSewShape is reversed"<GetBases(); // vertex for recognition Handle(TColStd_HSequenceOfTransient) VObjs = aCIDS->GetLocations(); Standard_Integer nbBases = aBasesObjs->Length(), nbv = (VObjs.IsNull() ? 0 :VObjs->Length()); if( nbv != nbBases ) { if(aCI) delete aCI; Standard_ConstructionError::Raise("Number of shapes for recognition is invalid"); } TopTools_SequenceOfShape SecVs,Bases; for(i=1; i<=nbBases; i++) { // vertex Handle(Standard_Transient) anItem = VObjs->Value(i); if(anItem.IsNull()) continue; Handle(GEOM_Function) aRef = Handle(GEOM_Function)::DownCast(anItem); TopoDS_Shape V = aRef->GetValue(); if(V.IsNull() || V.ShapeType() != TopAbs_VERTEX) continue; SecVs.Append(V); // section anItem = aBasesObjs->Value(i); if(anItem.IsNull()) continue; aRef = Handle(GEOM_Function)::DownCast(anItem); TopoDS_Shape aSh = aRef->GetValue(); if(aSh.IsNull()) continue; Bases.Append(aSh); } nbv = SecVs.Length(); nbBases = Bases.Length(); if( nbv != nbBases ) { if(aCI) delete aCI; Standard_ConstructionError::Raise("One of shapes for recognition is not a vertex"); } TopoDS_Compound aComp; B.MakeCompound(aComp); for(i=1 ; iface (and subshapes) TopTools_IndexedDataMapOfShapeShape FF; //TopoDS_Shape FS1 = SecFs.Value(i), FS2 = SecFs.Value(i+1); TopoDS_Shape FS1, FS2; TopoDS_Vertex V1 = TopoDS::Vertex(SecVs(i)); TopoDS_Vertex V2 = TopoDS::Vertex(SecVs(i+1)); FindFirstPairFaces(aShBase1, aShBase2, V1, V2, FS1, FS2); FF.Add(FS1,FS2); cout<<" first pair of corresponding faces is found"<edge for created pipe edges TopTools_IndexedDataMapOfShapeShape VPE; ShapeAnalysis_Edge sae; //cout<<"FF.Extent()="<IsKind(STANDARD_TYPE(Geom_RectangularTrimmedSurface))) { Handle(Geom_RectangularTrimmedSurface) RTS = Handle(Geom_RectangularTrimmedSurface)::DownCast(S1); S1 = RTS->BasisSurface(); } Handle(Geom_Plane) Pln1 = Handle(Geom_Plane)::DownCast(S1); if( Pln1.IsNull() ) { if(aCI) delete aCI; Standard_ConstructionError::Raise("Surface from face is not plane"); } gp_Vec aDir1(Pln1->Axis().Direction()); Handle(Geom_Surface) S2 = BRep_Tool::Surface(TopoDS::Face(F2)); if(S2->IsKind(STANDARD_TYPE(Geom_RectangularTrimmedSurface))) { Handle(Geom_RectangularTrimmedSurface) RTS = Handle(Geom_RectangularTrimmedSurface)::DownCast(S2); S2 = RTS->BasisSurface(); } Handle(Geom_Plane) Pln2 = Handle(Geom_Plane)::DownCast(S2); if( Pln2.IsNull() ) { if(aCI) delete aCI; Standard_ConstructionError::Raise("Surface from face is not plane"); } gp_Vec aDir2(Pln2->Axis().Direction()); gp_Pnt P1 = BRep_Tool::Pnt(TopoDS::Vertex(SecVs(i))); gp_Pnt P2 = BRep_Tool::Pnt(TopoDS::Vertex(SecVs(i+1))); gp_Vec aDir(P1,P2); if(fabs(aDir.Angle(aDir1))>PI/2.) aDir1.Reverse(); if(fabs(aDir.Angle(aDir2))>PI/2.) aDir2.Reverse(); TopExp_Explorer anExpE(F1,TopAbs_EDGE); TopTools_SequenceOfShape aNewFs; //int nbee=0; for(; anExpE.More(); anExpE.Next()) { TopoDS_Edge E1 = TopoDS::Edge(anExpE.Current()); //nbee++; if(!FF.Contains(E1)) cout<<"map FF not contains key E1"<SetValue(1,P2); HAP->SetValue(2,P3); GeomAPI_Interpolate anInt(HAP,Standard_False,1.e-7); anInt.Load(aDir1,aDir2); anInt.Perform(); C2 = anInt.Curve(); B.MakeEdge(E2,C2,1.e-7); B.Add(E2,TopoDS::Vertex(V2.Oriented(TopAbs_FORWARD))); B.Add(E2,TopoDS::Vertex(V3.Oriented(TopAbs_REVERSED))); VPE.Add(V2,E2); } // make E4 TopoDS_Edge E4; Handle(Geom_BSplineCurve) C4; if(VPE.Contains(V1)) { E4 = TopoDS::Edge(VPE.FindFromKey(V1)); double fp,lp; C4 = Handle(Geom_BSplineCurve)::DownCast(BRep_Tool::Curve(E4,fp,lp)); } else { Handle(TColgp_HArray1OfPnt) HAP = new TColgp_HArray1OfPnt(1,2); HAP->SetValue(1,P1); HAP->SetValue(2,P4); GeomAPI_Interpolate anInt(HAP,Standard_False,1.e-7); anInt.Load(aDir1,aDir2); anInt.Perform(); C4 = anInt.Curve(); B.MakeEdge(E4,anInt.Curve(),1.e-7); B.Add(E4,TopoDS::Vertex(V1.Oriented(TopAbs_FORWARD))); B.Add(E4,TopoDS::Vertex(V4.Oriented(TopAbs_REVERSED))); VPE.Add(V1,E4); } TopoDS_Wire W; B.MakeWire(W); B.Add(W,E1); B.Add(W,E2); B.Add(W,E3); B.Add(W,E4.Reversed()); //cout<<" wire for edge "<IsKind(STANDARD_TYPE(Geom_Conic)) ) { // IsConicC1 = true; // cout<<"C1 - Geom_Conic"<IsKind(STANDARD_TYPE(Geom_Line)) || C1->IsKind(STANDARD_TYPE(Geom_Conic)) ) { C1 = new Geom_TrimmedCurve(C1,fp,lp); } //if(IsConicC1) { // double tol = BRep_Tool::Tolerance(E1); // GeomConvert_ApproxCurve ApxC1(C1,tol,GeomAbs_C1,10,5); // C1 = ApxC1.Curve(); //} Handle(Geom_Curve) C3 = BRep_Tool::Curve(E3,fp,lp); if( C3->IsKind(STANDARD_TYPE(Geom_Line)) || C3->IsKind(STANDARD_TYPE(Geom_Conic)) ) { C3 = new Geom_TrimmedCurve(C3,fp,lp); } //filebuf fic; //ostream os(&fic); //os.precision(15); Handle(Geom_BSplineCurve) CE1 = GeomConvert::CurveToBSplineCurve(C1,Convert_RationalC1); if(CE1->Degree()<3) CE1->IncreaseDegree(3); Handle(Geom_BSplineCurve) CE2 = GeomConvert::CurveToBSplineCurve(C2,Convert_RationalC1); if(CE2->Degree()<3) CE2->IncreaseDegree(3); Handle(Geom_BSplineCurve) CE3 = GeomConvert::CurveToBSplineCurve(C3,Convert_RationalC1); if(CE3->Degree()<3) CE3->IncreaseDegree(3); Handle(Geom_BSplineCurve) CE4 = GeomConvert::CurveToBSplineCurve(C4,Convert_RationalC1); if(CE4->Degree()<3) CE4->IncreaseDegree(3); //cout<<"CE1->Degree()="<Degree()<<" CE2->Degree()="<Degree() // <<" CE3->Degree()="<Degree()<<" CE4->Degree()="<Degree()<D0(fp1,P1C1); C1->D0(lp1,P2C1); gp_Pnt P1C3,P2C3; C3->D0(fp2,P1C3); C3->D0(lp2,P2C3); int n1,n2; double fp,lp; // get points from C1 if(P1.Distance(P1C1)<1.e-6) { fp = fp1; lp = lp1; } else { fp = lp1; lp = fp1; } double step = (lp-fp)/(NbP-1); Points.SetValue(1,1,P1); double par = fp; for(n1=2; n1D0(par,P); Points.SetValue(1,n1,P); } Points.SetValue(1,NbP,P2); // get points from C3 if(P4.Distance(P1C3)<1.e-6) { fp = fp2; lp = lp2; } else { fp = lp2; lp = fp2; } step = (lp-fp)/(NbP-1); Points.SetValue(NbP,1,P4); par = fp; for(n1=2; n1D0(par,P); Points.SetValue(NbP,n1,P); } Points.SetValue(NbP,NbP,P3); // create isolines and get points from them for(n1=1; n1<=NbP; n1++) { gp_Pnt PI1 = Points.Value(1,n1); gp_Pnt PI2 = Points.Value(NbP,n1); Handle(TColgp_HArray1OfPnt) HAP = new TColgp_HArray1OfPnt(1,2); HAP->SetValue(1,PI1); HAP->SetValue(2,PI2); GeomAPI_Interpolate anInt(HAP,Standard_False,1.e-7); anInt.Load(aDir1,aDir2); anInt.Perform(); Handle(Geom_Curve) iso = anInt.Curve(); fp = iso->FirstParameter(); lp = iso->LastParameter(); step = (lp-fp)/(NbP-1); par = fp; TopoDS_Compound VComp; B.MakeCompound(VComp); for(n2=2; n2D0(par,P); Points.SetValue(n2,n1,P); } } // create surface and face //Handle(Geom_BezierSurface) BS = new Geom_BezierSurface(Points); BS = new Geom_BezierSurface(Points); } BRepBuilderAPI_MakeFace BB(BS,W); TopoDS_Face NewF = BB.Face(); Handle(ShapeFix_Face) sff = new ShapeFix_Face(NewF); sff->Perform(); sff->FixOrientation(); TopoDS_Face FixedFace = sff->Face(); aNewFs.Append(FixedFace); VPE.Add(E1,FixedFace); //cout<<" face for edge "<SetTolerance(Precision::Confusion()); aSewing->SetFaceMode(Standard_True); aSewing->SetFloatingEdgesMode(Standard_False); aSewing->SetNonManifoldMode(Standard_False); for ( anExp.Init( aShell, TopAbs_FACE ); anExp.More(); anExp.Next() ) { aSewing->Add(anExp.Current()); } aSewing->Perform(); cout<<" shell for face "<SewedShape(); //BRepTools::Write(aSewShape,"/dn02/users_Linux/skl/work/Bugs/14857/sew.brep"); if( aSewShape.ShapeType() == TopAbs_SHELL ) { aShell = TopoDS::Shell(aSewShape); GProp_GProps aSystem; BRepGProp::VolumeProperties(aShell, aSystem); if(aSystem.Mass()<0) { //cout<<"aSewShape is reversed"<Perform(); //TopoDS_Shell FixedShell = sfs->Shell(); /* GProp_GProps aSystem; BRepGProp::VolumeProperties(FixedShell, aSystem); if(aSystem.Mass()<0) { //cout<<"aSewShape is reversed"<GetType(); if(aType == PIPE_BASE_PATH) aCI = new GEOMImpl_IPipe(aFunction); else if(aType == PIPE_DIFFERENT_SECTIONS) aCI = new GEOMImpl_IPipeDiffSect(aFunction); else if(aType == PIPE_SHELL_SECTIONS) aCI = new GEOMImpl_IPipeShellSect(aFunction); else if(aType == PIPE_SHELLS_WITHOUT_PATH) aCI = new GEOMImpl_IPipeShellSect(aFunction); else return 0; TopoDS_Wire aWirePath; if(aType != PIPE_SHELLS_WITHOUT_PATH) { // working with path Handle(GEOM_Function) aRefPath = aCI->GetPath(); TopoDS_Shape aShapePath = aRefPath->GetValue(); if (aShapePath.IsNull()) { cout<<"Driver : path is null"<GetBase(); TopoDS_Shape aShapeBase = aRefBase->GetValue(); if (aShapeBase.IsNull()) { if(aCI) delete aCI; Standard_NullObject::Raise("MakePipe aborted : null base argument"); } // Make pipe aShape = BRepOffsetAPI_MakePipe(aWirePath, aShapeBase); } //building pipe with different sections else if (aType == PIPE_DIFFERENT_SECTIONS) { GEOMImpl_IPipeDiffSect* aCIDS = (GEOMImpl_IPipeDiffSect*)aCI; //GEOMImpl_IPipeDiffSect* aCIDS = static_cast(aCI); //BRepOffsetAPI_MakePipeShell aBuilder(aWirePath); Handle(TColStd_HSequenceOfTransient) aBasesObjs = aCIDS->GetBases (); Handle(TColStd_HSequenceOfTransient) aLocObjs = aCIDS->GetLocations (); Standard_Boolean aWithContact = (aCIDS->GetWithContactMode()); Standard_Boolean aWithCorrect = (aCIDS->GetWithCorrectionMode()); Standard_Integer i =1, nbBases = aBasesObjs->Length(), nbLocs = (aLocObjs.IsNull() ? 0 :aLocObjs->Length()); if(nbLocs && nbLocs != nbBases) { if(aCI) delete aCI; Standard_ConstructionError::Raise("Number of sections is not equal to number of locations "); } TopTools_SequenceOfShape aSeqBases; TopTools_SequenceOfShape aSeqLocs; TopTools_SequenceOfShape aSeqFaces; for( ; i <= nbBases; i++) { Handle(Standard_Transient) anItem = aBasesObjs->Value(i); if(anItem.IsNull()) continue; Handle(GEOM_Function) aRefBase = Handle(GEOM_Function)::DownCast(anItem); if(aRefBase.IsNull()) continue; TopoDS_Shape aShapeBase = aRefBase->GetValue(); if(aShapeBase.IsNull()) continue; TopAbs_ShapeEnum aTypeBase = aShapeBase.ShapeType(); //if for section was specified face with a few wires then a few // pipes were build and make solid Standard_Boolean NeedCreateSolid = Standard_False; if(aTypeBase == TopAbs_SHELL) { // create wire as boundary contour if shell is no closed // get free boundary shapes ShapeAnalysis_FreeBounds anAnalizer( aShapeBase ); TopoDS_Compound aClosed = anAnalizer.GetClosedWires(); TopExp_Explorer anExp; TopoDS_Shape aWire; Standard_Integer NbWires = 0; for ( anExp.Init( aClosed, TopAbs_WIRE ); anExp.More(); anExp.Next() ) { NbWires++; aWire = anExp.Current(); } if(NbWires!=1) { // bad case if(aCI) delete aCI; Standard_ConstructionError::Raise("Bad shell is used as section "); } NeedCreateSolid = Standard_True; aSeqFaces.Append(aShapeBase); aSeqBases.Append(aWire); } else if(aTypeBase == TopAbs_FACE) { NeedCreateSolid = Standard_True; //for case one path should be used other type function aSeqFaces.Append(aShapeBase); TopExp_Explorer aExpW(aShapeBase,TopAbs_WIRE); for( ; aExpW.More(); aExpW.Next()) { TopoDS_Shape aWireProf = aExpW.Current(); aSeqBases.Append(aWireProf); } } else if(aTypeBase == TopAbs_WIRE || aTypeBase == TopAbs_VERTEX) { aSeqBases.Append(aShapeBase); } else if(aTypeBase == TopAbs_EDGE) { TopoDS_Edge anEdge = TopoDS::Edge(aShapeBase); TopoDS_Shape aWireProf = BRepBuilderAPI_MakeWire(anEdge); aSeqBases.Append(aWireProf); } if(nbLocs) { Handle(Standard_Transient) anItemLoc = aLocObjs->Value(i); if(anItemLoc.IsNull()) continue; Handle(GEOM_Function) aRefLoc = Handle(GEOM_Function)::DownCast(anItemLoc); TopoDS_Shape aShapeLoc = aRefLoc->GetValue(); if(aShapeLoc.IsNull() || aShapeLoc.ShapeType() != TopAbs_VERTEX) continue; aSeqLocs.Append(aShapeLoc); } } nbLocs = aSeqLocs.Length(); // skl 02.05.2007 TopTools_SequenceOfShape Edges; if(nbLocs>0) { // we have to check that each location shape is a vertex from // path and update aSeqLocs if it is needed (and possible) TColgp_SequenceOfPnt PLocs; for(i=1; i<=nbLocs; i++) { TopoDS_Vertex V = TopoDS::Vertex(aSeqLocs.Value(i)); PLocs.Append(BRep_Tool::Pnt(V)); } //TopTools_SequenceOfShape Edges; TopExp_Explorer anExp; for ( anExp.Init( aWirePath, TopAbs_EDGE ); anExp.More(); anExp.Next() ) { Edges.Append(anExp.Current()); } int nbEdges = Edges.Length(); ShapeAnalysis_Edge sae; TopoDS_Edge edge = TopoDS::Edge(Edges.First()); double tol = BRep_Tool::Tolerance(edge); TopoDS_Vertex VF = sae.FirstVertex(edge); gp_Pnt PF = BRep_Tool::Pnt(VF); //cout<<"PF("< tol ) { if(aCI) delete aCI; Standard_ConstructionError::Raise ("First location shapes is not coincided with first vertex of aWirePath"); } aSeqLocs.ChangeValue(1) = VF; edge = TopoDS::Edge(Edges.Last()); tol = BRep_Tool::Tolerance(edge); TopoDS_Vertex VL = sae.LastVertex(edge); gp_Pnt PL = BRep_Tool::Pnt(VL); if( PL.Distance(PLocs.Last()) > tol ) { if(aCI) delete aCI; Standard_ConstructionError::Raise ("Last location shapes is not coincided with last vertex of aWirePath"); } aSeqLocs.ChangeValue(nbLocs) = VL; int jcurr = 2; for(i=1; i<=Edges.Length() && jcurr0 && PLocs.Value(jcurr).Distance(PPC.Point(1)) < tol ) { double param = PPC.Parameter(1); gp_Pnt PC1; C->D0(param,PC1); // split current edge Handle(Geom_TrimmedCurve) tc1 = new Geom_TrimmedCurve(C,fp,param); Handle(Geom_TrimmedCurve) tc2 = new Geom_TrimmedCurve(C,param,lp); TopoDS_Edge E1,E2; BRep_Builder B; gp_Pnt Pfp; C->D0(fp,Pfp); if(Pfp.Distance(P1) we have to update WirePath BRep_Builder B; TopoDS_Wire W; B.MakeWire(W); for(i=1; i<=Edges.Length(); i++) { B.Add(W,TopoDS::Edge(Edges.Value(i))); } aWirePath = W; } } // check curvature of wire for condition that // max summary angle between directions along // wire path must be < 4*PI. If not - split wire // and seguences of shapes, perform pipe for each // and make sewing after that double fp,lp; Handle(Geom_Curve) C = BRep_Tool::Curve(TopoDS::Edge(Edges.Value(1)),fp,lp); gp_Pnt P1,P2; gp_Vec Vec1,Vec2; C->D1(fp,P1,Vec1); C->D1(lp,P2,Vec2); double SumAng = fabs(Vec1.Angle(Vec2)); Vec1 = Vec2; P1 = P2; TColStd_SequenceOfInteger SplitEdgeNums,SplitLocNums; int LastLoc = 1; //cout<<"Edges.Length()="<D1(lp,P2,Vec2); double ang = fabs(Vec1.Angle(Vec2)); SumAng += ang; if(SumAng>4*PI) { SumAng = ang; SplitEdgeNums.Append(i-1); int j; for(j=LastLoc+1; j<=aSeqLocs.Length(); j++) { TopoDS_Vertex aVert = TopoDS::Vertex(aSeqLocs.Value(j)); gp_Pnt P = BRep_Tool::Pnt(aVert); if( P1.Distance(P) < tol ) { SplitLocNums.Append(j); LastLoc = j; break; } } } Vec1 = Vec2; P1 = P2; } //cout<<"SplitEdgeNums.Length()="<SetTolerance(Precision::Confusion()); aSewing->SetFaceMode(Standard_True); aSewing->SetFloatingEdgesMode(Standard_False); aSewing->SetNonManifoldMode(Standard_False); for(i=1; i<=aSeqRes.Length(); i++) { aSewing->Add(aSeqRes.Value(i)); } aSewing->Perform(); aShape = aSewing->SewedShape(); } else { // old implementation without splitting BRepOffsetAPI_MakePipeShell aBuilder(aWirePath); Standard_Integer nbShapes = aSeqBases.Length(); Standard_Integer step = nbShapes/nbBases; if(nbShapes < nbBases || fmod((double)nbShapes, (double)nbBases)) { if(aCI) delete aCI; Standard_ConstructionError::Raise("Invalid sections were specified for building pipe"); } Standard_Integer ind =0; for( i=1; i <= nbShapes && ind < nbShapes; i++) { //i+nbBases <= nbShapes TopTools_SequenceOfShape usedBases; Standard_Integer j = 1; for( ; j <= nbBases ; j++) { ind = i + (j-1)*step; TopoDS_Shape aWireProf = aSeqBases.Value(ind); usedBases.Append(aWireProf); if(nbLocs) { TopoDS_Shape aShapeLoc = aSeqLocs.Value(j); TopoDS_Vertex aVert = TopoDS::Vertex(aShapeLoc); aBuilder.Add(aWireProf,aVert,aWithContact,aWithCorrect); } else aBuilder.Add(aWireProf,aWithContact,aWithCorrect); } if(!aBuilder.IsReady()) { if(aCI) delete aCI; Standard_ConstructionError::Raise("Invalid input data for building PIPE: bases are invalid"); } aBuilder.Build(); aShape = aBuilder.Shape(); aSeqFaces.Append(aShape); for( j = 1; j <=usedBases.Length(); j++) aBuilder.Delete(usedBases.Value(j)); } //for case if section is face if(aSeqFaces.Length() >1) { BRep_Builder aB; TopoDS_Compound aComp; aB.MakeCompound(aComp); for( i = 1; i <= aSeqFaces.Length(); i++) aB.Add(aComp,aSeqFaces.Value(i)); aShape = aComp; } } } //building pipe with shell sections else if (aType == PIPE_SHELL_SECTIONS) { aShape = CreatePipeForShellSections(aWirePath,aCI); } //building pipe shell sections without path else if (aType == PIPE_SHELLS_WITHOUT_PATH) { aShape = CreatePipeShellsWithoutPath(aCI); } if (aCI) { delete aCI; aCI = 0; } if (aShape.IsNull()) return 0; BRepCheck_Analyzer ana (aShape, Standard_False); if (!ana.IsValid()) { ShapeFix_ShapeTolerance aSFT; aSFT.LimitTolerance(aShape,Precision::Confusion(),Precision::Confusion()); Handle(ShapeFix_Shape) aSfs = new ShapeFix_Shape(aShape); aSfs->SetPrecision(Precision::Confusion()); aSfs->Perform(); aShape = aSfs->Shape(); ana.Init(aShape, Standard_False); if (!ana.IsValid()) Standard_ConstructionError::Raise("Algorithm have produced an invalid shape result"); } TopoDS_Shape aRes = GEOMImpl_IShapesOperations::CompsolidToCompound(aShape); aFunction->SetValue(aRes); log.SetTouched(Label()); return 1; } //======================================================================= //function : GEOMImpl_PipeDriver_Type_ //purpose : //======================================================================= Standard_EXPORT Handle_Standard_Type& GEOMImpl_PipeDriver_Type_() { static Handle_Standard_Type aType1 = STANDARD_TYPE(TFunction_Driver); if ( aType1.IsNull()) aType1 = STANDARD_TYPE(TFunction_Driver); static Handle_Standard_Type aType2 = STANDARD_TYPE(MMgt_TShared); if ( aType2.IsNull()) aType2 = STANDARD_TYPE(MMgt_TShared); static Handle_Standard_Type aType3 = STANDARD_TYPE(Standard_Transient); if ( aType3.IsNull()) aType3 = STANDARD_TYPE(Standard_Transient); static Handle_Standard_Transient _Ancestors[]= {aType1,aType2,aType3,NULL}; static Handle_Standard_Type _aType = new Standard_Type("GEOMImpl_PipeDriver", sizeof(GEOMImpl_PipeDriver), 1, (Standard_Address)_Ancestors, (Standard_Address)NULL); return _aType; } //======================================================================= //function : DownCast //purpose : //======================================================================= const Handle(GEOMImpl_PipeDriver) Handle(GEOMImpl_PipeDriver)::DownCast(const Handle(Standard_Transient)& AnObject) { Handle(GEOMImpl_PipeDriver) _anOtherObject; if (!AnObject.IsNull()) { if (AnObject->IsKind(STANDARD_TYPE(GEOMImpl_PipeDriver))) { _anOtherObject = Handle(GEOMImpl_PipeDriver)((Handle(GEOMImpl_PipeDriver)&)AnObject); } } return _anOtherObject ; }