提取轴上交叉线的交点的功能 [英] Function to extract intersections of crossing lines on axes

查看:112
本文介绍了提取轴上交叉线的交点的功能的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

Perl中的代码为5.18.2.

Code in Perl is 5.18.2.

sub extract_crossing {
    my @x = @{ $_[0] }; my @y = @{ $_[1] };
    my @xcross =(); my @ycross =();
    for (my $i=0; $i<$#x; $i++) {
        my $k = ($y[$i] - $y[$i+1]) / ($x[$i] - $x[$i+1]);
        if($y[$i+1] * $y[$i] < 0) {
            my $xc = $x[$i+1] - $y[$i+1] / $k;
            push(@xcross, $xc);
        }
        if($x[$i+1] * $x[$i] < 0) {
            my $yc = $y[$i+1] - $x[$i+1] * $k;
            push(@ycross, $yc);
        }
    }
    return (\@xcross, \@ycross);
}

可以成功提取x轴和y轴的交叉点. 它看起来是第一个点,其中两个后续点的乘积为负. 如果是这样,请与相应的轴相交.

which extracts successfully crossing points with x- and y-axes. It looks first point where the product of two subsequent points is negative. If so, intersection point with corresponding axis.

但是,我觉得这个功能很多余,因为它是如此基本的操作.

However, I feel this function extraneous, since it is so basic operation.

如何使用Perl中的默认工具更好地进行提取?

推荐答案

如果List::MoreUtils符合您在评论中所说的Perl的默认工具"之一,则

If List::MoreUtils qualifies as one of Perl's "default tools" as you say in a comment, Math::Geometry::Planar should qualify as well. Math::Geometry::Planar provides a number of handy functions for calculating the intersection of segments, rays, and lines, as well as functions for manipulating polygons, calculating distances, and other goodies.

评估任何解决方案时,应确保它为许多输入(包括边缘情况)生成正确的结果.您的原始代码至少有一个错误(垂直线段被零除错误)...请确保

When evaluating any solution, you should make sure it generates correct results for a number of inputs, including edge cases. Your original code has at least one bug (a divide-by-zero error for vertical line segments)...let's make sure SegmentLineIntersection from Math::Geometry::Planar works as expected:

use strict;
use warnings;

use Math::Geometry::Planar qw(SegmentLineIntersection);
use Test::More tests => 8;

my @x_axis = ( [0, 0], [1, 0] );
my @y_axis = ( [0, 0], [0, 1] );

is_deeply(
    SegmentLineIntersection([ [-1, 2], [2, -1], @x_axis ]),
    [1, 0],
    'Segment (-1, 2), (2, -1) intersects x-axis once at (1, 0)'
);

is_deeply(
    SegmentLineIntersection([ [-1, 2], [2, -1], @y_axis ]),
    [0, 1],
    'Segment (-1, 2), (2, -1) intersects y-axis once at (0, 1)'
);

is(
    SegmentLineIntersection([ [0, 1], [1, 1], @x_axis ]),
    0,
    'Horizontal segment above x-axis never intersects x-axis'
);

is(
    SegmentLineIntersection([ [1, 0], [1, 1], @y_axis ]),
    0,
    'Vertical segment to the right of y-axis never intersects y-axis'
);

is(
    SegmentLineIntersection([ [0, 0], [1, 0], @x_axis ]),
    0,
    'Horizontal segment on x-axis returns false (intersects infinite times)'
);

is(
    SegmentLineIntersection([ [0, 0], [0, 1], @y_axis ]),
    0,
    'Vertical segment on y-axis returns false (intersects infinite times)'
);

is_deeply(
    SegmentLineIntersection([ [0, 0], [1, 1], @x_axis ]),
    [0, 0],
    'Segment beginning at origin intersects x-axis at (0, 0)'
);

is_deeply(
    SegmentLineIntersection([ [0, 0], [1, 1], @y_axis ]),
    [0, 0],
    'Segment beginning at origin intersects y-axis at (0, 0)'
);

输出:

1..8
ok 1 - Segment (-1, 2), (2, -1) intersects x-axis once at (1, 0)
ok 2 - Segment (-1, 2), (2, -1) intersects y-axis once at (0, 1)
ok 3 - Horizontal segment above x-axis never intersects x-axis
ok 4 - Vertical segment to the right of y-axis never intersects y-axis
ok 5 - Horizontal segment on x-axis returns false (intersects infinite times)
ok 6 - Vertical segment on y-axis returns false (intersects infinite times)
not ok 7 - Segment beginning at origin intersects x-axis at (0, 0)
#   Failed test 'Segment beginning at origin intersects x-axis at (0, 0)'
#   at geometry line 49.
#     Structures begin differing at:
#          $got = '0'
#     $expected = ARRAY(0x1b1f088)
not ok 8 - Segment beginning at origin intersects y-axis at (0, 0)
#   Failed test 'Segment beginning at origin intersects y-axis at (0, 0)'
#   at geometry line 55.
#     Structures begin differing at:
#          $got = '0'
#     $expected = ARRAY(0x1b1f010)
# Looks like you failed 2 tests of 8.

看起来我们的最后两个测试失败了:显然一条线上的一端的段不算作相交(在原始算法中也是如此).我不是几何专家,所以我无法评估这是错误还是数学上正确的.

Looks like our last two tests failed: apparently segments with one end on a line don't count as intersecting (this is the case in your original algorithm as well). I'm not a geometry expert, so I can't evaluate whether this is a bug or mathematically correct.

以下函数返回多个连接的线段的x截距.计算y截距的实现几乎相同.请注意,如果一对线段恰好在轴上相交,则不会像原始函数中那样将其视为截距.这可能是合乎要求的,也可能是不合要求的.

The following function returns the x-intercepts for multiple connected line segments. The implementation for calculating y-intercepts would be nearly identical. Note that if a pair of segments meet exactly on the axis, it doesn't count as an intercept, as in your original function. That may or may not be desirable.

use strict;
use warnings;

use Math::Geometry::Planar qw(SegmentLineIntersection);
use Test::Exception;
use Test::More tests => 3;

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

dies_ok { x_intercepts([ [0, 0] ]) } 'Dies with < 2 points';

is_deeply(
    x_intercepts([ [-1, -1], [1, 1], [1, -1] ]),
    [ [0, 0], [1, 0] ],
    'Intersects x-axis at (0, 0) and (1, 0)'
);

is_deeply(
    x_intercepts([ [-1, -1], [0, 0], [1, 1] ]),
    [],
    "No intercept when segments start or end on x-axis but don't cross it"
);

输出:

1..3
ok 1 - Dies with < 2 points
ok 2 - Intersects x-axis at (0, 0) and (1, 0)
ok 3 - No intercept when segments start or end on x-axis but don't cross it

请注意,此实现接受点的单个数组引用,其中点是对两个元素的数组的引用,而不是x和y坐标的单独数组引用.我认为这更加直观.

Note that this implementation accepts a single array reference of points, where a point is a reference to a two-element array, instead of separate array references of x- and y-coordinates. I think this is a little bit more intuitive.

这篇关于提取轴上交叉线的交点的功能的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆