Получить точки пересечения 2 прямоугольников

1

Как я могу получить точки пересечения двух прямоугольников. Я получил это до сих пор:

module.exports.boxIntersection = function(box1, box2) {
    var xMin1 = box1.x - box1.width;
    var xMin2 = box2.x - box2.width;
    var xMax1 = box1.x + box1.width;
    var xMax2 = box2.x + box2.width;
    var zMin1 = box1.z - box1.length;
    var zMin2 = box2.z - box2.length;
    var zMax1 = box1.z + box1.length;
    var zMax2 = box2.z + box2.length;
    var xMin = Math.max(xMin1, xMin2);
    var xMax = Math.min(xMax1, xMax2);
    if (xMax > xMin) {
        var zMin = Math.max(zMin1, zMin2);
        var zMax = Math.min(zMax1, zMax2);
        if (zMax > zMin) return [xMin, zMin, xMax, zMax];
    } return null;
};

Это возвращает только 2 точки пересечения. Но мне нужно, чтобы все точки пересечений возвращались так:

Изображение 174551

В таком случае, однако, он должен возвращать только 2 пункта:

Изображение 174551

Я увидел этот вопрос здесь: получить точки пересечения из 2 прямоугольников

Но он возвращает только 2 балла.

EDIT: в случае, когда прямоугольник выравнивается со стороной другого, должен возвращать только те точки, которые находятся на истинном пересечении, например: Изображение 174551

Теги:
collision
geometry
intersection

1 ответ

1
Лучший ответ

Ответ, который вы связываете, фактически "пересекает" прямоугольники как многоугольники, как многоугольные множества точек на плоскости, и возвращает нижние левые и верхние правые углы результирующего прямоугольника (как многоугольного множества). Две возвращенные точки фактически тривиально определяют все четыре угла результирующего прямоугольника. Таким образом, нет, он не "возвращает две точки". Он фактически возвращает четыре очка.

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

Или вы можете использовать несколько более хитрый подход.

Пусть говорят, что у нас есть два прямоугольника: (x11, y11)-(x12, y12) и (x21, y21)-(x22, y22). Прямоугольники нормализуются (как определено в ссылке). Мы все еще используем тот же метод min-max при вычислении прямоугольника перекрытия, но в то же время мы также запоминаем, какие исходные прямоугольники снабжали крайними значениями

int x1 = max(x11, x21);
unsigned flags_x1 = (x1 == x11) | ((x1 == x21) << 1);

int y1 = max(y11, y21);
unsigned flags_y1 = (y1 == y11) | ((y1 == y21) << 1);

int x2 = min(x12, x22);
unsigned flags_x2 = (x2 == x12) | ((x2 == x22) << 1);

int y2 = min(y12, y22);
unsigned flags_y2 = (y2 == y12) | ((y2 == y22) << 1);

Теперь мы проверяем, имеют ли эти прямоугольники правильное совпадение

if (x1 >= x2 || y1 >= y2)
 /* No overlap. Done */;

Но если существует перекрытие, мы используем наши flags_... variables для вывода только тех точек, которые формируются экстремальными значениями, которые поступают из двух разных прямоугольников

/* Lower-left */
if ((flags_x1 & flags_y1) == 0)
  /* Output (x1, y1) as intersection point */;

/* Lower-right */
if ((flags_x2 & flags_y1) == 0)
  /* Output (x2, y1) as intersection point */;

/* Upper-left */
if ((flags_x1 & flags_y2) == 0)
  /* Output (x1, y2) as intersection point */;

/* Upper-right */
if ((flags_x2 & flags_y2) == 0)
  /* Output (x2, y2) as intersection point */;

Обратите внимание, что если один прямоугольник полностью лежит внутри другого прямоугольника, то тест на перекрытие выше будет проходить (поскольку прямоугольники фактически перекрываются), но flags_... будут отбрасывать все четыре вершины.

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

  • 0
    Я добавил третью цифру к вопросу. Будет ли это работать в этом случае использования? И мои извинения, но я не знаком с этим синтаксисом в ответе; <<
  • 1
    @ Сидни де Врис: Мое текущее решение будет обрабатывать этот третий случай именно так, как вы его изобразили: оно не рассматривает внутреннее / внешнее «касание» как пересечение.
Показать ещё 5 комментариев

Ещё вопросы

Сообщество Overcoder
Наверх
Меню