A while back I wrote I script for converting and styling KML files from ERSI Shapefiles, like you might download or export form a program like Quantum GIS. It requires you have the web programming language PHP 5 installed, along with the ogr2ogr command.
‘ ?>
View Larger Map ‘ ?>
This program extensively uses the PHP/DOM model, to read and write the XML file. I am not an expert programmer — it’s a hobby, but I am very happy with the results. You might consider using the LATFOR data and Census TIGER/Line for this if your a New York State resident.
#!/usr/bin/php -q
<?php
// POLITICAL STYLING FOR KML
// Converts a Shapefile with Election Results in Percentage
//
// Input:
// File_Title = Title for KML Name Field (as Seen in Google Maps)
// District_Name = Field with District Name In It
// Percent_as_Decimal = Election Result with Percent.
// 0.00 - 0.49 = Shade of Red
// 0.50 = White
// 0.50 - 1.00 = Blue
// Shapefile_Name = Path to Shapefile
//
// Output:
// Google Maps KML File, Nicely Styled
if (!isset($argv[4])) {
echo "usage: php politicalKML.php [File_Title] [District_Name] [Percent_as_Decimal] [Shapefile_Name]\n";
exit;
}
// required fields
$fileTitle = $argv[1];
$nameField = $argv[2];
$percentField = $argv[3];
// filename
$filename = $argv[4];
$KMLfileName = substr($filename,0,-4).'.kml';
// convert shapefile to kml using ogr2ogr
system("ogr2ogr -f \"KML\" -sql \"SELECT * FROM ". substr($filename,0,-4)." ORDER BY $fileTitle ASC\" $KMLfileName $filename -dsco NameField=$nameField -dsco DescriptionField=$percentField");
// load our new kml file
$doc = new DOMDocument();
$doc->load($KMLfileName);
// first let's replace the name field with a nicer one
$oldnode = $doc->getElementsByTagName('name')->item(0);
$node = $doc->createElement('name', $fileTitle);
$doc->getElementsByTagName('Folder')->item(0)->replaceChild($node, $oldnode);
// delete schema field to save space
$oldnode = $doc->getElementsByTagName('Schema')->item(0);
$doc->getElementsByTagName('Folder')->item(0)->removeChild($oldnode);
// load each placemark, search for maximum — used for making color judgements
foreach ($doc->getElementsByTagName('SimpleData') as $data) {
if( $data->getAttribute('name') == $percentField) {
$max[] = abs(substr($data->nodeValue,0)-0.5);
}
}
// maximum in the political race
sort($max); $max = array_pop($max);
// calcuate multiplier for each race
$multiple = 255/$max;
// load each placemark, then set styling and percentage description
foreach ($doc->getElementsByTagName('Placemark') as $placemark) {
foreach ($placemark->getElementsByTagName('SimpleData') as $data) {
if( $data->getAttribute('name') == $percentField) {
$value = $data->nodeValue;
$color = substr($value,0);
}
}
// decide if we want to do this blue or red, and then calculate
// the amount of color versus white
// republican leaning
if ($color <= 0.5) {
$colorStr = sprintf('%02x', 255-floor(abs($color-0.5)*$multiple));
$colorStr = "a0{$colorStr}{$colorStr}ff";
}
// democratic leaning
if ($color > 0.5) {
$colorStr = sprintf('%02x', 255-floor(abs($color-0.5)*$multiple));
$colorStr = "a0ff{$colorStr}{$colorStr}";
}
if ($color == 0) {
$colorStr = '00ffffff';
}
// stylize the node based on color
$node = $doc->createElement('Style');
$linestyle = $doc->createElement('LineStyle');
$node->appendChild($linestyle);
$linestyle->appendChild($doc->createElement('width', 0.1));
$linestyle->appendChild($doc->createElement('color', 'ffffffff'));
$polystyle = $doc->createElement('PolyStyle');
$node->appendChild($polystyle);
$polystyle->appendChild($doc->createElement('color', $colorStr));
$oldnode = $placemark->getElementsByTagName('Style')->item(0);
$placemark->replaceChild($node, $oldnode);
// delete extended data to save KML space
$data = $placemark->getElementsByTagName('ExtendedData')->item(0);
$placemark->removeChild($data);
// update the description
$oldnode = $placemark->getElementsByTagName('description')->item(0);
$node = $doc->createElement('description', 'Recieved '.($color*100).'% of the vote.');
$placemark->replaceChild($node, $oldnode);
}
// finally write to the file
$doc->save($KMLfileName);
// calculate size in MB
$filesize = filesize($KMLfileName)/1024/1024;
if ( $filesize < 10) {
$zipCommand = "zip ".substr($KMLfileName,0,-4).".kmz $KMLfileName";
system($zipCommand);
$kmzfilesize = filesize(substr($KMLfileName,0,-4).".kmz")/1024/1024;
echo "KMZ is " .sprintf('%01.2f', $kmzfilesize)." MB, while the KML file is ".sprintf('%01.2f',$filesize)." MB.\n";
}
else {
echo "Woah Horsey! The produced file is greater then 10 MB, at a size of ".sprintf('%01.2f',$filesize)." MB uncompressed. You need to simply your polygons before proceeding, otherwise Google Maps won't be able to read it. \n";
}
>