【问题标题】:how can I simplify a graphicspath?如何简化图形路径?
【发布时间】:2014-03-21 07:57:17
【问题描述】:

我正在通过关注 MouseMove 事件创建一个相当密集的 GraphicsPath。除了在运动过程中进行过滤,还有没有简化GraphicsPath事后的例程?

我现在还想实现“基于矢量的洪水填充”,这将创建另一个非常密集的路径。

我想我将不得不逐步遍历它并比较每条线的方向,直到它的变化超过一个限制或直到变化加起来达到这个限制。或者我可以简单地删除所有其他点。比较粗糙。

我曾希望有一个内置例程或标准算法;但也许我没有使用正确的搜索词..?

感谢所有建议。

【问题讨论】:

    标签: c# winforms simplify graphicspath


    【解决方案1】:

    阅读this question我想起了我的旧帖子;所以我决定最终实现一个简单的归约方案:

    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:

    向以法莲致敬;我添加了建议的编辑以使用正确的起始角度..

    【讨论】:

    • 这在 y=2x 的情况下没有帮助,它有一个很大的增量,但只需要 2 个点......更复杂的想法会比较不同斜率之间的差异。谢谢
    • 不确定您的示例是否正确,但感谢您提醒我修正数学问题。我希望我能很快纠正它。它真的应该通过使用切线来正确测量角度..
    • @ephraim :刚刚做了数学更新。如果你能做一些测试,我将不胜感激..
    • 您仍然遇到同样的问题。 y=2x 我的意思是你有一条直线,所有点之间没有任何变化,这就是为什么我添加 float prevAngle = (float)(Angle(points[0], points[1]) /10);循环之前和 inisde:delta += ang - prevAngle; prevAngle = ang;
    • 啊,你说得对;多谢!! - (我在开始代码之前有这个,然后决定不需要它。但更好的是更好;-)
    【解决方案2】:

    您是否考虑过使用 GraphicsPath.GetBounds ?该页面上有一个很好的示例。

    "返回的边界矩形的大小受端帽类型、笔宽和笔斜接限制的影响,因此对有界路径产生“松散拟合”。近似公式为:初始边界矩形被笔宽膨胀,这个结果乘以斜接限制,加上一些额外的边距以允许端盖。"

    【讨论】:

    • 路径的边界没有问题,我的点太多了。
    猜你喜欢
    • 2010-11-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-12-10
    • 1970-01-01
    • 1970-01-01
    • 2012-05-20
    • 2011-03-04
    相关资源
    最近更新 更多