X-Git-Url: http://git.salome-platform.org/gitweb/?a=blobdiff_plain;f=src%2FGEOMImpl%2FGEOMImpl_PipeDriver.cxx;h=d84397a4c72512f8fdd7c2b85dbf4b3c4b29d629;hb=a9fe5759c52e7f225c6b1403bf93fc97c10874b9;hp=3f0f0c986af127b8973e557244905f380c18849c;hpb=b5261a981848dacc6b428a95d0e7731ebb8fdc91;p=modules%2Fgeom.git diff --git a/src/GEOMImpl/GEOMImpl_PipeDriver.cxx b/src/GEOMImpl/GEOMImpl_PipeDriver.cxx index 3f0f0c986..d84397a4c 100644 --- a/src/GEOMImpl/GEOMImpl_PipeDriver.cxx +++ b/src/GEOMImpl/GEOMImpl_PipeDriver.cxx @@ -1,4 +1,4 @@ -// Copyright (C) 2007-2014 CEA/DEN, EDF R&D, OPEN CASCADE +// Copyright (C) 2007-2016 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 @@ -38,16 +38,15 @@ #include #include #include -#include -#include #include #include #include #include +#include #include #include -#include +#include #include #include #include @@ -65,11 +64,13 @@ #include #include #include +#include #include #include #include #include #include +#include #include @@ -101,6 +102,29 @@ #include "utilities.h" +#define GROUP_DOWN 0 +#define GROUP_UP 1 +#define GROUP_SIDE1 2 +#define GROUP_SIDE2 3 +#define GROUP_OTHER 4 + +static const Standard_Real TolPipeSurf = 5.e-4; + +static bool FillGroups(const TopTools_SequenceOfShape *theGroups, + const TopTools_IndexedMapOfShape &theIndices, + Handle(TColStd_HArray1OfInteger) *theGroupIds); + +static void StoreGroups(GEOMImpl_IPipe *theCI, + Handle(TColStd_HArray1OfInteger) *theGroups); + +// after OCCT improvement +static bool DoGroups1(const TopoDS_Shape &theProfile, + BRepOffsetAPI_MakePipeShell &theSweep, + TopTools_SequenceOfShape *theGroups); + +static bool CreateGroups1(const TopoDS_Shape &theProfile, + BRepOffsetAPI_MakePipeShell &theSweep, + GEOMImpl_IPipe *theCI); //======================================================================= //function : GetID @@ -122,7 +146,7 @@ GEOMImpl_PipeDriver::GEOMImpl_PipeDriver() //======================================================================= //function : EvaluateBestSweepMode -//purpose : auxilary for right call of MakePipe and MakePipeShell +//purpose : auxiliary for right call of MakePipe and MakePipeShell //======================================================================= static GeomFill_Trihedron EvaluateBestSweepMode(const TopoDS_Shape& Spine) { @@ -152,10 +176,33 @@ static GeomFill_Trihedron EvaluateBestSweepMode(const TopoDS_Shape& Spine) 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.SetForceApproxC1(Standard_True); + + theBuilder.Build(); + + Standard_Boolean isDone = theBuilder.IsDone(); + + if (!isDone || + theBuilder.ErrorOnSurface() > TolPipeSurf) { + // Try to use Descrete Trihedron mode. + theBuilder.SetDiscreteMode(); + theBuilder.Build(); + isDone = theBuilder.IsDone(); + } + + return isDone; +} //======================================================================= //function : FillForOtherEdges -//purpose : auxilary for CreatePipeForShellSections() +//purpose : auxiliary for CreatePipeForShellSections() //======================================================================= static bool FillForOtherEdges(const TopoDS_Shape& F1, const TopoDS_Shape& E1, @@ -231,7 +278,7 @@ static bool FillForOtherEdges(const TopoDS_Shape& F1, //======================================================================= //function : FillCorrespondingEdges -//purpose : auxilary for CreatePipeForShellSections() +//purpose : auxiliary for CreatePipeForShellSections() //======================================================================= static bool FillCorrespondingEdges(const TopoDS_Shape& FS1, const TopoDS_Shape& FS2, @@ -256,17 +303,10 @@ static bool FillCorrespondingEdges(const TopoDS_Shape& FS1, if (!aBuilder.IsReady()) { return false; } - aBuilder.Build(); + + BuildPipeShell(aBuilder); + TopoDS_Shape aShape = aBuilder.Shape(); - /* - TopoDS_Compound C; - BRep_Builder B; - B.MakeCompound(C); - B.Add(C,aShape); - B.Add(C,FS1); - B.Add(C,FS2); - BRepTools::Write(C,"/dn02/users_Linux/skl/work/Bugs/14857/comp.brep"); - */ ShapeAnalysis_Edge sae; double tol = Max(BRep_Tool::Tolerance(TopoDS::Face(FS1)), BRep_Tool::Tolerance(TopoDS::Face(FS2))); @@ -366,7 +406,7 @@ static bool FillCorrespondingEdges(const TopoDS_Shape& FS1, //======================================================================= //function : FillCorrespondingEdges -//purpose : auxilary for CreatePipeShellsWithoutPath() +//purpose : auxiliary for CreatePipeShellsWithoutPath() //======================================================================= static bool FillCorrespondingEdges(const TopoDS_Shape& FS1, const TopoDS_Shape& FS2, @@ -468,7 +508,7 @@ static bool FillCorrespondingEdges(const TopoDS_Shape& FS1, //======================================================================= //function : FindNextPairOfFaces -//purpose : auxilary for CreatePipeForShellSections() +//purpose : auxiliary for CreatePipeForShellSections() //======================================================================= static void FindNextPairOfFaces(const TopoDS_Shape& aCurFace, TopTools_IndexedDataMapOfShapeListOfShape& aMapEdgeFaces1, @@ -529,7 +569,7 @@ static void FindNextPairOfFaces(const TopoDS_Shape& aCurFace, bool stat = FillForOtherEdges(F1other,E1,V1,FF); if (!stat) { if (aCI) delete aCI; - Standard_ConstructionError::Raise("FindNextPairOfFaces: Can not mapping other egdes"); + Standard_ConstructionError::Raise("FindNextPairOfFaces: Can not map other edges"); } FindNextPairOfFaces(F1other, aMapEdgeFaces1, aMapEdgeFaces2, FF, aCI); @@ -538,7 +578,7 @@ static void FindNextPairOfFaces(const TopoDS_Shape& aCurFace, //======================================================================= //function : FindFirstPairFaces -//purpose : auxilary for Execute() +//purpose : auxiliary for Execute() //======================================================================= static void FindFirstPairFaces(const TopoDS_Shape& S1, const TopoDS_Shape& S2, TopoDS_Vertex& V1, TopoDS_Vertex& V2, @@ -656,16 +696,54 @@ static void FindFirstPairFaces(const TopoDS_Shape& S1, const TopoDS_Shape& S2, FS2 = Fs(numface); } +//======================================================================= +//function : RemoveFaces +//purpose : This function returns theShapeFrom without faces of the shape +// theFacesToRm. It returns a shell if theShapeFrom is a solid or +// a compound otherwise. Auxiliary for CreatePipeWithDifferentSections +// method. +//======================================================================= +static TopoDS_Shape RemoveFaces(const TopoDS_Shape &theShapeFrom, + const TopoDS_Shape &theFacesToRm) +{ + TopTools_IndexedMapOfShape aMapFaces; + TopExp_Explorer anExp(theShapeFrom, TopAbs_FACE); + BRep_Builder aBuilder; + TopoDS_Shape aResult; + + if (theShapeFrom.ShapeType() == TopAbs_SOLID) { + // Create shell + aBuilder.MakeShell(TopoDS::Shell(aResult)); + } else { + // Create compound + aBuilder.MakeCompound(TopoDS::Compound(aResult)); + } + + TopExp::MapShapes(theFacesToRm, TopAbs_FACE, aMapFaces); + + for (; anExp.More(); anExp.Next()) { + const TopoDS_Shape &aFace = anExp.Current(); + + if (!aMapFaces.Contains(aFace)) { + aBuilder.Add(aResult, aFace); + } + } + + return aResult; +} + //======================================================================= //function : CreatePipeWithDifferentSections //purpose : //======================================================================= TopoDS_Shape GEOMImpl_PipeDriver::CreatePipeWithDifferentSections - (const TopoDS_Wire& theWirePath, - const Handle(TopTools_HSequenceOfShape) theHSeqBases, - const Handle(TopTools_HSequenceOfShape) theHSeqLocs, - const Standard_Boolean theWithContact, - const Standard_Boolean theWithCorrect) + (const TopoDS_Wire &theWirePath, + const Handle(TopTools_HSequenceOfShape) theHSeqBases, + const Handle(TopTools_HSequenceOfShape) theHSeqLocs, + const Standard_Boolean theWithContact, + const Standard_Boolean theWithCorrect, + const Standard_Boolean IsBySteps, + Handle(TColStd_HArray1OfInteger) *theGroups) { TopoDS_Shape aShape; @@ -841,7 +919,7 @@ TopoDS_Shape GEOMImpl_PipeDriver::CreatePipeWithDifferentSections } } if (nbEdges we have to update WirePath + // one of edges was split => we have to update WirePath BRep_Builder B; TopoDS_Wire W; B.MakeWire(W); @@ -852,53 +930,90 @@ TopoDS_Shape GEOMImpl_PipeDriver::CreatePipeWithDifferentSections } } - // 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; - } + + if (IsBySteps) { + // Fill SplitEdgeNums and SplitLocNums with intermediate location indices + // and corresponding edge indices. + Standard_Integer i = 1; + Standard_Integer j; + TopoDS_Vertex aVert; + gp_Pnt aP; + + for (j = 2; j < aSeqLocs.Length(); j++) { + SplitLocNums.Append(j); + aVert = TopoDS::Vertex(aSeqLocs.Value(j)); + aP = BRep_Tool::Pnt(aVert); + + while (i < Edges.Length()) { + Standard_Real aFp; + Standard_Real aLp; + TopoDS_Edge anEdge = TopoDS::Edge(Edges.Value(i)); + Standard_Real aTol = BRep_Tool::Tolerance(anEdge); + Handle(Geom_Curve) aC = BRep_Tool::Curve(anEdge, aFp, aLp); + gp_Pnt aPLast; + + aC->D0(aLp, aPLast); + i++; + + if (aP.Distance(aPLast) < aTol) { + SplitEdgeNums.Append(i - 1); + break; } } + } + } else { + // 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; + } + 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; + } } + bool isCreateGroups = (theGroups != NULL); + if (SplitLocNums.Length()==SplitEdgeNums.Length() && SplitEdgeNums.Length()>0) { - TopTools_SequenceOfShape aSeqRes; + TopTools_SequenceOfShape aSeqRes; + TopTools_DataMapOfShapeSequenceOfShape aMapResGroups[5]; + Standard_Integer iGrp; int nn, num1 = 1, num2 = 1; for (nn=1; nn<=SplitEdgeNums.Length(); nn++) { // create wirepath and sequences of shapes @@ -930,9 +1045,42 @@ TopoDS_Shape GEOMImpl_PipeDriver::CreatePipeWithDifferentSections if (!aBuilder.IsReady()) { Standard_ConstructionError::Raise("Invalid input data for building PIPE: bases are invalid"); } - aBuilder.Build(); + + Standard_Boolean isDone = BuildPipeShell(aBuilder); + + if (isDone && NeedCreateSolid && nn == 1) { + // Make solid for the first step. + isDone = aBuilder.MakeSolid(); + } + + if (!isDone) { + Standard_ConstructionError::Raise("Pipe construction failure"); + } + TopoDS_Shape resShape = aBuilder.Shape(); + + if (NeedCreateSolid && nn == 1) { + // Remove top lid from the result. + resShape = RemoveFaces(resShape, aBuilder.LastShape()); + } + aSeqRes.Append(resShape); + + // Create groups. + if (isCreateGroups) { + // Make groups. + TopTools_SequenceOfShape aGroups[5]; + + TopoDS_Shape aProfile = aTmpSeqBases.Value(1); + if (!DoGroups1(aProfile, aBuilder, aGroups)) { + Standard_ConstructionError::Raise("Generate groups failure"); + } + + // Get shapes from all groups. + for (iGrp = 0; iGrp < 5; ++iGrp) { + aMapResGroups[iGrp].Bind(resShape, aGroups[iGrp]); + } + } } // create wirepath and sequences of shapes for last part BRep_Builder B; @@ -961,9 +1109,42 @@ TopoDS_Shape GEOMImpl_PipeDriver::CreatePipeWithDifferentSections if (!aBuilder.IsReady()) { Standard_ConstructionError::Raise("Invalid input data for building PIPE: bases are invalid"); } - aBuilder.Build(); + + Standard_Boolean isDone = BuildPipeShell(aBuilder); + + if (isDone && NeedCreateSolid) { + isDone = aBuilder.MakeSolid(); + } + + if (!isDone) { + Standard_ConstructionError::Raise("Pipe construction failure"); + } + TopoDS_Shape resShape = aBuilder.Shape(); + + if (NeedCreateSolid) { + // Remove bottom lid from the result. + resShape = RemoveFaces(resShape, aBuilder.FirstShape()); + } + aSeqRes.Append(resShape); + + // Create groups. + if (isCreateGroups) { + // Make groups. + TopTools_SequenceOfShape aGroups[5]; + + TopoDS_Shape aProfile = aTmpSeqBases.Value(1); + if (!DoGroups1(aProfile, aBuilder, aGroups)) { + Standard_ConstructionError::Raise("Generate groups failure"); + } + + // Get shapes from all groups. + for (iGrp = 0; iGrp < 5; ++iGrp) { + aMapResGroups[iGrp].Bind(resShape, aGroups[iGrp]); + } + } + // make sewing for result Handle(BRepBuilderAPI_Sewing) aSewing = new BRepBuilderAPI_Sewing; aSewing->SetTolerance(Precision::Confusion()); @@ -975,6 +1156,78 @@ TopoDS_Shape GEOMImpl_PipeDriver::CreatePipeWithDifferentSections } aSewing->Perform(); aShape = aSewing->SewedShape(); + + if (NeedCreateSolid && aShape.ShapeType() == TopAbs_SHELL) { + // Build a solid. + BRepBuilderAPI_MakeSolid aMkSolid; + + aMkSolid.Add(TopoDS::Shell(aShape)); + + if (!aMkSolid.IsDone()) { + Standard_ConstructionError::Raise("Can't create solid pipe"); + } + + TopoDS_Solid aSolid = aMkSolid.Solid(); + BRepClass3d_SolidClassifier aSC(aSolid); + + aSC.PerformInfinitePoint(Precision::Confusion()); + + if (aSC.State() == TopAbs_IN) { + aShape = aSolid.Reversed(); + } else { + aShape = aSolid; + } + } + + if (isCreateGroups) { + // Replase Group shapes by modified ones. + TopTools_SequenceOfShape aSeqGroups[5]; + + // For each group. + for (iGrp = 0; iGrp < 5; ++iGrp) { + // For each pipe + for (i = 1; i <= aSeqRes.Length(); ++i) { + if (iGrp == GROUP_DOWN && i > 1) { + // For DOWN group we use only the first pipe. + continue; + } + + if (iGrp == GROUP_UP && i < aSeqRes.Length()) { + // For UP group we use only the last pipe. + continue; + } + + const TopTools_SequenceOfShape &aShapes = + aMapResGroups[iGrp].Find(aSeqRes.Value(i)); + Standard_Integer j; + + // For each sub-shape of pipe + for (j = 1; j <= aShapes.Length(); ++j) { + const TopoDS_Shape &aGrpShape = aShapes.Value(j); + + if (aSewing->IsModifiedSubShape(aGrpShape)) { + // Use the shape modified by sewing. + const TopoDS_Shape &aModifGrpShape = + aSewing->ModifiedSubShape(aGrpShape); + + aSeqGroups[iGrp].Append(aModifGrpShape); + } else { + // Use the shape as it is. + aSeqGroups[iGrp].Append(aGrpShape); + } + } + } + } + + // Fill groups + TopTools_IndexedMapOfShape anIndices; + + TopExp::MapShapes(aShape, anIndices); + + if (!FillGroups(aSeqGroups, anIndices, theGroups)) { + Standard_ConstructionError::Raise("Generate groups failure"); + } + } } else { // old implementation without splitting @@ -1014,9 +1267,7 @@ TopoDS_Shape GEOMImpl_PipeDriver::CreatePipeWithDifferentSections aBuilder.SetTolerance(aTolConf, aTolConf, aTolAng); - aBuilder.Build(); - - Standard_Boolean isDone = aBuilder.IsDone(); + Standard_Boolean isDone = BuildPipeShell(aBuilder); if (isDone && NeedCreateSolid) { isDone = aBuilder.MakeSolid(); @@ -1026,6 +1277,27 @@ TopoDS_Shape GEOMImpl_PipeDriver::CreatePipeWithDifferentSections Standard_ConstructionError::Raise("Pipe construction failure"); } aShape = aBuilder.Shape(); + + if (isCreateGroups) { + // Make groups. + TopTools_SequenceOfShape aSeqGroups[5]; + + TopoDS_Shape aProfile = usedBases.Value(1); + if (!DoGroups1(aProfile, aBuilder, aSeqGroups)) { + Standard_ConstructionError::Raise("Generate groups failure"); + } + + // Fill the groups. + //Handle(TColStd_HArray1OfInteger) aGroupIds[5]; + TopTools_IndexedMapOfShape anIndices; + const TopoDS_Shape aResult = aBuilder.Shape(); + + TopExp::MapShapes(aResult, anIndices); + + if (!FillGroups(aSeqGroups, anIndices, theGroups)) { + Standard_ConstructionError::Raise("Generate groups failure"); + } + } aSeqFaces.Append(aShape); for (j = 1; j <=usedBases.Length(); j++) aBuilder.Delete(usedBases.Value(j)); @@ -1037,13 +1309,11 @@ TopoDS_Shape GEOMImpl_PipeDriver::CreatePipeWithDifferentSections //======================================================================= //function : CreatePipeForShellSections -//purpose : auxilary for Execute() +//purpose : auxiliary for Execute() //======================================================================= static TopoDS_Shape CreatePipeForShellSections(const TopoDS_Wire& aWirePath, GEOMImpl_IPipe* aCI) { - //cout<<"CreatePipeForShellSections"<GetLocations(); Standard_Boolean aWithContact = (aCIDS->GetWithContactMode()); Standard_Boolean aWithCorrect = (aCIDS->GetWithCorrectionMode()); + Standard_Boolean isGenerateGroups = aCIDS->GetGenerateGroups(); Standard_Integer nbBases = aBasesObjs->Length(), nbSubBases = (aSubBasesObjs.IsNull() ? 0 :aSubBasesObjs->Length()), @@ -1067,8 +1338,6 @@ static TopoDS_Shape CreatePipeForShellSections(const TopoDS_Wire& aWirePath, 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); @@ -1240,7 +1509,6 @@ static TopoDS_Shape CreatePipeForShellSections(const TopoDS_Wire& aWirePath, for (; i<=Edges.Length(); i++) B.Add(W,Edges.Value(i)); Wires.Append(W); - //cout<<"Wires.Length()="<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(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; @@ -1512,8 +1629,25 @@ static TopoDS_Shape CreatePipeForShellSections(const TopoDS_Wire& aWirePath, if (aCI) delete aCI; Standard_ConstructionError::Raise("Invalid input data for building PIPE: bases are invalid"); } - aBuilder.Build(); - TopoDS_Shape aShape = aBuilder.Shape(); + + BuildPipeShell(aBuilder); + + TopoDS_Shape aShape = aBuilder.Shape(); + TopTools_SequenceOfShape aLocalGroups[5]; + + // Create groups. + if (isGenerateGroups) { + // Make groups. + if (!DoGroups1(aWire1, aBuilder, aLocalGroups)) { + if (aCI) delete aCI; + Standard_ConstructionError::Raise("Generate groups failure"); + } + + // Clear the groups Down and Up. + aLocalGroups[GROUP_DOWN].Clear(); + aLocalGroups[GROUP_UP].Clear(); + } + TopoDS_Shell aShell; B.MakeShell(aShell); for (anExp.Init(aShape, TopAbs_FACE); anExp.More(); anExp.Next()) { @@ -1521,9 +1655,17 @@ static TopoDS_Shape CreatePipeForShellSections(const TopoDS_Wire& aWirePath, } for (anExp.Init(aShBase1, TopAbs_FACE); anExp.More(); anExp.Next()) { B.Add(aShell,anExp.Current()); + + if (isGenerateGroups && i == 1) { + aLocalGroups[GROUP_DOWN].Append(anExp.Current()); + } } for (anExp.Init(aShBase2, TopAbs_FACE); anExp.More(); anExp.Next()) { B.Add(aShell,anExp.Current()); + + if (isGenerateGroups && i == nbBases - 1) { + aLocalGroups[GROUP_UP].Append(anExp.Current()); + } } // make sewing for this shell Handle(BRepBuilderAPI_Sewing) aSewing = new BRepBuilderAPI_Sewing; @@ -1556,6 +1698,30 @@ static TopoDS_Shape CreatePipeForShellSections(const TopoDS_Wire& aWirePath, else { B.Add(aComp,aShell); } + + if (isGenerateGroups) { + Standard_Integer iGrp; + + for (iGrp = 0; iGrp < 5; ++iGrp) { + Standard_Integer j; + + // For each sub-shape of pipe + for (j = 1; j <= aLocalGroups[iGrp].Length(); ++j) { + const TopoDS_Shape &aGrpShape = aLocalGroups[iGrp].Value(j); + + if (aSewing->IsModifiedSubShape(aGrpShape)) { + // Use the shape modified by sewing. + const TopoDS_Shape &aModifGrpShape = + aSewing->ModifiedSubShape(aGrpShape); + + aGroups[iGrp].Append(aModifGrpShape); + } else { + // Use the shape as it is. + aGroups[iGrp].Append(aGrpShape); + } + } + } + } } } else { @@ -1658,7 +1824,7 @@ static TopoDS_Shape CreatePipeForShellSections(const TopoDS_Wire& aWirePath, bool stat = FillForOtherEdges(FS1,E1,V11,FF); if (!stat) { if (aCI) delete aCI; - Standard_ConstructionError::Raise("FindForOtherEdges: Can not mapping other egdes"); + Standard_ConstructionError::Raise("FindForOtherEdges: Can not map other edges"); } } @@ -1750,8 +1916,33 @@ static TopoDS_Shape CreatePipeForShellSections(const TopoDS_Wire& aWirePath, if (aCI) delete aCI; Standard_ConstructionError::Raise("Invalid input data for building PIPE: bases are invalid"); } - aBuilder.Build(); - TopoDS_Shape aShape = aBuilder.Shape(); + + BuildPipeShell(aBuilder); + + TopoDS_Shape aShape = aBuilder.Shape(); + TopTools_SequenceOfShape aLocalGroups[5]; + + // Create groups. + if (isGenerateGroups) { + // Make groups. + if (!DoGroups1(aWire1, aBuilder, aLocalGroups)) { + if (aCI) delete aCI; + Standard_ConstructionError::Raise("Generate groups failure"); + } + + // Clear the groups Down and Up. + aLocalGroups[GROUP_DOWN].Clear(); + aLocalGroups[GROUP_UP].Clear(); + + if (i == 1) { + aLocalGroups[GROUP_DOWN].Append(F1); + } + + if (i == nbBases - 1) { + aLocalGroups[GROUP_UP].Append(F2); + } + } + TopoDS_Shell aShell; B.MakeShell(aShell); for (anExp.Init(aShape, TopAbs_FACE); anExp.More(); anExp.Next()) { @@ -1792,19 +1983,58 @@ static TopoDS_Shape CreatePipeForShellSections(const TopoDS_Wire& aWirePath, else { B.Add(aComp,aShell); } + + if (isGenerateGroups) { + // Replase Group shapes by modified ones. + Standard_Integer iGrp; + + // For each group. + for (iGrp = 0; iGrp < 5; ++iGrp) { + Standard_Integer j; + + // For each sub-shape of pipe + for (j = 1; j <= aLocalGroups[iGrp].Length(); ++j) { + const TopoDS_Shape &aGrpShape = aLocalGroups[iGrp].Value(j); + + if (aSewing->IsModifiedSubShape(aGrpShape)) { + // Use the shape modified by sewing. + const TopoDS_Shape &aModifGrpShape = + aSewing->ModifiedSubShape(aGrpShape); + + aGroups[iGrp].Append(aModifGrpShape); + } else { + // Use the shape as it is. + aGroups[iGrp].Append(aGrpShape); + } + } + } + } } } + } + } + if (isGenerateGroups) { + // Fill the groups. + Handle(TColStd_HArray1OfInteger) aGroupIds[5]; + TopTools_IndexedMapOfShape anIndices; + + TopExp::MapShapes(aComp, anIndices); + + if (!FillGroups(aGroups, anIndices, aGroupIds)) { + if (aCI) delete aCI; + Standard_ConstructionError::Raise("Generate groups failure"); } + + StoreGroups(aCI, aGroupIds); } - //BRepTools::Write(aComp,"/dn02/users_Linux/skl/work/Bugs/14857/comp.brep"); return aComp; } //======================================================================= //function : CreatePipeShellsWithoutPath -//purpose : auxilary for Execute() +//purpose : auxiliary for Execute() //======================================================================= static TopoDS_Shape CreatePipeShellsWithoutPath(GEOMImpl_IPipe* aCI) { @@ -1817,6 +2047,7 @@ static TopoDS_Shape CreatePipeShellsWithoutPath(GEOMImpl_IPipe* aCI) Handle(TColStd_HSequenceOfTransient) aBasesObjs = aCIDS->GetBases(); // vertex for recognition Handle(TColStd_HSequenceOfTransient) VObjs = aCIDS->GetLocations(); + Standard_Boolean isGenerateGroups = aCIDS->GetGenerateGroups(); Standard_Integer nbBases = aBasesObjs->Length(), nbv = (VObjs.IsNull() ? 0 :VObjs->Length()); @@ -1826,6 +2057,7 @@ static TopoDS_Shape CreatePipeShellsWithoutPath(GEOMImpl_IPipe* aCI) Standard_ConstructionError::Raise("Number of shapes for recognition is invalid"); } + TopTools_SequenceOfShape aGroups[5]; TopTools_SequenceOfShape SecVs,Bases; for (i=1; i<=nbBases; i++) { // vertex @@ -1877,8 +2109,23 @@ static TopoDS_Shape CreatePipeShellsWithoutPath(GEOMImpl_IPipe* aCI) } TopTools_MapOfShape aFaces1,aFaces2; + TopTools_MapOfShape aBndEdges1; + for (anExp.Init(aShBase1, TopAbs_FACE); anExp.More(); anExp.Next()) { - aFaces1.Add(anExp.Current()); + const TopoDS_Shape &aBaseFace1 = anExp.Current(); + + if (aFaces1.Add(aBaseFace1)) { + // Get boundary edges. + TopExp_Explorer anExpE(aBaseFace1, TopAbs_EDGE); + + for (; anExpE.More(); anExpE.Next()) { + const TopoDS_Shape &aBaseEdge1 = anExpE.Current(); + + if (!aBndEdges1.Add(aBaseEdge1)) { + aBndEdges1.Remove(aBaseEdge1); + } + } + } } for (anExp.Init(aShBase2, TopAbs_FACE); anExp.More(); anExp.Next()) { aFaces2.Add(anExp.Current()); @@ -1907,13 +2154,13 @@ static TopoDS_Shape CreatePipeShellsWithoutPath(GEOMImpl_IPipe* aCI) if (aCI) delete aCI; Standard_ConstructionError::Raise("Can not create correct pipe"); } - MESSAGE (" correspondences for sub-shapes of first pair of faces is found"); + MESSAGE (" correspondences for sub-shapes of first pair of faces found"); FindNextPairOfFaces(FS1, aMapEdgeFaces1, aMapEdgeFaces2, FF, aCI); - MESSAGE (" other correspondences is found, make pipe for all pairs of faces"); + MESSAGE (" other correspondences found, make pipe for all pairs of faces"); // make pipe for each pair of faces - // auxilary map vertex->edge for created pipe edges + // auxiliary map vertex->edge for created pipe edges TopTools_IndexedDataMapOfShapeShape VPE; ShapeAnalysis_Edge sae; //cout<<"FF.Extent()="<Degree()<3) CE4->IncreaseDegree(3); - //cout<<"CE1->Degree()="<Degree()<<" CE2->Degree()="<Degree() - // <<" CE3->Degree()="<Degree()<<" CE4->Degree()="<Degree()<FirstParameter(); lp = iso->LastParameter(); step = (lp-fp)/(NbP-1); @@ -2193,8 +2433,13 @@ static TopoDS_Shape CreatePipeShellsWithoutPath(GEOMImpl_IPipe* aCI) TopoDS_Face FixedFace = sff->Face(); aNewFs.Append(FixedFace); VPE.Add(E1,FixedFace); - //cout<<" face for edge "<SetTolerance(Precision::Confusion()); @@ -2217,7 +2471,6 @@ static TopoDS_Shape CreatePipeShellsWithoutPath(GEOMImpl_IPipe* aCI) 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; @@ -2242,38 +2495,54 @@ static TopoDS_Shape CreatePipeShellsWithoutPath(GEOMImpl_IPipe* aCI) B.Add(aComp,aShell); MESSAGE (" solid for face "<Perform(); - //TopoDS_Shell FixedShell = sfs->Shell(); - /* - GProp_GProps aSystem; - BRepGProp::VolumeProperties(FixedShell, aSystem); - if (aSystem.Mass()<0) { - //cout<<"aSewShape is reversed"<IsModifiedSubShape(aGrpShape)) { + // Use the shape modified by sewing. + const TopoDS_Shape &aModifGrpShape = + aSewing->ModifiedSubShape(aGrpShape); + + aGroups[iGrp].Append(aModifGrpShape); + } else { + // Use the shape as it is. + aGroups[iGrp].Append(aGrpShape); + } + } + } } - */ } } - //BRepTools::Write(aComp,"/dn02/users_Linux/skl/work/Bugs/14857/comp.brep"); + if (isGenerateGroups) { + // Fill the groups. + Handle(TColStd_HArray1OfInteger) aGroupIds[5]; + TopTools_IndexedMapOfShape anIndices; + + TopExp::MapShapes(aComp, anIndices); + + if (!FillGroups(aGroups, anIndices, aGroupIds)) { + if (aCI) delete aCI; + Standard_ConstructionError::Raise("Generate groups failure"); + } + + StoreGroups(aCI, aGroupIds); + } + return aComp; } //======================================================================= //function : CreatePipeBiNormalAlongVector -//purpose : auxilary for Execute() +//purpose : auxiliary for Execute() //======================================================================= static TopoDS_Shape CreatePipeBiNormalAlongVector(const TopoDS_Wire& aWirePath, GEOMImpl_IPipe* aCI) @@ -2333,19 +2602,426 @@ static TopoDS_Shape CreatePipeBiNormalAlongVector(const TopoDS_Wire& aWirePath, 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) { + + Standard_Boolean isDone = BuildPipeShell(PipeBuilder); + + if (isDone && aShapeBase.ShapeType() == TopAbs_FACE) { PipeBuilder.MakeSolid(); } + if (!CreateGroups1(aProf, PipeBuilder, aCIBN)) { + if (aCIBN) delete aCIBN; + Standard_ConstructionError::Raise("Generate groups failure"); + } + return PipeBuilder.Shape(); } +//======================================================================= +//function : FillGroups +//purpose : auxiliary for DoGroups() +//======================================================================= +bool FillGroups(const TopTools_SequenceOfShape *theGroups, + const TopTools_IndexedMapOfShape &theIndices, + Handle(TColStd_HArray1OfInteger) *theGroupIds) +{ + Standard_Integer i; + + for (i = 0; i < 5; ++i) { + if (!theGroups[i].IsEmpty()) { + const Standard_Integer aNbShapes = theGroups[i].Length(); + Standard_Integer j; + + theGroupIds[i] = new TColStd_HArray1OfInteger(1, aNbShapes); + + for (j = 1; j <= aNbShapes; ++j) { + const TopoDS_Shape &aShape = theGroups[i].Value(j); + const Standard_Integer anIndex = theIndices.FindIndex(aShape); + + if (anIndex == 0) { + return false; + } + + theGroupIds[i]->SetValue(j, anIndex); + } + } + } + + return true; +} + +//======================================================================= +//function : StoreGroups +//purpose : auxiliary for CreateGroups() +//======================================================================= +void StoreGroups(GEOMImpl_IPipe *theCI, + Handle(TColStd_HArray1OfInteger) *theGroups) +{ + if (theGroups[GROUP_DOWN].IsNull() == Standard_False) { + theCI->SetGroupDown(theGroups[GROUP_DOWN]); + } + + if (theGroups[GROUP_UP].IsNull() == Standard_False) { + theCI->SetGroupUp(theGroups[GROUP_UP]); + } + + if (theGroups[GROUP_SIDE1].IsNull() == Standard_False) { + theCI->SetGroupSide1(theGroups[GROUP_SIDE1]); + } + + if (theGroups[GROUP_SIDE2].IsNull() == Standard_False) { + theCI->SetGroupSide2(theGroups[GROUP_SIDE2]); + } + + if (theGroups[GROUP_OTHER].IsNull() == Standard_False) { + theCI->SetGroupOther(theGroups[GROUP_OTHER]); + } +} + +//======================================================================= +//function : CreateDownUpGroups +//purpose : auxiliary for DoGroups() +//======================================================================= +static bool CreateDownUpGroups(BRepPrimAPI_MakeSweep *theSweep, + TopTools_SequenceOfShape *theGroups, + Standard_Boolean &IsDoSides) +{ + const TopoDS_Shape aDownShape = theSweep->FirstShape(); + const TopAbs_ShapeEnum aType = aDownShape.ShapeType(); + TopAbs_ShapeEnum anUpDownType = TopAbs_SHAPE; + + IsDoSides = Standard_False; + + switch (aType) { + case TopAbs_EDGE: + case TopAbs_WIRE: + anUpDownType = TopAbs_EDGE; + + if (GEOMUtils::IsOpenPath(aDownShape)) { + IsDoSides = Standard_True; + } + break; + case TopAbs_FACE: + case TopAbs_SHELL: + anUpDownType = TopAbs_FACE; + break; + default: + break; + } + + if (anUpDownType == TopAbs_SHAPE) { + // Invalid Up and Down group type. + return false; + } + + TopExp_Explorer anExp(aDownShape, anUpDownType); + TopTools_MapOfShape aMapFence; + + // Create Down group. + for (; anExp.More(); anExp.Next()) { + const TopoDS_Shape &aShape = anExp.Current(); + + if (aMapFence.Add(aShape)) { + theGroups[GROUP_DOWN].Append(aShape); + } + } + + // Create Up group + const TopoDS_Shape anUpShape = theSweep->LastShape(); + + aMapFence.Clear(); + anExp.Init(anUpShape, anUpDownType); + + for (; anExp.More(); anExp.Next()) { + const TopoDS_Shape &aShape = anExp.Current(); + + if (aMapFence.Add(aShape)) { + theGroups[GROUP_UP].Append(aShape); + } + } + + return true; +} + +//======================================================================= +//function : DoGroups1 +//purpose : auxiliary for CreateGroups1() +//======================================================================= +bool DoGroups1 (const TopoDS_Shape &theProfile, + BRepOffsetAPI_MakePipeShell &theSweep, + TopTools_SequenceOfShape *theGroups) +{ + Standard_Boolean isDoSides = Standard_False; + + if (!CreateDownUpGroups(&theSweep, theGroups, isDoSides)) { + // Up and Down groups creation failure + return false; + } + + TopoDS_Shape aDownShape = theProfile; + if (aDownShape.IsNull()) aDownShape = theSweep.FirstShape(); + + if (isDoSides) { + // Create Side1 and Side2 groups. + const TopAbs_ShapeEnum aType = aDownShape.ShapeType(); + TopoDS_Vertex aV[2]; + Standard_Integer i; + + if (aType == TopAbs_EDGE) { + TopExp::Vertices(TopoDS::Edge(aDownShape), aV[0], aV[1], Standard_True); + } else { // aType == TopAbs_WIRE + TopExp::Vertices(TopoDS::Wire(aDownShape), aV[0], aV[1]); + } + + for (i = 0; i < 2; ++i) { + if (aV[i].IsNull() == Standard_False) { + const TopTools_ListOfShape &aLstSide = theSweep.Generated(aV[i]); + + if (!aLstSide.IsEmpty()) { + TopTools_ListIteratorOfListOfShape aSideIt(aLstSide); + TopTools_MapOfShape aMapFence; + const Standard_Integer anIdSide = + (i == 0 ? GROUP_SIDE1 : GROUP_SIDE2); + + for (; aSideIt.More(); aSideIt.Next()) { + const TopoDS_Shape &aSideShape = aSideIt.Value(); + + if (aSideShape.ShapeType() == TopAbs_EDGE) { + if (aMapFence.Add(aSideShape)) { + theGroups[anIdSide].Append(aSideShape); + } + } else if (aSideShape.ShapeType() == TopAbs_WIRE) { + if (aMapFence.Add(aSideShape)) { + TopExp_Explorer anExpWE (aSideShape, TopAbs_EDGE); + for (; anExpWE.More(); anExpWE.Next()) { + theGroups[anIdSide].Append(anExpWE.Current()); + } + } + } else { + // Only edges can be in Side1 and Side2 groups. + return false; + } + } + } + } + } + } else { + // Create Other group. Get boundary edges of the profile. + TopTools_MapOfShape aMapBndEdges; + TopExp_Explorer anExp(aDownShape, TopAbs_EDGE); + + for (; anExp.More(); anExp.Next()) { + const TopoDS_Shape &anEdge = anExp.Current(); + + if (!aMapBndEdges.Add(anEdge)) { + aMapBndEdges.Remove(anEdge); + } + } + + // Fill the map of faces generated from profile's boundary edges. + TopTools_MapIteratorOfMapOfShape anIter(aMapBndEdges); + TopTools_MapOfShape aMapFence; + + for (; anIter.More(); anIter.Next()) { + const TopTools_ListOfShape &aLstOther = theSweep.Generated(anIter.Key()); + + if (!aLstOther.IsEmpty()) { + TopTools_ListIteratorOfListOfShape anOtherIt(aLstOther); + + for (; anOtherIt.More(); anOtherIt.Next()) { + const TopoDS_Shape &anOtherShape = anOtherIt.Value(); + + if (anOtherShape.ShapeType() == TopAbs_FACE) { + if (aMapFence.Add(anOtherShape)) { + theGroups[GROUP_OTHER].Append(anOtherShape); + } + } else if (anOtherShape.ShapeType() == TopAbs_SHELL) { + if (aMapFence.Add(anOtherShape)) { + TopExp_Explorer anExpSHF (anOtherShape, TopAbs_FACE); + for (; anExpSHF.More(); anExpSHF.Next()) { + theGroups[GROUP_OTHER].Append(anExpSHF.Current()); + } + } + } else { + // Only faces can be in Other group. + return false; + } + } + } + } + } + + return true; +} + +//======================================================================= +//function : CreateGroups1 +//purpose : auxiliary for Execute() +//======================================================================= +bool CreateGroups1 (const TopoDS_Shape &theProfile, + BRepOffsetAPI_MakePipeShell &theSweep, + GEOMImpl_IPipe *theCI) +{ + if (!theCI->GetGenerateGroups()) { + // Nothing to do. + return true; + } + + // Make groups. + TopTools_SequenceOfShape aGroups[5]; + + if (!DoGroups1(theProfile, theSweep, aGroups)) { + return false; + } + + // Fill the groups. + Handle(TColStd_HArray1OfInteger) aGroupIds[5]; + TopTools_IndexedMapOfShape anIndices; + const TopoDS_Shape aResult = theSweep.Shape(); + + TopExp::MapShapes(aResult, anIndices); + + if (!FillGroups(aGroups, anIndices, aGroupIds)) { + return false; + } + + // Store groups. + StoreGroups(theCI, aGroupIds); + + return true; +} + +//======================================================================= +//function : DoGroups2 +//purpose : auxiliary for CreateGroups() +//======================================================================= +static bool DoGroups2(const TopoDS_Shape &theProfile, + const TopoDS_Shape &thePath, + BRepOffsetAPI_MakePipe &theSweep, + TopTools_SequenceOfShape *theGroups) +{ + Standard_Boolean isDoSides = Standard_False; + + if (!CreateDownUpGroups(&theSweep, theGroups, isDoSides)) { + // Up and Down groups creation failure + return false; + } + + if (isDoSides) { + // Create Side1 and Side2 groups. + const TopAbs_ShapeEnum aType = theProfile.ShapeType(); + TopoDS_Vertex aV[2]; + Standard_Integer i; + + if (aType == TopAbs_EDGE) { + TopExp::Vertices(TopoDS::Edge(theProfile), aV[0], aV[1], Standard_True); + } else { // aType == TopAbs_WIRE + TopExp::Vertices(TopoDS::Wire(theProfile), aV[0], aV[1]); + } + + for (i = 0; i < 2; ++i) { + if (aV[i].IsNull() == Standard_False) { + TopExp_Explorer anExpP(thePath, TopAbs_EDGE); + TopTools_MapOfShape aMapFence; + const Standard_Integer anIdSide = + (i == 0 ? GROUP_SIDE1 : GROUP_SIDE2); + + for (; anExpP.More(); anExpP.Next()) { + const TopoDS_Shape aSideShape = + theSweep.Generated(anExpP.Current(), aV[i]); + + if (aSideShape.ShapeType() == TopAbs_EDGE) { + if (aMapFence.Add(aSideShape)) { + theGroups[anIdSide].Append(aSideShape); + } + } else { + // Only edges can be is Side1 and Side2 groups. + return false; + } + } + } + } + } else { + // Create Other group. Get boundary edges of the profile. + TopTools_MapOfShape aMapBndEdges; + TopExp_Explorer anExp(theProfile, TopAbs_EDGE); + + for (; anExp.More(); anExp.Next()) { + const TopoDS_Shape &anEdge = anExp.Current(); + + if (!aMapBndEdges.Add(anEdge)) { + aMapBndEdges.Remove(anEdge); + } + } + + TopExp_Explorer anExpP(thePath, TopAbs_EDGE); + TopTools_MapOfShape aMapFence; + + for (; anExpP.More(); anExpP.Next()) { + TopTools_MapIteratorOfMapOfShape anIter(aMapBndEdges); + + for (; anIter.More(); anIter.Next()) { + const TopoDS_Shape anOtherShape = + theSweep.Generated(anExpP.Current(), anIter.Key()); + + if (anOtherShape.ShapeType() == TopAbs_FACE) { + if (aMapFence.Add(anOtherShape)) { + theGroups[GROUP_OTHER].Append(anOtherShape); + } + } else { + // Only faces can be in Other group. + return false; + } + } + } + } + + return true; +} + +//======================================================================= +//function : CreateGroups +//purpose : auxiliary for Execute() +//======================================================================= +static bool CreateGroups2(const TopoDS_Shape &theProfile, + const TopoDS_Shape &thePath, + BRepOffsetAPI_MakePipe &theSweep, + GEOMImpl_IPipe *theCI) +{ + if (!theCI->GetGenerateGroups()) { + // Nothing to do. + return true; + } + + // Make groups. + TopTools_SequenceOfShape aGroups[5]; + + if (!DoGroups2(theProfile, thePath, theSweep, aGroups)) { + return false; + } + + // Fill the groups. + Handle(TColStd_HArray1OfInteger) aGroupIds[5]; + TopTools_IndexedMapOfShape anIndices; + const TopoDS_Shape aResult = theSweep.Shape(); + + TopExp::MapShapes(aResult, anIndices); + + if (!FillGroups(aGroups, anIndices, aGroupIds)) { + return false; + } + + // Store groups. + StoreGroups(theCI, aGroupIds); + + return true; +} + //======================================================================= //function : Execute //purpose : //======================================================================= -Standard_Integer GEOMImpl_PipeDriver::Execute (TFunction_Logbook& log) const +Standard_Integer GEOMImpl_PipeDriver::Execute(Handle(TFunction_Logbook)& log) const { if (Label().IsNull()) return 0; Handle(GEOM_Function) aFunction = GEOM_Function::GetFunction(Label()); @@ -2407,9 +3083,20 @@ Standard_Integer GEOMImpl_PipeDriver::Execute (TFunction_Logbook& log) const if (aCI) delete aCI; Standard_TypeMismatch::Raise("MakePipe aborted : path shape is neither a wire nor an edge"); } + + // Check if it is possible to create groups. + if (aCI->GetGenerateGroups() && !GEOMUtils::IsOpenPath(aWirePath)) { + if (aCI) { + delete aCI; + } + + Standard_ConstructionError::Raise + ("Can't create groups if the path is closed"); + } } - TopoDS_Shape aShape; + TopoDS_Shape aShape; + const Standard_Boolean isGenerateGroups = aCI->GetGenerateGroups(); if (aType == PIPE_BASE_PATH) { Handle(GEOM_Function) aRefBase = aCI->GetBase(); @@ -2429,36 +3116,64 @@ Standard_Integer GEOMImpl_PipeDriver::Execute (TFunction_Logbook& log) const if (aShapeBase.ShapeType() == TopAbs_EDGE || aShapeBase.ShapeType() == TopAbs_WIRE) { - TopoDS_Wire Profile; + TopoDS_Wire aProfile; if (aShapeBase.ShapeType() == TopAbs_WIRE) - Profile = TopoDS::Wire(aShapeBase); + aProfile = TopoDS::Wire(aShapeBase); else { BRep_Builder BB; - BB.MakeWire(Profile); - BB.Add(Profile, aShapeBase); + BB.MakeWire(aProfile); + BB.Add(aProfile, 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()) + Sweep.Add(aProfile); + + Standard_Boolean isDone = BuildPipeShell(Sweep); + + if (!isDone) { if (aCI) delete aCI; Standard_ConstructionError::Raise("MakePipeShell failed"); } else aShape = Sweep.Shape(); //result is good - + + if (!CreateGroups1(aProfile, Sweep, aCI)) { + if (aCI) delete aCI; + Standard_ConstructionError::Raise("Generate groups failure"); + } } else { GeomFill_Trihedron theBestMode = EvaluateBestSweepMode(aWirePath); - aShape = BRepOffsetAPI_MakePipe(aWirePath, aShapeBase, theBestMode); + BRepOffsetAPI_MakePipe aMkPipe + (aWirePath, aShapeBase, theBestMode, Standard_True); + + if (aMkPipe.IsDone() && aMkPipe.ErrorOnSurface() <= TolPipeSurf) { + aShape = aMkPipe.Shape(); + + if (!CreateGroups2(aShapeBase, aWirePath, aMkPipe, aCI)) { + if (aCI) delete aCI; + Standard_ConstructionError::Raise("Generate groups failure"); + } + } else if (theBestMode != GeomFill_IsDiscreteTrihedron) { + // Try to use Descrete Trihedron mode. + BRepOffsetAPI_MakePipe aMkPipeDescrete + (aWirePath, aShapeBase, GeomFill_IsDiscreteTrihedron, Standard_True); + + if (aMkPipeDescrete.IsDone()) { + aShape = aMkPipeDescrete.Shape(); + + if (!CreateGroups2(aShapeBase, aWirePath, aMkPipeDescrete, aCI)) { + if (aCI) delete aCI; + Standard_ConstructionError::Raise("Generate groups failure"); + } + } + } } } @@ -2469,6 +3184,8 @@ Standard_Integer GEOMImpl_PipeDriver::Execute (TFunction_Logbook& log) const Handle(TColStd_HSequenceOfTransient) aLocObjs = aCIDS->GetLocations (); Standard_Boolean aWithContact = (aCIDS->GetWithContactMode()); Standard_Boolean aWithCorrect = (aCIDS->GetWithCorrectionMode()); + Standard_Boolean isBySteps = aCIDS->GetIsBySteps(); + if (aCI) { delete aCI; aCI = 0; @@ -2505,7 +3222,24 @@ Standard_Integer GEOMImpl_PipeDriver::Execute (TFunction_Logbook& log) const aHSeqLocs->Append(aShapeLoc); } - aShape = CreatePipeWithDifferentSections(aWirePath, aHSeqBases, aHSeqLocs, aWithContact, aWithCorrect); + + Handle(TColStd_HArray1OfInteger) *pGroups = NULL; + Handle(TColStd_HArray1OfInteger) aGroups[5]; + + if (isGenerateGroups) { + pGroups = aGroups; + } + + aShape = CreatePipeWithDifferentSections + (aWirePath, aHSeqBases, aHSeqLocs, + aWithContact, aWithCorrect, isBySteps, pGroups); + + if (isGenerateGroups) { + // Store created groups. + GEOMImpl_IPipeDiffSect aPipeDS(aFunction); + + StoreGroups(&aPipeDS, aGroups); + } } //building pipe with shell sections @@ -2530,19 +3264,8 @@ Standard_Integer GEOMImpl_PipeDriver::Execute (TFunction_Logbook& log) const 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 ( !GEOMUtils::CheckShape(aShape) && !GEOMUtils::FixShapeTolerance(aShape) ) + Standard_ConstructionError::Raise("Algorithm have produced an invalid shape result"); if (aType != PIPE_BASE_PATH && aType != PIPE_SHELLS_WITHOUT_PATH) { @@ -2556,15 +3279,103 @@ Standard_Integer GEOMImpl_PipeDriver::Execute (TFunction_Logbook& log) const aVertMaxTol = aTol; } aVertMaxTol += Precision::Confusion(); - aShape = GEOMImpl_GlueDriver::GlueFaces(aShape, aVertMaxTol, Standard_True); - //aShape = GEOMImpl_GlueDriver::GlueFaces(aShape, Precision::Confusion(), Standard_True); + + TopTools_DataMapOfShapeListOfShape aMapModif; + TopTools_DataMapOfShapeListOfShape *pMapModif = NULL; + + if (isGenerateGroups) { + pMapModif = &aMapModif; + } + + TopoDS_Shape aNewShape = GEOMImpl_GlueDriver::GlueFaces + (aShape, aVertMaxTol, Standard_True, pMapModif); + + if (isGenerateGroups && !aMapModif.IsEmpty()) { + // Update groups. + GEOMImpl_IPipe aCI(aFunction); + Handle(TColStd_HArray1OfInteger) aGroupIDs[5] = + { aCI.GetGroupDown(), aCI.GetGroupUp(), aCI.GetGroupSide1(), + aCI.GetGroupSide2(), aCI.GetGroupOther() }; + TopTools_IndexedMapOfShape anIndices; + TopTools_IndexedMapOfShape aNewIndices; + TopTools_SequenceOfShape aNewShapes[5]; + TopTools_MapOfShape aMapReplaced; + TopTools_MapOfShape aMapGlued; + Standard_Integer iGrp; + Standard_Integer i; + + TopExp::MapShapes(aShape, anIndices); + TopExp::MapShapes(aNewShape, aNewIndices); + + for (iGrp = 0; iGrp < 5; ++iGrp) { + if (aGroupIDs[iGrp].IsNull() == Standard_False) { + const Standard_Integer aLower = aGroupIDs[iGrp]->Lower(); + const Standard_Integer anUpper = aGroupIDs[iGrp]->Upper(); + + for (i = aLower; i <= anUpper; ++i) { + const Standard_Integer anIndex = aGroupIDs[iGrp]->Value(i); + const TopoDS_Shape &aSubShape = anIndices.FindKey(anIndex); + + if (aMapModif.IsBound(aSubShape)) { + const TopTools_ListOfShape &aListModif = + aMapModif.Find(aSubShape); + TopTools_ListIteratorOfListOfShape anIter(aListModif); + + for (; anIter.More(); anIter.Next()) { + const TopoDS_Shape &aNewShape = anIter.Value(); + + if (aMapReplaced.Add(aNewShape)) { + aNewShapes[iGrp].Append(aNewShape); + } else { + // This is a glued shape. It means that it is internal + // one and should be removed from groups later. + aMapGlued.Add(aNewShape); + } + } + } else { + // Shape is not modified. + aNewShapes[iGrp].Append(aSubShape); + } + } + } + } + + if (!aMapGlued.IsEmpty()) { + // Remove glued (internal) shapes from groups. + for (iGrp = 0; iGrp < 5; ++iGrp) { + Standard_Integer aNbShapes = aNewShapes[iGrp].Length(); + + for (i = 1; i < aNbShapes; ++i) { + const TopoDS_Shape &aNewShape = aNewShapes[iGrp].Value(i); + + if (aMapGlued.Contains(aNewShape)) { + aNewShapes[iGrp].Remove(i); + --i; + --aNbShapes; + } + } + } + } + + // Store modified groups. + Handle(TColStd_HArray1OfInteger) aNewGroupIDs[5]; + + if (!FillGroups(aNewShapes, aNewIndices, aNewGroupIDs)) { + Standard_ConstructionError::Raise("Generate groups failure"); + } + + StoreGroups(&aCI, aNewGroupIDs); + } + + aShape = aNewShape; } } + // Note: group indices should not be changed after the next call. TopoDS_Shape aRes = GEOMUtils::CompsolidToCompound(aShape); aFunction->SetValue(aRes); - log.SetTouched(Label()); + log->SetTouched(Label()); return 1; } @@ -2607,8 +3418,13 @@ GetCreationInformation(std::string& theOperationName, 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() ); + + if (!aCI.GetIsBySteps()) { + AddParam( theParams, "With contact", aCI.GetWithContactMode() ); + AddParam( theParams, "With correction", aCI.GetWithCorrectionMode() ); + } + + AddParam( theParams, "Step by step", aCI.GetIsBySteps() ); break; } case PIPE_SHELL_SECTIONS: @@ -2638,5 +3454,4 @@ GetCreationInformation(std::string& theOperationName, return true; } -IMPLEMENT_STANDARD_HANDLE (GEOMImpl_PipeDriver,GEOM_BaseDriver); IMPLEMENT_STANDARD_RTTIEXT (GEOMImpl_PipeDriver,GEOM_BaseDriver);