Wie kann ich programmgesteuert Features in einer Speicherebene in QGIS 1.9 erstellen und hinzufügen?


13

Ich hatte ein funktionierendes Plugin in QGIS 1.8, mit dem Daten aus einer MSAccess-Datenbank gelesen und einer Reihe von Speicherebenen hinzugefügt wurden. In der Zwischenzeit ist eine gewisse Verarbeitung erforderlich, daher halte ich es nicht für eine Option, einfach QGIS zu verwenden, um direkt aus der Datenbank zu lesen.

Ich würde gerne von QGIS 1.8 auf 1.9 umsteigen (hauptsächlich wegen der verbesserten Qualität des Print Composers). Das Plugin funktioniert nicht mit der neuen API.

Ich habe eine Vielzahl von Methoden ausprobiert, die bei der Google-Suche zum Einsatz kamen. Erstens : Ändern Sie den folgenden Code - von http://www.qgis.org/pyqgis-cookbook/vector.html#memory-provider - um Geometrie und Attribute zum Datenprovider hinzuzufügen und dann den Layer zu aktualisieren - um ihn an die neue API anzupassen ein wenig, aber die Attribute waren nicht sichtbar, bis ich vollständig in den Bearbeitungsmodus eingetreten bin (ähnlich wie http://hub.qgis.org/issues/3713 ). Bei einem alternativen Ansatz, der in Antwort 1 des obigen Links beschrieben wird, wurden die Ebene und die Attribute korrekt hinzugefügt, aber der Ebene konnten keine Features hinzugefügt werden.

Angesichts der Tatsache, dass es eine ziemlich einfache Aufgabe sein sollte, hoffe ich, dass jemand hier ein funktionierendes Beispiel dafür liefern kann, wie dies getan werden sollte. (PS: Ich bin kein professioneller Programmierer und die meisten meiner Codierungen sind ziemlich grob. Ich begrüße jede Anleitung, bitte Sie jedoch, meinerseits etwas Unwissen zu entschuldigen.)

# Receivers = a list of lists returned from a database query

# create layer
vl = QgsVectorLayer("Point", item, "memory")
pr = vl.dataProvider()

# add fields
pr.addAttributes( [ QgsField("Rec_No", QVariant.Int), QgsField("Include",  QVariant.String), QgsField("Label",  QVariant.String), QgsField("X", QVariant.Double),
                    QgsField("Y", QVariant.Double), QgsField("Z", QVariant.Double), QgsField("Height", QVariant.Double),
                    QgsField("Project_Re", QVariant.String), QgsField("NCA", QVariant.String),
                    QgsField("DayCrit", QVariant.Int), QgsField("EveCrit", QVariant.Int), QgsField("NightCrit", QVariant.Int) ] )

for i in range(len(Receivers)):          
  # add a feature
  fet = QgsFeature()
  X = Receivers[i][3]
  Y = Receivers[i][4]
  fet.setGeometry( QgsGeometry.fromPoint(QgsPoint(X,Y)) )

  # Details = a list of results returned from a database query specific to each result in 'Receivers'

  if Receivers[i][3] != 0:
    Include = 'Yes'
  else:
    Include = 'No'

  fet.setAttributeMap( { 0 : QVariant(Receivers[i][0]), 1 : QVariant(Include), 2 : QVariant(Receivers[i][2]),
                         3 : QVariant(Receivers[i][3]), 4 : QVariant(Receivers[i][4]), 5 : QVariant(Receivers[i][5]), 6 : QVariant(Receivers[i][6]),
                         7 : QVariant(Details[0]), 8 : QVariant(Details[1]), 9 : QVariant(Details[2]), 10 : QVariant(Details[3]), 11 : QVariant(Details[4]) } )
  pr.addFeatures( [ fet ] )

# add a style
vl.loadNamedStyle('C:/OSGeo4W/apps/qgis/python/plugins/Gopher2QGIS/styles/Receiver_Style.qml')

# update layer's extent when new features have been added
# because change of extent in provider is not propagated to the layer
vl.commitChanges()
vl.updateExtents()
vl.updateFieldMap()

QgsMapLayerRegistry.instance().addMapLayer(vl)

Schauen Sie sich das PinPoint-Plugin an. Es fügt einer Speicherebene Features mit Attributen hinzu und funktioniert mit der 2.0-API.
Gsherman

Sehr gut, wirkt wie ein Zauber. In diesem Beispiel habe ich einen Layer mit Punkten aus einem Restfull-Service hinzugefügt. QGis ist großartig
Peter Venema

Antworten:


8

Dank gsherman oben ist das PinPoint-Plugin-Beispiel perfekt.

Wie ich es verstehe, ist der Prozess:

  1. Erstellen Sie den Layer mit den Attributen in der Konstruktionszeichenfolge
  2. Fügen Sie den Layer zur Kartenregistrierung hinzu
  3. Beginnen Sie mit der Bearbeitung auf dieser Ebene
  4. Fügen Sie Features hinzu und übernehmen Sie die Änderungen

Hier ist ein Auszug aus meinem Code, der jetzt funktioniert.

layer =  QgsVectorLayer(
          "Point?field=Rec_No:integer&field=Include:string(120)&field=Label:string(120)&field=X:double&field=Y:double&field=Z:double&field=Height:double&field=Project_Re:string(120)&field=NCA:string(120)&field=DayCrit:integer&field=EveCrit:integer&field=NightCrit:integer",
          item,
          "memory")
QgsMapLayerRegistry.instance().addMapLayer(layer)

# Receivers = as in the above example 'Receivers' is a list of results
for i in range(len(Receivers)):

  # add a feature
  feature = QgsFeature()

  X = Receivers[i][3]
  Y = Receivers[i][4]
  feature.setGeometry( QgsGeometry.fromPoint(QgsPoint(X,Y)) )

  # Details = as in the above example 'Details' is a list of results

  if Receivers[i][1] != 0:
    Include = 'Yes'
  else:
    Include = 'No'

  values = [ QVariant(Receivers[i][0]), QVariant(Include), QVariant(Receivers[i][2]),
                         QVariant(Receivers[i][3]), QVariant(Receivers[i][4]), QVariant(Receivers[i][5]), QVariant(Receivers[i][6]),
                         QVariant(Details[0]), QVariant(Details[1]), QVariant(Details[2]), QVariant(Details[3]), QVariant(Details[4]) ]

  feature.setAttributes(values)
  layer.startEditing()
  layer.addFeature(feature, True)
  layer.commitChanges()

6

Basierend auf der Antwort von Adam Bioletti zeigen weitere Tests des beschriebenen Prozesses, dass die einzige wesentliche Anforderung darin besteht, mit der Bearbeitung der Speicherebene zu beginnen, bevor Änderungen vorgenommen werden, z. Dies kann vor dem Hinzufügen des Layers zur Zuordnungsregistrierung erfolgen.

Hier ist ein Update des Cookbook-Codes, der mit der 2.0-API funktioniert:

# create layer
vl = QgsVectorLayer("Point", "temporary_points", "memory")
pr = vl.dataProvider()

# changes are only possible when editing the layer
vl.startEditing()
# add fields
pr.addAttributes([QgsField("name", QVariant.String),QgsField("age", QVariant.Int),QgsField("size", QVariant.Double)])

# add a feature
fet = QgsFeature()
fet.setGeometry(QgsGeometry.fromPoint(QgsPoint(10,10)))
fet.setAttributes(["Johny", 2, 0.3])
pr.addFeatures([fet])

# commit to stop editing the layer
vl.commitChanges()

# update layer's extent when new features have been added
# because change of extent in provider is not propagated to the layer
vl.updateExtents()

# add layer to the legend
QgsMapLayerRegistry.instance().addMapLayer(vl)
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.