因此,我已经完成了一些谷歌搜索和其他工作,我的控制台充满了所有这些警告。只是有点不确定如何整体解决此方法。同样,我希望我的代码不会模糊,因为我不太确定这里的代码是否足够。不管这里是问题。一段时间以来,我一直在尝试将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);
}
我希望能解释大致情况,希望能对您有所帮助。谢谢。
答案 0 :(得分:5)
我无法重现您的错误。但是,您的代码中有很多错误,因此让我仔细研究一下,希望可以帮助您找到实际的错误。
首先,应在尽可能小的范围内定义变量:如果仅在函数内使用变量,则应在此函数内定义变量。如果变量仅在for
循环中使用,则应在此循环中定义它。本着这种精神,您应该删除
my $i;
my $j;
在代码开头的。另外,请记住,my
声明了仅在当前作用域中可见的词法变量(即,您只能在当前块中使用它)。例如,
else {
my $X_branch=$X2;
my $Y_branch=$Y2;
my $Z_branch=$Z2;
}
声明在else
块之后不存在的3个变量。
第二,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
(仍然是相同的范围界定问题)。 / p>
您的子branch
不会执行任何操作:您计算了$rho
,$theta
和$phi
,但是您没有返回它们(并且您也不要修改参数。)
在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
,{{1 }},$min_Y
和$max_Y
作为全局变量,您绝对不希望在文件的任何地方都定义$distance
或$min_radian
。
不要使用$b
或$a
(它们是$b
使用的特殊变量;您不想弄乱它们(请参阅{{3} }))。
另外,为了清楚起见,在子sort
中,您可以更紧凑地检索参数:
find_branch
我非常相信您的代码还有其他问题。如果需要更多帮助,请告诉我们您正在尝试做什么以及每个功能应该做什么。