Расширить реализацию MySQL алгоритма PiP?
Мне нужно сделать точку в запросе MySQL многоугольника.
Я уже нашел эти два больших решения:
http://forums.mysql.com/read.php?23,286574,286574
MySQL-реализация алгоритма лучевого кастинга?
Но эти функции могут только проверять, находится ли одна точка внутри поля. У меня есть запрос, где часть 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
UPDATE
Я попробовал его с 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 говорит, что это.
Ответы
Ответ 1
Итак, действительно, ваш вопрос заключается в том, как вы применяете одну и ту же функцию к нескольким значениям и возвращаете true, только если весь вызов функции возвращает true. Это не очень сложно.
Если бы это был я, я бы поместил точки (и, необязательно, многоугольники, не показанные в примере), в таблицу, а затем напишет функцию MySQL, чтобы применить метод raycasting к каждой точке - возврату false, если какое-либо одно вмешательство возвращает false, тогда return true. В приведенном ниже примере я предположил, что многоугольник извлекается из вашегополигона и идентифицируется по первичному ключу, тогда как точки индексируются внешним ключом (используя функцию mywithin by zarun):
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))')
);
Дает вам количество точек, не находящихся внутри многоугольника (что довольно дорого, когда вы только хотите узнать, не находится ли NONE из точек).
Ответ 2
что делать, если вы делаете
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, а не в многоугольник)
Ответ 3
Мне кажется, что вам нужно проверить, находятся ли несколько точек в многоугольнике. Если все есть, то и их выпуклая оболочка. Выясните их выпуклую оболочку (в основном: упорядочивайте их по часовой стрелке или против часовой стрелки), это создает многоугольник. Теперь проверьте, находится ли новый многоугольник внутри d.polygon.