Расчет границы вокруг нескольких связанных прямоугольников

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

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

Обновлено: не удалось заставить тег изображения работать должным образом, поэтому вот полная ссылка: http://www.flickr.com/photos/21093416@N04/3029621742/

У нас есть прямоугольники A и C, которые связаны специальным прямоугольником связи B. Вы можете представить это как два узла в графе (A, C) и границу между ними (B). Это означает, что прямоугольники имеют указатели друг на друга следующим образом: A-> B, A <-B-> C, C-> B

Каждый прямоугольник имеет четыре вершины, хранящиеся в массиве, где индекс 0 находится внизу слева, а индекс 3 - внизу справа.

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

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

Любой вклад приветствуется.

линии всегда будут вертикальными или горизонтальными? может быть перекрытие?

quick_dry 14.11.2008 15:06

Да, может быть перекрытие, это должно быть личное дело каждого. Пока линии всегда будут горизонтальными и вертикальными.

Nailer 14.11.2008 15:26
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
1
2
1 878
6
Перейти к ответу Данный вопрос помечен как решенный

Ответы 6

Простая уловка должна быть такой:

  1. Создайте область из первого прямоугольника
  2. Добавьте другие прямоугольники в область
  3. Получить границу региона (как-нибудь?: P)

Я голосую за этого, потому что думаю, что вы на правильном пути.

John 14.11.2008 20:48

Поразмыслив, я могу сделать что-то вроде этого:

Псевдокод:

 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)

Очевидно, этот псевдокод придется немного доработать, и он может не охватывать все случаи, но я думаю, что мог бы решить свою проблему.

Хм, немного подумав, нужно будет сделать несколько шагов, чтобы справиться с внутренними циклами и перекрытиями. Эта штука выходит из-под контроля.

Nailer 14.11.2008 15:32

Я не обдумал это полностью, но мне интересно, не могли бы вы сделать что-то вроде:

  • Составьте список всех краев.
  • Получите все ребра, где P1.X = P2.X
  • В этом списке найдите пары, в которых X равны
  • Для каждой пары замените одну или две кромки частей, где они НЕ перекрываются.
  • Сделайте что-нибудь умное, чтобы расположить края в правильном порядке

Будут ли ваши прямоугольники всегда выровнены по горизонтали, если нет, вам нужно будет сделать то же самое, но и для Y? И всегда ли они будут трогательными? В противном случае алгоритм не был бы нарушен, но «правильный порядок» не был бы определен.

Прямоугольники всегда будут касаться друг друга, а все линии будут горизонтальными или вертикальными.

Nailer 14.11.2008 15:30
  1. Вычислить сумму границ всех трех прямоугольников по отдельности.
  2. вычислить перекрывающийся прямоугольник A и B и вычесть его из суммы
  3. Сделайте то же самое для перекрывающегося прямоугольника B и C.

(чтобы получить перекрывающийся прямоугольник из A и B, займите 2 средние позиции X вместе со средними 2 положениями Y)

Пример (x1, y1) - (x2, y2):

  • Прямоугольник A: (1,1) - (3,4)
  • Прямоугольник B: (3,2) - (5,4)
  • Прямоугольник C: (4,3) - (6,6)

Расчет:

  1. 10 + 8 + 10 = 28
  2. Координаты X заказаны = 1,3,3,5, две средние - 3 и 3
    . Заказанные координаты Y = 1,2,4,4, две средние - 2 и 4
    . так: (3,2) - (3,4): boundery = 4
  3. Заказанные координаты X = 3,4,5,6, две средние - 4 и 5
    . Заказанные координаты Y = 2,3,4,6, две средние - 3 и 4
    . так: (4,3) - (5,4): boundery = 4
  4. 28 - 4 - 4 = 20

Это мой визуализированный пример:

   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)

Nailer 15.11.2008 17:59

Если посчитать, получится 20, как я и подсчитал. Если у вас есть другой пример, дайте мне знать. Я объясню, как это вычислить.

wimh 15.11.2008 19:06

Обобщенное решение этой проблемы - реализовать логические операции в терминах строки развертки. Вы можете найти краткое обсуждение здесь, чтобы начать работу. Из текста:

«Основа логических алгоритмов - строки развертки. По основным принципам очень хороша книга: Вычислительная геометрия - введение Франко П. Препарата и Майкла Яна Шамоса».

У меня есть эта книга, хотя сейчас она находится в офисе, поэтому я не могу найти номера страниц, которые вам следует прочитать, хотя глава 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, которая сделает всю работу за вас!

Мой коллега согласился, что это лучший подход к решению моей проблемы.

Nailer 18.11.2008 11:57

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