Хотя принятый ответ является правильным, я думаю, что стоит изучить этот ответ таким образом, чтобы обоснование ответа было совершенно очевидным.Это слишком распространенный алгоритм, чтобы иметь неполный (или, что еще хуже, противоречивый) ответ.Кроме того, лишь мельком взглянув на данную формулу, вы можете упустить красоту и расширяемость алгоритма, а также неявные решения, которые принимаются.
Во-первых, рассмотрим один из способов определения двумерного прямоугольника с помощью:
- (x, y) для верхней левой точки
- (x, y)для нижней правой точки
Это может выглядеть следующим образом:
Я указываю верхний левый с треугольником ивнизу справа с кружком.Это сделано для того, чтобы избежать непрозрачного синтаксиса, такого как x1, x2
для этого примера.
Два перекрывающихся прямоугольника могут выглядеть следующим образом:
Обратите внимание, что для поиска перекрытия вы ищете место, гдеоранжевый и синий сталкиваются:
Как только вы это узнаете, становится очевидным, что перекрытие является результатом нахождения и умножения этих двух затемненных линий:
Длина каждой линии - это минимальное значение точек окружности за вычетом максимального значения точек треугольника.
Здесь я использую двухцветную форму, чтобы показать, что сравниваются оранжевая и синяя точки.Маленькая буква после двухцветной формы указывает на то, что треугольники сравниваются вдоль этой оси (x или y).
Например, чтобы найти длину затемненной синей линии, можно увидеть, что оранжевые и синие треугольники сравниваются, чтобы найти максимальное значение междудва.Атрибут, который сравнивается, является атрибутом x.Максимальное значение x между оранжевым и синим треугольниками составляет 210.
Другой способ сказать то же самое: длина новой линии, которая подходит для обеих сравниваемых линий, определяется путем вычитанияближайшая точка на самой длинной стороне линии от самой дальней точки на ближайшей стороне линии.
Нахождение этих линий дает полную информацию о перекрывающихся областях.
Как только у вас есть это, найти процент перекрытия тривиально:
Но подождите, если оранжевый прямоугольник не совпадает с синим, у вас возникнет проблема:
В этом примере вы получаете -850 для нашей области перекрытия, что не может быть правильным.Еще хуже, если обнаружение не пересекается ни с одним из измерений (ни по оси x, ни по оси y), тогда вы все равно получите положительное число, поскольку оба измерения отрицательны.Вот почему вы видите Max(0, ...) * Max(0, ...)
как часть решения;это гарантирует, что если любое из перекрытий будет отрицательным, вы получите 0 обратно от вашей функции.
Окончательная формула в соответствии с нашей символикой:
Стоит отметить, что использование функции max(0, ...)
может не потребоваться,Возможно, вы захотите узнать, перекрывает ли что-то одно из своих измерений, а не все;если вы используете max, вы уничтожите эту информацию.По этой причине подумайте, как вы хотите работать с неперекрывающимися изображениями.Обычно функцию max можно использовать, но стоит знать, что она делает.
Наконец, обратите внимание, что, поскольку это сравнение касается только линейных измерений, его можно масштабировать до произвольных размеров или произвольных перекрывающихся четырехугольников.
Подведем итог:
intersecting_area =
max(0, min(orange.circle.x, blue.circle.x) - max(orange.triangle.x, blue.triangle.x)) * max(0, min(orange.circle.y, blue.circle.y) - max(orange.triangle.y, blue.triangle.y))
percent_coverage = intersecting_area / (orange_area + blue_area - intersecting_area)