X-Git-Url: http://git.salome-platform.org/gitweb/?a=blobdiff_plain;f=src%2FGEOMImpl%2FGEOMImpl_PipeDriver.cxx;h=9812da16af8b6518df08ad6fb722c75c6fe71e5c;hb=7965cd72610905458b4f389e82212349e7061aec;hp=54b81eddc60329ebb70230f06731c275844702c4;hpb=d3dd282390888d7dc091ba2c2ffe7923bd7458e6;p=modules%2Fgeom.git diff --git a/src/GEOMImpl/GEOMImpl_PipeDriver.cxx b/src/GEOMImpl/GEOMImpl_PipeDriver.cxx index 54b81eddc..9812da16a 100644 --- a/src/GEOMImpl/GEOMImpl_PipeDriver.cxx +++ b/src/GEOMImpl/GEOMImpl_PipeDriver.cxx @@ -1,36 +1,119 @@ +// Copyright (C) 2007-2012 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. +// +// 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 -using namespace std; -#include "GEOMImpl_PipeDriver.hxx" -#include "GEOMImpl_IPipe.hxx" -#include "GEOMImpl_Types.hxx" -#include "GEOM_Function.hxx" +#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" + +////////////////////////////////////////////////////////////////////////// +// Uncomment below macro to perform gluing in the end of MakePipe operation +// as fix of issue 0020207. +////////////////////////////////////////////////////////////////////////// +//#define GLUE_0020207 + + //======================================================================= //function : GetID //purpose : //======================================================================= const Standard_GUID& GEOMImpl_PipeDriver::GetID() { - static Standard_GUID aPipeDriver("FF1BBB19-5D14-4df2-980B-3A668264EA16"); + static Standard_GUID aPipeDriver ("FF1BBB19-5D14-4df2-980B-3A668264EA16"); return aPipeDriver; } - //======================================================================= //function : GEOMImpl_PipeDriver //purpose : @@ -39,84 +122,2411 @@ 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"<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_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 + 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 + 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; + 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*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); + 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"); + } + aBuilder.Build(); + 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); + 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"); + } + aBuilder.Build(); + 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); + + 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; + 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.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; + } + } + + 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); + 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 = 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); + 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; 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); + PipeBuilder.Build(); + if (aShapeBase.ShapeType() == TopAbs_FACE) { + PipeBuilder.MakeSolid(); + } + + return PipeBuilder.Shape(); +} + //======================================================================= //function : Execute //purpose : //======================================================================= -Standard_Integer GEOMImpl_PipeDriver::Execute(TFunction_Logbook& log) const +Standard_Integer GEOMImpl_PipeDriver::Execute (TFunction_Logbook& log) const { if (Label().IsNull()) return 0; Handle(GEOM_Function) aFunction = GEOM_Function::GetFunction(Label()); - - GEOMImpl_IPipe aCI (aFunction); Standard_Integer aType = aFunction->GetType(); - TopoDS_Shape aShape; + 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; - if (aType == PIPE_BASE_PATH) { - Handle(GEOM_Function) aRefBase = aCI.GetBase(); - Handle(GEOM_Function) aRefPath = aCI.GetPath(); - TopoDS_Shape aShapeBase = aRefBase->GetValue(); + TopoDS_Wire aWirePath; + if (aType != PIPE_SHELLS_WITHOUT_PATH) { + // working with path + Handle(GEOM_Function) aRefPath = aCI->GetPath(); TopoDS_Shape aShapePath = aRefPath->GetValue(); - if (aShapeBase.IsNull() || aShapePath.IsNull()) { - Standard_NullObject::Raise("MakePipe aborted : null shape argument"); + + if (aShapePath.IsNull()) { + MESSAGE ("Driver : path is null"); + if (aCI) delete aCI; + Standard_NullObject::Raise("MakePipe aborted : null path argument"); } // Get path contour - TopoDS_Wire aWire; - if (aShapePath.ShapeType() == TopAbs_WIRE) { - aWire = TopoDS::Wire(aShapePath); - } else { + 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); - aWire = BRepBuilderAPI_MakeWire(anEdge); - } else { - Standard_TypeMismatch::Raise("MakePipe aborted : path shape is neither a wire nor an edge"); + 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 - aShape = BRepOffsetAPI_MakePipe(aWire, aShapeBase); + 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); + Sweep.Build(); + + if (!Sweep.IsDone()) + { + if (aCI) delete aCI; + Standard_ConstructionError::Raise("MakePipeShell failed"); + } + else + aShape = Sweep.Shape(); //result is good + + } + else + aShape = BRepOffsetAPI_MakePipe(aWirePath, aShapeBase); } - else { + + //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()) { - Standard_ConstructionError::Raise("Algorithm have produced an invalid shape result"); + 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"); } - aFunction->SetValue(aShape); + // Glue (for bug 0020207) + // No gluing is needed as the bug 0020207 is fixed in OCCT. +#ifdef GLUE_0020207 + 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); + } +#endif - log.SetTouched(Label()); + TopoDS_Shape aRes = GEOMUtils::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); + 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); + 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); - + 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); + sizeof(GEOMImpl_PipeDriver), + 1, + (Standard_Address)_Ancestors, + (Standard_Address)NULL); return _aType; } @@ -135,5 +2545,5 @@ const Handle(GEOMImpl_PipeDriver) Handle(GEOMImpl_PipeDriver)::DownCast(const Ha } } - return _anOtherObject ; + return _anOtherObject; }