Итерация по всем точкам внутри GraphicsPath

157
09 августа 2018, 18:20

Товарищи, возник такой вопрос:
Положим, мы имеем некий GraphicsPath. Необходимо каким-то образом достать из него все точки с целыми координатами, которые удовлетворяют условию graphicsPath.IsVisible(x, y).

Дабы избежать проблемы XY, расскажу, для чего мне это необходимо: с помощью экземпляра GraphicsPath я пытаюсь задать множество точек, по которым необходимо пройтись в обрабатываемом мною изображении (а так как координаты каждого из пикселей - число целое, то и выбрать мне нужно лишь точки с целочисленными координатами).

Пока что у меня в коде висит такой костыльный вариант:

Image img = ...;
GraphicsPath path = ...;
for (int y = 0; y < img.Height; y++)
    for (int x = 0; x < img.Width; x++)
        if (path.IsVisible(x, y))
            ...

То есть я прохожусь по всем точкам изображения и работаю лишь с теми, что удовлетворяют заданным условиям. Данный метод является совершенно не оптимальным, ибо, предположим, если в GraphicsPath содержится всего одна точка, проход по тысячам других точек улетает впустую...

Думаю, в этом вопросе может помочь GraphicsPathIterator, который позволяет последовательно пройтись по всем добавленным "фигурам". Право, я все равно пока не совсем представляю алгоритма, который бы позволил мне по точкам контура получить все необходимые мне точки (то есть не только контура, но и те, что внутри него)

Буду крайне признателен любым соображениям по сему вопросу. Возможно, есть какие-то более простые пути, чем тот, которым я пытаюсь идти сейчас ¯\_(ツ)_/¯

UPD:

Попробовал использовать GraphicsPathIterator и предложенный метод GraphicsPath.GetBounds(). Получилось вот что:

public static IEnumerable<Point> GetInnerPoints(this GraphicsPath Path, float Deviation)
{
    Pen pen = new Pen(Color.White, Deviation);
    HashSet<Point> points = new HashSet<Point>();
    GraphicsPathIterator iter = new GraphicsPathIterator(Path);
    int length = iter.SubpathCount;
    for (int i = 0; i < length; i++)
    {
        GraphicsPath sub = new GraphicsPath();
        iter.NextSubpath(sub, out bool closed);
        RectangleF rect = sub.GetBounds();
        int minX = (int)rect.Left;
        int minY = (int)rect.Top;
        int maxX = (int)Math.Ceiling(rect.Right) + 1;
        int maxY = (int)Math.Ceiling(rect.Bottom) + 1;
        for (int y = minY; y < maxY; y++)
            for (int x = minX; x < maxX; x++)
                if (sub.IsVisible(x, y) || sub.IsOutlineVisible(x, y, pen))
                {
                    Point current = new Point(x, y);
                    if (!points.Contains(current))
                    {
                        points.Add(current);
                        yield return current;
                    }
                }
    }
}
public static IEnumerable<Point> GetInnerPoints(this GraphicsPath Path)
{
    return GetInnerPoints(Path, 0.1f);
}

Собственно, логика такова: я прохожусь по всем Subpath в данном GraphicsPath, исследуя лишь используемые ими площади и выцепляя нужные мне точки с целочисленными координатами. Сие работает вроде бы как надо, правда, подозреваю, можно все таки сделать лучше и куда oптимальнее ¯\_(ツ)_/¯

UPD2:

Пришел к выводу, что сей метод слишком медленный. К примеру, если в GraphicsPath добавить Rectangle, равный площади всего изображения, то метод работает в сотни раз медленнее, чем просто обработка всего изображения ¯\_(ツ)_/¯

READ ALSO
Распознание текста с картинки

Распознание текста с картинки

Как очень качественно распознать текст с помощью Tesseract или ему подобных ?

134
Можно ли поставить Visual Studio 2017 оффлайн?

Можно ли поставить Visual Studio 2017 оффлайн?

Привет есть офлайн установщий хочу поставить C# только можно без интеренета это сделать?

140
Как подключить БД к WPF?

Как подключить БД к WPF?

Хотел подключить SQl Server к WPF - Программа запускается и сразу же крашится, но ошибки не выдает

150
Yandex-php. open_basedir restriction in effect

Yandex-php. open_basedir restriction in effect

Warning: file_exists(): open_basedir restriction in effectFile(/tmp/guzzle-cacert

143