Rを用いたGIS

しばらく前に作った資料「Rを用いたGIS」のリンクです。
google slideとgithub.ioに置いてあったけど、埋もれて探せなくなってきたのでこちらにスクラップ)

※資料を作成したときからsfパッケージのバージョンも上がってるので、今となっては動かないコードもあるかもしれません。

最初のバージョン
docs.google.com

応用編を一部変更
docs.google.com

上の資料のコードをRmarkdownで出力したもの
tmizu23.github.io

植生調査の凡例一覧をRSelemiumとrvestでスクレイピングしてxlsxデータにする

最新の凡例一覧をデータで公開してもらえれば済む話ですが、凡例Q&Aここのエクセルは更新されていないようなので、統一凡例一覧表スクレイピングしてみます。

ただ、凡例のサイトは生データのtableでなくて、javascriptで生成されており、rvestだけではスクレイピングできないのでSelemiumも利用します。

スクレイピングした凡例も、公開されているshpの属性中の凡例をすべては網羅していないのでご注意ください。

Selemiumの準備

以下のサイトを参考にしました。C:\seleniumに必要なファイルを入れてパスも通しておきます。javaが入っていない場合は、javaもインストールしておきます。
qiita.com

Rでスクレイピングする準備

RでRSeleniumとrvestとtydiverseのパッケージをインストールしておきます。

スクレイピングの実行

seleniumのサーバーを起動します。コマンドプロンプト

cd C:\
java -jar selenium-server-standalone-3.141.59.jar

以下のコードをRで実行すると、凡例一覧をエクセルで保存できます。10ページ目が空になっているので、そこだけ後から修正してください。

gist.github.com


RTKGPS+をWindowsでビルド

(2020.8.12追記 apkを更新しました。http://tmizu23.hatenablog.com/entry/2020/08/09/100146 )

スマホ用のRTKアプリ「RTKGPS+」をカスタマイズしてビルドする方法です。

GNSSの後処理キネマティック (PPK) をするためには、受信機のRawデータを取得する必要があります。Pixcel3などのアンドロイドスマホとNeo-M8TなどのRTK対応の受信機をUSBで接続してRTKGPS+を使うと、Rawデータを簡単に取得できます。ただ、オリジナルのアプリだとQZSSのデータが表示されないのと、2周波対応のZED-F9Pの受信機に対応してなさそうなので、カスタマイズしてみます。ついでにマップに地理院地図も表示できるようにしてみます。

※オリジナルのものでもQZSSのRawデータは取得できてるっぽいのでPPKの処理は問題ないですが。

2周波表示とQZSS表示のポイントは、該当箇所のコメントアウトを外すことと、RTKGPS+用のパッチを当てればよかっただけなのですが...コードを理解してそれに気が付くまでが長かった...

f:id:tmizu23:20191107194012j:plain:w300


play.google.com

Android Studioのインストール

developer.android.com

ダウンロードしてインストールする

RTKGPS+のコード取得

github.com

git で以下のコマンドで取得する。RTKLIBなど関連プロジェクトも含めて取得するため --recursive が必要なので注意!

git clone --recursive https://github.com/eltorio/RtkGps.git

Android StudioでRTKGPS+を開く

Android Studioで取得したRtkGpsフォルダを開くと、自動でSyncされて足りないライブラリなどをインストールするようにメッセージやらエラーがでるので従う。

必要なライブラリがそろうと、ビルドできるようになるがエラーで止まるので、以下のコードの修正をする。

環境変数を設定する

Windows環境変数のPathに以下を追加
C:\Users\mizutani\AppData\Local\Android\Sdk\ndk\20.0.559457
C:\Users\mizutani\AppData\Local\Android\Sdk\platform-tools

ビルドが通るようにコードの修正

  • jni/Application.mkを修正

APP_STLc++_staticから変更。APP_ABIを追加

APP_STL := c++_shared
APP_ABI := armeabi-v7a
  • build.gradleを修正

abiFiltersをarmeabi-v7a以外をコメントアウトする。(とりあえずデバッグするためにビルドを速くしたいから。リリース時は、要変更)
defaultConfigの packagingOptionsに pickFirstを追加する。

defaultConfig {
        applicationId "gpsplus.rtkgps"
        minSdkVersion 21
        targetSdkVersion 26
        multiDexEnabled true
  ndk {
            abiFilters = []
            abiFilters.add('armeabi-v7a')
            //abiFilters.add('x86')
            //abiFilters.add('x86_64')
            //abiFilters.add('arm64-v8a')
        }
        packagingOptions {
            pickFirst 'lib/armeabi-v7a/libc++_shared.so'
            pickFirst 'lib/armeabi-v7a/libproj.so'
            pickFirst 'lib/armeabi-v7a/librtkgps.so'
            pickFirst 'lib/armeabi-v7a/libntripcaster.so'
            pickFirst 'lib/armeabi-v7a/libgdalalljni.so'
            pickFirst 'lib/x86_64/libc++_shared.so'
            //pickFirst 'lib/x86_64/libntripcaster.so'
            //pickFirst 'lib/x86_64/librtkgps.so'
            //pickFirst 'lib/x86_64/libproj.so'
            //pickFirst 'lib/x86_64/libgdalalljni.so'
            //pickFirst 'lib/x86/libc++_shared.so'
            //pickFirst 'lib/x86/librtkgps.so'
            //pickFirst 'lib/x86/libgdalalljni.so'
            //pickFirst 'lib/x86/libntripcaster.so'
            //pickFirst 'lib/x86/libproj.so'
            //pickFirst 'lib/arm64-v8a/libc++_shared.so'
            //pickFirst 'lib/arm64-v8a/libproj.so'
            //pickFirst 'lib/arm64-v8a/librtkgps.so'
            //pickFirst 'lib/arm64-v8a/libntripcaster.so'
            //pickFirst 'lib/arm64-v8a/libgdalalljni.so'
        }
 もともとあるコード
}
  • License.java.sampleの変更

src/gpsplus/rtkgps/geoportail/License.java.sampleのファイル名をLicense.javaに変更

QZSSを表示できるようにコードを修正

jni/rtklib.mkのRTKLIB_CFLAGSをコメントアウトしていあるものに変更(RtkGps+の作者はQZSSが関係ない地域の人だったのかな?)

RTKLIB_CFLAGS := -DENAGLO -DENAGAL -DENAQZS -DENACMP -DNFREQ=3 -DTRACE

ライブラリのビルド

Android StudioのTerminalでRtkGps/jniのフォルダに移動後、ndk-buildのコマンドでライブラリをビルド

cd RtkGps/jni
ndk-build

アプリのビルド

Android Studioでビルドボタンを押す

アプリの起動テスト

Android StudioでBuild APKをするとbuild/outputs/debugフォルダにapkができるので、実際のスマホにコピーして、ファイルアプリから開いてインストールする。

デバッグ

https://okfoxy1990.com/android-apps-wifi-debug
Android Studioで開発したアプリを実機でテストする方法【初心者向け】 | TechAcademyマガジン

上記を参考にしてWIFI接続でデバッグできるようにする。USBは受信機を接続しているので。

開発者モードでUSBデバッグを有効にしてから、USB接続して、以下のコマンドを打つ
adb.exe tcpip 5555
USB外して、以下のコマンドを打つ。ipはスマホのipアドレスを確認して指定
adb.exe connect 192.168.1.11

Android Studioで実機のデバイスを指定して実行すると、実機にアプリがインストールされて起動する。

デバッグモードとなっているのでAndroid StudioのLogcatタブにLogが出力される。

RTKLIBの更新

submoduleとなっているRTKLIBを更新する。

rtklibexplorerバージョンの場合
cd RtkGps
git submodule deinit  -f jni/RTKLIB
git rm -rf jni/RTKLIB
rmdir /s .git\modules\jni\RTKLIB
git submodule add https://github.com/rtklibexplorer/RTKLIB.git jni/RTKLIB

jni/rtklib.mkの以下の行を削除

    $(RTKLIB_PATH)/src/rcv/ss2.c \

jni/RTKLIB-unixsocket.patchのパッチをあてる
android studioVCS -> Apply patch... でファイルを指定する

オリジナルの場合

android studioのterminalで以下を実行(コマンドプロンプトなのでフォルダ消すときはrmdir)

cd RtkGps
git submodule deinit  -f jni/RTKLIB
git rm -rf jni/RTKLIB
rmdir /s .git\modules\jni\RTKLIB
git submodule add -b rtklib_2.4.3 https://github.com/tomojitakasu/RTKLIB.git jni/RTKLIB

jni/rtklib.mkの以下の行を削除

$(RTKLIB_PATH)/src/rcv/swiftnav.c \
$(RTKLIB_PATH)/src/rcv/comnav.c \

jni/prcopt.cを変更する(面倒なのでパッチの内容)

diff --git a/jni/prcopt.c b/jni/prcopt.c
index 49d6884..7b88048 100644
--- a/jni/prcopt.c
+++ b/jni/prcopt.c
@@ -189,16 +189,16 @@ void processing_options2prcopt_t(JNIEnv* env, jobject thiz, prcopt_t *dst)
    GET_FIELD(modear, Int)
    GET_FIELD(glomodear, Int)
 
-   GET_FIELD(gpsmodear, Int)
+   //GET_FIELD(gpsmodear, Int)
    GET_FIELD(bdsmodear, Int)
-   GET_FIELD(arfilter, Int)
-   GET_FIELD(minfixsats, Int)
-   GET_FIELD(minholdsats, Int)
-   GET_FIELD(mindropsats, Int)
-   GET_FIELD(rcvstds, Int)
+   //GET_FIELD(arfilter, Int)
+   //GET_FIELD(minfixsats, Int)
+   //GET_FIELD(minholdsats, Int)
+   //GET_FIELD(mindropsats, Int)
+   //GET_FIELD(rcvstds, Int)
    GET_FIELD(armaxiter, Int)
-   GET_FIELD(varholdamb, Double)
-   GET_FIELD(gainholdamb, Double)
+   //GET_FIELD(varholdamb, Double)
+   //GET_FIELD(gainholdamb, Double)
    GET_FIELD(maxaveep, Int)
    GET_FIELD(initrst, Int)
    GET_FIELD(outsingle, Int)
@@ -352,22 +352,21 @@ static void ProcessingOptions_load_defaults(JNIEnv* env, jobject thiz)
    SET_FIELD(modear, Int)
    SET_FIELD(glomodear, Int)
 
-   SET_FIELD(gpsmodear, Int)
+   //SET_FIELD(gpsmodear, Int)
    SET_FIELD(bdsmodear, Int)
-   SET_FIELD(arfilter, Int)
-   SET_FIELD(minfixsats, Int)
-   SET_FIELD(minholdsats, Int)
-   SET_FIELD(mindropsats, Int)
-   SET_FIELD(rcvstds, Int)
+   //SET_FIELD(arfilter, Int)
+   //SET_FIELD(minfixsats, Int)
+   //SET_FIELD(minholdsats, Int)
+   //SET_FIELD(mindropsats, Int)
+   //SET_FIELD(rcvstds, Int)
    SET_FIELD(armaxiter, Int)
-   SET_FIELD(varholdamb, Double)
-   SET_FIELD(gainholdamb, Double)
-   SET_FIELD(maxaveep, Int)
-   SET_FIELD(initrst, Int)
-   SET_FIELD(outsingle, Int)
-   SET_FIELD(syncsol, Int)
-   SET_FIELD(freqopt, Int)
-
+   //SET_FIELD(varholdamb, Double)
+   //SET_FIELD(gainholdamb, Double)
+   //SET_FIELD(maxaveep, Int)
+   //SET_FIELD(initrst, Int)
+   //SET_FIELD(outsingle, Int)
+   //SET_FIELD(syncsol, Int)
+   //SET_FIELD(freqopt, Int)
    SET_FIELD(maxout, Int)
    SET_FIELD(minlock, Int)
    SET_FIELD(minfix, Int)

jni/RTKLIB-unixsocket.patchのパッチをあてる
android studioVCS -> Apply patch... でファイルを指定する

osmdroidの更新と地理院地図の追加

build.gradleにosmdroidの最新バージョン追加。もともとのosmdroidのjarは削除する

dependencies {
    implementation 'org.osmdroid:osmdroid-android:6.1.2'
もともとあったコード
}

osmdroidのバージョンの違いによりエラーがでるのでMapFragment.javaまわりを修正。地理院地図を追加してgeoportailの地図を削除。

上記を変更したRtkGps+のコードはこちらにあります。
(2019.11.29 追記:apkも以下のreleaseの中にアップしておきました。)
github.com

あとがき

もともとの目的はドローン用対空標識の座標決めで、2周波RTKだったら3分ぐらいの受信と電子基準点との後処理でFixするかも?という期待でしたが、結果5km離れた電子基準点では、3分ではFixせず、最低5分は必要でした。あと、PPKしか試してないので、RTKGps+を使って2周波のRTK測位を試したいですが、Zed-F9Pは1台しかないので、安くなってからかな...

Lat,Lon,Altのcsvファイルの座標系を変換するスクリプト

pos ファイルからLat Lon Altを計算するスクリプト - 自然環境保全のための周辺技術で作成したcsvファイルは緯度、経度なので、それを他の座標系に変換するスクリプトを作成しました。Photoscanへの入力時に平面直角座標系にしておきたい場合に使います。

使い方

以下からLatLonAlt2XYZ.batを保存して、OSGeo4W_ROOT(QGISがインストールしてある場所)とEPSG(変換したい座標系)を指定して、csvファイルをドラッグ&ドロップします。ファイル名_out.csvとファイル名_out.geojsonが出力されます。csvはphotoscanへのGCPのインポートに、geojsonはQGISで場所の確認に利用します。

gist.github.com

pos ファイルからLat Lon Altを計算するスクリプト

RTKLIBのrtkpostで作成したposファイルからLat Lon Altを算出するスクリプトを作りました。出力する値は、posファイルのQ=1:fixしたものを抽出して、その中央値を計算したものになります。EXCELでも出来ますが、大量に処理する必要がある場合などにどうぞ。

使い方

以下からpos2LatLonAlt.jsを保存して、posファイルをドラッグ&ドロップすると、posファイルと同じフォルダに同名のcsvファイルが作成されます。複数ファイルをドラッグ&ドロップすると、最初のcsvファイルにまとめて出力されます。

gist.github.com

QGIS Bezier Editing Plugin を作りました。

QGISでもIllustratorみたいにベジエ曲線で地物を描きたい!ということでBezier Editing というプラグインを作成し、公式プラグインに登録してみました。

https://github.com/tmizu23/BezierEditing/wiki/images/BezierEditing.png

https://github.com/tmizu23/BezierEditing/wiki/images/tools.png

プラグインでは、こんなことができます。

  • アンカーとハンドルでベジエ曲線を描いてフィーチャーを作成。フィーチャーはアンカー間を10点で補間する仕様になっています。
  • フィーチャーをベジエ曲線に逆変換して、再編集。ただし、プラグインで作成したフィーチャーだけが再編集可能です。
  • ポイント、ライン、ポリゴンに対応。ポリゴンは、最初と最後のアンカーがスナップしている必要があります。
  • フリーハンドの曲線もベジエ曲線に変換できます。
  • 分割と結合も可能。


インストールは、QGISのメニューからプラグイン > プラグインの管理とインストール で 「Bezier Editing」 と検索してください。


操作のイメージは以下をどうぞ

編集ツール
https://github.com/tmizu23/BezierEditing/wiki/images/editing.gif

フリーハンドツール
https://github.com/tmizu23/BezierEditing/wiki/images/freehand.gif


使い方のドキュメントは、こちらにあります。
github.com


バグやPull Requestがある場合は、こちらにお願いします。
github.com

QGIS3にプラグインを移植する方法

qgis2用に作ったプラグインをqgis3に対応させるためのメモです。

qgis2to3の準備

OSGeo4Wをインストール
QGISスタンドアローンインストーラーでインストールされるものだとpy3_envでパスがうまく指定されないのでpipがC:\OSGeo4Wのpythonを読み込もうとするので、OSGeo4Wネットワークインストーラーを使います。)

OSGeo4W shell を管理者で実行

py3_env
pip install qgis2to3

qgis2to3の実行

OSGeo4W shellを普通に実行

py3_env
cd C:\Users\mizutani\.qgis2\python\plugins
mkdir myplugin_qgis3
python "c:\OSGeo4W64\apps\Python37\Scripts\qgis2to3" -w -n -o myplugin_qgis3 myplugin

importの修正

importを以下に変更

from qgis.PyQt.QtCore import *
from qgis.PyQt.QtWidgets import *
from qgis.PyQt.QtGui import *
from qgis.core import *
from qgis.gui import *

metadata.txtの修正

metadata.txtのプラグインの対応バージョンを3.0に変更

qgisMinimumVersion=3.0

qgis3のプラグイン置き場に移動

mv myplugin_qgis3 %USERPROFILE%\AppData\Roaming\QGIS\QGIS3\profiles\default\python\plugins\myplugin

リソースのコンパイル

cd %USERPROFILE%\AppData\Roaming\QGIS\QGIS3\profiles\default\python\plugins\myplugin
qt5_env
pyrcc5 -o resources.py resources.qrc

QGIS3の起動とエラーの修正

qgis3を起動してプラグインでエラーになる箇所を修正

変更箇所
QGIS API Documentation: Backwards Incompatible Changes