#! /usr/local/bin/perl 

###################################################################
## Thu Sep 22 15:38:51 PDT 2005
## attempt to read a shape file and create an ungenerated ascii of it
## for input to Newman and G?'s cartogram program
###################################################################



#use Geo::Shapelib qw/:all/;

#my $shapfile = new Geo::Shapelib "../FBORN.shp" ;

use Getopt::Std;
use strict;
use vars qw|$Useage $opt_s  $log|;
use Geo::ShapeFile;


=head1 ungenerate
"ungenerates" an ESRI "shape" file resulting in two ASCII files 
organized and named to be input into the Newman and Gastener 
diffusion cartogram program : cartogram

=head2 Synopsis
$0 -s shape-file-stem-name

=head2 Output

This will look for .shp, .shx, and .dbf files corresponding to the
name given in the -s argument. It will create a new directory called
shape-file-stem-name-CART, and in that directory it will write
"census.gen" and "map.dat" which are the ungenerated shape file and
the data file which Newman and Gastner's cartogram program expect --
named in the way that program likes it best.

The map.dat file DEFINITELY should be edited. Guesses are involved in
it's creation. Hopefuly it will give you the name and proper order of
the polygons in the shape file.

=cut

########################################################################




$| =1; 

$Useage='$0 -s shape-file-name-NO-suffix';

getopt('s:');

die ($Useage) unless ($opt_s);

die ("shape file missing component or is unreadable") unless
  (-r "$opt_s.shp") and
  (-r "$opt_s.shx") and 
  (-r "$opt_s.dbf");




my $shapefile = eval{new Geo::ShapeFile("$opt_s")};
unless(defined $shapefile) {
  print STDERR "Error reading shapefiles: $opt_s -- often the solution is\n".
    "to run dos2unix on the .dbf file\n\n:".

      $@."\n";
  exit;
}

my $numshapes= $shapefile->shapes();

die ("No shapes found in $opt_s\n") unless ($numshapes);
print STDERR "shapefile read. found to contain $numshapes shapes.\n";

### try to make a new directory
my $dirname=$opt_s.'-CART';
(-f $dirname) and die("$dirname is a file -- ".
		      "I was gonna create a directory by that name");
if (-d $dirname)  {
  print  $dirname." already exists shall we use it?[N/y]:";

  my $response =<STDIN>;
  die("ok, quitting") unless
    $response=~/[yY]/;
}else{

  mkdir $dirname or die ("can't create $dirname");
}

my $mapfile = $dirname.'/map.gen';
if (-f $mapfile) {
  print  $mapfile."exists shall we OVERWRITE it?[N/y]:";
  my $response =<STDIN>;
  die("ok, quitting") unless
    $response=~/[yY]/;
 }

open MAP, ">$mapfile" or die("can't open $mapfile");

my $census = $dirname.'/census.dat';
if (-f $census)   {
  print  $census."exists shall we OVERWRITE it?[N/y]:";
  my $response =<STDIN>;
  die("ok, quitting") unless
    $response=~/[yY]/;
}
open CENSUS, ">$census" or die("can't open $census");

########################################################################
## files are open, shape files are read. 
## Let's degenerate the shape file
########################################################################



print  "printing map.gen ...\n";
close(STDERR);
#open STDERR, '>', \$log or die("log variable won't open");
#print STDERR "ignore 8 bytes left messages..\n";
$log='ignore those 8 bytes left messages';

for (1.. $shapefile->shapes()){
  my $shapeno=$_;

  ## this works but casues an unsightly warning on stderr

open(STDERR, '>>', \$log ) or die ("can't redirect stderr");

  my $shape = $shapefile->get_shp_record($_);

open(STDERR, ">&STDOUT") or  die("can't get stderr back");

  print  "polygon: $shapeno\r";


  my %db = $shapefile->get_dbf_record($shapeno);
  print CENSUS $shapeno."  100  ";
  map{print CENSUS $db{$_}."  "}keys(%db);
  print CENSUS "\n";

#  print $shape->dump();
#  my @points= $shape->points();
  for (1..$shape->num_parts()){
#    print STDERR "shapenumber: $shapeno (of ".$shapefile->shapes().')'.
      "part number $_ (of ".$shape->num_parts().")\n";
    my @part = eval {
		     $shape->get_part($_)} ;
    print MAP "     $shapeno\n";
    map{print MAP "    $_->{X}    $_->{Y}\n";} @part;
    print MAP "END\n";

#    print $part->{X}."\t".$part->{Y}."\n";

  }

}
print MAP "END\n";


close MAP;
close CENSUS;

my $out= qq|


The directory $dirname should contain two files: map.gen is
the the "ungenerated" shape file; census.dat is a rough approximation of
the data file for the Gastner and Newman cartogram program. Its contents
reflect that of $opt_s .dbf.  The cartogram program expects that file
to  have the number of the shape (ie. geographical entity) in
column 1 and the data by which the map should be distorted in column 2
(this program sticks 100 in that column). All other columns are
ignored. Hopefuly one of the other columns will have the human
readable name of the shape, it would certainly be handy for editing
the file if it did.

After you edit census.dat you should be able to cd to $dirname
and type 'cartogram'.  If you are lucky, cartogram will read census.dat and 
map.gen and produce map.ps (the original map) and cartogram.ps the cartogram.


|;

print $out;

print STDERR "this is to stderr\n";
open LOG, ">ungen.log"  or die ("can't open log file");
print LOG $log."\n";
close(LOG);
