2013-06-15 4 views
0

У меня есть таблица с точками. Я хотел бы создать многоугольник на основе этих точек, а затем вернуть только те точки, которые находятся по периметру (исключая точки, находящиеся внутри многоугольника). Есть ли простой способ сделать это на уровне базы данных с помощью SDO GEOMETRY? Я нахожу sth как GrahamScan, но я не могу найти что-либо подобное для Spatialмногоугольник на основе точек периметра - оракул пространственный

+0

Как вы определяете периметр неупорядоченного множества точек в первую очередь? Вы ищете выпуклый корпус (google, если вы не знаете, что это такое) из набора точек? – Spacedman

ответ

2

Я не могу придумать ни одного easy Ответьте на встроенные пакеты, поставляемые Oracle. Возможно, вам придется подумать о написании довольно ужасного кода, чтобы сделать это, если вы хотите решить проблему в Oracle.

сырное решение может быть разбить это на несколько шагов:

  1. Грубой силы всех возможных линий между каждым набором из двух точек (выберите декартовы произведение точек, построить их в линию):
  2. Найдите все линии, где нет пересечения с любой другой линией (внешний периметр) и получите значения точек.
  3. Соедините значения точек с исходной таблицей, чтобы получить любые данные (при необходимости).

Это, скорее всего, не будет работать или хорошо масштабироваться, но оно должно работать, если ваш набор данных не очень большой.

Вот быстрые иллюстрации (непроверенный SQL) ...

Входы:

SELECT sdo_geometry(2001, NULL, sdo_point_type(tbl.x, tbl.y, NULL), NULL, NULL) 
FROM my_table tbl 

Inputs to algorithm

декартово произведение координат преобразуется в строки:

WITH point_cartesian AS (
    SELECT 
    tbl.x x1 
    , tbl.y y1 
    , tbl2.x x2 
    , tbl2.y y2 
    FROM my_table tbl 
    CROSS JOIN my_table tbl2 
    WHERE tbl.x != tbl2.x 
    OR tbl.y != tbl2.y 
) 
SELECT sdo_geometry(
    2002 
, NULL 
, NULL 
, sdo_elem_info_array(1, 2, 1) 
, sdo_ordinate_array(x1, y1, x2, y2) 
) 
FROM point_cartesian 

Cartesian product of coordinates converted to lines

Определить нужные строки:

WITH point_cartesian AS (
    SELECT 
    tbl.x x1 
    , tbl.y y1 
    , tbl2.x x2 
    , tbl2.y y2 
    FROM my_table tbl 
    CROSS JOIN my_table tbl2 
    WHERE tbl.x != tbl2.x 
    OR tbl.y != tbl2.y 
) 
, lines AS (
    SELECT sdo_geometry(
    2002 
    , NULL 
    , NULL 
    , sdo_elem_info_array(1, 2, 1) 
    , sdo_ordinate_array(x1, y1, x2, y2) 
) geom 
    , ROWNUM line_id 
    FROM point_cartesian 
) 
SELECT * 
FROM lines l1 
WHERE NOT EXISTS (
    SELECT 1 
    FROM lines l2 
    WHERE l2.line_id != l1.line_id 
    AND sdo_geom.sdo_intersect (l1.geom, l2.geom, 0.05) IS NOT NULL 
) 

Identify lines

Обратите внимание: SQL не тестировался, но, надеюсь, вы поняли идею.

+0

Brillant ответ –

2

Если данные действительно так описаны в первом ответе, то самым простым и быстрым методом является получение выпуклого корпуса вокруг вашего набора точек. Предполагая, что ваш вклад таблицы my_table, который содержит две колонки, X и Y, которые представляют долготы и широты (отсюда SRID из 4326):

select sdo_aggr_convexhull (
     sdoaggrtype (
      sdo_geometry(2001, 4326, sdo_point_type(x, y, NULL), NULL, NULL), 
      0.5 
     ) 
     ) 
from my_table; 

В результате получается многоугольник строится с помощью точки периметра.

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

  • Нет связанных вопросов^_^