Как я могу упростить графический путь?

Я создаю довольно плотный GraphicsPath, следуя событию MouseMove. Помимо фильтрации во время движения, есть ли рутина для упрощения GraphicsPath по факту?

Я также хочу реализовать "векторную заливку" сейчас, и это создаст еще один очень плотный путь.

Я предполагаю, что мне придется пройти через это и сравнить направления каждой линии, пока она не изменится больше, чем предел, или пока изменения не сложатся до этого предела. Или я мог бы просто стереть все остальные точки. Скорее сырая.

Я надеялся на встроенную процедуру или стандартный алгоритм; но, может быть, я не использовал правильные слова для поиска..?

Все предложения приветствуются.

2 ответа

Решение

Читая этот вопрос, я вспомнил свой старый пост; поэтому я решил наконец реализовать простую схему сокращения:

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

Вот результат со значениями эпсилона 1, 0,1 и 0,01:

Обратите внимание на GraphicsPath.PathPoints только для чтения, поэтому мы должны заново создать путь из нового списка точек!

Обновление: я обновил математику для работы с 1°/10 вместо уклонов, заменив Slope функция с Angle функция.. Это должно дать более единообразные результаты по различным направлениям..

Обновление 2:

Слава Ефрему; Я добавил предлагаемые правки, чтобы использовать правильный начальный угол.

Вы изучали использование GraphicsPath.GetBounds? На этой странице есть хороший пример.

"Размер возвращаемого ограничивающего прямоугольника зависит от типа заглушки, ширины пера и предела угла наклона пера и, следовательно, создает" свободную посадку "на ограниченном пути. Примерная формула: начальный ограничивающий прямоугольник надувается ширина пера, и этот результат умножается на предел митры плюс некоторый дополнительный запас, чтобы учесть заглушки ".

Другие вопросы по тегам