php移动网站开发公众号营销
postgis
postgis是pg数据库的一个插件,除原数据类型外(int varchar)、新增了空间数据类型(geography和geometry)。比如我们新建一张道路表road(字段有名称varchar、建设时间timestamp、地理位置geometry),可以将道路名字、建设时间存进去,同时把道路的位置坐标和使用的坐标系存到一个geometry类型字段。再建一张建筑表存建筑位置,这样就能利用postgis提供的函数分析马路附近有哪些建筑这类问题。
geometry是几何类型,基础是平面,平面上两点之间的最短路径是直线。几何函数(面积、距离、长度、交点等)是使用线性向量和笛卡尔平面计算的。这简化了实施并运行得更快,但对于地球球面以上的数据是不准确的。它可以存地理坐标系数据,只是计算大范围计算精度有局限,更适合选择合适的投影坐标系存平面坐标。
geography地理数据类型基于球面模型。球体上两点之间的最短路径是一个大圆弧。地理上的函数(面积、距离、长度、交点等)是使用球体上的弧计算的。通过考虑世界的球体形状,函数可提供更准确的结果。
人员设备demo表
用4326二维地理坐标系(只有经纬度),制作一份地图,导入pg,表结构如下
CREATE TABLE public.demo_building (
id int8 NOT NULL,
geom public.geometry(multipolygonzm, 4326) NULL,
"name" varchar(10) NULL,
CONSTRAINT demo_building_pkey PRIMARY KEY (id)
);
CREATE TABLE public.demo_person (
id int8 NOT NULL,
geom public.geometry(pointzm, 4326) NULL,
"name" varchar(10) NULL,
CONSTRAINT demo_person_pkey PRIMARY KEY (id)
);
查询设备最近的人员
select
person ."name" ,
ST_Distance(building.geom, person.geom)
from
demo_building building,
demo_person person
where
building."name" = '设备1'
ORDER BY ST_Distance(building.geom, person.geom) asc
-- 基于索引的KNN查询
select
person ."name"
from
demo_person person
order by person.geom <-> (select building.geom from demo_building building where building."name" = '设备1')
qgis使用“要素之间最短线”,源图层为building,目标图层为person,可绘制最短线,打开属性表可看距离
判断人员是否在围栏内
--距离原点指定0.5范围内的人员,圆形围栏
select
person.geom ,
person ."name" ,
person .geom <-> 'SRID=4326;POINT Z(-0.764265422077925 -0.0342836850649348 0)'::geometry as dist
from
demo_person person
where person .geom <-> 'SRID=4326;POINT Z(-0.764265422077925 -0.0342836850649348 0)'::geometry <= 0.5
--在指定多边形范围内的人,在矿工作区内的人,多边形围栏
select
*
from
demo_person person
where
ST_Contains((select building .geom from demo_building building where building ."name" = '矿工作区')::geometry,person.geom);
--在指定多边形边上的人,在高坡工作区边上的人,围栏边上
select
*
from
demo_person person
where
ST_Intersects((select building .geom from demo_building building where building ."name" = '高坡工作区')::geometry,person.geom);
聚合区域人员数量
--查询指定范围内的人员,在矿工作区内的人员数量
select count(1) from demo_person person where ST_Within(person.geom,(select building .geom from demo_building building where building ."name" = '矿工作区')::geometry);