Я работаю над проектом, в котором мне нужно создать границу вокруг группы прямоугольников.
Давайте использовать это изображение как пример того, чего я хочу достичь.
Обновлено: не удалось заставить тег изображения работать должным образом, поэтому вот полная ссылка: http://www.flickr.com/photos/21093416@N04/3029621742/
У нас есть прямоугольники A и C, которые связаны специальным прямоугольником связи B. Вы можете представить это как два узла в графе (A, C) и границу между ними (B). Это означает, что прямоугольники имеют указатели друг на друга следующим образом: A-> B, A <-B-> C, C-> B
Каждый прямоугольник имеет четыре вершины, хранящиеся в массиве, где индекс 0 находится внизу слева, а индекс 3 - внизу справа.
Я хочу «пройти» по этой связанной структуре и вычислить вершины, составляющие границу (красная линия) вокруг нее. У меня уже есть несколько небольших идей, как этого добиться, но я хочу знать, есть ли у некоторых из вас, более склонных к математике, какие-нибудь изящные уловки в рукавах.
Причина, по которой я публикую это здесь, заключается в том, что кто-то мог решить аналогичную проблему раньше, и у меня есть некоторые идеи, которые я мог бы использовать. Я не ожидаю, что кто-то сядет и долго и усердно обдумает это. Я буду работать над решением параллельно, пока жду ответов.
Любой вклад приветствуется.
Да, может быть перекрытие, это должно быть личное дело каждого. Пока линии всегда будут горизонтальными и вертикальными.





Простая уловка должна быть такой:
Я голосую за этого, потому что думаю, что вы на правильном пути.
Поразмыслив, я могу сделать что-то вроде этого:
Псевдокод:
LinkRectsConnectedTo(Rectangle rectangle,Edge startEdge) // Edge can be West,North,East,South
for each edge in rectangle starting with the edge facing last rectangle
add vertices in the edge to the final boundary polygon
if edge is connected to another rectangle
if edge not equals startEdge
recursively call LinkRectsConnectedTo(rectangle,startEdge)
Очевидно, этот псевдокод придется немного доработать, и он может не охватывать все случаи, но я думаю, что мог бы решить свою проблему.
Хм, немного подумав, нужно будет сделать несколько шагов, чтобы справиться с внутренними циклами и перекрытиями. Эта штука выходит из-под контроля.
Я не обдумал это полностью, но мне интересно, не могли бы вы сделать что-то вроде:
Будут ли ваши прямоугольники всегда выровнены по горизонтали, если нет, вам нужно будет сделать то же самое, но и для Y? И всегда ли они будут трогательными? В противном случае алгоритм не был бы нарушен, но «правильный порядок» не был бы определен.
Прямоугольники всегда будут касаться друг друга, а все линии будут горизонтальными или вертикальными.
(чтобы получить перекрывающийся прямоугольник из A и B, займите 2 средние позиции X вместе со средними 2 положениями Y)
Пример (x1, y1) - (x2, y2):
Расчет:
Это мой визуализированный пример:
1 2 3 4 5 6
1 +---+---+
| |
2 + A +---+---+
| | B |
3 + + +---+---+
| | | | |
4 +---+---+---+---+ +
| |
5 + C +
| |
6 +---+---+
Я не уверен, чего вы пытаетесь достичь с помощью своего алгоритма. Как это поможет мне создать граничный многоугольник вокруг моих прямоугольников? Что в вашем примере будет состоять из следующих точек: (1,1), (3,1), (3,2), (5,2), (5,3), (6,3), (6, 6), (4,6), (4,4), (1,4)
Если посчитать, получится 20, как я и подсчитал. Если у вас есть другой пример, дайте мне знать. Я объясню, как это вычислить.
Обобщенное решение этой проблемы - реализовать логические операции в терминах строки развертки. Вы можете найти краткое обсуждение здесь, чтобы начать работу. Из текста:
«Основа логических алгоритмов - строки развертки. По основным принципам очень хороша книга: Вычислительная геометрия - введение Франко П. Препарата и Майкла Яна Шамоса».
У меня есть эта книга, хотя сейчас она находится в офисе, поэтому я не могу найти номера страниц, которые вам следует прочитать, хотя глава 8 о геометрии прямоугольников, вероятно, является лучшей отправной точкой.
Используя пример, где прямоугольники перпендикулярны друг другу и поэтому могут быть представлены четырьмя значениями (двумя координатами x и двумя координатами y):
1 2 3 4 5 6
1 +---+---+
| |
2 + A +---+---+
| | B |
3 + + +---+---+
| | | | |
4 +---+---+---+---+ +
| |
5 + C +
| |
6 +---+---+
1) собрать все координаты x (как слева, так и справа) в список, затем отсортировать его и удалить дубликаты
1 3 4 5 6
2) соберите все координаты y (как верхние, так и нижние) в список, затем отсортируйте его и удалите дубликаты
1 2 3 4 6
3) создать 2D-массив по количеству промежутков между уникальными координатами x * количеству промежутков между уникальными координатами y. Это должен быть только один бит на ячейку, поэтому в С ++ вектор <bool>, вероятно, даст вам очень эффективную с точки зрения памяти версию этого
4 * 4
4) закрасьте все прямоугольники в эту сетку
1 3 4 5 6
1 +---+
| 1 | 0 0 0
2 +---+---+---+
| 1 | 1 | 1 | 0
3 +---+---+---+---+
| 1 | 1 | 1 | 1 |
4 +---+---+---+---+
0 0 | 1 | 1 |
6 +---+---+
5) для каждой ячейки в сетке, для каждого края, если ячейка рядом с ней в этом кардинальном направлении не закрашена, проведите граничную линию для этого края.
В вопросе прямоугольники описываются как четыре вектора, каждый из которых представляет собой угол. Если каждый прямоугольник может вращаться произвольно и отличаться от других, то описанный выше подход не будет работать. Проблема поиска пути вокруг сложного многоугольника регулярно решается растеризаторами векторной графики, и хороший подход к решению проблемы - использование библиотеки, такой как Cairo, которая сделает всю работу за вас!
Мой коллега согласился, что это лучший подход к решению моей проблемы.
линии всегда будут вертикальными или горизонтальными? может быть перекрытие?