Oracle Spatial — SDO_BUFFER не работает?

У меня есть таблица с SDO_Geometries, и я запрашиваю все геометрии, чтобы найти их начальную и конечную точки, а затем вставляю эти точки в другую таблицу с именем ORAHAN. Теперь моя основная цель состоит в том, чтобы для каждой точки в орахане я должен найти, пересекается ли она с другой точкой в ​​орахане при предоставлении 2-сантиметрового буфера точкам. Итак, я пишу некоторый pl sql, используя функции Relate и Bufer, но когда я проверяю некоторые записи в Map Info, я вижу, что есть точки в пределах 1 см от себя, но нет записи в таблице пересечений с именем ORAHANCROSSES. Я неправильно использую эти функции или что?

Примечание. Я использую Oracle Database 11g Enterprise Edition Release 11.2.0.1.0 — 64-битную версию Production и PL/SQL Release 11.2.0.1.0 — и SDO_PACKAGE.

ORAHAN имеет около 400 тысяч записей (точки и другие столбцы).

declare
BEGIN
 for curs in (select * from ORAHAN t) loop
   for curs2 in (select *
                   from ORAHAN t2
                  where SDO_RELATE(t2.geoloc,SDO_GEOM.SDO_BUFFER(curs.geoloc,0.02,0.5) , 
                  'mask=ANYINTERACT') = 'TRUE'
                    and t2.mi_prinx <> curs.mi_prinx) loop                    
     Insert INTO ORAHANCROSSES
     values
       (curs.Mip, curs.Startmi, curs2.Mip, curs2.Startmi);
     commit;
   end loop;
 end loop;
END;

А это изображение карты MapInfo, на котором показаны 3 точки, расположенные близко друг к другу примерно на 1 сантиметр. Но в ораханкроссах нет записи, соответствующей этим трем.

Примечание: 0,00001000 км равно 1 см введите здесь описание изображения

Метаданные Орахана:

select * from user_sdo_geom_metadata where table_name = 'ORAHAN';

введите здесь описание изображения

И диминфо:

введите здесь описание изображения


person Ardahan Kisbet    schedule 29.07.2016    source источник


Ответы (1)


Какова система координат ваших данных? И самое главное, какой допуск вы установили в своих метаданных?

Некоторые другие комментарии:

1) Не используйте отношение с буферным подходом. Просто используйте дистанционный подход.

2) Вам не нужен цикл PL/SQL для такого рода запросов, просто используйте простой CTAS:

create table orahancrosses as
select c1.mip mip_1, c1.startmi startmi_1, c2.mip mip_2, c2.startmi startmi_2
from orahan c1, orahan c2
where sdo_within_distance (c2.geoloc, c1.geoloc, 'distance=2 unit=cm') = 'TRUE'
and c2.mi_prinx <> c1.mi_prinx;

3) Как написано, пары точек A и B, находящиеся в пределах 2 см, будут возвращены дважды: один раз как (A,B) и еще раз как (B,A). Чтобы избежать этого (и вернуть только один из случаев), напишите запрос следующим образом:

create table orahancrosses as
select c1.mip mip_1, c1.startmi startmi_1, c2.mip mip_2, c2.startmi startmi_2
from orahan c1, orahan c2
where sdo_within_distance (c2.geoloc, c1.geoloc, 'distance=2 unit=cm') = 'TRUE'
and c1.rowid < c2.rowid;

3) Обработка упомянутого вами количества точек (400000+) должна работать лучше с использованием метода SDO_JOIN, например:

create table orahancrosses as
select c1.mip mip_1, c1.startmi startmi_1, c2.mip mip_2, c2.startmi startmi_2
from  table (
        sdo_join (
          'ORAHAN','GEOLOC',
          'ORAHAN','GEOLOC',
          'DISTANCE=2 UNIT=CM'
        )
      ) j,
      orahan c1, 
      orahan c2
where j.rowid1 < j.rowid2
and c1.rowid = j.rowid1
and c2.rowid = j.rowid2;

Это, вероятно, все еще потребует времени для обработки - в зависимости от мощности вашего сервера базы данных. Если у вас есть лицензии на Oracle Enterprise Edition и ваше оборудование имеет достаточную мощность (количество ядер), то параллелизм может сократить затраченное время.

4) Вы говорите, что используете Oracle 11g. Какая именно версия? Версия 11.2.0.4 — это конечная версия 11gR2. Все, что старше, больше не поддерживается. К настоящему времени вы действительно должны быть на 12cR1 (12.1.0.2). Основным преимуществом версии 12.1.0.2 в вашем случае является функция Vector Performance Accelerator, которая ускоряет ряд пространственных функций и операторов (только если у вас есть соответствующие лицензии Oracle Spatial — она недоступна с бесплатной функцией Oracle Locator).

======================================

Используя две точки в вашем примере. Рассчитаем расстояние:

select sdo_geom.sdo_distance(
  sdo_geometry (2001,null,sdo_point_type(521554.782174622,4230983.08336913,null),null,null), 
  sdo_geometry (2001,null,sdo_point_type(521554.782174622,4230983.07336716,null),null,null),
  0.005
) distance
from dual;


  DISTANCE
----------
 .01000197

1 row selected.

Заметьте, я не указываю SRID. Если предположить, что координаты выражены в метрах, то расстояние между ними действительно чуть больше 1 см.

======================================

Причина, по которой ваш исходный синтаксис не работает, как вы заметили, заключается в допуске, указанном вами для вызова SDO_BUFFER(). Вы передаете его как 0,5 (= 50 см), чтобы создать буфер с радиусом 0,02 (2 см). Эффект заключается в том, что полученный буфер эффективно растворяется в самой точке.

Например, при допуске 0,5:

select sdo_geom.sdo_buffer(sdo_geometry (2001,null,sdo_point_type(521554.782174622,4230983.08336913,null),null,null),0.02,0.5) from dual;

Производит:

SDO_GEOMETRY(2001, NULL, SDO_POINT_TYPE(521554.782, 4230983.08, NULL), NULL, NULL)

При допуске 0,005:

select sdo_geom.sdo_buffer(sdo_geometry (2001,null,sdo_point_type(521554.782174622,4230983.08336913,null),null,null),0.02,0.005) from dual;

Вы получаете правильный буфер:

SDO_GEOMETRY(2003, NULL, NULL, SDO_ELEM_INFO_ARRAY(1, 1003, 2), SDO_ORDINATE_ARRAY(521554.782, 4230983.06, 521554.802, 4230983.08, 521554.782, 4230983.1, 521554.762, 4230983.08, 521554.782, 4230983.06))

И самая близкая точка теперь совпадает с этим буфером:

select sdo_geom.relate(
  sdo_geom.sdo_buffer(sdo_geometry (2001,null,sdo_point_type(521554.782174622,4230983.08336913,null),null,null),0.02,0.005),
  'determine',
  sdo_geometry (2001,null,sdo_point_type(521554.782174622,4230983.07336716,null),null,null),
  0.005
) relation
from dual;

RELATION
------------------------- 
CONTAINS

1 row selected.

======================================

Теперь тот факт, что ваши данные не имеют надлежащего явного SRID, означает, что использование явных единиц измерения или поиска на основе расстояния не будет работать. Поскольку база данных не знает, в какой системе координат находятся ваши данные, она не знает, как определить, что расстояние между двумя точками меньше заданного числа см или метров. Все, что вы можете сделать, это предположить, что координаты указаны в метрах.

Поэтому в приведенных выше примерах замените 'DISTANCE=2 UNIT=CM' на 'DISTANCE=0.02'.

person Albert Godfrind    schedule 31.07.2016
comment
Я работаю в компании, которая использует oracle 11gR2 в некоторых проектах. Орахан имеет около 400 000 записей (строк). Я как можно скорее отредактирую свой вопрос и добавлю значение допуска в метаданные. - person Ardahan Kisbet; 01.08.2016
comment
Если компания использует 11gR2 и имеет надлежащего системного администратора и администратора баз данных, то они, вероятно, уже используют 11.2.0.4. Тем не менее, в этой версии и с объемом данных, которые вам нужно обработать, подход SDO_JOIN, безусловно, является правильным (я добавил синтаксис в свой ответ). В версии 12c с функцией Vector Performance Accelerator все было бы по-другому. - person Albert Godfrind; 01.08.2016
comment
Я попробовал то, что вы сказали, метод SDO_JOIN, и он очень быстрый. Он сделал работу за 2 минуты. Спасибо за это. Но проблема все еще остается. Он не находит пересечения, пока некоторые точки находятся на расстоянии 1 см друг от друга. Я предполагаю, что diminfo моей колонки неверен. - person Ardahan Kisbet; 01.08.2016
comment
Таким образом, допуски, которые у вас есть, составляют 0,000082491 для X и 0,0001000197 для Y. Значения странные (и тем более, что значения различны для X и Y). Но я помню, что Mapinfo вычисляла странные значения толерантности. Однако допуск составляет менее 2 см, поэтому ваша проверка должна работать нормально. - person Albert Godfrind; 01.08.2016
comment
Не могли бы вы опубликовать координаты двух точек, которые вы показываете, которые находятся на расстоянии 1 см друг от друга? Чтобы подтвердить, у вас есть SRID, установленный в NULL? Какую систему координат/проекцию вы используете в Mapinfo? - person Albert Godfrind; 01.08.2016
comment
Координаты верхней точки: X: 521554,782174622 Y: 4230983,08336913 Координаты нижней точки: X: 521554,782174622 Y: 4230983,07336716 - person Ardahan Kisbet; 01.08.2016
comment
Давайте продолжим обсуждение в чате. - person Ardahan Kisbet; 01.08.2016
comment
Когда я даю правильное значение допуска из исходной таблицы, оно выполняет свою работу правильно. Спасибо за ваш ответ. - person Ardahan Kisbet; 02.08.2016