Исходные данные: направление (угол), координаты текущей ячейки (x,y).
Код: Выделить всё
sub nextcell($$$) {
#получаем исходные данные
my ($ang, $x, $y) = @_;
#дополнительные переменные
my ($K, $dx, $dy);
my ($temp1, $temp2);
#проверим, не вертикальное ли направление
$temp1 = sin($ang);
if (abs($temp1)==1) { $y+=$temp1; } # если да, то просто увеличиваем y-координату
else {
#проверим, не горизантальное ли направление
#но, в принципе, на горизонтальность можно не проверять
$temp2 = cos($ang);
if (abs($temp2)==1) { $x+=$temp2; } # если да, то просто увеличиваем x-координату
else {
#определим, в какую сторону изменяется x (влево(-1) или вправо(1))
$dx = $temp2>0 ? 1 : -1;
#определим коэффициент прямой и округлим до 12 знаков после запятой.
$K = sprintf("%.12f", $temp1/$temp2);
if (abs($K)==1) { #направление 45 градусов надо обработать отдельно
if (abs($y) > abs($x)) { $x+=$dx; }
elsif (abs($x) > abs($y)) { $y+=$K*$dx; }
elsif (abs($x) % 2) { $x+=$dx; }
else { $y+=$K*$dx; }
}
else { #общий случай
#определим, в какую сторону изменяется y (вниз(-1) или вверх(1) если dx = 1 и наоборот)
$dy = $K>0 ? $dx : -$dx;
#чтобы найти следующую ячейку, на определить, какую сторону ячейки пересекает прямая "на выходе". Рассмотрим случай когда движимся вправо вверх. Прямая может выйти либо через верхнюю сторону, либо через правую. Определим координату y, в которой прямая пересекает вертикаль, содержащую правую сторону ячейки и сравним с координатой y верхней стороны ячейки. Если больше первое, то прямая выходит через верхнюю сторону, если меньше - через правую.
$temp1 = sprintf("%.10f", abs($K * ($x + $dx * 0.5)) - ($y + $dy * 0.5));
if ($temp1 < 0) { $x += $dx; }
elsif ($temp1 > 0) { $y += $dy; }
elsif (abs($K) > 1) { $y += $dy; }
else { $x += $dx; }
}
}
}
# возвращем координаты следующей ячейки
return ($x, $y);
}