1
1

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 3 years have passed since last update.

ArcGIS Pro のマップフレームをポリゴンにする

Posted at

対象読者 ArcGIS Pro で図面を作成する方

実行環境 Windows10, Python 3.7.9

はじめに

図枠の異なる図面を複数作成すると、それぞれの図面の位置関係を把握するための索引図が欲しくなります。

ここでは索引図に使えるような図枠を、ポリゴンタイプのシェープファイルで作成します。

処理としては、ArcGIS Pro レイアウト内のマップフレームからポリゴンデータへの変換になります。

レイアウトやマップフレームの設定の読み取りは、素直に ArcPy を使います。

ポリゴンデータの作成には ArcPy のデータアクセスモジュールを使ってもよいのですが、個人的趣味で pyshp ライブラリを使います。

なお pyshp は、ArcGIS Pro のデフォルト環境にインストールされています。

スクリプトをツールボックスにツールとして登録し、ArcGIS Pro アプリケーションから実行します。

マップの角度について

マップの角度設定が0であれば、マップの範囲の南西端・北東端座標が作成したいポリゴンの四隅座標と一致するので、取得した座標値で四角形のポリゴンを作成することができます。

マップに角度をつけている場合、すなわち北がマップの上を向いてない場合は工夫が必要になります。

ここでは、マップの角度をもとに戻してからマップ範囲の南西端・北東端座標を取得した後、マップの中心座標を中心にマップに設定されていた角度だけ回転させてポリゴンの四隅座標を計算することにしています。

つまり、点Aを中心として点Bをθ度回転する処理を四隅座標に対して行います。

numpy で行列計算を使う方法がスマートですが、行列があまり得意ではないという個人的理由により、以下の式1で計算しています。

二次元直交座標系の点 (x, y) を原点 (0, 0) を中心として反時計回りに角度θ度回転する式です。

x' = xcosθ - ysinθ
y' = x
sinθ + ycosθ

マップ中心 (X, Y) は座標系の原点ではないので、式を変形して使います。

*x' = (x-X)*cosθ - (y-Y)*sinθ + X
y' = (x-X)*sinθ + (y-Y)cosθ + Y

コード

import os.path
import math
import arcpy
import shapefile

# 関数:(x0, y0)を中心として(x_in, y_in)を時計回りにrotation[度]回転した座標を返す
def rotate(x0, y0, rotation, x_in, y_in):
	# 式の定義を考慮して角度の正負を逆転し、ラジアンに変換
	rad = math.radians(-1*rotation)
	# 相対座標
	x = x_in - x0
	y = y_in - y0
	# 回転
	x_out = x*math.cos(rad) - y*math.sin(rad) + x0
	y_out = x*math.sin(rad) + y*math.cos(rad) + y0
	return x_out, y_out

# レイアウト名
lyt_name = arcpy.GetParameterAsText(0)
# マップフレーム名
mpf_name = arcpy.GetParameterAsText(1)
# 出力フォルダ
path_fold = arcpy.GetParameterAsText(2)

# シェープファイル名
path_shp = os.path.join(path_fold, mpf_name + '.shp')
# 座標系定義情報ファイル名
path_prj = os.path.join(path_fold, mpf_name + '.prj')

# ArcGIS Pro で現在開いているプロジェクトを取得
aprx = arcpy.mp.ArcGISProject('CURRENT')
# レイアウトを取得
lyt = aprx.listLayouts(lyt_name)[0]
# マップフレームを取得
mpf = lyt.listElements('MAPFRAME_ELEMENT', mpf_name)[0]
# マップの座標系を取得
sr = mpf.map.spatialReference
# マップフレームの縮尺を取得
scale = mpf.camera.scale
# マップフレームの傾き(反時計回りの回転角[度])を取得
rotation = mpf.camera.heading
# 中心座標を取得
x0 = mpf.camera.X
y0 = mpf.camera.Y

# マップフレームの回転を解除(それぞれの座標軸と辺の方向をそろえるため)
mpf.camera.heading = 0

# マップフレームの範囲を取得
extent = mpf.camera.getExtent()
# 四隅座標を取得
xmin, ymin, xmax, ymax = [float(coord) for coord in str(extent).split(' ')[:4]]

# マップフレームの角度を戻す
mpf.camera.heading = rotation

# ポリゴンの四隅座標を取得
x1, y1 = rotate(x0, y0, rotation, xmin, ymin)
x2, y2 = rotate(x0, y0, rotation, xmin, ymax)
x3, y3 = rotate(x0, y0, rotation, xmax, ymax)
x4, y4 = rotate(x0, y0, rotation, xmax, ymin)

# シェープファイル書き込み
with shapefile.Writer(path_shp) as w:
	w.field('scale', 'N')
	w.field('rotation', 'N')
	w.poly([
		[[x1, y1], [x2, y2], [x3, y3], [x4, y4], [x1, y1]]
	])
	w.record(scale, rotation)

# プロジェクトファイル作成
with open(path_prj, 'w') as f:
	# 座標系を定義するパラメータの文字列を取得
	text = sr.exportToString()
	f.write(text)

ツールボックスへの実装

ツールボックスに上述のスクリプトを追加します。
パラメータの定義.PNG

第2パラメータにレイアウトとの依存関係をもたせたマップフレームを指定したかったのですが、該当しそうなデータタイプが見当たらなかったため、String としました。

実行

マップを30度(反時計回り)回転させたマップフレームをレイアウトに配置し、ツールを実行します。
レイアウト_30deg.jpg

結果

マップフレームで表示している範囲を示すのポリゴンデータが作成されました。
マップ.jpg
テーブルには縮尺と角度が格納されています。
テーブル.PNG

最後に

マップフレームをポリゴンに変換しました。

アプリケーションに同様のツールが標準で組み込まれていても良さそうなものですが、どうも無いようです。

なお ArcGIS Pro の Python リファレンス はほとんど英語ですが、マップやレイアウトをクラスとして扱えるので、英語が分からなくてもそれらの設定値の取得は結構簡単です。

  1. フリー百科事典『ウィキペディア(Wikipedia)』 回転 (数学)

1
1
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
1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?