brick/geo

GIS几何库

维护者

详细信息

github.com/brick/geo

源代码

问题

资助包维护!
BenMorel

0.11.1 2024-08-19 20:33 UTC

README

PHP的GIS几何库。

Build Status Coverage Status Latest Stable Version Total Downloads License

简介

此库是OpenGIS规范(http://www.opengeospatial.org/standards/sfa)的PHP实现。

它提供了几何类(如PointLineStringPolygon等),并能原生读取/写入多种格式:WKB、WKT、EWKB、EWKT和GeoJSON。

它还提供了一个GeometryEngine接口用于高级计算(如长度、面积、并集、交集等),以及将这些操作委托给第三方GIS引擎的实现:GEOS扩展或支持GIS的数据库(如MySQL或PostgreSQL)。

要求和安装

此库需要PHP 8.1。对于PHP 8.0,您可以使用版本0.9。对于PHP 7.4,您可以使用版本0.7

使用Composer安装库

composer require brick/geo

如果您只需要基本操作,例如构建几何对象、从/导出到支持的格式(WKB、WKT、EWKB、EWKT或GeoJSON),则已准备好。

如果您需要高级功能,如length()union()intersection等,请转到配置部分以选择一个GeometryEngine实现。

项目状态和发布流程

此库仍在开发中。

当前版本号为0.x.y。当引入非破坏性更改(添加新方法、优化现有代码等)时,将增加y

当引入破坏性更改时,总是开始一个新的0.x版本周期。

因此,将项目锁定到给定的发布周期,如0.11.*是安全的。

如果您需要升级到较新的发布周期,请查看发布历史记录以获取每个进一步的0.x.0版本引入的更改列表。

快速入门

use Brick\Geo\LineString;
use Brick\Geo\Point;
use Brick\Geo\Polygon;

// Building geometries from coordinates

$lineString = LineString::of(
    Point::xy(1, 2),
    Point::xy(3, 4),
);

echo $lineString->asText(); // LINESTRING (1 2, 3 4)

// Importing geometries

$point = Point::fromText('POINT (1 2)');

echo $point->x(); // 1
echo $point->y(); // 2

// Using advanced calculations from a GeometryEngine
// (see the Configuration section)

$polygon = Polygon::fromText('POLYGON ((0 0, 0 3, 3 3, 0 0))');
echo $geometryEngine->area($polygon); // 4.5

$centroid = $geometryEngine->centroid($polygon);
echo $centroid->asText(); // POINT (1 2)

配置

通过GeometryEngine接口提供高级计算。该库包含以下实现

  • PDOEngine:通过PDO连接与GIS兼容的数据库进行通信。
    此引擎目前支持以下数据库
    • MySQL版本5.6或更高版本(仅限2D几何)
    • MariaDB版本5.5或更高版本
    • PostgreSQL带有PostGIS扩展
  • SQLite3Engine:通过带有SpatiaLite扩展的SQLite3数据库进行通信。
  • GEOSEngine:使用GEOS PHP扩展

您选择合适的实现应遵循两个标准

  • 可用性:如果您已经使用MySQL等支持GIS的数据库,这可能会是一个容易的选择;
  • 功能:并非所有数据库都提供相同的GIS功能
    • 某些功能可能在PostgreSQL上可用,但在其他数据库上不可用(请参阅空间函数参考部分)
    • 某些功能可能仅限于特定的几何类型和/或SRID;例如,buffer()在MySQL上工作,但在SRID 4326(GPS坐标,距离以米为单位)的Polygon上会失败
    • 某些数据库可能在SRID 4326上返回米为单位的距离,而其他数据库可能返回度为单位

您可能应该从最简单的方法开始,并测试这种设置是否符合您的期望。

以下是所有可能的配置的逐步指南

使用PDO和MySQL 5.6或更高版本

点击展开
  • 确保您的MySQL版本至少为5.6
    早期版本仅基于边界框提供部分GIS支持,且不受支持。

  • 在您的项目中使用此启动代码

    use Brick\Geo\Engine\PDOEngine;
    
    $pdo = new PDO('mysql:host=localhost', 'root', '');
    $geometryEngine = new PDOEngine($pdo);

使用自己的连接参数更新代码,或者如果您已有(推荐),则使用现有的PDO连接。

使用PDO和MariaDB 5.5或更高版本

点击展开

MariaDB是MySQL的一个分支,因此您可以遵循与MySQL相同的流程。只需确保您的MariaDB版本为5.5或更高。

使用PDO和带有PostGIS的PostgreSQL

点击展开
  • 确保PostGIS已安装在您的服务器上

  • 如有需要,在数据库服务器上启用PostGIS

      CREATE EXTENSION postgis;
    
  • 在您的项目中使用此启动代码

    use Brick\Geo\Engine\PDOEngine;
    
    $pdo = new PDO('pgsql:host=localhost', 'postgres', '');
    $geometryEngine = new PDOEngine($pdo);

使用自己的连接参数更新代码,或者如果您已有(推荐),则使用现有的PDO连接。

使用PDO和带有SpatiaLite的SQLite

点击展开

由于PDO_SQLITE驱动程序的限制,目前无法*使用SELECT LOAD_EXTENSION()查询加载SpatiaLite扩展,因此您无法使用PDO驱动程序与SpatiaLite一起使用。

您需要使用SQLite3驱动程序。请注意,您可以使用现有的PDO_SQLITE代码,您需要做的只是创建一个额外的内存SQLite3数据库,仅用于驱动几何引擎。

*实际上可能的,使用moxio/sqlite-extended-api,它使用FFI和Z-Engine,但请注意,这个库仍然是实验性的!

使用带有SpatiaLite的SQLite3

点击展开
  • 确保SpatiaLite已安装在您的系统上

  • 确保在您的php.ini中启用了SQLite3扩展

      extension=sqlite3.so
    
  • 确保在您的php.ini中配置了SpatiaLite安装的SQLite3扩展目录

      [sqlite3]
      sqlite3.extension_dir = /usr/lib
    
  • 在您的项目中使用此启动代码

    use Brick\Geo\Engine\SQLite3Engine;
    
    $sqlite3 = new SQLite3(':memory:');
    $sqlite3->loadExtension('mod_spatialite.so');
    $geometryEngine = new SQLite3Engine($sqlite3);
  • 根据您使用的函数,您可能需要运行此查询来初始化空间元数据

    SELECT InitSpatialMetaData();

    如果您的数据库是持久的,则只需运行此查询一次,但如果您的数据库是内存中的,则每次连接都需要运行它。请注意,这可能会影响性能。

在这个例子中,我们为GIS计算创建了一个内存数据库,但您也可以使用现有的SQLite3连接。

使用GEOS PHP绑定

点击展开
  • 确保GEOS的PHP绑定已安装在您的服务器上(GEOS 3.6.0及以后版本;早期版本需要使用带有--enable-php标志编译GEOS)。

  • 确保在您的php.ini中启用了GEOS扩展

      extension=geos.so
    
  • 在您的项目中使用此启动代码

    use Brick\Geo\Engine\GEOSEngine;
    
    $geometryEngine = new GEOSEngine();

几何层次结构

所有几何对象都位于Brick\Geo命名空间中,并扩展了一个基类Geometry

几何形状异常

所有几何形状异常都位于 Brick\Geo\Exception 命名空间中,并扩展了基类 GeometryException 对象。

几何形状异常是细粒度的:在整个项目中,只抛出基类 GeometryException 类的子类。这使用户可以选择捕获特定的异常,或者捕获所有与几何形状相关的异常。

以下是所有异常的列表

  • CoordinateSystemException 在混合具有不同 SRID 或维度(例如 XY 与 XYZ)的对象时抛出
  • EmptyGeometryException 在尝试访问空几何形状上的不存在属性时抛出
  • GeometryEngineException 在当前几何形状引擎不支持功能时抛出
  • GeometryIOException 在读取或写入(E)WKB/T 数据时出错时抛出
  • InvalidGeometryException 在创建无效的几何形状时抛出,例如只有单个 PointLineString
  • NoSuchGeometryException 在尝试从一个集合中获取一个不存在索引的几何形状时抛出
  • UnexpectedGeometryException 在几何形状不是预期子类型实例时抛出,例如在调用 Point::fromText() 时使用 LineString WKT。

几何形状引擎方法参考

这是 GeometryEngine 接口中所有可用方法的列表。某些方法仅在您使用特定几何形状引擎时可用,有时需要最小版本。

导入和导出几何形状

此库支持从以下格式导入和导出

  • WKT
  • WKB
  • EWKT
  • EWKB
  • GeoJSON

WKT

已知文本(WKT)是几何形状的标准文本格式。

每个几何形状类都提供了一个方便的方法 fromText(),它接受一个 WKT 字符串和一个可选的 SRID,并返回一个几何形状对象

use Brick\Geo\Point;

$point = Point::fromText('POINT (1.5 2.5)', 4326);

可以使用方便的方法 asText() 将几何形状转换为 WKT

echo $point->asText(); // POINT (1.5 2.5)

您还可以直接使用 WKTReaderWKTWriter 类;后者允许您以美观的格式输出。

WKB

已知二进制(WKB)是几何形状的标准二进制格式。

每个几何形状类都提供了一个方便的方法 fromBinary(),它接受一个 WKB 二进制字符串和一个可选的 SRID,并返回一个几何形状对象

use Brick\Geo\Point;

$point = Point::fromBinary(hex2bin('0101000000000000000000f83f0000000000000440'), 4326);

echo $point->asText(); // POINT (1.5 2.5)
echo $point->SRID(); // 4326

可以使用方便的方法 asBinary() 将几何形状转换为 WKB

echo bin2hex($point->asBinary()); // 0101000000000000000000f83f0000000000000440

您还可以直接使用 WKBReaderWKBWriter 类;后者允许您选择输出的字节序(大端或小端)。

EWKT

扩展 WKT 是一个特定于 PostGIS 的文本格式,它包括几何形状对象的 SRID,这在标准 WKT 格式中缺失。您可以使用 EWKTReaderEWKTWriter 类导入和导出此格式

use Brick\Geo\Point;
use Brick\Geo\IO\EWKTReader;
use Brick\Geo\IO\EWKTWriter;

$reader = new EWKTReader();
$point = $reader->read('SRID=4326; POINT (1.5 2.5)');

echo $point->asText(); // POINT (1.5 2.5)
echo $point->SRID(); // 4326

$writer = new EWKTWriter();
echo $writer->write($point); // SRID=4326; POINT (1.5 2.5)

EWKB

扩展WKB是PostGIS特定的二进制格式,它包含几何对象的SRID,这是标准WKB格式所缺少的。您可以使用EWKBReaderEWKBWriter类从这个格式导入和导出。

use Brick\Geo\Point;
use Brick\Geo\IO\EWKBReader;
use Brick\Geo\IO\EWKBWriter;

$reader = new EWKBReader();
$point = $reader->read(hex2bin('0101000020e6100000000000000000f83f0000000000000440'));

echo $point->asText(); // POINT (1.5 2.5)
echo $point->SRID(); // 4326

$writer = new EWKBWriter();
echo bin2hex($writer->write($point)); // 0101000020e6100000000000000000f83f0000000000000440

GeoJSON

GeoJSON是一种基于JSON的开放标准格式,旨在表示简单的地理要素,并在RFC 7946中标准化。

此库支持使用GeoJSONReaderGeoJSONWriter类从GeoJSON文档导入几何对象并将其导出。

use Brick\Geo\Point;
use Brick\Geo\IO\GeoJSONReader;
use Brick\Geo\IO\GeoJSONWriter;

$reader = new GeoJSONReader();
$point = $reader->read('{ "type": "Point", "coordinates": [1, 2] }');

echo $point->asText(); // POINT (1 2)
echo $point->SRID(); // 4326

$writer = new GeoJSONWriter();
echo $writer->write($point); // {"type":"Point","coordinates":[1,2]}

该库支持读取和写入FeatureFeatureCollection对象,以及自定义属性。

GeoJSON旨在仅支持WGS84,因此所有几何对象都使用SRID 4326导入。

减少坐标精度

在将几何对象以文本格式导出之前,您可能需要减少坐标的精度以保持输出文件的大小,同时保留足够的精度。您可以使用RoundCoordinatesProjector实现这一点。

use Brick\Geo\Point;
use Brick\Geo\Projector\RoundCoordinatesProjector;

$roundProjector = new RoundCoordinatesProjector(2);

$point = Point::xy(1.2345678, 2.3456789);
echo $point->asText(); // POINT (1.2345678 2.3456789)

$roundedPoint = $point->project($roundProjector);
echo $roundedPoint->asText(); // POINT (1.23 2.35)

Doctrine映射

您可以使用brick/geo-doctrine包在您的Doctrine实体中使用brick/geo类型。