BRepMesh_EdgeTessellator: do not use points out of face range and edge tolerance.
Test cases for issue CR26692
//function : Value
//purpose :
//=======================================================================
-void BRepMesh_EdgeTessellationExtractor::Value(
+Standard_Boolean BRepMesh_EdgeTessellationExtractor::Value(
const Standard_Integer theIndex,
Standard_Real& theParameter,
gp_Pnt& thePoint,
theParameter = myProvider.Parameter(theIndex, thePoint);
theUV = myPCurve->Value(theParameter);
+
+ return Standard_True;
}
//! @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)
mySquareEdgeDef = aPreciseLinDef * aPreciseLinDef;
mySquareMinSize = Max(mySquareEdgeDef, theMinSize * theMinSize);
+ myEdgeSqTol = BRep_Tool::Tolerance (theEdge);
+ myEdgeSqTol *= myEdgeSqTol;
Standard_Boolean isSameParam = BRep_Tool::SameParameter(theEdge);
if (isSameParam)
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);
}
//=======================================================================
//! @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)
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)
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);
}
//! @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)
};
--- /dev/null
+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
--- /dev/null
+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