From 660b601eddd5f00778e7f330bff08349689dbf3c Mon Sep 17 00:00:00 2001 From: oan Date: Mon, 15 Feb 2016 19:33:29 +0300 Subject: [PATCH] 0026692: BRepMesh hangs on the attached shape due to tessellation points produced out of surface range BRepMesh_EdgeTessellator: do not use points out of face range and edge tolerance. Test cases for issue CR26692 --- .../BRepMesh_EdgeTessellationExtractor.cxx | 4 +- .../BRepMesh_EdgeTessellationExtractor.hxx | 10 ++-- src/BRepMesh/BRepMesh_EdgeTessellator.cxx | 46 +++++++++++++++++-- src/BRepMesh/BRepMesh_EdgeTessellator.hxx | 13 ++++-- src/BRepMesh/BRepMesh_FastDiscret.cxx | 37 +++++++++------ src/BRepMesh/BRepMesh_IEdgeTool.hxx | 10 ++-- tests/bugs/mesh/bug26692_1 | 18 ++++++++ tests/bugs/mesh/bug26692_2 | 18 ++++++++ 8 files changed, 125 insertions(+), 31 deletions(-) create mode 100644 tests/bugs/mesh/bug26692_1 create mode 100644 tests/bugs/mesh/bug26692_2 diff --git a/src/BRepMesh/BRepMesh_EdgeTessellationExtractor.cxx b/src/BRepMesh/BRepMesh_EdgeTessellationExtractor.cxx index d01f24d101..d85d0934bd 100644 --- a/src/BRepMesh/BRepMesh_EdgeTessellationExtractor.cxx +++ b/src/BRepMesh/BRepMesh_EdgeTessellationExtractor.cxx @@ -45,7 +45,7 @@ BRepMesh_EdgeTessellationExtractor::BRepMesh_EdgeTessellationExtractor( //function : Value //purpose : //======================================================================= -void BRepMesh_EdgeTessellationExtractor::Value( +Standard_Boolean BRepMesh_EdgeTessellationExtractor::Value( const Standard_Integer theIndex, Standard_Real& theParameter, gp_Pnt& thePoint, @@ -56,4 +56,6 @@ void BRepMesh_EdgeTessellationExtractor::Value( theParameter = myProvider.Parameter(theIndex, thePoint); theUV = myPCurve->Value(theParameter); + + return Standard_True; } diff --git a/src/BRepMesh/BRepMesh_EdgeTessellationExtractor.hxx b/src/BRepMesh/BRepMesh_EdgeTessellationExtractor.hxx index 82dbc8259b..5b847d39dd 100644 --- a/src/BRepMesh/BRepMesh_EdgeTessellationExtractor.hxx +++ b/src/BRepMesh/BRepMesh_EdgeTessellationExtractor.hxx @@ -57,10 +57,12 @@ public: //! @param theParameter parameters on PCurve corresponded to the solution. //! @param thePoint tessellation point. //! @param theUV coordinates of tessellation point in parametric space of face. - virtual void Value(const Standard_Integer theIndex, - Standard_Real& theParameter, - gp_Pnt& thePoint, - gp_Pnt2d& theUV) Standard_OVERRIDE; + //! @return True in case of valid result, false elewhere. + virtual Standard_Boolean Value( + const Standard_Integer theIndex, + Standard_Real& theParameter, + gp_Pnt& thePoint, + gp_Pnt2d& theUV) Standard_OVERRIDE; DEFINE_STANDARD_RTTIEXT(BRepMesh_EdgeTessellationExtractor,BRepMesh_IEdgeTool) diff --git a/src/BRepMesh/BRepMesh_EdgeTessellator.cxx b/src/BRepMesh/BRepMesh_EdgeTessellator.cxx index c59079d276..d1895602c1 100644 --- a/src/BRepMesh/BRepMesh_EdgeTessellator.cxx +++ b/src/BRepMesh/BRepMesh_EdgeTessellator.cxx @@ -54,6 +54,8 @@ BRepMesh_EdgeTessellator::BRepMesh_EdgeTessellator( mySquareEdgeDef = aPreciseLinDef * aPreciseLinDef; mySquareMinSize = Max(mySquareEdgeDef, theMinSize * theMinSize); + myEdgeSqTol = BRep_Tool::Tolerance (theEdge); + myEdgeSqTol *= myEdgeSqTol; Standard_Boolean isSameParam = BRep_Tool::SameParameter(theEdge); if (isSameParam) @@ -150,18 +152,54 @@ BRepMesh_EdgeTessellator::BRepMesh_EdgeTessellator( splitSegment(aSurf, aCurve2d, aParamArray(i), aParamArray(i + 1), 1); } } + + const Standard_Real aTol = Precision::Confusion(); + const Standard_Real aDu = mySurface->UResolution (aTol); + const Standard_Real aDv = mySurface->VResolution (aTol); + + myFaceRangeU[0] = mySurface->FirstUParameter() - aDu; + myFaceRangeU[1] = mySurface->LastUParameter() + aDu; + + myFaceRangeV[0] = mySurface->FirstVParameter() - aDv; + myFaceRangeV[1] = mySurface->LastVParameter() + aDv; } //======================================================================= //function : Value //purpose : //======================================================================= -void BRepMesh_EdgeTessellator::Value(const Standard_Integer theIndex, - Standard_Real& theParameter, - gp_Pnt& thePoint, - gp_Pnt2d& theUV) +Standard_Boolean BRepMesh_EdgeTessellator::Value( + const Standard_Integer theIndex, + Standard_Real& theParameter, + gp_Pnt& thePoint, + gp_Pnt2d& theUV) { myTool->Value(theIndex, mySurface, theParameter, thePoint, theUV); + + // If point coordinates are out of surface range, + // it is necessary to re-project point. + if (mySurface->GetType() != GeomAbs_BSplineSurface && + mySurface->GetType() != GeomAbs_BezierSurface && + mySurface->GetType() != GeomAbs_OtherSurface) + { + return Standard_True; + } + + // Let skip periodic case. + if (mySurface->IsUPeriodic() || mySurface->IsVPeriodic()) + return Standard_True; + + // Point lies within the surface range - nothing to do. + if (theUV.X() > myFaceRangeU[0] && theUV.X() < myFaceRangeU[1] && + theUV.Y() > myFaceRangeV[0] && theUV.Y() < myFaceRangeV[1]) + { + return Standard_True; + } + + gp_Pnt aPntOnSurf; + mySurface->D0 (theUV.X (), theUV.Y (), aPntOnSurf); + + return (thePoint.SquareDistance (aPntOnSurf) < myEdgeSqTol); } //======================================================================= diff --git a/src/BRepMesh/BRepMesh_EdgeTessellator.hxx b/src/BRepMesh/BRepMesh_EdgeTessellator.hxx index d560f602a1..80b184d3dd 100644 --- a/src/BRepMesh/BRepMesh_EdgeTessellator.hxx +++ b/src/BRepMesh/BRepMesh_EdgeTessellator.hxx @@ -58,10 +58,12 @@ public: //! @param theParameter parameters on PCurve corresponded to the solution. //! @param thePoint tessellation point. //! @param theUV coordinates of tessellation point in parametric space of face. - virtual void Value(const Standard_Integer theIndex, - Standard_Real& theParameter, - gp_Pnt& thePoint, - gp_Pnt2d& theUV) Standard_OVERRIDE; + //! @return True in case of valid result, false elewhere. + virtual Standard_Boolean Value( + const Standard_Integer theIndex, + Standard_Real& theParameter, + gp_Pnt& thePoint, + gp_Pnt2d& theUV) Standard_OVERRIDE; DEFINE_STANDARD_RTTIEXT(BRepMesh_EdgeTessellator,BRepMesh_IEdgeTool) @@ -80,6 +82,9 @@ private: BRepAdaptor_Curve myCOnS; Standard_Real mySquareEdgeDef; Standard_Real mySquareMinSize; + Standard_Real myEdgeSqTol; + Standard_Real myFaceRangeU[2]; + Standard_Real myFaceRangeV[2]; }; DEFINE_STANDARD_HANDLE(BRepMesh_EdgeTessellator, BRepMesh_IEdgeTool) diff --git a/src/BRepMesh/BRepMesh_FastDiscret.cxx b/src/BRepMesh/BRepMesh_FastDiscret.cxx index ff5019daaf..e78ba1e0bf 100644 --- a/src/BRepMesh/BRepMesh_FastDiscret.cxx +++ b/src/BRepMesh/BRepMesh_FastDiscret.cxx @@ -829,35 +829,44 @@ void BRepMesh_FastDiscret::update( else { const Standard_Integer aNodesNb = aEdgeTool->NbPoints(); - TColStd_Array1OfInteger aNewNodes (1, aNodesNb); - TColStd_Array1OfInteger aNewNodInStruct(1, aNodesNb); - TColStd_Array1OfReal aNewParams (1, aNodesNb); + TColStd_Array1OfInteger aNewNodesVec (1, aNodesNb); + TColStd_Array1OfInteger aNewNodesInStructVec(1, aNodesNb); + TColStd_Array1OfReal aNewParamsVec (1, aNodesNb); - aNewNodInStruct(1) = ipf; - aNewNodes (1) = isvf; - aNewParams (1) = aEAttr.FirstParam; - - aNewNodInStruct(aNodesNb) = ipl; - aNewNodes (aNodesNb) = isvl; - aNewParams (aNodesNb) = aEAttr.LastParam; + Standard_Integer aNodesCount = 1; + aNewNodesInStructVec(aNodesCount) = ipf; + aNewNodesVec (aNodesCount) = isvf; + aNewParamsVec (aNodesCount) = aEAttr.FirstParam; + ++aNodesCount; Standard_Integer aLastPointId = myAttribute->LastPointId(); for (Standard_Integer i = 2; i < aNodesNb; ++i) { gp_Pnt aPnt; gp_Pnt2d aUV; Standard_Real aParam; - aEdgeTool->Value(i, aParam, aPnt, aUV); + if (!aEdgeTool->Value(i, aParam, aPnt, aUV)) + continue; + myBoundaryPoints->Bind(++aLastPointId, aPnt); Standard_Integer iv2, isv; myAttribute->AddNode(aLastPointId, aUV.Coord(), BRepMesh_Frontier, iv2, isv); - aNewNodInStruct(i) = aLastPointId; - aNewNodes (i) = isv; - aNewParams (i) = aParam; + aNewNodesInStructVec(aNodesCount) = aLastPointId; + aNewNodesVec (aNodesCount) = isv; + aNewParamsVec (aNodesCount) = aParam; + ++aNodesCount; } + aNewNodesInStructVec(aNodesCount) = ipl; + aNewNodesVec (aNodesCount) = isvl; + aNewParamsVec (aNodesCount) = aEAttr.LastParam; + + TColStd_Array1OfInteger aNewNodes (aNewNodesVec.First (), 1, aNodesCount); + TColStd_Array1OfInteger aNewNodInStruct(aNewNodesInStructVec.First(), 1, aNodesCount); + TColStd_Array1OfReal aNewParams (aNewParamsVec.First(), 1, aNodesCount); + P1 = new Poly_PolygonOnTriangulation(aNewNodes, aNewParams); P2 = new Poly_PolygonOnTriangulation(aNewNodInStruct, aNewParams); } diff --git a/src/BRepMesh/BRepMesh_IEdgeTool.hxx b/src/BRepMesh/BRepMesh_IEdgeTool.hxx index c3493e0f51..6bbd84a74b 100644 --- a/src/BRepMesh/BRepMesh_IEdgeTool.hxx +++ b/src/BRepMesh/BRepMesh_IEdgeTool.hxx @@ -33,10 +33,12 @@ public: //! @param theParameter parameters on PCurve corresponded to the solution. //! @param thePoint tessellation point. //! @param theUV coordinates of tessellation point in parametric space of face. - virtual void Value(const Standard_Integer theIndex, - Standard_Real& theParameter, - gp_Pnt& thePoint, - gp_Pnt2d& theUV) = 0; + //! @return True in case of valid result, false elewhere. + virtual Standard_Boolean Value( + const Standard_Integer theIndex, + Standard_Real& theParameter, + gp_Pnt& thePoint, + gp_Pnt2d& theUV) = 0; DEFINE_STANDARD_RTTIEXT(BRepMesh_IEdgeTool,Standard_Transient) }; diff --git a/tests/bugs/mesh/bug26692_1 b/tests/bugs/mesh/bug26692_1 new file mode 100644 index 0000000000..881959ca93 --- /dev/null +++ b/tests/bugs/mesh/bug26692_1 @@ -0,0 +1,18 @@ +puts "========" +puts "OCC26692" +puts "========" +puts "" +####################################################################### +# BRepMesh hangs on the attached shape due to tessellation points produced out of surface range +####################################################################### + +restore [locate_data_file bug26692_face_bad_shading.brep] a + +vinit +vclear + +incmesh a 0.1 -a 2 + +vdisplay a +vfit +vdump ${imagedir}/${casename}.png diff --git a/tests/bugs/mesh/bug26692_2 b/tests/bugs/mesh/bug26692_2 new file mode 100644 index 0000000000..3f8ef7be11 --- /dev/null +++ b/tests/bugs/mesh/bug26692_2 @@ -0,0 +1,18 @@ +puts "========" +puts "OCC26692" +puts "========" +puts "" +####################################################################### +# BRepMesh hangs on the attached shape due to tessellation points produced out of surface range +####################################################################### + +restore [locate_data_file bug26692_face_bad_shading.brep] a + +vinit +vclear + +incmesh a 100 + +vdisplay a +vfit +vdump ${imagedir}/${casename}.png