backend suggestions: handle holes in GeoJSON polygons

This commit is contained in:
Birte Kristina Friesel 2024-08-24 07:59:19 +02:00
parent 087536862b
commit c142d4fae4
No known key found for this signature in database
GPG key ID: B63118F7196EA660

View file

@ -1000,6 +1000,25 @@ sub password_form {
$self->render('change_password'); $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 { sub backend_form {
my ($self) = @_; my ($self) = @_;
my $user = $self->current_user; my $user = $self->current_user;
@ -1039,7 +1058,6 @@ sub backend_form {
my ( $user_lat, $user_lon ) my ( $user_lat, $user_lon )
= $self->journeys->get_latest_checkout_latlon( uid => $user->{id} ); = $self->journeys->get_latest_checkout_latlon( uid => $user->{id} );
say $user_lat . ' ' . $user_lon;
for my $backend (@backends) { for my $backend (@backends) {
my $type = 'UNKNOWN'; my $type = 'UNKNOWN';
@ -1058,27 +1076,29 @@ sub backend_form {
@{ $s->{coverage}{regions} // [] } ]; @{ $s->{coverage}{regions} // [] } ];
$backend->{has_area} = $s->{coverage}{area} ? 1 : 0; $backend->{has_area} = $s->{coverage}{area} ? 1 : 0;
if ( $s->{coverage}{area} if (
and $s->{coverage}{area}{type} eq 'Polygon' ) $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} elsif ( $s->{coverage}{area}
and $s->{coverage}{area}{type} eq 'MultiPolygon' ) and $s->{coverage}{area}{type} eq 'MultiPolygon' )
{ {
for my $s_poly ( for my $s_poly (
@{ $s->{coverage}{area}{coordinates} // [] } ) @{ $s->{coverage}{area}{coordinates} // [] } )
{ {
my $poly if (
= Math::Polygon->new( @{ $s_poly->[0] // [] } ); $self->lonlat_in_polygon(
say $backend->{name} . ' ' . $poly->area; $s_poly, [ $user_lon, $user_lat ]
if ( $poly->contains( [ $user_lon, $user_lat ] ) ) { )
)
{
push( @suggested_backends, $backend ); push( @suggested_backends, $backend );
last; last;
} }