1
0
mirror of https://git.dev.opencascade.org/repos/occt.git synced 2025-04-03 17:56:21 +03:00

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
This commit is contained in:
oan 2016-02-15 19:33:29 +03:00 committed by abv
parent 451c4a3a57
commit 660b601edd
8 changed files with 125 additions and 31 deletions

View File

@ -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;
}

View File

@ -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)

View File

@ -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);
}
//=======================================================================

View File

@ -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)

View File

@ -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);
}

View File

@ -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)
};

View File

@ -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

View File

@ -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