$NetBSD: patch-ac,v 1.1 2003/01/08 17:29:06 tsarna Exp $

Drew Einhorn's gpsfetchmap.pl enhancements from:

http://s2.selwerd.nl/~dirk-jan/gpsdrive/archive/msg01772.html

--- src/gpsfetchmap.pl.orig	Sun Nov 24 11:04:38 2002
+++ src/gpsfetchmap.pl	Wed Jan  8 12:13:17 2003
@@ -1,4 +1,4 @@
-#!/usr/bin/perl
+#!/usr/bin/env perl
 
 # gpsfetchmap
 #
@@ -9,38 +9,71 @@
 gpsfetchmap (c) 2002 Kevin Stephens <gps\@suburbialost.com>
 modified (Sept 06, 2002) by Sven Fichtner <sven.fichtner\@flugfunk.de>
 modified (Sept 18, 2002) by Sven Fichtner <sven.fichtner\@flugfunk.de>
-modified (Nov 21, 2002) by Magnus Mnsson <ganja\@0x63.nu>
-Version 1.04
+modified (Nov 21, 2002) by Magnus Månsson <ganja\@0x63.nu>
+modified (Dec 24, 2002) by Drew Einhorn <drew.einhorn\@starband.net>
+Version 1.05
 EOP
 
 use strict;
 use Getopt::Long;
 use Pod::Usage;
-
-# Setup possible scales
-my @SCALES = (1000,1500,2000,3000,5000,7500,10000,15000,20000,30000,50000,75000,
-              100000,150000,200000,300000,500000,750000,1000000,1500000,2000000,3000000,
-              5000000,7500000,10000000,15000000,20000000,30000000,50000000,75000000);
+use POSIX qw(floor ceil);
+use File::Temp qw/ tempfile tempdir /; 
 
 # Set defaults and get options from command line
 Getopt::Long::Configure('no_ignore_case');
-my ($lat,$lon,$slat,$endlat,$slon,$endlon,$waypoint,$area,$unit,$mapdir,$debug,$force,$version,$man,$help);
-my $failcount = 0;
+my (@SCALES,$lat,$lon,$slat,$endlat,$slon,$endlon,$waypoint,$area,$unit,$debug,$force,$version,$man,$help);
+
+my $failcount;
+my $writecount;
+my $cachecount;
 my $polite = 'no';
 my $scale = '50000';
 my $CONFIG_DIR    = "$ENV{'HOME'}/.gpsdrive"; # Should we allow config of this?
 my $CONFIG_FILE   = "$CONFIG_DIR/gpsdriverc";
 my $WAYPT_FILE    = "$CONFIG_DIR/way.txt";
-my $KOORD_FILE    = 'map_koord.txt'; # Should we allow config of this?
 my $FILEPREFIX    = 'map_';
 my $mapserver     = 'mapblast';
+my $replace       = '0';
+my $mapdir        = "";
 
 GetOptions ('lat=f' => \$lat, 'lon=f' => \$lon, 'start-lat=f' => \$slat, 'end-lat=f' => \$endlat, 'start-lon=f' => \$slon, 'end-lon=f' => \$endlon, 'scale=s' => \$scale, 'mapserver=s' => \$mapserver, 
             'waypoint=s' =>, \$waypoint, 'area=s' => \$area, 'unit=s' => \$unit,'mapdir=s' => \$mapdir, 'polite:i' => \$polite,
             'WAYPOINT=s' => \$WAYPT_FILE, 'CONFIG=s' => \$CONFIG_FILE, 'PREFIX=s' => \$FILEPREFIX,
-            'FORCE' => \$force, 'debug' => \$debug, 'MAN' => \$man, 'help|x' => \$help, 'version' => \$version)
+            'FORCE' => \$force, 'debug' => \$debug, 'MAN' => \$man, 'help|x' => \$help, 'version' => \$version, 'replace' => \$replace)
    or pod2usage(1);
 
+if ($mapdir eq "") {
+  $mapdir = $CONFIG_DIR;
+} else {
+  $mapdir = $CONFIG_DIR/$mapdir;
+}
+my $LOCK_SH = 1;
+my $LOCK_EX = 2;
+my $LOCK_NB = 4;
+my $LOCK_UN = 8;
+
+my $KOORD_FILE    = "$mapdir/map_koord.txt"; # Should we allow config of this?
+open(KOORD,">>$KOORD_FILE") || die "Can't open: $KOORD_FILE";
+
+# Setup possible scales
+my %ts1;
+if ($mapserver eq "terraserver") {
+  my ($s, $ts);
+
+  @SCALES = ();
+  $s = 2757;
+  for ($ts = 10; $ts <= 16; $ts++) {
+    @SCALES = (@SCALES, $s);
+    $ts1{$s} = $ts;
+    $s *= 2;
+  }
+} else {
+  @SCALES = (1000,1500,2000,3000,5000,7500,10000,15000,20000,30000,50000,75000,
+              100000,150000,200000,300000,500000,750000,1000000,1500000,2000000,3000000,
+              5000000,7500000,10000000,15000000,20000000,30000000,50000000,75000000);
+}
+
 pod2usage(1) if $help;
 pod2usage(-verbose=>2) if $man;
 
@@ -55,7 +88,6 @@
 
 
 # Setup up some constants
-my $EXPEDIAFACT   = 1378.6;
 my $DIFF          = 0.0000028;
 my $RADIUS_KM     = 6371.01;
 my $LAT_DIST_KM   = 110.87;
@@ -64,7 +96,7 @@
 
 # Get the list of scales we need
 my $SCALES_TO_GET_ref = get_scales(\$scale);
-print "Scale to download: ", join(",",sort {$a <=> $b} @{$SCALES_TO_GET_ref}), "\n" if ($debug);
+print "Scales to download: ", join(",",sort {$a <=> $b} @{$SCALES_TO_GET_ref}), "\n" if ($debug);
 
 # Get the center waypoint if they want one
 if ($waypoint) {
@@ -82,7 +114,7 @@
 unless ($slat && $slon && $endlat && $endlon) {
    ($slat,$slon,$endlat,$endlon) = get_coords(\$lat,\$lon,\$area,\$unit); 
 }
-print "Upper left: $slat $slon, Lower Right: $endlat, $endlon\n" if ($debug);
+print "Lower left: $slat $slon, Upper Right: $endlat, $endlon\n" if ($debug);
 
 unless ($force) {
    my $count = file_count(\($slat,$slon,$endlat,$endlon));
@@ -93,67 +125,136 @@
 
 print "\nDownloading files:\n";
 
-# Change into the gpsdrive maps directory 
-chdir($CONFIG_DIR);
-chdir($mapdir);
-
 # Ok start getting the maps
 foreach my $scale (@{$SCALES_TO_GET_ref}) {
-   # Setup k
-   my $k = $DIFF * $scale;
-   my $lati = $slat;   
-   while ($lati < $endlat) {
-      my $long = $slon;
-      while ($long < $endlon) {
-         my $filename = "$FILEPREFIX$scale-$lati-$long.gif";
-         if (! -s $filename) {
-            LOOP: {
-               if ($mapserver eq 'expedia') {
-                  next LOOP if ($scale <=1000);
-                  my $expediascale= sprintf("%d",$scale / $EXPEDIAFACT);
-                  my $where;
-                  if ($lon < -30) {
-                     $where = 'USA0409';
-                  } else {
-                     $where = 'EUR0809';
-                  }
-                  print "http://msrvmaps.mappoint.net/isapi/MSMap.dll?ID=3XNsF.\&C=$lati,$long\&L=$where\&CV=1\&A=$expediascale\&S=1280,1024\&O=0.000000,0.000000\&MS=0\&P=\n"
-                     if ($debug);
-                  `wget -nd -q -O tmpmap.gif "http://msrvmaps.mappoint.net/isapi/MSMap.dll?ID=3XNsF.\&C=$lati,$long\&L=$where\&CV=1\&A=$expediascale\&S=1280,1024\&O=0.000000,0.000000\&MS=0\&P="`;
-                  $scale = $expediascale * $EXPEDIAFACT;           
-               } elsif ($mapserver eq 'mapblast') {
-                  print "http://www.mapblast.com/myblastd/MakeMap.d?\&CT=$lati:$long:$scale\&IC=\&W=1280\&H=1024\&LB=\n"
-                     if ($debug);
-                  `wget -nd -q -O tmpmap.gif "http://www.mapblast.com/myblastd/MakeMap.d?\&CT=$lati:$long:$scale\&IC=\&W=1280\&H=1024\&LB="`;                  
-               }      
-               if (-s 'tmpmap.gif') {
-                  open(KOORD,">>$KOORD_FILE") || die "Can't open: $KOORD_FILE";
-                  print KOORD "$filename $lati $long $scale\n";
-                  rename('tmpmap.gif',$filename);
-                  print ".";
-                  print "\nWrote $filename\n" if ($debug);
-               } else {
-                  $failcount++;
-                  print ",";
-               }
-            }
-            # sleep if polite is turned on to be nice to the webserver of the mapserver
-            sleep($polite) if ($polite =~ /\d+/);
-            sleep(1) if (!$polite);
-         }
-         $long += $k;
-      }
-      $lati += $k;
-   }
-}
-print "Failcount: $failcount\n";
-print "\n";
+  # Setup k
+  my $k = sprintf("%.4f", $DIFF * $scale);
+  getmaps($scale, $slat, $endlat, $slon, $endlon, $k);
+}   
 
 ################################################################################
 #
 # Subroutines
 #
 ################################################################################
+
+sub getmaps {
+  my ($scale, $slat, $endlat, $slon, $endlon, $k) = @_;
+
+  print "Getting maps for scale: $scale\n";
+
+  my $l = floor($slat / $k);
+  my $lati = $k * $l;
+
+  $l = ceil($endlat / $k);
+  my $elat = $k * $l;
+  
+  while ($lati <= $elat) {
+    $l = floor($slon / $k);
+    my $long = $k * $l;
+    
+    $l = ceil($endlon / $k);
+    my $elon = $k * $l;
+    
+    while ($long <= $elon) {
+      getmap($scale, $lati, $long);
+      $long += $k;
+    }
+    $lati += $k;
+  }
+  print "\n";
+  print "Failcount: $failcount\n";
+  print "Cachecount: $cachecount\n";
+  print "Writecount: $writecount\n";
+}
+
+sub lock {
+  flock KOORD, $LOCK_EX;
+  # Move past addtions by other processes
+  seek KOORD, 0, 2;
+}
+
+sub unlock {
+  flock KOORD, $LOCK_UN;
+}
+
+sub getmap {
+  my ($scale, $lati, $long) = @_;
+  my $filename;
+  my $url;
+  my $la;
+  my $lo;
+
+  $la = sprintf("%.4f", $lati);
+  $lo = sprintf("%.4f", $long);
+
+  my $EXPEDIAFACT   = 1378.6;
+  $filename = mapfilename("$FILEPREFIX", $scale, $la, $lo);
+  $url = "";
+  if (! $replace && -e "$mapdir/$filename") {
+    $cachecount++;
+    print "=";
+    print "\nCached $filename\n" if ($debug);
+  } else {
+    if ($mapserver eq 'expedia' && $scale > 1000) {
+      my $expediascale= sprintf("%d",$scale / $EXPEDIAFACT);
+      my $where;
+      if ($lon < -30) {
+	$where = 'USA0409';
+      } else {
+	$where = 'EUR0809';
+      }
+      $url = "http://msrvmaps.mappoint.net/isapi/MSMap.dll?ID=3XNsF.\\&C=$la,$lo\\&L=$where\\&CV=1\\&A=$expediascale\\&S=1280,1024\\&O=0.000000,0.000000\\&MS=0\\&P=";
+    } elsif ($mapserver eq 'mapblast') {
+      $url = "http://www.mapblast.com/myblastd/MakeMap.d?\\&CT=$la:$lo:$scale\\&IC=\\&W=1280\\&H=1024\\&LB="; 
+    } elsif ($mapserver eq 'terraserver') {
+       my $sc = $ts1{$scale};
+       $url = "http://terraservice.net/GetImageArea.ashx?t=1\\&lat=$la\\&lon=$lo\\&s=$sc\\&w=1280\\&h=1024";
+    } elsif ($mapserver eq 'tiger') {
+      my $s = $scale / 300000.0;
+      $url = "http://tiger.census.gov/cgi-bin/mapper/map.gif?lat=$la\\&lon=$lo\\&wid=0.001\\&ht=$s\\&iwd=1280\\&iht=1024\\&on=majroads\\&on=places\\&on=shorelin\\&on=streets\\&on=interstate\\&on=statehwy\\&on=ushwy\\&on=water\\&tlevel=-\\&tvar=-\\&tmeth=i";
+    }
+    if ($url ne "") {
+      my $p = "--wait=$polite --random-wait" if (!$polite);
+      my ($fh, $tempfile) = tempfile( "temp_XXXXXX", DIR => "$mapdir" );
+
+      `wget $p -nd -q -O $tempfile $url`;                  
+      print $url if ($debug);
+
+      if (-s $tempfile) {
+	lock();
+	print KOORD "$filename $la $lo $scale\n";
+	unlock();
+	rename($tempfile, "$mapdir/$filename");
+	print ".";
+	print "\nWrote $filename\n" if ($debug);
+	$writecount++;
+      } else {
+	$failcount++;
+	print "\nFailed $filename\n";
+      }
+      # NEED convert to greyscale 
+      # and draw grid lines?
+      # using ImageMaqick?
+    }
+  }
+}
+
+sub mapfilename {
+  my ($prefix, $scale, $lati, $long) = @_;
+  my $pathname;
+  my $filename;
+
+  if ($mapserver eq 'terraserver') {
+    $scale = $ts1{$scale};
+  }
+  $pathname=sprintf("%s/%s/%03d/%08.4f/%d/", $mapserver, $scale, $lati, $lati, $long);
+  `mkdir -p "$mapdir/$pathname"`;
+  # I know there's a builtin mkdir, but last time I fussed with it
+  # there was no -p, and using it was tedious
+  $filename = sprintf("%s%d-%08.4f-%09.4f.gif", $prefix, $scale, $lati, $long);
+  return "$pathname$filename";
+}
 
 sub error_check {
    my $status;
