2014-01-15 3 views
1

При попытке разобраться с GEOMETRYCOLLECTION в PostGIS я нашел here, что похоже на преобразование GEOMETRYCOLLECTION в простое GEOMETRY, но оно работает только с внутренней функцией ST_Intersect.Передача имени функции в качестве аргумента

Как я довольно ленив, я подумал, что было бы неплохо сделать его более мощным, если функция будет выполнена как аргумент, но это не работает.

CREATE OR REPLACE FUNCTION ST_GeoCollConv_(geofunction, geometry, geometry) RETURNS boolean AS $$ 
     DECLARE 
       is1collection boolean; 
       is2collection boolean; 
     BEGIN 

       is1collection := GeometryType($1) = 'GEOMETRYCOLLECTION'; 
       is2collection := GeometryType($2) = 'GEOMETRYCOLLECTION'; 

       IF NOT is1collection AND NOT is2collection THEN 
         return PERFORM geofunction($1, $2); 
       END IF; 


       IF NOT is1collection THEN 
         FOR i IN 1..ST_NumGeometries($2) LOOP 
           IF PERFORM geofunction($1, ST_GeometryN($2, i)) THEN 
             RETURN true; 
           END IF; 
         END LOOP; 
       ELSIF NOT is2collection THEN 
         FOR i IN 1..ST_NumGeometries($1) LOOP 
           IF PERFORM geofunction(ST_GeometryN($1, i), $2) THEN 
             RETURN true; 
           END IF; 
         END LOOP; 
       ELSE 
         FOR i IN 1..ST_NumGeometries($1) LOOP 
           IF ST_GeoCollConv_(geofunction, $1, $2) THEN 
             RETURN true; 
           END IF; 
         END LOOP; 
       END IF; 

       RETURN false; 

     END; 
$$ LANGUAGE 'plpgsql'; 

Как я могу это достичь?

ответ

1

Функции не являются гражданами первого класса в postgres (я не могу думать о РСУБД, где они есть) и не могут быть переданы в качестве аргументов. Следующее самое ближайшее - перечислить все возможные функции (st_overlaps, st_intersects, st_within и т. Д.), Передать флаг, указывающий, к какой функции вы говорите, и включить это в свои операторы if, например. «if func = 'overlaps» и st_overlaps (geom1, geom2) else, если func =' внутри 'и st_within (geom1, geom2) ... ".

Геометрические коллекции могут быть немного расстроены. Вы вынуждены использовать их? Можете ли вы использовать мультиполигоны?

Также обратите внимание, что сама функция немного чрезмерна. Вы можете использовать st_dump для перечисления всех геометрий (работает, даже если у вас есть простая геометрия), затем присоедините результаты. Например:

create or replace function st_intersects_gc(geometry, geometry) 
returns boolean 
as 
$$ 
    select exists (
      select 1 
      from st_dump($1) a 
        join st_dump($2) b 
         on st_intersects(a.geom, b.geom) 
      limit 1 
      ) 
    ; 
$$ 
language sql 
immutable 
; 

Пример использования (там также должен быть пример, иллюстрирующий, что это работает должным образом для коллекции, как хорошо, но я не один на руках):

-- returns false 
select st_intersects_gc('POINT(0 0)'::geometry, 'LINESTRING (2 0, 0 2)'::geometry) 

-- returns true 
select st_intersects_gc('POINT(0 0)'::geometry, 'LINESTRING (0 0, 0 2)'::geometry) 

В вашей обуви, Я бы написал один из них для каждой функции, которую вы планируете использовать.

+0

Благодаря yieldsfalsehood, у меня больше успеха с вашим решением, чем с любым экспериментом, который я сделал до сих пор, особенно если я использую функцию ST_Overlaps. Я еще не знаю, как использовать мультиполигоны и буду исследовать в этом направлении. (недостаточно репутации для +1) – annoyed

+0

Рад, что я мог помочь, и удачи! – yieldsfalsehood

Смежные вопросы