#!/usr/bin/perl # Given pylons and target areas, make wedge polygons with the wide # part pointing to the target area. We are simulating cell tower # antenna maps. # # Author: Dan Jacobson https://www.jidanni.org/ # Copyright: https://www.gnu.org/licenses/gpl.htm # Created: 2024-03-17T21:43:36+0000 # Last-Updated: 2024-03-30T23:03:47+0000 # Update #: 111 # use strict; use warnings q(all); use Data::Dumper; my $G = "geod +ellps=WGS84 -f %.6f"; my @pole = reverse qw/24.181664 120.865677/; for ( 100, 700 ) { next; my @in = pylon_and_radius2cicle( \@pole, $_ ); my $csv; for (@in) { $csv .= qq{@$_} . $/; } my $com = "ogr2ogr -f LIBKML -nlt POLYGON $_.kml $_.csv -dialect SQLite -sql \"SELECT MakeLine(MakePoint(CAST(field_1 AS float), CAST(field_2 AS float))) FROM '$_'\""; $com =~ tr/\n/ /; $com =~ s/\s+/ /g; open( my $fh, ">", "$_.csv" ) or die; print $fh $csv; close $fh; for ("$_.kml") { unlink if -f } my $res = qx/$com/; } #exit; my %targets; # # centers of areas with poor reception. I.e., where # the people sitting around the pizza pie are # located. # ( N => [qw/120.870499 24.195144/], S => [qw/120.866551 24.182822/] ); # ( # N => [ reverse qw/24.182686 120.867726/ ], # S => [ reverse qw/24.180960 120.864931/ ] # ); my %azimuths; $azimuths{N} = 180 + ( $azimuths{S} = 240 ); %targets = %azimuths; #Hack supreme my %pylons; ## %pylons= ( 158 => [qw/120.8710656 24.1873743/], 159 => [qw/120.8724266 24.1822381/] ); for (qw/N S/) { # $pylons{$_} = [ reverse split / /, $ENV{$_} ]; $pylons{$_} = \@pole; } for my $p ( sort keys %pylons ) { for my $t ( sort keys %targets ) { next unless $p eq $t; # print "\n$p -> $t:\n"; my @in = pylon_and_azimuth2wedge( $pylons{$p}, $azimuths{$p} || pylon_and_target2azimuth( $pylons{$p}, $targets{$t} ) ) or die; my $csv; for (@in) { $csv .= qq{@$_} . $/; } my $com = "ogr2ogr -f LIBKML -nlt POLYGON $p$t.kml $p$t.csv -dialect SQLite -sql \"SELECT MakeLine(MakePoint(CAST(field_1 AS float), CAST(field_2 AS float))) FROM '$p$t'\""; $com =~ tr/\n/ /; $com =~ s/\s+/ /g; open( my $fh, ">", "$p$t.csv" ) or die; print $fh $csv; close $fh; for ("$p$t.kml") { unlink if -f } my $res = qx/$com/; } } sub pylon_and_target2azimuth { #given a pylon lonlat, and a target lonlat, get the azimuth my @pylon = @{ $_[0] }; my @target = @{ $_[1] }; my $args = join $", ( reverse @pylon ), ( reverse @target ); my $res = qx/echo $args|$G -I -p/ or die; my @rez = split /\s+/, $res; return $rez[0]; } sub pylon_and_azimuth2wedge { #given a pylon lonlat, and an azimuth, make a pizza #slice polygon representing an antenna my @pylon = @{ $_[0] }; my $azimuth = $_[1]; my $width = 120; #degrees my $radius = $ENV{radius} || die; #meters my $increment = 5; #degrees between points on the arc my @argl; for ( my $angle = $azimuth - $width / 2 ; $angle <= $azimuth + $width / 2 ; $angle += $increment ) { my $args = join $", ( reverse @pylon ), $angle, $radius; push @argl, $args; } { #close the polygon my $args = join $", ( reverse @pylon ), (0) x 2; push @argl, $args; unshift @argl, $args; } my $argz = join $/, @argl; my $res = qx/echo "$argz"|$G -p/ or die; my @nodes; for my $line ( split /\n/, $res ) { push @nodes, [ ( split /\s+/, $line )[ 1, 0 ] ]; } return @nodes; } sub pylon_and_radius2cicle { #given a pylon lonlat, and a radius in meters, make a ring. my @pylon = @{ $_[0] }; my $radius = $_[1] || die; my $increment = 5; #degrees between points on the arc my @argl; for ( my $angle = 0 ; $angle <= 360 ; $angle += $increment ) { my $args = join $", ( reverse @pylon ), $angle, $radius; push @argl, $args; } my $argz = join $/, @argl; my $res = qx/echo "$argz"|$G -p/ or die; my @nodes; for my $line ( split /\n/, $res ) { push @nodes, [ ( split /\s+/, $line )[ 1, 0 ] ]; } return @nodes; }