Пространственная геометрия Oracle покрыта наиболее

У меня есть таблица, которая содержит несколько геометрий. Я пытаюсь извлечь тот, который больше всего покрыт другой геометрией.

Это лучше всего объяснить с помощью картинок и кода.

В настоящее время я делаю этот простой пространственный запрос, чтобы получить любые строки, которые пространственно взаимодействуют с переданными в WKT Geometry

SELECT ID, NAME FROM MY_TABLE WHERE 
sdo_anyinteract(geom, 
sdo_geometry('POLYGON((400969 95600,402385 95957,402446 95579,400905 95353,400969 95600))',27700)) = 'TRUE';

Прекрасно работает, возвращает кучу строк, которые каким-либо образом взаимодействуют с моим переданным в геометрии.

Что я предпочитаю, тем не менее, чтобы найти, какой из них больше всего покрыт моим пройденным в геометрии. Посмотрите на это изображение.

Пример выбора полигона

Цветные блоки представляют собой MY_TABLE. Черный многоугольник сверху представляет мой пройденный в геометрии, с которой я ищу. Результат, который я хочу получить из этого, - это Polygon 2, так как он больше всего покрыт моим полигоном. Это возможно? Есть ли что-то, что я могу использовать, чтобы получить процент покрытия и упорядочить его тем или иным способом, который просто возвращает только один результат?

--РЕДАКТИРОВАТЬ--

Просто в дополнение к принятому ответу (который вы должны опустить и дать голос, поскольку это является полной основой для этого), это то, что я закончил.

SELECT name, MI_PRINX, 
SDO_GEOM.SDO_AREA(
  SDO_GEOM.SDO_INTERSECTION(
    GEOM, 
    sdo_geometry('POLYGON((400969.48717156524 95600.59583240788,402385.9445972018 95957.22742049221,402446.64806962677 95579.91508788493,400905.95874489535 95353.03765349534,400969.48717156524 95600.59583240788))',27700)
    ,0.005
  )
,0.005) AS intersect_area 
FROM LIFE_HEATHLAND WHERE sdo_anyinteract(geom, sdo_geometry('POLYGON((400969.48717156524 95600.59583240788,402385.9445972018 95957.22742049221,402446.64806962677 95579.91508788493,400905.95874489535 95353.03765349534,400969.48717156524 95600.59583240788))',27700)) = 'TRUE'
ORDER BY INTERSECT_AREA DESC;

Это возвращает мне все результаты, которые пересекают мой полигон запроса с новым столбцом с именем INTERSECT_AREA, который обеспечивает площадь. Затем я могу отсортировать это и подобрать наибольшее число.

1 ответ

Решение

Просто вычислите пересечение между каждой из возвращенных геометрий и окном вашего запроса (используя SDO_GEOM.SDO_INTERSECTION()), вычислите площадь каждого такого пересечения (используя SDO_GEOM.SDO_AREA()) и вернуть строку с наибольшей площадью (упорядочить результаты в порядке убывания вычисляемой области и сохранить только первую строку).

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

SELECT s.state,
       sdo_geom.sdo_area (
         sdo_geom.sdo_intersection (
           s.geom, p.geom, 0.5),
         0.5, 'unit=sq_km') area
  FROM us_states s, us_parks p
 WHERE SDO_ANYINTERACT (s.geom, p.geom) = 'TRUE'
   AND p.name = 'Yellowstone NP'
 ORDER by area desc;

Который возвращает:

STATE                                AREA
------------------------------ ----------
Wyoming                        8100.64988
Montana                        640.277886
Idaho                          154.657145

3 rows selected.

Чтобы сохранить только строку с наибольшим пересечением, выполните:

SELECT * FROM (
  SELECT s.state,
         sdo_geom.sdo_area (
           sdo_geom.sdo_intersection (
             s.geom, p.geom, 0.5),
           0.5, 'unit=sq_km') area
    FROM us_states s, us_parks p
   WHERE SDO_ANYINTERACT (s.geom, p.geom) = 'TRUE'
     AND p.name = 'Yellowstone NP'
   ORDER by area desc
)
WHERE rownum = 1;     

давая:

STATE                                AREA
------------------------------ ----------
Wyoming                        8100.64988

1 row selected.

Следующий вариант также возвращает процент поверхности парка в каждом пересекающемся состоянии:

WITH p AS (
  SELECT s.state,
         sdo_geom.sdo_area (
           sdo_geom.sdo_intersection (
             s.geom, p.geom, 0.5),
           0.5, 'unit=sq_km') area
    FROM us_states s, us_parks p
   WHERE SDO_ANYINTERACT (s.geom, p.geom) = 'TRUE'
     AND p.name = 'Yellowstone NP'
)
SELECT state, area,
       RATIO_TO_REPORT(area) OVER () * 100 AS pct
FROM p
ORDER BY pct DESC;

Если вы хотите вернуть геометрию пересечений, просто включите это в свой набор результатов.

Другие вопросы по тегам