vis4.net

Hi, I'm Gregor, welcome to my blog where I mostly write about data visualization, cartography, colors, data journalism and some of my open source software projects.

Reading ESRI Shapefiles in PHP

This tutorial is the first part of a tutorial series about customized map projection in flash/actionscript. It shows how to extract plain coordinates out of a shapefile using the PHP Class Shapefile Reader by Juan Carlos Gonzales. 1 Reading Shapefiles in PHP, [2 Reading Shapefiles in ActionScript](http://vis4.net/blog/2010/04/reading-shapefiles-in-as3/).

Step 1: Download the map data

So, before we can draw any map we need a list of all countries and the coordinates of their boundaries. Luckily the internet is full of what we need, mostly packed in a binary data format called “shapefile” or “ESRI shapefile”. We start by downloading a shapefile from finder.geocommons.com which is a large portal for free map datasets. I decided to use the dataset World Countries Boundary File, World, 2002 because it includes not only information about the country boundaries but also some useful meta information like ISO codes etc. Here is a direct link to the zip-file containing the shapefiles. The zip-package contains three files, one shp-file containing all shape coordinates, one dbf-file containing all shape meta data and one shx-file containing the shape index file. You find more information on the structure shapefiles in the wikipedia.

Step 2: Import of the map data

Since flash has no built-in support for reading in shapefiles we need to do this by ourself using some external libraries. We can do this bei either on client-side in actionscript or on server-side in some server language like php or python. Zachary Forest Johnson from indiemaps.com compared both techniques and suggested the server-side method and that’s also what we’ll use in this tutorial. The next step is to create a small php script that reads in the shapefiles and outputs the shape coordinates so we can import them in actionscript. Therefore you need to download the PHP Class Shapefile Reader by Juan Carlos Gonzalez from phpclasses.org (you also need to create a free account first). I will go into the import script. The first part initializes our

// including the shapefile reader class
require 'ShapeFile.inc.php';

// importing the downloaded shapefile
$shp = new ShapeFile("5961.shp", array('noparts' => false));

Step 3: Output to a new csv file

Now we are ready to go through the shapefile and save the needed data into a csv file. I chose the following column setup for the csv file: iso 3 country code, iso 2 country code, country name and number of shapes, followed by one column for each shape coordinates. The coordinates are seperated by semicolons.

USA	US	United States	49	-135.69,57.36;-135.89,57.43;-136.01,57.51;

The php script continues with the opening of a new file for writing and a while-loop to iterate over all shapefile records. Inside the loop we extract the records meta data and store them into an array.

    // opening a new file for writing
    $out = fopen ("mapdata.csv", "w");

    while ($record = $shp->getNext()) {
    	// process meta data
    	$dbf_data = $record->getDbfData();
    	$data = array();
    	$data[] = trim($dbf_data["ISO_3_CODE"]);
    	$data[] = trim($dbf_data["ISO_2_CODE"]);
    	$data[] = trim($dbf_data["NAME"]);

Now we also read in the records shape data and store the number of shapes and each shape coordinates into the same array. The last thing to do is writing the data array into the output file and closing the file after finishing the iteration.

    	// process shape data
    	$shp_data = $record->getShpData();

    	// store number of parts
    	$data[] = $shp_data['numparts'];

    	foreach ($shp_data['parts'] as $part) {
    		$coords = array();
    		foreach ($part['points'] as $pt) $coords[] = $pt['x'] . ',' . $pt['y'];
    		$data[] = implode(';', $coords);
    	}
    	// write data as tab-seperated values into file
    	fputs($out, implode("\t", $data) . "\n");
    }
    fclose($out);

Step 4: further improvements

Since we want to send this file through the web later on it is a good time to think about the file size. By now the resulting csv file is about 3.6 megabytes large, which seems too much for me. In most cases we don’t need the country coordinates in such high resolution so one thing we can easily do is to round up the coordinates a little bit. Afterwards we can also look for duplicate coordinates and filter them out.

Download tutorial files

You can download a zip file containing the php script, the shapefiles and the resulting csv file.

The next tutorial will continue by showing how to read in the csv map file in flash/actionscript and how to draw a static world map. Update: I decided to insert another tutorial about how to read shapefiles but this time in actionscript, just to show both ways.

Comments

Reading ESRI Shapefiles in ActionScript | vis4 | information visualization (Apr 22, 2010)

[…] after Zachary Forest Johnson told me that he changed is mind about server-side reading of shapefiles, I decided to create another tutorial showing the […]

Zachary Forest Johnson (Apr 19, 2010)

I did indeed begin loading shapefiles server-side before transmitting to Flash, but I quickly learned that loading them client-side with Edwin van Rijkom’s SHP library was far easier and more efficient. So I’d go for that, unless you need to do much intense processing of the geodata (building topology, for instance, which you probably don’t wanna be doing in the browser).

Gregor Aisch (Apr 22, 2010)

@Zachary: thanks for this remark. I think I’ll add another tutorial that shows how to import shapefiles in as3, just to provide both ways.

Jens Schwaiger (Aug 13, 2010)

I used the data from the zip file to produce a worldmap in asymptote. The code and the resulting pdf file may be found here: http://www.uni-graz.at/~schwaige/asymptote/countries.asy > http://www.uni-graz.at/~schwaige/asymptote/countries.pdf

Rasmikant (Aug 11, 2010)

Hello, I am reading shape files with Edwin van Rijkom’s SHP library. But the size of my shape file is around 20MB. My browser is getting too slow while importing it. Could you please suggest what is the right way to do it.

Tutorial: Rendering a World Map in ActionScript | vis4.net (Aug 27, 2010)

[…] 1 Reading Shapefiles in PHP, 2 Reading Shapefiles in ActionScript, 3 Displaying a Static World Map in ActionScript. […]

Thomas (Sep 14, 2010)

Hello, I get this error and I don’t have access to php.ini:

Fatal error: Call to undefined function dbase_open() Do you know if I must re-configure php or is there anything else I can do? Thanks.

NJ (Jul 30, 2011)

I tried this code and i am getting an error on line

foreach($shp_data[‘parts’] as $part)

the error msg is:

Warning: Invalid argument supplied for foreach() in D:\xampp\htdocs\shapefile-tutorial\tutorial.php on line 28

plz can u suggest me what might be the problem..