はじめに
いまは公開停止となっているiOSアプリfeildaceess風に、写真を上部に並べて、写真と写真撮影位置と線で結んで表示するQGISスタイルとモデルを作ったので紹介します。
feildaccess2(iOSアプリ)のスクリーンショット(ちなみに場所は愛媛県の滑床渓谷です)
QGISスタイル、モデルファイルの置き場所
使い方の流れ
ジオタグ付き写真の写真を用意する
GPS付カメラで写真を撮るなどします
モデルの読み込み
QGISを起動し、プロセッシングツールボックスの歯車のアイコンから「ツールボックスにモデル」を追加を選択し、上記に置いている2つの.model3ファイルを指定します。
そのあと、PhotoView_Inport を右クリック→「出力のためのレンダリングスタイルを編集」→「PhotoView.qml」を設定します。
プロジェクトのCRSに投影座標系(平面直角座標)を設定
メニューのプロジェクト→プロパティ→座標参照系 を開き、写真を撮影した地域の投影座標系(平面直角座標)を設定します。
https://www.gsi.go.jp/sokuchikijun/jpc.html
残念ながら、地理座標系では動きません。また、地図を回転すると動きません。
ジオタグ付き写真からレイヤを作成
プロセッシングツールボックス→「PhotoView_Inport」を開き、Folderにジオタグ付き写真を保存したフォルダを指定し、実行します。
マップキャンバスの上部に写真が表示されます。
このモデルは、下記を行い、ポイントレイヤを出力します。
- プロセッシング「ジオタグ(位置情報)付きの写真」
- プロセッシング「レイヤの再投影」。上記をプロジェクトCRS(投影座標が期待される)に再投影
- プロセッシング「属性のリファクタリング」2つのフィールド追加
- invisible(真偽値) 真の場合、写真の表示対象から除外
- label(STRING) 値が入っている場合、ラベルとして使用。ない場合filenameフィールドを使用
表示のパラメータの設定・更新
「PhotoView_Parameter」のモデルを使ってプロジェクト変数を設定・更新すると、写真の枚数や余白などのパラメータをを変えることができます。以下は写真枚数を変更した例
プリントコンポーザ
内部の処理について
座標の計算など
写真はラスター画像マーカで、写真の上中央をポイントジオメトリで指定しており、この位置の計算がこのスタイルのキモになります。
画面中央から近い画像を表示することを実現するには、他のポイントとの比較をする必要があり、表示範囲のポイントを抽出して、画面中央との距離の配列を作って並べ替えた後、指定数を抽出し、さらにX座標で並べ替えて位置決めをしています。
以下は、ラスター画像マーカのアンカー位置を計算する式です。
/*
ラスタ画像マーカーのアンカー位置、ラベルのアンカー位置 共通
*/
with_variable('Number', to_int( coalesce(@PhotoView_Number , 5) ) ,
with_variable('TopMargin', to_real(coalesce(@PhotoView_TopMargin ,8.0))*@map_scale/1000,
with_variable('PhotoBySideMargin',to_real(coalesce(@PhotoView_PhotoBySideMargin , 15.0)),
with_variable('SideMargin', @map_extent_width /(1+(@PhotoBySideMargin+1)*@Number),
with_variable('Extent',intersection( @map_extent , translate( @map_extent ,0,-@PhotoBySideMargin*@SideMargin*0.800-@TopMargin)),
with_variable('i', --左から何番目か
array_find(
array_foreach(
array_sort(
array_foreach(
array_slice(
array_sort(
array_agg( array( distance( @map_extent_center , $geometry ),$id ,$x ) ,filter:=if( attribute( 'invisible' ),false,true) and within( $geometry , @Extent ))
)
,0,@Number-1)
, array_reverse(@element))
)
,@element[1])
,$id), -- i の定義終わり
with_variable('p0',translate(@map_extent_center,(1+@PhotoBySideMargin/2)*@SideMargin-@map_extent_width/2,
@map_extent_height/2-@TopMargin),
translate(@p0,(1+@PhotoBySideMargin)*@SideMargin*@i,0)
)))))))
下図は、座標計算のメモです。
with_variable()は関数内で使えるローカル変数を定義できる関数で、これなしではこれは作れません。
構文 with_variable(name,value,expression)
引数
name 設定する変数の名前
value 設定する値
expression 変数が使用できる式
曲線の引き出し線
参考にしたfeildaceessと違い、写真の引き出し線は曲線になっています。
これは、写真の縦横比が取得できないため、写真の下端が設定できず、直線だと適切な位置に写真側の端点を設定できなかったため、写真からいったん下げて、写真と結んだラインをスムージングするという処理にしたためです。
処理速度
個別の地物ごとに表示範囲の地物のジオメトリの配列化→画面中心との距離計算→並べ替えを行っているので、表示範囲の地物の数が増えると極端に重くなります。下記は地物が500個の例で、ノートPCのi7で12秒かかりました。100個くらいなら、そんなに処理は重くありません。
おわりに
旅行で写真を撮ったら、試しに使ってみてください。