-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge remote-tracking branch 'refs/remotes/origin/dev'
- Loading branch information
Showing
8 changed files
with
1,204 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
MIT License | ||
|
||
Copyright (c) 2018 Daan De Smedt | ||
|
||
Permission is hereby granted, free of charge, to any person obtaining a copy | ||
of this software and associated documentation files (the "Software"), to deal | ||
in the Software without restriction, including without limitation the rights | ||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | ||
copies of the Software, and to permit persons to whom the Software is | ||
furnished to do so, subject to the following conditions: | ||
|
||
The above copyright notice and this permission notice shall be included in all | ||
copies or substantial portions of the Software. | ||
|
||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | ||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | ||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE | ||
SOFTWARE. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,94 @@ | ||
PHPWKTParser | ||
=============== | ||
|
||
Well-known text (WKT) is a text markup language for representing vector geometry objects on a map, spatial reference systems of spatial objects and transformations between spatial reference systems. | ||
|
||
|
||
EWKT (Extended Well-Known Text), a PostGIS-specific format that includes the spatial reference system identifier (SRID) and up to 4 ordinate values (XYZM), is also supported (ex: `SRID=31370;POINT(44 60)`). | ||
|
||
|
||
`PHPWKTParser` provides a simple usage helper class to read WKT and EWKT and parse this text representation to a workable PHP array holding the parsed WKT/EWKT definition. Read and parse 2D, 3D and 4D WKT (Well Known Text) / EWKT (Extended Well-Known Text) object strings into geometry objects with this simple WKT PHP adapter library. | ||
|
||
|
||
|
||
## Installation | ||
|
||
Install the package through [composer](http://getcomposer.org): | ||
|
||
``` | ||
composer require daandesmedt/phpwktadapter | ||
``` | ||
|
||
Make sure, that you include the composer [autoloader](https://getcomposer.org/doc/01-basic-usage.md#autoloading) somewhere in your codebase. | ||
|
||
|
||
## Supported geometry | ||
|
||
| Geometry Type | Example | | ||
| --- | --- | | ||
| POINT | POINT(30 10) | | ||
| LNESTRING | LINESTRING(30 10, 10 30, 40 40) | | ||
| POLYGON | POLYGON((0 0,10 0,10 10,0 10,0 0)) | | ||
| MULTIPOINT | MULTIPOINTZM(0 0 10 10,10 0 0 0,10 10 0 0,20 20 0 10) | | ||
| MULTILINESTRING | MULTILINESTRING((0 0,10 0,10 10,0 10)) | | ||
| MULTIPOLYGON | MULTIPOLYGON(((40 40, 20 45, 45 30, 40 40)), ((20 35, 10 30, 10 10, 30 5, 45 20, 20 35), (30 20, 20 15, 20 25, 30 20))) | | ||
| GEOMETRYCOLLECTION | GEOMETRYCOLLECTION(POINT(10 20),LINESTRING(0 0,10 0)) | | ||
|
||
|
||
## PHPWKTParser parsed and returned geometry array response | ||
|
||
The `read($wkt)` function of the `PHPWKTParser` adapter will return a associative array as representation of the parsed WKT/EWKT (in case of valid). | ||
|
||
|
||
``` | ||
array( | ||
// the geometry object type | ||
"type" => string, | ||
// integer or float values for POINT - nested array (integer or float) for other geometry types | ||
"value" => array, | ||
// integer representing the EWKT SRID, null when not present | ||
"srid" => integer | null, | ||
// string (Z, M or ZM) representing the dimension, null when not present | ||
"dimension" => string | null | ||
) | ||
``` | ||
|
||
## Working examples | ||
|
||
Working examples can be found in the `examples` folder. | ||
|
||
|
||
## Sample usage | ||
|
||
```php | ||
<?php | ||
|
||
require __DIR__ . '/../vendor/autoload.php'; | ||
|
||
use daandesmedt\PHPWKTAdapter\WKTAdapter; | ||
|
||
$adapter = new WKTAdapter(); | ||
$res = $adapter->read('SRID=31370;POINT(30 10)'); | ||
var_dump($res); | ||
``` | ||
|
||
## Handling exceptions | ||
|
||
Invalid format in the specified WKT / EWKT will result in a `UnexpectedValueException` thrown by the `WKTAdapter` . | ||
|
||
|
||
```php | ||
<?php | ||
|
||
require __DIR__ . '/../vendor/autoload.php'; | ||
|
||
use daandesmedt\PHPWKTAdapter\WKTAdapter; | ||
|
||
$adapter = new WKTAdapter(); | ||
|
||
try { | ||
$res = $adapter->read('SRID=31370;POINT(bad format)'); | ||
} catch (UnexpectedValueException $e) { | ||
var_dump($e->getMessage()); | ||
} | ||
``` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,31 @@ | ||
{ | ||
"name": "daandesmedt/phpwktadapter", | ||
"description": "Read and parse 2D, 3D and 4D WKT (Well Known Text) / EWKT (Extended Well-Known Text) object strings into geometry objects with this simple WKT PHP adapter library.", | ||
"keywords": ["php", "string", "text", "geometry", "geography", "spatial", "wkt", "ewkt"], | ||
"type": "library", | ||
"license": "MIT", | ||
"authors": [ | ||
{ | ||
"name": "Daan De Smedt", | ||
"email": "[email protected]" | ||
} | ||
], | ||
"autoload": { | ||
"psr-4": { | ||
"daandesmedt\\PHPWKTAdapter\\": "src/PHPWKTAdapter" | ||
} | ||
}, | ||
"autoload-dev": { | ||
"psr-4": { | ||
"daandesmedt\\Tests\\PHPWKTAdapter\\": "tests/PHPWKTAdapter" | ||
} | ||
}, | ||
"minimum-stability": "stable", | ||
"require": { | ||
"php": ">=7.0", | ||
"doctrine/lexer": "^1.0" | ||
}, | ||
"require-dev": { | ||
"phpunit/phpunit": "^8.2" | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,81 @@ | ||
<?php | ||
|
||
require __DIR__ . '/../vendor/autoload.php'; | ||
|
||
use daandesmedt\PHPWKTAdapter\WKTAdapter; | ||
|
||
|
||
$adapter = new WKTAdapter(); | ||
|
||
|
||
// HANDLE EXCEPTION | ||
// ######################################################### | ||
try { | ||
$res = $adapter->read('SRID=31370;POINT(bad format)'); | ||
} catch (UnexpectedValueException $e) { | ||
var_dump($e->getMessage()); | ||
} | ||
|
||
|
||
// POINT | ||
// ######################################################### | ||
$res = $adapter->read('SRID=31370;POINT(30 10)'); | ||
$res = $adapter->read('SRID=31370;POINTZM(30 10 5 60)'); | ||
$res = $adapter->read('SRID=31370;POINT ZM (30 10 5 60)'); | ||
$res = $adapter->read('SRID=31370;POINTM(30 10 80)'); | ||
$res = $adapter->read('SRID=31370;POINT M (30 10 80)'); | ||
$res = $adapter->read('SRID=31370;POINT Z (30 10 80)'); | ||
|
||
|
||
// POLYGON | ||
// ######################################################### | ||
$res = $adapter->read('SRID=31370;POLYGON((0 0,10 0,10 10,0 10,0 0))'); | ||
var_dump($res); | ||
exit; | ||
|
||
$res = $adapter->read('SRID=31370;POLYGON((0 0,10 0,10 10,0 10,0 0))'); | ||
$res = $adapter->read('SRID=31370;POLYGONZM((0 0 0 1,10 0 0 1,10 10 0 1,0 10 0 1,0 0 0 1))'); | ||
$res = $adapter->read('SRID=31370;POLYGONM((0 0 1,10 0 1,10 0 1,0 0 1,0 0 1))'); | ||
|
||
|
||
// LINESTRING | ||
// ######################################################### | ||
$res = $adapter->read('SRID=31370;LINESTRING(30 10, 10 30, 40 40)'); | ||
$res = $adapter->read('SRID=31370;LINESTRINGZM(15 15 0 0, 20 20 0 0)'); | ||
$res = $adapter->read('SRID=31370;LINESTRINGM(15 15 0, 20 20 0)'); | ||
|
||
|
||
// MULTIPOINT | ||
// ######################################################### | ||
$res = $adapter->read('SRID=31370;MULTIPOINT(0 10,10 10,10 20,10 30)'); | ||
$res = $adapter->read('SRID=31370;MULTIPOINTZM(0 0 10 10,10 0 0 0,10 10 0 0,20 20 0 10)'); | ||
$res = $adapter->read('SRID=31370;MULTIPOINTM(0 10 10,10 10 10,0 0 0,20 10 30)'); | ||
|
||
|
||
// MULTILINESTRING | ||
// ######################################################### | ||
$res = $adapter->read('SRID=31370;MULTILINESTRING((0 0,10 0,10 10,0 10))'); | ||
$res = $adapter->read('SRID=31370;MULTILINESTRING((0 0,10 0,10 10,0 10),(5 5,7 5,7 7,5 7))'); | ||
$res = $adapter->read('SRID=31370;MULTILINESTRINGZM((0 0 10 10,10 0 0 0,10 10 0 0,20 20 0 10),(60 40 10 10,70 10 20 40))'); | ||
$res = $adapter->read('SRID=31370;MULTILINESTRINGM((0 10 10,10 10 10,0 0 0,20 10 30))'); | ||
|
||
|
||
// MULTIPOLYGON | ||
// ######################################################### | ||
$res = $adapter->read('SRID=31370;MULTIPOLYGON (((30 20, 45 40, 10 40, 30 20)),((15 5, 40 10, 10 20, 5 10, 15 5)))'); | ||
$res = $adapter->read('SRID=31370;MULTIPOLYGON (((40 40, 20 45, 45 30, 40 40)), ((20 35, 10 30, 10 10, 30 5, 45 20, 20 35), (30 20, 20 15, 20 25, 30 20)))'); | ||
$res = $adapter->read('SRID=31370;MULTIPOLYGONZM(((40 40 10 10, 20 45 10 10, 45 30 10 10, 40 40 10 10)), ((20 35 10 10, 10 30 10 10, 10 10 10 10, 30 5 10 10, 45 20 10 10, 20 35 10 10)))'); | ||
$res = $adapter->read('SRID=31370;MULTIPOLYGONM(((40 40 10, 20 45 10, 45 30 10, 40 40 10)), ((20 35 10, 10 30 10, 10 10 10, 30 5 10, 45 20 10, 20 35 10)))'); | ||
|
||
|
||
// GEOMETRYCOLLECTION | ||
// ######################################################### | ||
$res = $adapter->read('SRID=31370;GEOMETRYCOLLECTION(POINT(10 20),LINESTRING(0 0,10 0))'); | ||
$res = $adapter->read('GEOMETRYCOLLECTION(POINT(10 20),POINT(0 10))'); | ||
$res = $adapter->read('GEOMETRYCOLLECTIONM(POINT(10 20 0),POINT(10 0 10))'); | ||
$res = $adapter->read('GEOMETRYCOLLECTIONZM(POINT(10 20 0 0),POINT(10 0 0 10))'); | ||
|
||
|
||
// DUMP | ||
// ######################################################### | ||
var_dump($res); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
<?xml version="1.0" encoding="UTF-8"?> | ||
|
||
<phpunit bootstrap="vendor/autoload.php" | ||
colors="true" | ||
convertErrorsToExceptions="true" | ||
convertNoticesToExceptions="true" | ||
convertWarningsToExceptions="true" | ||
processIsolation="false" | ||
stopOnFailure="true" | ||
> | ||
|
||
<testsuites> | ||
<testsuite name="WKTAdapterTest"> | ||
<directory>tests/PHPWKTAdapter</directory> | ||
</testsuite> | ||
</testsuites> | ||
|
||
</phpunit> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,129 @@ | ||
<?php | ||
|
||
namespace daandesmedt\PHPWKTAdapter\Lexer; | ||
|
||
use Doctrine\Common\Lexer\AbstractLexer; | ||
|
||
|
||
class WKTLexer extends AbstractLexer | ||
{ | ||
// character types | ||
const T_NONE = 1; | ||
const T_INTEGER = 2; | ||
const T_STRING = 3; | ||
const T_FLOAT = 5; | ||
const T_CLOSE_PARENTHESIS = 6; | ||
const T_OPEN_PARENTHESIS = 7; | ||
const T_COMMA = 8; | ||
const T_DOT = 10; | ||
const T_EQUALS = 11; | ||
const T_SEMICOLON = 50; | ||
|
||
// SRID | ||
const T_SRID = 500; | ||
const T_Z = 501; | ||
const T_M = 502; | ||
const T_ZM = 501; | ||
|
||
// Geometry types | ||
const T_TYPE = 600; | ||
const T_POINT = 601; | ||
const T_LINESTRING = 602; | ||
const T_POLYGON = 603; | ||
const T_MULTIPOINT = 604; | ||
const T_MULTILINESTRING = 605; | ||
const T_MULTIPOLYGON = 606; | ||
const T_GEOMETRYCOLLECTION = 607; | ||
|
||
/** | ||
* getCatchablePatterns | ||
* | ||
* @return array | ||
*/ | ||
protected function getCatchablePatterns() | ||
{ | ||
return array( | ||
'', | ||
'zm|[a-z]+[a-ln-y]', | ||
'[+-]?[0-9]+(?:[\.][0-9]+)?(?:e[+-]?[0-9]+)?' | ||
); | ||
} | ||
|
||
|
||
/** | ||
* getNonCatchablePatterns | ||
* | ||
* @return array | ||
*/ | ||
protected function getNonCatchablePatterns() | ||
{ | ||
return array('\s+'); | ||
} | ||
|
||
|
||
/** | ||
* getType | ||
* | ||
* @param string $value | ||
* @return int | ||
*/ | ||
protected function getType(&$value) : int | ||
{ | ||
// check numeric | ||
if (is_numeric($value)) { | ||
$value += 0; | ||
if (is_int($value)) { | ||
return self::T_INTEGER; | ||
} | ||
return self::T_FLOAT; | ||
} | ||
|
||
// check geom / srid type | ||
if (ctype_alpha($value)) { | ||
$name = __class__ . '::T_' . strtoupper($value); | ||
if (defined($name)) { | ||
return constant($name); | ||
} | ||
return self::T_STRING; | ||
} | ||
|
||
// check characteral type | ||
switch ($value) { | ||
case '.': | ||
return self::T_DOT; | ||
case ',': | ||
return self::T_COMMA; | ||
case '(': | ||
return self::T_OPEN_PARENTHESIS; | ||
case ')': | ||
return self::T_CLOSE_PARENTHESIS; | ||
case '=': | ||
return self::T_EQUALS; | ||
case ';': | ||
return self::T_SEMICOLON; | ||
default: | ||
return self::T_NONE; | ||
} | ||
} | ||
|
||
/** | ||
* getValue | ||
* | ||
* @return string | ||
*/ | ||
public function getValue() : string | ||
{ | ||
return $this->token['value']; | ||
} | ||
|
||
/** | ||
* getLookaheadType | ||
* | ||
* @return int | ||
*/ | ||
public function getLookaheadType() : int | ||
{ | ||
return (int)$this->lookahead['type']; | ||
} | ||
|
||
} |
Oops, something went wrong.