Re: [Portugal] expressão sql para preencher tabela com rua mais próxima

Diego Moreira moreira.geo at gmail.com
Sun Aug 21 21:04:11 EDT 2011


Boa Noite Pedro,

Como sugestão do Pedro Venâncio, e tbm considero importante vamos dar
fechamento ao post. Vou voltar a te responder aqui para caso alguem venha
depois, será mais fácil encontrar uma resposta.

Segue a conversa referente a esse post, mas que estava em outro.

*Em 20-08-2011 23:34, Diego Moreira escreveu: *
*
*
* Opá,

Então Pedro,

Esse problema, no meu ponto de vista, pode ser resolvido de duas formas:

1 - Refatorar a tabela rua para que permita somente lineString. Uma Rua é
composta por vários trechos, cada tupla da tabela seria um trecho. (Acho a
mais interessante).

2 - "Encapsular" a função ST_Line_Interpolate_Point, caso vc tenha uma
MultiLine, ela calcula o ponto a X distancia para cada linha e retorna um
multPoint.

O que acha?


Diego Moreira Carvalho


Caro Diego,

Eu preferia optar pela segunda opção uma vez que não me era conveniente
modificar os trechos...Pode ajudar-me a fazer isso para testarmos?
*

*Com os melhores cumprimentos,
Pedro Costa
Geógrafo
Especializado em Sistemas de Informação Geográfica e Ordenamento do Território*


Respondendo:

Seguem duas funções:

*CREATE OR REPLACE FUNCTION smartUnion(geom1 geometry, geom2 geometry)
RETURNS geometry AS $$
-- Autor: Diego Moreira Carvalho
-- E-mail: moreira.geo  gmail.com
-- Data: 20/08/2011
-- Descrição: Esta função retorna a união das duas geometrias, caso alguma
geometria seja inválida, retorna a que é válida.
DECLARE
    retorno geometry;
BEGIN
    IF ST_IsValid(geom1) AND ST_IsValid(geom2) THEN
        retorno := ST_Union(geom1, geom2);
    ELSIF ST_IsValid(geom1) THEN
        retorno := geom1;
    ELSIF ST_IsValid(geom2) THEN
        retorno := geom2;
    END IF;
    RETURN retorno;
END;
$$ LANGUAGE plpgsql;


CREATE OR REPLACE FUNCTION Line_Interpolate_Point_Alter(a_linestring
geometry, a_fraction float) RETURNS geometry AS $$
-- Autor: Diego Moreira Carvalho
-- E-mail: moreira.geo  gmail.com
-- Data: 21/08/2011
-- Descrição: Esta função é o encapsulamento da função
ST_Line_Interpolate_Point para aceitar multiLines
DECLARE
    numGeometries integer;
    it integer;
    segment geometry;
    point geometry;
    retorno geometry;
BEGIN
    numGeometries := ST_NumGeometries(a_linestring);

    IF  numGeometries > 0 THEN
        numGeometries := numGeometries;
    ELSE
        numGeometries := 0;
    END IF;

    IF numGeometries > 0 THEN
        it := 1;
        WHILE it < (numGeometries + 1) LOOP
            segment := ST_GeometryN(a_linestring, it);
            point := ST_Line_Interpolate_Point(segment, a_fraction);
            retorno := smartUnion(point, retorno);
        it := it +1;
        END LOOP;
    ELSE
        point := ST_Line_Interpolate_Point(a_linestring, a_fraction);
        retorno := point;
    END IF;
    RETURN retorno;
END;
$$ LANGUAGE plpgsql;
*
Vc deve usa-la assim:

UPDATE passeios
SET rua =
(SELECT FID_ FROM ruas
ORDER BY ST_Distance(* Line_Interpolate_Point_Alter*(ruas.wkb_geometry,
0.5), passeios.wkb_geometry)) ASC LIMIT 1)

Qualquer problema é só falar;


Com os melhores cumprimentos,

Diego Moreira Carvalho



Em 19 de agosto de 2011 12:53, Pedro Costa <pedrocostaarma  sapo.pt>escreveu:

>  Encontrei que podemos acrescentar geometryN para aceita multi-geometrias:
>
> UPDATE passeios
> SET rua =
> (SELECT FID_ FROM ruas
>
>
> ORDER BY ST_Distance(ST_Line_Interpolate_Point(geometryN(ruas.wkb_geometry,
> 0.5), passeios.wkb_geometry)) ASC LIMIT 1)
>
>
> No entanto não reconhece a função
>
>
>
>
> On 19-08-2011 13:28, Diego Moreira wrote:
>
> Resolveu?
>
> Diego Moreira Carvalho
>
>
>
> Em 19 de agosto de 2011 09:13, Diego Moreira <moreira.geo  gmail.com>escreveu:
>
>> O método ST_Line_Interpolate_Point retorna um ponto ao longo de uma linha
>> dado uma porcentagem do comprimento desta linha.... se passarmos sempre 0.5,
>> teremos sempre o meio da linha... independente do numero de vértices que ela
>> tem,
>> Agora eu acho que resolve
>>
>>
>> "UPDATE passeios SET rua =
>> (SELECT FID_ FROM eixos_rua ORDER BY ST_Distance(*ST_Line_Interpolate_Point(eixos_rua.wkb_geometry,
>> 0.5)* , passeios.wkb_geometry) ASC LIMIT 1)"
>>
>>
>> Diego Moreira Carvalho
>>
>>
>>
>>
>> Em 19 de agosto de 2011 08:54, Pedro Costa <pedrocostaarma  sapo.pt>
>> escreveu:
>>
>> > Exactamente, neste caso estou a mudar a unha,  mas sabes alguma maneira
>> mais
>> > rápida?
>> >
>> > Obrigado
>> >
>> >
>> >
>> > On 19-08-2011 12:50, Diego Moreira wrote:
>> >
>> > Provavelmente os mal atribuídos estao relacionados a ruas que tem
>> somente
>> > dois ou tres pontos.... da para resolver...
>> >
>> > Em 19/08/2011 06:47, "Pedro Costa" <pedrocostaarma  sapo.pt> escreveu:
>> >> Caro Diego,
>> >>
>> >> Funcionou... Obrigado pela ajuda.
>> >> Apesar de tudo alguns passeios ainda são mal atribuídos, mas melhorou
>> >> bastante...
>> >>
>> >> Com os melhores cumprimentos,
>> >>
>> >> Pedro Costa
>> >>
>> >>
>> >>
>> >>
>> >>
>> >> Em 18-08-2011 20:04, Diego Moreira escreveu:
>> >>> Acho que vai dar certo, o pg numa divisão do tipo 3/2 retorna 1,
>> >>> retornaria 1.5 se fosse 3.0/2...
>> >>> Então... acho que vai funcionar.
>> >>>
>> >>> Diego Moreira Carvalho
>> >>>
>> >>>
>> >>>
>> >>> Em 18 de agosto de 2011 16:00, Diego Moreira <moreira.geo  gmail.com
>> >>> <mailto:moreira.geo  gmail.com>> escreveu:
>> >>>
>> >>> NumPoints(geometry)
>> >>>
>> >>> Encontra e Retorna o número de pontos na primeira linha na
>> >>> geometria. Retorna NULO se não há nenhuma linha na geometria.
>> >>>
>> >>> PointN(geometry,integer)
>> >>>
>> >>> Retorna o enésimo ponto na primeira linha na geometria.
>> >>> Retorna NULO se não há nenhuma linha na geometria.
>> >>>
>> >>> "UPDATE passeios SET rua =
>> >>> (SELECT FID_ FROM eixos_rua ORDER BY
>> >>> ST_Distance(PointN(eixos_rua.wkb_geometry,
>> >>> NumPoints(eixos_rua.wkb_geometry)/2) , passeios.wkb_geometry) ASC
>> >>> LIMIT 1)"
>> >>>
>> >>>
>> >>> Sera que isso dá certo? caso não, o problema é que a função PointN
>> >>> espera receber um inteiro, mas o resultado da divisão por 2
>> >>> retorna um numero tipo 3.5
>> >>>
>> >>> Diego Moreira Carvalho
>> >>>
>> >>>
>> >>>
>> >>> Em 18 de agosto de 2011 15:49, Pedro Costa <pedrocostaarma  sapo.pt
>> >>> <mailto:pedrocostaarma  sapo.pt>> escreveu:
>> >>>
>> >>> É exactamente por isso Diego. Mas sabes como faço para
>> >>> determinar a contagem de pontos em sql?
>> >>>
>> >>> Obrigado
>> >>>
>> >>>
>> >>>
>> >>>
>> >>> On 18-08-2011 19:40, Diego Moreira wrote:
>> >>>> Boa tarde Pedrom
>> >>>>
>> >>>> Acredito que tal problema ocorre porque as vezes a
>> >>>> estremidade da rua adjacente a que deveria ser escolhida é
>> >>>> mais próxima. Acho que o problema pode ser resolvido da
>> >>>> seguinte forma:
>> >>>>
>> >>>> Pego o ponto n/2 do eixo da rua: se a rua tem dez pontos pego
>> >>>> o 5 ponto, e executo aquela mesma sql, só que com este ponto,
>> >>>> e não com a geometria(eixos_rua.wkb_geometry).
>> >>>>
>> >>>> Acho que deve resolver.
>> >>>>
>> >>>> Espero ter ajudado.
>> >>>>
>> >>>> Diego Moreira Carvalho
>> >>>>
>> >>>>
>> >>>>
>> >>>> Em 18 de agosto de 2011 11:39, Pedro Costa
>> >>>> <pedrocostaarma  sapo.pt <mailto:pedrocostaarma  sapo.pt>>
>> >>>> escreveu:
>> >>>>
>> >>>> Pessoal é o seguinte, eu tenho duas tabelas no pgadmin
>> >>>> (passeios e ruas), e quero que o campo rua dos passeios
>> >>>> seja prenchido pela rua correspondente. Isto pode
>> >>>> fazer-se em função da distância, como o João Carvalho me
>> >>>> ajudou:
>> >>>>
>> >>>> "UPDATE passeios SET rua = (SELECT FID_ FROM eixos_rua
>> >>>> ORDER BY
>> >>>> ST_Distance(eixos_rua.wkb_geometry,passeios.wkb_geometry)
>> >>>> ASC LIMIT 1)"
>> >>>>
>> >>>> No entanto em muitos casos a rua escolhida não é a
>> >>>> correspondente, esta query não é muito eficiente neste
>> >>>> caso. Alguém sabe uma maneira diferente em que seja
>> >>>> escolhida a rua que está mais próxima "em toda a sua
>> >>>> extensão"?
>> >>>> Podem ver a imagem em anexo para perceberem melhor, as
>> >>>> linhas verdes são os passeios e as vermelhas os eixos de
>> >>>> rua. Alguém tem alguma ideia que possa ajudar?
>> >>>>
>> >>>> Obrigado
>> >>>>
>> >>>> _______________________________________________
>> >>>> Portugal mailing list
>> >>>> Portugal  lists.osgeo.org <mailto:Portugal  lists.osgeo.org>
>> >>>> http://lists.osgeo.org/mailman/listinfo/portugal
>> >>>>
>> >>>>
>> >>>>
>> >>>>
>> >>>> _______________________________________________
>> >>>> Portugal mailing list
>> >>>> Portugal  lists.osgeo.org <mailto:Portugal  lists.osgeo.org>
>> >>>> http://lists.osgeo.org/mailman/listinfo/portugal
>> >>>
>> >>>
>> >>> _______________________________________________
>> >>> Portugal mailing list
>> >>> Portugal  lists.osgeo.org <mailto:Portugal  lists.osgeo.org>
>> >>> http://lists.osgeo.org/mailman/listinfo/portugal
>> >>>
>> >>>
>> >>>
>> >>>
>> >>>
>> >>> _______________________________________________
>> >>> Portugal mailing list
>> >>> Portugal  lists.osgeo.org
>> >>> http://lists.osgeo.org/mailman/listinfo/portugal
>> >
>> >
>> > _______________________________________________
>> > Portugal mailing list
>> > Portugal  lists.osgeo.org
>> > http://lists.osgeo.org/mailman/listinfo/portugal
>> >
>> >
>> > _______________________________________________
>> > Portugal mailing list
>> > Portugal  lists.osgeo.org
>> > http://lists.osgeo.org/mailman/listinfo/portugal
>> >
>> >
>>
>>
>
>
> _______________________________________________
> Portugal mailing listPortugal  lists.osgeo.orghttp://lists.osgeo.org/mailman/listinfo/portugal
>
>
>
> _______________________________________________
> Portugal mailing list
> Portugal  lists.osgeo.org
> http://lists.osgeo.org/mailman/listinfo/portugal
>
>
-------------- próxima parte ----------
Um anexo em HTML foi limpo...
URL: http://lists.osgeo.org/pipermail/portugal/attachments/20110821/fa6d35ef/attachment-0001.html


More information about the Portugal mailing list