Skip to content

Commit 4876d11

Browse files
committed
Merge remote-tracking branch 'refs/remotes/origin/dev'
2 parents 7e21aa8 + c90b9bc commit 4876d11

File tree

8 files changed

+1204
-0
lines changed

8 files changed

+1204
-0
lines changed

LICENSE

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
MIT License
2+
3+
Copyright (c) 2018 Daan De Smedt
4+
5+
Permission is hereby granted, free of charge, to any person obtaining a copy
6+
of this software and associated documentation files (the "Software"), to deal
7+
in the Software without restriction, including without limitation the rights
8+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9+
copies of the Software, and to permit persons to whom the Software is
10+
furnished to do so, subject to the following conditions:
11+
12+
The above copyright notice and this permission notice shall be included in all
13+
copies or substantial portions of the Software.
14+
15+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21+
SOFTWARE.

README.md

Lines changed: 94 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,94 @@
1+
PHPWKTParser
2+
===============
3+
4+
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.
5+
6+
7+
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)`).
8+
9+
10+
`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.
11+
12+
13+
14+
## Installation
15+
16+
Install the package through [composer](http://getcomposer.org):
17+
18+
```
19+
composer require daandesmedt/phpwktadapter
20+
```
21+
22+
Make sure, that you include the composer [autoloader](https://getcomposer.org/doc/01-basic-usage.md#autoloading) somewhere in your codebase.
23+
24+
25+
## Supported geometry
26+
27+
| Geometry Type | Example |
28+
| --- | --- |
29+
| POINT | POINT(30 10) |
30+
| LNESTRING | LINESTRING(30 10, 10 30, 40 40) |
31+
| POLYGON | POLYGON((0 0,10 0,10 10,0 10,0 0)) |
32+
| MULTIPOINT | MULTIPOINTZM(0 0 10 10,10 0 0 0,10 10 0 0,20 20 0 10) |
33+
| MULTILINESTRING | MULTILINESTRING((0 0,10 0,10 10,0 10)) |
34+
| 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))) |
35+
| GEOMETRYCOLLECTION | GEOMETRYCOLLECTION(POINT(10 20),LINESTRING(0 0,10 0)) |
36+
37+
38+
## PHPWKTParser parsed and returned geometry array response
39+
40+
The `read($wkt)` function of the `PHPWKTParser` adapter will return a associative array as representation of the parsed WKT/EWKT (in case of valid).
41+
42+
43+
```
44+
array(
45+
// the geometry object type
46+
"type" => string,
47+
// integer or float values for POINT - nested array (integer or float) for other geometry types
48+
"value" => array,
49+
// integer representing the EWKT SRID, null when not present
50+
"srid" => integer | null,
51+
// string (Z, M or ZM) representing the dimension, null when not present
52+
"dimension" => string | null
53+
)
54+
```
55+
56+
## Working examples
57+
58+
Working examples can be found in the `examples` folder.
59+
60+
61+
## Sample usage
62+
63+
```php
64+
<?php
65+
66+
require __DIR__ . '/../vendor/autoload.php';
67+
68+
use daandesmedt\PHPWKTAdapter\WKTAdapter;
69+
70+
$adapter = new WKTAdapter();
71+
$res = $adapter->read('SRID=31370;POINT(30 10)');
72+
var_dump($res);
73+
```
74+
75+
## Handling exceptions
76+
77+
Invalid format in the specified WKT / EWKT will result in a `UnexpectedValueException` thrown by the `WKTAdapter` .
78+
79+
80+
```php
81+
<?php
82+
83+
require __DIR__ . '/../vendor/autoload.php';
84+
85+
use daandesmedt\PHPWKTAdapter\WKTAdapter;
86+
87+
$adapter = new WKTAdapter();
88+
89+
try {
90+
$res = $adapter->read('SRID=31370;POINT(bad format)');
91+
} catch (UnexpectedValueException $e) {
92+
var_dump($e->getMessage());
93+
}
94+
```

composer.json

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
{
2+
"name": "daandesmedt/phpwktadapter",
3+
"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.",
4+
"keywords": ["php", "string", "text", "geometry", "geography", "spatial", "wkt", "ewkt"],
5+
"type": "library",
6+
"license": "MIT",
7+
"authors": [
8+
{
9+
"name": "Daan De Smedt",
10+
"email": "[email protected]"
11+
}
12+
],
13+
"autoload": {
14+
"psr-4": {
15+
"daandesmedt\\PHPWKTAdapter\\": "src/PHPWKTAdapter"
16+
}
17+
},
18+
"autoload-dev": {
19+
"psr-4": {
20+
"daandesmedt\\Tests\\PHPWKTAdapter\\": "tests/PHPWKTAdapter"
21+
}
22+
},
23+
"minimum-stability": "stable",
24+
"require": {
25+
"php": ">=7.0",
26+
"doctrine/lexer": "^1.0"
27+
},
28+
"require-dev": {
29+
"phpunit/phpunit": "^8.2"
30+
}
31+
}

examples/WKTAdapter.php

Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
<?php
2+
3+
require __DIR__ . '/../vendor/autoload.php';
4+
5+
use daandesmedt\PHPWKTAdapter\WKTAdapter;
6+
7+
8+
$adapter = new WKTAdapter();
9+
10+
11+
// HANDLE EXCEPTION
12+
// #########################################################
13+
try {
14+
$res = $adapter->read('SRID=31370;POINT(bad format)');
15+
} catch (UnexpectedValueException $e) {
16+
var_dump($e->getMessage());
17+
}
18+
19+
20+
// POINT
21+
// #########################################################
22+
$res = $adapter->read('SRID=31370;POINT(30 10)');
23+
$res = $adapter->read('SRID=31370;POINTZM(30 10 5 60)');
24+
$res = $adapter->read('SRID=31370;POINT ZM (30 10 5 60)');
25+
$res = $adapter->read('SRID=31370;POINTM(30 10 80)');
26+
$res = $adapter->read('SRID=31370;POINT M (30 10 80)');
27+
$res = $adapter->read('SRID=31370;POINT Z (30 10 80)');
28+
29+
30+
// POLYGON
31+
// #########################################################
32+
$res = $adapter->read('SRID=31370;POLYGON((0 0,10 0,10 10,0 10,0 0))');
33+
var_dump($res);
34+
exit;
35+
36+
$res = $adapter->read('SRID=31370;POLYGON((0 0,10 0,10 10,0 10,0 0))');
37+
$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))');
38+
$res = $adapter->read('SRID=31370;POLYGONM((0 0 1,10 0 1,10 0 1,0 0 1,0 0 1))');
39+
40+
41+
// LINESTRING
42+
// #########################################################
43+
$res = $adapter->read('SRID=31370;LINESTRING(30 10, 10 30, 40 40)');
44+
$res = $adapter->read('SRID=31370;LINESTRINGZM(15 15 0 0, 20 20 0 0)');
45+
$res = $adapter->read('SRID=31370;LINESTRINGM(15 15 0, 20 20 0)');
46+
47+
48+
// MULTIPOINT
49+
// #########################################################
50+
$res = $adapter->read('SRID=31370;MULTIPOINT(0 10,10 10,10 20,10 30)');
51+
$res = $adapter->read('SRID=31370;MULTIPOINTZM(0 0 10 10,10 0 0 0,10 10 0 0,20 20 0 10)');
52+
$res = $adapter->read('SRID=31370;MULTIPOINTM(0 10 10,10 10 10,0 0 0,20 10 30)');
53+
54+
55+
// MULTILINESTRING
56+
// #########################################################
57+
$res = $adapter->read('SRID=31370;MULTILINESTRING((0 0,10 0,10 10,0 10))');
58+
$res = $adapter->read('SRID=31370;MULTILINESTRING((0 0,10 0,10 10,0 10),(5 5,7 5,7 7,5 7))');
59+
$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))');
60+
$res = $adapter->read('SRID=31370;MULTILINESTRINGM((0 10 10,10 10 10,0 0 0,20 10 30))');
61+
62+
63+
// MULTIPOLYGON
64+
// #########################################################
65+
$res = $adapter->read('SRID=31370;MULTIPOLYGON (((30 20, 45 40, 10 40, 30 20)),((15 5, 40 10, 10 20, 5 10, 15 5)))');
66+
$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)))');
67+
$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)))');
68+
$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)))');
69+
70+
71+
// GEOMETRYCOLLECTION
72+
// #########################################################
73+
$res = $adapter->read('SRID=31370;GEOMETRYCOLLECTION(POINT(10 20),LINESTRING(0 0,10 0))');
74+
$res = $adapter->read('GEOMETRYCOLLECTION(POINT(10 20),POINT(0 10))');
75+
$res = $adapter->read('GEOMETRYCOLLECTIONM(POINT(10 20 0),POINT(10 0 10))');
76+
$res = $adapter->read('GEOMETRYCOLLECTIONZM(POINT(10 20 0 0),POINT(10 0 0 10))');
77+
78+
79+
// DUMP
80+
// #########################################################
81+
var_dump($res);

phpunit.xml

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
3+
<phpunit bootstrap="vendor/autoload.php"
4+
colors="true"
5+
convertErrorsToExceptions="true"
6+
convertNoticesToExceptions="true"
7+
convertWarningsToExceptions="true"
8+
processIsolation="false"
9+
stopOnFailure="true"
10+
>
11+
12+
<testsuites>
13+
<testsuite name="WKTAdapterTest">
14+
<directory>tests/PHPWKTAdapter</directory>
15+
</testsuite>
16+
</testsuites>
17+
18+
</phpunit>

src/PHPWKTAdapter/Lexer/WKTLexer.php

Lines changed: 129 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,129 @@
1+
<?php
2+
3+
namespace daandesmedt\PHPWKTAdapter\Lexer;
4+
5+
use Doctrine\Common\Lexer\AbstractLexer;
6+
7+
8+
class WKTLexer extends AbstractLexer
9+
{
10+
// character types
11+
const T_NONE = 1;
12+
const T_INTEGER = 2;
13+
const T_STRING = 3;
14+
const T_FLOAT = 5;
15+
const T_CLOSE_PARENTHESIS = 6;
16+
const T_OPEN_PARENTHESIS = 7;
17+
const T_COMMA = 8;
18+
const T_DOT = 10;
19+
const T_EQUALS = 11;
20+
const T_SEMICOLON = 50;
21+
22+
// SRID
23+
const T_SRID = 500;
24+
const T_Z = 501;
25+
const T_M = 502;
26+
const T_ZM = 501;
27+
28+
// Geometry types
29+
const T_TYPE = 600;
30+
const T_POINT = 601;
31+
const T_LINESTRING = 602;
32+
const T_POLYGON = 603;
33+
const T_MULTIPOINT = 604;
34+
const T_MULTILINESTRING = 605;
35+
const T_MULTIPOLYGON = 606;
36+
const T_GEOMETRYCOLLECTION = 607;
37+
38+
/**
39+
* getCatchablePatterns
40+
*
41+
* @return array
42+
*/
43+
protected function getCatchablePatterns()
44+
{
45+
return array(
46+
'',
47+
'zm|[a-z]+[a-ln-y]',
48+
'[+-]?[0-9]+(?:[\.][0-9]+)?(?:e[+-]?[0-9]+)?'
49+
);
50+
}
51+
52+
53+
/**
54+
* getNonCatchablePatterns
55+
*
56+
* @return array
57+
*/
58+
protected function getNonCatchablePatterns()
59+
{
60+
return array('\s+');
61+
}
62+
63+
64+
/**
65+
* getType
66+
*
67+
* @param string $value
68+
* @return int
69+
*/
70+
protected function getType(&$value) : int
71+
{
72+
// check numeric
73+
if (is_numeric($value)) {
74+
$value += 0;
75+
if (is_int($value)) {
76+
return self::T_INTEGER;
77+
}
78+
return self::T_FLOAT;
79+
}
80+
81+
// check geom / srid type
82+
if (ctype_alpha($value)) {
83+
$name = __class__ . '::T_' . strtoupper($value);
84+
if (defined($name)) {
85+
return constant($name);
86+
}
87+
return self::T_STRING;
88+
}
89+
90+
// check characteral type
91+
switch ($value) {
92+
case '.':
93+
return self::T_DOT;
94+
case ',':
95+
return self::T_COMMA;
96+
case '(':
97+
return self::T_OPEN_PARENTHESIS;
98+
case ')':
99+
return self::T_CLOSE_PARENTHESIS;
100+
case '=':
101+
return self::T_EQUALS;
102+
case ';':
103+
return self::T_SEMICOLON;
104+
default:
105+
return self::T_NONE;
106+
}
107+
}
108+
109+
/**
110+
* getValue
111+
*
112+
* @return string
113+
*/
114+
public function getValue() : string
115+
{
116+
return $this->token['value'];
117+
}
118+
119+
/**
120+
* getLookaheadType
121+
*
122+
* @return int
123+
*/
124+
public function getLookaheadType() : int
125+
{
126+
return (int)$this->lookahead['type'];
127+
}
128+
129+
}

0 commit comments

Comments
 (0)