Ответ 1
Его называют минимальным окружным кругом ( "MEC" ) или иногда "наименьшим окружением".
Хороший сайт: http://www.personal.kent.edu/~rmuhamma/Compgeometry/MyCG/CG-Applets/Center/centercli.htm
Если круг определен X, Y его центра и радиуса, то как я могу найти круг, который охватывает заданное количество кругов? Один круг, который является наименьшим возможным кругом, полностью содержит 2 или более круга любого размера и местоположения.
Сначала я попытался просто охватить 2 круга, найдя середину центров и находясь в середине новой окружности, в то время как радиус был равен половине радиуса 2 начальных окружностей и половину расстояния между их центрами, но почему-то это всегда оказывалось немного неактивным. Проблема всегда представляла собой проблему с поиском радиуса, но у меня такая головная боль, и я не могу заставить ее работать.
Мне не обязательно нужен метод поиска круга, который охватывает 3 или более круга. Я могу найти круг, который охватывает 2, взять этот круг и охватить его другим, а другой, а последний круг должен охватывать все круги, заданные на всех этапах.
Его называют минимальным окружным кругом ( "MEC" ) или иногда "наименьшим окружением".
Хороший сайт: http://www.personal.kent.edu/~rmuhamma/Compgeometry/MyCG/CG-Applets/Center/centercli.htm
Учитывая два круга, с центрами [x1, y1], [x2, y2] и радиусами R1 и R2. Каков центр окружного круга?
Предположим, что R1 не больше R2. Если второй круг меньше, просто замените их.
Вычислить расстояние между центрами окружностей.
D = sqrt ((x1-x2) ^ 2 + (y1-y2) ^ 2)
Первый круг лежит внутри второго круга? Таким образом, если (D + R1) <= R2, то мы закончили. Верните большой круг в круг окружности с центром [x1, x2] с радиусом R2.
Если (D + R1) > R2, то окружная окружность имеет радиус (D + R1 + R2)/2
В этом последнем случае центр охватывающей окружности должен лежать вдоль линии, соединяющей два центра. Таким образом, мы можем написать новый центр как
center = (1-theta)*[x1,y1] + theta*[x2,y2]
где theta дается выражением
theta = 1/2 + (R2 - R1)/(2*D)
Заметим, что theta всегда будет положительным числом, так как мы заверили, что (D + R1) > R2. Аналогично, мы должны быть в состоянии обеспечить, чтобы theta никогда не превышала 1. Эти два условия гарантируют, что охватывающий центр лежит строго между двумя исходными центрами окружности.
Так как мое неточное решение не понравилось. Это способ получить точное решение. Но его медленный (O (N ^ 4)?) И вычислительно противный. (В отличие от неточного метода)
Сначала вам нужно знать, что, учитывая три круга, мы можем найти окружность, касательную к ним, чем содержащую все три. Это один из кругов Аполлония. Вы можете получить алгоритм из mathworld.
Далее вы можете показать, что наименьшая окружная окружность для N кругов тангенциальна по меньшей мере к 3 из N кругов.
Чтобы найти этот круг, мы делаем следующее
Могут быть некоторые приемы, чтобы ускорить это, но он должен дать точное решение. Некоторые из "трюков" для получения алгоритма Smallest Enclosing Circle для линейного времени могут быть применимы здесь, но я подозреваю, что они не будут тривиальными адаптациями.
Проблема, которую вы имеете под рукой, называется наименьшей охватывающей сферой сфер. Я написал свой тезис об этом, см. "Самый маленький охватывающий шар шаров" , ETH Zurich.
Вы можете найти очень эффективную реализацию С++ в Библиотека алгоритмов вычислительной геометрии (CGAL) в пакете Ограничение томов. (Нет необходимости использовать все CGAL, просто извлеките необходимые исходные файлы и файлы заголовков, и вы работаете.)
Примечание.. Если вы ищете алгоритм вычисления самой маленькой охватывающей сферы только точек, есть другие реализации там, см. этот пост.
Я собираюсь рекомендовать против этого, теперь
См. Обсуждение ниже.
Я бы рассмотрел итеративный метод push-pull.
distance_to_center_of_circle[i]+radius_of_circle[i]
и образуют векторную сумму по мере продвижения. Также обратите внимание, что нужный радиус в текущем местоположении является максимальным из этих длин.Вы закончите, когда он остановится [+].
В соответствии с просьбой уточнить второй шаг. Вызовите проверяемую позицию \vec{P}
(векторное количество). [+] Вызовите центры каждой окружности \vec{p}_i
(также векторные величины), а радиус каждой окружности - r_i
. Составьте сумму \sum_i=1^n \hat{p_i - P}*|(p_i-P)|+r_i)
. [+++] Каждый элемент суммы указывает в направлении от текущей точки оценки к центру рассматриваемого круга, но длиннее на r_i
. Сама сумма представляет собой векторную величину.
Радиус R
должен заключить весь круг из P
в max(|p_i-P|_r_i)
.
Я не думаю, что конкретный случай, который был поднят, является проблемой, но он поставил меня на случай, когда этот алгоритм терпит неудачу. Неудача - это неспособность улучшить решение, а не одно из расходящихся, но все же...
Рассмотрим четыре круга радиуса 1, расположенные в
(-4, 1)
(-5, 0)
(-4, 1)
( 5, 0)
и начальное положение (-1, 0)
. Симметричный по дизайну, так что все расстояния лежат вдоль оси х.
Правильное решение (0, 0)
с радиусом 6, но вектор, вычисленный на шаге 2, составляет около:: вычисляет яростно:: (-.63, 0)
, указывая в неправильном направлении, что приводит к тому, чтобы никогда не находить улучшение по отношению к началу координат.
Теперь приведенный выше алгоритм будет фактическим выбрать (-2, 0)
для начальной точки, которая дает начальную векторную сумму:: вычисляет яростно:: около +1.1. Таким образом, плохой выбор размера шага на (3) приведет к менее оптимальному решению.:: вздыхать::
Возможное решение:
Однако на данный момент это не намного лучше, чем чистое случайное блуждание, и у вас нет простого условия знать, когда он сходится. Мех.
[+] Или, конечно, замедляет ваше удовлетворение.
[++] Использование латексной нотации.
[+++] Здесь \hat{}
означает нормализованный вектор, указывающий в том же направлении, что и аргумент.
Я взял то, что некоторые из вас сказали, и вот решение, которое я обнаружил:
public static Circle MinimalEnclosingCircle(Circle A, Circle B) {
double angle = Math.Atan2(B.Y - A.Y, B.X - A.X);
Point a = new Point((int)(B.X + Math.Cos(angle) * B.Radius), (int)(B.Y + Math.Sin(angle) * B.Radius));
angle += Math.PI;
Point b = new Point((int)(A.X + Math.Cos(angle) * A.Radius), (int)(A.Y + Math.Sin(angle) * A.Radius));
int rad = (int)Math.Sqrt(Math.Pow(a.X - b.X, 2) + Math.Pow(a.Y - b.Y, 2)) / 2;
if (rad < A.Radius) {
return A;
} else if (rad < B.Radius) {
return B;
} else {
return new Circle((int)((a.X + b.X) / 2), (int)((a.Y + b.Y) / 2), rad);
}
}
Круг определяется центром X, Y его центра и радиусом, все являются ints. Там есть конструктор Circle (int X, int Y, int Radius). Выйдя из некоторых старых концепций триггеров, я решил, что лучший способ - найти 2 точки на кругах, которые находятся на расстоянии друг от друга. Как только у меня это будет, средняя точка будет центром, а половина расстояния будет радиусом, и, следовательно, мне будет достаточно, чтобы определить новый круг. Если я хочу охватить 3 или более круга, я сначала запустил это на 2 круга, затем запустил это на появляющемся окружении и другом круге и так далее до тех пор, пока не будет охвачен последний круг. Там может быть более эффективный способ сделать это, но сейчас это работает, и я доволен этим.
Мне кажется странным отвечать на мой вопрос, но я не мог прийти к этому решению без всяких идей и ссылок. Спасибо всем.
Просто понять уравнения circle и получить уравнение (или ряд) для поиска ответа, а затем начать реализацию. Возможно, мы сможем помочь вам в этом, если вы что-то сделали.
Итак, если вам не нужен точный круг, это может сделать приближение.
Все круги должны находиться внутри круга с центром в X с радиусом R1 + R2
Это не тривиальная проблема. Я не прочитал все ответы выше, поэтому, если я повторю то, что кто-то уже сказал, это моя проблема.
Каждый круг c_i определяется тремя параметрами x_i, y_i, r_i
Для оптимальной окружности C *
необходимо найти x *, y *, r *C * таков, что он содержит c_i для всех i
Пусть d_i = || (x, y) - (x_i, y_i) || + r_i
Тогда, если r - радиус круга, который содержит все c_i, то r >= d_i для всех i
Мы хотим, чтобы r было как можно меньше
Итак, r * = max (d_i)
Таким образом, мы хотим минимизировать максимум d_i
So (x *, y *) задаются аргументом arg min max (d_i). И один раз (x *, y *) найдутся, r * можно легко вычислить и будет равно max (d_i). Это минимаксная проблема.
Чтобы упростить понимание, рассмотрим только 2 круга, как мы можем найти (x *, y *)?
(x *, y *) можно найти, найдя (x, y), которые минимизируют (d_1 - d_2) ^ 2. В общем случае
пусть e_ij = (d_i - d_j) ^ 2
Затем определим e =\sum e_ij для я!= j (найдутся n) Из 2-х членов в этой сумме)
(x *, y *) = arg min e
И это то, что нужно решить.
Совет: если r_i = 0 для всех i, то это сводится к традиционной минимальной проблеме окружного круга, когда вход представляет собой кучу точек, и мы хотим найти минимальный круг, который покрывает все из них.