Skip Menu |

This queue is for tickets about the Math-Polygon CPAN distribution.

Report information
The Basics
Id: 119530
Status: resolved
Priority: 0/
Queue: Math-Polygon

People
Owner: Nobody in particular
Requestors: ANDK [...] cpan.org
Cc:
AdminCc:

Bug Information
Severity: Wishlist
Broken in: 1.04
Fixed in: 1.05



Subject: [PATCH] Add distance method
Hi Mark, would you mind taking this patch to add a distance method? I hope you like it. Let me know if I can improve on it. Thanks && Kind Regards,
Subject: 0001-Add-distance-method.patch
From 7b7dd285e7aed74848c9fae1d1e82ef3daf71a53 Mon Sep 17 00:00:00 2001 From: Andreas Koenig <andk@cpan.org> Date: Wed, 28 Dec 2016 06:12:51 +0100 Subject: [PATCH] Add distance method --- MANIFEST | 1 + lib/Math/Polygon.pm | 5 +++++ lib/Math/Polygon.pod | 6 ++++++ lib/Math/Polygon/Calc.pm | 45 +++++++++++++++++++++++++++++++++++++++++++++ t/15distance.t | 29 +++++++++++++++++++++++++++++ 5 files changed, 86 insertions(+) create mode 100644 t/15distance.t diff --git a/MANIFEST b/MANIFEST index 26b8f88..8e92ced 100644 --- a/MANIFEST +++ b/MANIFEST @@ -20,6 +20,7 @@ t/11size.t t/12beauty.t t/13rot.t t/14inside.t +t/15distance.t t/30cross.t t/31clipl.t t/32clipf1.t diff --git a/lib/Math/Polygon.pm b/lib/Math/Polygon.pm index 5ed9152..230a984 100644 --- a/lib/Math/Polygon.pm +++ b/lib/Math/Polygon.pm @@ -153,6 +153,11 @@ sub contains($) polygon_contains_point($point, $self->points); } +sub distance($) +{ my ($self, $point) = @_; + polygon_distance($point, $self->points); +} + sub isClosed() { polygon_is_closed(shift->points) } diff --git a/lib/Math/Polygon.pod b/lib/Math/Polygon.pod index 235a1be..1c05134 100644 --- a/lib/Math/Polygon.pod +++ b/lib/Math/Polygon.pod @@ -192,6 +192,12 @@ example: $poly->counterClockwise +=item $obj-E<gt>B<distance>($point) + +Returns a numeric value indicating the distance of the point to the +closest point on the border of the polygon, zero if the point is on an +edge. + =item $obj-E<gt>B<equal>( <$other | ARRAY,[$tolerance]> | $points ) Compare two polygons, on the level of points. When the polygons are diff --git a/lib/Math/Polygon/Calc.pm b/lib/Math/Polygon/Calc.pm index 2e62d4c..a05d8e1 100644 --- a/lib/Math/Polygon/Calc.pm +++ b/lib/Math/Polygon/Calc.pm @@ -20,6 +20,7 @@ our @EXPORT = qw/ polygon_is_closed polygon_clockwise polygon_counter_clockwise + polygon_distance polygon_perimeter polygon_same polygon_start_minxy @@ -332,4 +333,48 @@ sub polygon_is_closed(@) $first->[0]==$last->[0] && $first->[1]==$last->[1]; } +sub polygon_distance($@) +{ my $p = shift; + + my ($x, $y) = @$p; + # http://stackoverflow.com/questions/10983872/distance-from-a-point-to-a-polygon#10984080 with correction from + # http://stackoverflow.com/questions/849211/shortest-distance-between-a-point-and-a-line-segment + my $minDist; + for my $i (0..$#_-1) { # closed! + my $j = $i+1; + my($x1,$y1,$x2,$y2) = map { $_->[0], $_->[1] } @_[$i,$j]; + my $A = $x - $x1; + my $B = $y - $y1; + my $C = $x2 - $x1; + my $D = $y2 - $y1; + my $dot = $A * $C + $B * $D; + my $len_sq = $C * $C + $D * $D; + my $param = -1; + if ($len_sq != 0) { #in case of 0 length line + $param = $dot / $len_sq; + } + my($xx, $yy); + + if ($param < 0) { + $xx = $x1; + $yy = $y1; + } + elsif ($param > 1) { + $xx = $x2; + $yy = $y2; + } + else { + $xx = $x1 + $param * $C; + $yy = $y1 + $param * $D; + } + + my $dx = $x - $xx; + my $dy = $y - $yy; + my $dist = sqrt($dx * $dx + $dy * $dy); + $minDist = $dist unless defined $minDist; + $minDist = $dist if $dist < $minDist; + } + return $minDist; +} + 1; diff --git a/t/15distance.t b/t/15distance.t new file mode 100644 index 0000000..50b16e0 --- /dev/null +++ b/t/15distance.t @@ -0,0 +1,29 @@ +#!/usr/bin/perl + +use strict; +use warnings; + +use Test::More tests => 13; + +use lib '../lib'; +use Math::Polygon::Calc; + +my @p = ([1,1], [3,1], [3,3], [1,3], [1,1]); + +is( polygon_distance([1,1], @p), 0); +is( polygon_distance([1,0], @p), 1); +is( polygon_distance([0,1], @p), 1); +is( polygon_distance([2,0], @p), 1); +is( polygon_distance([2,2], @p), 1); +is( polygon_distance([0,2], @p), 1); +is( polygon_distance([3,0], @p), 1); +is( polygon_distance([0,3], @p), 1); +is( polygon_distance([0,0], @p), polygon_distance([4,4], @p)); +is( polygon_distance([4,0], @p), polygon_distance([0,4], @p)); + +@p = ([6,2],[7,1],[8,2],[7,3],[6,2]); + +is( polygon_distance([5,1], @p), polygon_distance([5,3], @p)); +is( polygon_distance([6,0], @p), polygon_distance([6,4], @p)); +is( polygon_distance([7,2], @p), polygon_distance([8,3], @p)); + -- 2.9.3
Subject: Re: [rt.cpan.org #119530] [PATCH] Add distance method
Date: Wed, 28 Dec 2016 13:03:25 +0100
To: Andreas Koenig via RT <bug-Math-Polygon [...] rt.cpan.org>
From: Mark Overmeer <mark [...] overmeer.net>
* Andreas Koenig via RT (bug-Math-Polygon@rt.cpan.org) [161228 05:26]: Show quoted text
> Wed Dec 28 00:25:49 2016: Request 119530 was acted upon. > Queue: Math-Polygon > Subject: [PATCH] Add distance method > Ticket <URL: https://rt.cpan.org/Ticket/Display.html?id=119530 > > > Hi Mark, > would you mind taking this patch to add a distance method? > I hope you like it. Let me know if I can improve on it.
Hi Andreas, Thanks for your contribution. I added handling of the special cases with zero and one point, and slightly adapted it to my coding style. I released it as v1.05 to CPAN a few minutes ago. -- See you in 2017! MarkOv ------------------------------------------------------------------------ Mark Overmeer MSc MARKOV Solutions Mark@Overmeer.net solutions@overmeer.net http://Mark.Overmeer.net http://solutions.overmeer.net
CC: ANDK [...] cpan.org
Subject: Re: [rt.cpan.org #119530] [PATCH] Add distance method
Date: Wed, 28 Dec 2016 14:40:21 +0100
To: "Mark Overmeer via RT" <bug-Math-Polygon [...] rt.cpan.org>
From: Andreas Koenig <andreas.koenig.7os6VVqR [...] franz.ak.mind.de>
Show quoted text
>>>>> On Wed, 28 Dec 2016 07:03:44 -0500, "Mark Overmeer via RT" <bug-Math-Polygon@rt.cpan.org> said:
Show quoted text
> I released it as v1.05 to CPAN a few minutes ago.
Wow, that was quick. Amazing, thank you! Show quoted text
> See you in 2017!
Yupp, See you! -- andreas
Thanks again!