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)での操作のみをサポートします。必要なことを実行する「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()はオブジェクトの形状を使用します。

于 2009-07-03T09:07:03.317 に答える
6

dbs を PostgreSQL の PostGIS 拡張機能のように空間演算子が正しく実装されたものに変更できない場合はhttp://postgis.refractions.net/、2 段階のアプローチを使用してこの問題を解決できます。

まず、交差演算子 ( ) を使用して、MySQL がバウンディング ボックスに基づいてバウンディング ボックスの事前フィルタリング結果を提供するようにします (これがデフォルトで実行されますhttp://dev.mysql.com/doc/refman/5.1/en/functions-that-test-spatial-relationships-between-geometries.html#function_intersects)。クエリが遅い場合は、最初にジオメトリ フィールドにインデックスがあることを確認してください。

次に、クエリで使用した元のジオメトリを、GEOS ( http://trac.osgeo.org/geos/) (C++ ベースですが、Python などのさまざまな言語のバインディングもあります)、Shapely ( http://trac.gispython.org/lab/wiki/Shapely)OGR (または Java Topology Suite ( JTS) http://www.vividsolutions.com/jts/jtshome.htm)。

withinintersectsなどの適切な演算子を使用して、クエリ結果から返された各ジオメトリをテストします。これらのライブラリはいずれも、ブール値の結果を返します。

個人的には、OGR には大きなコミュニティが用意されているので、OGR のサンプルを見てみたいと思います。

あ、そうそう、リンク貼っててすいません…「新人」なのでリンクは1つしか貼れません(?)

于 2009-07-05T18:12:58.867 に答える
1

MySQL フォーラムのこの投稿に記載されている機能は、私にとっては完璧に機能します。

それほど迅速ではなく、パラメーター「mp」が使用している空間列と同じタイプであることを確認する必要があります (私は ogr2ogr を使用して Ordnance Survey シェープファイルを 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 に答える