





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;
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
ark писал(а):Хм, а где здесь геометрия/алгоритм привязки? Насколько я понял, точки привязки выбираются (проверяются) в SDO_RELATE. Т.е. вопрос по алгоритму выбора данных, а не по привязке. Трудно разбираться без подробностей. Однако, вот этозачем? Назначьте сразу 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?
- Код: Выделить всё
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
ЗЫ Кстати, не втему, STR_SICADA_LLOT это, случайно, не СНС "Цикада"?


   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;

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

Не кажется - зависит от обстоятельств. Может, мне надо два (или десять) максимальных значений?Qwertiy писал(а):Тебе не кажется, что сортировка более затратная операция, чем цикл?
А WHERE на что? Что-нить типаQwertiy писал(а):Или SQL должен сам понять, что order by + top 1 это выбор максимального элемента и не сортировать?
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
ark писал(а):да и то, наверное, лучше курсор гонять, чем записи по одной вытаскивать

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

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');
 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;
Сейчас этот форум просматривают: нет зарегистрированных пользователей и гости: 7