使用mysql判断经纬度是否在多边形内

14

我已经创建了下面的表格

CREATE TABLE geom (g GEOMETRY);

我已经插入了许多行,如下所示:

INSERT INTO geom (g)
VALUES(PolygonFromText('POLYGON((
9.190586853 45.464518970,
9.190602686 45.463993916,
9.191572471 45.464001929,
9.191613325 45.463884676,
9.192136130 45.463880767,
9.192111509 45.464095594,
9.192427961 45.464117804,
9.192417811 45.464112862,
9.192509035 45.464225851,
9.192493139 45.464371079,
9.192448471 45.464439002,
9.192387444 45.464477861,
9.192051402 45.464483037,
9.192012814 45.464643592,
9.191640825 45.464647090,
9.191622331 45.464506215,
9.190586853 45.464518970))')
);

现在我想搜索所有数据并返回其中任何一个多边形包含我拥有的经纬度的条目。

如何使用mysql实现这一点?或者是否有人知道任何可以指导我的链接?

4个回答

17
MySQL自v5.1起仅支持对最小边界矩形(MBR)的操作。虽然有一个"Contains"函数可以完成您所需的操作,但它并没有完全实现,并会回退到使用MBRContains
来自相关手册页面

目前,MySQL根据规范尚未实现这些功能。已经实现的函数返回与相应的基于MBR的函数相同的结果。这包括以下列表中的函数,除了Distance()和Related()。

这些功能可能在将来的版本中得到实现,以完全支持空间分析,而不仅仅是基于MBR的支持。

你可以让MySQL基于MBR给出一个近似结果,然后进行后处理以执行更准确的测试。或者,切换到PostGIS!(更新于2012年5月 - 感谢Mike Toews)MySQL 5.6.1+提供了使用对象形状的函数而不是MBR。MySQL最初实现了这些函数,使它们使用对象边界矩形并返回与相应的基于MBR的函数相同的结果。从MySQL 5.6.1开始,可用具有精确对象形状的对应版本。这些版本带有ST_前缀。例如,Contains()使用对象边界矩形,而ST_Contains()使用对象形状。

2
好消息是,v5.6有一整套以ST_为前缀的函数,它们的实现与PostGIS类似。 - Mike T

6
如果您无法将数据库更改为已正确实现空间运算符的数据库,例如PostgreSQL的PostGIS扩展http://postgis.refractions.net/,则可以使用两部分方法解决此问题。
首先,让MySQL基于边界框(这是默认行为)使用其相交运算符(http://dev.mysql.com/doc/refman/5.1/en/functions-that-test-spatial-relationships-between-geometries.html#function_intersects)给出一个边界框预过滤结果。如果查询速度很慢,请确保您的几何字段上有索引。
然后,将您在查询中使用的原始几何形状转换为GIS几何库的几何对象,例如GEOS (http://trac.osgeo.org/geos/)(基于C ++,但也具有不同语言的绑定,如Python),Shapely (http://trac.gispython.org/lab/wiki/Shapely)OGR(或Java拓扑套件(JTS)http://www.vividsolutions.com/jts/jtshome.htm)。
使用适当的运算符(如withinintersects)测试从查询结果中返回的每个几何形状。任何这些库都会给您一个布尔值结果。
就我个人而言,我会查看OGR的示例,因为它有一个随时准备帮助的大社区。
哦对了,抱歉把链接放成那样...我想,由于我是“新手”,只能发布一个链接(?)

1

这篇帖子中提供的MySQL论坛上的函数对我来说完美地运行。

它不是很快,您必须确保参数“mp”与您正在使用的空间列具有相同的类型(我使用ogr2ogr将Ordnance Survey形状文件导入MySQL,因此必须将其从“MULTIPOLYGON”更改为“GEOMETRY”)


只是补充一下,我通过将原始的shape文件运行到http://mapshaper.com/test/demo.html中,将查询速度提高了一个数量级——感谢Douglas-Peucker... - user159895
@所有人,对于那些使用MySQL版本低于5.6的人,这应该会有所帮助。 - Ganesh RJ

0

我已经重写了之前由@danherd在帖子中给出的function,使其可以使用由多个多边形组成的真实多边形。 对于那些仍在使用旧版MySql的人来说,这应该会有所帮助。

这就是它:

DELIMITER //

CREATE FUNCTION GISWithin(pt POINT, mp MULTIPOLYGON) RETURNS INT(1) DETERMINISTIC

BEGIN

DECLARE str_big, str, xy LONGTEXT;
DECLARE x, y, p1x, p1y, p2x, p2y, m, xinters DECIMAL(16, 13) DEFAULT 0;
DECLARE counter INT DEFAULT 0;
DECLARE p, pb, pe, sb, se, ct DECIMAL(16, 0) DEFAULT 0;

SELECT MBRWithin(pt, mp) INTO p;
IF p != 1 OR ISNULL(p) THEN
return p;
END IF;

SELECT X(pt), Y(pt), ASTEXT(mp) INTO x, y, str_big;
SET str_big = REPLACE(str_big, 'MULTIPOLYGON(((','');
SET str_big = REPLACE(str_big, ')))', '');
SET str_big = REPLACE(str_big, ')),((', '|');
SET str_big = CONCAT(str_big, '|');

SET sb = 1;
SET se = LOCATE('|', str_big);
SET str = SUBSTRING(str_big, sb, se - sb);

WHILE se > 0 DO
SET ct = ct + 1;
SET str = SUBSTRING(str_big, sb, se - sb);

SET pb = 1;
SET pe = LOCATE(',', str);
SET xy = SUBSTRING(str, pb, pe - pb);
SET p = INSTR(xy, ' ');
SET p1x = SUBSTRING(xy, 1, p - 1);
SET p1y = SUBSTRING(xy, p + 1);
SET str = CONCAT(str, xy, ',');

WHILE pe > 0 DO
SET xy = SUBSTRING(str, pb, pe - pb);
SET p = INSTR(xy, ' ');
SET p2x = SUBSTRING(xy, 1, p - 1);
SET p2y = SUBSTRING(xy, p + 1);
IF p1y < p2y THEN SET m = p1y; ELSE SET m = p2y; END IF;
IF y > m THEN
IF p1y > p2y THEN SET m = p1y; ELSE SET m = p2y; END IF;
IF y <= m THEN
IF p1x > p2x THEN SET m = p1x; ELSE SET m = p2x; END IF;
IF x <= m THEN
IF p1y != p2y THEN
SET xinters = (y - p1y) * (p2x - p1x) / (p2y - p1y) + p1x;
END IF;
IF p1x = p2x OR x <= xinters THEN
SET counter = counter + 1;
END IF;
END IF;
END IF;
END IF;
SET p1x = p2x;
SET p1y = p2y;
SET pb = pe + 1;
SET pe = LOCATE(',', str, pb);
END WHILE; 

SET sb = se + 1;
SET se = LOCATE('|', str_big, sb);

END WHILE;

RETURN counter % 2;

END

DELIMITER ; 

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接