一、PostGis函数使用异常Case:
报错内容:
parse error - invalid geometry (lwgeom_pg.c:96)
问题复现:
select ST_MPointFromText(‘MULTIPOINT(’||replace(replace(feeds,’:’, ’ ‘),’;’,’,’)||’)’) from test limit 2; – 正常
select ST_MPointFromText(‘MULTIPOINT(’||replace(replace(feeds,’:’, ’ ‘),’;’,’,’)||’)’) from test limit 3; – 报错
ERROR: parse error - invalid geometry (lwgeom_pg.c:96) (seg16 slice1 … pid=15695) (cdbdisp.c:1326) --这是GPDB报的错。
原因:
直接查询test.feeds,发现里面有一些空数据,这些空的数据,导致了postgis在转换时报错。
create table test(feeds text);
insert into test values (’’);
insert into test values (‘1:1;100:2’);
test=> select ST_MPointFromText(‘MULTIPOINT(’||replace(replace(feeds,’:’, ’ ‘),’;’,’,’)||’)’) from test;
ERROR: parse error - invalid geometry
HINT: “MULTIPOINT()” <-- parse error at position 13 within geometry
CONTEXT: SQL function “st_mpointfromtext” statement 1
解决方法:
将’'空字符串,转换为0坐标,或者过滤这些数据即可。
select ST_MPointFromText(‘MULTIPOINT(’||replace(replace(feeds,’:’, ’ ‘),’;’,’,’)||’)’) from test where feeds<>’’;
或者
select case when feeds=’’ then ST_MPointFromText(‘MULTIPOINT(0 0)’) else ST_MPointFromText(‘MULTIPOINT(’||replace(replace(feeds,’:’, ’ ‘),’;’,’,’)||’)’) end from test;
二、用Postgis转换坐标系
前台Openlayers转换坐标系,后台Postgis转换:
SELECT ST_AsText(ST_Transform(st_geometryfromtext(‘POINT(120.8 20.5)’,4326),900913));
–将point转换为geometry类型,并将4326坐标系转换为900913坐标系
三、PostGIS的Geometry数据类型
Geometry是PostGIS的概念,目前支持的几何体类型格式如下:
geometry的两种形式:
1、WKT(Well Known Text)
–使用如下SQL语句浏览:
select AsText(pt) from test1;
POINT(1 1) --点
MULTIPOINT(1 1, 3 4, -1 3) --线
LINESTRING(1 1, 2 2, 3 4) --面
POLYGON((0 0, 0 1, 1 1, 1 0, 0 0)) --多边形
MULTIPOLYGON((0 0, 0 1, 1 1, 1 0, 0 0), (5 5, 5 6, 6 6, 6 5, 5 5)) --多面
MULTILINESTRING((1 1, 2 2, 3 4),(2 2, 3 3, 4 5)) --多线
2、Canonical Form形式,增强的十六进制编码
–使用如下SQL语句浏览:
select pt from test1;
3、另外EWKT、EWKB和Canonical格式
EWKT和EWKB相比OGC WKT和WKB格式主要的扩展有3DZ、3DM、4D坐标和内嵌空间参考支持。
以下以EWKT语句定义了一些几何对象:
POINT(0 0 0) --3D点
SRID=32632;POINT(0 0) --内嵌空间参考的点
POINTM(0 0 0) --带M值的点
POINT(0 0 0 0) --带M值的3D点
SRID=4326;MULTIPOINTM(0 0 0,1 2 1) --内嵌空间参考的带M值的多点
–使用EWKT格式插入一个点到表中:
INSERT INTO table(SHAPE,NAME) VALUES (GeomFromEWKT(‘SRID=4326;POINTM(116.39 39.9 10)’),‘北京’)
PostGis 3D空间语法以及函数应用:
在执行几何类型的sql语句的时候一定要注意类型的转换、表空间列的属性或者使用适当的类型
–插入:
insert into SSS(geometryType) values(ST_GeomFromText(‘POINTZ(116.39 21 39.9)’, 4326));
–修改:
UPDATE eee SET geometryType = ST_GeomFromText(‘POINTM(116.39 21 39.9)’,4326)
–新增:
CREATE TABLE weq (id serial PRIMARY KEY, details VARCHAR(10000), template VARCHAR(255), create_time VARCHAR(255), modeUrl VARCHAR(255), geoJson VARCHAR(255), geometryType geometry(POINTM,4326))
–ST_DWithin将两个使用同样的坐标投影和SRID的几何参数作为输入,距离在范围内返回 true,否则false
sde.st_dwithin (st_geometry geometry1, st_geometry geometry2, double_precision distance);
SELECT
sde.st_distance(pt.geom, poly.geom) distance_meters,
sde.st_dwithin(pt.geom, poly.geom, 300) DWithin
FROM pt, poly;
–A是否包含B,包含返回t,不包含返回f
SELECT ST_Contains(st_astext(geometrytype),‘POINTZ(151 50 30)’) FROM videodata
–找到 POINT(1000 1000) 100米范围内的查询如下:
SELECT * FROM geotable WHERE ST_DWithin(geocolumn, ‘POINT(1000 1000)’, 100.0);
–查询点在面内,包含返回t,不包含返回f
SELECT ST_Contains(st_astext(ST_MakePolygon(ST_GeomFromText('LINESTRINGZ (0 0 1,0 2 1,2 2 1,2 0 1,0 0 1) '))),‘POINTZ(1 1 5)’)
–或者
SELECT ST_Contains( ST_MakePolygon(ST_GeomFromText(ST_ASTEXT(geometrytype))),st_pointz(0,0,0)) FROM videodata
–点是否在面内,包含返回t,不包含返回f
sql语句如下:
select * from tb_data_region_polygon0 where ST_Within(st_geomfromtext(‘point(114.186684 30.512029)’,4326),geom);
select * from tb_data_region_polygon0 where ST_DWithin(st_geomfromtext(‘point(114.186684 30.512029)’,4326),geom,0);
select * from tb_data_region_polygon0 where ST_Covers(geom,st_geomfromtext(‘point(114.186684 30.512029)’,4326));
PostGis 中 Geomery 使用 ST_distance 计算出来的单位是弧度,不是米,
–将点变成投影坐标,转换之后以米为单位
SELECT ST_Length(ST_Transform(geom, 4326)) FROM ditie
–查询ditie表点到每个线的距离,条件是在80000米之内的点
select
(ST_distance(geom::geography,ST_GeomFromText(‘POINT(121 32)’, 4326)::geography))
from ditie
where ST_dwithin(geom::geography,ST_GeomFromText(‘POINT(121 32)’, 4326)::geography, 80000)
–下面这种办法查出来的结果也是以米为单位的两点间的距离
SELECT ST_Distance(
ST_Transform(ST_GeomFromText(‘POINT(-87.734087560562 43.770129071141)’,4326),26986),
ST_Transform(ST_GeomFromText(‘POINT(-87.747382933006 43.759234252055)’, 4326),26986));
–项目中,直接把坐标存成geography格式,避免数据转换
ST_GeographyFromText(‘SRID=4326;POINT(-110 30)’)
–改变表的空间字段srid为4326
update table_name set the_geom = st_geomfromtext(ST_AsText(the_geom),4326)