Greetings, all.

I was playing around with Image2D::pnpoly and Image2D::polyfill (and
polyfillv), and I noticed that the latter two do not have the same behavior
as pnpoly. I have some tests below.

use strict;
use warnings;
use PDL;
use PDL::Image2D;

# A triangle
my $px = pdl(3,15,9);
my $py = pdl(3,3,9);
print "Testing the triangle\n";
&testPoly($px,$py);

# A square (be careful to draw it convexly!)
$px = pdl(4,4,8,8);
$py = pdl(4,8,8,4);
print "Testing the square\n";
&testPoly($px,$py);

sub testPoly
{
    my $px = shift;
    my $py = shift;
    my $points = $px->cat($py)->xchg(0,1);

    my $img1 = zeroes(20, 11);
    my $img2 = zeroes(20, 11);
    my $img3 = zeroes(20, 11);
    my $img4 = zeroes(20, 11);

    my $img5 = pnpoly($img1->xvals,$img1->yvals,$px,$py);
    print $img5, $img5->sumover, "\n";
    $img2->polyfillv($points) .= 1;
    print $img2, $img2->sumover, "\n";
    $img3->polyfill($points, 1);
    print $img3, $img3->sumover, "\n";
}


>From the output, I believe that pnpoly produces the correct answer insofar
as it produces the correct area for the square. Moreover, the documentation
for polyfill and polyfillv states that "fill the area *inside* the given
polygon with a given colour" and "return the (dataflown) area of an image *
within* a polygon," respectively. However, the area selected for color
filling in polyfill contains more than the points interior to the polygon,
and similarly for polyfillv.

After some investigation into PDL/Lib/Image2D, I found that polyfillv uses
polyfill, so their identical behavior is expected.

My proposed fix is to use pnpoly to determine the interior points. Then
polyfill becomes simply

sub PDL::polyfill
{
    my ($im, $ps, $col) = @_;
    barf("ps must contain pairwise points.\n") unless $ps->getdim(0) == 2;
    barf("color not specified.\n") unless $col;
    $im->where($im->pnpoly($im->xvals, $im->yvals, $ps->slice('0,:'),
$ps->slice('1,:'))) .= $col;
}

and polyfillv becomes

sub PDL::polyfillv
{
    my ($im, $ps) = @_;
    barf("ps must contain pairwise points.\n") unless $ps->getdim(0) == 2;
    return $im->where($im->pnpoly($im->xvals, $im->yvals,
$ps->slice('0,:'), $ps->slice('1,:')));
}

This will remove the need for the PP version of polyfill. Assuredly, these
fixes are not optimal. If $im is large, then two large intermediates
($im->xvals and $im->yvals) are created.

I did not file this as a bug report, I wanted to run it by everyone to see
if I was missing something. Additionally, I am not closely familiar with
the coding standards, so I would appreciate any tips on that, as well.

Many thanks.

- Tim
_______________________________________________
Perldl mailing list
[email protected]
http://mailman.jach.hawaii.edu/mailman/listinfo/perldl

Reply via email to