我们本次实践的主要内容

  • 地理围栏数据构建
  • mysql 如何使用geo相关字段类型
  • 围栏算法计算

地理围栏数据构建

使用DDL创建一个数据库模式:

CREATE TABLE `geo_1` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `fence_point` point NOT NULL COMMENT '中心点',
  `fence_polygon` polygon NOT NULL COMMENT '单个围栏',
  `fence_multipolygon` multipolygon NOT NULL COMMENT '多围栏',
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4

使用原生sql语句插入几条数据

INSERT INTO `geo_1`(
    `id`,
    `fence_point`,
    `fence_polygon`,
    `fence_multipolygon`
)
VALUES(
    NULL,
    GEOMFROMTEXT('POINT(117.134516 36.672215)'),
    GEOMFROMTEXT(
        'POLYGON((117.147711 36.692958,117.152174 36.664804,117.120588 36.659434,117.116297 36.678848,117.147711 36.692958))'
    ),
    GEOMFROMTEXT(
        'MULTIPOLYGON(((117.143528 36.678686,117.144215 36.676758,117.142927 36.67669,117.142412 36.677997,117.143528 36.678686)),((117.144837 36.675829,117.144794 36.674487,117.143743 36.674659,117.14385 36.675881,117.144837 36.675829)),((117.127574 36.670235,117.124227 36.668858,117.124785 36.666448,117.13075 36.667412,117.127574 36.670235)))'
    )
);

特别要注意的几点:

  • POINT类型是单个点,构建只需要一个POINT类型数据即可
  • POLYGON类型或者MULTIPOLYGON中的数据必须是首位相连,也就是第一组数据和最后一组数据是相同的,以构成一个闭合的多边形。

mysql 如何使用geo相关字段类型

这里推荐使用 grimzy/laravel-mysql-spatial 来处理地理数据,具体使用方式可参考官方文档。

composer.json 

"grimzy/laravel-mysql-spatial": "^2.2",

在模型中使用Trait方式引入

use GrimzyLaravelMysqlSpatialEloquentSpatialTrait;

模型类中使用示例

class MyMap extends Model
{
    use SpatialTrait;
    protected $spatialFields = [
        'fence_point',
        'fence_polygon',
        'fence_multipolygon',
    ];
}

这样我们对数据字段的读写都会经过处理,转换成我们书西的colllection对象。极大方便数据的处理方式。举几个例子:
需要引入的类型

use GrimzyLaravelMysqlSpatialTypesMultiPolygon;
use GrimzyLaravelMysqlSpatialTypesPoint;
use GrimzyLaravelMysqlSpatialTypesPolygon;
use GrimzyLaravelMysqlSpatialTypesLineString;

保存中心点数据

$mapInfo = Map::find(1);
$mapInfo->fence_point = new Point(117.1234556, 36.123456);
$mapInfo->save();

保存多边形数据

$coorArr = [[117.147711 36.692958],[117.152174 36.664804],[117.120588 36.659434],[117.116297 36.678848],[117.147711 36.692958]];
$mapInfo = Map::find(1);
$linePath = [];
foreach ($coorArr as $point){
    array_push($linePath, new Point($point[1], $point[0]));
}
array_push($linePath, array_first($linePath));
$lineStringPath = new LineString($linePath);
$mapInfo->fence_polygon= new Polygon([$lineStringPath]);
$mapInfo->save();

配合百度地图api我们可以实现如下效果,在线划围栏、围栏展示等可视化操作

web地理围栏.png

围栏算法计算

配合我之前文章里面提到的围栏算法,可以实现左边点围栏是否在指定区域应用。

http://www.evenvi.com/index.php/archives/45/ [ 围栏算法]

Tags: 围栏算法, mysql, 地理围栏, polygon

Related Posts:

1 Comment »

  1. 猫猫侠

    拜读猫神大作~~~

Leave a Comment