J'ai posé cette question plusieurs fois sur stackoverflow et irc entre #qgis et #postgis et j'ai également essayé de le coder ou de le mettre en œuvre moi-même dans postgis sans véritable réponse.
En utilisant la programmation (de préférence en python), j'aimerais tracer une ligne d'une couche de points à sa projection sur la ligne la plus proche d'une couche de lignes ou de polygones.
À l'heure actuelle, la plupart de mes données sont sous la forme ESRI et dans les formats postgis; Cependant, je préférerais ne pas utiliser une solution postgis car je suis principalement un utilisateur de shp + qgis.
Une solution idéale consisterait à implémenter GDAL / OGR avec des bibliothèques python ou similaires.
- Utilisation des bibliothèques GDAL / OGR par où dois-je commencer? serait-il possible de donner un plan de solution?
- Puis-je utiliser NetworkX pour effectuer l'analyse du voisin le plus proche?
- Est-ce réellement possible?
Si c'est plus facile, les points pourraient se connecter au point final du segment au lieu d'un point projeté
Réponses:
Cette question s'est avérée un peu plus délicate que ce que je pensais être la bonne. Il existe de nombreuses implémentations de la distance la plus courte elle-même, telles que la distance fournie par Shapely (à partir de GEOS). Peu de solutions fournissent le point d'intersection lui-même, mais seulement la distance.
Ma première tentative a tamponné le point en fonction de la distance entre le point et le polygone et a recherché des intersections, mais les erreurs d'arrondi l'empêchent de donner une réponse exacte.
Voici une solution complète utilisant Shapely, basée sur ces équations :
Pour la postérité, il semblerait que cette extension ArcView résoud assez bien ce problème, dommage que ce soit sur une plate-forme morte écrite dans une langue morte ...
la source
pairs
c'est algorithmiquement O (n) ou quelque chose. @eprand solution peut-être modifié pour utiliser KNN mais je réussi à vivre sans PostGIS jusqu'à présent ...Une réponse PostGIS (pour multilinestring, si linestring, supprime la fonction st_geometryn)
la source
C'est un peu vieux, mais je cherchais des solutions à ce problème aujourd'hui (point -> ligne). La solution la plus simple que j'ai rencontrée pour ce problème est la suivante:
la source
Si je vous ai bien compris, les fonctionnalités que vous demandez sont intégrées à PostGIS.
Pour obtenir un point projeté sur une ligne, vous pouvez utiliser ST_Closestpoint (sur PostGIS 1.5).
Vous trouverez quelques conseils sur son utilisation à l' adresse suivante : http://blog.jordogskog.no/2010/02/07/how-to-use-the-new-distance-related-functions-in-postgis-part1/
Il est également possible de trouver le point le plus proche d'un polygone par exemple.
Si vous voulez que la ligne entre les deux points les plus proches sur les deux géométries, vous pouvez utiliser ST_Shortestline. ST_Closestpoint est le premier point de ST_Shortestline
La longueur de ST_Shortestline entre deux géométries est la même que ST_Distance entre les géométries.
la source
Voir le commentaire ci-dessous sur la façon dont ma réponse ne doit pas être considérée comme une solution fiable ... Je vais laisser cet article original ici pour que les autres puissent examiner le problème.
Si je comprends la question, cette procédure générale devrait fonctionner.
Pour trouver le chemin le plus court entre un point (défini par x, y ou x, y, z) et une polyine (définie par un ensemble de connexions constitué de x, y ou x, y, z) dans l'espace euclidien:
1) À partir d'un point défini par l'utilisateur (je l'appellerai pt0), trouvez le sommet le plus proche de la polyligne (pt1). OGRinfo peut interroger les sommets d'une polyligne, puis des calculs de distance peuvent être effectués via des méthodes standard. Par exemple, parcourez une distance calculée comme suit: distance_in_radians = 2 * math.asin (math.sqrt (math.pow ((math.sin ((pt.serveur), (pt0_radians-ptx_radians) / 2)), 2)), 2) + math.cos (pt0_radians) * math.cos (ptx_radians) * math.pow ((math.sin ((pt0_radians-ptx_radians) / 2)), 2)))
2) Enregistrer la valeur de distance minimale associée (d1) et (pt1)
3) examinez les deux segments qui s’éloignent de pt1 (dans la chaîne ogrinfo, ce seront les sommets antérieurs et suivants). Enregistrez ces sommets (n2 et n3).
4) créer la formule y = mx + b pour chaque segment
5) Reliez votre point (pt0) à la perpendiculaire pour chacune de ces deux formules
6) Calculer la distance et les intersections (d2 et d3; pt2, pt3)
7) Comparez les trois distances (d1, d2, d3) pour la plus courte. Votre pt0 vers le nœud associé (pt1, pt2 ou pt3) est le lien le plus court.
C'est un courant de conscience qui répond - j'espère que ma vision mentale du problème et de la solution me convient.
la source
Voici un script python pour QGIS> 2.0 élaboré à partir des astuces et solutions données ci-dessus. Cela fonctionne très bien pour un nombre raisonnable de points et de lignes. Mais je ne l'ai pas essayé avec une énorme quantité d'objets.
Bien sûr, il fallait copier en mode inactif ou toute autre solution moins "solution pythonique" et l'enregistrer sous "le plus proche.point.py".
Dans la boîte à outils QGIS, accédez au script, aux outils, ajoutez un script, puis choisissez-le.
!!! ATTENTION !!! Faites attention au fait que certains points "étranges" / mal projetés peuvent être produits à cause de cette commande de ligne:
La
counterSelec
valeur qu'il contient définit combien de plus proches voisins sont retournés. En fait, chaque point doit être projeté à la distance la plus courte possible pour chaque objet de la ligne; et la distance minimale trouvée donnerait la bonne ligne et le point projeté comme voisins les plus proches que nous cherchons. Afin de réduire le temps de boucle, la commande Voisin la plus proche est utilisée. Choisir unecounterSelec
valeur réduite à 1 renverra le "premier" objet rencontré (sa boîte englobante plus exactement) et il se peut que ce ne soit pas le bon. Différents objets de taille de ligne peuvent obliger à choisir peuvent être 3 ou 5, voire des objets plus proches afin de déterminer la distance la plus courte. Plus la valeur est élevée, plus cela prend de temps. Avec des centaines de points et de lignes, il commence à devenir très lent avec 3 ou 5 voisins les plus proches, avec des milliers, il peut être déréglé par ces valeurs.la source
En fonction de vos intérêts et de votre cas d'utilisation, il pourrait être utile d'examiner les "algorithmes de correspondance de carte". Par exemple, il existe un projet RoadMatcher sur le wiki OSM: http://wiki.openstreetmap.org/wiki/Roadmatcher .
la source