Расположение квадратов по кругу с минимальным диаметром - PullRequest
18 голосов
/ 21 июля 2010

Учитывая n квадратов с длиной ребра l , как определить минимальный радиус r круга, чтобы я мог равномерно распределить все квадраты вдольпериметр круга без их перекрытия?(Ограничение: первый квадрат всегда будет располагаться в 12 часов.)

Дополнительный вопрос: как мне разместить n одинаковых прямоугольников с высотой ч и шириной ш ?

пример http://pub.n3rd.org/circle.png

Ответы [ 6 ]

12 голосов
/ 21 июля 2010

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

Что бы я сделал, это поместил бы эти квадраты в круг из 1 единицы (слишком маленький, я знаю, терпите меня), равномерно распределенный на нем. Это достаточно просто, просто сложите (разделите) свои 360 градусов на количество квадратов. Затем просто проверьте все свои квадраты на совпадение со своими соседями; если они перекрываются, увеличьте радиус.

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

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

РЕДАКТИРОВАТЬ У меня есть лучшее решение:

Я думал о том, что сказать вам, если вы спросите: "Как я узнаю, что квадраты перекрываются?" Это дало мне представление о том, как точно рассчитать размер круга за один шаг:

Поместите свои квадраты в слишком маленький круг. Вы знаете, как: вычислить точки на окружности, где ваши углы 360 / n пересекают его, и поместить центр квадрата туда. На самом деле вам пока не нужно размещать квадраты, для следующих шагов требуются только середины.

Чтобы вычислить минимальное расстояние квадрата до его соседа: вычислите разницу в X и разницу в Y средних точек и возьмите их минимум. X и Y на самом деле являются просто косинусами и синусами на круге.

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

Минимальное (X или Y) расстояние между квадратами должно стать 1,0. Так что просто возьмите обратную величину минимального расстояния и умножьте на это размер круга. Престо, твой круг подходящего размера.

EDIT

Не теряя общности, я думаю, что можно немного прибавить моё решение, так что оно близко к кодированию. Вот уточнение:

  • Предположим, квадраты имеют размер 1, т.е. каждая сторона имеет длину 1 единицу. В конце концов ваши поля наверняка будут больше 1 пикселя, но это только вопрос масштабирования.
  • Избавьтесь от угловых чехлов:

    if (n < 2) throw new IllegalArgumentException();
    if (n == 2) return 0.5; // 2 squares will fit exactly on a circle of radius 0.5
    
  • Начните с размера круга r, равного 0,5, что, безусловно, будет слишком маленьким для любого числа квадратов> 2.

    r = 0.5;
    dmin = 1.0; // start assuming minimum distance is fine
    a = 2 * PI / n;
    for (p1 = 0.0; p1 <= PI; p1+=a) { // starting with angle 0, try all points till halfway around
       // (yeah, we're starting east, not north. doesn't matter)
       p2 = p1 + a; // next point on the circle 
       dx = abs(r * cos(p2) - r * cos(p1))
       dy = abs(r * sin(p2) - r * sin(p1))
       dmin = min(dmin, dx, dy)
    }
    
    r = r / dmin;
    

EDIT

Я превратил это в настоящий код Java и получил что-то похожее на это для запуска. Код и результаты здесь: http://ideone.com/r9aiu

Я создал графический вывод, используя GnuPlot. Мне удалось создать простые диаграммы блоков, расположенных по кругу, вырезав и вставив наборы точек из выходных данных в файл данных, а затем запустив

plot '5.dat' with boxxyerrorbars

* * * * * * .5 в файле служат для определения размера блоков ... ленивое, но рабочее решение. .5 применяется к обеим сторонам от центра, поэтому размеры ящиков равны 1,0.

Увы, мой алгоритм не работает . Это делает радиусы слишком большими, таким образом помещая коробки намного дальше, чем необходимо. Даже уменьшение в 2 раза (возможно, было ошибкой использовать 0,5 в некоторых местах) не помогло.

Извините, я сдаюсь. Может быть, мой подход может быть спасен, но он не работает так, как я это сделал. (


EDIT

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

Алгоритм корректировал меньшие расстояний X или Y, чтобы они были как минимум 1. Легко показать, что это просто глупо.Если у вас много ящиков, то на восточном и западном краях круга у вас есть ящики, сложенные почти прямо друг на друге, с их X очень близко друг к другу, но они защищены от прикосновения, имея достаточное расстояние Y междуих.

Итак ... чтобы сделать эту работу, вы должны масштабировать максимум dx и dy, чтобы (во всех случаях) быть как минимум радиусом (или он был в два раза больше радиуса)??)коробки точно соприкасаются. Проблема решена! :)

Хостинг imgur.comХостинг imgur.com

(Эти изображения шире, чем они высокие, потому что GnuPlot не знал, что я хотел пропорционального расположения. Просто представьте, что все работы сжаты в квадратную форму :))

4 голосов
/ 21 июля 2010

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

Мой результат вычислений:

Rmin <= X /(sqrt (2) * sin (180 / N)) </p>

Где: X - длина стороны квадрата, а N - необходимое количество квадратов.

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

- EDIT -

Используя идею Дэйва в комментарии ниже, мы также можем вычислить хорошую нижнюю границу, учитываякруги должны быть внутри квадратов (таким образом, имея радиус X / 2).Эта граница:

Rmin> = X / (2 * sin (180 / N))

1 голос
/ 21 июля 2010

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

И, что касается вашего последующего вопроса: я предлагаю вам решить задачу для квадратов с длиной стороны min(h,w) на круге, а затем преобразовать квадраты в прямоугольники, а круг в эллипс с эксцентриситетом ч / ш или ш / ч).

0 голосов
/ 21 июля 2010

Предположим, что вы решили проблему за 3 или 4 квадрата.

Если у вас есть n > = 5 квадратов, и расположите один квадрат в верхней части круга, выПусть еще один квадрат попадет в первый квадрант декартовой плоскости, концентрической с вашим кругом.

Задача состоит в том, чтобы найти радиус r для круга таким образом, чтобы левая сторона круга была следующейк верхнему, и правая сторона верхнего круга не пересекаются.

x Координата правой стороны верхнего круга равна x1 = L / 2, где L - сторона квадрата.Координата x левой стороны круга рядом с верхней является x2 = r cos a - L / 2, где r - радиус, а a - угол между каждой парой квадратных центров ( a = 360 / n градусов).

Итак, нам нужно решить x1 <= <em>x2 , что приводит к

r > = L / cos a .

L и a известны, поэтому мысделано: -)

0 голосов
/ 21 июля 2010

Я бы решил это так:

Чтобы найти соотношение между радиусом r и длиной l, давайте проанализируем безразмерное представление

  • получим центры на окружности (x1, y1) .. (xn, yn)
  • из каждого центра получить нижний правый угол i-го квадрата и верхний левый угол i + 1-го квадрата
  • обе точки должны либоимеют равные x или равные y, в зависимости от того, что дает меньше l
  • процедура должна повторяться для каждого центра, а та, которая дает наименьшее значение l, является окончательным решением.

Это оптимальное решениеи могут быть решены его членами r = f (l).Решение может быть адаптировано к прямоугольникам путем корректировки формулы для xLR [i] и yUL [i + 1].

Попытка дать некоторый псевдокод.

РЕДАКТИРОВАТЬ:
Естьошибка в процедуре, нижний правый и верхний левый не являются необходимыми ближайшими точками для двух соседних квадратов / прямоугольников.

0 голосов
/ 21 июля 2010

Вы начинаете с произвольного круга (например, с диаметром (* n l)) и располагаете квадраты равномерно по окружности. Затем вы проходите через каждую пару соседних квадратов и:

  • рассчитать прямую линию, соединяющую их средние точки,
  • рассчитать пересечение этой линии с промежуточными квадратными сторонами (M1 и M2 - средние точки, S1 и S2 - соответствующие пересечения с квадратной стороной:

                    S2         S1
    M1--------------*----------*---------------M2
    
    ------------------------
    |                      |
    |                      |
    |                      |
    |                      |
    |          M1          |
    |           \          |
    |            \         |
    |      -------*------- +--------
    |      |       \       |       |
    |      |        \      |       |
    -------+---------*------       |
           |          \            |
           |           M2          |
           |                       |
           |                       |
           |                       |
           |                       |
           -------------------------
    
  • вычислите масштабный коэффициент, который вам понадобится, чтобы S1 и S2 сошлись вместе (просто отношение суммы M1-S1 и S2-M2 к M1-M2), и

окончательно масштабируйте круг по максимуму найденных масштабных коэффициентов.

Редактировать: Это точное решение. Тем не менее, небольшая мысль может еще больше оптимизировать скорость:

  • Это нужно сделать только для квадратов, ближайших к 45 ° (если четное n ), соответственно. 45 ° и 135 ° (если n нечетно; на самом деле вы можете доказать, что необходим только один из них).
  • Для больших n оптимальное расстояние между квадратами на круге будет быстро приближаться к длине диагонали квадрата. Таким образом, вы можете предварительно рассчитать коэффициенты масштабирования для нескольких маленьких n (до дюжины или около того), а затем получить достаточно хорошее приближение с диагональю.
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...