Ответ зависит немного от количества прямоугольников, которые у вас есть. Метод грубой силы проверяет ваши координаты против каждой прямоугольной пары, в свою очередь:
found = false
for each r in rectangles:
if point.x > r.x1 && point.x < r.x2:
if point.y > r.y1 && point.y < r.y2
found = true
break
Вы можете получить более эффективным путем сортировки прямоугольников в регионах, и, глядя на «ограничивающими прямоугольниками». Затем вы выполняете двоичный поиск через дерево постоянно уменьшающихся ограничивающих прямоугольников. Это занимает немного больше работы, но делает поиск O (ln (n)), а не O (n) - для больших наборов прямоугольников и многих поисков, улучшение производительности будет значительным. Вы можете увидеть версию этого (которая смотрит на пересечение прямоугольника с набором прямоугольников - но вы легко адаптируетесь к «точке внутри») в this earlier answer. В более общем плане, посмотрите на тему quad trees, которые являются именно такой структурой данных, которая вам понадобится для двумерной задачи.
Немного менее эффективный (но более быстрый) метод сортирует прямоугольники в нижнем левом углу (например) - вам тогда нужно искать только подмножество прямоугольников.
Если координаты являются целыми числами, вы можете сделать двоичную маску - тогда поиск является одной операцией (в вашем случае для этого потребуется таблица поиска 512 МБ). Если ваше пространство относительно малонаселено (т. Е. Вероятность «промаха» достаточно велика), вы могли бы рассмотреть возможность использования недокадровой битовой карты (например, используя координаты/8), - тогда размер карты уменьшится до 8 М, а если у вас есть «нет» хит ", вы сэкономите себя на счет более пристального изучения. Конечно, вы должны округлить левый/нижний и округлить верхние/правые координаты, чтобы сделать эту работу правильной.
Расширение немного с примером:
Imagine координаты могут быть только 0 - 15 х, и 0 - 7 у. Есть три прямоугольника (все [x1 y1 x2 y2]
:. [2 3 4 5]
, [3 4 6 7]
и [7 1 10 5]
Мы можем сделать это в матрице (я отмечаю нижний левый угол с номером прямоугольника - обратите внимание, что 1 и 2 перекрытия):
...xxxx.........
...xxxx.........
..xxxxx.........
..x2xxxxxxx.....
..1xx..xxxx.....
.......xxxx.....
.......3xxx.....
................
Вы можете превратить это в массив нулей и единиц - так что «есть ли прямоугольник в этой точке» - это то же самое, что «этот бит установлен». Один поиск даст вам ответ. Чтобы сэкономить место, вы можете уменьшить размер массив - если по-прежнему нет удара, у вас есть свой ответ, но если есть удар, вам нужно будет проверить «это реально» - поэтому он экономит меньше времени, а экономия зависит от разреженности вашей матрицы (sparser = faster). Подвыборный массив будет выглядеть следующим образом (2x понижающая дискретизация):
.oxx....
.xxooo..
.oooxo..
...ooo..
Я использую x
, чтобы отметить «если вы нажмете эту точку, вы уверены, что в прямоугольнике», и o
сказать «некоторые из них прямоугольник». Многие из пунктов теперь «возможно», и меньше времени сохраняется. Если вы сделали более серьезную понижающую дискретизацию, вы можете подумать о наличии двухбитовой маски: это позволит вам сказать, что «весь этот блок заполнен прямоугольниками» (т.- дальнейшая обработка не требуется: x
выше) или «дополнительная обработка необходима» (например, o
выше). Это скоро начинает усложняться, чем подход Q-дерева ...
Нижняя линия: чем больше сортировка/организация прямоугольников вы делаете спереди, тем быстрее вы можете выполнять поиск.
@pablochan Добавлен к вопросу. – marshall
Сколько их много? – pablochan
это можно сделать с помощью 2D BIT, если координаты x и y вершин прямоугольника невелики (т. Е. В пределах 10^3). – Fallen