banniere

Le portail francophone de la géomatique


Toujours pas inscrit ? Mot de passe oublié ?
Nom d'utilisateur    Mot de passe              Toujours pas inscrit ?   Mot de passe oublié ?

#1 Wed 28 June 2017 12:38

hotegbe
Participant occasionnel
Date d'inscription: 28 Jun 2017
Messages: 32

QGIS / Pyqgis: Algorithme De Dijkstra

Bonjour, je sollicite votre aide par rapport à l'API pyqgis.
étant nouveau utilisateur des SIG je souhaiterais réaliser une opération.

Il s'agit pour moi de recherher le plus court chemin dans un graphe en utilisant l'agorithme de DIJKSTRA.

Le code de la doc de qgis après quelques petites adaptations marche bien sauf que je ne récupère rien à la fin si ce n'est un tracé graphique. Je souhaiterais après léxécution récupérer le chemin le plus court retrouvé (le résultat) sous forme d'entité que j'insère dans une table et ainsi de suite pour éventuellement d'autres chemins plus courts que je calculerai.

from PyQt4.QtCore import *
from PyQt4.QtGui import *

from qgis.core import *
from qgis.gui import *
from qgis.networkanalysis import *

vl = qgis.utils.iface.mapCanvas().currentLayer()
director = QgsLineVectorLayerDirector(vl, -1, '', '', '', 3)
properter = QgsDistanceArcProperter()
director.addProperter(properter)
crs = qgis.utils.iface.mapCanvas().mapRenderer().destinationCrs()
builder = QgsGraphBuilder(crs)

pStart = QgsPoint(-0.835953, 0.15679)
pStop = QgsPoint(-1.1027, 0.699986)

tiedPoints = director.makeGraph(builder, [pStart, pStop])
graph = builder.graph()

tStart = tiedPoints[0]
tStop = tiedPoints[1]

idStart = graph.findVertex(tStart)
idStop = graph.findVertex(tStop)

(tree, cost) = QgsGraphAnalyzer.dijkstra(graph, idStart, 0)

if tree[idStop] == -1:
  print "Path not found"
else:
  p = []
  curPos = idStop
  while curPos != idStart:
    p.append(graph.vertex(graph.arc(tree[curPos]).inVertex()).point())
    curPos = graph.arc(tree[curPos]).outVertex();

  p.append(tStart)

  rb = QgsRubberBand(qgis.utils.iface.mapCanvas())
  rb.setColor(Qt.red)

  for pnt in p:
    rb.addPoint(pnt).[/b]

Pourriez vous m'aider svp à améliorer ce code ?
Merci

Hors ligne

 

#2 Wed 28 June 2017 15:21

Sylvain PIERRE
Participant assidu
Lieu: Strasbourg
Date d'inscription: 6 Sep 2005
Messages: 170

Re: QGIS / Pyqgis: Algorithme De Dijkstra

Bonjour,

Il vous manque quelque chose à la fin du traitement.
Le résultat est en l'état uniquement stockée dans la QgsRubberBand qui n'est qu'une couche graphique recevant les objets créés lorsqu'on dessine des lignes ou des polygones.
Il faut donc transformer ces objets graphiques en objets géographiques

Code:

        geom = rb .asGeometry()
        polyline = geom.asGeometryCollection()[0].asPolyline()

Il vous faudra également "pousser" ces objets géographiques dans une layer, voir ici: http://docs.qgis.org/testing/en/docs/py … ector.html

Voilà qq pistes pour avancer

Sylvain

Hors ligne

 

#3 Wed 28 June 2017 15:52

hotegbe
Participant occasionnel
Date d'inscription: 28 Jun 2017
Messages: 32

Re: QGIS / Pyqgis: Algorithme De Dijkstra

Bonjour,
Merci pour votre aide.

Cependant en rajoutant les deux lignes de code à mon script, je n'ai pas d'objet géographique créé. je n'ai pas non plus d'erreur.
J'ai juste rajouté les deux lignes que vous m'avez communiquées à la fin du script.

A votre avis pourquoi ça coince encore?

Hors ligne

 

#4 Wed 28 June 2017 16:20

Sylvain PIERRE
Participant assidu
Lieu: Strasbourg
Date d'inscription: 6 Sep 2005
Messages: 170

Re: QGIS / Pyqgis: Algorithme De Dijkstra

La réponse est à rechercher ans la seconde partie de mon message, il vous faut manipuler de nouvelles classes de l'API PyQgis:
QgsVectorLayer entre autre ainsi que certaines de ses sous-classes, ainsi que QgsMapLayerRegistry

Code:

vl = QgsVectorLayer("MultiLineString?crs=epsg:3948", "temporary_line", "memory")
pr = vl.dataProvider()
pr.addFeatures([polyline])
if vl.isValid():
     QgsMapLayerRegistry.instance().addMapLayer(vl)

Attention de spécifier le code epsg correspondant à votre projection courante

Le code est fourni sans garantie , mais dans l'esprit c'est ce qu'il faut faire

Hors ligne

 

#5 Thu 29 June 2017 10:23

hotegbe
Participant occasionnel
Date d'inscription: 28 Jun 2017
Messages: 32

Re: QGIS / Pyqgis: Algorithme De Dijkstra

Je vous remercie pour votre réponse.  après quelques modifications j'obtiens un résultat qui m'a permis de bien avancer dans mon travail. Cependant,
J'ai une erreur python qui persiste "qgis dumpé" après exécution de mon code plusieurs fois.
J'ai désinstallé et changé la version de mon QGIS mais rien n'y fait; j'ai même changé d'ordinateur.

Comment régler ce souci svp?
Merci

Hors ligne

 

#6 Thu 29 June 2017 10:52

Sylvain PIERRE
Participant assidu
Lieu: Strasbourg
Date d'inscription: 6 Sep 2005
Messages: 170

Re: QGIS / Pyqgis: Algorithme De Dijkstra

A mon avis c'est le recours à une layer de type memory
a chaque fois que vous lancer le script, la memory layer est créée
Il faudrait travailler sur une couche physique ans laquelle vous enregistrerez vos objets

1 créer un shape avec geometrie ligne
2 modifier le code

Code:

inLayer = 'le_nom_de_mon_shape'
for layer in QgsMapLayerRegistry.instance().mapLayers().values():
    if inLayer in layer.name():
       vl = layer
       pr = vl.dataProvider()
       pr.addFeatures([polyline])

Hors ligne

 

#7 Thu 29 June 2017 13:57

hotegbe
Participant occasionnel
Date d'inscription: 28 Jun 2017
Messages: 32

Re: QGIS / Pyqgis: Algorithme De Dijkstra

J'ai pu avancer j'obtiens bien une couche dans laquelle une entité est créée.
Cependant le chemin le plus court recherché ne passe plus par tous les points intermédiaires entre le point de départ et d'arrivée.

Mon code est le suivant









geom = rb .asGeometry()
polyline = geom.asGeometryCollection()[0].asPolyline()


v_layer = QgsVectorLayer("LineString", "cable", "memory")
pr = v_layer.dataProvider()

seg = QgsFeature()

seg.setGeometry(QgsGeometry.fromPolyline([polyline]))

pr.addFeatures( [seg] )

v_layer.updateExtents()

QgsMapLayerRegistry.instance().addMapLayers([v_layer]).




Comment puis je imposer la géométrie de polyline à l'entité que je créee dans ma table??

Merci

Hors ligne

 

#8 Thu 29 June 2017 14:25

Sylvain PIERRE
Participant assidu
Lieu: Strasbourg
Date d'inscription: 6 Sep 2005
Messages: 170

Re: QGIS / Pyqgis: Algorithme De Dijkstra

Peut-être remplacer

Code:

geom = rb .asGeometry()
polyline = geom.asGeometryCollection()[0].asPolyline()

par

Code:

polyline = QgsGeometry( rb.asGeometry() )

En tous cas creuser autour de la construction de cet objet polyline

Hors ligne

 

#9 Thu 29 June 2017 14:47

hotegbe
Participant occasionnel
Date d'inscription: 28 Jun 2017
Messages: 32

Re: QGIS / Pyqgis: Algorithme De Dijkstra

Pour ça il n'y a aucun souci. c'est plutôt au niveau de la création du feature (entité) dans ma couche.
Mon souci est au niveau de la géométrie du feature que je vais insérer dans la couche que je crée. En renseignant directement tStart et tStop dans seg.setGeometry j'obtiens un tracé de ligne droite entre ces deux points et une insertion de ce tracé comme entité dans ma couche.
Du coup je n'arrive pas à imposer la géométrie de mon polyline à cette nouvelle que je crée comme ci bas.


seg = QgsFeature()
seg.setGeometry(QgsGeometry.fromPolyline([tStart ,tStop]))



Mon but est de garder la géométrie de polyline dans le seg.setGeometry.


Je ne sais pas si je suis plus clair.
Merci


voici le code plus détaillé











  for pnt in p:
    rb.addPoint(pnt)
   
polyline = QgsGeometry( rb.asGeometry() )


v_layer = QgsVectorLayer("LineString", "cable", "memory")
pr = v_layer.dataProvider()
seg = QgsFeature()
seg.setGeometry(QgsGeometry.fromPolyline([tStart ,tStop]))
pr.addFeatures( [seg] )
v_layer.updateExtents()
QgsMapLayerRegistry.instance().addMapLayers([v_layer])



Hors ligne

 

#10 Thu 29 June 2017 15:05

Sylvain PIERRE
Participant assidu
Lieu: Strasbourg
Date d'inscription: 6 Sep 2005
Messages: 170

Re: QGIS / Pyqgis: Algorithme De Dijkstra

Vous ne mettez que le point de départ et celui d'arrivée
Il faudrait remplacer dans

Code:

seg.setGeometry(QgsGeometry.fromPolyline([tStart ,tStop]))

par

Code:

seg.setGeometry(QgsGeometry.fromPolyline([polyline ]))

Hors ligne

 

#11 Thu 29 June 2017 15:15

hotegbe
Participant occasionnel
Date d'inscription: 28 Jun 2017
Messages: 32

Re: QGIS / Pyqgis: Algorithme De Dijkstra

Voici l'erreur que je récupère en faisant  seg.setGeometry(QgsGeometry.fromPolyline([polyline ]))



Traceback (most recent call last):
  File "<input>", line 1, in <module>
  File "c:/users/shount~1/appdata/local/temp/tmplczshv.py", line 53, in <module>
    seg.setGeometry(QgsGeometry.fromPolyline([polyline ]))
TypeError: QgsGeometry.fromPolyline(list-of-QgsPoint): argument 1 has unexpected type 'list'

Hors ligne

 

#12 Thu 29 June 2017 16:13

Sylvain PIERRE
Participant assidu
Lieu: Strasbourg
Date d'inscription: 6 Sep 2005
Messages: 170

Re: QGIS / Pyqgis: Algorithme De Dijkstra

pourquoi ne pas avoir conservé le code suivant:

Code:

       pr.addFeatures([polyline])

?

Hors ligne

 

#13 Thu 29 June 2017 16:18

hotegbe
Participant occasionnel
Date d'inscription: 28 Jun 2017
Messages: 32

Re: QGIS / Pyqgis: Algorithme De Dijkstra

je récupère toujours la meme erreur en essayant de passer polyline en paramètre comme ceci :


pr.addFeatures([polyline])
seg.setGeometry(QgsGeometry.fromPolyline([polyline]))

Hors ligne

 

#14 Thu 29 June 2017 16:30

Sylvain PIERRE
Participant assidu
Lieu: Strasbourg
Date d'inscription: 6 Sep 2005
Messages: 170

Re: QGIS / Pyqgis: Algorithme De Dijkstra

Normalement pas besoin de la seconde ligne

Hors ligne

 

#15 Thu 29 June 2017 16:32

hotegbe
Participant occasionnel
Date d'inscription: 28 Jun 2017
Messages: 32

Re: QGIS / Pyqgis: Algorithme De Dijkstra

C'est pareil polyline n'est pas accepté en tant qu'argument ni par addfeatures() ni par setGeometry comme écrit plus haut.
même erreur

Hors ligne

 

#16 Thu 29 June 2017 16:45

dominique.lys
Participant assidu
Date d'inscription: 5 Oct 2006
Messages: 473
Site web

Re: QGIS / Pyqgis: Algorithme De Dijkstra

Peut-être

Code:

poly = QgsPolyline(p) #avec p la liste de QgsPoint 
geom = QgsGeometry.fromPolyline(poly)
feat = QgsFeature()
feat.setGeometry(geom)
pr.addFeature(seg)

Hors ligne

 

#17 Thu 29 June 2017 16:52

Sylvain PIERRE
Participant assidu
Lieu: Strasbourg
Date d'inscription: 6 Sep 2005
Messages: 170

Re: QGIS / Pyqgis: Algorithme De Dijkstra

Il faut alors gérer en même temps un objet rubberband et un objet liste de points qgis

Code:

else:
  p = []
  coordinatePairs = []
  curPos = idStop
  while curPos != idStart:
    pnt = graph.vertex(graph.arc(tree[curPos]).inVertex()).point()
    print pnt
    p.append(pnt)
   coordinatePairs.append(QgsPoint(pnt))
    curPos = graph.arc(tree[curPos]).outVertex()

....
seg.setGeometry(QgsGeometry.fromPolyline([coordinatePairs]))

par contre il faudrait voir ce que donne le print pnt pour être certain qu'il renvoie bien un couple X,Y

Dernière modification par Sylvain PIERRE (Thu 29 June 2017 16:56)

Hors ligne

 

#18 Thu 29 June 2017 17:05

hotegbe
Participant occasionnel
Date d'inscription: 28 Jun 2017
Messages: 32

Re: QGIS / Pyqgis: Algorithme De Dijkstra

la liste de QgsPoint  est constituée des coordonnées des points de départ et d'arrivé du tracé.
avec cela je récupère l'erreur suivante :

Traceback (most recent call last):
  File "<input>", line 1, in <module>
  File "c:/users/shount~1/appdata/local/temp/tmp9zubp9.py", line 59, in <module>
    poly = QgsPolyline(p)
NameError: name 'QgsPolyline' is not defined

Hors ligne

 

#19 Thu 29 June 2017 17:20

Sylvain PIERRE
Participant assidu
Lieu: Strasbourg
Date d'inscription: 6 Sep 2005
Messages: 170

Re: QGIS / Pyqgis: Algorithme De Dijkstra

Heu là il faudrait calmement repartir de l'ensemble du code...

Hors ligne

 

#20 Thu 29 June 2017 17:21

hotegbe
Participant occasionnel
Date d'inscription: 28 Jun 2017
Messages: 32

Re: QGIS / Pyqgis: Algorithme De Dijkstra

seg.setGeometry(QgsGeometry.fromPolyline([coordinatePairs]))
TypeError: QgsGeometry.fromPolyline(list-of-QgsPoint): argument 1 has unexpected type 'list'



l'array coordinatepairs n'est pas accepté comme argument non plus.
le print pnt renvoie bien un couple de (X,Y ) en boucle

Hors ligne

 

#21 Thu 29 June 2017 21:27

JD
Moderateur
Date d'inscription: 8 Aug 2013
Messages: 726

Re: QGIS / Pyqgis: Algorithme De Dijkstra

Bonsoir,

vous pouvez passer par la construction de la polyligne
ou alors vous supprimez les ligne entre --- et vous décommentez les lignes en commentaires.


Code:

#  rb = QgsRubberBand(qgis.utils.iface.mapCanvas())
#  rb.setColor(Qt.red)
#-----
geom = QgsGeometry.fromPolyline(p)
#-----

#  for pnt in p:
#    rb.addPoint(pnt)

v_layer = QgsVectorLayer("LineString", "cable", "memory")
QgsMapLayerRegistry.instance().addMapLayers([v_layer])
pr = v_layer.dataProvider()
v_layer.startEditing()
seg = QgsFeature()
#geom = rb.asGeometry()
seg.setGeometry(geom)
pr.addFeatures( [seg] )
v_layer.commitChanges()

Cordialement,

Dernière modification par lejedi76 (Thu 29 June 2017 21:34)

Hors ligne

 

#22 Fri 30 June 2017 08:29

hotegbe
Participant occasionnel
Date d'inscription: 28 Jun 2017
Messages: 32

Re: QGIS / Pyqgis: Algorithme De Dijkstra

Bonjour lejedi76, votre solution marche bien et je vous en remercie.
Maintenant je voudrais savoir comment automatiser les points de départ et d'arrivée de mon tracé afin d'éviter de fixer   


pStart = QgsPoint(4.818554,45.832345)
pStop = QgsPoint(4.828114,45.8332884)


Mais juste en prenant pour paramètre les coordonnées d'un x et d'un y par simple clic dans le canevas.

Merci

Hors ligne

 

#23 Fri 30 June 2017 09:25

Sylvain PIERRE
Participant assidu
Lieu: Strasbourg
Date d'inscription: 6 Sep 2005
Messages: 170

Re: QGIS / Pyqgis: Algorithme De Dijkstra

Script + interaction avec l'interface = plugin

Je crois que vous allez devoir plonger un peu plus profondément dans le développement avec l'API PyQgis.
Cela ouvre des possibilités vraiment intéressantes

Sylvain

Hors ligne

 

#24 Fri 30 June 2017 09:42

hotegbe
Participant occasionnel
Date d'inscription: 28 Jun 2017
Messages: 32

Re: QGIS / Pyqgis: Algorithme De Dijkstra

Merci à vous. je commence à creuser

Hors ligne

 

#25 Fri 30 June 2017 10:28

hotegbe
Participant occasionnel
Date d'inscription: 28 Jun 2017
Messages: 32

Re: QGIS / Pyqgis: Algorithme De Dijkstra

par rapport au résultat, j'obtiens à chaque fois la création d'un nouveau layer avec une nouvelle entité que je crée ce qui n'est pas mon objectif.
Il s'agit plutôt de mettre toutes les entités créées dans le même layer avec les champs qui sont déjà prédéfinis plitôt que de recréer à chaque fois un nouveau layer.

Je mets ci joint le code

Code:

 from PyQt4.QtCore import *
from PyQt4.QtGui import *
from qgis.core import *
from qgis.gui import *
from qgis.networkanalysis import *

vl = qgis.utils.iface.mapCanvas().currentLayer()
director = QgsLineVectorLayerDirector(vl, -1, '', '', '', 3)
properter = QgsDistanceArcProperter()
director.addProperter(properter)
crs = qgis.utils.iface.mapCanvas().mapRenderer().destinationCrs()
builder = QgsGraphBuilder(crs)

pStart = QgsPoint(4.83382,45.83818)
pStop = QgsPoint(4.841678,45.834846)
tiedPoints = director.makeGraph(builder, [pStart, pStop])
graph = builder.graph()

tStart = tiedPoints[0]
tStop = tiedPoints[1]

idStart = graph.findVertex(tStart)
idStop = graph.findVertex(tStop)

(tree, cost) = QgsGraphAnalyzer.dijkstra(graph, idStart, 0)

if tree[idStop] == -1:
  print "Path not found"
else:
  p = []
  curPos = idStop
  while curPos != idStart:
    pnt = graph.vertex(graph.arc(tree[curPos]).inVertex()).point()

    p.append(pnt)
   
    curPos = graph.arc(tree[curPos]).outVertex()

  p.append(tStart)

  rb = QgsRubberBand(qgis.utils.iface.mapCanvas())
  rb.setColor(Qt.red)
  
  
geom = QgsGeometry.fromPolyline(p)

for pnt in p:
    rb.addPoint(pnt)
    
    
v_layer = QgsVectorLayer("LineString", "cable", "memory")
QgsMapLayerRegistry.instance().addMapLayers([v_layer])
pr = v_layer.dataProvider()
v_layer.startEditing()
v_layer.addAttribute(QgsField("id", QVariant.String))
v_layer.addAttribute(QgsField("longueur", QVariant.String))
v_layer.addAttribute(QgsField("type", QVariant.String))
v_layer.addAttribute(QgsField("diametre", QVariant.String))
seg = QgsFeature()
geom = rb.asGeometry()
seg.setGeometry(geom)
pr.addFeatures( [seg] )
v_layer.commitChanges()

Hors ligne

 

Pied de page des forums

Powered by FluxBB