Эффективное проецирование 2D-плоскости на 1D-линию

У меня есть массив [width, height, x, y] векторов, например: [[width_1, height_1, x_1, y_1],...,[width_n, height_n, x_n, y_n]], представляющий 2D-плоскость блоков. Этот вектор потенциально длинный (n > 10k).

Пример:

введите здесь описание изображения

должны быть спроектированы как:

введите здесь описание изображения

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

введите здесь описание изображения

Критерий, по которому блок должен быть проектом, не имеет большого значения. В примере я взял первый (по оси x) самый большой; что кажется разумным.

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

Итак, как конкретно можно эффективно спроецировать 2D-плоскость на линию, в некотором смысле «отбрасывая тень», таким образом, чтобы сохранить метод наблюдения за тем, какие блоки участвуют в сегменте линии (тени)?

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


person JoelKuiper    schedule 27.03.2014    source источник
comment
как вы решаете, какой блок проецируется, а какой нет? Вы хотите сохранить историю для каждого блока? Не совсем понятно, что вы хотите...   -  person Chris Maes    schedule 27.03.2014
comment
@ChrisMaes в примере я предположил первый по величине. В редактировании я объясняю проблему более конкретно. У меня есть документ (например, html), для которого я хотел бы создать миникарту, которая может отображать аннотации. Я думаю, что эстетически более крупные блоки красивее, чем куча более мелких.   -  person JoelKuiper    schedule 27.03.2014


Ответы (1)


Предполагая, что прямоугольники всегда выровнены по осям, как в вашем примере, я бы использовал линию развертки подход:

  1. Отсортируйте вершины/основания прямоугольника в соответствии с их значением y. Для каждого элемента сохраните ссылку на полные данные прямоугольника.

  2. Просканируйте список в порядке возрастания y, сохраняя набор S прямоугольников, представляющих прямоугольники, содержащие текущее значение y. Для каждой вершины прямоугольника r добавьте r к S. Аналогично, для каждой нижней части r удалите r из S. Каждый раз, когда вы это делаете, сегмент закрывается и начинается новый. Если вы проверите S в этот момент, у вас есть все прямоугольники, которые участвуют в сегменте, так что это место для применения политики выбора цвета сегмента.

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

person Eyal Schneider    schedule 27.03.2014