QGIS 1.9のプログラムでメモリレイヤーにフィーチャを作成して追加するにはどうすればよいですか?


13

QGIS 1.8には、MSAccessデータベースからデータを読み取り、一連のメモリレイヤーに追加する作業プラグインがありました。暫定にはいくつかの処理が含まれているため、単にQGISを使用してデータベースから直接読み取ることは選択肢とは思いません。

QGIS 1.8から1.9に移行したいと思います(主に印刷コンポーザの品質が向上したため)。プラグインは新しいAPIでは機能しません。

Google検索で出てきたさまざまな方法を試しました。1つは、http: //www.qgis.org/pyqgis-cookbook/vector.html#memory-provider から以下のコードを変更します。つまり、ジオメトリと属性をデータプロバイダーに追加し、レイヤーを更新して、新しいAPIが機能するようにします少しですが、編集モードに入るまで属性は表示されませんでした(http://hub.qgis.org/issues/3713に似ています)。上記のリンクの返信#1で詳しく説明されている別のアプローチでは、レイヤーと属性を正しく追加しましたが、レイヤーに機能を追加できませんでした。

それは非常に単純なタスクであるべきであるため、ここにいる誰かがこれがどのように行われるべきかの実例を提供できることを期待しています。(PS私はプロのプログラマーではなく、私のコーディングの大部分はかなり粗雑です-どんなガイダンスも歓迎しますが、私の側で無知を許してください)

# 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)

PinPointプラグインをご覧ください。メモリレイヤーに属性を持つ機能を追加し、2.0 APIで動作します。
gsherman

非常に良い、魅力のように動作します。この例を使用して、restfullサービスからのポイントを持つレイヤーを追加しました。QGisは素晴らしいです
ピーターヴェネマ

回答:


8

上記のgshermanのおかげで、PinPointプラグインの例は完璧です。

私が理解しているように、プロセスは次のとおりです。

  1. 構築文字列の属性を使用してレイヤー作成します
  2. 上記のレイヤーをマップレジストリに追加します
  3. そのレイヤーで編集を開始します
  4. 機能を追加して変更をコミットする

ここに、現在動作する私のコードの抜粋があります。

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

Adam Biolettiの回答に基づいて、説明されているプロセスのさらなるテストは、属性や機能の作成などの変更を行う前にメモリレイヤーの編集を開始し、変更をコミットすることが唯一の必須要件であることを示しています。これは、マップレジストリにレイヤーを追加する前に実行できます。

以下は、2.0 APIで動作するクックブックのコードの更新です。

# 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)
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.