Perl - Реализация скрипта Perl с модулем Perl - PullRequest
0 голосов
/ 21 марта 2019

Я бы подумал, что это слишком большой и слишком конкретный вопрос для обычного вопроса 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 и добавил подпрограмму grid. Я предположил, что мне просто нужно вызвать его, так как этот скрипт отличается от того, как он генерируется, по сравнению с другими структурами поддержки:

Так заменили это:

 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 Ответ

4 голосов
/ 21 марта 2019

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;

вверху каждого скрипта)

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