3
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

Arc GISに追加されているshapefileをQGISに(またはその逆)

Last updated at Posted at 2019-10-24

Python(一部手作業)で、ArcMap上に追加されているレイヤをQGISに追加する(またはその逆の)手順を、紹介します。

#Ⅰ. ArcGISからQGISへ

##Ⅰ-1. ArcGISのPythonコンソールでの作業
ArcMapのPythonコンソールに以下を実行します。

#mxdの定義
mxd = arcpy.mapping.MapDocument("CURRENT")
#get layer list
lyr = arcpy.mapping.ListLayers(mxd)


#レイヤの保存先パスをリストに格納
lyrPath =[]
for l in lyr:
	if l.isFeatureLayer ==True or l.isRasterLayer ==True:
		lyrPath.append(l.dataSource)
print(lyrPath)

実行結果として、追加されているレイヤの保存先パスがリストで取得される。
通常「arcpy.mapping.ListLayers(mxd)」を実行するとレイヤの一覧を取得できるが、下の図のようにレイヤーがグループになっていると、そのグループもリストに加わってしまい、次の処理でそれぞれのレイヤのパスを取得する段階でエラーになってしまう。
そこで、それぞれのレイヤーのタイプを調べて、ベクターレイヤもしくはラスターレイヤだったらlyrPathという別のリストに入れてあげるということをしています。

image.png

(ここでは、基盤地図情報から用意したshpと10mDEMがリスト化されています。)

下の画像の赤枠で囲った、実行結果の保存パスが表示されている部分(「[」から、「]」まで)を範囲選択してコピーしてください。

image.png

##Ⅰ-2. QGISのPythonコンソールでの作業
今度はQGISのpythonコンソールを立ち上げて、以下のコードの「lyrPath = 」に続いて、先ほどArcGISのPythonコンソールでコピーした内容を貼り付けて実行する。

lyrPath =  コピーした内容を貼り付け

(今回の例の場合だと、こうなる)
image.png

続いて、以下を実行する。

lyrPath.reverse()
for i in lyrPath:
	if i[len(i)-4:] ==".shp":
		iface.addVectorLayer(i,'','ogr')
	else:
	 	iface.addRasterLayer(i,"")

完成!
image.png

iface.addVector(Raster)Layerでそれぞれのデータを追加していますが、そのままリスト順で追加すると、次々にレイヤのトップに追加されて、最終的に、ArcGISでのレイヤの並びとQGISのレイヤの並びが逆になってしまいます。
image.png

そこでlyrPath.reverse()でリストの並びを逆にしてあげています。
次のforループではパスの最後4文字が「.shp」ならベクターで追加、そうでないならラスターとして追加という感じです。
(.shpじゃないベクターデータならどうするかということはとりあえず無視しています)

#Ⅱ. QGISからArcGISへ

##Ⅱ-1. QGISのPythonコンソールでの作業
QGISのPythonコンソールに以下を実行。

lyrlist = QgsProject.instance().mapLayers()

lyrPath =[]
for i in lyrlist:
	lyrPath.append(lyrlist[i].dataProvider().dataSourceUri())

print(lyrPath)

image.png

実行結果として、レイヤーのパスをリストで取得します。
QGISではレイヤ内にグループがあっても、リストには無視してくれます。
しかしこちらで気になるのが、パスを取得すると各レイヤのパスの後ろに「|layerid=0」というのがくっついています。(図中紫枠)
さらにフィルターをかけているレイヤには、後ろに「subset=フィルター式」がはいります(図中青枠)。
これらは、データをロードするときに邪魔になりますが、次の処理で対処するとしてとりあえず気にせず「print(lyrPath)」の実行結果部分(図中赤枠範囲)をコピーします。

##Ⅱ-2. ArcGISのPythonコンソールでの作業

今度はArcGISのpythonコンソールを立ち上げて、以下のコードの「lyrPath = 」に続いて、先ほどQGISのPythonコンソールでコピーしたレイヤのパスの内容を貼り付けて実行する。

lyrPath =  コピーした内容を貼り付け

(今回の場合だと、こうなる)
image.png

続いて以下を実行。

mxd = arcpy.mapping.MapDocument("CURRENT")
df = arcpy.mapping.ListDataFrames(mxd,"")[0]


for i in lyrPath:
	if i.find(".shp") !=-1:
		addlayer = arcpy.mapping.Layer(i[0:i.find(".shp") +4])
		arcpy.mapping.AddLayer(df, addlayer, "BOTTOM")
	else:
		addlayer = arcpy.mapping.Layer(i)
		arcpy.mapping.AddLayer(df, addlayer, "BOTTOM")

実行結果
image.png

無事追加される。

forループでlyrPath内をひとつずつ追加していくのですが、上で書いたとおり、QGISで取得した保存先パスの後ろに「layerid」とか「subset」とか余計な文字が入っています。
そこで、パス内に「.shp」という文字が入っているかを検索し、あればその.shpまでの文字数文までをレイヤーとして読み込む。
ラスターの時にはそういった余計な文字が入っていないので、「.shp」という文字が入っていなければ(=ラスターの時は)、そのままレイヤとして読み込む。
ということです。
追加の際には"BOTTOM"を指定して、レイヤの最下層に追加するようにしてやれば、QGISでのレイヤの並びと同じになります。

#Ⅲ. 課題
kmlやcsv、xyzタイルなどシェープファイルやラスター以外のデータがレイヤとしてあった場合を対応できてないです。

あと、QGISでレイヤのパスを取得するとフィルター情報も拾えるので、Arcに追加するときにそれも反映できればいいですね。

それはまた追々。

3
3
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?