Пространственная геометрия 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;
Если вы хотите вернуть геометрию пересечений, просто включите это в свой набор результатов.