Дан угол, под которым луч выходит из начала координат (от -180 до 180) и угол на который он поворачивается (от -360 до 360). Требуется определить, пересечет ли он третий луч, угол которого также задан.
Есть ли какой-то простой алгоритм? Или нужно писать кучу if-ов учитывая пересечение первым лучом нуля, 180 или -180 градусов?
Здравствуйте, 777777w, Вы писали:
7>Дан угол, под которым луч выходит из начала координат (от -180 до 180) и угол на который он поворачивается (от -360 до 360). Требуется определить, пересечет ли он третий луч, угол которого также задан.
Третий? А где второй?
7>Есть ли какой-то простой алгоритм? Или нужно писать кучу if-ов учитывая пересечение первым лучом нуля, 180 или -180 градусов?
Здравствуйте, Dorofey, Вы писали:
7>>Дан угол, под которым луч выходит из начала координат (от -180 до 180) и угол на который он поворачивается (от -360 до 360). Требуется определить, пересечет ли он третий луч, угол которого также задан.
D>Третий? А где второй?
Второй это положение первого после поворота.
7>>Есть ли какой-то простой алгоритм? Или нужно писать кучу if-ов учитывая пересечение первым лучом нуля, 180 или -180 градусов?
D>Бррр, какие кучу if-ов? Ты хочешь написать 360 if-ов? Вау, индиан стайл солюшн
Чтобы было понятно — конкретный пример. Первый луч +10 градусов, поворачивается на -340 градусов. Пересечет ли он луч -20 градусов? +170? +20? Напиши выражение возвращающее bool.
Здравствуйте, 777777w, Вы писали:
7>Есть ли какой-то простой алгоритм? Или нужно писать кучу if-ов учитывая пересечение первым лучом нуля, 180 или -180 градусов?
Строим уравнения прямых, на которых лежат лучи. Ищем точку пересечения и проверяем, что она лежит в границах луча.
Если луч 1 повёрнут на угол alpha радиан, то уравнение его прямой будет:
-x*sin(alpha) + y*cos(alpha) = 0
Здравствуйте, Cyberax, Вы писали:
7>>Есть ли какой-то простой алгоритм? Или нужно писать кучу if-ов учитывая пересечение первым лучом нуля, 180 или -180 градусов? C>Строим уравнения прямых, на которых лежат лучи. Ищем точку пересечения и проверяем, что она лежит в границах луча.
Точка пересечения лучей всегда будет в начале координат независимо от углов.
Здравствуйте, 777777w, Вы писали:
7>Чтобы было понятно — конкретный пример. Первый луч +10 градусов, поворачивается на -340 градусов. Пересечет ли он луч -20 градусов? +170? +20? Напиши выражение возвращающее bool.
if (testAngle > startAngle &&
testAngle < (startAngle+rotateAngle))
Здравствуйте, 777777w, Вы писали:
7>>>Есть ли какой-то простой алгоритм? Или нужно писать кучу if-ов учитывая пересечение первым лучом нуля, 180 или -180 градусов? C>>Строим уравнения прямых, на которых лежат лучи. Ищем точку пересечения и проверяем, что она лежит в границах луча. 7>Точка пересечения лучей всегда будет в начале координат независимо от углов.
Можно детально задачу с рисунком?
Здравствуйте, 777777w, Вы писали:
7>Дан угол, под которым луч выходит из начала координат (от -180 до 180) и угол на который он поворачивается (от -360 до 360). Требуется определить, пересечет ли он третий луч, угол которого также задан.
7>Есть ли какой-то простой алгоритм? Или нужно писать кучу if-ов учитывая пересечение первым лучом нуля, 180 или -180 градусов?
Луч заметает некий интервал углов на окружности. Приводим этот интервал к полностью неотрицательному, добавляя при необходимости 2Pi или 4Pi так, чтобы левая точка интервала (неважно, начало это, или конец) стала неотрицательной, и лежала в диапазоне [0, 2Pi). Потом третью точку тоже делаем неотрицательной, и проверяем, что или она (X) или (X+2Pi) лежит внутри интервала
Здравствуйте, MBo, Вы писали:
MBo>Луч заметает некий интервал углов на окружности. Приводим этот интервал к полностью неотрицательному, добавляя при необходимости 2Pi или 4Pi так, чтобы левая точка интервала (неважно, начало это, или конец) стала неотрицательной, и лежала в диапазоне [0, 2Pi). Потом третью точку тоже делаем неотрицательной, и проверяем, что или она (X) или (X+2Pi) лежит внутри интервала
Добавлю, стоит еще разворачивать дугу, чтобы направление всегда было CW или CCW (смотря что выбрано за положительное направление).
Тогда пасьянс сходится.
_____________________
С уважением,
Stanislav V. Zudin
Здравствуйте, Stanislav V. Zudin, Вы писали:
SVZ>Добавлю, стоит еще разворачивать дугу, чтобы направление всегда было CW или CCW (смотря что выбрано за положительное направление).
Собственно, интервал (отрезок) ненаправленный, поэтому ориентация уже волновать не будет.
Здравствуйте, MBo, Вы писали:
MBo>Здравствуйте, Stanislav V. Zudin, Вы писали:
SVZ>>Добавлю, стоит еще разворачивать дугу, чтобы направление всегда было CW или CCW (смотря что выбрано за положительное направление).
MBo>Собственно, интервал (отрезок) ненаправленный, поэтому ориентация уже волновать не будет.
Нашел контрпример, когда алгоритм не сработает.
Поискал у себя в закромах.
В общем достаточно посчитать векторное произведение векторов SD и SE.
D — точка пересечения луча и окружности,
S — начало дуги, E — конец дуги.
Знак произведения показывает, попадает луч в дугу или нет.
В этом случае направление дуги не важно.
_____________________
С уважением,
Stanislav V. Zudin
Здравствуйте, Stanislav V. Zudin, Вы писали:
SVZ>Нашел контрпример, когда алгоритм не сработает.
А я пока не нашел...
SVZ>Поискал у себя в закромах. SVZ>В общем достаточно посчитать векторное произведение векторов SD и SE. SVZ> SVZ>Знак произведения показывает, попадает луч в дугу или нет. SVZ>В этом случае направление дуги не важно.
То есть как не важно? А если дуга рисуется от S к E против часовой стрелки? Тогда произведение останется прежним, но точка D попадает на дугу!
Задача выглядит так: попадает ли угловая координата НаправлениеЛуча2 в интервал [НачалоЛуча1, НачалоЛуча1 + ПоворотЛуча1].
Поскольку у нас есть зацикливание, то
— либо придётся распознать, что интервал вышел за область значений [-180,+180] — и тогда рассмотреть уже два интервала [-180,конец] и [начало,+180]
— либо размножить проверяемую точку — и проверить вхождение луч2, луч2-360, луч2+360 в интервал [начало,конец]
— либо размножить интервал — и проверить вхождение луч2 в [начало,конец], [начало-360,конец-360], [начало+360,конец+360]
Понятно, что проверять надо не три, а только два варианта — в зависимости от того, куда сместился оригинальный интервал.
Ну а если коротко, то
bool belongs(int a, int b, int c) // a <- [b,b+c]
{
assert(a >= -180 && a <= 180);
assert(b >= -180 && b <= 180);
assert(c >= -360 && c <= 360);
// быстрые проверкиif(c == 0) return a==b;
if(c == -360 || c == 360) return true;
int x, y; // [b,b+c] = [x,y]if(c < 0) { x=b+c; y=b; } else { x=b; y=b+c; } // упорядочиваем границы интервалаif(a < x) a += 360; // даём шанс - перемещаем точку вправо на полный циклreturn a>=x && a<=y;
}
Здравствуйте, 777777w, Вы писали:
7>Дан угол, под которым луч выходит из начала координат (от -180 до 180) и угол на который он поворачивается (от -360 до 360). 7>Есть ли какой-то простой алгоритм? Или нужно писать кучу if-ов учитывая пересечение первым лучом нуля, 180 или -180 градусов?
Если тебе важно не писать много условий, то можно обойтись одним:
угол t находится внутри сектора [s; s + a] только если cos(s – t + a/2) ≥ cos(a/2).
Очевидно, все случаи с периодичностью тут уже учтены внутри косинуса. Разумеется двукратное вычисление косинуса и является главным недостатком такого решения.
Здравствуйте, 777777w, Вы писали:
7>Дан угол, под которым луч выходит из начала координат (от -180 до 180) и угол на который он поворачивается (от -360 до 360). Требуется определить, пересечет ли он третий луч, угол которого также задан.
7>Есть ли какой-то простой алгоритм? Или нужно писать кучу if-ов учитывая пересечение первым лучом нуля, 180 или -180 градусов?
Вычислить угол между 1-м и 3-м лучём в направлении вращения 1-го луча.
Сравнить вычисленный угол с углом поворота.
Здравствуйте, 777777w, Вы писали:
7>Чтобы было понятно — конкретный пример. Первый луч +10 градусов, поворачивается на -340 градусов. Пересечет ли он луч -20 градусов? +170? +20? Напиши выражение возвращающее bool.
Что значит пересечет? Если все лучи исходят из начала координат, казалось бы, все они в начале координат и пересекаются между собой. Поэтому выражение будет состоять из одного слова, true
W>угол t находится внутри сектора [s; s + a] только если cos(s – t + a/2) ≥ cos(a/2). W>Разумеется двукратное вычисление косинуса и является главным недостатком такого решения.
Впрочем, от косинуса требуется лишь сравнение на больше–меньше, а не точное значение. Так что можно его заменить на похожую функцию, скажем на модуль и остаток от деления:
|180° – (|s – t + a/2| mod 360°)| ≥ 180° – |a/2|
Не то чтобы запись получилась короче, но зато никакой тригонометрии.