Товарищи, возник такой вопрос:
Положим, мы имеем некий 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
, равный площади всего изображения, то метод работает в сотни раз медленнее, чем просто обработка всего изображения ¯\_(ツ)_/¯
Кофе для программистов: как напиток влияет на продуктивность кодеров?
Рекламные вывески: как привлечь внимание и увеличить продажи
Стратегії та тренди в SMM - Технології, що формують майбутнє сьогодні
Выделенный сервер, что это, для чего нужен и какие характеристики важны?
Современные решения для бизнеса: как облачные и виртуальные технологии меняют рынок
Как очень качественно распознать текст с помощью Tesseract или ему подобных ?
Привет есть офлайн установщий хочу поставить C# только можно без интеренета это сделать?
Хотел подключить SQl Server к WPF - Программа запускается и сразу же крашится, но ошибки не выдает
Warning: file_exists(): open_basedir restriction in effectFile(/tmp/guzzle-cacert