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

4 回答 4

17

从 v5.1 开始的 MySQL 仅支持对最小边界矩形 (MBR)的操作。虽然有一个“包含”功能可以满足您的需要,但它没有完全实现,而是回退到使用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() 使用对象形状。

于 2009-07-03T09:07:03.317 回答
6

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

首先让 MySQL 使用它们的 intersects 运算符 ( ) 为您提供基于边界框的边界框预过滤结果(这是默认情况下所做的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 的样本,因为它有一个随时准备提供帮助的大型社区。

哦,是的,很抱歉放了这样的链接......我想因为我是“新人”,所以我只能发布一个链接(?)

于 2009-07-05T18:12:58.867 回答
1

MySQL 论坛上这篇文章中给出的功能对我来说非常适合。

它不是很快,您必须确保参数“mp”与您使用的空间列类型相同(我使用 ogr2ogr 将军械测量 shapefile 导入 MySQL,因此必须将其从“MULTIPOLYGON”更改为“GEOMETRY ')

于 2011-01-24T17:17:19.513 回答
0

我重写了@danherd 在上一篇文章中给出的函数,因此它可以处理由多个多边形组成的真实多面体。对于那些仍在使用旧版 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 ; 
于 2013-11-14T12:11:24.007 回答