简体   繁体   English

我该如何简化图形路径?

[英]how can I simplify a graphicspath?

I'm creating a rather dense GraphicsPath by following the MouseMove event. 我正在通过跟随MouseMove事件创建一个相当密集的GraphicsPath。 Besides filtering during the movement, is there a routine to simplify the GraphicsPath after the fact? 除了在移动过程中进行过滤之外,还有一个例程可以在事后简化GraphicsPath吗?

I also want to implement a 'vector-based flood fill' now and this will create another really dense path. 我现在也想实现一个'基于矢量的洪水填充',这将创建另一个真正密集的路径。

I guess I will have to step through it and compare the directions of each line until it changes more than a limit or until the changes add up to this limit. 我想我必须逐步完成并比较每一行的方向,直到它改变超过限制或直到更改加起来达到此限制。 Or I could simply erase every other point. 或者我可以简单地删除其他每一点。 Rather crude. 相当粗鲁。

I had hoped for a built-in routine or a standard algorithm; 我曾希望有一个内置的例程或标准算法; but maybe I have not used the right search words..? 但也许我没有使用正确的搜索词......?

All suggestions appreciated. 所有建议都赞赏。

Reading this question I was reminded of my old post; 读到这个问题,我想起了我的旧职位; so I decided to finally implement a simple reduction scheme: 所以我决定最终实施一个简单的减少方案:

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

Here is a result with epsilon values of 1, 0.1 and 0.01: 这是epsilon值为1,0.1和0.01的结果:

在此输入图像描述

Note the the GraphicsPath.PathPoints are read-only, so we have to re-create the path from the new points list! 请注意, GraphicsPath.PathPoints是只读的,因此我们必须从新的点列表重新创建路径!

Update: I have updated the math to work with 1°/10 instead of slopes, replacing the Slope function with an Angle function.. This should give more uniform results over various directions.. 更新:我已经更新了数学与1°/ 10,而不是斜坡工作,更换Slope与功能Angle的功能。这应该给了不同的方向更均匀的结果..

Update 2: 更新2:

Kudos to ephraim; 感谢以法莲; I have added the suggested edits to use a proper starting angle.. 我添加了建议的编辑以使用正确的起始角度..

Have you looked into using GraphicsPath.GetBounds ? 您是否考虑过使用GraphicsPath.GetBounds There's a nice example on that page to. 该页面上有一个很好的例子。

"The size of the returned bounding rectangle is influenced by the type of end caps, pen width, and pen miter limit, and therefore produces a "loose fit" to the bounded path. The approximate formula is: the initial bounding rectangle is inflated by pen width, and this result is multiplied by the miter limit, plus some additional margin to allow for end caps." “返回的边界矩形的大小受端盖类型,笔宽和笔斜限制的影响,因此会对有界路径产生”松散拟合“。近似公式为:初始边界矩形被膨胀笔宽,此结果乘以斜接限制,加上一些额外的余量以允许结束。“

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM