Re[3]: Попадание луча между двумя другими лучами
От: sz36 Россия  
Дата: 19.12.13 22:30
Оценка:
Здравствуйте, 777777w, Вы писали:

7> Напиши выражение возвращающее bool.


Пожалуйста

  bool res=(rotateAngle > 0) ? (testAngle>startAngle && testAngle<(startAngle+rotateAngle)) 
                             : (testAngle<startAngle && testAngle>(startAngle+rotateAngle));
Re[4]: Попадание луча между двумя другими лучами
От: 777777w Россия  
Дата: 20.12.13 04:01
Оценка:
Здравствуйте, sz36, Вы писали:

S>
S>  bool res=(rotateAngle > 0) ? (testAngle>startAngle && testAngle<(startAngle+rotateAngle)) 
S>                             : (testAngle<startAngle && testAngle>(startAngle+rotateAngle));
S>


Если бы все было так просто, я бы не задавал таких вопросов. Простейший тестовый пример:

startAngle = 170
rotateAngle = 20
testAngle = -179

не выдерживает проверки этой формулой
Re[2]: Попадание луча между двумя другими лучами
От: 777777w Россия  
Дата: 20.12.13 04:04
Оценка:
Здравствуйте, watchmaker, Вы писали:

W>Здравствуйте, 777777w, Вы писали:


7>>Дан угол, под которым луч выходит из начала координат (от -180 до 180) и угол на который он поворачивается (от -360 до 360).

7>>Есть ли какой-то простой алгоритм? Или нужно писать кучу if-ов учитывая пересечение первым лучом нуля, 180 или -180 градусов?

W>Если тебе важно не писать много условий, то можно обойтись одним:

W>угол t находится внутри сектора [s; s + a] только если cos(s – t + a/2) ≥ cos(a/2).
W>Очевидно, все случаи с периодичностью тут уже учтены внутри косинуса.

Мне это совершенно не очевидно. Нельзя ли привести математическое доказательство?

W>Разумеется двукратное вычисление косинуса и является главным недостатком такого решения.


На дворе 21 век, поэтому вычисление косинуса не является препятствием. Гораздо более серьезным недостатком является то, что ни один придуманный мной тестовый пример не подтверждает работоспособность этого алгоритма.
Re: Попадание луча между двумя другими лучами
От: Буравчик Россия  
Дата: 20.12.13 06:44
Оценка:
Здравствуйте, 777777w, Вы писали:

7>Дан угол, под которым луч выходит из начала координат (от -180 до 180) и угол на который он поворачивается (от -360 до 360). Требуется определить, пересечет ли он третий луч, угол которого также задан.


7>Есть ли какой-то простой алгоритм? Или нужно писать кучу if-ов учитывая пересечение первым лучом нуля, 180 или -180 градусов?


Протестированное решение

a — угол первого луча
delta — угол поворота первого луча
b — угол луча, для которого требуется определить пересечет ли его первый луч при повороте

Алгоритм работает для любых a, delta, b (не только в диапазоне из задачи)

Решение: Изменяем систему координат таким образом, чтобы первый луч был равен нулю, а второй луч задан положительным углом (т.е. по часовой стрелке). Далее нам останется рассмотреть два варианта — либо угол поворота также положительный (по часовой стрелке), либо отрицательный (против часовой)

def cover(a, delta, b):
  # Шаг первый - поворачиваем систему координат на угол a
  b -= a
  a -= a
  
  # Шаг второй - если необходимо переворачиваем (отражаем) систему координат
  if b < 0:
    b = -b
    delta = -delta

  # Привели систему к виду:
  assert a == 0  
  assert b >= 0
 
  # Корректируем b, если он очень большой
  b = b % 360

  # Сравниваем нашу delta c углом b (b > 0)
  if delta >= 0:  # delta и b идут в одном направлении (по часовой)
    return delta >= b
  else:           # delta < 0, т.е. против часовой
    return -delta >= 360 - b
Best regards, Буравчик
Re[2]: Попадание луча между двумя другими лучами
От: Буравчик Россия  
Дата: 20.12.13 08:26
Оценка:
Здравствуйте, Буравчик, Вы писали:
Б>
Б>  # Сравниваем нашу delta c углом b (b > 0)
Б>  if delta >= 0:  # delta и b идут в одном направлении (по часовой)
Б>    return delta >= b
Б>  else:           # delta < 0, т.е. против часовой
Б>    return -delta >= 360 - b
Б>


Перепутал здесь "по часовой" и "против часовой", но это только в комментариях. На код не влияет
Best regards, Буравчик
Re[3]: Попадание луча между двумя другими лучами
От: watchmaker  
Дата: 20.12.13 10:10
Оценка:
Здравствуйте, 777777w, Вы писали:

W>>угол t находится внутри сектора [s; s + a] только если cos(s – t + a/2) ≥ cos(a/2).

W>>Очевидно, все случаи с периодичностью тут уже учтены внутри косинуса.
7>Мне это совершенно не очевидно.
Косинус — функция периодическая.
7>Нельзя ли привести математическое доказательство?
Идея такая:
Проверим, что угол 0 лежит внутри сектора, заметаемый вектором с началом в угле s при повороте на угол a. Возьмём биссектрису этого сектора, у неё будет угол (s+a/2). Любое направление, что находится внутри сектора, имеет угол между ним и биссектрисой меньше |a/2|. Всё что находится вне сектора имеет угол с биссектрисой больше |a/2|.
Берёшь пару единичных векторов U(cos(s+a/2), sin(s+a/2)) и V(1, 0) — один из них соответствует биссектрисе, второй — цели проверки. Скалярное произведение U·V = |U|·|V|·cos(i) = cos(i), где i — это искомый угол. Если он больше |a/2|, то вхождения нет, если меньше — есть. Но в если записать скалярное произведение покоординатно, то U·V = cos(s+a/2). Таким образом нужно просто решить, что же больше: cos(s+a/2) или cos(a/2).
Случай с произвольной целью t сводится просто к повороту всей конструкции на угол (-t). В этом случае a, разумеется, не меняется, а начало сектора переходит в (s – t). То есть сравнивать на больше–меньше придётся cos(s – t + a/2) и cos(a/2).

W>>Разумеется двукратное вычисление косинуса и является главным недостатком такого решения.


7>На дворе 21 век, поэтому вычисление косинуса не является препятствием. Гораздо более серьезным недостатком является то, что ни один придуманный мной тестовый пример не подтверждает работоспособность этого алгоритма.

То есть? Ты придумал миллиард примеров и на них всех формула дала верный ответ, но тебе нужно более полное доказательство?

Или ты нашел пример, где формула даёт неверный ответ? В таком случае, возможно, ты зря говоришь о том, что «вычисление косинуса не является препятствием» — вдруг ты в своём калькуляторе радианы с градусами перепутал при вычислениях, например.
Re[4]: Попадание луча между двумя другими лучами
От: 777777w Россия  
Дата: 20.12.13 14:36
Оценка:
Здравствуйте, watchmaker, Вы писали:

7>>Нельзя ли привести математическое доказательство?

W>Идея такая:
W>Проверим, что угол 0 лежит внутри сектора, заметаемый вектором с началом в угле s при повороте на угол a. Возьмём биссектрису этого сектора, у неё будет угол (s+a/2). Любое направление, что находится внутри сектора, имеет угол между ним и биссектрисой меньше |a/2|. Всё что находится вне сектора имеет угол с биссектрисой больше |a/2|.

Кажется дошло... Действительно должно работать, сейчас попробую.
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.