waigani's diary

QGISを中心にFOSS4Gをいじくる

I wanna try GNOSIS SDK!

FOSS4G SEOUL

9/14-19に韓国で開催されていたFOSS4G SEOULに参加してきました。
f:id:waigani:20150921154047j:plain

内容報告については、10/12(月)のFOSS4G Tokyoで報告があるはずですので、そちらにお任せしておきます。
FOSS4G Tokyo/Osakaでお待ちしております。www.osgeo.jp

試してみたいものはいっぱいあるのですが、いくつ試せるかな。
気になったものをまずはご紹介です。

GNOSIS SDK

バーチャル地球儀というと、Googole EarthやFOSS4Gで言えばcesiumですよね。他の選択肢はないのかなと思っていたのですが、FOSS4G SEOULでの発表の中でGNOSIS SDKが紹介されていました。ecere.ca

  • 3D表示、地形表現ができるバーチャル地球儀を開発するためのSDK
  • Ecere SDK上で使う
  • 言語はeC
  • cross platform(Windows, Linux, OS X and Android)
  • GeoTIFF, Shapefile, SRTM .hgt and Esri ASCII Gridが読み込める
  • スタイルシートで地図表現をつける

らしいのです。何より、デモを見ていて動作が早いし、操作性が良さそうと感じました。

使用に際しては基本お問い合わせのようですが、
 The GNOSIS SDK can be made available free of charge for educational institutions.
となっています。サイトからダウンロードしてすぐ試せるものはないようです。

ただ

ということなので、評価版をそのうちもらって試してみたいと思っています。

Ecere SDK

今回試してみたのはEcere SDKになります。こちらはNew BSD licenseで公開されていて、2D/3Dグラフィックを含むアプリケーションを作成できます。
eCってどんな感じ?という不安もあるので、こちらでアプリケーション作成の雰囲気を掴んでみましょう。

インストール後立ち上げてみると、
f:id:waigani:20150921165931p:plain
背景が龍安寺の石庭!日本のみなさんぜひ使ってみましょう。

サンプルが入っているので、メニューから「project」→「open」で開いてすぐ試せますし、コードも見ることが出来ます。
回転するキューブのサンプルを少々書き換えながらいろいろ遊んでいます。
f:id:waigani:20150921170656p:plain

ドキュメントも一通り揃っているようなので、引き続き試してみたいです。

QGIS講習会【印刷編】補足

QGIS講習会【印刷編】行いました

3/29(日)に北海道大学にて、日本森林学会大会の関連集会としてGIS講習会を行いました。午後の印刷編の講師を担当しております。資料は下記にリンクしておきますが、資料でさらっと書いているところを講習ではじっくりやっていたりするので、もし次回どこかで開催されましたら是非受講してみてください。

講習補足

講習の中で逆に教えてもらったことや、質問で答えられずに流してしまったところもありましたので、いくつか補足しておきます。

画像の向きを地図の傾きに合わせる

方位記号として画像を配置したような場合に、地図の傾きに画像の傾きを同期させることができます。
これは講習中、受講者の方から教えていただきました。ありがとうございます。
画像アイテムのプロパティに「イメージの傾き」という項目があります。「地図と同期する」にチェックを入れて、同期させる地図を選択しておくと、傾きを地図と合わせることができます。
f:id:waigani:20150330210241p:plain

地図アイテムのプロパティで「メインプロパティ」→「地図の傾き」を変更すると、地図の傾きに同期して画像が傾くことを確認できます。
f:id:waigani:20150330210642p:plain

テキストアイテムに属性を表示する

地図帳機能で複数地図を出力する際に、タイトルを変更したいような場合です。
テキストアイテムのプロパティで「メインプロパティ」の「式の挿入...」を選択しましょう。
f:id:waigani:20150330211334p:plain

「地図帳の作成」で被覆レイヤが選ばれていると、表示されるダイアログ(式の挿入)の「フィールドと値」に被覆レイヤの属性カラムが表示されます。ここから表示したい属性を選択しましょう。
f:id:waigani:20150330211559p:plain

コンポーザ上で下記のように表示されますが、
f:id:waigani:20150330211846p:plain
地図帳のプレビューにすると各地物の属性が表示されます。
f:id:waigani:20150330212033p:plain

地図帳機能での出力ファイル名

デフォルトではoutput_1、output_2のようにつきますが、これを変更します。
「地図帳の作成」→「出力」→「出力ファイル名の式」横の"ε"をクリックしましょう。
f:id:waigani:20150330212748p:plain

「'」で囲んで文字列を入れて、「||」で文字列を連結します。テキストアイテムへの属性の表示の例と同様に、地物の属性を表示することもできます。下記例では、'output_'という文字列に続けて、被覆レイヤの地物から区域番号属性を持ってきてファイル名とするよう指定しています。
f:id:waigani:20150330213135p:plain

おわりに

式の機能はまだ使ってみたことがないものが多いです。ラベル表示の際などにも、複数属性を組み合わせて条件付けしながらラベルを表示させるなど、いろいろできるはずなのですが。
誰か複雑に使ってみた例書いてくれるとうれしいな。

OpenCVを使って、QGIS顔認識プラグインを作ってみた

OpenCVを使ってみたかっただけです

この記事はFOSS4G Advent Calendar 2014の7日目が空いてそうなので予備で用意した記事です。違う日に公開されるかもしれませんが気にせずに。

2日目のZero_Kohakuさんの記事を読んでOpenCVを使ってみたくなっただけです。

使ってみたくなったのはいいのですが、何していいか思いつかず適当に検索していたらこんな記事が。
いいですね。特に意味は無いですが顔認識してみましょう。

QGIS顔認識プラグイン

プラグインを作成したので下記からダウンロードしてください。
https://github.com/waigania13/facialRecognition/archive/master.zip

前提としてOpenCVがインストールされている必要があります。この辺は、Zero_Kohakuさんの記事を参照してください。
QGISにプラグインをインストールすると、メニュー"プラグイン"→"facialRecognition"が追加されますので、ご確認ください。
f:id:waigani:20141206110340p:plain

プラグインが実行されると、読み込み済みのラスタレイヤの選択を行えます。レイヤを選択して"OK"を押してください。
f:id:waigani:20141206110346p:plain

フリー素材でテスト

フリー素材アイドル MIKA☆RIKAから素材をお借りしてテストしてみます。

QGISに画像を読み込んでプラグインを実行すると、顔と認識されたところに黒枠が表示されます。
違うところも認識されていますが、パラメータをいじれば精度あがるのかな?細かいところはわからず・・・
顔が認識されているので良しとしましょう。
f:id:waigani:20141206110725p:plain

Natural Earthのラスタでテスト

NaturalEarthから1:50m Raster Dataをダウンロードしてテストしてみましょう。
f:id:waigani:20141206111144p:plain

いっぱい認識されますね。
f:id:waigani:20141206111432p:plain

いくつか見てみると。
顔っぽいやつもあるかな??
f:id:waigani:20141206111658p:plain
f:id:waigani:20141206111927p:plain

LibreOfficeに地理院地図を貼り付ける

FOSS4G Advent Calendar 2014

今年もやりますFOSS4G Advent Calendar。毎年のように一番手です。

この記事はFOSS4Gとはあまり関係ありませんが、FOSS4G Advent Calendar 2014の1日目の記事です。

今年もありがとうございました

まだ一ヶ月ありますが、本年も皆様のご協力で楽しく過ごさせていただきました。
FOSS4G Hokkaidoは初の3日間で開催することができましたし、11月にはオープンデータ+QGISで本も出すことができました。手にとって頂ければ幸いです。

[オープンデータ+QGIS] 統計・防災・環境情報がひと目でわかる地図の作り方

[オープンデータ+QGIS] 統計・防災・環境情報がひと目でわかる地図の作り方

地理院地図パートナーネットワークに参加して

さてここから本題です。11/20に第一回地理院地図パートナーネットワークに参加しました。地理院タイル利用事例とても面白く聞かせていただきました。下記から資料を見ることが出来ますので、ご一読をおすすめします。
パートナーネットワーク会議

みなさんleaflet+geoserver使ってるなmapserverいないなとか、分散処理でのタイル作成について詳細聞きたいとか、色々感想はあるのですが、個人的に一番良かったのは、

  • JAVAやエクセルを利用した開発事例

でした。
やっぱりエクセルですよ、エクセルで帳票作成ですよ。そして真似したくなるわけですよ。
エクセルでやると丸パクリなので、そこはオープンソースソフトウェアを使おうということで、LibreOfficeのマクロで指定経緯度の地理院タイルを貼り付けてみました。

指定経緯度の地理院タイルを貼り付ける

きちんと帳票のスタイル作るべきですが、そこまでやらずに単に1タイル持って来て貼り付けてます。指定経緯度の位置にも●発生しています。
先に実行結果を。
f:id:waigani:20141126231602p:plain

都庁の座標(35.689521,139.691704)を与えて、ズーム15の地理院タイルを持って来ています。

マクロ

LibreOfficeはpythonでマクロ書けるんですね。
解説出来るほどlibreofficeのマクロ判っていないので、解説省略。
下記のコードをgetGSITile.pyのような名前で、

ユーザディレクトリ\AppData\Roaming\LibreOffice\4\user\Scripts\python

に保存しておきます。Scripts\pythonが存在しない場合は、自分で作成する必要があります。


#東京
LAT = 35.689521
LNG = 139.691704

のところを書き換えて頂ければ、好きな場所の地理院タイルを貼り付けられます。
もしくはセルから値を持ってくるように改変しましょう。

実行方法

マクロを指定ディレクトリに置いたことを確認した後、LibreOffice Clacを起動します。
メニューの[ツール]から[マクロ]→[マクロ実行]を選択します。
f:id:waigani:20141126234101p:plain

ライブラリから[マイマクロ]→[getGSITile]と選択するとマクロ名が表示されます。表示されるマクロ名から[getGSITile]を選択し、[実行]を押します。
f:id:waigani:20141126234523p:plain

実行すると、指定経緯度を含む地理院タイルが読み込まれ、シートに貼り付けられます。また、経緯度の位置に●が表示されます。

国土地理院コンテンツ利用規約

利用規約は確認の上使いましょうね。
国土地理院コンテンツ利用規約|国土地理院

うーんもうちょっと情報欲しい

libreofficeのマクロに関する情報どこから取ってくるのがいいんでしょう?情報少ないですね。こちらのサイトを参考にさせていただきました。
OSS( Open Source Software )でいこう!!「 OpenOffice.org / LibreOfficeを使おう編 」

地理院地図3Dにthree.jsのOculusRiftEffectとOculusControlsを足してみる

FOSS4G Advent Calendar 2014

今年もFOSS4G Advent Calendarが行われます。今年はQiitaに場所を移しての開催ですのでご注意ください。自分で参加日登録して、記事を書いたら自分でリンクすることになります。
FOSS4G Advent Calendar 2014 - Qiita

昨年の様子は下記からご覧ください。
FOSS4G Advent Calendar 2013 : ATND

以下の記事はAdvent Calendarのネタに使おうかと思いましたが、FOSS4G出てこないなと考え直して先に公開しちゃいます。

OculusRift風表示

夏に某所でthree.jsで簡単に試せるよと教えてもらったのですが、そのまま放置してたのでそろそろ試そうかと。
three.jsのexamplesに、OculusRiftのeffectとcontrolsの例が載っています。それを真似して、地理院地図3DからダウンロードできるWebGL用ファイルにeffectとcontrolsを追加してあげます。OculusRiftは持ってないので、ブラウザで表示までやってみましょう。

地理院地図3DからWebGL用ファイルをダウンロード

地理院地図3Dから、WebGL用のファイルをダウンロードしておきます。お好きな範囲で3Dモデルを作成しましょう。
ダウンロードしたファイルは解凍して、webサーバの元におきます。
f:id:waigani:20141108003736p:plain

three.jsから必要なファイルをコピー

three.js - Javascript 3D libraryをダウンロードします。
必要なファイルは解凍後の、以下の3ファイルです。

  • examples/js/effects/OculusRiftEffect.js
  • examples/js/controls/OculusControls.js
  • examples/js/controls/FirstPersonControls.js

これらのファイルを、地理院地図3DからダウンロードしたWebGL用ファイルのディレクトリにコピーしておきます。js以下に置くとしました。

  • js/OculusRiftEffect.js
  • js/OculusControls.js
  • js/FirstPersonControls.js

地理院地図3Dを少々修正

下記の箇所を追加・修正しています。

  • 16-18行目 必要なファイルを追加
  • 23-25行目 追加したcontrolsのupdate追加
  • 28-31行目 OculusRiftEffectでの描画に変更
  • 134行目 TrackballControlsをコメントアウト
  • 137-139行目 OculusRiftEffectの作成
  • 140-141行目 OculusControlsの作成
  • 143-149行目 FirstPersonControlsの作成
  • 164-165行目 OculusRiftEffectへのサイズ設定


表示してみると

こんな感じで表示されます。キーボードからw/s/a/d/r/fキーで操作することも出来ます。
f:id:waigani:20141108093042p:plain
f:id:waigani:20141108093050p:plain

TaoVisor | 3DVRゴーグル タオバイザー着たらちゃんと遊ぼう。

国土地理院のベクトルタイルをQGISに読み込んでみる

ベクトルタイルの提供実験

国土地理院のベクトルタイルの提供実験が行われています。
ベクトルタイルの提供実験について|国土地理院

早速、D3.js+leafletで表示している方も。
[D3+Leaflet]国土地理院さん渾身のベクトルタイルで遊んでみた。 | GUNMA GIS GEEK

乗り遅れるわけにはいかないので、QGISで強引に表示してみます。

今回試してみた方法

道路中心線のベクトルタイルはGeoJSONで提供されています。QGISでは一般的なベクトルデータを読み込む際は、OGRというベクトルデータを扱うライブラリを利用しています。OGRはGeoJSONにも対応していますので、QGISでGeoJSONをそのまま読み込むことが出来ます。

試しに提供されているベクトルタイルを1枚ダウンロードしておいて、QGISに表示してみましょう。
http://cyberjapandata.gsi.go.jp/xyz/experimental_rdcl/15/29132/12853.geojson

特に気をつける点もなく表示されます。
f:id:waigani:20140809151003j:plain

キャンパスの地理座標範囲からタイルファイルのズームレベル、X、Yを求めて、必要なファイルさえわかれば、後はGeoJSONにネット越しに直に、もしくは一旦ダウンロードしておいて表示することが出来ます。もちろん、キャンパスの縮尺の変更、表示範囲の変更に合わせて、ファイルの読み込み直しは必要になります。

今回は、キャンバスがリフレッシュされるタイミングで必要なタイルを計算して、1ファイルを1レイヤとして読み込んでみました。
拾うイベントがこれでいいのかとか、グループ消された時の処理とか、プラグイン消された時の処理とか色々考えるべきですが、まずは表示するというところをやってみたということで。

作ったプラグイン

プラグイン

GitHubに置いておきます。ユーザーディレクトリ\.qgis2\python\pluginsにコピーしてお試し下さい。
https://github.com/waigania13/vectorTileswaigania13/vectorTiles · GitHub

実行

【プラグイン】メニューに【vector tiles】→【国土地理院ベクトルタイル提供実験】が出来ますので、実行してみてください。
f:id:waigani:20140809154940j:plain

表示

つくば周辺に移動してベクトルタイルが表示されます。
f:id:waigani:20140810224101j:plain

注意

ogrではgeojsonへのupdateをサポートしてない旨、エラーがいっぱい出ますので注意してください。

処理内容

ズームレベルを求める

少々手抜き。キャンパス上の縮尺500をズームレベル20と仮定して、なんとなく求めます。

X,Yを求める

こんな関数を用意しておきました。この辺はタイルマップの説明をググっていただくと、色々資料があるかと。

vectortiles.py

主な処理を行っているファイルの中身です。

  • 102-103行 : キャンバスの表示範囲を経緯度で持って来ます
  • 106-108行 : 南西、北東のズーム、X、Yの決定
  • 112-119行 : 必要なファイルを決める、すでに読み込まれている時は改めて読み込まない
  • 132-139行 : 必要なタイルの読み込み
  • 143行 : 前回表示範囲のファイルと、今回の表示範囲のファイルを比較、必要無いレイヤは消す

とかやってます。
レイヤへのファイルの読み込みは、ネット越しに直に行っています。
124-130行のコメントアウトを外して、132行目をコメントアウトすると、ファイルを一時フォルダにダウンロードしてきた上で読み込みになります。


つづきあるかな...

別々のレイヤとして読まずに1つのレイヤに入れた方がスタイル付けるの楽ですよね。OpenLayers Pluginを改造した方が賢いかな。誰か任せた。

QGIS プロセッシング Scriptsで一括処理したい その2

若干捕捉

QGIS プロセッシング Scriptsで一括処理したい その1 - waigani's diaryの続きを少々。

multiple vector

入力にfolderを指定しているのですが、本当はファイルを複数指定したいところです。

##input=multiple vector

という指定方法もあるのですが、これだとQGISに読み込み済みのレイヤしか対象に出来なかったりします。

processing.getObject()

前回の記事とは関係ないのですが、processingの仕様もバージョンによって少し変わっています。ファイル名を受け取りレイヤインスタンスを返してくれたメソッドが、以前のバージョンですと、

processing.getobject()

と書いていたところが、QGIS 2.4では

processing.getObject()

となっていたりします。ご注意ください。

複数のベクトルファイルを1つにする

QGISのメニューに【ベクタ】→【データマネジメントツール】→【複数のシェープファイルを1つに結合する】という機能があります。processingで対応するのは'qgis:mergevectorlayers'になるようです。ただしprocessingで実行すると、2つのファイルを指定して1つにする機能になっているようです。
複数のベクトルファイルを指定して1つにマージする機能が、processingのアルゴリズムの中になさそうなので、自作してみましょう。
入力は、

  • 基準とするベクトルファイル指定
  • マージするベクトルファイルの入っているフォルダを指定
  • 出力ファイル名指定

とします。
処理の内容としては、

  • 基準のベクトルファイルを出力ベクトルファイルにコピー
  • 入力先フォルダから拡張子.shpのファイル名を取得
  • 基準のベクトルファイルと違う図形タイプのファイルは対象外
  • 基準のベクトルファイルと違う属性定義(名称と型だけ確認している)のファイルは対象外
  • 対象のファイルについては、出力ベクトルファイルに図形をコピー

としています。

##[My Scripts]=group
##source=vector
##target_folder=folder
##output_file=output vector

from processing.core.VectorWriter import VectorWriter
from processing.core.ProcessingLog import ProcessingLog
import os
import glob 

def isSameFields(f1, f2) :
    if f1.count() != f2.count() :
        return False
    for i in range(0, f1.count()) :
        if f1.at(i).name() != f2.at(i).name() :
            return False
        if f1.at(i).type() != f2.at(i).type() :
            return False

ProcessingLog().addToLog(ProcessingLog.LOG_INFO, "source vector file :" + source)
ProcessingLog().addToLog(ProcessingLog.LOG_INFO, "target folder :" + target_folder)
ProcessingLog().addToLog(ProcessingLog.LOG_INFO, "output vector file :" + output_file)

sourceLayer = processing.getObject(source)
provider = sourceLayer.dataProvider()

writer = VectorWriter(output_file, provider.encoding(), provider.fields(), provider.geometryType(), sourceLayer.crs())
features = sourceLayer.getFeatures()
for feature in features:
    writer.addFeature(feature)
  
files = glob.glob(os.path.join(target_folder, r'*.shp'))
for file in files:
    if os.path.normpath(file) == os.path.normpath(sourceLayer.source()) :
        continue
    layer = processing.getObject(file)
    if provider.geometryType ()  != layer.dataProvider().geometryType () :
        ProcessingLog().addToLog(ProcessingLog.LOG_INFO, "different geometry type :" + file)
        continue
    if isSameFields(provider.fields(), layer.dataProvider().fields()) :
        ProcessingLog().addToLog(ProcessingLog.LOG_INFO, "different fields :" + file)
        continue
    features = layer.getFeatures()
    for feature in features:
        writer.addFeature(feature)

del writer

適当な名前にして、

 ユーザのホームディレクトリ\.qgis2\processing\scripts

に置いておきます。qgisを再起動して、プロセッシングツールボックスから追加されたスクリプトを探して実行しましょう。

出力ベクトルファイルに対して、同一のスクリプト内もしくはモデラーで繋げて処理を行うことで、

  • ファイルをマージ
  • マージしたファイルに対して解析処理

の流れを作ってあげることが出来ます。