Skip to content

Commit

Permalink
backend suggestions: handle holes in GeoJSON polygons
Browse files Browse the repository at this point in the history
  • Loading branch information
derf committed Aug 24, 2024
1 parent 0875368 commit c142d4f
Showing 1 changed file with 34 additions and 14 deletions.
48 changes: 34 additions & 14 deletions lib/Travelynx/Controller/Account.pm
Original file line number Diff line number Diff line change
Expand Up @@ -1000,6 +1000,25 @@ sub password_form {
$self->render('change_password');
}

sub lonlat_in_polygon {
my ( $self, $polygon, $lonlat ) = @_;

my $circle = shift( @{$polygon} );
my @holes = @{$polygon};

my $circle_poly = Math::Polygon->new( @{$circle} );
if ( $circle_poly->contains($lonlat) ) {
for my $hole (@holes) {
my $hole_poly = Math::Polygon->new( @{$hole} );
if ( $hole_poly->contains($lonlat) ) {
return;
}
}
return 1;
}
return;
}

sub backend_form {
my ($self) = @_;
my $user = $self->current_user;
Expand Down Expand Up @@ -1039,7 +1058,6 @@ sub backend_form {

my ( $user_lat, $user_lon )
= $self->journeys->get_latest_checkout_latlon( uid => $user->{id} );
say $user_lat . ' ' . $user_lon;

for my $backend (@backends) {
my $type = 'UNKNOWN';
Expand All @@ -1058,27 +1076,29 @@ sub backend_form {
@{ $s->{coverage}{regions} // [] } ];
$backend->{has_area} = $s->{coverage}{area} ? 1 : 0;

if ( $s->{coverage}{area}
and $s->{coverage}{area}{type} eq 'Polygon' )
if (
$s->{coverage}{area}
and $s->{coverage}{area}{type} eq 'Polygon'
and $self->lonlat_in_polygon(
$s->{coverage}{area}{coordinates},
[ $user_lon, $user_lat ]
)
)
{
# [0] == outer polygon, [1:] == holes within polygon
my $poly = Math::Polygon->new(
@{ $s->{coverage}{area}{coordinates}[0] } );
say $backend->{name} . ' ' . $poly->area;
if ( $poly->contains( [ $user_lon, $user_lat ] ) ) {
push( @suggested_backends, $backend );
}
push( @suggested_backends, $backend );
}
elsif ( $s->{coverage}{area}
and $s->{coverage}{area}{type} eq 'MultiPolygon' )
{
for my $s_poly (
@{ $s->{coverage}{area}{coordinates} // [] } )
{
my $poly
= Math::Polygon->new( @{ $s_poly->[0] // [] } );
say $backend->{name} . ' ' . $poly->area;
if ( $poly->contains( [ $user_lon, $user_lat ] ) ) {
if (
$self->lonlat_in_polygon(
$s_poly, [ $user_lon, $user_lat ]
)
)
{
push( @suggested_backends, $backend );
last;
}
Expand Down

0 comments on commit c142d4f

Please sign in to comment.