ptum has asked for the wisdom of the Perl Monks concerning the following question:

I've recently been asked to parse a collection of ESRI shape files to determine whether a given point falls within them.
"What luck!" I chortled, as I happened across jasonk's module.

Grabbing a sample shape file, I slapped together the example shown below.

The problem is, the X and Y point coordinates that I received seem to be wildly divergent from my expectations. Am I experiencing some kind of weird floating point problem, or do I need to convert my point values from some kind of projection? I was hoping for X and Y coordinates in terms of latitudinal and longitudinal degrees; solid, stable values like 44.234112 and -70.43101 -- the kind of numbers you wouldn't be ashamed to have over for dinner. Instead, I get numbers that I would be afraid to meet in a dark alley.

The contents of the .prj file (which seems to define the projection) are as follows:

GEOGCS["GCS_North_American_1983",DATUM["D_North_American_1983",SPHEROI +D["GRS_1980",6378137,298.257222101]],PRIMEM["Greenwich",0],UNIT["Degr +ee",0.017453292519943295]]

Here's the code I've slapped together:

#!/usr/local/bin/perl -w use strict; use Geo::ShapeFile; use Geo::ShapeFile::Point comp_includes_m => 0, comp_includes_z => 0; my $shapefile = new Geo::ShapeFile("/my/shape/dir/shape_group"); for(1 .. $shapefile->shapes()) { my $shape = $shapefile->get_shp_record($_); print "===============================================\n"; print "ID: ", $shape->shape_id(), "\n"; print "Centroid: ", $shape->centroid(), "\n"; print "Parts: ", $shape->num_parts(), "\n"; print "Points: ", $shape->num_points(), "\n"; print "Type: ", $shape->shape_type(), "\n"; print "X min: ", $shape->x_min(), "\n"; print "Y min: ", $shape->y_min(), "\n"; print "X max: ", $shape->x_max(), "\n"; print "Y max: ", $shape->y_max(), "\n"; print "Height: ", $shape->height(), "\n"; print "Width: ", $shape->width(), "\n"; my @points = $shape->corners(); foreach my $this_corner (@points) { print "Corner X: ", $this_corner->X(), "\n"; print "Corner Y: ", $this_corner->Y(), "\n"; } print "===============================================\n"; }

... and here's the output:

=============================================== ID: 1 Centroid: Point(X=-1.36971256117202e+301,Y=5.19769721893395e+296) Parts: 1 Points: 189 Type: 5 X min: 3.99649220734208e-297 Y min: -6.04919389741984e-286 X max: 5.7228212357179e-306 Y max: 1.59100403324442e+218 Height: -3.99649220161926e-297 Width: 1.59100403324442e+218 Corner X: 3.99649220734208e-297 Corner Y: -6.04919389741984e-286 Corner X: 5.7228212357179e-306 Corner Y: -6.04919389741984e-286 Corner X: 5.7228212357179e-306 Corner Y: 1.59100403324442e+218 Corner X: 3.99649220734208e-297 Corner Y: 1.59100403324442e+218 ===============================================

I'm using version 2.51 of Geo::ShapeFile. Any insight that the monks can provide would be very much appreciated.

Replies are listed 'Best First'.
Re: Geo::ShapeFile and Projection Conversion (floating point troubles?)
by GrandFather (Saint) on Sep 20, 2006 at 01:40 UTC

    Try reordering your use statements:

    use Geo::ShapeFile::Point comp_includes_m => 0, comp_includes_z => 0; use Geo::ShapeFile;

    From the "Important Note" in the documentation:

    This module uses overloaded operators to allow you to use == or eq to compare two point objects. By default points are considered to be equal only if their X, Y, Z, and M attributes are equal. If you want to exclude the Z or M attributes when comparing, you should use comp_includes_z or comp_includes_m when importing the object. Note that you must do this before you load the Geo::ShapeFile module, or it will pass it's own arguments to import, and you will get the default behavior

    DWIM is Perl's answer to Gödel

      Although this is true, it isn't affecting the code shown, which isn't doing any comparisons...


      We're not surrounded, we're in a target-rich environment!
Re: Geo::ShapeFile and Projection Conversion (floating point troubles?)
by jasonk (Parson) on Sep 20, 2006 at 14:39 UTC

    That looks a lot like an endian issue, unfortunately at the time it was written I didn't have a lot of access to big-endian machines so it didn't get a whole lot of testing in big-endian environments. There are a whole lot of things on my Geo::ShapeFile todo list, and this is at the top, but sadly I don't have much time to work through that list as my current job doesn't involve mapping and I've recently been busy with other things.

    If you can send me a sample of your shape data, it may help in tracking down some of those endian issues (or at the very least I could verify whether that is indeed the issue.)


    We're not surrounded, we're in a target-rich environment!

      I've sent the relevant shape files to one of your email addresses. I'm running Perl 5.8.8 on a Solaris 5.9 platform. Any help or guidance you can suggest would be greatly appreciated. :)