diff --git a/src/GEOMGUI/GEOM_msg_en.ts b/src/GEOMGUI/GEOM_msg_en.ts index 2d94e74b7..42cd00013 100644 --- a/src/GEOMGUI/GEOM_msg_en.ts +++ b/src/GEOMGUI/GEOM_msg_en.ts @@ -4907,6 +4907,10 @@ Ignoring units will cause model scaling (as dimensions are supposed to be specif JUNCTION_FACE_3 Junction 3 + + INTERNAL_FACES + Internal faces + GEOM_PLUGINS_OTHER Other diff --git a/src/GEOMImpl/GEOMImpl_IAdvancedOperations.cxx b/src/GEOMImpl/GEOMImpl_IAdvancedOperations.cxx index 594dd255b..142c6d40f 100644 --- a/src/GEOMImpl/GEOMImpl_IAdvancedOperations.cxx +++ b/src/GEOMImpl/GEOMImpl_IAdvancedOperations.cxx @@ -31,6 +31,7 @@ #include "GEOM_PythonDump.hxx" #include "GEOMUtils.hxx" #include "GEOMAlgo_Splitter.hxx" +#include "GEOMAlgo_FinderShapeOn1.hxx" #include "GEOMImpl_Gen.hxx" #include "GEOMImpl_Types.hxx" @@ -43,6 +44,7 @@ #include "GEOMImpl_I3DPrimOperations.hxx" #include "GEOMImpl_ILocalOperations.hxx" #include "GEOMImpl_IHealingOperations.hxx" +#include "GEOMImpl_IGroupOperations.hxx" #include "GEOMImpl_GlueDriver.hxx" #include "GEOMImpl_PipeTShapeDriver.hxx" @@ -70,6 +72,7 @@ #include #include +#include #include #include #include @@ -82,6 +85,8 @@ #include #include #include +#include +#include #include @@ -119,6 +124,7 @@ GEOMImpl_IAdvancedOperations::GEOMImpl_IAdvancedOperations(GEOM_Engine* theEngin my3DPrimOperations = new GEOMImpl_I3DPrimOperations(GetEngine(), GetDocID()); myLocalOperations = new GEOMImpl_ILocalOperations(GetEngine(), GetDocID()); myHealingOperations = new GEOMImpl_IHealingOperations(GetEngine(), GetDocID()); + myGroupOperations = new GEOMImpl_IGroupOperations(GetEngine(), GetDocID()); } //============================================================================= @@ -137,6 +143,7 @@ GEOMImpl_IAdvancedOperations::~GEOMImpl_IAdvancedOperations() delete my3DPrimOperations; delete myLocalOperations; delete myHealingOperations; + delete myGroupOperations; } //============================================================================= @@ -790,6 +797,337 @@ bool GEOMImpl_IAdvancedOperations::MakeGroups(Handle(GEOM_Object) theShape, int return true; } +//============================================================================= +/*! + * Return faces that are laying on surface. + */ +//============================================================================= +bool GEOMImpl_IAdvancedOperations::GetFacesOnSurf + (const TopoDS_Shape &theShape, + const Handle_Geom_Surface& theSurface, + const Standard_Real theTolerance, + TopTools_ListOfShape &theFaces) +{ + GEOMAlgo_FinderShapeOn1 aFinder; + + aFinder.SetShape(theShape); + aFinder.SetTolerance(theTolerance); + aFinder.SetSurface(theSurface); + aFinder.SetShapeType(TopAbs_FACE); + aFinder.SetState(GEOMAlgo_ST_ON); + + // Sets the minimal number of inner points for the faces that do not have own + // inner points at all (for e.g. rectangular planar faces have just 2 triangles). + // Default value=3 + aFinder.SetNbPntsMin(3); + // Sets the maximal number of inner points for edges or faces. + // It is usefull for the cases when this number is very big (e.g =2000) to improve + // the performance. If this value =0, all inner points will be taken into account. + // Default value=0 + aFinder.SetNbPntsMax(100); + aFinder.Perform(); + + // Interprete results + Standard_Integer iErr = aFinder.ErrorStatus(); + // the detailed description of error codes is in GEOMAlgo_FinderShapeOn1.cxx + if (iErr) { + MESSAGE(" iErr : " << iErr); + TCollection_AsciiString aMsg (" iErr : "); + aMsg += TCollection_AsciiString(iErr); + SetErrorCode(aMsg); + return false; + } + Standard_Integer iWrn = aFinder.WarningStatus(); + // the detailed description of warning codes is in GEOMAlgo_FinderShapeOn1.cxx + if (iWrn) { + MESSAGE(" *** iWrn : " << iWrn); + } + + const TopTools_ListOfShape &aListRes = aFinder.Shapes(); // the result + TopTools_ListIteratorOfListOfShape anIter (aListRes); + + for (; anIter.More(); anIter.Next()) { + theFaces.Append(anIter.Value()); + } + + return true; +} + +//============================================================================= +/*! + * Creates and returns conical face. + */ +//============================================================================= +TopoDS_Shape GEOMImpl_IAdvancedOperations::MakeConicalFace + (const gp_Ax2 &theAxis, + const double theRadius, + const double theRadiusThin, + const double theHeight, + const gp_Trsf &theTrsf) +{ + BRepPrimAPI_MakeCone aMkCone (theAxis, theRadius, theRadiusThin, theHeight); + TopoDS_Shape aResult; + + aMkCone.Build(); + if (aMkCone.IsDone()) { + TopExp_Explorer anExp(aMkCone.Shape(), TopAbs_FACE); + + for (; anExp.More(); anExp.Next()) { + TopoDS_Face aFace = TopoDS::Face(anExp.Current()); + + if (aFace.IsNull() == Standard_False) { + BRepAdaptor_Surface anAdaptor(aFace, Standard_False); + + if (anAdaptor.GetType() == GeomAbs_Cone) { + // This is a conical face. Transform and return it. + BRepBuilderAPI_Transform aTransf(aFace, theTrsf, Standard_False); + + aResult = aTransf.Shape(); + break; + } + } + } + } + + return aResult; +} + +//============================================================================= +/*! + * Generate the internal group of a Pipe T-Shape + */ +//============================================================================= +bool GEOMImpl_IAdvancedOperations::MakeInternalGroup + (const Handle(GEOM_Object) &theShape, + const double theR1, const double theLen1, + const double theR2, const double theLen2, + const double theRL, double theTransLenL, + const double theRR, double theTransLenR, + const double theRI, double theTransLenI, + const Handle(TColStd_HSequenceOfTransient) &theSeq, + const gp_Trsf &theTrsf) +{ + SetErrorCode(KO); + + if (theShape.IsNull()) { + return false; + } + + TopoDS_Shape aShape = theShape->GetValue(); + + if (aShape.IsNull()) { + SetErrorCode("Shape is not defined"); + return false; + } + + // Compute tolerance + Standard_Real aMaxTol = -RealLast(); + TopExp_Explorer anExp(aShape, TopAbs_VERTEX); + + for (; anExp.More(); anExp.Next()) { + TopoDS_Vertex aVertex = TopoDS::Vertex(anExp.Current()); + + if (aVertex.IsNull() == Standard_False) { + const Standard_Real aTol = BRep_Tool::Tolerance(aVertex); + + if (aTol > aMaxTol) { + aMaxTol = aTol; + } + } + } + + // Construct internal surfaces. + Standard_Integer i = 0; + const Standard_Integer aMaxNbSurf = 5; + Handle(Geom_Surface) aSurface[aMaxNbSurf]; + TopTools_ListOfShape aConicalFaces; + Standard_Real aTolConf = Precision::Confusion(); + + // 1. Construct the internal surface of main pipe. + gp_Ax2 anAxis1 (gp::Origin(), gp::DX(), gp::DZ()); + gp_Ax2 anAxis2 (gp::Origin(), gp::DZ(), gp::DX()); + + aSurface[i++] = new Geom_CylindricalSurface(anAxis1, theR1); + + // 2. Construct the internal surface of incident pipe. + aSurface[i++] = new Geom_CylindricalSurface(anAxis2, theR2); + + // 3. Construct the internal surface of left reduction pipe. + if (theRL > aTolConf) { + aSurface[i++] = new Geom_CylindricalSurface(anAxis1, theRL); + + if (theTransLenL > aTolConf) { + // 3.1. Construct the internal surface of left transition pipe. + gp_Pnt aPLeft (-theLen1, 0., 0.); + gp_Ax2 anAxisLeft (aPLeft, -gp::DX(), gp::DZ()); + TopoDS_Shape aConeLeft = + MakeConicalFace(anAxisLeft, theR1, theRL, theTransLenL, theTrsf); + + if (aConeLeft.IsNull() == Standard_False) { + aConicalFaces.Append(aConeLeft); + } + } + } + + // 4. Construct the internal surface of right reduction pipe. + if (theRR > aTolConf) { + // There is no need to construct another cylinder of the same radius. Skip it. + if (Abs(theRR - theRL) > aTolConf) { + aSurface[i++] = new Geom_CylindricalSurface(anAxis1, theRR); + } + + if (theTransLenL > aTolConf) { + // 4.1. Construct the internal surface of right transition pipe. + gp_Pnt aPRight (theLen1, 0., 0.); + gp_Ax2 anAxisRight (aPRight, gp::DX(), gp::DZ()); + TopoDS_Shape aConeRight = + MakeConicalFace(anAxisRight, theR1, theRR, theTransLenR, theTrsf); + + if (aConeRight.IsNull() == Standard_False) { + aConicalFaces.Append(aConeRight); + } + } + } + + // 5. Construct the internal surface of incident reduction pipe. + if (theRI > aTolConf) { + aSurface[i++] = new Geom_CylindricalSurface(anAxis2, theRI); + + if (theTransLenI > aTolConf) { + // 5.1. Construct the internal surface of incident transition pipe. + gp_Pnt aPInci (0., 0., theLen2); + gp_Ax2 anAxisInci (aPInci, gp::DZ(), gp::DX()); + TopoDS_Shape aConeInci = + MakeConicalFace(anAxisInci, theR2, theRI, theTransLenI, theTrsf); + + if (aConeInci.IsNull() == Standard_False) { + aConicalFaces.Append(aConeInci); + } + } + } + + // Get faces that are laying on cylindrical surfaces. + TopTools_ListOfShape aFaces; + gp_Trsf anInvTrsf = theTrsf.Inverted(); + + for (i = 0; i < aMaxNbSurf; i++) { + if (aSurface[i].IsNull()) { + break; + } + + aSurface[i]->Transform(theTrsf); + + TopTools_ListOfShape aLocalFaces; + + if (!GetFacesOnSurf(aShape, aSurface[i], aMaxTol, aLocalFaces)) { + return false; + } + + if (i < 2) { + // Check if the result contains outer cylinders. + // It is required for main and incident pipes. + TopTools_ListIteratorOfListOfShape anIter(aLocalFaces); + + while (anIter.More()) { + TopExp_Explorer anExp(anIter.Value(), TopAbs_VERTEX); + Standard_Boolean isInside = Standard_False; + + // Get a vertex from this shape + if (anExp.More()) { + TopoDS_Vertex aVtx = TopoDS::Vertex(anExp.Current()); + + if (aVtx.IsNull() == Standard_False) { + gp_Pnt aPnt = BRep_Tool::Pnt(aVtx); + + aPnt.Transform(anInvTrsf); + + if (i == 0) { + // Check if the point is inside the main pipe. + isInside = (Abs(aPnt.X()) <= theLen1); + } else { // i == 1 + // Check if the point is inside the incident pipe. + isInside = (aPnt.Z() <= theLen2); + } + } + } + + if (isInside) { + // Keep this face. + anIter.Next(); + } else { + // Remove this face. + aLocalFaces.Remove(anIter); + } + } + } + + aFaces.Append(aLocalFaces); + } + + // Get faces that are laying on conical faces. + if (aConicalFaces.IsEmpty() == Standard_False) { + Handle(GEOM_Object) aCone = + GetEngine()->AddObject(GetDocID(), GEOM_TSHAPE); + Handle(GEOM_Function) aFunction = + aCone->AddFunction(GEOMImpl_PipeTShapeDriver::GetID(), TSHAPE_BASIC); + TopTools_ListIteratorOfListOfShape aFIter(aConicalFaces); + Handle(GEOM_Object) aConeFromShape; + + for (; aFIter.More(); aFIter.Next()) { + aFunction->SetValue(aFIter.Value()); + aConeFromShape = myShapesOperations->GetInPlace(theShape, aCone); + + if (aConeFromShape.IsNull() == Standard_False) { + aConeFromShape->GetLastFunction()->SetDescription(""); + TopoDS_Shape aConeFaces = aConeFromShape->GetValue(); + TopExp_Explorer anExp(aConeFaces, TopAbs_FACE); + + for (; anExp.More(); anExp.Next()) { + TopoDS_Face aConeFace = TopoDS::Face(anExp.Current()); + + if (aConeFace.IsNull() == Standard_False) { + aFaces.Append(aConeFace); + } + } + } + } + } + + // Create a group of internal faces. + if (aFaces.IsEmpty() == Standard_False) { + Handle(GEOM_Object) aGroup = myGroupOperations->CreateGroup(theShape, TopAbs_FACE); + + if (aGroup.IsNull() == Standard_False) { + aGroup->GetLastFunction()->SetDescription(""); + aGroup->SetName("INTERNAL_FACES"); + + TopTools_IndexedMapOfShape anIndices; + Handle(TColStd_HSequenceOfInteger) aSeqIDs = new TColStd_HSequenceOfInteger; + + TopExp::MapShapes(aShape, anIndices); + + TopTools_ListIteratorOfListOfShape anIter(aFaces); + + for (; anIter.More(); anIter.Next()) { + const TopoDS_Shape &aFace = anIter.Value(); + const Standard_Integer anIndex = anIndices.FindIndex(aFace); + + if (anIndex > 0) { + aSeqIDs->Append(anIndex); + } + } + + myGroupOperations->UnionIDs(aGroup, aSeqIDs); + aGroup->GetLastFunction()->SetDescription(""); + theSeq->Append(aGroup); + } + } + + SetErrorCode(OK); + + return true; +} + bool GEOMImpl_IAdvancedOperations::MakePipeTShapePartition(Handle(GEOM_Object) theShape, double theR1, double theW1, double theL1, double theR2, double theW2, double theL2, @@ -1663,19 +2001,26 @@ Handle(TColStd_HSequenceOfTransient) Handle(TColStd_HSequenceOfTransient) aSeq = new TColStd_HSequenceOfTransient; aSeq->Append(aShape); - if (theHexMesh) { - // Get the groups - try { + try { + if (theHexMesh) { + // Get the groups if (!MakeGroups(aShape, TSHAPE_BASIC, theR1, theW1, theL1, theR2, theW2, theL2, 0., 0., 0., aSeq, gp_Trsf())) return NULL; } - catch (Standard_Failure) { - Handle(Standard_Failure) aFail = Standard_Failure::Caught(); - SetErrorCode(aFail->GetMessageString()); + + // Get internal group. + if (!MakeInternalGroup(aShape, theR1, theL1, theR2, theL2, theRL, theLtransL, + theRR, theLtransR, theRI, theLtransI, + aSeq, gp_Trsf())) { return NULL; } } + catch (Standard_Failure) { + Handle(Standard_Failure) aFail = Standard_Failure::Caught(); + SetErrorCode(aFail->GetMessageString()); + return NULL; + } //Make a Python command TCollection_AsciiString anEntry, aListRes("["); @@ -1828,20 +2173,27 @@ GEOMImpl_IAdvancedOperations::MakePipeTShapeWithPosition Handle(TColStd_HSequenceOfTransient) aSeq = new TColStd_HSequenceOfTransient; aSeq->Append(aShape); - if (theHexMesh) { - // Get the groups - try { + try { + if (theHexMesh) { + // Get the groups if (!MakeGroups(aShape,TSHAPE_BASIC, theR1, theW1, theL1, theR2, theW2, theL2, 0., 0., 0., aSeq, aTrsf)) { return NULL; } } - catch (Standard_Failure) { - Handle(Standard_Failure) aFail = Standard_Failure::Caught(); - SetErrorCode(aFail->GetMessageString()); + + // Get internal group. + if (!MakeInternalGroup(aShape, theR1, theL1, theR2, theL2, theRL, theLtransL, + theRR, theLtransR, theRI, theLtransI, + aSeq, aTrsf)) { return NULL; } } + catch (Standard_Failure) { + Handle(Standard_Failure) aFail = Standard_Failure::Caught(); + SetErrorCode(aFail->GetMessageString()); + return NULL; + } //Make a Python command TCollection_AsciiString anEntry, aListRes("["); @@ -2049,19 +2401,26 @@ GEOMImpl_IAdvancedOperations::MakePipeTShapeChamfer Handle(TColStd_HSequenceOfTransient) aSeq = new TColStd_HSequenceOfTransient; aSeq->Append(aShape); - if (theHexMesh) { - // Get the groups - try { + try { + if (theHexMesh) { + // Get the groups if (!MakeGroups(aShape, TSHAPE_CHAMFER, theR1, theW1, theL1, theR2, theW2, theL2, theH, theW, 0., aSeq, gp_Trsf())) return NULL; } - catch (Standard_Failure) { - Handle(Standard_Failure) aFail = Standard_Failure::Caught(); - SetErrorCode(aFail->GetMessageString()); + + // Get internal group. + if (!MakeInternalGroup(aShape, theR1, theL1, theR2, theL2, theRL, theLtransL, + theRR, theLtransR, theRI, theLtransI, + aSeq, gp_Trsf())) { return NULL; } } + catch (Standard_Failure) { + Handle(Standard_Failure) aFail = Standard_Failure::Caught(); + SetErrorCode(aFail->GetMessageString()); + return NULL; + } //Make a Python command TCollection_AsciiString anEntry, aListRes("["); @@ -2285,19 +2644,26 @@ GEOMImpl_IAdvancedOperations::MakePipeTShapeChamferWithPosition Handle(TColStd_HSequenceOfTransient) aSeq = new TColStd_HSequenceOfTransient; aSeq->Append(aShape); - if (theHexMesh) { - // Get the groups - try { + try { + if (theHexMesh) { + // Get the groups if (!MakeGroups(aShape, TSHAPE_CHAMFER, theR1, theW1, theL1, theR2, theW2, theL2, theH, theW, 0., aSeq, aTrsf)) return NULL; } - catch (Standard_Failure) { - Handle(Standard_Failure) aFail = Standard_Failure::Caught(); - SetErrorCode(aFail->GetMessageString()); + + // Get internal group. + if (!MakeInternalGroup(aShape, theR1, theL1, theR2, theL2, theRL, theLtransL, + theRR, theLtransR, theRI, theLtransI, + aSeq, aTrsf)) { return NULL; } } + catch (Standard_Failure) { + Handle(Standard_Failure) aFail = Standard_Failure::Caught(); + SetErrorCode(aFail->GetMessageString()); + return NULL; + } //Make a Python command TCollection_AsciiString anEntry, aListRes("["); @@ -2517,19 +2883,26 @@ GEOMImpl_IAdvancedOperations::MakePipeTShapeFillet Handle(TColStd_HSequenceOfTransient) aSeq = new TColStd_HSequenceOfTransient; aSeq->Append(aShape); - if (theHexMesh) { - // Get the groups - try { + try { + if (theHexMesh) { + // Get the groups if (!MakeGroups(aShape, TSHAPE_FILLET, theR1, theW1, theL1, theR2, theW2, theL2, 0., 0., theRF, aSeq, gp_Trsf())) return NULL; } - catch (Standard_Failure) { - Handle(Standard_Failure) aFail = Standard_Failure::Caught(); - SetErrorCode(aFail->GetMessageString()); + + // Get internal group. + if (!MakeInternalGroup(aShape, theR1, theL1, theR2, theL2, theRL, theLtransL, + theRR, theLtransR, theRI, theLtransI, + aSeq, gp_Trsf())) { return NULL; } } + catch (Standard_Failure) { + Handle(Standard_Failure) aFail = Standard_Failure::Caught(); + SetErrorCode(aFail->GetMessageString()); + return NULL; + } //Make a Python command TCollection_AsciiString anEntry, aListRes("["); @@ -2765,19 +3138,26 @@ GEOMImpl_IAdvancedOperations::MakePipeTShapeFilletWithPosition Handle(TColStd_HSequenceOfTransient) aSeq = new TColStd_HSequenceOfTransient; aSeq->Append(aShape); - if (theHexMesh) { - // Get the groups - try { + try { + if (theHexMesh) { + // Get the groups if (!MakeGroups(aShape, TSHAPE_FILLET, theR1, theW1, theL1, theR2, theW2, theL2, 0., 0., theRF, aSeq, aTrsf)) return NULL; } - catch (Standard_Failure) { - Handle(Standard_Failure) aFail = Standard_Failure::Caught(); - SetErrorCode(aFail->GetMessageString()); + + // Get internal group. + if (!MakeInternalGroup(aShape, theR1, theL1, theR2, theL2, theRL, theLtransL, + theRR, theLtransR, theRI, theLtransI, + aSeq, aTrsf)) { return NULL; } } + catch (Standard_Failure) { + Handle(Standard_Failure) aFail = Standard_Failure::Caught(); + SetErrorCode(aFail->GetMessageString()); + return NULL; + } //Make a Python command TCollection_AsciiString anEntry, aListRes("["); diff --git a/src/GEOMImpl/GEOMImpl_IAdvancedOperations.hxx b/src/GEOMImpl/GEOMImpl_IAdvancedOperations.hxx index 401ab372d..88cfaa223 100644 --- a/src/GEOMImpl/GEOMImpl_IAdvancedOperations.hxx +++ b/src/GEOMImpl/GEOMImpl_IAdvancedOperations.hxx @@ -37,6 +37,9 @@ class GEOMImpl_IBlocksOperations; class GEOMImpl_I3DPrimOperations; class GEOMImpl_ILocalOperations; class GEOMImpl_IHealingOperations; +class GEOMImpl_IGroupOperations; +class Handle_Geom_Surface; +class TopTools_ListOfShape; class GEOMImpl_IAdvancedOperations: public GEOM_IOperations { private: @@ -64,6 +67,26 @@ private: Handle(TColStd_HSequenceOfTransient) theSeq, gp_Trsf aTrsf); + bool GetFacesOnSurf(const TopoDS_Shape &theShape, + const Handle_Geom_Surface& theSurface, + const Standard_Real theTolerance, + TopTools_ListOfShape &theFaces); + + TopoDS_Shape MakeConicalFace(const gp_Ax2 &theAxis, + const double theRadius, + const double theRadiusThin, + const double theHeight, + const gp_Trsf &theTrsf); + + bool MakeInternalGroup(const Handle(GEOM_Object) &theShape, + const double theR1, const double theLen1, + const double theR2, const double theLen2, + const double theRL, const double theTransLenL, + const double theRR, const double theTransLenR, + const double theRI, const double theTransLenI, + const Handle(TColStd_HSequenceOfTransient) &theSeq, + const gp_Trsf &theTrsf); + gp_Trsf GetPositionTrsf(double theL1, double theL2, Handle(GEOM_Object) P1 = 0, Handle(GEOM_Object) P2 = 0, @@ -84,6 +107,7 @@ private: GEOMImpl_I3DPrimOperations* my3DPrimOperations; GEOMImpl_ILocalOperations* myLocalOperations; GEOMImpl_IHealingOperations* myHealingOperations; + GEOMImpl_IGroupOperations* myGroupOperations; public: