Использование неинициализированного значения $ d в делении {/} в - PullRequest
0 голосов
/ 19 марта 2019

Итак, я занимался поиском и поиском других сайтов, моя консоль заполнена всеми этими предупреждениями. Просто немного не уверен, как исправить этот метод в целом. Кроме того, я надеюсь, что мой код не расплывчатый, так как я не слишком уверен, достаточно ли здесь кода. Независимо от этого здесь проблема. Некоторое время я пытался интегрировать скрипт Perl в мой модуль. Сам скрипт работает, но не в модуле. Сообщение об ошибке при попытке запустить именно этот метод:

 sub generate_pillars_shape{
    my $d=$_[4];
    @X_values=$_[0]/$d..$_[1]/$d;
    @X_values=map{$_*$d} @X_values;
    @Y_values=$_[2]/$d..$_[3]/$d;
    @Y_values=map{$_*$d} @Y_values;
    for $i (0..$#X_values){
    @Y=(@Y,@Y_values);
    for $j (0..$#Y_values){
        $X[$i*($#Y_values+1)+$j]= $X_values[$i];
    }
    }
    return (\@X,\@Y);
}

Весь код состоит из этого:

use 5.010;
use Math::Trig ':radial';
use Math::Trig;
use List::Util qw(max min);

my $min_X=0;
my $max_X=60;
my $min_Y=0;
my $max_Y=60;
my $distance=10;
my @X_values;
my @Y_values;
my $i;
my $j;

#The minimum angle from horizontl your printer can make, in degrees
my $min_angle= 30;

#Ignore the next line, it is not an input parame
my @Z;
my ($X_ref,$Y_ref)= generate_pillars_shape($min_X,$max_X,$min_Y,$max_Y,$distance);my @X=@$X_ref;my @Y=@{$Y_ref};
for my $i (0..$#X){
    $Z[$i]=20;#The function that defined the height of each point. This setting wil give you a flat roof. For a more advanced tree, try:
    #$Z[$i]=-0.01*$X[$i]**2+0.2*$Y[$i]-0.005*$Y[$i]**2+20;
}

#End of input parameters.

my $min_radian = deg2rad($min_angle);
my $b = tan($min_radian);
@Z=map{$_/$b} @Z;



while ($#X>0){
  my ($I,$J)=find_min_dist(\@X,\@Y,\@Z);
  my ($X_branch,$Y_branch,$Z_branch)=find_branch($X[$I],$Y[$I],$Z[$I],$X[$J],$Y[$J],$Z[$J]);
  my @X_list= ($X_branch,$X[$I],$X[$J]);
  my @Y_list= ($Y_branch,$Y[$I],$Y[$J]);
  my @Z_list= ($Z_branch,$Z[$I],$Z[$J]);
  for my $j (0..$#Y_list){
      if (abs($X_list[my $j]) < 0.001){
      $X_list[$j]=0;
      }
      if (abs($Y_list[my $j]) < 0.001){
      $Y_list[$j]=0;
      }
      if (abs($Z_list[my $j]) < 0.001){
      $Z_list[$J]=0;
      }
  }
  branch (\@X_list,\@Y_list,\@Z_list);
  splice (@X,$I,1,$X_branch);
  splice (@X,$J,1);
  splice (@Y,$I,1,$Y_branch);
  splice (@Y,$J,1);
  splice (@Z,$I,1,$Z_branch);
  splice (@Z,$J,1);
}

sub generate_pillars_shape{
    my $d=$_[4];
    @X_values=$_[0]/$d..$_[1]/$d;
    @X_values=map{$_*$d} @X_values;
    @Y_values=$_[2]/$d..$_[3]/$d;
    @Y_values=map{$_*$d} @Y_values;
    for $i (0..$#X_values){
    @Y=(@Y,@Y_values);
    for $j (0..$#Y_values){
        $X[$i*($#Y_values+1)+$j]= $X_values[$i];
    }
    }
    return (\@X,\@Y);
}

sub branch{
  my @X=@{ $_[0] };
  my @Y=@{ $_[1] };
  my @Z=@{ $_[2] };
  @Z=map{$_*$b}@Z;
  for my $i (1..$#X){
    my ($rho, $theta, $phi) = cartesian_to_spherical($X[$i]-$X[0],$Y[$i]-$Y[0],$Z[$i]-$Z[0]);
    $phi = rad2deg($phi);
    if (abs($phi)<0.001){$phi=0;}
    $theta = rad2deg($theta)+90;
    if (abs($theta)<0.001){$theta=0;}
    if (abs($rho)>0.001){}
  }
}

sub find_min_dist{
  my @X=@{ $_[0] };
  my @Y=@{ $_[1] };
  my @Z=@{ $_[2] };
  my $min_dist=($X[0]-$X[1])**2+($Y[0]-$Y[1])**2+($Z[0]-$Z[1])**2;
  my $max_Z=$Z[0];
  my $I=0;
  my $J=1;
  for my $i (1..$#Z){
      if ($Z[$i]>=$max_Z){
      $max_Z=$Z[$i];
      my $I=$i;}
  }
  for my $j (0..$#X){
    if ($j!=$I){
      my $dist=(($X[$I]-$X[$j])**2+($Y[$I]-$Y[$j])**2+($Z[$I]-$Z[$j])**2);
      if ($min_dist>$dist){
    $min_dist=$dist;
    my $J=$j;
      }}}
  return ($I,$J);
}

sub find_branch{
  my $X1=$_[0];
  my $Y1=$_[1];
  my $Z1=$_[2];
  my $X2=$_[3];
  my $Y2=$_[4];
  my $Z2=$_[5];
  my $rXY=sqrt(($X1-$X2)**2+($Y1-$Y2)**2);
  if (abs($Z1-$Z2) < $rXY) {
    my $Z_branch=($Z1+$Z2-$rXY)/2;
    my $a=($Z1-$Z_branch)/$rXY;
    my $X_branch=(1-$a)*$X1+$a*$X2;
    my $Y_branch=(1-$a)*$Y1+$a*$Y2;
  }
  elsif ($Z1 < $Z2) {
    my $X_branch=$X1;
    my $Y_branch=$Y1;
    my $Z_branch=$Z1;
  }
  else {
    my $X_branch=$X2;
    my $Y_branch=$Y2;
    my $Z_branch=$Z2;
  }
  return my($X_branch,$Y_branch,$Z_branch);
}

Я надеюсь, что это объясняет общую ситуацию, любая помощь будет оценена. Спасибо.

1 Ответ

5 голосов
/ 19 марта 2019

Я не могу воспроизвести вашу ошибку.Однако в вашем коде много ошибок, поэтому позвольте мне их просмотреть, и, надеюсь, это поможет вам найти вашу реальную ошибку.

Во-первых, переменные должны быть определены в наименьшей возможной области видимости: еслипеременная используется только внутри функции, она должна быть определена внутри этой функции.Если переменная используется только в цикле for, она должна быть определена в этом цикле.В этом духе вы должны удалить

my $i;
my $j;

в начале вашего кода.Также имейте в виду, что my объявляет лексическую переменную, видимую только в текущей области ( т.е. вы можете использовать ее только в текущем блоке).Например,

else {
    my $X_branch=$X2;
    my $Y_branch=$Y2;
    my $Z_branch=$Z2;
}

объявляет 3 переменные, которые не существуют после блока else.

Second, my объявляет new переменную, ипоэтому следует использовать только один раз для каждой переменной.Если вы пишете

my $x = 5;
return my $x;

В первой строке объявляется переменная $x и устанавливается значение 5.Вторая строка объявляет новую переменную $x (таким образом, затеняя старую) со значением undef и возвращает ее.Вместо этого вы хотите написать:

my $x = 5;
return $x;

Теперь позвольте мне пройтись по вашему коду, чтобы указать на несколько ошибок / улучшений:

  • $X_list[my $j] должно быть $X_list[$j] (согласно началу этого ответа).

  • Все еще в find_branch, у вас есть проблема с областью действия определенных вами переменных (см. началомоего ответа).У вас должно быть что-то вроде:

    my ($X_branch, $Y_branch, $Z_branch);
    if (abs($Z1-$Z2) < $rXY) {
        $Z_branch=($Z1+$Z2-$rXY)/2;
        my $a=($Z1-$Z_branch)/$rXY;
        $X_branch=(1-$a)*$X1+$a*$X2;
        $Y_branch=(1-$a)*$Y1+$a*$Y2;
    }
    elsif ($Z1 < $Z2) {
        $X_branch=$X1;
        $Y_branch=$Y1;
        $Z_branch=$Z1;
    }
    else {
        $X_branch=$X2;
        $Y_branch=$Y2;
        $Z_branch=$Z2;
    }
    return ($X_branch,$Y_branch,$Z_branch);
    

    Эти два исправления должны заглушать все предупреждения.Тем не менее, я подозреваю, что в вашем коде есть и другие проблемы.

  • В find_min_dist вы не должны писать my $I = $i и my $J = $j, а скорее $I = $i и $J = $j (все та же проблема с областями видимости).

  • Ваш подчиненный branch ничего не делает: вы вычисляете некоторые $rho, $theta и $phi, но вы нене возвращайте их (и вы не изменяете аргументы).

  • In generate_pillars_shape, @X_values, @Y_values, @X, @Y должны всебыть локально объявленным с my.Кроме того, вы можете инициализировать @X_values с помощью @X_values = grep { $_ % $d == 0 } $_[0] .. $_[1] (то же самое для @Y_values), что, на мой взгляд, более читабельно, чем то, что вы написали.

  • Вы должны поместить свой код в функции иликодовые блоки ({ ... }), чтобы использовать правильную область видимости: хотя может иметь смысл иметь $min_X, $max_X, $min_Y, $max_Y и $distance в качестве глобальных переменных, вы определенно не хотите$min_radian или $b определены везде в вашем файле.

  • Не используйте $a или $b (это специальные переменные, используемые sort; выне хочу связываться с ними (см., например, этот вопрос ).

  • Кроме того, просто для ясности, в вашей подгруппе find_branch вы можетебыть немного более компактным для получения аргументов:

      my ($X1, $Y1, $Z1, $X2, $Y2, $Z2) = @_;
    

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...