Добавлен , опубликован
Передо мной стояла задача сделать проверку находится ли точка в произвольно повернутом прямоугольнике. Немного поискав на просторах интернета - я понял, что придется делать самому.
Сначала я попытался через обычные варовские ректы, но что то пошло не так:
Затем проверкой координат, но оно тоже не увенчалось успехом (извиняюсь за корявый чертеж):
После, друг присылает мне это:
"Интеграл по контуру".
В общем, суммируете углы AXB, BXC, CXD, DXA.
Если сумма равна ±360°, то точка внутри многоугольника.
Если сумма равна ±180°, то точка на ребре.
В остальных случаях точка снаружи.
После очередного корявого чертежа я убеждаюсь что скорее всего оно и правда так работает:
Но как теперь узнать углы, зная координаты точек? На помощь приходит Теорема косинусов прямиком из 9 класса Вот ссылка на вики, для конкретики
Я написал простенький код для нахождения углов таким способом:
function FindAngle takes location a, location b, location c returns real
    real bb = DistanceBetweenPoints(a, b)
    real cc = DistanceBetweenPoints(a, c)
    real aa = DistanceBetweenPoints(b, c)
    return Rad2Deg(Acos((bb*bb+cc*cc-aa*aa)/(2*bb*cc)))
endfunction
Ну и дописываю использующую ее, конечную функцию:
function IsInRectangle takes location loc, location a, location b, location c, location d returns boolean
    real q1 = FindAngle(loc, a, b)
    real q2 = FindAngle(loc, b, c)
    real q3 = FindAngle(loc, c, d)
    real q4 = FindAngle(loc, d, a)
    return q1+q2+q3+q4 > 359//>359 используется из за небольшого разброса
endfunction
И так, казалось бы успех. Все работает, но на тестах вдруг я обнаруживаю точки, в которых юниты иногда не детектятся, так сказать слепые зоны.
Используя кучу BJDebugMsg мне удается понять, что происходит не так:
Перебором определяется ситуация, при которой bb*bb+cc*cc-aa*aa равен -X, а 2*bb*cc X.
В результате их деления получается -1. Эта ситуация нам подходит, однако Acos такое число не нравится, и он выдает 0.
Фикс не заставляет себя ждать:
function FindAngle takes location a, location b, location c returns real
    real bb = DistanceBetweenPoints(a, b)
    real cc = DistanceBetweenPoints(a, c)
    real aa = DistanceBetweenPoints(b, c)
    real n = (bb*bb+cc*cc-aa*aa)/(2*bb*cc)
    if n == -1
    return 999.
    endif
    return Rad2Deg(Acos(n))
endfunction
Так как подобная ситуация всегда нам подходит, просто возвращаем 999, что приводит к тому что IsInRectangle возвращает true.
Я не знаю, интересен ли подобный контент или нет, поэтому если вам понравилось, дайте знать кнопкой.
`
ОЖИДАНИЕ РЕКЛАМЫ...
1
29
1 год назад
Отредактирован nazarpunk
1
Есть же наработка. Если вкратце, то ложим прямоугольник на оси и ищем обычным сравнением.
0
13
1 год назад
0
Есть же наработка.
Ее я проглядел. Хотя, самому писать иногда интереснее.
0
27
1 год назад
0
Чтобы оставить комментарий, пожалуйста, войдите на сайт.