IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

PostgreSQL Discussion :

selection par proximité postgis


Sujet :

PostgreSQL

  1. #1
    Membre éclairé
    Inscrit en
    Décembre 2006
    Messages
    243
    Détails du profil
    Informations forums :
    Inscription : Décembre 2006
    Messages : 243
    Par défaut selection par proximité postgis
    Bonjour,

    J'utilise postgis et je cherche à récupérer les valeurs d'une colonne d'une table dont les points correspondants sont les plus proches des points d'une autre table. Les tables sont assez grosses (et encore c'était bien pire avant) 20000 et 300000 points environ.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    select a.*, b."Z" from tmp_pts_aep a,mnt_lg b
    where Distance(a.the_geom,b.the_geom)=(select min(distance(d.the_geom,c.the_geom)) from tmp_pts_aep c, mnt_lg d);
    Cette requête est très longue, et je ne sais pas si elle va produire un résultat correct.

    Qu'en pensez-vous ?

    Merci.

    (il n'y a peut être pas beaucoup de géomaticien par ici....)

  2. #2
    Membre émérite
    Homme Profil pro
    Inscrit en
    Janvier 2006
    Messages
    491
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Corse (Corse)

    Informations forums :
    Inscription : Janvier 2006
    Messages : 491
    Par défaut
    bonjour je ferais comme ça:
    au prealable il faut creer des gist index sur les deux tables

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     CREATE INDEX id1 ON tmp_pts_aep USING GIST ( the_geom); 
    CREATE INDEX id2 ON mnt_lg  USING GIST ( the_geom);
    puis une requete du style
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    SELECT a.*, b."Z" FROM tmp_pts_aep a,mnt_lg b,min(Distance(a.the_geom,b.the_geom)) FROM tmp_pts_aep a,mnt_lg b where b.the_geom  && 'BOX3D(x( a.the_geom)-val y(a.the_geom)-val
    , x( a.the_geom)+val y(a.the_geom)+val)'::box3d
    &&: operateur "inclus dans"
    BOX3D(x1 y1,) definit un rectangle dont coord sommet haut gauche sont x1 y1 et sommet inf droit x2 y2
    dans la requete j'ai centré ce rectangle par rapport au poin t de la premiere table , val etant une valeur arbitraire que tu fixes poour etre sur d'avoir le point le plus proche de la deuxieme table tout en limitant la recherche aux points les plus proches(c'est clair...)
    de plus l'operateur && utilise les gist index

  3. #3
    Membre éclairé
    Inscrit en
    Décembre 2006
    Messages
    243
    Détails du profil
    Informations forums :
    Inscription : Décembre 2006
    Messages : 243
    Par défaut
    Merci pour cette réponse.

    Effectivement les index risques d'êtres utiles...

    Sinon c'est clair pour la box3D, par contre elle est décrite en 2D est-ce normal ??.

    voila ce que j'execute :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    create table result as select a.*, b."X", b."Y", b."Z" from tmp_pts_aep a,mnt_lg b
    where Distance(a.the_geom,b.the_geom)=(select min(distance(d.the_geom,c.the_geom)) from tmp_pts_aep c, mnt_lg d
    where b.the_geom && 'BOX3D(x(a.the_geom)-30 y(a.the_geom)-30, x(a.the_geom)+30 y(a.the_geom)+30)::box3D');
    mais j'obtiens une erreur :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    ERREUR:  erreur de syntaxe sur ou près de « y »
    LIGNE 3 : where b.the_geom && BOX3D(x(a.the_geom)-30 y(a.the_geom)-30,...
                                                         ^
     
    ********** Erreur **********
     
    ERREUR: erreur de syntaxe sur ou près de « y »
    État SQL :42601
    Caractère : 239
    edit : j'actualise le message (zones [code] au fur et à mesure mais je vais bientôt en poster un nouveau car pour suivre ca risque d'être dur...

  4. #4
    Membre éclairé
    Inscrit en
    Décembre 2006
    Messages
    243
    Détails du profil
    Informations forums :
    Inscription : Décembre 2006
    Messages : 243
    Par défaut
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    create table result as select a.*, b."X", b."Y", b."Z" from tmp_pts_aep a,mnt_lg b
    where Distance(a.the_geom,b.the_geom)=(select min(distance(d.the_geom,c.the_geom)) from tmp_pts_aep c, mnt_lg d
    where d.the_geom && 'BOX3D(x(c.the_geom)-30 y(c.the_geom)-30, x(c.the_geom)+30 y(c.the_geom)+30)'::box3d);
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    ERREUR:  BOX2DFLOAT4 parser - couldnt parse.  It should look like: BOX(xmin ymin,xmax ymax)
     
    ********** Erreur **********
     
    ERREUR: BOX2DFLOAT4 parser - couldnt parse.  It should look like: BOX(xmin ymin,xmax ymax)
    État SQL :XX000

  5. #5
    Membre éclairé
    Inscrit en
    Décembre 2006
    Messages
    243
    Détails du profil
    Informations forums :
    Inscription : Décembre 2006
    Messages : 243
    Par défaut
    Le problème, c'est ce qu'il y a dans les box3D : x(a.the_geom)+30...

    Peut on utiliser une fonction à cette endroit ? Si oui comment ?

    Merci

  6. #6
    Membre éclairé
    Inscrit en
    Décembre 2006
    Messages
    243
    Détails du profil
    Informations forums :
    Inscription : Décembre 2006
    Messages : 243
    Par défaut
    Une solution (simple) :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    where d.the_geom && ST_expand(c.the_geom, 30)
    En attente du résultat..

  7. #7
    Membre éclairé
    Inscrit en
    Décembre 2006
    Messages
    243
    Détails du profil
    Informations forums :
    Inscription : Décembre 2006
    Messages : 243
    Par défaut
    La requête ne m'a retourné que deux lignes : celles pour lesquelles les points d'une couche avaient les coordonnées x et y égales (sur la partie entière) aux points de l'autre couche.
    2 points sur environ 20000 !

  8. #8
    Membre émérite
    Homme Profil pro
    Inscrit en
    Janvier 2006
    Messages
    491
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Corse (Corse)

    Informations forums :
    Inscription : Janvier 2006
    Messages : 491
    Par défaut
    bonjour ,
    peut-etre que 30 est une valeur trop faible essaye une valeur plus importante .
    autrement tu peux essayer lafonction buffer(the_geom, ta_valeur)

  9. #9
    Membre émérite
    Homme Profil pro
    Inscrit en
    Janvier 2006
    Messages
    491
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Corse (Corse)

    Informations forums :
    Inscription : Janvier 2006
    Messages : 491
    Par défaut
    re bonjour , je pense qu'il ya un probleme avec la precision des distances ,on a jamais egalité sauf quand la distance est nulle (=0), je n'arrive pas a faire des arrondis qui permettrai de resoudre ce probleme
    je te propose une autre solution (un peu bizarre...) mais qui devrait marcher
    en gros il faut faire l'egalité sur un champs identifiant de la deuxiieme bas (que j'ai noté id) et dans la sous requete tu ordonne par la distance et tu limite le resultat à la premiere ligne



    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    SELECT a.*, b."Z",b.id FROM tmp_pts_aep a,mnt_lg b
    WHERE b.id=(SELECT  d.id FROM tmp_pts_aep c, mnt_lg d)
    WHERE d.the_geom && buffer(c.the_geom,30) 
    order by distance(a.the_geom,b.the_geom) limit 1)
    ;

  10. #10
    Membre éclairé
    Inscrit en
    Décembre 2006
    Messages
    243
    Détails du profil
    Informations forums :
    Inscription : Décembre 2006
    Messages : 243
    Par défaut
    Merci pour cette réponse,

    Je test des choses dans ce genre la...

  11. #11
    Membre éclairé
    Inscrit en
    Décembre 2006
    Messages
    243
    Détails du profil
    Informations forums :
    Inscription : Décembre 2006
    Messages : 243
    Par défaut
    Bonjour,

    Encore mieux, 1 ligne retournée.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    select a.*, b."X" ,b."Y", b."Z", distance(a.the_geom,b.the_geom)
    from tmp_pts_aep a,mnt_lg1 b
    where b.the_geom && ST_buffer(a.the_geom,300) 
    order by distance asc limit 1;


    Je vais essayer la requête avec lien identifiant...

  12. #12
    Membre éclairé
    Inscrit en
    Décembre 2006
    Messages
    243
    Détails du profil
    Informations forums :
    Inscription : Décembre 2006
    Messages : 243
    Par défaut
    Bonjour,

    J'ai résolu mon problème sans fonctionnalité spatiale (en partie seulement).

    -création d'une table (ID_DIST) avec les identifiants des points des deux tables et la distance qu'il y a entre chacun deux (dans la limite d'un buffer).
    -auto jointure qui retourne l'occurrence ayant la distance minimale pour chaque identifiant d'une des couches.
    -mise à jour d'une des tables en fonction de ID_DIST.

    (L'élévation que je souhaite obtenir sera possible grâce à une macro fournie par le logiciel que j'utilise.)

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. selection par click droit
    Par mecocha dans le forum MFC
    Réponses: 2
    Dernier message: 22/12/2004, 22h35
  2. Selection par clic de souris
    Par bilbonec dans le forum OpenGL
    Réponses: 7
    Dernier message: 16/04/2004, 00h25
  3. Select par mot-clés ou 1er lettre
    Par maadadi dans le forum Langage SQL
    Réponses: 4
    Dernier message: 11/02/2004, 10h50
  4. selection par date
    Par adgabd dans le forum MS SQL Server
    Réponses: 6
    Dernier message: 12/01/2004, 10h28
  5. [TListBox] Selection par défaut
    Par Nuts07 dans le forum Composants VCL
    Réponses: 8
    Dernier message: 12/05/2003, 10h00

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo