Perl-使用Perl模块实现Perl脚本

时间:2019-03-21 10:20:38

标签: perl

我想这对于一个正常的StackOverflow问题来说太大了,太具体了,所以我可以理解是否没有任何帮助。但是,我将尝试说明我面临的问题。另外,我是Perl的新手,我知道您不应该在一开始就声明所有变量,我只是想看看是否可以先实现此变量。

我有一个Perl脚本:

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

#Input parameters:

#The ouput filename:
$outfile = 'Tree.scad';

#The coordinates of the points that is to be supported.
$min_X=0;
$max_X=60;
$min_Y=0;
$max_Y=60;
$distance=10;

#The minimum angle from horizontal your printer can make, in degrees
$min_angle= 40;

#Ignore the next line, it is not an input parameter.
($X_ref,$Y_ref)=grid($min_X,$max_X,$min_Y,$max_Y,$distance);@X=@$X_ref;@Y=@{$Y_ref};
for $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.

$min_radian = deg2rad($min_angle);
$b = tan($min_radian);
@Z=map{$_/$b}@Z;
open $output, '>', $outfile or die "error writing to '$outfile'"; 

print $output "width=2;\n";
print $output "sphere_radius=0;\n";
print $output "base_plate_size=10;\n\n";

while ($#X>0){
  ($I,$J)=find_min_dist(\@X,\@Y,\@Z);
  ($X_branch,$Y_branch,$Z_branch)=find_branch($X[$I],$Y[$I],$Z[$I],$X[$J],$Y[$J],$Z[$J]);
  @X_list=($X_branch,$X[$I],$X[$J]);
  @Y_list=($Y_branch,$Y[$I],$Y[$J]);
  @Z_list=($Z_branch,$Z[$I],$Z[$J]);
  for $j (0..$#Y_list){
      if (abs($X_list[$j]) < 0.001){
      $X_list[$j]=0;
      }
      if (abs($Y_list[$j]) < 0.001){
      $Y_list[$j]=0;
      }
      if (abs($Z_list[$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);
}

print $output 'if(base_plate_size>0){';
print $output "\n translate([$X[0],$Y[0],$Z[0]*$b])\n";
print $output "cube([base_plate_size,base_plate_size,1],center=true);}";

sub grid{
    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 $i (1..$#X){
    ($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){
    print $output "translate([$X[0],$Y[0],$Z[0]])\n";
    print $output "rotate([0,0,$theta])\n";
    print $output "rotate([$phi,0,0])\n";
    print $output "translate([-width/2,-width/2,0])";
    print $output "cube([width,width,$rho]);\n";
    print $output 'if (sphere_radius>0){';
    print $output "\n translate([$X[$i],$Y[$i],$Z[$i]])\n";
    print $output "sphere(sphere_radius,center=1);}\n";}
  }
}

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 $i (1..$#Z){
      if ($Z[$i]>=$max_Z){
      $max_Z=$Z[$i];
      $I=$i;}
  }
  for $j (0..$#X){
    if ($j!=$I){
      $dist=(($X[$I]-$X[$j])**2+($Y[$I]-$Y[$j])**2+($Z[$I]-$Z[$j])**2);
      if ($min_dist>$dist){
    $min_dist=$dist;
    $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];
  $rXY=sqrt(($X1-$X2)**2+($Y1-$Y2)**2);
  if (abs($Z1-$Z2) < $rXY) {
    $Z_branch=($Z1+$Z2-$rXY)/2;
    $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);
}

哪个生成一个scad文件并按以下方式输出: enter image description here

我认为最好在切片程序Slic3r中实现此方法。现在,由于我想至少在程序中显示此结构并决定是否可以执行此操作,因此尝试将其分开。

Slic3r原​​始代码:https://github.com/slic3r/Slic3r/blob/21eb603cc16946b14e77d3c10cbee2f1163503c6/lib/Slic3r/Print/SupportMaterial.pm

修改后的Slic3r代码:https://pastebin.com/aHzXT4RW

所以比较是,我删除了generate_pillar_supports并添加了我的网格子程序。我认为我只需要调用它,因为与以下其他支持结构相比,该脚本与其生成方式是分开的:

因此替换为:

 my $shape = [];
    if ($self->object_config->support_material_pattern eq 'pillars') {
        $self->generate_pillars_shape($contact, $support_z, $shape);
    }

与此:

my $shape = [];
    if ($self->object_config->support_material_pattern eq 'pillars') {
        $self->grid($min_X,$max_X,$min_Y,$max_Y,$distance);
    }

但是,不幸的是,我无法形成一个很好的结构,而是这样的: enter image description here

正如我所说,我知道这是一个很大的问题,我不会深入研究整个Slic3ing程序,因此可能更难理解。但是,从简短的角度看,有谁知道这个问题是什么?我是否将子例程称为错误,脚本是否仅可用于生成scad文件,等等。我所需要的只是查看它是否能够显示。谢谢。

1 个答案:

答案 0 :(得分:4)

sub grid似乎不是一种方法,但您将其称为一个方法

$self->grid($min_X,$max_X,$min_Y,$max_Y,$distance);

此语法实际上发送$self作为第一个参数,因此该调用等同于函数调用

grid($self,$min_X,$max_X,$min_Y,$max_Y,$distance);

您可能只想说

grid($min_X,$max_X,$min_Y,$max_Y,$distance);

(您也很想说

use strict;
use warnings;

在每个脚本的顶部)