oracle spatial алгоритм привязки

Работа VB и СУБД (Access, MSSQL, MySQL, Oracle и пр.)
Правила форума
При создании новой темы не забывайте указывать используемую СУБД.
Anta
Продвинутый пользователь
Продвинутый пользователь
 
Сообщения: 106
Зарегистрирован: 19.08.2012 (Вс) 22:00

oracle spatial алгоритм привязки

Сообщение Anta » 28.11.2012 (Ср) 4:22

Здравствуйте, ищу алгоритм привязки к точке. задача: в Автокад пользователь рисует линию, нужно чтоб начало линии совпало с близлежайшей точкой, к примеру, нарисованы 2 пересекающиеся линии и координаты начала новой линии должны совпасть с координатами точки пересечения, привязаться к этой точке и взять ее координату за начало. Задачу нужно реализовать на pl/sql, я ищу хотя б алгоритм. Если я выбрала не тот форум, переадресуйте, где лучше разместить тему. Спасибо

ark
Бывалый
Бывалый
 
Сообщения: 216
Зарегистрирован: 18.07.2011 (Пн) 0:57

Re: oracle spatial алгоритм привязки

Сообщение ark » 28.11.2012 (Ср) 6:26

Уточните задачу. Надо найти ближайшую к заданной (x0,y0) точку из некоего массива точек {X(i);Y(i)}?
Пространство Евклидово и двумерное?

Qwertiy
Доктор VB наук
Доктор VB наук
 
Сообщения: 2753
Зарегистрирован: 26.06.2011 (Вс) 21:26

Сообщение Qwertiy » 28.11.2012 (Ср) 7:43

Если тут используется Автокад, то почему он не выполняет привязку?

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

Qwertiy
Доктор VB наук
Доктор VB наук
 
Сообщения: 2753
Зарегистрирован: 26.06.2011 (Вс) 21:26

Сообщение Qwertiy » 28.11.2012 (Ср) 7:46

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

ark
Бывалый
Бывалый
 
Сообщения: 216
Зарегистрирован: 18.07.2011 (Пн) 0:57

Re: oracle spatial алгоритм привязки

Сообщение ark » 28.11.2012 (Ср) 8:58

А как задаются (хранятся в БД) фигуры? Как определяется "ключевая" точка (пересечение, центр, излом)? Согласен с Qwertiy - не думаю, что pl/sql силён в геометрии, потому м.б. это решать всё-таки в автокаде?

Anta
Продвинутый пользователь
Продвинутый пользователь
 
Сообщения: 106
Зарегистрирован: 19.08.2012 (Вс) 22:00

Re: oracle spatial алгоритм привязки

Сообщение Anta » 29.11.2012 (Чт) 20:11

линии находятся на определенном слое, и соответственно в таблице, где столбец GEOM хранит геометрич. данные обекта, Qwertiy прав в подходе.
вот мой код, который компилируется без ошибок, но правильно ли реализован:
Код: Выделить всё
create or replace
FUNCTION SNAP(VAR_POINT In SDO_GEOMETRY, VAR_DIST In NUMBER) RETURN SDO_GEOMETRY AS START_POINT SDO_GEOMETRY;

BEGIN
  DECLARE
  POINT_TEMP SDO_GEOMETRY;
  RAYON NUMBER (10,3);
  UNBUFFER SDO_GEOMETRY;
  NB_OBJET NUMBER(3);
  MSGTXT VARCHAR2(200);
 
  GEOM_TEMP SDO_GEOMETRY;
  PROJ_ID NUMBER(10);
 
  POINT_A SDO_GEOMETRY;
  POINT_B SDO_GEOMETRY;
 
  NB_POINT_start NUMBER(1);
  NB_POINT_end NUMBER(1);
 
  I NUMBER(2);
 
   
  BEGIN
 
  POINT_TEMP:=VAR_POINT;
  PROJ_ID:=VAR_POINT.SDO_SRID;
  RAYON:=VAR_DIST;
  UNBUFFER:=SDO_GEOM.SDO_BUFFER(POINT_TEMP,RAYON,0.001);
 
  SELECT COUNT(*) GEOM INTO NB_OBJET FROM STR_SICADA_LLOT_S where SDO_RELATE(GEOM,UNBUFFER, 'MASK =ANYINTERACT querytype = WINDOW') = 'TRUE';
 
  IF NB_OBJET=0 THEN
   START_POINT:=SDO_GEOMETRY(2001,PROJ_ID,MDSYS.SDO_POINT_TYPE(0,0,NULL),NULL,NULL);

  ELSE
  IF NB_OBJET>0 THEN
   
   
    FOR ITEM IN (SELECT GEOM FROM STR_SICADA_LLOT_S where SDO_RELATE(GEOM,UNBUFFER, 'MASK =ANYINTERACT querytype = WINDOW') = 'TRUE')
      LOOP
     
      select COUNT(*) geom INTO NB_POINT_START FROM (SELECT SDO_LRS.GEOM_SEGMENT_START_PT(GEOM) as geom FROM STR_SICADA_LLOT_S WHERE SDO_RELATE(SDO_LRS.GEOM_SEGMENT_START_PT(GEOM),UNBUFFER, 'MASK =ANYINTERACT querytype = WINDOW') = 'TRUE') a , TABLE(sdo_util.getvertices(a.geom)) pt;
      select COUNT(*) geom INTO NB_POINT_END FROM (SELECT SDO_LRS.GEOM_SEGMENT_END_PT(GEOM) as geom FROM STR_SICADA_LLOT_S WHERE SDO_RELATE(SDO_LRS.GEOM_SEGMENT_END_PT(GEOM),UNBUFFER, 'MASK =ANYINTERACT querytype = WINDOW') = 'TRUE') a , TABLE(sdo_util.getvertices(a.geom)) pt;
   
       
       IF NB_POINT_START =1  THEN
           SELECT SDO_LRS.GEOM_SEGMENT_START_PT(GEOM) INTO POINT_A FROM STR_SICADA_LLOT_S WHERE SDO_RELATE(SDO_LRS.GEOM_SEGMENT_START_PT(GEOM),UNBUFFER, 'MASK =ANYINTERACT querytype = WINDOW') = 'TRUE';
           START_POINT:=POINT_A;
           EXIT;
     
           ELSE
           SELECT SDO_LRS.GEOM_SEGMENT_END_PT(GEOM) INTO POINT_B FROM STR_SICADA_LLOT_S WHERE SDO_RELATE(SDO_LRS.GEOM_SEGMENT_END_PT(GEOM),UNBUFFER, 'MASK =ANYINTERACT querytype = WINDOW') = 'TRUE';
           START_POINT:=POINT_B;
           EXIT;
       END IF;
       
      END LOOP;
     
  END IF;
end if;
 
  RETURN START_POINT;
END;
END SNAP;

ark
Бывалый
Бывалый
 
Сообщения: 216
Зарегистрирован: 18.07.2011 (Пн) 0:57

Re: oracle spatial алгоритм привязки

Сообщение ark » 30.11.2012 (Пт) 2:54

Хм, а где здесь геометрия/алгоритм привязки? Насколько я понял, точки привязки выбираются (проверяются) в SDO_RELATE. Т.е. вопрос по алгоритму выбора данных, а не по привязке. Трудно разбираться без подробностей. Однако, вот это
Код: Выделить всё
SELECT COUNT(*) GEOM INTO NB_OBJET FROM STR_SICADA_LLOT_S where SDO_RELATE(GEOM,UNBUFFER, 'MASK =ANYINTERACT querytype = WINDOW') = 'TRUE';
  IF NB_OBJET=0 THEN
зачем? Назначьте сразу START_POINT:=SDO_GEOMETRY(2001,PROJ_ID,MDSYS.SDO_POINT_TYPE(0,0,NULL),NULL,NULL);, и если запрос SELECT GEOM FROM будет пустой, то и цикл For будет пустой. Дальше, насколько я понял из проверки,IF NB_POINT_START =1 THEN, предыдущие запросы могут возвратить только 0 или 1? Тогда зачем For - Вы выходите на первом же цикле - если 1, то START_POINT:=POINT_A;, если 0 - START_POINT:=POINT_B;. Если есть какой-то признак "близости" точки к объекту, может, добавит его в запрос вместе с ORDER BY?

ЗЫ Кстати, не втему, STR_SICADA_LLOT это, случайно, не СНС "Цикада"?

Anta
Продвинутый пользователь
Продвинутый пользователь
 
Сообщения: 106
Зарегистрирован: 19.08.2012 (Вс) 22:00

Re: oracle spatial алгоритм привязки

Сообщение Anta » 30.11.2012 (Пт) 15:28

ark писал(а):Хм, а где здесь геометрия/алгоритм привязки? Насколько я понял, точки привязки выбираются (проверяются) в SDO_RELATE. Т.е. вопрос по алгоритму выбора данных, а не по привязке. Трудно разбираться без подробностей. Однако, вот это
Код: Выделить всё
SELECT COUNT(*) GEOM INTO NB_OBJET FROM STR_SICADA_LLOT_S where SDO_RELATE(GEOM,UNBUFFER, 'MASK =ANYINTERACT querytype = WINDOW') = 'TRUE';
IF NB_OBJET=0 THEN
зачем? Назначьте сразу START_POINT:=SDO_GEOMETRY(2001,PROJ_ID,MDSYS.SDO_POINT_TYPE(0,0,NULL),NULL,NULL);, и если запрос SELECT GEOM FROM будет пустой, то и цикл For будет пустой. Дальше, насколько я понял из проверки,IF NB_POINT_START =1 THEN, предыдущие запросы могут возвратить только 0 или 1? Тогда зачем For - Вы выходите на первом же цикле - если 1, то START_POINT:=POINT_A;, если 0 - START_POINT:=POINT_B;. Если есть какой-то признак "близости" точки к объекту, может, добавит его в запрос вместе с ORDER BY?

ЗЫ Кстати, не втему, STR_SICADA_LLOT это, случайно, не СНС "Цикада"?


Спасибо за cовет и в тоже время вы мне указали на ошибку, количество точек начала или конца может быть больше 0..., сегодня протестирую
Цикада)) , SICADA- SI кадастр ).

Anta
Продвинутый пользователь
Продвинутый пользователь
 
Сообщения: 106
Зарегистрирован: 19.08.2012 (Вс) 22:00

Re: oracle spatial алгоритм привязки

Сообщение Anta » 30.11.2012 (Пт) 15:48

упс, что-то я сама потерялась, если линий в радиусе проверки >1, то точек конца или начала будет больше нуля, но я ведь в цикле беру по одной линии для проверки, для одной линии может быть только по одной точке начала и конца.

ark
Бывалый
Бывалый
 
Сообщения: 216
Зарегистрирован: 18.07.2011 (Пн) 0:57

Re: oracle spatial алгоритм привязки

Сообщение ark » 01.12.2012 (Сб) 10:58

Код: Выделить всё
   FOR ITEM IN (SELECT ...') 
     LOOP
--Пошёл первый проход цикла
         IF NB_POINT_START =1  THEN -- проверяется только первый объект
             --SELECT....
             START_POINT:=POINT_A;
             EXIT; --<- Выход из цикла здесь (даже если есть ещё линии)
         ELSE
             --SELECT....
             START_POINT:=POINT_B;
             EXIT; --Или здесь в любом случае (даже если есть ещё линии, или, наоборот, NB_POINT_START=NB_POINT_END=0)
         END IF;
--Сюда выполнение никогда не дойдёт
     END LOOP;

Насколько я понял, объектов вокруг может быть больше 1, иначе зачем цикл?
Вообще говоря, для поиска обычно цикл не нужен - достаточно правильного запроса с WHERE + ORDER BY + TOP(1)
У Вас здесь вообще нет признака, по которому выбирается "нужный" объект. Да и ITEM из цикла тоже нигде не используется

Qwertiy
Доктор VB наук
Доктор VB наук
 
Сообщения: 2753
Зарегистрирован: 26.06.2011 (Вс) 21:26

Сообщение Qwertiy » 01.12.2012 (Сб) 11:29

ark писал(а):Вообще говоря, для поиска обычно цикл не нужен - достаточно правильного запроса с WHERE + ORDER BY + TOP(1)

Тебе не кажется, что сортировка более затратная операция, чем цикл? Или SQL должен сам понять, что order by + top 1 это выбор максимального элемента и не сортировать?

ark
Бывалый
Бывалый
 
Сообщения: 216
Зарегистрирован: 18.07.2011 (Пн) 0:57

Re: oracle spatial алгоритм привязки

Сообщение ark » 02.12.2012 (Вс) 8:39

Qwertiy писал(а):Тебе не кажется, что сортировка более затратная операция, чем цикл?
Не кажется - зависит от обстоятельств. Может, мне надо два (или десять) максимальных значений?
Qwertiy писал(а):Или SQL должен сам понять, что order by + top 1 это выбор максимального элемента и не сортировать?
А WHERE на что? Что-нить типа
Код: Выделить всё
select T1.* FROM MyTable T1,
    (select max(colName) as maxvalue, id from MyTable group by id) T2   
    where T1.id= T2.id and T1.colName = T2.maxvalue
, или ещё как, а не врукопашную записи перебирать. Наверное, варианты, когда цикл лучше, возможны (да и то, наверное, лучше курсор гонять, чем записи по одной вытаскивать), но мне пока не попадались такие задачи.

Qwertiy
Доктор VB наук
Доктор VB наук
 
Сообщения: 2753
Зарегистрирован: 26.06.2011 (Вс) 21:26

Сообщение Qwertiy » 02.12.2012 (Вс) 12:06

ark писал(а):да и то, наверное, лучше курсор гонять, чем записи по одной вытаскивать

Я думал, что for это и есть курсор...

Anta
Продвинутый пользователь
Продвинутый пользователь
 
Сообщения: 106
Зарегистрирован: 19.08.2012 (Вс) 22:00

Re: oracle spatial алгоритм привязки

Сообщение Anta » 05.12.2012 (Ср) 2:50

В район буферной зоны возле точки может попасть n линий, туда попадает либо начало , либо конец линии. нужно взять первую встретившуюся в буфеной зоне точку (точка начала или конца отрезка) и задать ее как стратовую. Я решила сразу проверять точки: начала и конца, но не сработало. Нужен цикл для всех линий, имеющее какое-либо отношение с буферной зоной,
Код: Выделить всё
SELECT COUNT(*) GEOM INTO NB_OBJET FROM STR_SICADA_LLOT_S where SDO_RELATE(GEOM,UNBUFFER, 'MASK =ANYINTERACT querytype = WINDOW') = 'TRUE';
IF NB_OBJET=0 THEN
, если нет объекта, то точка старта (0,0) если есть объекты : взять координаты точки начала сравнить попадают ли в зону, если нет, то координаты конца.Работает

ark
Бывалый
Бывалый
 
Сообщения: 216
Зарегистрирован: 18.07.2011 (Пн) 0:57

Re: oracle spatial алгоритм привязки

Сообщение ark » 05.12.2012 (Ср) 4:35

Anta писал(а):нужно чтоб начало линии совпало с близлежайшей точкой
Anta писал(а):нужно взять первую встретившуюся в буфеной зоне точку
Так ближайшую или первую попавшуюся? Вы уж определитесь.
Нужен цикл для всех линий, имеющее какое-либо отношение с буферной зоной,
У Вас нету цикла, IF...ELSE ВСЕГДА выходит на первом же элементе

ark
Бывалый
Бывалый
 
Сообщения: 216
Зарегистрирован: 18.07.2011 (Пн) 0:57

Re: oracle spatial алгоритм привязки

Сообщение ark » 05.12.2012 (Ср) 5:35

Я б сделал что-нить типа
Код: Выделить всё
DECLARE @tblPoints TABLE(ptGeom SDO_GEOMETRY);
--Добавляем ВСЕ начальные точки из зоны
INSERT INTO @tblPoints (ptGeom) (
          SELECT SDO_LRS.GEOM_SEGMENT_START_PT(GEOM)
          FROM STR_SICADA_LLOT_S
          WHERE SDO_RELATE(SDO_LRS.GEOM_SEGMENT_START_PT(GEOM),UNBUFFER, 'MASK =ANYINTERACT querytype = WINDOW') = 'TRUE');
--Добавляем ВСЕ конечные точки из зоны
INSERT INTO @tblPoints (ptGeom) (
          SELECT SDO_LRS.GEOM_SEGMENT_END_PT(GEOM)
          FROM STR_SICADA_LLOT_S
          WHERE SDO_RELATE(SDO_LRS.GEOM_SEGMENT_END_PT(GEOM),UNBUFFER, 'MASK =ANYINTERACT querytype = WINDOW') = 'TRUE');

А теперь уже из таблицы tblPoints выбираем ближайшую (или 0, если таблица пустая)

Anta
Продвинутый пользователь
Продвинутый пользователь
 
Сообщения: 106
Зарегистрирован: 19.08.2012 (Вс) 22:00

Re: oracle spatial алгоритм привязки

Сообщение Anta » 11.12.2012 (Вт) 0:21

всем спасибо,работающий вариант:
Код: Выделить всё
START_POINT:=SDO_GEOMETRY(2001,PROJ_ID,MDSYS.SDO_POINT_TYPE(0,0,NULL),NULL,NULL);
   
   SELECT count(*) into NB_OBJET  FROM temp_STR_SICADA_LLOT_S where SDO_RELATE(GEOM,UNBUFFER, 'MASK =ANYINTERACT querytype = WINDOW') = 'TRUE';
   if NB_OBJET > 1 then
    FOR ITEM IN (SELECT GEOM FROM temp_STR_SICADA_LLOT_S where SDO_RELATE(GEOM,UNBUFFER, 'MASK =ANYINTERACT querytype = WINDOW') = 'TRUE')
      LOOP
      null;

         GEOM_TEMP := item.geom;
         POINT_A := SDO_LRS.GEOM_SEGMENT_START_PT(GEOM_TEMP);
         POINT_b := SDO_LRS.GEOM_SEGMENT_END_PT(GEOM_TEMP);
         
         IF SDO_GEOM.RELATE(POINT_A, 'anyinteract',UNBUFFER, 0.005) = 'TRUE' THEN
           START_POINT := POINT_A;
         ELSE
           START_POINT := POINT_B;
         END IF;
         
         
      END LOOP;
     
END IF;

ark
Бывалый
Бывалый
 
Сообщения: 216
Зарегистрирован: 18.07.2011 (Пн) 0:57

Re: oracle spatial алгоритм привязки

Сообщение ark » 11.12.2012 (Вт) 6:25

1. Всё равно не вижу выбор ближайшей точки
2. Теперь Loop, наоборот, без выхода - т.е. START_POINT будет по последнему элементу.


Вернуться в Базы данных

Кто сейчас на конференции

Сейчас этот форум просматривают: нет зарегистрированных пользователей и гости: 5

    TopList