Oracle: как проверить, перекрываются ли два многоугольника или нет
Я измерил площадь земли (участок) и зафиксировал координаты GPS в 4 ее углах с помощью устройства GPS. Теперь у меня есть два вопроса
- Как сохранить это Oracle Database. ( кажется, ответ на первый пункт. не так ли?)
- После сохранения я хочу проверить, перекрывает ли какой-либо участок (частично или полностью) другой существующий график в базе данных или нет?
2 ответа
Я получил очень полезные комментарии от Рене и Бена. и на основании я решил свои проблемы..
--------------------------- CREATING TABLE --------------------------
create table tbl_location(
id int constraint id_pk primary key,
unit_code char(2) not null,
plot_id number(15) not null,
season_cntrl number(2),
Ryot_code varchar2(9),
share_or_perc_val number(2) not null,
plot_no varchar2(18) not null,
total_area decimal(5,5),
a1 varchar2(15),
b1 varchar2(15),
a2 varchar2(15),
b2 varchar2(15),
a3 varchar2(15),
b3 varchar2(15),
a4 varchar2(15),
b4 varchar2(15),
location sdo_geometry
);
--------------------------- CREATING SEQUENCE FOR ID ---------------------------
create sequence location_sequence
start with 1
increment by 1
nocache
nocycle;
/
--- createing a trigger for auto-incrementation of ID ------------------------------
Create or replace trigger id_increment
before insert on tbl_location
for each row
begin
select location_sequence.nextval into :new.id from dual;
end;
для данных о местоположении столбцов
update tbl_location set location = SDO_GEOMETRY(2003,NULL,NULL,SDO_ELEM_INFO_ARRAY(1,1003,1),SDO_ORDINATE_ARRAY( '80.16181','27.8682866666666','80.1616516666666','27.8681266666666','80.161215','27.867975','80.1613933333333','27.8685933333333','80.16181','27.8682866666666' )) where id =2;
update tbl_location set location = SDO_GEOMETRY(2003,NULL,NULL,SDO_ELEM_INFO_ARRAY(1,1003,1),SDO_ORDINATE_ARRAY( '80.1538483333333','27.88376','80.15354','27.8841166666666','80.1529499999999','27.8834933333333','80.1532','27.8832566666666','80.1538483333333','27.88376' )) where id =3;
Чтобы получить участки (многоугольник), которые пересекаются друг с другом
select a.id as id1, b.id as id2,a.unit_code, a.ryot_code,a.share_or_perc_val,
sdo_geom.sdo_intersection(a.location, b.location, 0.005) location,
a.plot_no, a.total_area
from tbl_location a
Inner Join tbl_location b on
a.id < b.id and sdo_geom.sdo_intersection(a.location, b.location,0.005) is not null ;
Есть гораздо более простой способ сделать это.
Кажется, ваша проблема использует функцию SDO_GEOM.RELATE. Эта функция возвращает отношения между двумя или более полигонами.
В следующем примере все отношения к другим многоугольникам в вашей таблице показаны к многоугольнику с 1
SELECT c.id,
SDO_GEOM.RELATE(c.polygon, 'determine', c_b.polygon, 0.005) relationship
FROM my_polygon_table c, my_polygon_talbe c_b WHERE c_b.id = 1;
Результатом является одно из опсибильных отношений: ANYINTERACT; СОДЕРЖИТ; ПОКРЫТА; ОХВАТЫВАЕТ; РАЗЪЕДИНЕНИЕ; РАВНО; ВНУТРИ; НА; OVERLAPBDYDISJOINT; OVERLAPBDYINTERSECT; СЕНСОРНЫЙ;
Позаботьтесь также о правильном ключевом слове:
Если вы передадите ключевое слово DETERMINE в маске, функция вернет одно ключевое слово отношения, которое наилучшим образом соответствует геометрии.
Если вы передаете ключевое слово ANYINTERACT в маске, функция возвращает ИСТИНА, если две геометрии не пересекаются.
Ну, вы можете просто вызвать SDO_GEOM.SDO_AREA() для результата функции SDO_GEOM.SDO_INTERSECTION().
Однако это не даст вам значимых результатов: ваши геометрии находятся (как кажется) в геодезических координатах WGS84 (то есть в десятичных градусах), но вы загружаете их без указания какой-либо системы координат. В результате любой расчет площади вернет результат в квадратных градусах, бессмысленный и непригодный результат.
Вы должны загрузить свои две геометрии следующим образом:
update tbl_location set location = SDO_GEOMETRY(2003,4326,NULL,SDO_ELEM_INFO_ARRAY(1,1003,1),SDO_ORDINATE_ARRAY( 80.16181,27.8682866666666,80.1616516666666,27.8681266666666,80.161215,27.867975,80.1613933333333,27.8685933333333,80.16181,27.8682866666666 )) where id =2;
update tbl_location set location = SDO_GEOMETRY(2003,4326,NULL,SDO_ELEM_INFO_ARRAY(1,1003,1),SDO_ORDINATE_ARRAY( 80.1538483333333,27.88376,80.15354,27.8841166666666,80.1529499999999,27.8834933333333,80.1532,27.8832566666666,80.1538483333333,27.88376 )) where id =3;
Наконец, ваш подход работает только потому, что вы играете только с двумя геометриями. Как только вы начнете работать с реальными данными, запрос будет работать очень плохо: он требует вычисления пересечения между каждой формой и всеми остальными. Для набора из 10000 фигур это означает 100 000 000 вычислений (на самом деле 99 990 000, поскольку вы избегаете пересечения геометрии с самим собой).
Надлежащий подход заключается в обнаружении форм, которые пересекаются, используя пространственную индексацию. Подходящий подход - использовать для этого процедуру SDO_JOIN().