PHP Shapefile
PHP library to read and write ESRI Shapefiles, compatible with WKT and GeoJSON
Contents
- Get it
- Features
- Basic Usage
- Namespaces and Classes
- Files and filenames
- A note about Polygons orientation
- Geometry input/output formats
- DBF data input/output
- Examples
- History
- Comments and Ideas
Get it
GitHub
View project on GitHub or download the latest release.
Composer
composer require gasparesganga/php-shapefile
Features
- Reads and writes all kinds of Shapefiles, including Z and M ones
- Supports WKT/EWKT and GeoJSON input and output
- Completely standalone library
- Very fast and lightweight on memory
- Sequential read or random access to specific records
- Implements the Iterator and Fluent interfaces
- PHP 5.4+ compatible
- PHP FIG PSR-1, PSR-4 and PSR-12 compliant
Basic Usage
Reading Shapefiles
// Register autoloader
require_once('php-shapefile/src/Shapefile/ShapefileAutoloader.php');
Shapefile\ShapefileAutoloader::register();
// Import classes
use Shapefile\Shapefile;
use Shapefile\ShapefileException;
use Shapefile\ShapefileReader;
try {
// Open Shapefile
$Shapefile = new ShapefileReader('/path/to/file.shp');
// Read all the records
while ($Geometry = $Shapefile->fetchRecord()) {
// Skip the record if marked as "deleted"
if ($Geometry->isDeleted()) {
continue;
}
// Print Geometry as an Array
print_r($Geometry->getArray());
// Print Geometry as WKT
print_r($Geometry->getWKT());
// Print Geometry as GeoJSON
print_r($Geometry->getGeoJSON());
// Print DBF data
print_r($Geometry->getDataArray());
}
} catch (ShapefileException $e) {
// Print detailed error information
echo "Error Type: " . $e->getErrorType()
. "\nMessage: " . $e->getMessage()
. "\nDetails: " . $e->getDetails();
}
Writing Shapefiles
// Register autoloader
require_once('php-shapefile/src/Shapefile/ShapefileAutoloader.php');
Shapefile\ShapefileAutoloader::register();
// Import classes
use Shapefile\Shapefile;
use Shapefile\ShapefileException;
use Shapefile\ShapefileWriter;
use Shapefile\Geometry\Point;
try {
// Open Shapefile
$Shapefile = new ShapefileWriter('/path/to/file.shp');
// Set shape type
$Shapefile->setShapeType(Shapefile::SHAPE_TYPE_POINT);
// Create field structure
$Shapefile->addNumericField('ID', 10);
$Shapefile->addCharField('DESC', 25);
// Write some records (let's pretend we have an array of coordinates)
foreach ($coords_array as $i => $coords) {
// Create a Point Geometry
$Point = new Point($coords['x'], $coords['y']);
// Set its data
$Point->setData('ID', $i);
$Point->setData('DESC', "Point number $i");
// Write the record to the Shapefile
$Shapefile->writeRecord($Point);
}
// Finalize and close files to use them
$Shapefile = null;
} catch (ShapefileException $e) {
// Print detailed error information
echo "Error Type: " . $e->getErrorType()
. "\nMessage: " . $e->getMessage()
. "\nDetails: " . $e->getDetails();
}
Check the Examples section for more usage hints.
Namespaces and Classes
There are 2 Namespaces, Shapefile
and Shapefile\Geometry
, containing the following Classes:
- Shapefile\ShapefileAutoloader
- Shapefile\ShapefileException
- Abstract Shapefile\Shapefile
- Shapefile\ShapefileReader
- Shapefile\ShapefileWriter
- Abstract Shapefile\Geometry\Geometry
- Shapefile\Geometry\Point
- Shapefile\Geometry\MultiPoint
- Shapefile\Geometry\Linestring
- Shapefile\Geometry\MultiLinestring
- Shapefile\Geometry\Polygon
- Shapefile\Geometry\MultiPolygon
To keep things easy and tidy, all package-wide constants are exposed by Shapefile\Shapefile
Abstract Class, e.g.: Shapefile::OPTION_SUPPRESS_Z
.
Class Shapefile\ShapefileAutoloader
This is a simple static class which provides autoloading capabilities for the library. Use the static method Shapefile\ShapefileAutoloader::register()
as shown in the example to register the PHP Shapefile autoloader.
▲ Back to Namespaces and Classes
Class Shapefile\ShapefileException
A custom exception which extends PHP native Exception class. It can be used to isolate PHP Shapefile related exceptions. It adds 2 custom methods getErrorType()
and getDetails()
. See it in action in the example above.
▲ Back to Namespaces and Classes
ShapefileException::getErrorType
public ShapefileException::getErrorType( void ) : string
Gets internal error type as a string. Useful to react to specific errors.
Here are all possible error types:
Error | Description |
---|---|
Shapefile::ERR_UNDEFINED |
Undefined error |
Shapefile::ERR_FILE_MISSING |
A required file is missing |
Shapefile::ERR_FILE_EXISTS |
Check if the file exists and is readable and/or writable |
Shapefile::ERR_FILE_INVALID_RESOURCE |
File pointer resource not valid |
Shapefile::ERR_FILE_OPEN |
Unable to open file |
Shapefile::ERR_FILE_READING |
Error during binary file reading |
Shapefile::ERR_FILE_WRITING |
Error during binary file writing |
Shapefile::ERR_SHP_TYPE_NOT_SUPPORTED |
Shape type not supported |
Shapefile::ERR_SHP_TYPE_NOT_SET |
Shape type not set |
Shapefile::ERR_SHP_TYPE_ALREADY_SET |
Shape type has already been set |
Shapefile::ERR_SHP_GEOMETRY_TYPE_NOT_COMPATIBLE |
Geometry type must be compatible with Shapefile shape type |
Shapefile::ERR_SHP_MISMATCHED_BBOX |
Bounding box must have the same dimensions as the Shapefile (2D, 3D or 4D) |
Shapefile::ERR_SHP_FILE_ALREADY_INITIALIZED |
Cannot change Shapefile definition after it has been initialized with data |
Shapefile::ERR_SHP_WRONG_RECORD_TYPE |
Wrong record shape type |
Shapefile::ERR_DBF_FILE_NOT_VALID |
.dbf file doesn’t seem to be a valid dBase III or dBase IV format |
Shapefile::ERR_DBF_MISMATCHED_FILE |
Mismatched .dbf file. Number of records not corresponding to the .shp file |
Shapefile::ERR_DBF_EOF_REACHED |
End of .dbf file reached. Number of records not corresponding to the .shp file |
Shapefile::ERR_DBF_MAX_FIELD_COUNT_REACHED |
Cannot add other fields, maximum number of fields in a .dbf file reached |
Shapefile::ERR_DBF_FIELD_NAME_NOT_VALID |
Too many field names conflicting |
Shapefile::ERR_DBF_FIELD_TYPE_NOT_VALID |
Field type must be CHAR, DATE, LOGICAL, MEMO or NUMERIC |
Shapefile::ERR_DBF_FIELD_SIZE_NOT_VALID |
Field size incorrect according to its type |
Shapefile::ERR_DBF_FIELD_DECIMALS_NOT_VALID |
Field decimals incorrect according to its type |
Shapefile::ERR_DBF_CHARSET_CONVERSION |
Error during conversion from provided .dbf file input charset to UTF-8 |
Shapefile::ERR_DBT_EOF_REACHED |
End of .dbt file reached. File might be corrupted |
Shapefile::ERR_GEOM_NOT_EMPTY |
Cannot reinitialize non-empty Geometry |
Shapefile::ERR_GEOM_COORD_VALUE_NOT_VALID |
Invalid coordinate value |
Shapefile::ERR_GEOM_MISMATCHED_DIMENSIONS |
All geometries in a collection must have the same dimensions (2D, 3D or 4D) |
Shapefile::ERR_GEOM_MISMATCHED_BBOX |
Bounding box must have the same dimensions as the Geometry (2D, 3D or 4D) |
Shapefile::ERR_GEOM_MISSING_FIELD |
Geometry is missing a field defined in the Shapefile |
Shapefile::ERR_GEOM_POINT_NOT_VALID |
A Point can be either EMPTY or al least 2D |
Shapefile::ERR_GEOM_POLYGON_OPEN_RING |
Polygons cannot contain open rings |
Shapefile::ERR_GEOM_POLYGON_WRONG_ORIENTATION |
Polygon orientation not compliant with Shapefile specifications |
Shapefile::ERR_GEOM_RING_AREA_TOO_SMALL |
Ring area too small. Cannot determine ring orientation |
Shapefile::ERR_INPUT_RANDOM_ACCESS_UNAVAILABLE |
Shapefile has been loaded ignoring .shx file, only sequential read is possible |
Shapefile::ERR_INPUT_RECORD_NOT_FOUND |
Record index not found (check the total number of records in the .shp file) |
Shapefile::ERR_INPUT_FIELD_NOT_FOUND |
Field not found |
Shapefile::ERR_INPUT_GEOMETRY_TYPE_NOT_VALID |
Geometry type not valid. Must be of specified type |
Shapefile::ERR_INPUT_GEOMETRY_INDEX_NOT_VALID |
Geometry index not valid (check the total number of geometries in the collection) |
Shapefile::ERR_INPUT_ARRAY_NOT_VALID |
Array not valid |
Shapefile::ERR_INPUT_WKT_NOT_VALID |
WKT not valid |
Shapefile::ERR_INPUT_GEOJSON_NOT_VALID |
GeoJSON not valid |
Shapefile::ERR_INPUT_NUMERIC_VALUE_OVERFLOW |
Integer value overflows field size definition |
▲ Back to Namespaces and Classes
ShapefileException::getDetails
public ShapefileException::getDetails( void ) : string
Gets additional details about the error. It might return an empty string if no details are available.
Class Shapefile\Shapefile
This is the base Abstract Class for both ShapefileReader
and ShapefileWriter
. It cannot be directly instantiated, but exposes the following public methods for Classes than extend it:
- isZ
- isM
- getShapeType
- getBoundingBox
- getPRJ
- getCharset
- setCharset
- getFieldsNames
- getField
- getFieldType
- getFieldSize
- getFieldDecimals
- getFields
- getTotRecords
▲ Back to Namespaces and Classes
Shapefile::isZ
public Shapefile::isZ( void ) : bool
Returns true
if the Shapefile is of type Z or false
if it isn’t.
Shapefile::isM
public Shapefile::isM( void ) : bool
Returns true
if the Shapefile is of type M or false
if it isn’t. Please note that Z Shapefiles include M dimension too.
Shapefile::getShapeType
public Shapefile::getShapeType( [ int $format ] ) : mixed
Gets the Shapefile type as either text or number. Possible output values are:
Shape type | Value | Description |
---|---|---|
Shapefile::SHAPE_TYPE_NULL |
0 | Null Shape |
Shapefile::SHAPE_TYPE_POINT |
1 | Point |
Shapefile::SHAPE_TYPE_POLYLINE |
3 | PolyLine |
Shapefile::SHAPE_TYPE_POLYGON |
5 | Polygon |
Shapefile::SHAPE_TYPE_MULTIPOINT |
8 | MultiPoint |
Shapefile::SHAPE_TYPE_POINTZ |
11 | PointZ |
Shapefile::SHAPE_TYPE_POLYLINEZ |
13 | PolyLineZ |
Shapefile::SHAPE_TYPE_POLYGONZ |
15 | PolygonZ |
Shapefile::SHAPE_TYPE_MULTIPOINTZ |
18 | MultiPointZ |
Shapefile::SHAPE_TYPE_POINTM |
21 | PointM |
Shapefile::SHAPE_TYPE_POLYLINEM |
23 | PolyLineM |
Shapefile::SHAPE_TYPE_POLYGONM |
25 | PolygonM |
Shapefile::SHAPE_TYPE_MULTIPOINTM |
28 | MultiPointM |
$format
It specifies the return format and can be one of:
Shapefile::FORMAT_INT
: Integer (Default)
Shapefile::FORMAT_STR
: String
Shapefile::getBoundingBox
public Shapefile::getBoundingBox( void ) : array
Returns the whole Shapefile bounding box as an Array:
[
[xmin] => float
[xmax] => float
[ymin] => float
[ymax] => float
[zmin] => float // Present only in Z Shapefiles
[zmax] => float // Present only in Z Shapefiles
[mmin] => float/false // Present only in M and Z Shapefiles
[mmax] => float/false // Present only in M and Z Shapefiles
]
“No data” values set for M coordinates in the shapefiles are returned as Boolean false
.
Eventual Shapefile::OPTION_SUPPRESS_Z
and Shapefile::OPTION_SUPPRESS_M
options set with ShapefileReader constructor or ShapefileWriter constructor will effectively condition the output.
Shapefile::getPRJ
public Shapefile::getPRJ( void ) : string
Returns the raw WKT string from the .prj file. If there’s no .prj file then null
is returned.
Shapefile::getCharset
public Shapefile::getCharset( void ) : string
Returns the value read from the .cpg file, set with setCharset method, or the default one: 'ISO-8859-1'
.
Note that ShapefileReader
Class will use this information to convert data read from the files to UTF-8 when option Shapefile::OPTION_DBF_CONVERT_TO_UTF8
is enabled. See Strings charset conversion for details.
Shapefile::setCharset
public Shapefile::setCharset( mixed $charset ) : self
When called from a ShapefileReader
instance it sets the charset used to convert strings to UTF-8 when option Shapefile::OPTION_DBF_CONVERT_TO_UTF8
is enabled. It will overwrite the one read from the .cpg file.
When called from a ShapefileWriter
instance it sets the charset that will be written into the .cpg file. Note that no conversion is carried out by the library when writing Shapefiles, see Strings charset conversion for details.
Returns self instance to provide a fluent interface.
$charset
A string containing the charset name or a falsy value (e.g.: false
or empty string ""
) to reset it to default 'ISO-8859-1'
.
Shapefile::getFieldsNames
public Shapefile::getFieldsNames( void ) : array
Returns an Array of all fields names found in the Shapefile.
Shapefile::getField
public Shapefile::getField( string $name ) : array
Returns an Array representing the specified field definition:
[
[type] => string
[size] => int
[decimals] => int
]
$name
The name of the field to return. If it does not exist, a Shapefile::ERR_INPUT_FIELD_NOT_FOUND
ShapefileException will be thrown.
Shapefile::getFieldType
public Shapefile::getFieldType( string $name ) : string
Returns a String representing the specified field type. It can be one of:
Shapefile::DBF_TYPE_CHAR
: String.Shapefile::DBF_TYPE_DATE
: Date.Shapefile::DBF_TYPE_LOGICAL
: Logical/Boolean.Shapefile::DBF_TYPE_MEMO
: Memo (requires a .dbt file).Shapefile::DBF_TYPE_NUMERIC
: Numeric.Shapefile::DBF_TYPE_FLOAT
: Floating point numbers. This is actually not part of dBaseIII PLUS specifications, but since there are many Shapefiles out there using it, it has been included in this library.
$name
The name of the field to return. If it does not exist, a Shapefile::ERR_INPUT_FIELD_NOT_FOUND
ShapefileException will be thrown.
Shapefile::getFieldSize
public Shapefile::getFieldSize( string $name ) : int
Returns the lenght of the specified field. Note that all data is stored as a String into .dbf files.
$name
The name of the field to return. If it does not exist, a Shapefile::ERR_INPUT_FIELD_NOT_FOUND
ShapefileException will be thrown.
Shapefile::getFieldDecimals
public Shapefile::getFieldDecimals( string $name ) : int
Returns the lenght of the decimal part of the specified field. This makes sense only for fields of type Shapefile::DBF_TYPE_NUMERIC
.
$name
The name of the field to return. If it does not exist, a Shapefile::ERR_INPUT_FIELD_NOT_FOUND
ShapefileException will be thrown.
Shapefile::getFields
public Shapefile::getFields( void ) : array
Returns and Array representing the fields definition in the .dbf file:
[
[fieldname] => [
[type] => string
[size] => int
[decimals] => int
]
]
Shapefile::getTotRecords
public Shapefile::getTotRecords( void ) : int
Returns the number of records present in the Shapefile.
Special value Shapefile::UNKNOWN
will be returned when Shapefile::OPTION_IGNORE_FILE_SHX
constructor option is to true
.
Class Shapefile\ShapefileReader
The Shapefile reading Class that exposes all the public methods of the Shapefile base Class, plus the following ones:
This class also implements the Iterator interface. See Example 2 for details.
▲ Back to Namespaces and Classes
ShapefileReader::__construct
public ShapefileReader::__construct( mixed $files [, array $options = array() ] )
$files
String or Array, see Files and filenames for details.
$options
Use the $options
array parameter to pass some options and change the behaviour of the Class.
$Shapefile = new ShapefileReader('myshape.shp', [
Shapefile::OPTION_SUPPRESS_M => true,
Shapefile::OPTION_DBF_NULL_PADDING_CHAR => '*',
Shapefile::OPTION_DBF_IGNORED_FIELDS => ['FIELD_1', 'FIELD_2'],
]);
Here are the supported options and their default values:
Option | Default value | Description |
---|---|---|
Shapefile::OPTION_DBF_ALLOW_FIELD_SIZE_255 |
false |
Allows a maximum field size of 255 bytes instead of 254 bytes in the .dbf file |
Shapefile::OPTION_DBF_CONVERT_TO_UTF8 |
true |
Converts from input charset to UTF-8 all strings read from the .dbf file |
Shapefile::OPTION_DBF_FORCE_ALL_CAPS |
false |
Forces all column names in upper case in the .dbf file |
Shapefile::OPTION_DBF_IGNORED_FIELDS |
[] |
Array containing the names of the fields to ignore from the .dbf file |
Shapefile::OPTION_DBF_NULL_PADDING_CHAR |
null |
Defines a null padding character used in the .dbf file to represent null values |
Shapefile::OPTION_DBF_NULLIFY_INVALID_DATES |
true |
Returns a null value for invalid dates when reading .dbf files |
Shapefile::OPTION_DBF_RETURN_DATES_AS_OBJECTS |
false |
Returns dates as DateTime objects instead of ISO strings (YYYY-MM-DD ) |
Shapefile::OPTION_FORCE_MULTIPART_GEOMETRIES |
false |
Reads Polyline and Polygon Geometries as Multi (ESRI specs do not distinguish between Linestring/MultiLinestring and Polygon/MultiPolygon) |
Shapefile::OPTION_IGNORE_FILE_DBF |
false |
Ignores .dbf file (useful to recover corrupted Shapefiles). Data will not be available for geometries |
Shapefile::OPTION_IGNORE_FILE_SHX |
false |
Ignores .shx file (useful to recover corrupted Shapefiles). This might not always work and random access to specific records will not be possible |
Shapefile::OPTION_IGNORE_GEOMETRIES_BBOXES |
false |
Ignores geometries bounding boxes read from shapefile and computes some real ones instead |
Shapefile::OPTION_IGNORE_SHAPEFILE_BBOX |
false |
Ignores bounding box read from shapefile and computes a real one instead |
Shapefile::OPTION_POLYGON_CLOSED_RINGS_ACTION |
Shapefile::ACTION_CHECK |
Defines action to perform on Polygons rings. They should be closed but some software don’t enforce that, creating uncompliant Shapefiles. Possible values are Shapefile::ACTION_IGNORE , Shapefile::ACTION_CHECK and Shapefile::ACTION_FORCE . See Polygon __construct option $closed_rings for details |
Shapefile::OPTION_POLYGON_ORIENTATION_READING_AUTOSENSE |
true |
Allows Polygons orientation to be either clockwise or counterclockwise when reading Shapefiles (see this note about Polygons orientation). Set it to false to raise a Shapefile::ERR_GEOM_POLYGON_WRONG_ORIENTATION ShapefileException in case of Shapefiles uncompliant with ESRI specs |
Shapefile::OPTION_POLYGON_OUTPUT_ORIENTATION |
Shapefile::ORIENTATION_COUNTERCLOCKWISE |
Forces a specific orientation for Polygons after reading them (see this note about Polygons orientation). Possible values are Shapefile::ORIENTATION_CLOCKWISE , Shapefile::ORIENTATION_COUNTERCLOCKWISE and Shapefile::ORIENTATION_UNCHANGED |
Shapefile::OPTION_SUPPRESS_M |
false |
Ignores M dimension from Shapefile |
Shapefile::OPTION_SUPPRESS_Z |
false |
Ignores Z dimension from Shapefile |
ShapefileReader::getCurrentRecord
public ShapefileReader::getCurrentRecord( void ) : int
Returns the index of the current record. Note that record count starts from 1
in Shapefiles. When the last record is reached, the special value Shapefile::EOF
will be returned.
ShapefileReader::setCurrentRecord
public ShapefileReader::setCurrentRecord( int $index ) : self
Sets the index of the current record. If an invalid index is provided, this method will throw a ShapefileException
.
Calling this method will raise a Shapefile::ERR_INPUT_RANDOM_ACCESS_UNAVAILABLE
ShapefileException when Shapefile::OPTION_IGNORE_FILE_SHX
constructor option is set to true
.
Returns self instance to provide a fluent interface.
$index
The index of the record. Note that record count starts from 1
in Shapefiles.
ShapefileReader::fetchRecord
public Shapefile::fetchRecord( void ) : Geometry
Reads the current record returning a Geometry
object and moves the cursor forward to the next one.
When the last record is reached, the cursor will be set to the special value Shapefile::EOF
and this method will return Boolean value false
.
If you prefer using the Iterator interface, see Example 2 for details.
Class Shapefile\ShapefileWriter
The Shapefile writing Class that exposes all the public methods of the Shapefile base Class, plus the following ones:
- __construct
- setShapeType
- setCustomBoundingBox
- resetCustomBoundingBox
- setPRJ
- addCharField
- addDateField
- addLogicalField
- addMemoField
- addNumericField
- addFloatField
- addField
- writeRecord
- flushBuffer
▲ Back to Namespaces and Classes
ShapefileWriter::__construct
public ShapefileWriter::__construct( mixed $files [, array $options = array() ] )
$files
String or Array, see Files and filenames for details.
$options
Use the $options
array parameter to pass some options and change the behaviour of the Class.
$Shapefile = new ShapefileWriter('myshape.shp', [
Shapefile::OPTION_DBF_FORCE_ALL_CAPS => true,
Shapefile::OPTION_DBF_NULL_PADDING_CHAR => '*',
Shapefile::OPTION_EXISTING_FILES_MODE => Shapefile::MODE_OVERWRITE,
]);
Here are the supported options and their default values:
Option | Default value | Description |
---|---|---|
Shapefile::OPTION_BUFFERED_RECORDS |
10 |
Number of records to keep into memory buffer before writing them. Use a value equal or less than 0 to keep all records into a buffer and write them at once |
Shapefile::OPTION_CPG_ENABLE_FOR_DEFAULT_CHARSET |
false |
Writes a .cpg file (if there is one open) also when .dbf file data charset is the default one |
Shapefile::OPTION_DBF_ALLOW_FIELD_SIZE_255 |
false |
Allows a maximum field size of 255 bytes instead of 254 bytes in the .dbf file |
Shapefile::OPTION_DBF_FORCE_ALL_CAPS |
false |
Forces all column names in upper case in the .dbf file |
Shapefile::OPTION_DBF_NULL_PADDING_CHAR |
null |
Defines a null padding character to use in the .dbf file to represent null values |
Shapefile::OPTION_DBF_NULLIFY_INVALID_DATES |
true |
Nullify invalid dates when writing .dbf files |
Shapefile::OPTION_DELETE_EMPTY_FILES |
true |
Deletes empty files after closing them (only if they weren’t passed as resource handles) |
Shapefile::OPTION_ENFORCE_GEOMETRY_DATA_STRUCTURE |
true |
Enforces Geometries to have all data fields defined in Shapefile (otherwise null will be assumed) |
Shapefile::OPTION_EXISTING_FILES_MODE |
Shapefile::MODE_PRESERVE |
Defines behaviour with existing files with the same name. Possible values are Shapefile::MODE_PRESERVE (a Shapefile::ERR_FILE_EXISTS ShapefileException will be thrown), Shapefile::MODE_APPEND (new records will be appended to existing files), Shapefile::MODE_OVERWRITE (existing files will be completely overwritten) |
Shapefile::OPTION_SUPPRESS_M |
false |
Ignores M dimension in Geometries |
Shapefile::OPTION_SUPPRESS_Z |
false |
Ignores Z dimension in Geometries |
ShapefileWriter::setShapeType
public ShapefileWriter::setShapeType( [ int $type ] ) : self
Sets the Shapefile type.
Returns self instance to provide a fluent interface.
$type
Shape type. It can be on of the following:
Shape type | Value | Description |
---|---|---|
Shapefile::SHAPE_TYPE_NULL |
0 | Null Shape |
Shapefile::SHAPE_TYPE_POINT |
1 | Point |
Shapefile::SHAPE_TYPE_POLYLINE |
3 | PolyLine |
Shapefile::SHAPE_TYPE_POLYGON |
5 | Polygon |
Shapefile::SHAPE_TYPE_MULTIPOINT |
8 | MultiPoint |
Shapefile::SHAPE_TYPE_POINTZ |
11 | PointZ |
Shapefile::SHAPE_TYPE_POLYLINEZ |
13 | PolyLineZ |
Shapefile::SHAPE_TYPE_POLYGONZ |
15 | PolygonZ |
Shapefile::SHAPE_TYPE_MULTIPOINTZ |
18 | MultiPointZ |
Shapefile::SHAPE_TYPE_POINTM |
21 | PointM |
Shapefile::SHAPE_TYPE_POLYLINEM |
23 | PolyLineM |
Shapefile::SHAPE_TYPE_POLYGONM |
25 | PolygonM |
Shapefile::SHAPE_TYPE_MULTIPOINTM |
28 | MultiPointM |
ShapefileWriter::setCustomBoundingBox
public ShapefileWriter::setCustomBoundingBox( array $bounding_box ) : self
Sets a custom bounding box for the Shapefile, ignoring the one that is computed out of all the Geometries contained into it.
Returns self instance to provide a fluent interface.
$bounding_box
Associative array with the xmin
, xmax
, ymin
, ymax
and optional zmin
, zmax
, mmin
, mmax
values.
ShapefileWriter::resetCustomBoundingBox
public ShapefileWriter::resetCustomBoundingBox( void ) : self
Resets the custom bounding box for the Shapefile, meaning the normally computed one will be written into the file.
Returns self instance to provide a fluent interface.
ShapefileWriter::setPRJ
public ShapefileWriter::setPRJ( string $prj ) : self
Sets PRJ well-known-text that will be written into the .prj file.
Returns self instance to provide a fluent interface.
$prj
PRJ well-known-text. Pass a falsy value (e.g.: false
or empty string ""
) to delete it.
ShapefileWriter::addCharField
public ShapefileWriter::addCharField( string $name [, int $size = 254 ] ) : string
Adds a char field (type Shapefile::DBF_TYPE_CHAR
) to the Shapefile definition. It returns the effective field name after eventual sanitization.
$name
Name of the field. Maximum 10 characters. Only letters, numbers and underscores are allowed. Invalid or duplicated names will be silently sanitized, meaning that they will be truncated at 10 characters, not allowed characters replaced with underscores and in case of resulting duplicated names or conflicts, a serial number from _1
to 99
will be added.
$size
Lenght of the field, between 1 and 254 characters. Defaults to 254.
ShapefileWriter::addDateField
public ShapefileWriter::addDateField( string $name ) : string
Adds a date field (type Shapefile::DBF_TYPE_DATE
) to the Shapefile definition. It returns the effective field name after eventual sanitization.
$name
Name of the field. Maximum 10 characters. Only letters, numbers and underscores are allowed. Invalid or duplicated names will be silently sanitized, meaning that they will be truncated at 10 characters, not allowed characters replaced with underscores and in case of resulting duplicated names or conflicts, a serial number from _1
to 99
will be added.
ShapefileWriter::addLogicalField
public ShapefileWriter::addLogicalField( string $name ) : string
Adds a logical field (type Shapefile::DBF_TYPE_LOGICAL
) to the Shapefile definition. It returns the effective field name after eventual sanitization.
$name
Name of the field. Maximum 10 characters. Only letters, numbers and underscores are allowed. Invalid or duplicated names will be silently sanitized, meaning that they will be truncated at 10 characters, not allowed characters replaced with underscores and in case of resulting duplicated names or conflicts, a serial number from _1
to 99
will be added.
ShapefileWriter::addMemoField
public ShapefileWriter::addMemoField( string $name ) : string
Adds a memo field (type Shapefile::DBF_TYPE_MEMO
) to the Shapefile definition. It returns the effective field name after eventual sanitization.
$name
Name of the field. Maximum 10 characters. Only letters, numbers and underscores are allowed. Invalid or duplicated names will be silently sanitized, meaning that they will be truncated at 10 characters, not allowed characters replaced with underscores and in case of resulting duplicated names or conflicts, a serial number from _1
to 99
will be added.
ShapefileWriter::addNumericField
public ShapefileWriter::addNumericField( string $name [, int $size = 10 [, int $decimals = 0 ]] ) : string
Adds a numeric field (type Shapefile::DBF_TYPE_NUMERIC
) to the Shapefile definition. It returns the effective field name after eventual sanitization.
$name
Name of the field. Maximum 10 characters. Only letters, numbers and underscores are allowed. Invalid or duplicated names will be silently sanitized, meaning that they will be truncated at 10 characters, not allowed characters replaced with underscores and in case of resulting duplicated names or conflicts, a serial number from _1
to 99
will be added.
$size
Lenght of the field, between 1 and 254 characters. Defaults to 10.
$decimals
Number of decimal digits. Defaults to 0, meaning an integer number. See DBF data input/output section for details.
ShapefileWriter::addFloatField
public ShapefileWriter::addFloatField( string $name [, int $size = 20 [, int $decimals = 10 ]] ) : string
Adds a float field (type Shapefile::DBF_TYPE_FLOAT
) to the Shapefile definition. It returns the effective field name after eventual sanitization.
Note that this field type is actually not part of dBaseIII PLUS original specifications.
$name
Name of the field. Maximum 10 characters. Only letters, numbers and underscores are allowed. Invalid or duplicated names will be silently sanitized, meaning that they will be truncated at 10 characters, not allowed characters replaced with underscores and in case of resulting duplicated names or conflicts, a serial number from _1
to 99
will be added.
$size
Lenght of the field, between 1 and 254 characters. Defaults to 20.
$decimals
Number of decimal digits. Defaults to 10. Number of decimal digits cannot be 0 for this field type. See DBF data input/output section for details.
ShapefileWriter::addField
public ShapefileWriter::addField( string $name, string $type, int $size, int $decimals ) : string
Adds a field to the Shapefile definition. This is a kind of low level method that allows to add a field of any type. It returns the effective field name after eventual sanitization.
$name
Name of the field. Maximum 10 characters. Only letters, numbers and underscores are allowed. Invalid or duplicated names will be silently sanitized, meaning that they will be truncated at 10 characters, not allowed characters replaced with underscores and in case of resulting duplicated names or conflicts, a serial number from _1
to 99
will be added.
$type
Type of the field. It can be one of:
Shapefile::DBF_TYPE_CHAR
: String.Shapefile::DBF_TYPE_DATE
: Date.Shapefile::DBF_TYPE_LOGICAL
: Logical/Boolean.Shapefile::DBF_TYPE_MEMO
: Memo (requires a .dbt file).Shapefile::DBF_TYPE_NUMERIC
: Numeric.Shapefile::DBF_TYPE_FLOAT
: Floating point numbers. This is actually not part of dBaseIII PLUS specifications, but since there are many Shapefiles out there using it, it has been included in this library.
$size
Lenght of the field, between 1 and 254 characters.
$decimals
Number of decimal digits for numeric types.
ShapefileWriter::writeRecord
public ShapefileWriter::writeRecord( Geometry $Geometry ) : self
Writes a record to the Shapefile (actually, to all open files: .shp, .shx, .dbf and optional .dbt).
Returns self instance to provide a fluent interface.
$Geometry
A Geometry
object to be written into the Shapefile. It has to be compatible with the Shapefile shape type. If no shape type has been set, a Shapefile::ERR_SHP_TYPE_NOT_SET
ShapefileException will be thrown.
Depending on the state of Shapefile::OPTION_ENFORCE_GEOMETRY_DATA_STRUCTURE
option, either null
values will be used for missing data fields or a Shapefile::ERR_GEOM_MISSING_FIELD
ShapefileException will be thrown.
ShapefileWriter::flushBuffer
public ShapefileWriter::flushBuffer( void ) : self
Writes memory buffers to files. This will effectively reset the record counter that causes automatic buffer flushing according to the value specified with Shapefile::OPTION_BUFFERED_RECORDS
constructor option.
Returns self instance to provide a fluent interface.
Class Shapefile\Geometry\Geometry
This is the base Abstract Class for all the other Geometries. It cannot be directly instantiated, but exposes the following public methods for Classes than extend it:
- initFromArray
- initFromWKT
- initFromGeoJSON
- getArray
- getWKT
- getGeoJSON
- getBoundingBox
- setCustomBoundingBox
- resetCustomBoundingBox
- isEmpty
- isZ
- isM
- isDeleted
- setFlagDeleted
- getData
- setData
- getDataArray
- setDataArray
▲ Back to Namespaces and Classes
Geometry::initFromArray
public Geometry::initFromArray( array $array ) : self
Initializes the Geometry using a structured Array. See Geometry input/output formats for details.
Returns self instance to provide a fluent interface.
$array
The structured Array to initialize the Geometry with.
Geometry::initFromWKT
public Geometry::initFromWKT( string $wkt ) : self
Initializes the Geometry using a WKT String. See Geometry input/output formats for details.
Returns self instance to provide a fluent interface.
$wkt
The WKT String to initialize the Geometry with.
Geometry::initFromGeoJSON
public Geometry::initFromGeoJSON( string $geojson ) : self
Initializes the Geometry using a GeoJSON String. See Geometry input/output formats for details.
Returns self instance to provide a fluent interface.
$geojson
The GeoJSON String to initialize the Geometry with.
Geometry::getArray
public Geometry::getArray( void ) : array
Converts the Geometry into a structured Array. See Geometry input/output formats for details.
Geometry::getWKT
public Geometry::getWKT( void ) : string
Converts the Geometry into a WKT String. See Geometry input/output formats for details.
Geometry::getGeoJSON
public Geometry::getGeoJSON( [, bool $flag_bbox = true [, bool $flag_feature = false ]] ) : string
Converts the Geometry into a GeoJSON String. See Geometry input/output formats for details.
$flag_bbox
Boolean flag to include a "bbox"
member into the GeoJSON output. It defaults to true
for all the Geometries but Points, where it defaults to false
.
$flag_feature
Boolean flag to output a complete "Feature"
object with all the data instead of a simple “Geometry"
one.
Geometry::getBoundingBox
public Geometry::getBoundingBox( void ) : array
Returns the Geometry bounding box as an Array:
[
[xmin] => float
[xmax] => float
[ymin] => float
[ymax] => float
[zmin] => float // Present only in Z Geometries
[zmax] => float // Present only in Z Geometries
[mmin] => float/false // Present only in M and Z Geometries
[mmax] => float/false // Present only in M and Z Geometries
]
“No data” values set for M coordinates are returned as Boolean false
.
Geometry::setCustomBoundingBox
public Geometry::setCustomBoundingBox( array $bounding_box ) : self
Sets a custom bounding box for the Geometry, overriding the computed one. No formal check is carried out except the compliance of dimensions.
Returns self instance to provide a fluent interface.
$bounding_box
The bounding box array with "xmin"
, "xmax"
, "ymin"
, "ymax"
, and optional "zmin"
, "zmax"
, "mmin"
and "mmax"
members.
Geometry::resetCustomBoundingBox
public Geometry::resetCustomBoundingBox( void ) : self
Resets a previously set custom bounding box for the Geometry, causing getBoundingBox method to return a normally computed one.
Returns self instance to provide a fluent interface.
Geometry::isEmpty
public Geometry::isEmpty( void ) : bool
Returns true
if the Geometry is empty or false
if it isn’t.
Geometry::isZ
public Geometry::isZ( void ) : bool
Returns true
if the Geometry has the Z dimension or false
if it doesn’t.
Geometry::isM
public Geometry::isM( void ) : bool
Returns true
if the Geometry has the M dimension or false
if it doesn’t.
Geometry::isDeleted
public Geometry::isDeleted( void ) : bool
Returns true
if the record is marked as deleted in the .dbf file false
if it isn’t.
Geometry::setFlagDeleted
public Geometry::isDeleted( bool $value ) : self
Marks or unmarks the Geometry as deleted in the .dbf file. This makes sense only when writing Shapefiles.
Returns self instance to provide a fluent interface.
$value
Boolean value of the deleted flag.
Geometry::getData
public Geometry::getData( string $fieldname ) : mixed
Gets data value for the speficied field. Refer to the DBF data input/output section for details.
$fieldname
The field name to get the data for.
Geometry::setData
public Geometry::setData( string $fieldname, mixed $value) : self
Sets data value for the speficied field name. Refer to the DBF data input/output section for details.
Returns self instance to provide a fluent interface.
$fieldname
The field name to set the data for.
$value
The value to assign to the specified field in the Geometry.
Geometry::getDataArray
public Geometry::getDataArray( void ) : array
Gets all the data of the Geometry as an associative Array. Refer to the DBF data input/output section for details.
Geometry::setDataArray
public Geometry::setDataArray( array $data ) : self
Sets all the data of the Geometry using an associative Array. Refer to the DBF data input/output section for details.
Returns self instance to provide a fluent interface.
$data
Associative Array containing the data to assign to the different fields in the Geometry.
Class Shapefile\Geometry\Point
Point Geometry Class. It exposes all the public methods of the Geometry base Class, plus the following ones:
▲ Back to Namespaces and Classes
Point::__construct
public Point::__construct( [float $x = null, float $y = null [, float $z = null [, float $m = null ]]] )
You can create an empty Point without specifying any coordinate and using one of initFromArray, initFromWKT and initFromGeoJSON methods later on, or directly defining it passing its coordinates to the constructor.
If you choose for the latter, you will have to pass both X and Y coordinates, while both Z and M ones are optional.
$x
Value for X coordinate.
$y
Value for Y coordinate.
$z
Value for Z coordinate.
$m
Value for M coordinate.
Point::getX
public Point::getX( void ) : float
Returns the value of the X coordinate.
Point::getY
public Point::getY( void ) : float
Returns the value of the Y coordinate.
Point::getZ
public Point::getZ( void ) : float
Returns the value of the Z coordinate.
Point::getM
public Point::getM( void ) : float
Returns the value of the M coordinate.
Class Shapefile\Geometry\MultiPoint
MultiPoint Geometry Class. It exposes all the public methods of the Geometry base Class, plus the following ones:
▲ Back to Namespaces and Classes
MultiPoint::__construct
public MultiPoint::__construct( [ Points[] $points ] )
You can create an empty MultiPoint without passing any argument to its constructor and using one of initFromArray, initFromWKT and initFromGeoJSON methods later on, or directly defining it providing an array of Point Geometries.
$points
Array of Point Geometries.
MultiPoint::addPoint
public MultiPoint::addPoint( Point $Point ) : self
Adds a Point to the Collection.
Returns self instance to provide a fluent interface.
$Point
Point Geometry to add.
MultiPoint::getPoint
public MultiPoint::getPoint( int $index ) : Point
Gets a Point from the Collection at the specified index.
$index
Index of the Point Geometry to retrieve.
MultiPoint::getPoints
public MultiPoint::getPoints( void ) : Point[]
Gets all the Points from the Collection as an array of Point Geometries.
MultiPoint::getNumPoints
public MultiPoint::getNumPoints( void ) : int
Gets the number of Points in the Collection.
Class Shapefile\Geometry\Linestring
Linestring Geometry Class. It exposes all the public methods of the Geometry base Class, plus the following ones:
- __construct
- addPoint
- getPoint
- getPoints
- getNumPoints
- isClockwise
- isClosedRing
- forceClockwise
- forceCounterClockwise
- forceClosedRing
▲ Back to Namespaces and Classes
Linestring::__construct
public Linestring::__construct( [ Points[] $points ] )
You can create an empty Linestring without passing any argument to its constructor and using one of initFromArray, initFromWKT and initFromGeoJSON methods later on, or directly defining it providing an array of Point Geometries.
$points
Array of Point Geometries.
Linestring::addPoint
public Linestring::addPoint( Point $Point ) : self
Adds a Point to the Collection.
Returns self instance to provide a fluent interface.
$Point
Point Geometry to add.
Linestring::getPoint
public Linestring::getPoint( int $index ) : Point
Gets a Point from the Collection at the specified index.
$index
Index of the Point Geometry to retrieve.
Linestring::getPoints
public Linestring::getPoints( void ) : Point[]
Gets all the Points from the Collection as an array of Point Geometries.
Linestring::getNumPoints
public Linestring::getNumPoints( void ) : int
Gets the number of Points in the Collection.
Linestring::isClockwise
public Linestring::isClockwise( [$flag_throw_exception = false ] ) : bool|Shapefile::UNDEFINED
Checks whether a ring is clockwise or not (it works with open rings too).
Returns boolean true
or false
or special value Shapefile::UNDEFINED
in case Geometry is empty, so be sure to use the identity operator ===
to check return value.
$flag_throw_exception
Boolean flag to throw a Shapefile::ERR_GEOM_RING_NOT_ENOUGH_VERTICES
ShapefileException if there are not enough points to determine ring direction. This method returns Shapefile::UNDEFINED
in case this flag is set to false
and there are not enough vertices in the Linestring.
Linestring::isClosedRing
public Linestring::isClosedRing( void ) : bool
Checks whether the Linestring is a closed ring or not. A closed ring has at least 4 vertices and the first and last ones must be the same.
Linestring::forceClockwise
public Linestring::forceClockwise( void ) : self
Forces the Linestring (or ring) to be in clockwise direction (it works with open rings too).
It throws a Shapefile::ERR_GEOM_RING_NOT_ENOUGH_VERTICES
ShapefileException if there are not enough points to determine current direction.
Returns self instance to provide a fluent interface.
Linestring::forceCounterClockwise
public Linestring::forceCounterClockwise( void ) : self
Forces the Linestring (or ring) to be in counterclockwise direction (it works with open rings too).
It throws a Shapefile::ERR_GEOM_RING_NOT_ENOUGH_VERTICES
ShapefileException if there are not enough points to determine current direction.
Returns self instance to provide a fluent interface.
Linestring::forceClosedRing
public Linestring::forceClosedRing( void ) : self
Forces Linestring to be a closed ring, adding a point identical to the first one in case it is missing.
Returns self instance to provide a fluent interface.
Class Shapefile\Geometry\MultiLinestring
MultiLinestring Geometry Class. It exposes all the public methods of the Geometry base Class, plus the following ones:
▲ Back to Namespaces and Classes
MultiLinestring::__construct
public MultiLinestring::__construct( [ Linestring[] $linestrings ] )
You can create an empty MultiLinestring without passing any argument to its constructor and using one of initFromArray, initFromWKT and initFromGeoJSON methods later on, or directly defining it providing an array of Linestring Geometries.
$linestrings
Array of Linestring Geometries.
MultiLinestring::addLinestring
public MultiLinestring::addLinestring( Linestring $Linestring ) : self
Adds a Linestring to the Collection.
Returns self instance to provide a fluent interface.
$Linestring
Linestring Geometry to add.
MultiLinestring::getLinestring
public MultiLinestring::getLinestring( int $index ) : Linestring
Gets a Linestring from the Collection at the specified index.
$index
Index of the Linestring Geometry to retrieve.
MultiLinestring::getLinestrings
public MultiLinestring::getLinestrings( void ) : Linestring[]
Gets all the Linestrings from the Collection as an array of Linestring Geometries.
MultiLinestring::getNumLinestrings
public MultiLinestring::getNumLinestrings( void ) : int
Gets the number of Linestrings in the Collection.
Class Shapefile\Geometry\Polygon
Polygon Geometry Class. Throughout this Class the term Ring is used to refer to a closed Linestring, that is a Linestring with at least 4 vertices whose first and last ones must be the same. All Linestrings forming part of a Polygon are enforced to be closed rings.
It exposes all the public methods of the Geometry base Class, plus the following ones:
- __construct
- addRing
- getRing
- getRings
- getNumRings
- getOuterRing
- getInnerRings
- isClockwise
- isCounterClockwise
- forceClockwise
- forceCounterClockwise
- forceClosedRings
▲ Back to Namespaces and Classes
Polygon::__construct
public Polygon::__construct( [ Linestring[] $linestrings [, int $closed_rings = Shapefile::ACTION_CHECK [, int $force_orientation = Shapefile::ORIENTATION_COUNTERCLOCKWISE]]] )
You can create an empty Polygon without passing any argument to its constructor and using one of initFromArray, initFromWKT and initFromGeoJSON methods later on, or directly defining it providing an array of Linestring Geometries.
$linestrings
Array of Linestring Geometries.
$closed_rings
Optional action to perform on polygon rings. Possible values:
Shapefile::ACTION_IGNORE
: No action taken.Shapefile::ACTION_CHECK
: Checks for open rings and eventually throws aShapefile::ERR_GEOM_POLYGON_OPEN_RING
ShapefileException.Shapefile::ACTION_FORCE
: Forces all rings to be closed.
$force_orientation
Optional orientation to force for polygon rings. Possible values:
Shapefile::ORIENTATION_CLOCKWISE
: Forces clockwise outer ring and counterclockwise inner rings.Shapefile::ORIENTATION_COUNTERCLOCKWISE
: Forces counterclockwise outer ring and clockwise inner rings.Shapefile::ORIENTATION_UNCHANGED
: Preserves original orientation.
Polygon::addRing
public Polygon::addRing( Linestring $Linestring ) : self
Adds a Linestring to the Collection. Keep in mind that the first one will be recognized as the Polygon outer ring and no formal checks will be made.
Returns self instance to provide a fluent interface.
$Linestring
Linestring Geometry to add.
Polygon::getRing
public Polygon::getRing( int $index ) : Linestring
Gets a Linestring from the Collection at the specified index.
$index
Index of the Linestring Geometry to retrieve.
Polygon::getRings
public Polygon::getRings( void ) : Linestring[]
Gets all the Linestrings from the Collection as an array of Linestring Geometries.
Polygon::getNumRings
public Polygon::getNumRings( void ) : int
Gets the number of Linestrings in the Collection.
Polygon::getOuterRing
public Polygon::getOuterRing( void ) : Linestring
Gets the Polygon outer ring (that is, the ring at index 0
);
Polygon::getInnerRings
public Polygon::getInnerRings( void ) : Linestring[]
Gets Polygon inners rings as an array of Linestring Geometries.
Polygon::isClockwise
public Polygon::isClockwise( void ) : bool|Shapefile::UNDEFINED
Checks whether Polygon outer ring has a clockwise orientation and all its inner rings have a counterclockwise one.
Note that a false
return value does not guarantee Polygon is strictly counterclockwise. Use Polygon::forceCounterClockwise to enforce that!
Returns boolean true
or false
or special value Shapefile::UNDEFINED
in case Geometry is empty, so be sure to use the identity operator ===
to check return value.
Polygon::isCounterClockwise
public Polygon::isCounterClockwise( void ) : bool|Shapefile::UNDEFINED
Checks whether Polygon outer ring has a counterclockwise orientation and all its inner rings have a clockwise one.
Note that a false
return value does not guarantee Polygon is strictly clockwise. Use Polygon::forceClockwise to enforce that!
Returns boolean true
or false
or special value Shapefile::UNDEFINED
in case Geometry is empty, so be sure to use the identity operator ===
to check return value.
Polygon::forceClockwise
public Polygon::forceClockwise( void ) : self
Forces Polygon outer ring to have a clockwise orientation and all its inner rings to have a counterclockwise one.
It throws a Shapefile::ERR_GEOM_RING_NOT_ENOUGH_VERTICES
ShapefileException if there are not enough points in a ring to determine its direction.
Returns self instance to provide a fluent interface.
Polygon::forceCounterClockwise
public Polygon::forceCounterClockwise( void ) : self
Forces Polygon outer ring to have a counterclockwise orientation and all its inner rings to have a clockwise one.
It throws a Shapefile::ERR_GEOM_RING_NOT_ENOUGH_VERTICES
ShapefileException if there are not enough points in a ring to determine its direction.
Returns self instance to provide a fluent interface.
Polygon::forceClosedRings
public Polygon::forceClosedRings( void ) : self
Forces all Polygon rings to be closed.
Returns self instance to provide a fluent interface.
Class Shapefile\Geometry\MultiPolygon
MultiPolygon Geometry Class. It exposes all the public methods of the Geometry base Class, plus the following ones:
- __construct
- addPolygon
- getPolygon
- getPolygons
- getNumPolygons
- isClockwise
- isCounterClockwise
- forceClockwise
- forceCounterClockwise
- forceClosedRings
▲ Back to Namespaces and Classes
MultiPolygon::__construct
public MultiPolygon::__construct( [ Polygon[] $polygons [, int $closed_rings = Shapefile::ACTION_CHECK [, int $force_orientation = Shapefile::ORIENTATION_COUNTERCLOCKWISE]]] )
You can create an empty MultiPolygon without passing any argument to its constructor and using one of initFromArray, initFromWKT and initFromGeoJSON methods later on, or directly defining it providing an array of Polygon Geometries.
$polygons
Array of Polygon Geometries.
$closed_rings
Optional action to perform on polygons rings. Possible values:
Shapefile::ACTION_IGNORE
: No action taken.Shapefile::ACTION_CHECK
: Checks for open rings and eventually throws aShapefile::ERR_GEOM_POLYGON_OPEN_RING
ShapefileException.Shapefile::ACTION_FORCE
: Forces all rings to be closed.
$force_orientation
Optional orientation to force for polygons rings. Possible values:
Shapefile::ORIENTATION_CLOCKWISE
: Forces clockwise outer rings and counterclockwise inner rings.Shapefile::ORIENTATION_COUNTERCLOCKWISE
: Forces counterclockwise outer rings and clockwise inner rings.Shapefile::ORIENTATION_UNCHANGED
: Preserves original orientation.
MultiPolygon::addPolygon
public MultiPolygon::addPolygon( Polygon $Polygon ) : self
Adds a Polygon to the Collection.
Returns self instance to provide a fluent interface..
$Polygon
Polygon Geometry to add.
MultiPolygon::getPolygon
public MultiPolygon::getPolygon( int $index ) : Polygon
Gets a Polygon from the Collection at the specified index.
$index
Index of the Polygon Geometry to retrieve.
MultiPolygon::getPolygons
public MultiPolygon::getPolygons( void ) : Polygon[]
Gets all the Polygons from the Collection as an array of Polygon Geometries.
MultiPolygon::getNumPolygons
public MultiPolygon::getNumPolygons( void ) : int
Gets the number of Polygons in the Collection.
MultiPolygon::isClockwise
public Polygon::isClockwise( void ) : bool|Shapefile::UNDEFINED
Checks whether all MultiPolygon outer rings have a clockwise orientation and all its inner rings have a counterclockwise one.
Note that a false
return value does not guarantee MultiPolygon is strictly counterclockwise. Use MultiPolygon::forceCounterClockwise to enforce that!
Returns boolean true
or false
or special value Shapefile::UNDEFINED
in case Geometry is empty, so be sure to use the identity operator ===
to check return value.
MultiPolygon::isCounterClockwise
public Polygon::isCounterClockwise( void ) : bool|Shapefile::UNDEFINED
Checks whether all MultiPolygon outer rings have a counterclockwise orientation and all its inner rings have a clockwise one.
Note that a false
return value does not guarantee MultiPolygon is strictly clockwise. Use MultiPolygon::forceClockwise to enforce that!
Returns boolean true
or false
or special value Shapefile::UNDEFINED
in case Geometry is empty, so be sure to use the identity operator ===
to check return value.
MultiPolygon::forceClockwise
public MultiPolygon::forceClockwise( void ) : self
Forces all MultiPolygon outer rings to have a clockwise orientation and all its inner rings to have a counterclockwise one.
It throws a Shapefile::ERR_GEOM_RING_NOT_ENOUGH_VERTICES
ShapefileException if there are not enough points in a ring to determine its direction.
Returns self instance to provide a fluent interface.
MultiPolygon::forceCounterClockwise
public MultiPolygon::forceCounterClockwise( void ) : self
Forces all MultiPolygon outer rings to have a counterclockwise orientation and all its inner rings to have a clockwise one.
It throws a Shapefile::ERR_GEOM_RING_NOT_ENOUGH_VERTICES
ShapefileException if there are not enough points in a ring to determine its direction.
Returns self instance to provide a fluent interface.
MultiPolygon::forceClosedRings
public MultiPolygon::forceClosedRings( void ) : self
Forces all MultiPolygon rings to be closed.
Returns self instance to provide a fluent interface.
Files and filenames
Filenames can be passed either as a String with the path to the .shp
file (with or without the extension), as an Array containing individual paths to single files or as an Array of resource handles.
For example, the three following variants are equivalent:
// This is will look for "myshape.shp", "myshape.shx" and "myshape.dbf" files
$Shapefile = new ShapefileReader('myshape');
// This as well
$Shapefile = new ShapefileReader('myshape.shp');
// And this too
$Shapefile = new ShapefileReader([
Shapefile::FILE_SHP => 'myshape.shp',
Shapefile::FILE_SHX => 'myshape.shx',
Shapefile::FILE_DBF => 'myshape.dbf',
]);
In order to provide greater flexibility, it also accepts resource handles:
// Reading files
$Shapefile = new ShapefileReader([
Shapefile::FILE_SHP => fopen('/path/to/file.shp', 'rb'),
Shapefile::FILE_SHX => fopen('/path/to/file.shx', 'rb'),
Shapefile::FILE_DBF => fopen('/path/to/file.dbf', 'rb'),
]);
// Writing files
$Shapefile = new ShapefileWriter([
Shapefile::FILE_SHP => fopen('/path/to/file.shp', 'c+b'),
Shapefile::FILE_SHX => fopen('/path/to/file.shx', 'c+b'),
Shapefile::FILE_DBF => fopen('/path/to/file.dbf', 'c+b'),
]);
Keep in mind that in order for Shapefile::MODE_APPEND
to work as expected when passing resource handles to ShapefileWriter
constructor, resource handles access mode must be for binary reading and writing. The library internally uses c+b
, but as any of r+b
, wb
, w+b
, xb
, x+b
, cb
and c+b
will work just fine.
Supported file types are:
Shapefile::FILE_SHP
: Required. Geometries file.Shapefile::FILE_SHX
: Required. Index file.Shapefile::FILE_DBF
: Required. Attributes file.Shapefile::FILE_DBT
: Optional. Extended Memo attributes file.Shapefile::FILE_PRJ
: Optional. WKT projection file.Shapefile::FILE_CPG
: Optional. .dbf charset file.
Closing files / Releasing the handles
This library adopts a PDO-like behaviour when it comes to closing open files and releasing their handles: they are closed upon object destruction. This means that if you want to close open files, simply set the ShapefileReader or ShapefileWriter instance to null
:
$Shapefile = null;
It is extremely important to keep this in mind when writing Shapefiles: files will be finalized just before closing them! This means that if you want to do something with those newly created Shapefiles, you will have to close them destroying the ShapefileWriter instance before.
To answer the question “why not a close() method?” For the same reason as there is none in PDO: a ShapefileReader or ShapefileWriter instance with closed files would make no sense at all.
A note about Polygons orientation
ESRI Shapefile specifications establish clockwise orientation for Polygons outer rings and counterclockwise orientation for inner ones.
GeoJSON on the other hand dictates the opposite, as well as Simple Features used to do (this has been dropped eventually, allowing either orientation for Polygons). There is a lot of confusion about this subject and to make things worse the expression right-hand rule is used for both scenarios.
It is worth noting that many Simple Features implementations (such as PostGIS) will not reject Polygons not complying with the specification, nor should proper GeoJSON parsers (see the note in section 3.1.6).
This library gives the greatest flexibility to the programmer when reading Shapefiles through ShapefileReader Shapefile::OPTION_POLYGON_ORIENTATION_READING_AUTOSENSE
and Shapefile::OPTION_POLYGON_OUTPUT_ORIENTATION
constructor options. By default they are set respectively to true
and Shapefile::ORIENTATION_COUNTERCLOCKWISE
, meaning the library will be able to read a Shapefile even when it is not compliant with ESRI specs and output Polygons/MultiPolygons will be forced to have a counterclockwise orientation (that is, opposite of ESRI specs). This should ensure the widest interoperability out-of-the-box, but changing the value of those options will allow for every desired behaviour.
When writing a Shapefile things are easier, since the library will take care of everything and always produce a file compliant with ESRI specifications: it analyzes and eventually corrects Polygons/MultiPolygons, forcing closed rings, clockwise-oriented outer rings and counterclockwise inner rings.
Geometry input/output formats
Starting from v3 of this library, geometries are represented by specific classes that extend a Geometry abstract base class.
When reading from Shapefiles, multi MULTI*
, 3dz * Z
, 3dm * M
and 4d * ZM
geometries are recognized as such, unless some specific options like Shapefile::OPTION_SUPPRESS_Z
and Shapefile::OPTION_SUPPRESS_M
are being used.
ESRI Shapefile specifications allow a special “no data” value for M coordinates, which is represented by Boolean false
value in this library.
The structure of getArray, getWKT and getGeoJSON methods output is given below.
Point geometries
- Array:
[
[x] => float
[y] => float
[z] => float // Present only for 3dz and 4d types
[m] => float/bool // Present only for 3dm and 4d types
]
- WKT:
POINT [Z][M] (x y z m)
- GeoJSON Geometry:
{
"type": "Point" / "PointM"
"coordinates": [x, y, z, m]
}
- GeoJSON Feature:
{
"type": "Feature",
"geometry": {
"type": "Point" / "PointM",
"coordinates": [x, y, z, m]
},
"properties":{
"FIELD_1": "data1",
"FIELD_n": "datan"
}
}
MultiPoint geometries
- Array: [
[numpoints] => int
[points] => [
[
[x] => float
[y] => float
[z] => float // Present only for 3dz and 4d types
[m] => float/bool // Present only for 3dm and 4d types
]
]
]
- WKT:
MULTIPOINT [Z][M] (x y z m, x y z m)
N.B.: Points coordinates may be enclosed in additional brackets: MULTIPOINT ((x y z m), (x y z m))
- GeoJSON Geometry:
{
"type": "MultiPoint" / "MultiPointM",
"bbox": [xmin, ymin, zmin, mmin, xmax, ymax, zmax, mmax],
"coordinates": [
[x, y, z, m]
]
}
- GeoJSON Feature:
{
"type": "Feature",
"geometry": {
"type": "MultiPoint" / "MultiPointM",
"bbox": [xmin, ymin, zmin, mmin, xmax, ymax, zmax, mmax],
"coordinates": [
[x, y, z, m]
]
},
"properties":{
"FIELD_1": "data1",
"FIELD_n": "datan"
}
}
Linestring geometries
- Array: [
[numpoints] => int
[points] => [
[
[x] => float
[y] => float
[z] => float // Present only for 3dz and 4d types
[m] => float/bool // Present only for 3dm and 4d types
]
]
]
- WKT:
LINESTRING [Z][M] (x y z m, x y z m)
- GeoJSON Geometry:
{
"type": "LineString" / "LineStringM",
"bbox": [xmin, ymin, zmin, mmin, xmax, ymax, zmax, mmax],
"coordinates": [
[x, y, z, m]
]
}
- GeoJSON Feature:
{
"type": "Feature",
"geometry": {
"type": "LineString" / "LineStringM",
"bbox": [xmin, ymin, zmin, mmin, xmax, ymax, zmax, mmax],
"coordinates": [
[x, y, z, m]
]
},
"properties":{
"FIELD_1": "data1",
"FIELD_n": "datan"
}
}
MultiLinestring geometries
- Array: [
[numparts] => int
[parts] => [
[
[numpoints] => int
[points] => [
[
[x] => float
[y] => float
[z] => float
[m] => float/bool
]
]
]
]
]
- WKT:
MULTILINESTRING [Z][M] ((x y z m, x y z m, x y z m), (x y z m, x y z m))
- GeoJSON Geometry:
{
"type": "MultiLineString" / "MultiLineStringM"
"coordinates": [
[
[x, y, z, m]
]
]
}
- GeoJSON Feature:
{
"type": "Feature",
"geometry": {
"type": "MultiLineString" / "MultiLineStringM",
"bbox": [xmin, ymin, zmin, mmin, xmax, ymax, zmax, mmax],
"coordinates": [
[
[x, y, z, m]
]
]
},
"properties":{
"FIELD_1": "data1",
"FIELD_n": "datan"
}
}
Polygon geometries
- Array: [
[numrings] => int
[rings] => [
[
[numpoints] => int
[points] => [
[
[x] => float
[y] => float
[z] => float
[m] => float/bool
]
]
]
]
]
- WKT:
POLYGON [Z][M] ((x y z m, x y z m, x y z m, x y z m), (x y z m, x y z m, x y z m))
- GeoJSON Geometry:
{
"type": "Polygon" / "PolygonM"
"coordinates": [
[
[x, y, z, m]
]
]
}
- GeoJSON Feature:
{
"type": "Feature",
"geometry": {
"type": "Polygon" / "PolygonM",
"bbox": [xmin, ymin, zmin, mmin, xmax, ymax, zmax, mmax],
"coordinates": [
[
[x, y, z, m]
]
]
},
"properties":{
"FIELD_1": "data1",
"FIELD_n": "datan"
}
}
MultiPolygon geometries
- Array: [
[numparts] => int
[parts] => [
[
[numrings] => int
[rings] => [
[
[numpoints] => int
[points] => [
[
[x] => float
[y] => float
[z] => float
[m] => float/bool
]
]
]
]
]
]
]
- WKT:
MULTIPOLYGON [Z][M] (((x y z m, x y z m, x y z m, x y z m), (x y z m, x y z m, x y z m)), ((x y z m, x y z m, x y z m, x y z m), (x y z m, x y z m, x y z m)))
- GeoJSON Geometry:
{
"type": "MultiPolygon" / "MultiPolygonM"
"coordinates": [
[
[
[x, y, z, m]
]
]
]
}
- GeoJSON Feature:
{
"type": "Feature",
"geometry": {
"type": "MultiPolygon" / "MultiPolygonM",
"bbox": [xmin, ymin, zmin, mmin, xmax, ymax, zmax, mmax],
"coordinates": [
[
[
[x, y, z, m]
]
]
]
},
"properties":{
"FIELD_1": "data1",
"FIELD_n": "datan"
}
}
DBF data input/output
Despite some misleading information that can be found on the internet, .dbf files that come with ESRI Shapefiles must follow dBase III PLUS specifications and not dBase IV ones.
It is true dBase III PLUS and dBase IV are quite similar, but the differences between them are enough to prevent a perfectly compliant ESRI Shapefile parser from opening/reading a file using the wrong version specs.
More specifically, the full original version required by ESRI Shapefile standard is dBase III PLUS without memo files, which stores all the data as ISO-8859-1
-encoded text.
However, I took some licences and included custom charsets (.cpg files) and memo fields (.dbt files) support in this library, because a lot of modern software is using those features and they have become a de facto standard for Shapefiles.
Having clarified that, there are a couple of implications and things to keep in mind when using the library:
Numbers are stored as text in .dbf files
When reading a Shapefile, this library will not try to convert integer and floating point numbers to such. Instead, they will be returned as text, leaving complete freedom about data conversion and/or interpretation to the programmer. ShapefileReader getFieldDecimals method comes in handy for accurate conversion, but keep in mind that there is a lot of software out there creating not really compliant or accurate Shapefiles and the value returned by this method is often just descriptive or even plainly wrong in relation to the actual data stored in the .dbf file (that’s the reason why this library does not attempt an automatic conversion in the first place).
When writing a Shapefile, the library will take care of formal compliance to field size and decimals values, truncating eventual exceeding decimal parts, e.g.: the value 123.123456
in a field of size 10 with 5 decimals will be formatted as 123.1234
. If the lenght of the formatted value exceeds field size, a Shapefile::ERR_INPUT_NUMERIC_VALUE_OVERFLOW
ShapefileException will be thrown (e.g.: trying to store the value 123456.99
in a field of of size 10 with 5 decimals would produce 123456.9900
and raise the exception).
Dates are returned as text in ISO format or as DateTime
objects
Depending on the state of Shapefile::OPTION_DBF_NULLIFY_INVALID_DATES
and Shapefile::OPTION_DBF_RETURN_DATES_AS_OBJECTS
options, ShapefileReader Class will try to validate dates and return them as text in ISO YYYY-MM-DD format, as a DateTime object or as null
in case of an invalid date when Shapefile::OPTION_DBF_NULLIFY_INVALID_DATES
is enabled.
Logical values are converted to the right type
Logical values are parsed, converted and returned as boolean
. Beware that null
values are allowed for Shapefile::DBF_TYPE_LOGICAL
fields (internally stored as "?"
), thus possible return values are true
, false
and null
.
When reading a Shapefile, characters "T"
, "t"
, "Y"
, "y"
and "1"
are recognized as true
, while "F"
, "f"
, "N"
, "n"
and "0"
are recognized as false
. Anything else will be considered as null
.
When writing a Shapefile, the above values are accepted as well as true
, false
, null
and other data types: numbers are loosely casted to bool before conversion, truthy and falsy string values are stricly checked against allowed ones using the first non-trimmable char (e.g.: string "No way"
becomes "N"
hence false
) and anything else is considered as null
(or, in dBase terms, not initialized).
Strings charset conversion
When reading a Shapefile, if Shapefile::OPTION_DBF_CONVERT_TO_UTF8
is enabled, all strings will be converted to UTF-8 from the charset specified in the .cpg file or with setCharset method. It is important to perform the conversion directly into the library because strings are whitespace-padded into .dbf files and trimming them to remove useless padding before converting to UTF-8 might mess up the actual encoding (dBase specs assume strings are stored as ISO-8859-1
, where each character is always a single byte).
When writing a Shapefile, it is up to you to provide input strings encoded in the same charset specified with setCharset method. Keep in mind that dBase specifications only allow ISO-8859-1
encoding where each character occupy one single byte. Using a different charset encoding will likely reduce the effective maximun size of 254 characters allowed for a field (e.g.: for UTF-8
strings, more than one byte per character might be used). Longer strings will be truncated according to the specified field size, of course.
Memo fields
Memo fields do not have a size limitation by design (even though original specs did not allow .dbt files larger than 2GB). They store text in 512bytes consecutive blocks of plain text and their content is treated the same way as character fields (see above for charset conversion implications).
Examples
Example 1 - Get Shapefile info
// Register autoloader
require_once('php-shapefile/src/Shapefile/ShapefileAutoloader.php');
Shapefile\ShapefileAutoloader::register();
// Import classes
use Shapefile\Shapefile;
use Shapefile\ShapefileException;
use Shapefile\ShapefileReader;
echo "<pre>";
try {
// Open Shapefile
$Shapefile = new ShapefileReader('example.shp');
// Get Shape Type
echo "Shape Type : ";
echo $Shapefile->getShapeType() . " - " . $Shapefile->getShapeType(Shapefile::FORMAT_STR);
echo "\n\n";
// Get number of Records
echo "Records : ";
print_r($Shapefile->getTotRecords());
echo "\n\n";
// Get Bounding Box
echo "Bounding Box : ";
print_r($Shapefile->getBoundingBox());
echo "\n\n";
// Get PRJ
echo "PRJ : ";
print_r($Shapefile->getPRJ());
echo "\n\n";
// Get Charset
echo "Charset : ";
print_r($Shapefile->getCharset());
echo "\n\n";
// Get DBF Fields
echo "DBF Fields : ";
print_r($Shapefile->getFields());
echo "\n\n";
} catch (ShapefileException $e) {
// Print detailed error information
echo "Error Type: " . $e->getErrorType()
. "\nMessage: " . $e->getMessage()
. "\nDetails: " . $e->getDetails();
}
echo "</pre>";
Example 2 - Read a Shapefile using a foreach iterator
// Register autoloader
require_once('php-shapefile/src/Shapefile/ShapefileAutoloader.php');
Shapefile\ShapefileAutoloader::register();
// Import classes
use Shapefile\Shapefile;
use Shapefile\ShapefileException;
use Shapefile\ShapefileReader;
try {
$Shapefile = new ShapefileReader('example.shp');
foreach ($Shapefile as $i => $Geometry) {
/*
Do something with $Geometry here...
$i contains the record number.
*/
}
} catch (ShapefileException $e) {
// Handle the exception here...
}
Example 3 - Build a complex Geometry out of simple ones
// Import classes
use Shapefile\Geometry\Point;
use Shapefile\Geometry\Linestring;
use Shapefile\Geometry\Polygon;
// Build a Linestring passing an array of Points to its constructor
$Linestring1 = new Linestring([
new Point(0, 0),
new Point(2, 4),
new Point(4, 0),
new Point(0, 0),
]);
// Create en empty Linestring and initialize it with some WKT
$Linestring2 = new Linestring();
$Linestring2->initFromWKT('LINESTRING (1 1, 2 2, 3 1, 1 1)');
// Create an empty Polygon and adds an outer and an inner ring with previously created Linestrings
$Polygon = new Polygon();
$Polygon->addRing($Linestring1);
$Polygon->addRing($Linestring2);
Example 4 - Deal with record-level errors individually
// Register autoloader
require_once('php-shapefile/src/Shapefile/ShapefileAutoloader.php');
Shapefile\ShapefileAutoloader::register();
// Import classes
use Shapefile\Shapefile;
use Shapefile\ShapefileException;
use Shapefile\ShapefileReader;
try {
// Open Shapefile
$Shapefile = new ShapefileReader('example.shp');
// Read all records
$tot = $Shapefile->getTotRecords();
for ($i = 1; $i <= $tot; ++$i) {
try {
// Manually set current record. Don't forget this!
$Shapefile->setCurrentRecord($i);
// Fetch a Geometry
$Geometry = $Shapefile->fetchRecord();
// Skip deleted records
if ($Geometry->isDeleted()) {
continue;
}
/*
Do something with $Geometry here...
*/
} catch (ShapefileException $e) {
// Handle some specific errors types or fallback to default
switch ($e->getErrorType()) {
// We're crazy and we don't care about those invalid geometries... Let's skip them!
case Shapefile::ERR_GEOM_RING_AREA_TOO_SMALL:
case Shapefile::ERR_GEOM_RING_NOT_ENOUGH_VERTICES:
// The following "continue" statement is just syntactic sugar in this case
continue;
break;
// Let's handle this case differently... :)
case Shapefile::ERR_GEOM_POLYGON_WRONG_ORIENTATION:
exit("Do you want the Earth to change its rotation direction?!?");
break;
// A fallback is always a nice idea
default:
exit(
"Error Type: " . $e->getErrorType()
. "\nMessage: " . $e->getMessage()
. "\nDetails: " . $e->getDetails()
);
break;
}
}
}
} catch (ShapefileException $e) {
/*
Something went wrong during Shapefile opening!
*/
}
Wait, what about MultiPatch shape types?
Well, after more than 15 years working with GIS related technologies, I have yet to see a MultiPatch Shapefile. Supporting them is not currently in the todo list.
History
29 August 2023 - Version 3.4.1
23 January 2021 - Version 3.4.0
17 September 2020 - Version 3.3.3
17 August 2020 - Version 3.3.2
13 August 2020 - Version 3.3.1
23 May 2020 - Version 3.3.0
9 April 2020 - Version 3.2.0
2 February 2020 - Version 3.1.3
15 January 2020 - Version 3.1.2
10 November 2019 - Version 3.1.1
30 October 2019 - Version 3.1.0
23 September 2019 - Version 3.0.2
31 August 2019 - Version 3.0.1
30 August 2019 - Version 3.0.0
7 April 2018 - Version 2.4.3
6 December 2017 - Version 2.4.2
30 November 2017 - Version 2.4.1
20 November 2017 - Version 2.4.0
14 September 2017 - Version 2.3.0
23 November 2016 - Version 2.2.0
17 November 2016 - Version 2.1.0
10 November 2016 - Version 2.0.1
1 November 2016 - Version 2.0.0
31 March 2016 - Version 1.1
13 November 2014 - Version 1.0
Comments and Ideas
Want to leave a comment or give me an idea? Send me an or use the comments section below.