我正在与perl合作制作一个可与Dot产品/各种矢量数学配合使用的脚本。我有一个工作脚本(仍在进行中/需要改进),这将完成我的要求。
#!/usr/bin/perl
use strict;
use warnings;
use diagnostics;
use Math::Vector::Real;
use 5.010;
use Math::Trig;
my $source = "./IN";
my $out = "./OUT";
open(IN, '<', $source) or die "Couldn't open $source: $!\n";
open(OUT, '>', $out) or die "Couldn't open $out: $!\n";
my(@data);
while (<IN>) {
push @data, [ split ];
}
my $v;
my $u;
$v = V(0, 0, 0);
$u = V(0, 0, 0);
my $i = 0;
sub maths {
my $dot = $v * $u;
my $mag1 = (sqrt ((@$v[0])**2 + (@$v[1])**2 + (@$v[2])**2 ));
my $mag2 = (sqrt ((@$u[0])**2 + (@$u[1])**2 + (@$u[2])**2 ));
my $prefinal = acos( ( $dot ) / ( $mag1 * $mag2 ) );
my $degrees = ( ( 180 / 3.14159 ) * ( $prefinal ) );
return ($degrees);
}
my $ref1 = $data[$i][0];
my $ref2 = $data[$i][1];
my $ref3 = $data[$i][2];
my $ref4 = $data[$i+1][0];
my $ref5 = $data[$i+1][1];
my $ref6 = $data[$i+1][2];
$v->[0] = $ref1;
$v->[1] = $ref2;
$v->[2] = $ref3;
$u->[0] = $ref4;
$u->[1] = $ref5;
$u->[2] = $ref6;
my $result = maths;
print "$result\n";
脚本中的很多内容都是残留的,并且易于遵循(对我而言)。 我希望它做的是让脚本旋转输入文件的每一行并对其执行计算。 类似于拥有的东西:
foreach $i (@data) {
my $ref1 = $data[$i][0];
my $ref2 = $data[$i][1];
my $ref3 = $data[$i][2];
my $ref4 = $data[$i+1][0];
my $ref5 = $data[$i+1][1];
my $ref6 = $data[$i+1][2];
$v->[0] = $ref1;
$v->[1] = $ref2;
$v->[2] = $ref3;
$u->[0] = $ref4;
$u->[1] = $ref5;
$u->[2] = $ref6;
my $result = maths;
print "$result\n";
}
感激不尽。
答案 0 :(得分:0)
您可以使用以下内容:
my $v = V( @{ $data[$i+0] } );
my $u = V( @{ $data[$i+1] } );
清理:
#!/usr/bin/perl
use strict;
use warnings;
use Math::Trig qw( acos );
use Math::Vector::Real qw( V );
sub maths {
my ($v, $u) = @_;
my $dot = $v * $u;
my $mag1 = sqrt( $v->[0]**2 + $v->[1]**2 + $v->[2]**2 );
my $mag2 = sqrt( $u->[0]**2 + $u->[1]**2 + $u->[2]**2 );
my $prefinal = acos( $dot / ( $mag1 * $mag2 ) );
my $degrees = ( 180 / 3.14159 ) * $prefinal;
return $degrees;
}
{
my @data = map { V( split ) } <>;
for my $i (0..$#data-1) {
for my $j ($i+1..$#data) {
my $maths = maths(@data[$i, $j]);
print("$i,$j: $maths\n");
}
}
}
或者使用鲍罗丁的替代方法:
#!/usr/bin/perl
use strict;
use warnings;
use Math::Trig qw( acos atan2 );
use Math::Vector::Real qw( V );
use constant DEG_PER_RAD => 45 / atan2(1, 1);
{
my @data = map { V( split ) } <>;
for my $i (0..$#data-1) {
for my $j ($i+1..$#data) {
my $maths = atan2(@data[$i, $j]) * DEG_PER_RAD;
print("$i,$j: $maths\n");
}
}
}
用法:
perl script.pl ./IN >./OUT
答案 1 :(得分:0)
根据我的评论,您的程序的大多数功能都是由您已经使用的Math::Vector::Real
模块提供的
看起来你想要文件中连续的3D矢量对之间的角度。此代码从文件中的每一行创建向量,直到@pair
中有两个向量,然后使用atan2
计算它们之间的角度。根据定义,DEG_PER_RAD
根据atan2(1,1)
的值π÷4 预先计算为
#!/usr/bin/perl
use strict;
use warnings;
use Math::Vector::Real;
use constant DEG_PER_RAD => 45 / atan2(1, 1);
my ( $source, $out ) = qw/ IN OUT /;
open my $in_fh, '<', $source or die qq{Unable to open "$source" for input: $!\n};
open my $out_fh, '<', $out or die qq{Unable to open "$out" for output: $!\n};
select $out_fh;
my @pair;
while ( <$in_fh> ) {
push @pair, V(split);
if ( @pair == 2 ) {
my $degrees = atan2(@pair) * DEG_PER_RAD;
print "$degrees\n";
shift @pair;
}
}
要对每对可能的向量进行计算,最简单的方法是将整个文件读入一个向量数组,并使用两个嵌套循环从那里处理它们
此代码演示。在原始程序中select
调用后插入它。它使用两个引起角度
my @data;
push @data, V(split) while <$in_fh>;
for my $i ( 0 .. $#data-1 ) {
for my $j ( $i+1 .. $#data ) {
my $degrees = atan2(@data[$i,$j]) * DEG_PER_RAD;
print "[$i,$j] $degrees\n";
}
}