Как использовать обложки sdo_relate с полигоном и точкой

#oracle #oracle11g #geospatial

Вопрос:

Я пытаюсь найти все точки, которые покрыты полигоном на сервере oracle11g. Inside и contains возвращают логические значения, но covers и covered всегда являются ложными. Я неправильно это понимаю? Разве обложки не должны быть истинными, если «содержит» истинно, когда точка находится в середине прямоугольника многоугольника?

Создать таблицу

 CREATE TABLE geo
(
    name varchar(255),
    geo  MDSYS.SDO_GEOMETRY NOT NULL
);
 

Настройка метаданных

 insert into user_sdo_geom_metadata(table_name, column_name, diminfo, srid)
VALUES (
       'GEO',
       'GEO',
       SDO_DIM_ARRAY(MDSYS.SDO_DIM_ELEMENT('LONGITUDE',-180, 180, 0.25),
                     MDSYS.SDO_DIM_ELEMENT('LATITUDE',-90, 90, 0.25)),
       4326);
 

Создание пространственного индекса

 CREATE INDEX blabla ON geo (geo) INDEXTYPE IS MDSYS.SPATIAL_INDEX;
 

Сделайте прямоугольник между 0/0 и 2/2

 INSERT INTO geo (name, geo)
VALUES ('SimplePolygon',
        sdo_geometry(2003, 4326, null,
                     sdo_elem_info_array(1, 1003, 1),
                     sdo_ordinate_array(0, 0,
                                        2, 0,
                                        2, 2,
                                        0, 2,
                                        0, 0)));
 

Поставьте точку на 1/1

 INSERT INTO geo(name, geo)
VALUES ('SimplePoint',
        sdo_geometry(2001, 4326, null,
                     sdo_elem_info_array(1, 1, 1),
                     sdo_ordinate_array(1, 1)));
 

Сопоставьте все данные со всеми данными и посмотрите, какая маска возвращает значение true/false.

 select
  g1.name, 
  g2.name,
  sdo_relate(g1.geo, g2.geo, 'mask=COVEREDBY') as COVEREDBY,
  sdo_relate(g1.geo, g2.geo, 'mask=COVERS') as COVERS,
  sdo_relate(g1.geo, g2.geo, 'mask=COVERS INSIDE') as COVERSINSIDE,
  sdo_relate(g1.geo, g2.geo, 'mask=INSIDE') as INSIDE,
  sdo_relate(g1.geo, g2.geo, 'mask=CONTAINS') as CONTAINS,
  sdo_relate(g1.geo, g2.geo, 'mask=ANYINTERACT') as ANYINTERACT,
  -- turn around geometry
  sdo_relate(g2.geo, g1.geo, 'mask=COVEREDBY') as COVEREDBY2,
  sdo_relate(g2.geo, g1.geo, 'mask=COVERS') as COVERS2,
  sdo_relate(g2.geo, g1.geo, 'mask=INSIDE') as INSIDE2,
  sdo_relate(g2.geo, g1.geo, 'mask=CONTAINS') as CONTAINS2,
  sdo_relate(g2.geo, g1.geo, 'mask=ANYINTERACT') as ANYINTERACT2
from geo g1, geo g2
 

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

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

Ответ №1:

Из документации по пространственным отношениям и фильтрации:

  • COVERS : Граница и внутренняя часть одного объекта полностью содержатся во внутренней части или границе другого объекта, их внутренние части пересекаются, а граница или внутренняя часть одного объекта и граница другого объекта пересекаются.
  • COVEREDBY : Противоположность COVERS . A COVEREDBY B подразумевает B COVERS A .

Топологические Соотношения

Причина, по которой связь является ложной, заключается в конечном условии, что «и граница или внутренняя часть одного объекта и граница другого объекта пересекаются». Поскольку ваша точка и прямоугольник не имеют границ, которые пересекаются, то они COVER ни COVEREDBY то, ни другое.

Комментарии:

1. Я ставлю точку на границе многоугольника, но covers не возвращает TRUE. Если я сделаю это с другим полигоном, который частично находится на линии большего многоугольника, то COVERS вернет значение TRUE для двух полигонов. Может ли быть так, что точки несовместимы с ОБЛОЖКАМИ.