Страница 1 из 1

Добавлено: 05 апр 2004, 01:08
chur
Вот такой вот алгоритм (perl)
Исходные данные: направление (угол), координаты текущей ячейки (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);
}

Добавлено: 06 апр 2004, 11:04
chur
Нет, это алгоритм рисования якобы прямой.
Например. Начальная ячейка (0,0), угол 1 рад.
Вызываем функцию nextcell(1,0,0) - ответ: следущая ячейка (0,1)
Вызываем функцию еше раз: nextcell(1,0,1) - ответ: (1,1) и т.д.
nextcell(1,1,1) - (1,2)
nextcell(1,1,2) - (2,2)
nextcell(1,2,2) - (2,3)
nextcell(1,2,3) - (2,4)
nextcell(1,2,4) - (3,4)
nextcell(1,3,4) - (3,5)
nextcell(1,3,5) - (4,5)

Добавлено: 08 апр 2004, 03:20
Naeel Maqsudov
Короче надо построить дерево всех кратчайших путей из любой клетки до ценра.

Давайте попробуем так:
Центр известен, углы известны, поле ограничено (Как я понимаю 100x100) Cледовательно, можно
найти точки, находящиеся на краю поля и на лучах проведеных из центра под углами a и b.

Также можно определить все точки лежащие на краю поля между этими двумя точками (Это всегда самые удаленные точки от заданного центра, т.е. точки лежащие на краях поля). Таких точек будет 396, если разница между углами a и b 360 градусов.

Теперь берем алгоритм Брезенхема для построения прямой (самый первый, предложенный в этой дискуссии выше). И начинаем как бы строить отрезки от крайних точе к центру. Присваивая каждой точке номер, вес (уровень), и ссылку на предыдущую точку. НО в этот алгоритм добавим дополнительное условие выхода при попадании в точку, в которой мы уже побывали (ей уже будет присвоен номер, вес и т.д.)

Ну как?