简体   繁体   中英

how can I simplify a graphicspath?

I'm creating a rather dense GraphicsPath by following the MouseMove event. Besides filtering during the movement, is there a routine to simplify the GraphicsPath after the fact?

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:

在此输入图像描述

Note the the GraphicsPath.PathPoints are read-only, so we have to re-create the path from the new points list!

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

Update 2:

Kudos to ephraim; I have added the suggested edits to use a proper starting angle..

Have you looked into using 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."

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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