// Copyright (C) 2007-2014 CEA/DEN, EDF R&D, OPEN CASCADE // // Copyright (C) 2003-2007 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, or (at your option) any later version. // // 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 #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 : EvaluateBestSweepMode //purpose : auxilary for right call of MakePipe and MakePipeShell //======================================================================= static GeomFill_Trihedron EvaluateBestSweepMode(const TopoDS_Shape& Spine) { GeomFill_Trihedron theMode = GeomFill_IsFrenet; TopExp_Explorer Explo(Spine, TopAbs_EDGE); for (; Explo.More(); Explo.Next()) { TopoDS_Edge anEdge = TopoDS::Edge(Explo.Current()); Standard_Real fpar, lpar; Handle(Geom_Curve) aCurve = BRep_Tool::Curve(anEdge, fpar, lpar); GeomAdaptor_Curve GAcurve(aCurve, fpar, lpar); Handle(GeomAdaptor_HCurve) GAHcurve = new GeomAdaptor_HCurve(GAcurve); Handle(GeomFill_CorrectedFrenet) aCorrFrenet = new GeomFill_CorrectedFrenet(Standard_True); //for evaluation aCorrFrenet->SetCurve(GAHcurve); GeomFill_Trihedron aMode = aCorrFrenet->EvaluateBestMode(); if (aMode == GeomFill_IsDiscreteTrihedron) { theMode = aMode; break; } if (aMode == GeomFill_IsCorrectedFrenet) theMode = aMode; } return theMode; } //======================================================================= //function : BuildPipeShell //purpose : Builds a pipe shell. If failed, try to build in Descrete Trihedron // mode. Returns Standard_True if the building is done successfully. //======================================================================= static Standard_Boolean BuildPipeShell(BRepOffsetAPI_MakePipeShell &theBuilder) { theBuilder.Build(); Standard_Boolean isDone = theBuilder.IsDone(); if (!isDone) { // Try to use Descrete Trihedron mode. theBuilder.SetDiscreteMode(); theBuilder.Build(); isDone = theBuilder.IsDone(); } return isDone; } //======================================================================= //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"<Length(); Standard_Integer nbLocs = (theHSeqLocs.IsNull() ? 0 : theHSeqLocs->Length()); if (nbLocs && nbLocs != nbBases) { Standard_ConstructionError::Raise("Number of sections is not equal to number of locations "); } TopTools_SequenceOfShape aSeqBases; TopTools_SequenceOfShape aSeqLocs; TopTools_SequenceOfShape aSeqFaces; Standard_Boolean NeedCreateSolid = Standard_False; Standard_Integer i = 1; for (i = 1; i <= nbBases; i++) { if (theHSeqBases->Value(i).IsNull()) continue; // Make copy to prevent modifying of base object 0020766 : EDF 1320 TopoDS_Shape aShapeBase; BRepBuilderAPI_Copy Copy (theHSeqBases->Value(i)); if (Copy.IsDone()) aShapeBase = Copy.Shape(); TopAbs_ShapeEnum aTypeBase = aShapeBase.ShapeType(); //if for section was specified face with a few wires then a few // pipes were build and make solid 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 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) { TopoDS_Shape aShapeLoc = theHSeqLocs->Value(i); 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) { 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) { 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(PPCurve.Point(1)) < tol) { double param = PPCurve.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; gp_Pnt P1,P2; gp_Vec Vec1,Vec2; double SumAng = 0; if ( Edges.Length() > 0 ) { Handle(Geom_Curve) C = BRep_Tool::Curve(TopoDS::Edge(Edges.Value(1)),fp,lp); C->D1(fp,P1,Vec1); C->D1(lp,P2,Vec2); 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*M_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; } if (SplitLocNums.Length()==SplitEdgeNums.Length() && SplitEdgeNums.Length()>0) { TopTools_SequenceOfShape aSeqRes; int nn, num1 = 1, num2 = 1; for (nn=1; nn<=SplitEdgeNums.Length(); nn++) { // create wirepath and sequences of shapes BRep_Builder B; TopoDS_Wire tmpW; B.MakeWire(tmpW); for (i=num1; i<=SplitEdgeNums.Value(nn); i++) { B.Add(tmpW,TopoDS::Edge(Edges.Value(i))); } num1 = SplitEdgeNums.Value(nn) + 1; TopTools_SequenceOfShape aTmpSeqBases; TopTools_SequenceOfShape aTmpSeqLocs; for (i=num2; i<=SplitLocNums.Value(nn); i++) { aTmpSeqBases.Append(aSeqBases.Value(i)); aTmpSeqLocs.Append(aSeqLocs.Value(i)); } num2 = SplitLocNums.Value(nn); // make pipe BRepOffsetAPI_MakePipeShell aBuilder(tmpW); GeomFill_Trihedron theBestMode = EvaluateBestSweepMode(tmpW); if (theBestMode == GeomFill_IsDiscreteTrihedron) aBuilder.SetDiscreteMode(); Standard_Integer nbShapes = aTmpSeqBases.Length(); for (i=1; i<=nbShapes; i++) { TopoDS_Shape aShapeLoc = aTmpSeqLocs.Value(i); TopoDS_Vertex aVert = TopoDS::Vertex(aShapeLoc); aBuilder.Add(aTmpSeqBases.Value(i), aVert, theWithContact, theWithCorrect); } if (!aBuilder.IsReady()) { Standard_ConstructionError::Raise("Invalid input data for building PIPE: bases are invalid"); } BuildPipeShell(aBuilder); TopoDS_Shape resShape = aBuilder.Shape(); aSeqRes.Append(resShape); } // create wirepath and sequences of shapes for last part BRep_Builder B; TopoDS_Wire tmpW; B.MakeWire(tmpW); for (i=num1; i<=Edges.Length(); i++) { B.Add(tmpW,TopoDS::Edge(Edges.Value(i))); } TopTools_SequenceOfShape aTmpSeqBases; TopTools_SequenceOfShape aTmpSeqLocs; for (i=num2; i<=aSeqLocs.Length(); i++) { aTmpSeqBases.Append(aSeqBases.Value(i)); aTmpSeqLocs.Append(aSeqLocs.Value(i)); } // make pipe for last part BRepOffsetAPI_MakePipeShell aBuilder(tmpW); GeomFill_Trihedron theBestMode = EvaluateBestSweepMode(tmpW); if (theBestMode == GeomFill_IsDiscreteTrihedron) aBuilder.SetDiscreteMode(); Standard_Integer nbShapes = aTmpSeqBases.Length(); for (i=1; i<=nbShapes; i++) { TopoDS_Shape aShapeLoc = aTmpSeqLocs.Value(i); TopoDS_Vertex aVert = TopoDS::Vertex(aShapeLoc); aBuilder.Add(aTmpSeqBases.Value(i), aVert, theWithContact, theWithCorrect); } if (!aBuilder.IsReady()) { Standard_ConstructionError::Raise("Invalid input data for building PIPE: bases are invalid"); } BuildPipeShell(aBuilder); TopoDS_Shape resShape = aBuilder.Shape(); aSeqRes.Append(resShape); // make sewing for result Handle(BRepBuilderAPI_Sewing) aSewing = new BRepBuilderAPI_Sewing; aSewing->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); GeomFill_Trihedron theBestMode = EvaluateBestSweepMode(aWirePath); if (theBestMode == GeomFill_IsDiscreteTrihedron) aBuilder.SetDiscreteMode(); Standard_Integer nbShapes = aSeqBases.Length(); Standard_Integer step = nbShapes/nbBases; if (nbShapes < nbBases || fmod((double)nbShapes, (double)nbBases)) { Standard_ConstructionError::Raise("Invalid sections were specified for building pipe"); } Standard_Integer ind =0; Standard_Real aTolConf = Precision::Confusion(); Standard_Real aTolAng = Precision::Angular(); 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, theWithContact, theWithCorrect); } else aBuilder.Add(aWireProf, theWithContact, theWithCorrect); } if (!aBuilder.IsReady()) { Standard_ConstructionError::Raise("Invalid input data for building PIPE: bases are invalid"); } aBuilder.SetTolerance(aTolConf, aTolConf, aTolAng); Standard_Boolean isDone = BuildPipeShell(aBuilder); if (isDone && NeedCreateSolid) { isDone = aBuilder.MakeSolid(); } if (!isDone) { Standard_ConstructionError::Raise("Pipe construction failure"); } aShape = aBuilder.Shape(); aSeqFaces.Append(aShape); for (j = 1; j <=usedBases.Length(); j++) aBuilder.Delete(usedBases.Value(j)); } } return aShape; } //======================================================================= //function : CreatePipeForShellSections //purpose : auxilary for Execute() //======================================================================= static TopoDS_Shape CreatePipeForShellSections(const TopoDS_Wire& aWirePath, GEOMImpl_IPipe* aCI) { //cout<<"CreatePipeForShellSections"<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(PPCurve.Point(1)) < tol) { double param = PPCurve.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); GeomFill_Trihedron theBestMode = EvaluateBestSweepMode(WPath); if (theBestMode == GeomFill_IsDiscreteTrihedron) aBuilder.SetDiscreteMode(); 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"); } BuildPipeShell(aBuilder); 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 = M_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); GeomFill_Trihedron theBestMode = EvaluateBestSweepMode(WPath); if (theBestMode == GeomFill_IsDiscreteTrihedron) aBuilder.SetDiscreteMode(); 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"); } BuildPipeShell(aBuilder); 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; i < nbBases; i++) { MESSAGE ("Make pipe between sections "<face (and sub-shapes) 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); MESSAGE (" first pair of corresponding faces is found"); // add pairs of edges and vertexes to FF bool stat = FillCorrespondingEdges(FS1, FS2, V1, V2, FF); if (!stat) { if (aCI) delete aCI; Standard_ConstructionError::Raise("Can not create correct pipe"); } MESSAGE (" correspondences for sub-shapes of first pair of faces is found"); FindNextPairOfFaces(FS1, aMapEdgeFaces1, aMapEdgeFaces2, FF, aCI); MESSAGE (" other correspondences is found, make pipe for all pairs of faces"); // make pipe for each pair of faces // auxilary map vertex->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)) > M_PI/2.) aDir1.Reverse(); if (fabs(aDir.Angle(aDir2)) > M_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)) MESSAGE ("map FF not contains key E1"); if (VPE.Contains(E1)) { aNewFs.Append(VPE.FindFromKey(E1)); #ifdef _DEBUG_ MESSAGE (" using existed face"); #endif continue; } TopoDS_Edge E3 = TopoDS::Edge(FF.FindFromKey(E1)); TopoDS_Vertex V1 = sae.FirstVertex(E1); TopoDS_Vertex V2 = sae.LastVertex(E1); if (!FF.Contains(V1)) MESSAGE ("map FF not contains key V1"); if (!FF.Contains(V2)) MESSAGE ("map FF not contains key V2"); TopoDS_Vertex V3 = TopoDS::Vertex(FF.FindFromKey(V2)); TopoDS_Vertex V4 = TopoDS::Vertex(FF.FindFromKey(V1)); TopoDS_Vertex Vtmp = sae.FirstVertex(E3); if (Vtmp.IsSame(V4)) E3.Reverse(); gp_Pnt P1 = BRep_Tool::Pnt(V1); gp_Pnt P2 = BRep_Tool::Pnt(V2); gp_Pnt P3 = BRep_Tool::Pnt(V3); gp_Pnt P4 = BRep_Tool::Pnt(V4); // make E2 TopoDS_Edge E2; Handle(Geom_BSplineCurve) C2; if (VPE.Contains(V2)) { E2 = TopoDS::Edge(VPE.FindFromKey(V2)); double fp,lp; C2 = Handle(Geom_BSplineCurve)::DownCast(BRep_Tool::Curve(E2,fp,lp)); } else { Handle(TColgp_HArray1OfPnt) HAP = new TColgp_HArray1OfPnt(1,2); HAP->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(); MESSAGE (" 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"<GetBase(); Handle(GEOM_Function) aRefVec = aCIBN->GetVector(); TopoDS_Shape aShapeBase = aRefBase->GetValue(); TopoDS_Shape aShapeVec = aRefVec->GetValue(); if (aShapeBase.IsNull()) { if (aCIBN) delete aCIBN; Standard_NullObject::Raise("MakePipe aborted : null base argument"); } // Make copy to prevent modifying of base object: 0021525 BRepBuilderAPI_Copy Copy (aShapeBase); if (Copy.IsDone()) aShapeBase = Copy.Shape(); TopoDS_Shape aProf; if (aShapeBase.ShapeType() == TopAbs_VERTEX) { aProf = aShapeBase; } else if (aShapeBase.ShapeType() == TopAbs_EDGE) { aProf = BRepBuilderAPI_MakeWire(TopoDS::Edge(aShapeBase)).Shape(); } else if (aShapeBase.ShapeType() == TopAbs_WIRE) { aProf = aShapeBase; } else if (aShapeBase.ShapeType() == TopAbs_FACE) { TopExp_Explorer wexp (aShapeBase,TopAbs_WIRE); aProf = wexp.Current(); } else { Standard_TypeMismatch::Raise ("MakePipe aborted : invalid type of base"); } BRepOffsetAPI_MakePipeShell PipeBuilder (aWirePath); PipeBuilder.Add(aProf); if (aShapeVec.IsNull()) { if (aCIBN) delete aCIBN; Standard_NullObject::Raise ("MakePipe aborted : null vector argument"); } if (aShapeVec.ShapeType() != TopAbs_EDGE) Standard_TypeMismatch::Raise ("MakePipe aborted: invalid type of vector"); TopoDS_Edge anEdge = TopoDS::Edge(aShapeVec); TopoDS_Vertex V1, V2; TopExp::Vertices(anEdge, V1, V2, Standard_True); if (V1.IsNull() || V2.IsNull()) Standard_NullObject::Raise ("MakePipe aborted: vector is not defined"); gp_Vec aVec(BRep_Tool::Pnt(V1), BRep_Tool::Pnt(V2)); gp_Dir BiNormal(aVec); PipeBuilder.SetMode(BiNormal); Standard_Boolean isDone = BuildPipeShell(PipeBuilder); if (isDone && aShapeBase.ShapeType() == TopAbs_FACE) { PipeBuilder.MakeSolid(); } return PipeBuilder.Shape(); } //======================================================================= //function : Execute //purpose : //======================================================================= Standard_Integer GEOMImpl_PipeDriver::Execute (TFunction_Logbook& log) const { if (Label().IsNull()) return 0; Handle(GEOM_Function) aFunction = GEOM_Function::GetFunction(Label()); Standard_Integer aType = aFunction->GetType(); GEOMImpl_IPipe* aCI = 0; 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 if (aType == PIPE_BI_NORMAL_ALONG_VECTOR) aCI = new GEOMImpl_IPipeBiNormal (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()) { MESSAGE ("Driver : path is null"); if (aCI) delete aCI; Standard_NullObject::Raise("MakePipe aborted : null path argument"); } // Get path contour bool isOk = false; if (aShapePath.ShapeType() == TopAbs_COMPOUND) { TopTools_SequenceOfShape anEdges; TopExp_Explorer anExp; BRep_Builder B; TopoDS_Wire W; B.MakeWire(W); for (anExp.Init(aShapePath, TopAbs_EDGE); anExp.More(); anExp.Next()) { B.Add(W, anExp.Current()); isOk = true; } if (isOk) aWirePath = W; } else if (aShapePath.ShapeType() == TopAbs_WIRE) { aWirePath = TopoDS::Wire(aShapePath); isOk = true; } else { if (aShapePath.ShapeType() == TopAbs_EDGE) { TopoDS_Edge anEdge = TopoDS::Edge(aShapePath); aWirePath = BRepBuilderAPI_MakeWire(anEdge); isOk = true; } } if (!isOk) { if (aCI) delete aCI; Standard_TypeMismatch::Raise("MakePipe aborted : path shape is neither a wire nor an edge"); } } TopoDS_Shape aShape; if (aType == PIPE_BASE_PATH) { Handle(GEOM_Function) aRefBase = aCI->GetBase(); TopoDS_Shape aShapeBase; // Make copy to prevent modifying of base object 0020766 : EDF 1320 BRepBuilderAPI_Copy Copy(aRefBase->GetValue()); if (Copy.IsDone()) aShapeBase = Copy.Shape(); if (aShapeBase.IsNull()) { if (aCI) delete aCI; Standard_NullObject::Raise("MakePipe aborted : null base argument"); } // Make pipe if (aShapeBase.ShapeType() == TopAbs_EDGE || aShapeBase.ShapeType() == TopAbs_WIRE) { TopoDS_Wire Profile; if (aShapeBase.ShapeType() == TopAbs_WIRE) Profile = TopoDS::Wire(aShapeBase); else { BRep_Builder BB; BB.MakeWire(Profile); BB.Add(Profile, aShapeBase); } BRepOffsetAPI_MakePipeShell Sweep (aWirePath); BRepBuilderAPI_MakeFace FaceBuilder (aWirePath, Standard_True); //to find the plane of spine if (FaceBuilder.IsDone()) Sweep.SetMode(FaceBuilder.Face()); Sweep.Add(Profile); Standard_Boolean isDone = BuildPipeShell(Sweep); if (!isDone) { if (aCI) delete aCI; Standard_ConstructionError::Raise("MakePipeShell failed"); } else aShape = Sweep.Shape(); //result is good } else { GeomFill_Trihedron theBestMode = EvaluateBestSweepMode(aWirePath); BRepOffsetAPI_MakePipe aMkPipe(aWirePath, aShapeBase, theBestMode); if (aMkPipe.IsDone()) { aShape = aMkPipe.Shape(); } else if (theBestMode != GeomFill_IsDiscreteTrihedron) { // Try to use Descrete Trihedron mode. BRepOffsetAPI_MakePipe aMkPipeDescrete (aWirePath, aShapeBase, GeomFill_IsDiscreteTrihedron); if (aMkPipeDescrete.IsDone()) { aShape = aMkPipeDescrete.Shape(); } } } } //building pipe with different sections else if (aType == PIPE_DIFFERENT_SECTIONS) { GEOMImpl_IPipeDiffSect* aCIDS = (GEOMImpl_IPipeDiffSect*)aCI; Handle(TColStd_HSequenceOfTransient) aBasesObjs = aCIDS->GetBases (); Handle(TColStd_HSequenceOfTransient) aLocObjs = aCIDS->GetLocations (); Standard_Boolean aWithContact = (aCIDS->GetWithContactMode()); Standard_Boolean aWithCorrect = (aCIDS->GetWithCorrectionMode()); if (aCI) { delete aCI; aCI = 0; } Standard_Integer nbBases = aBasesObjs->Length(); Standard_Integer nbLocs = (aLocObjs.IsNull() ? 0 : aLocObjs->Length()); Handle(TopTools_HSequenceOfShape) aHSeqBases = new TopTools_HSequenceOfShape; Handle(TopTools_HSequenceOfShape) aHSeqLocs = new TopTools_HSequenceOfShape; Standard_Integer i; for (i = 1; 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; if (aRefBase->GetValue().IsNull()) continue; aHSeqBases->Append(aRefBase->GetValue()); } for (i = 1; i <= nbLocs; 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; aHSeqLocs->Append(aShapeLoc); } aShape = CreatePipeWithDifferentSections(aWirePath, aHSeqBases, aHSeqLocs, aWithContact, aWithCorrect); } //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); } //building a pipe with constant bi-normal along given vector else if (aType == PIPE_BI_NORMAL_ALONG_VECTOR) { aShape = CreatePipeBiNormalAlongVector(aWirePath, 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"); } if (aType != PIPE_BASE_PATH && aType != PIPE_SHELLS_WITHOUT_PATH) { TopExp_Explorer anExpV (aShape, TopAbs_VERTEX); if (anExpV.More()) { Standard_Real aVertMaxTol = -RealLast(); for (; anExpV.More(); anExpV.Next()) { TopoDS_Vertex aVertex = TopoDS::Vertex(anExpV.Current()); Standard_Real aTol = BRep_Tool::Tolerance(aVertex); if (aTol > aVertMaxTol) aVertMaxTol = aTol; } aVertMaxTol += Precision::Confusion(); aShape = GEOMImpl_GlueDriver::GlueFaces(aShape, aVertMaxTol, Standard_True); //aShape = GEOMImpl_GlueDriver::GlueFaces(aShape, Precision::Confusion(), Standard_True); } } TopoDS_Shape aRes = GEOMUtils::CompsolidToCompound(aShape); aFunction->SetValue(aRes); log.SetTouched(Label()); return 1; } //================================================================================ /*! * \brief Returns a name of creation operation and names and values of creation parameters */ //================================================================================ bool GEOMImpl_PipeDriver:: GetCreationInformation(std::string& theOperationName, std::vector& theParams) { if (Label().IsNull()) return 0; Handle(GEOM_Function) function = GEOM_Function::GetFunction(Label()); Standard_Integer aType = function->GetType(); switch ( aType ) { case PIPE_BASE_PATH: { theOperationName = "PIPE"; GEOMImpl_IPipe aCI( function ); AddParam( theParams, "Base Object", aCI.GetBase() ); AddParam( theParams, "Path Object", aCI.GetPath() ); break; } case PIPE_BI_NORMAL_ALONG_VECTOR: { theOperationName = "PIPE"; GEOMImpl_IPipeBiNormal aCI( function ); AddParam( theParams, "Base Object", aCI.GetBase() ); AddParam( theParams, "Path Object", aCI.GetPath() ); AddParam( theParams, "BiNormal", aCI.GetVector() ); break; } case PIPE_DIFFERENT_SECTIONS: { theOperationName = "PIPE"; GEOMImpl_IPipeDiffSect aCI( function ); AddParam( theParams, "Bases", aCI.GetBases() ); AddParam( theParams, "Locations", aCI.GetLocations() ); AddParam( theParams, "Path", aCI.GetPath() ); AddParam( theParams, "With contact", aCI.GetWithContactMode() ); AddParam( theParams, "With correction", aCI.GetWithCorrectionMode() ); break; } case PIPE_SHELL_SECTIONS: { theOperationName = "PIPE"; GEOMImpl_IPipeShellSect aCI( function ); AddParam( theParams, "Bases", aCI.GetBases() ); AddParam( theParams, "Sub-Bases", aCI.GetSubBases() ); AddParam( theParams, "Locations", aCI.GetLocations() ); AddParam( theParams, "Path", aCI.GetPath() ); AddParam( theParams, "With contact", aCI.GetWithContactMode() ); AddParam( theParams, "With correction", aCI.GetWithCorrectionMode() ); break; } case PIPE_SHELLS_WITHOUT_PATH: { theOperationName = "PIPE"; // MakePipeShellsWithoutPath GEOMImpl_IPipeShellSect aCI( function ); AddParam( theParams, "Bases", aCI.GetBases() ); AddParam( theParams, "Locations", aCI.GetLocations() ); break; } default: return false; } return true; } IMPLEMENT_STANDARD_HANDLE (GEOMImpl_PipeDriver,GEOM_BaseDriver); IMPLEMENT_STANDARD_RTTIEXT (GEOMImpl_PipeDriver,GEOM_BaseDriver);