Разделите ваше окно на w
на h
блоки. Вы будете поддерживать массив w
на h
, dist
. dist[x][y]
содержит размер наибольшего круга, который может быть центрирован в (x, y). (Вы можете использовать пиксели в качестве блоков, хотя мы будем обновлять весь массив с каждым размещенным кружком, поэтому вы можете выбрать более крупные блоки для повышения скорости за счет небольшого уменьшения плотности упаковки.)
1009 * инициализация *
Изначально установите все dist[x][y]
на min(x, y, w - x, h - y)
. Это кодирует пределы, заданные ограничительной рамкой, являющейся окном.
Процедура обновления
Каждый раз, когда вы добавляете в окно круг, скажем один, расположенный в (a, b)
с радиусом r
, вам необходимо обновить все элементов dist
.
Требуется обновление для каждой позиции (x, y)
:
dist[x][y] = min(dist[x][y], sqrt((x - a)^2 + (y - b)^2) - r);
(Очевидно, ^2
здесь означает возведение в квадрат, а не XOR.) По сути, мы говорим: «Установите dist [x] [y] на минимальное расстояние до только что установленного круга, если ситуация уже не хуже этого. «. dist
значения для точек внутри только что размещенного круга будут отрицательными, но это не имеет значения.
Поиск следующего местоположения
Затем, когда вы хотите вставить следующую окружность радиуса q
, просто отсканируйте через dist
в поисках места со значением dist
> = q
. (Если вы хотите случайным образом выбрать такое местоположение, найдите полный список действительных местоположений, а затем случайным образом выберите одно.)