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