使用mysql查看lat / long是否落在多边形内

时间:2009-07-03 08:34:30

标签: mysql gis polygon point

我创建了下表

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 个答案:

答案 0 :(得分:17)

从v5.1开始的MySQL仅支持minimum bounding rectangles (MBR)上的操作。虽然有一个“Contains”功能可以满足您的需求,但它没有完全实现,而是回归到使用MBRContains

来自relevant manual page

  

目前,MySQL没有实现   这些功能按照   规格。那些是   实现返回相同的结果   相应的基于MBR的功能。   这包括的功能   以下列表除了距离()   和相关()。

     

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

你可以做的是让MySQL给你一个基于MBR的近似结果,然后对它进行后处理以执行更准确的测试。或者,切换到PostGIS

(2012年5月更新 - 感谢Mike Toews)

MySQL 5.6.1+提供functions which use object shapes而不是MBR

  

MySQL最初实现了这些功能,以便他们使用   对象边界矩形并返回与结果相同的结果   相应的基于MBR的功能。截至MySQL 5.6.1,对应   可以使用精确对象形状的版本。这些版本   以ST_前缀命名。例如,Contains()使用object   边界矩形,而ST_Contains()使用对象形状。

答案 1 :(得分:6)

如果您无法将dbs更改为像PostgreSQL的PostGIS扩展http://postgis.refractions.net/那样正确实现空间运算符的dbs,则可以使用两部分方法解决此问题。

首先让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({ {1}},OGR(或Java拓扑套件(JTS)http://trac.gispython.org/lab/wiki/Shapely))。

使用适当的运算符测试从查询结果中获取的每个几何,例如 。任何这些库都会给你一个布尔结果。

就个人而言,我会查看OGR的样本,因为它有一个可以提供帮助的大社区。

哦,是的,抱歉这样的链接...我猜我是“新的”我只能发一个链接(?)

答案 2 :(得分:1)

MySQL论坛上this post中给出的功能非常适合我。

它不是很快,你必须确保参数'mp'与你正在使用的空间列的类型相同(我使用ogr2​​ogr将Ordnance Survey shapefile导入MySQL,所以不得不从'MULTIPOLYGON'更改它'几何')

答案 3 :(得分: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 ;