【DM版本】:DM8
【问题描述】:
我数据库表point_info中的locations字段有如下7个点坐标,我想绘制一个矩形区域,然后判断矩形区域内包含的点,ST_MakeEnvelope 的参数我选用了7个点坐标的最大经度、纬度以及最小经度、纬度,坐标系为4490.但是计算的结果并不包含点4,点4位于矩形的左下角。
点1 POINT(118.755395 36.952633)
点2 POINT(118.79 36.871)
点3 POINT(118.89416 36.81115)
点4 POINT(118.753 36.785)
点5 POINT(118.776 36.787)
点6 POINT(118.779 36.79)
点7 POINT(118.759 36.795)
我的sql如下:
SELECT *, dmgeo2.ST_X(locations), dmgeo2.ST_Y(locations) FROM POINT_INFO
WHERE dmgeo2.ST_Intersects(dmgeo2.ST_GeomToGeog(locations),
dmgeo2.ST_GeomToGeog(dmgeo2.ST_MakeEnvelope(118.753,36.785,118.89416 , 36.952633,4490)))
问题排查如下:
首先我不从表里查,直接构建一个点,与矩形判断,返回结果为1.
sql如下:
SELECT dmgeo2.ST_Intersects(dmgeo2.ST_GeomToGeog(dmgeo2.ST_POINT(118.753,36.785,4490)),
dmgeo2.ST_GeomToGeog(dmgeo2.ST_MakeEnvelope(118.753,36.785,118.89416 , 36.952633,4490)))
我使用如下sql查询了构建的矩形的情况(情况1),以及自己构建点的情况(情况2),和表中locations 字段的情况(情况3),发现小数点后有精度问题,可能是因为这个问题导致的。
情况1 sql 及执行结果:
SELECT dmgeo2.ST_AsText(dmgeo2.ST_GeomToGeog(dmgeo2.ST_MakeEnvelope(118.753,36.785,118.89416 , 36.952633,4490)));
执行结果:
POLYGON((118.753 36.785000000000004,118.753 36.952633000000006,118.89416 36.952633000000006,118.89416 36.785000000000004,118.753 36.785000000000004))
情况2 sql 及执行结果:
SELECT dmgeo2.ST_AsText(dmgeo2.ST_GeomToGeog(dmgeo2.ST_POINT(118.753,36.785,4490)));
执行结果:
POINT(118.753 36.785000000000004)
情况3 sql 及执行结果
SELECT dmgeo2.ST_AsText(dmgeo2.ST_GeomToGeog(locations)) FROM POINT_INFO ;
执行结果:
POINT(118.753 36.785)
情况分析:
应该是因为精度问题导致的边界上的点导致的没有查询进去矩形左下角边界的点。
问题:为什么会出现这个精度问题,point_info中的数据我在执行插入的时候,使用的是如下形式
insert into point_info VALUES (dmgeo2.ST_GeomFromText('point (1 1)',4490));
是几何形式的点位信息。是不是因为这个原因导致的。因为后续计算过程,我都使用了 ST_GeomToGeog 去进行转换,还请答疑解惑,辛苦专家了。
情况补充
后续我使用 如下sql创建点位信息,也会出现精度一丢丢偏差
insert into point_info VALUES (dmgeo2.ST_POINT(118.753,36.785,4490));
想咨询下专家,如果存储的是经纬度点位信息,该使用 ST_GeomFromText还是使用 ST_POINT 去进行创建呢
我这边测试了一下,虽然ST_GEOMETRY和ST_POINT在创建表时都可以作为点的数据类型,但ST_GEOMETRY是ST_POINT的父类,范围要更大一些,二者的转换可能会有些许精度差异,所以要按照你业务的需求来选择,如果是以ST_POINT作为点的数据类型,dmgeo2.ST_MakeEnvelope创建多边形并和点做相交判断会更加准确,如果你是ST_GEOMETRY作为点的数据类型,就要像以下sql一样去创建多边形就行判断
SELECT *, dmgeo2.ST_X(geom), dmgeo2.ST_Y(geom) FROM GEOMS_GEO2
WHERE dmgeo2.ST_Intersects(dmgeo2.ST_GeomToGeog(geom),
dmgeo2.ST_GeomToGeog(
dmgeo2.st_geomfromtext('polygon ((118.753 36.785,118.753 36.952633,118.89416 36.952633,118.89416 36.785,118.753 36.785))', 4490)));