我正在按照 MouseMove 事件创建一个相当密集的 GraphicsPath。除了在移动过程中进行过滤之外,是否有一个例程来简化 GraphicsPath 的事后?
我现在还想实现一个“基于矢量的洪水填充”,这将创建另一个非常密集的路径。
我想我将不得不逐步检查它并比较每条线的方向,直到它的变化超过一个限制或直到变化加起来达到这个限制。或者我可以简单地删除所有其他点。比较粗糙。
我曾希望有一个内置的例程或标准算法;但也许我没有使用正确的搜索词..?
所有建议表示赞赏。
我正在按照 MouseMove 事件创建一个相当密集的 GraphicsPath。除了在移动过程中进行过滤之外,是否有一个例程来简化 GraphicsPath 的事后?
我现在还想实现一个“基于矢量的洪水填充”,这将创建另一个非常密集的路径。
我想我将不得不逐步检查它并比较每条线的方向,直到它的变化超过一个限制或直到变化加起来达到这个限制。或者我可以简单地删除所有其他点。比较粗糙。
我曾希望有一个内置的例程或标准算法;但也许我没有使用正确的搜索词..?
所有建议表示赞赏。
读到这个问题,我想起了我的旧帖子;所以我决定最终实现一个简单的缩减方案:
List<PointF> ReducePath(List<PointF> points, float epsilon)
{
if (points.Count < 3) return points;
var newPoints = new List<PointF>();
newPoints.Add(points[0]);
float delta = 0f;
float prevAngle = (float)(Angle(points[0], points[1]) /10f);
for (int i = 1; i < points.Count - 1; i++)
{
float ang = Angle(points[i-1], points[i])/10f;
delta += ang - prevAngle;
prevAngle = ang;
if (Math.Abs(delta) > epsilon)
{
delta = 0;
newPoints.Add(points[i]);
}
}
newPoints.Add(points[ points.Count -1]);
return newPoints;
}
float Angle(PointF p1, PointF p2)
{
if (p1.Y == p2.Y) return p1.X > p2.Y ? 0 : 180;
else if (p1.X == p2.X) return p1.Y > p2.Y ? 90 : 270;
else return (float)Math.Atan((p1.Y - p2.Y)/(p1.X - p2.X));
}
//float Slope(PointF p1, PointF p2)
//{
// if (p1.Y == p2.Y) return 0;
// else if (p1.X == p2.X) return 12345;
// else return (p1.Y - p2.Y)/(p1.X - p2.X);
//}
以下是 epsilon 值为 1、0.1 和 0.01 的结果:
注意GraphicsPath.PathPoints
是只读的,所以我们必须从新的点列表中重新创建路径!
更新:我已经更新了数学以使用 1°/10 而不是斜率,用Slope
函数替换Angle
函数..这应该在各个方向上给出更统一的结果..
更新 2:
向以法莲致敬;我添加了建议的编辑以使用正确的起始角度..
您是否考虑过使用GraphicsPath.GetBounds?该页面上有一个很好的示例。
“返回的边界矩形的大小受端盖类型、笔宽和笔斜接限制的影响,因此对有界路径产生“松散拟合”。近似公式为:初始边界矩形膨胀笔宽,这个结果乘以斜接限制,加上一些额外的边距以允许端盖。”