PHP 地理坐标库mjaschen/phpgeo的介绍(距离和电子围栏)

浏览量:401

简介

mjaschen/phpgeo是一个小型PHP库,提供地理坐标(包括对不同椭球体的支持)、多折线(GPS轨迹)、多边形、边界等抽象。Phpgeo允许你用这些抽象来执行不同的计算,比如距离,轨道长度等。本章我们主要介绍它对计算距离和电子围栏的使用。

版本要求

根据其官网使用说明:
phpgeo requires at least PHP 7.3. phpgeo fully supports PHP 8.
The 3.x releases require PHP >= 7.2 but don’t get feature updates any longer. Bugfixes will be backported.
The 2.x releases require PHP >= 7.0 but don’t get feature updates any longer. Bugfixes won’t be backported.
The 1.x release line has support for PHP >= 5.4. Bugfixes won’t be backported
其他的PHP版本,请参考packagist这里的版本对照,找到合适的版本

安装

composer require mjaschen/phpgeo

使用

在介绍使用之前,需要说明一下,phpgeo默认使用wGS-84坐标系(如果有不了解坐标系的请自行百度了解),也就是国际坐标系,通常情况下我们使用的设备通过GPS获取的坐标使用的就是这个坐标系,但在地图上获取的经纬度就不一定是这个坐标系,尤其是国内的地图,所以在国内使用地图上获取的经纬度计算时需要转换一下。下面例子都将默认使用wGS-84坐标系做演示。官网的原文是这样说的:phpgeo supports arbitrary ellipsoids. WGS-84 is used as default when no other ellipsoid is given. For day-to-day calculations it’s not needed to care about ellipsoids in the most cases

距离计算

关于距离计算其实可以通过两种方法去计算,第一种是通过两点生成一条线,然后计算这条线的长度,另一种是直接计算两点的距离

第一种通过生成一条线计算长度

<?php

use Location\Coordinate;
use Location\Distance\Haversine;
use Location\Line;

$line = new Line(
    new Coordinate(52.5, 13.5),
    new Coordinate(52.6, 13.4)
);
//这里计算出的长度单位是米
$length = $line->getLength(new Haversine());

print_r( "这条线的长度为".$length."米")

//当然,我们还可以计算出来这条线的其他信息
//例如 中间点

$midpoint = $line->getMidpoint();

printf(
            '这条线的中间点的纬度是: %.3f ;经度是: %.3f .',
           $midpoint->getLat(),
           $midpoint->getLng(),
        );

第二种直接计算两点的距离

直接使用计算器对象:

<?php

use Location\Coordinate;
use Location\Distance\Vincenty;

$coordinate1 = new Coordinate(19.820664, -155.468066);
$coordinate2 = new Coordinate(20.709722, -156.253333);

$calculator = new Vincenty();

echo $calculator->getDistance($coordinate1, $coordinate2);

或者通过注入计算器实例来调用 Coordinate 实例的 getDistance() 方法

<?php

use Location\Coordinate;
use Location\Distance\Vincenty;

$coordinate1 = new Coordinate(19.820664, -155.468066);
$coordinate2 = new Coordinate(20.709722, -156.253333);

echo $coordinate1->getDistance($coordinate2, new Vincenty());

电子围栏

我们这里说的电子围栏其实是指地图上的电子围栏,也就是在地图上画出围栏,然后根据自己的业务计算目标和这个围栏的相对关系

Phpgeo有一个多边形实现,可以用来确定一个几何图形(点,线,polyline,多边形)是否包含在其中。一个多边形至少由三个点组成。

<?php

use Location\Coordinate;
use Location\Polygon;

$geofence = new Polygon();

$geofence->addPoint(new Coordinate(-12.085870,-77.016261));
$geofence->addPoint(new Coordinate(-12.086373,-77.033813));
$geofence->addPoint(new Coordinate(-12.102823,-77.030938));
$geofence->addPoint(new Coordinate(-12.098669,-77.006476));

$outsidePoint = new Coordinate(-12.075452, -76.985079);
$insidePoint = new Coordinate(-12.092542, -77.021540);

echo $geofence->contains($outsidePoint)
    ? 'Point 1 is located inside the polygon' . PHP_EOL
    : 'Point 1 is located outside the polygon' . PHP_EOL;

echo $geofence->contains($insidePoint)
    ? 'Point 2 is located inside the polygon' . PHP_EOL
    : 'Point 2 is located outside the polygon' . PHP_EOL;

上面的代码输出:

Point 1 is located outside the polygon
Point 2 is located inside the polygon

通过上面的代码我们可以计算出目标是否在围栏中,而应用到实际业务场景中,我们通常是在目标进入围栏或者移出围栏时触发下一步业务,这就要结合数据库,存储目标每次位置发生变化后相对围栏的内外关系,然后这次又和上次的内外关系做比对,确定目标和围栏的相对关系是否又变化,从而判断出目标是进入围栏还是移出围栏,再根据判断结果进行下一步业务操作

结语

mjaschen/phpgeo 是一个很好的PHP库,并且从目前看,作者维护也比较好。上面只是简单介绍了它的两个功能,还有更多的功能感兴趣的同学可以自行去它的文档上学习。在实际项目中对于空间的计算,它是一个很好的选择,但是,它并不是最好的选择,如果你对PostgreSQL有了解,建议使用它结合PostGIS,在空间计算上,PostGIS在性能和使用领域有更广阔的用途。

感兴趣的小伙伴请点赞+评论,就下期继续分享关于空间计算的进阶篇:PostGIS 距离计算建议

留下评论