I am considering this answer which uses a single array reference of points, where a point is a reference to a two-element array.
My original code of the question (function extract-crossing
) uses two separate arrays $x
and $y
here which I call like this:
my @x = @{ $_[0] }; my @y = @{ $_[1] };
...
return extract_crossing(\@x, \@y);
The new code below based on the answer takes (x, y)
and returns a single datatype, here x intercept points:
use strict; use warnings;
use Math::Geometry::Planar qw(SegmentLineIntersection);
use Test::Exception;
sub x_intercepts {
my ($points) = @_;
die 'Must pass at least 2 points' unless @$points >= 2;
my @intercepts;
my @x_axis = ( [0, 0], [1, 0] );
foreach my $i (0 .. $#$points - 1) {
my $intersect = SegmentLineIntersection([@$points[$i,$i+1],@x_axis]);
push @intercepts, $intersect if $intersect;
}
return \@intercepts;
}
which I try to call like this:
my @x = @{ $_[0] }; my @y = @{ $_[1] };
...
my $masi = x_intercepts(\@x);
return $masi;
However, the code does not make sense.
I am confused about passing the "double array" to the x_intercepts()
function.
How can you make the example code clearer to the original setting?
If I am understanding the problem here, @ThisSuitIsBlackNot++ has written a function (
x_intercepts
which is available in the thread: Function to extract intersections of crossing lines on axes) that expects its argument to be a reference to a list of array references. Thex_intercepts
subroutine in turn uses a function fromMath::Geometry::Planar
which expects the points of a line segment to be passed as series of array references/anonymous arrays that contain thex,y
values for each point.Again - it is not entirely clear - but it seems your data is in two different arrays: one containing all the x values and one with the corresponding y values. Is this the case? If this is not correct please leave a comment and I will remove this answer.
If that is the source of your problem then you can "munge" or transform your data before you pass it to
x_intercepts
or - as @ThisSuitIsBlackNot suggests - you can rewrite the function. Here is an example of munging your existing data into an "@input_list
" to pass tox_intercepts
.Adding the lines above to your script produces:
Output:
You have to be very careful doing this kind of thing and using tests to make sure you are passing the correctly transformed data in an expected way is a good idea.
I think a more general difficulty is that until you are familiar with perl it is sometimes tricky to easily see what sorts of values a subroutine is expecting, where they end up after they are passed in, and how to access them.
A solid grasp of perl data structures can help with that - for example I think what you are calling a "double array" or "double element" here is an "array of arrays". There are ways to make it easier to see where default arguments passed to a subroutine (in
@_
) are going (notice how @ThisSuitIsBlackNot has passed them to a nicely named array reference: "($points)
"). Copious re-reading ofperldoc
perbsub
can help things seem more obvious.References are key to understanding perl subroutines since to pass an array or hash to a subrouting you need to do so by references. If the argument passed
x_intercepts
is a list of two lists of anonymous arrays then when it is assigned to($points)
,@$points->[0]
@$points->[1]
will be the arrays contain those lists.I hope this helps and is not too basic (or incorrect). If @ThisSuitIsBlackNot finds the time to provide an answer you should accept it: some very useful examples have been provided.