简体   繁体   中英

Perl - Implementing Perl Script with Perl Module

I would imagine this is too big and too specific for a normal StackOverflow question, so I can understand if there isn't any possible help. However I will try and show what is the issue I am facing. Also I am new to Perl and I know you shouldn't declare all variables at the start, I'm just trying to see if I can get this implemented first.

I have a Perl script:

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);
}

Which produces a scad file and outputs it as this: 在此处输入图片说明

I thought it would be good to implement this method in a slicing program, Slic3r. Now what I have done is attempted to still keep it separate since I would like to show at least this structure in the program and decide whether or not it is possible to do.

Slic3r Original Code: https://github.com/slic3r/Slic3r/blob/21eb603cc16946b14e77d3c10cbee2f1163503c6/lib/Slic3r/Print/SupportMaterial.pm

Modified Slic3r Code: https://pastebin.com/aHzXT4RW

So the comparison is, I removed the generate_pillar_supports and added my grid subroutine. I assumed I would just have to call it since this script is separate to how it's generated compared to the other support structures on:

So replaced this:

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

With this:

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

However unfortunately, I have not been able to get a nice structure to form but rather this: 在此处输入图片说明

As I said, I know this is a large question and I'm not diving into the entire Slic3ing program so it might be even harder to understand. However just from a brief look, would anyone know what the issue is? Am I calling the subroutine wrong, does the script only work to produce a scad file, etc. All I would need is just to see if this is able to show or not. Thanks.

sub grid does not appear to be a method, but you are calling it as one

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

This syntax actually sends $self as the first argument, so that call is equivalent to the function call

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

What you probably want is to just say

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

(You also really want to say

use strict;
use warnings;

at the top of every script)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM