§ Описание метода

Для того, чтобы вычислить точку пересечения луча с квадратом, для начала я приведу необходимую иллюстрацию
(0,0) (1,0) (0,1) (1,1)
Здесь указаны точки (0,0)-(1,1) это размер квадрата, в котором будет вестись поиск точки пересечения луча
x,y dx,dy
Давайте сначала рассмотрим следующее. В зависимости от того, куда будет направлен луч (в положительную или отрицательную сторону - вправо или влево, вверх или вниз), будет известно, о какую стенку он будет отбиваться. Направление вектора задается через (dx, dy) а начальная же точка вектора находится в x, y. Необходимо помнить, что x \in [0,1), y \in [0,1] .
Далее, если dx > 0, то это значит, что где бы не был x, то вектор пересечет только правую грань. Если dx < 0, то значит, вектор пересечет левую грань квадрата. Аналогично и с dy, если dy > 0, вектор пересечет нижнюю грань, иначе если dy < 0, то верхнюю грань.

§ Вычисление

Давайте представим, что у нас есть вектор dx,dy=(0.2, 0.1), а точка, в которой находимся x,y=(0.4, 0.3). Итак, первое, что точно уже известно, что точка пересечения будет либо на правой грани (потому что dx > 0) либо на нижней грани (потому что dy > 0). После того, как определились с гранями, надо узнать, на какое количество раз (возьмем как переменную cr) надо умножить вектор, чтобы его конец попал на одну из граней
Могут быть следующие ситуации
  • Если dx > 0, тогда расстояние от x до 1 (правая грань) будет 1-x а значит, что если это расстояние поделить на шаг dx, то и получим наш cr = \frac{1-x}{dx}
  • Если же dx < 0, то тогда расстояние до левой грани будет равно 0-x ну или просто -x, а количество шагов, которое надо сделать, будет равняться cr = \frac{0-x}{dx}
  • Если же dx = 0, то просто берем cr = 1000 (какое-нибудь большое число), чтобы показать, что количество шагов очень велико
Совершенно аналогично будет с dy, просто надо будет поменять x на y, dx на dy. Формулы остаются теми же для вычисления.

§ Выбор варианта

Теперь у нас есть все, чтобы найти точку пересечения с гранями. Вычислив cr для x, и cr для y, необходимо сравнить их друг с другом и выбрать наименьший. Почему так? Потому что надо найти наименьшее количество шагов, чтобы найти удар вектора от стенку. Это, думаю, вполне очевидно. Теперь же, после вычисления наименьшего, остается лишь умножить его на dx, dy и прирастить вектор
1/* Расчет количества шагов */
2float crx = dx > 0 ? (1 - x) / dx : (dx == 0 ? 1000 : -x / dx);
3float cry = dy > 0 ? (1 - y) / dy : (dy == 0 ? 1000 : -y / dy);
4
5/* Выбор наименьшего */
6float cr  = crx < cry ? crx : cry;
7
8/* Приращение */
9x += dx*cr;
10y += dy*cr;