Geo::Shapelib(3pm)
π Geo::Shapelib(3pm) π
User Contributed Perl Documentation, 3pm section, bestie. okay so this page is literally the whole vibe for Geo::Shapelib. π
πΈ NAME πΈ
Geo::Shapelib β a Perl extension for reading and writing shapefiles as defined by ESRI(r). No cap, it's giving geographic data realness. πΊοΈβ¨
β¨ SYNOPSIS β¨
First up, the basic import:
use Geo::Shapelib qw/:all/;
or
use Geo::Shapelib qw/:all/;
my $shapefile = new Geo::Shapelib {
Name => 'stations',
Shapetype => POINT,
FieldNames => ['Name','Code','Founded'],
FieldTypes => ['String:50','String:10','Integer:8']
};
while (<DATA>) {
chomp;
my($station,$code,$founded,$x,$y) = split /\|/;
push @{$shapefile->{Shapes}},{ Vertices => [[$x,$y,0,0]] };
push @{$shapefile->{ShapeRecords}}, [$station,$code,$founded];
}
$shapefile->save();
π DESCRIPTION π
okay so this is the library for reading, creating, and writing shapefiles as defined by ESRI(r) using Perl. The Perl code uses Frank Warmerdam's Shapefile C Library (http://shapelib.maptools.org/). And bestie, the library is included in this distribution. Slay. π«Ά
Currently no methods exist for populating an empty Shape. You need to do it in your own code. This is how:
First you include the module into your code. If you want to define the shape type using its name, import all:
use Geo::Shapelib qw/:all/;
Create the shapefile object and specify its name and type:
$shapefile = new Geo::Shapelib {
Name => <filename>,
Shapetype => <type from the list>,
FieldNames => <field name list>,
FieldTypes => <field type list>
}
The name (filename, may include path) of the shapefile, the extension is not used (it is stripped in the save method).
The shape type is an integer. This module defines shape type names as constants (see below).
The field name list is an array reference of the names of the data items assigned to each shape.
The field type list is an array reference of the types of the data items. Field type is either 'Integer', 'Double', or 'String'.
The types may have optional 'width' and 'decimals' fields defined, like this:
'Integer[:width]' defaults: width = 10
'Double[:width[:decimals]]' defaults: width = 10, decimals = 4
'String[:width]' defaults: width = 255
There are some other attributes which can be defined in the constructor (see below), they are rarely needed. The shape object will need or get a couple of other attributes as well. They should be treated as private:
$shapefile->{NShapes}is the number of shapes in your object. Shapefile is a collection of shapes. This is usually automatically deduced from the Shapes array when needed.$shapefile->{MinBounds}is set by shapelib C functions.$shapefile->{MaxBounds}is set by shapelib C functions.
Create the shapes and respective shape records and put them into the shape:
for many times {
make $s, a new shape as a reference to a hash
push @{$shapefile->{Shapes}}, $s;
make $r, a shape record as a reference to an array
push @{$shapefile->{ShapeRecords}}, $r;
}
how to create $s? It is a (reference to an) hash.
set:
$s->{Vertices} this is a reference to an array of arrays of four values, one for each vertex: x, y, z, and m of the vertex. There should be at least one vertex in $s. Point has only one vertex.
$s->{Parts}:
$s->{Parts} is not needed in simple cases. $s->{Parts} is a reference to an array (a) of arrays (b). There is one (b) array for each part. In a (b) array the first value is an index to the Vertices array denoting the first vertex of that part. The second value is the type of the part (NOTE: not the type of the shape). The type is 5 (Ring) unless the shape is of type Multipatch. The third value is set as the type of the part as a string when reading from a file but the save method requires only the first two values.
The index of the last vertex of any part is implicitly the index of the next part minus one or the index of the last vertex.
forget these:
$s->{ShapeId}may be left undefined. The save method sets it to the index in the Shapes array. Instead create and use an id field in the record.$s->{NParts}and$s->{NVertices}may be set but that is usually not necessary since they are calculated in the save method. You only need to set these if you want to save less parts or vertices than there actually are in the Parts or Vertices arrays.$s->{SHPType}is the type of the shape and it is automatically set to$shape->{Shapetype}unless defined (which you should not do)
The shape record is simply an array reference, for example:
$r = [item1,item2,item3,...];
That's all. Then save it and start your shapefile viewer to look at the result. π
π EXPORT π
None by default. The following export tags are defined.
:constantsβ This exports constant functions for the individual types of shapefile Types and shapefile part types. They all return scalar (integer) values. The shapetype functions:POINT,ARC,POLYGON,MULTIPOINT,POINTZ,ARCZ,POLYGONZ,MULTIPOINTZ,POINTM,ARCM,POLYGONM,MULTIPOINTM,MULTIPATCHare defined. The shapefile part types:TRISTRIP,TRIFAN,OUTERRING,INNERRING,FIRSTRING,RINGare defined.:typesβ Exports two hashes:%ShapeTypes,%PartTypeswhich map the shapelib type integers to string values.:allβ All possible exports are included.
π¦ CONSTRUCTORS π¦
This one reads in an existing shapefile:
$shapefile = new Geo::Shapelib "myshapefile", {<options>};
This one creates a new, blank Perl shapefile object:
$shapefile = new Geo::Shapelib {<options>};
{<options>} is optional in both cases, an example (note the curly braces):
$shapefile = new Geo::Shapelib {
Name => $shapefile,
Shapetype => POINT,
FieldNames => ['Name','Code','Founded'],
FieldTypes => ['String:50','String:10','Integer:8']
};
$shapefile = new Geo::Shapelib "myshapefile" {
Rtree => 1
};
π Options:
Likeβ A shapefile from which to copyShapeType,FieldNames, andFieldTypes.Nameβ Default is"shapefile". The filename (if given) becomes the name for the shapefile unless overridden by this.Shapetypeβ Default"POINT". The type of the shapes. (All non-null shapes in a shapefile are required to be of the same shape type.)FieldNamesβ Default is[].FieldTypesβ Default is[].ForceStringsβ Default is0. If1, sets allFieldTypesto string, may be useful if values are very large ints.Rtreeβ Default is0. If1, creates an R-tree of the shapes into an elementRtree. (RequiresLoadAll.)
When a shapefile is read from files they end up in a bit different kind of data structure than what is expected by the save method for example and what is described above. These flags enable the conversion, they are not normally needed.
CombineVerticesβ Default is1.CombineVerticesis experimental. The default behavior is to put all vertices into theVerticesarray and part indexes into thePartsarray. IfCombineVerticesis set to0there is noVerticesarray and all data goes into theParts. Currently settingCombineVerticesto0breaks saving of shapefiles. πUnhashFieldsβ Default is1. Makes$self's attributesFieldNames,FieldTypesrefs to lists, andShapeRecordsa list of lists.
The default is to load all data into Perl variables in the constructor. With these options the data can be left into the files to be loaded on-demand.
Loadβ Default is1. If0, has the same effect asLoadRecords=>0andLoadAll=>0.LoadRecordsβ Default is1. Reads shape records into$self->{ShapeRecords}automatically in the constructor using theget_record($shape_index)method.LoadAllβ Default is1. Reads shapes (the geometry data) into$self->{Shapes}automatically in the constructor using theget_shape($shape_index)method.
data_model π§
Returns the data model, converted into two arrays. That's it, that's the job.
If a filename got handed to a constructor at some point, then the data model was read straight out of the dbf file and stashed as a hashref in the FieldTypes attribute. This method takes that hashref and splits it into two arrays: FieldNames and the matching FieldTypes. Those arrayrefs get stored in attributes with those exact names β but only if UnhashFields is TRUE. π
get_shape(shape_index, from_file) π¦
Returns shape nr. shape_index+1 (heads up bestie, the first index is 0, not 1). The shape is read from a file even if the array Shapes exists, whenever from_file is TRUE.
Option CombineVertices is in operation here, fyi.
Use this method to get a shape unless you know what you are doing. π
get_record(shape_index, from_file) πΈ
Returns the record that belongs to shape nr. shape_index+1 (again, first index is 0). The record is read from a file even if the array ShapeRecords exists, whenever from_file is TRUE.
get_record_arrayref(shape_index, FieldNames, from_file) π
Returns the record belonging to shape nr. shape_index+1 (first index 0, you know the drill) as an arrayref. The parameter FieldNames may be undef, but if it is defined, it's used as the array that the record array gets sorted according to. This matters in the case where ShapeRecords contains hashrefs. The record is read from the file even if the array ShapeRecords exists, whenever from_file is TRUE.
Use this method to get a record of a shape unless you know what you are doing. π
get_record_hashref(shape_index, from_file) π
Returns the record belonging to shape nr. shape_index+1 (first index 0) as a hashref. The record is read from the file even if the array ShapeRecords exists, whenever from_file is TRUE. And if records are sitting in the array ShapeRecords as a list of lists, then FieldNames must contain the names of the fields. No skips, no shortcuts.
Use this method to get a record of a shape unless you know what you are doing. π
lengths(shape) β
Returns the lengths of the parts of the shape. That means the lengths of the parts of a polyline, or the length of the boundary of a polygon. Both 2D and 3D data are taken into account. She's thorough like that. π₯
π Using shapefile quadtree spatial indexing π
Want a list of shape ids within the specified bound, using a shapefile quadtree index? Say less:
$shapefile->query_within_rect($bounds, $maxdepth = 0);
$bounds should be an array reference of 4 elements: (xmin, ymin, xmax, ymax).
This method uses the quadtree indices defined by Shapelib β not ESRI spatial index files (.sbn, .sbx). And if a quadtree index (<basename>.qix) doesn't exist yet, one gets created and saved as a file. Not me creating files without asking, but okay bestie, slay. β¨
If you just want to create an index, there's a method for that too:
$shapefile->create_spatial_index($maxdepth = 0);
$maxdepth (optional) is the maximum depth of the index to create. Default is 0, which means shapelib will calculate a reasonable default depth for you. She's got it. π
π³ Rtree and editing the shapefile π³
Building an R-tree for the shapes:
$shapefile->Rtree();
This happens automatically if the Rtree-option is set when a shapefile is loaded from files.
Then you can use methods like these (there are not yet any wrappers for them, so get cozy with the raw calls):
my @shapes;
$shapefile->{Rtree}->query_point(@xy,\@shapes); # or
$shapefile->{Rtree}->query_completely_within_rect(@rect,\@shapes); # or
$shapefile->{Rtree}->query_partly_within_rect(@rect,\@shapes);
That gives you a list of shapes (indexes into the shape array), which you can feed for example to the select_vertices function:
for my $shape (@shapes) {
my $vertices = $shapefile->select_vertices($shape,@rect);
my $n = @$vertices;
print "you selected $n vertices from shape $shape\n";
}
The shapefile object remembers the selected vertices (iconic behaviour, honestly), and calling:
$shapefile->move_selected_vertices($dx,$dy);
moves them. The bboxes of the affected shapes, and the R-tree if one exists, are updated automatically. And to clear all selections from all shapes, call:
$selected->clear_selections();
π Setting the bounds of the shapefile π
$shapefile->set_bounds;
Sets the MinBounds and MaxBounds of all shapes and of the shapefile. Everyone gets bounds. No one left out. π«Ά
πΎ Saving the shapefile πΎ
$shapefile->save($filename);
The argument $shapefile is optional β the internal attribute $shapefile->{Name} gets used if $filename isn't specified. And if $filename is specified, it also becomes the new name.
$filename may contain an extension, but it gets removed and .shp etc. are used instead. Sorry to that extension, it's not staying. π
If you are not sure that the bounds of the shapefile are ok, then call $shapefile->set_bounds; before saving. Do it. Future you says thank you.
π οΈ create, add, close π οΈ
$shapefile->create($filename);
and then, many times over:
$shapefile->add($shape, $record);
and finally:
$shapefile->close();
These methods make it easy to create large shapefiles. $filename is optional. Heads up though: these methods create some temporary variables (prefix: _) in internal data, and that's exactly why calling the close method is required. Don't ghost the close. π
ποΈ Dump ποΈ
$shapefile->dump($to);
$to can be undef (in which case dump uses STDOUT), a filename, or a reference to a filehandle (e.g., \*DUMP).
This method just dumps all the data. And a lil warning: if you have created the shapefile yourself, then the reported bounds may be incorrect. π
π AUTHOR π
Ari Jolma, https://github.com/ajolma
π REPOSITORY π
https://github.com/ajolma/Geo-Shapelib
That's the whole page bestie, you made it to the end π This little gem comes from perl v5.40.1, dated 2025-03-06, and it lives under the name Geo::Shapelib(3pm). Go read the repo, go build something iconic with your shapefiles, and remember: call close. Periodt. π
β¨
π¦ where this page comes from
- debian trixie: libgeo-shapelib-perl 0.22-7 Β· Artistic-2.0
- ubuntu questing: libgeo-shapelib-perl 0.22-7
- π girlified by deepseek-ai/DeepSeek-V4.1-Flash on : a language model's rewrite of the original, under its terms