扩展PiP算法的MySQL实现?

时间:2013-01-16 17:40:37

标签: php mysql raycasting point-in-polygon

我需要在多边形 MySQL查询中创建一个点。

我已经找到了这两个很好的解决方案:

http://forums.mysql.com/read.php?23,286574,286574

MySQL implementation of ray-casting Algorithm?

但是这些函数只能检查一个点是否在poly中。我有一个查询,其中PiP部分应该只是查询的一部分,并检查多边形内的x点。

这样的事情:

$points = list/array/whatever of points in language of favour

SELECT d.name
FROM data AS d
WHERE d.name LIKE %red%
// just bla bla

// how to do this ?
AND $points INSIDE d.polygon
AND myWithin( $points, d.polygo ) // or

更新

我尝试使用 MBR 这样的功能:

SET @g1 = GeomFromText('Polygon((13.43971 52.55757,13.41293 52.49825,13.53378 52.49574, 13.43971 52.55757))');
SET @g2 = GeomFromText('Point(13.497834 52.540489)');
SELECT MBRContains(@g1,@g2);

G2不应该在G1内,但 MBR 表示它是。

3 个答案:

答案 0 :(得分:2)

所以你的问题是如何将相同的函数应用于多个值,并且只有在对函数的所有调用都返回true时才返回true。这不是很难。

如果是我,我会将点(以及可选的多边形 - 未在示例中显示)放入表中,然后编写MySQL函数以将光线投射方法应用于每个点 - 如果任何一个交互返回false则返回false,然后返回true。在下面的示例中,我假设多边形是从您的多边形获取并由主键标识,而点由外键标识(使用zarun函数mywithin):

 DECLARE FUNCTION allwithin(
     pointSetKey INT) 
 RETURNS INT(1)  
 BEGIN 

 DECLARE current POINT;

 DECLARE check CURSOR FOR SELECT p.point
     FROM yourpoints p
     WHERE p.set=pointSetKey;

 OPEN check;

 nextPoint: LOOP

    FETCH check INTO current;

    IF (0=mywithin(current, yourpolygon)) THEN
         RETURN 0;
    END IF;

 END LOOP;

 RETURN 1;

 END;

 INSERT INTO yourpoints (pointsetkey, point)
 VALUES (
      128,
      GeomFromText('Point(13.497834 52.540489)')
 ),
 (
      128,
      GeomFromText('Point(13.6 52.1)')
 ),
 ....
 ;

 SELECT allwithin(128
 , GeomFromText('Polygon((13.43971 52.55757,13.41293 52.49825,13.53378 52.49574, 13.43971 52.55757))')
 );

...或

 SELECT COUNT(*)
 FROM yourpoints p
 WHERE p.set=128
 AND mywithin(p.point
      , GeomFromText('Polygon((13.43971 52.55757,13.41293 52.49825,13.53378 52.49574, 13.43971 52.55757))')
      );

会给你不在多边形内部的点数(当你只想知道这些点是否在外面时,这是相当昂贵的。)

答案 1 :(得分:1)

如果你这样做

SET @g1 = GEOMFROMTEXT('Polygon((13.43971 52.55757,13.41293 52.49825,13.53378 52.49574, 13.43971 52.55757))');
SET @g2 = GEOMFROMTEXT('Point(13.497834 52.540489)');
SELECT  ST_Contains(@g1,@g2);

而不是MBRContains?据我了解MySQL空间文档。 MBR *函数是最小边界矩形,因此它显示您的点是否在几何体上的最小矩形内,但不在几何体本身内(如果它是不规则多边形并且该点在MBR内部而不在多边形)

答案 2 :(得分:0)

在我看来如下:你需要测试多个点是否在多边形中。如果一切都是,那么他们的凸壳也是如此。弄清楚它们的凸包(基本上:按时钟顺序或逆时针顺序排列),这会创建一个多边形。现在测试新多边形是否在d.polygon内。