引っ越しました

はてな」から、『ダイアリーからブログへ引っ越してね』というお願いメールが何度か届いたので、引っ越しました。見た目を昔に合わせるのは、面倒なので当分やらないと思います。記事も、ほかに SNS を持っているので、更新は進まないと思いますが、過去記事の中に多少備忘録として使えるものがあるので、残しておこうと思います。
こういうときに、黒歴史的なことを書かない習慣にしていることは大事ですね。

ところで、自分の認識では数人もいなかったはずの『ファン』が 45人もいます。その大半は虚偽アカウントのようで、id:xxxxx をクリックすると 404 not found が表示されます。運営に「可能ならばなんとかしてね」という趣旨のお願いをだしておきましたが、どうなることやら。

役所で FOSS4G を広めるには?

 今年も Advent Calendar の季節が到来しました。
 Kubo Mayumi さんのご厚意でエントリさせていただいたので、割当日よりも少し遅れましたが、少し思うところを書いてみます。
 今年のネタは、11月の FOSS4G Tokyo でも少し話題になった、FOSS4G を(特に役所に)広めるには、です。これは、私の前職(国土交通大学校測量部長)にも関係しています。役所の都合で書いていますので、オープンソースソフトウェアの開発者の方々から見ると【何か虫のいいことを書いているなぁ】という印象を持たれるかもしれません。それでも、そういう「手前勝手」の中に、良いソフトが拡がるために必要な条件が潜んでいると思っています。

仮定

 役所で使う場合には、いくつかの仮定が必要です。これは、役所に限らず、キャズムの右側にいる人にある程度まで共通しています。

  1. 利用者の大半(場合によっては全員)が IT の知識を十分なレベルまでは持っていない
  2. 研究者だったら「ググれカス」で済むような案件でも、調べられない(調べる暇やスキルがない)

安定していること

 最初に、仕事場で使うソフトウェアは、安定していることが何よりも重要です。
 当たり前のようですが、これは極めて重要です。ボスに「良いソフトがあります」と言ってデモをすることになったときに、ボタっと落ちたのでは台無しです。
 実は、バグが少ないことだけでは十分ではなく、実質的なバージョンアップの頻度が少ないことも重要です。ここで「実質的な」とは、「使い勝手の変更を求めるような」くらいの意味で書いています。OS(Windows 7 を想定)やブラウザ(Firefox を想定)は、更新頻度は高いですが、使用感が殆ど変化しないので、頻繁にアップデートが起きる割には気になりません(Windows Update は馴らされているだけかも知れませんが)。

セキュリティホールがないこと

 セキュリティ的に大丈夫かどうかは、今や大きな問題です。スペックがどれだけ良くても、セキュリティ的に不安があるソフトウェアは、早晩、システム管理者から利用を禁止されてしまいます。実際に、私が国土交通大学校で「布教」を行った際にも、セキュリティをどう見るのか、といった質問は少なからずありました。
 オープンソースだからセキュリティが弱いということはないと思います。プロプライエタリでないソフトウェアでも、Apachephp など、セキュリティ的に問題ないと見られているものはちゃんとあります。一時的なセキュリティホールが見つかることはあると思いますが、有志が素早く塞いでいます。
 ただ、Apache などは、以下の条件を満たしていると思います。

  1. 専門家のコミュニティが機能していて
  2. 保守を専門に請け負ってくれる専門家が多数いる

 日本における FOSS4G の場合、OSGeo.jp がこのような役割を相当量果たしてくれています。継続的にサポートが得られ、最近では良い解説本も登場しています。このようなコミュニティの存在は貴重です。

教育システム

 ソフトウェアをブラックボックスだと思い込むならば、教育システムは不要かもしれません。
 Apache はその好例です。私自身は、自分で Apache をインストールし立ち上げたこともありますが(威張るほどのことではありませんね)、普通の役人はそういうことはしません。その場合であっても、Apache のようなソフトウェアであれば、維持管理は専門の技術者に委託することができます。役人は教育を受ける必要がないのです。
 しかし、GIS は自分たちでも使いこなす必要があります。すなわち、教育システムが必須です。このとき、残念ながら「ググれカス」が成立しない場合が多いです。GIS が本業ではないと思っている役人に「ググれカス」と言うと、相当数が逃げてしまいます(Late Majority も多いので)。
 私自身、2014-Nov の FOSS4G Tokyo では自分のことを Early Majority であると申しましたが、これは QGIS に限った話であって、その他の Open Source Software では Late Majority だったり Laggard だったりします(威張ってはいけませんね)。

コアになる人材がみつかるか

 地理院の場合は、@_hfu_ さんがいてくれる御蔭で、コア人材は当分の間維持できると思います。まあ、@_hfu_ さんはどうみてもキャズムの左側の人材ですが(笑)、彼以外にも何人かコア人材がいます。
 組織によっては、コアになる人材がいない(まだ資質を発現していない)ところもあります。国土交通大学校では、QGIS を普及させる上で組織のコアになる人材を育てることを目的とした研修も開催していましたが、参加してくれた人は、もともとポテンシャルを持っている人が多かったように思います。
 一方、コアになり得る人材が、技術として何を選ぶ(好む)かは分かりません。たとえば、@_hfu_ さんにとって、FOSS4G を盛り上げることは第一目的ではなく、あくまで、国土地理院の業務を上手く回すことが第一目的だと思います。その目的に FOSS4G が適っている限り、FOSS4G は使われ続けるでしょう。しかし、もしもその目的から外れると、使わなくなるかもしれません(この、恐ろしい話は、もちろん @_hfu_ さんとは事前に相談していません)。
 彼でも誰でも、自分の業務を回すことが第一目的の人にとっては、特定のソフトを使うことは第一義ではないのですね。


 それよりも、コアとなる人材(その多くは early adopter だと思います)が、大多数の同僚(彼らはキャズムの右にいる)と乖離してしまわないことが重要です。私が見る限り、自分以外の同僚全てがキャズムの右にいるために、必ずしも万全の幸せを享受できていない人もいるように思います。キャズムの右にいる人でも、キャズムの近くにいるならば、キャズムの左にいる人とチャネルを維持することはできます。そのような人もコアになる人材に数えて良いかも知れません。私の立ち位置はこのあたりのようだと思っています。

発注時の話

 昔と違って、役所では随意契約ができなくなりました。つまり「あの会社にお願いするのが一番良いと分かっているのだけど、そういうような指定ができない」のです。
 そこで、ソフトウェア開発まわりの発注をかける場合は、まず、仕様書をしっかり書き、仕様書の内容を満たす能力がある人(一般には複数)の中から、価格競争で受注者を選ぶことになります。
 ここで、不適格な会社を受注させないという観点で良い仕様書を書くことは、決して容易ではありません。仕様書を書く側が、当該ソフトウェアのことをよく知っていない限り、良い仕様書を書くことが難しいわけですね。コアになる人材がいない場合は、このレベルのことが難しい場合もあります。
 しかし、キャズムの左側にいる技術者の多くにとっては、そういう仕様書を書くことの難しさには興味を感じないのではないでしょうか。フェイス・トゥ・フェイスで、よく分かる者同士で話し合えば、落としどころは見えてくるのに、発注者のいないところで(あるいは、理解の悪い発注者の前で)書面を書いたりするのは効率が悪く感じる人もいるのではないかという気がします。一般に発注者は、受注者が持っているような技術力を持っていませんので、難しい表現だと通じないこともあります。が、難しいことをやさしく言うために時間を割くんだったら、プログラムの1行でも書いている方が楽しい、と考える人もいるでしょう。ただ、以前に比べると、このあたりの事情は変わりつつあるように思います。分かりやすい資料を作ることが、ハイクラス技術者の楽しみになってきているように思えます。slideshare のようなメディア、TeD のようなイベントの存在が影響しているのかもしれません。

で?

 世の中に真に必要な技術だったら、自然に(なんだかんだ言っても)広まっていくのかもしれません。
 GIS は、まだ、そこまでに到っていない技術です。ここでは、それをどう広めるか、という話として書いてみました。そこに、工夫の余地があるわけですし、発注者の甘えをどこまで補うかという受注者の苦悩がある、のかもしれません。

QGIS Dufour でレンダリング

 初心者にも優しいGISであるQGIS、最新版(CodeName Dufour, ver.2.0.1)になってさらに使いやすくなりました。この項では、そのうち、QGISレンダリング機能について紹介します。
 地図のレンダリングは、例えば書籍【Infographics】や【Illustrator で地図を表現する3行レシピ】など、既にいくつか良書があります。Illustratorを使えば様々なレンダリングができたとしても驚くべきことではありません。それを、QGISでどこまでできるか、が本稿の主眼です。


 図1は地理院地図です。地理院地図は平成25年10月30日からウェブ公開されています。この地理院地図の公開にあたっては、内部処理でOpenLayersが利用されていますので、外部からのアクセスがしやすくなりました。私は既に11月1日のFOSS4G TokyoにおけるLightning Talkで、QGISのOpenLayersPluginを用いてQGIS上で地理院地図を表示させる方法について話しました(図2)。

この方法では、予め地理院レンダリングしたタイル画像を順に読み出して配置しているに過ぎません。これをベクタデータ(shapeファイル)でどこまで再現できるかが今回の勝負です。
 地理院地図は、地理院が無償公開している基盤地図情報よりも明らかに詳細なデータを使用しています。完全に同じものではないのですが、国土基本情報というものがあり、標準地域2次メッシュ単位で170円で販売されています。試しにつくばエリアを2メッシュほど購入してみました。各メッシュはShapeファイルで350Mbytesほどあります。販売データには、位置情報以外の情報は何も付与されていません。つまり、建物記号や土地利用記号などのシンボルデータ、個々のshapeの色、線幅などの情報も付与されていません。従って、これをいきなりQGISで開くと、図3のように悲惨なことになります(笑)。

 最初はレイヤがアルファベット順に並んでいるので、上から順に一つずつプロパティを確かめて線幅、塗りつぶし色、透明度などを順番に設定していきます。その過程で、上下関係を入れ替えた方が良いレイヤも幾組かありますので、入れ替えていきます。レイヤの上下関係は、おおざっぱに言って、

  1. 注記、点図形、線図形、面図形の順
  2. 人工物、自然物、仮想物の順

という原則に従いますが、強調対象が何かによっては多少順序が入れ替わることもあります。このあたりは、昔の紙地図原図(つまりマイラと呼ばれたフィルム)の重ね合わせ順序と本質的に似ています。その上で、他の地物と表示の強さについてバランスを考慮する必要があります。色の濃淡を何度も微妙に変更する必要があり、しかも一箇所いじると他のレイヤも変更したくなります。ともかく、ある程度試行錯誤を繰り返してできたのがこの図4です。

 図4はまったく自己流の色設計ですが、こういうレベルまで来ると、既存の地図の真似がしたくなります。で、地理院地図の真似をしてみたのが図5です。図1と比べると、完全には一致していないことが分かりますが、それでも図1と並べなければかなり近いイメージになっています。ちなみに、基盤地図情報ではここまでの絵は出せません。そもそもレイヤ数もずっと少ないです。

 さて、地図レンダリングにあたって、図5は図4より少しだけ工夫していますので、そのあたりを説明します。
 まず道路です。図5の道路は、図1の道路と同様に、道路種別で色を塗り分けた上で、道路の幅員に応じた表示となっています。QGIS Dufourでは、道路縁と道路中心線を使っています。道路縁は、文字通り道路縁を高い位置精度で取得して得られるベクタデータです。道路中心線は、道路縁よりは若干位置精度は低いと推定されますが、道路のネットワーク構造を考える場合に欠かせないベクタデータです。道路の属性(国道、都道府県道、市町村道、高速道路などの種別と、幅員区分)は、道路中心線の方に付与されています。
 図5では、1) 道路縁を道路中心線より優先させて描画することとした上で、2) 道路中心線はライン属性を二重とし(図6)、3) 下側属性を道路幅員で分類して線幅を決め(図7)、4) さらに線の色を道路種別で分類し(図8)、5) 上側属性として細い線を表示する(図9)、という段階を踏んでいます。ここで、3)4) と二種類の分類を続けてできる点が最新版のQGIS(Dufour, ver.2.0.1)の特徴です。Wroclaw(ver.1.7.4)まではこのような機能はありませんでした(私は日本語環境が不安だったver.1.8は使っていません)。特に、図8で示す case when – then – else – end 文の威力は大きいと思います。これがある御蔭で、道路縁の内側を幅員に応じて塗りつぶすことができ、その際の色を道路種別に応じて変更できているのです。図5では、画面中央の新井付近で県道(黄色)が細い川を横切っています。この黄色い帯がなければ、道路の路面も河川の青が表示されてしまいます。




 ただし、道路中心線の幅員区分は5段階に分類されているだけなので、道路中心線の幅員区分から機械的に発生させた幅広の着色線は道路縁の位置とはぴったり一致してくれません。これは、表示縮尺を一桁拡大してみればよく分かります(図10)。位置精度に拘らないレンダリングをしたい場合は、道路縁を表示させるのではなく、道路中心線に3番目のライン属性を設け、先ほどの?で下側属性を道路幅員で分類して線幅を決めたのと同様に、そのさらに下側に道路幅員で分類してやや太めの線幅の線を灰色や茶色で引く手法もあります。これでも完全には解決しませんが、その例を念のために示します(図11)。


 このほか、【樹木に囲まれた居住地】というポリゴンがあります。これは、集落を含むようなポリゴンで、内部に何軒かの家屋があり、数本の道路が通っています。このポリゴンは薄い色で表現しますが、建物や道路が不明瞭になってはならないので、低めのコントラストで最下層のレイヤとして配置することになります(図12、薄いオレンジ色のポリゴン)。

 このように、QGIS Dufourは地図レンダリングエンジンが大幅に強化されたことがわかります。ここまで凝ったレンダリングをする場合は、設定にそれなりの時間を要します。せっかく位置精度の高いデータを配布しているわけですから、標準的な線属性も.qmlなどで一緒に配布するのも面白いかも知れません。ただし、.qmlだけではレイヤの上下関係は指定できないので、実際には.qgsで配布する方が良いことになります。すると、QGIS専用の設定となりますので、地理院配布よりもOSGeo.jpなどサードパーティ配布の方が適していると言えます。
 さて、ここまでレンダリングしてみると、国土基本情報の側にさらに注文したいことが見えてきます。例えば、実際の道路に工事その他による変更があった場合、道路縁や道路中心線は細かいセグメントに分割されます。しかし、ネットワーク解析を行う場合には、細かいセグメント分割は不要です。従って、交差点から次の交差点までは1路線1セグメントである方が有難いことになります(これは、QGISの上でユーザが加工することも不可能ではありませんので、国土地理院の宿題だとは言わないことにしておきます)。また、道路縁には不可視属性のフィールドがあり、これが1の場合は表示しない扱いとするべきですが、不可視属性をもつセグメントは実際よりも長めであるように思えます。あるいは盛り土の法面情報が不十分なのかも知れません。このあたりは属性情報をどこまで正確に取得するかという話になります。位置精度も位相精度も間違ってはいないので、微妙な話です(この場合も、QGISの上でユーザが加工することで、不可視属性を持つセグメントの長さをクリップすることは可能です)。

 ここまで、QGIS Dufourがレンダリングエンジンとしても使えることを見てきました。ここまでできるとなれば、これまでIllustratorで行っていた地図レンダリングのかなりの部分をQGISでもできることになりますので、これまたプロプライエタリソフトの初級〜中級の部分をFOSS4Gが置き換え可能になる良い例と考えます。地図データを大規模配信する場合は、現時点ではMapServerやGeoServerを(PostGISなどと組み合わせて)使うのでしょうけど、MapServerの設定をどのようにするか、アタリを付けるレベルであればQGISで簡便に確認できるような気がします。Dufourはこういう点でも今までのバージョンから大きく進化しており、まさにメジャーバージョンが2に上がっただけのことはあると考えています。

iframe に電子国土を(その1)

たしかに、こうすれば電子国土の地図タイルが表示されるようだ。


 tmizu23 さんのサイト http://d.hatena.ne.jp/tmizu23/20121212 の情報を参考にしました。

 Google Gadget を使わなければならないが、はてなの場合はこうしないと html 文のタグがサニタイズされてしまう。

Quantum GIS / OpenLayers Plug-in

はじめに

 javascript 学習を始めて最初に出くわす中ボスとして、QGISOpenLayers プラグインを解読し電子国土版を作成してみようというのである。といっても、プラグインpython で書かれており、私は python は分からない。なので、分かる範囲での解読に限定される。
 また、javascript がなんとか理解できるようになったのは今年になってからである。以下の記事にはツッコミどころも当然あるだろうと考える。遠慮なくツッコミを入れて頂けると有り難い。

python の部分

 プラグインのフォルダを開くと、いくつか python のファイルがあるほか、3つのフォルダ(html, ui, i18n)と、いくつかのアイコンが格納されている。このうち、i18n は各国語対応のフォルダ(のはず)で、ui は jQuery のユーザインターフェースの筈である。

 エディタで順に見ていくと、openlayers_plugin.py が一番キモになるファイルに見える。といっても、私には殆ど分からない。ただ、124行目に #Layers とあり、直後の行から self.olLayerTypeRegistry() という関数が幾つも並んでいる。引数はいずれも OlLayerType() という関数で、この関数は4つもしくは5つの引数を持っている。

第一引数:全て’self’ である。
第二引数:’Google Physical’, ‘OpenStreetMap’, ‘Bing Aerial’ 等と書かれているので、表示しようとする地図レイヤの種別であろうと推定される
第三引数:対応するアイコンであろうと推定される
第四引数:地図を表示させるための html ファイルであろうと推定される
第五引数:一つを除いて全て True が指定されている(唯一の例外は、第五引数が存在していない)

なので、もしも電子国土を地図として表示させたいのであれば、第二引数に ‘CyberJapan’ など電子国土らしい名前を指定し、第三引数に電子国土のアイコンを指定し、第四引数に専用の地図描画 html を用意すれば良いように思われる。

ここまでは、わざわざ書かなくても、誰でも分かる話である。問題は、html フォルダにどのような内容のファイルを追加するか、である。そこで、既存の html ファイルを眺めて、共通パターンがないか探ってみた。

html の解読:apple.html を例にとって

 apple.html を覗くと、こういう構成になっている:

スタイルシートjavascript をインクルードする宣言部分
<html xmlns="http://www.w3.org/1999/xhtml">
  <head>
    <title>OpenLayers Apple iPhoto map Layer</title>
    <link rel="stylesheet" href="qgis.css" type="text/css">
    <script src="OpenLayers.js"></script>
    <script src="OlOverviewMarker.js"></script>
javasecipt のセクション(ここがメイン)

といっても、グローバル変数を3つと、このプラグインを起動した時に一回だけ呼び出される init 関数を定義しているだけである。

    <script type="text/javascript">
グローバル変数
        var map;

OpenLayers.Map オブジェクトのmap インスタンス

        var loadEnd;

(Boolean 型の変数)

        var oloMarker; // OpenLayer Overview Marker

QGIS の全体図マーカーと関係があるらしい)

init 関数
        function init() {
            map = new OpenLayers.Map('map', {

OpenLayers.Map コンストラクタを呼び出してインスタンス map を生成している。
・このコンストラクタを呼び出す際には、いくつか引数を指定するのが通例である。ここでは、以下のプロパティを指定している:

                theme: null,

(意味不明、なくても困らないと考える)

                controls: [],

(このmapオブジェクトのコントロールは何も用意しない→全て Quantum GIS 側で処理するから)

                projection: new OpenLayers.Projection("EPSG:3857"),

(デフォルトで使用する CRS として 3857 -真球疑似メルカトル投影- を使用する)、

                units: "m",

(使用する単位はメートルである)

                maxResolution: 156543.0339,

(最小縮尺における 1pixel のサイズで、単位はメートル。赤道周囲長約4万kmの 1/256 で与えられる)

                maxExtent: new OpenLayers.Bounds(-20037508.34, -20037508.34, 20037508.34, 20037508.34)

(描画範囲、東経0度北緯0度を座標原点とみて、東西南北に約2万kmの範囲を指定している。この値は、真球疑似メルカトル図法を利用していることと関係がある。当然、極は表示できない。)

            });
            loadEnd = false;

(初期状態では、地図の読み出しが終わっていない、ということ)。

            function layerLoadStart(event)
            {
              loadEnd = false;
            }
            function layerLoadEnd(event)
            {
              loadEnd = true;
            }

・これら2つの関数は、地図レイヤの読み出し完了に関するイベントと連動して変数 loadEnd を変化させる。

・続いて、変数 apple に地図レイヤを生成している。具体的には、タイル型の地図として、OpenLayers.Layer.XYZ を呼び出している(これは、電子国土でも同じ)。

            var apple = new OpenLayers.Layer.XYZ(
              "Apple iPhoto map",
              "http://gsp2.apple.com/tile?api=1&style=slideshow&layers=default&lang=en&z=${z}&x=${x}&y=${y}&v=9",
              {
                sphericalMercator: true,
                wrapDateLine: true,
                // TODO: min zoom level 2
                numZoomLevels: 15,
//                attribution: "", // FIXME: attribution
                eventListeners: {
                  "loadstart": layerLoadStart,
                  "loadend": layerLoadEnd

・ここで、コンストラクタの呼び出しに際して、イベントリスナにloadstart, loadend の2イベントを登録している(処理関数は先ほど定義したlayerLoadStart, layerLoadEnd の2関数である)。地図レイヤの生成にイベントリスナを定義しているので、データの読み出しをウォッチするのだなと推定できる。

                }
              }
            );
            map.addLayer(apple);

・生成した地図レイヤを地図( map インスタンス)に登録している。

            map.addControl(new OpenLayers.Control.Attribution());

著作権表示処理を実施している。ただし、attribution には空文字列がセットされており、「誰か直して」とコメントされている(笑)。

            map.setCenter(new OpenLayers.LonLat(0, 0), 3);

・初期表示として、東経0度、北緯0度、ズームレベル3を指定している。

            oloMarker = new OlOverviewMarker(map, getPathUpper(document.URL) + '/x.png');

・最後に、OlOvervierMarker を呼び出している( x.png は、赤いXの印のアイコンであるが、プラグインでこれが表示される様子はなく、意味不明である)。

        }
    </script>

スクリプトはこれで終わりである。

 </head>
body 部分

body は非常にシンプルで、

 <div id=”map”></div> 

 があるだけである。
スクリプトで定義した地図インスタンス map が結びつけられ、地図として表示される。

  <body onload="init()">
    <div id="map"></div>
  </body>
</html>

ちなみに、この html は単体でも動作する。その場合は、配列 control が空なので、表示された地図を操作することはできず、デフォルトの表示位置及び表示ズームレベルで表示される。
・また、たとえば下記のような簡単な html からこの apple.html を呼び出した場合でも動作し、iframe の内部一杯にちゃんと地図が表示される。
( OloverviewMarker は無視される)

<html>
  <head></head>
  <body>
    <iframe src=”apple.html” width=”500” height=”500”> </iframe>
  </body>
</html>

(文法的に完全な html ではないが、シンプルさを強調するためにあえてこういうコーディングにしている)
・このサンプルプログラムは、Quantum GIS における OpenLayers plug-in の挙動を知る上で本質的であると考える。Quantum GIS は、実質的には、こういう iframe を plug-in 側の html に提供すると共に、適宜 OpenLayers が受け取れるようなコントロールイベントを渡しているのである。
(サンプルプログラムにはそういうイベントを渡す処理は書かれていないが、例えば【ズームレベルを一段上げる】というボタンを設置し対応するイベントを plug-in 側の html に渡すような処理ならば、javascript で実装可能と考える。)

電子国土の場合

それでは、電子国土ではどうなるか。
実は、意外に難しくないと考えられる。

考え方

・map インスタンスを生成する部分などは同じで、
・地図レイヤとして webtisMap を生成する。これは webtis_v4.js を使えば簡単に実現できる( OpenLayers.Layer.XYZ をプロトタイプに持つクラスである)。
・イベントリスナのコールバックを忘れずに挿入する。
 これは、地図レイヤの生成時に引数として渡しても良いが、引数生成後に

	map.events.register('loadstart', map, layerLoadStart);
	map.events.register('loadend', map, layerLoadEnd);

を定義する方法も考えられる。両方試してみたが、この方法の方が優れているようだ(通常の方法では、実行時に原因不明のタイル抜けが頻発する)。
国土地理院のサーバでは、ズームレベル 15 - 17 において空中写真オルソ画像を表示させることも可能である。こちらの場合は、layer インスタンスを作成した直後に

	var mapMeta = {dataId: "DJBMO" }; // オルソ画像のタイル情報
	webtisOrtho.setMapMeta(15,mapMeta);
	webtisOrtho.setMapMeta(16,mapMeta);
	webtisOrtho.setMapMeta(17,mapMeta);

とすることで、ズームレベル 15 - 17 を空中写真オルソ画像に変更できる。
・実は、webtis には getOrthoDataSet というメソッドが用意されており、最初からオルソ画像をタイル情報に含むようなデータセット(ズームレベルとタイル情報のペアからなるハッシュ情報)を返してくれる。なので、地図レイヤ生成時に

	cjpOrtho = new webtis.Layer.BaseMap(‘webtisOrtho’,new getOrthoDataSet()) ;

のようなコーディングが効けばエレガントなのであるが、残念ながら getOrthoDataSet はコンストラクタではないので、この記法は使えない。

実装、既知のバグについて

OpenLayers plugin にはバグが存在する。プラグインのバグか Quantum GIS のバグかについても切り分けつつ、既知のバグを報告する。

Quantum GIS 立ち上げ直後に OpenLayers Plugin を起動するとエラーになる

【現象】
・このエラーは、QGIS 立ち上げ直後の画面サイズに拠ります。1200×800 位のディスプレイだと 100% 再現しますが、1920×1280 くらいの広いディスプレイだと再現しない場合もあります。
プラグインを呼び出す前に、オプション画面でシステムの CRS を EPSG:3857 に変更すると、今度はエラーを 100% 防ぐことができます。
電子国土に限定されず、Google でも OSM でもどれでも起こります。ただし、もとになる OpenLayers.Layer のタイプが異なる場合に全て該当するかどうかは未検証です。
【原因推定】
・エラーメッセージを見る限り、OpenLayers.LonLat(x,y).transform() 周辺が出しているように見えます( transform が直接出しているわけではなさそうですが)。
・デフォルトでは CRS として EPSG:4326 が定義されています。
これでOpenLayers.Bounds(-2000万, -2000万, 2000万, 2000万) や
maxResolution = 156543.0339 のようなコードを実行した場合に、これが度だと考えるとおかしなことになります。縮尺計算をした結果、NaN が帰ってくるということだろうと考えます。
・画面が広いと、辛うじて縮尺が NaN にならずに済むのではないか、とも推定されます。
・事前に CRS を EPSG:3857 に変更してあれば、上記コードを正しく解釈できるので、エラーにならないのでしょう。
【解析】
・これは間違いなく Quantum GIS 本体のバグです。
 その証拠に、

<html>
  <head></head>
  <body>
    <iframe src=”apple.html” width=”500” height=”500”> </iframe>
  </body>
</html>

 のような簡素な html から(QGISからではなく)plugin 同梱の html を呼び出した場合は絶対にエラーになりません。iframe には CRS の概念がないので、CRS マッチング処理をする必要がないからです。
Quantum GIS では、CRS マッチングをする必要があるので、現在の表示画面における四隅座標( CRS に基づく値)を plug-in に与えてどのような範囲でタイルをだすのか計算させているはずです。この計算で NaN が発生していると見られます。
Quantum GIS の立ち上げ直後に CRS を EPSG:3857 に変更すれば、エラーは 100% 防げますが、EPSG:4326 は利用頻度が高いと思われますので、これをユーザに要求するのは無理でしょう。
・ところで、地図レイヤによっては、日付変更線を越えてサイクリックに横長の画像を表示するものがあります。そういえば、この場合の挙動を調べていませんでした。
【対策案】
・このプラグインを呼び出す場合に、必ず先に何か shape ファイルその他の別レイヤを読み出しておくことにすれば、エラーは防げます。
・現実的な縮尺で地図が表示されていれば、OpenLayers Plugin はその縮尺を踏襲しつつ CRS を強制的に EPSG:3857 に変更しますので、計算の途中で NaN になるようなことがなくなります。

QGIS ver.1.6.0 の場合は、1回目に必ずエラーになる

【現象】
Quantum GIS のバージョンが 1.6.0 の場合は、初めてこのプラグインを起動した場合にかなりの確率でエラーになります。ただし、もう一度プラグインを起動すると、何事もなかったかのように動作してくれます。
電子国土GoogleOSM など、表示レイヤの種類に関係なく発生します。
・バージョン 1.7.x では発生しません。バージョン 1.8.x は試していません。
【原因、解析】
・よく分かりません。
・初期化処理が途中でエラーになるものの、QGIS 内の環境を一部改良してくれるので、もう一度走らせると今度はうまくいく、ということのように思えます。
【対策案】
・あまり気にせず使い続けて大丈夫だと考えます。ver.1.7.x 以降を使えばそもそも発現しませんし。

電子国土で、1/1500万程度の縮尺で表示させると、表示が乱れることがある

【現象】
電子国土で、ズームレベル0から徐々に拡大していくと、ズームレベル5または6位で地図画像が東西にずれて表示されることがあります。
Quantum GIS でパンしても、画像は変わってくれません(依然、画像が偏った位置に表示される)。
・この状態でさらに拡大すると、場合によっては白抜けの画面になる場合があります。
【原因、解析】
電子国土レイヤでは、ズームレベル5-8の地図タイルとして「1/500万日本とその周辺」から起こしたデータを使用しています。この「1/500万日本とその周辺」は、もともと日本付近のみで作成された紙地図で、図郭は縦長でした。
・ズームレベル5〜6程度では、画面の左右にタイルが存在しないような表示を求めることが起こりえます。表示範囲が一旦ここに嵌ると、表示が崩れるようです。
・ズームレベル5〜6で、NoData タイルの扱いが不正になっているものと考えられます。電子国土サーバ側のエラーの可能性もあります。
【対策案】
・先に何かデータを表示させておけば(1/1000万程度より表示縮尺が大きければ)、このエラーは発生しません。

OpenLayers plugin を表示させた後で、CRS を EPSG:3857 以外に変更すると、表示が崩れる

【現象】
OpenLayers plugin を表示させると、CRS は自動的に EPSG:3857 に変更されます。
・ここで、Quantum GIS のオプション画面で CRS を強制的に他の値に変更すると、on-the-fly の有無に関係なく、表示が崩れます。具体的には、OpenLayers で表示される地図タイルと、それ以外のレイヤがぴったり重ならなくなり、OpenLayers 地図タイルの表示範囲が狭くなります。
【原因、解析】
・OpenLyaers の地図タイルは、EPSG:3857 以外では表示できません。map インスタンスが project:{EPSG:3857} で生成されている上に、OpenLayers にはmap.changeCRS のようなメソッドが用意されていません。
・map インスタンスを生成する際に、displayProjection を指定すればと思って試して見ましたが、EPSG:4326 でもダメでした。効いていない感じです。
 なので、そもそも OpenLayers の内部変数 displayProjection は命名もしくは仕様が不正だと思います。
・また、map インスタンス生成時に displayProjection に EPSG:4326 を指定しても、Quantum GIS 側も認識しません。
 本来、(1)データの座標記述に使用されている CRS、(2)画面で表示する際の CRS、(3)ユーザが座標指定する際の CRS の3つを上手く使い分ける必要があります。(3)は、QGISでは地図表示メインウインドウの下に表示されるマウス位置のことを想定しています。(2)のCRSとして EPSG:3857 や EPSG:3100( JGD2000 / UTM54N )などを使ったとしても、座標値は LatLon で欲しい場合があると思うのですが、どうでしょうか。
・まあ、それ以前に、(1)のケースと(2)のケースのどちらの CRS を指定するべきかが明瞭でない場面が多いですね。GIS の初心者を悩ませる高いハードルの一つだと思います。
・将来の QGIS では、on-the-fly が充実して、CRS を自由に変更できるようになるかも知れません。
・一方、OpenLayers 側が proj4 を内包して対応する、という可能性もあると思います。
【対策案】
・一旦 OpenLayers プラグインを表示させた場合は、CRS は EPSG:3857 で我慢するしかありません。

実装方法

 電子国土の地図を表示するための html ファイル( cjp_mao.html )は https://dl.dropbox.com/u/47691954/cjp_map.html に、
 また、電子国土のオルソ画像を表示するための html ファイル( cjp_ortho.html )は https://dl.dropbox.com/u/47691954/cjp_ortho.html に、それぞれ置いてあります。
 電子国土のアイコンは国土地理院のサイトからでも取得できると思いますが、一応 https://dl.dropbox.com/u/47691954/cjp_icon.png に置いてあります。

 実装方法は、大体下記の手順で良いと思います。Quantum GIS についての最小限度の知識を仮定して書いています。また、Windows ユーザを念頭において書いています。

  1. C:\Users\【username】\.qgis\python\plugins\openlayers フォルダを開く
    • 【username】は、Windows のログインユーザ名です
    • 当たり前ですが、OpenLayers Plugin は既にインストールされているものとします。
  2. openlayers_plugin.py をエディタで開く
  3. プラグインのバージョンにもよりますが、122行目付近に #Layers という行があるはずです
  4. その直後から self.openlayerTypeRegistry.add という関数が10行くらい書かれている筈です
  5. この並びの最後に、以下のように引数を変更した行を追加します。
    • 第2引数を CyberJapanMap(など、電子国土の地図だと分かる名前)
    • 第3引数を cjp_icon.png
    • 第4引数を cjp_map.html
  6. さらに、以下のように引数を変更した行を追加します。
    • 第2引数を CyberJapanOrtho(など、電子国土のオルソ画像だと分かる名前)
    • 第3引数を cjp_icon.png
    • 第4引数を cjp_ortho.html
  7. このフォルダに、cjp_icon.png をコピーします。
  8. このフォルダの下にある html フォルダに、cjp_map.html と chp_ortho.html をコピーします。

これで Ok です。Quantum GIS を立ち上げて、OpenLayers プラグインを呼び出すと、ちゃんと最下行に電子国土のアイコンと共に、Add CyberJapanMap Layer 及び Add CyberJapanOrtho Layer という行が登場し、これらを選ぶと電子国土の地図(またはオルソ画像)が表示されます。
 なお、オルソ画像はズームレベル 15 から 17 だけ用意されていますので、表示縮尺 1/5,000〜1/40,000 くらいでないと表示されません。それ以外の縮尺の場合は、地図が表示されます。

おわりに

 はてなダイアリーに書いてみましたが、もとのデザインをちょっと変わった設定にしてしまっていましたので、あまり見やすくなく、申し訳ありません。特に、super-pre 記法で html モードとか javascript モードを使ってみたところ、不必要にカラフルになってしまい、ちょっと自分でも引いています(汗)。

 最初に書いたように、ツッコミ大歓迎です。よろしくお願い致します。


 

Quantum GIS のマニュアルを改める

 Quantum GIS の独習用マニュアルを書いてみて、1年ちょっと経過した。

 昨年のマニュアルは、予備知識をできるだけ求めず、準備も要さず、ほぼ手ぶらの状態から GIS が覚えられるように、ということを中心に書いていた。これには理由があり、一日(6時間から7時間を想定)で話せる内容と、自分の話術のつたなさを考えた場合に、余計な前置きや準備をしている時間がないだろうと考えて、枝葉を刈り込んだのだった。

 従って、インストールは実演なし(インストール済みのマシンで説明を開始する前提)、データもダウンロードや解凍、shape 変換などの実演なし(予め用意しておいたものを使う前提、ただしマニュアルを読んだ人が自力でデータを調達できなければならないので、全てダウンロードフリーのデータを使用する)、空間解析は私がまだ上手く説明できないのでやらないこととし、代わりにデータの編集方法を説明して終わり、という代物だった。
 その上で、初心者が独習できるよう、マウスをほんの少し動かした際の画面の変化をいちいち画面イメージとして取り込み、「こういう操作をすればこうなる」については丁寧な解説を試みた。守備範囲は狭いが、その範囲内では分かりやすく書いたつもりであった。

 しかしながら、GISGIS らしいところは全く説明できていなかった。何しろ、最初の方で「空間解析には言及しない」と宣言しているのである。初心者向けだから、を言い訳に開き直っていたのであった。

 ともかく、自分の講義に何度か使ってみた。1回目はまあこんなものかなと思い、2回目はああ改良の余地があるなと思い、3回目は根本的に変えた方がよいのではないかと思い至った。で、そのことを twitter で少しつぶやいたところ、wata909 さんに見つかってしまい、こうして advent calendar に書く羽目になったのである。

−−−

 書き直すに当たって、前提条件はあまり変えていない。

 初心者が読む前提とすること、まだ ver.1.6.0 Copiapo を使うことは、前回のままである。
 Copiapo の使用を続ける理由であるが、私が作成するマニュアルは、それほど GIS に期待していないような行政官にも読んでもらうことを目指すので、資料が日本語でないとダメだと考えている。本当は ver.1.7 以降の方が機能的に優れる部分があるし、バグも一般的には減少する傾向にあるのだが、日本語の資料の多さを重視して ver.1.6.0 で説明を続けることにしたのである。ver.1.8 は日本語の取り扱いにバグがある点も気になった。
 一方、昨年度版は簡単な地図編集(shape file の作成)ができれば終わり、というレベルだったが、さすがにこれでは学習意欲が湧きにくい。そこで今回は、地図や測量の知識を持たない人向けの用途を意識して、チェーン店のサイトにある店舗一覧のテーブルをコピーしてきて、それにジオコーディングを施し、shape の点レイヤに変換し、店舗分布図を作成することを目標に設定してみた。その際、背景地図は、基盤地図情報25000を使用し、最初から .qml と .qix を用意しておいて、見栄えを良くすることとした。この時点ではまだ空間解析に触れていないので、GIS の醍醐味を依然として解説していないことに代わりはないのであるが、そもそも GIS の初心者は空間解析なんかやらないし、概念も理解しないかもしれない。この点は、昨年同様割り切りである。実際に講義に使う場合も、2日目以降の課題になるので、時間が足りなければ(そして聞く側の予備知識が少なければ)空間解析は端折られることになるものと考える。
 説明に要する時間も、昨年はあまり読めていなかったのだが(なんとなく一日分としていたのだが)、今回は丸二日掛けられる分量にまで増やすこととした。ただし、実際には一日で済ませなければならないことも多い。その場合は、後半及び枝葉に該当する部分を飛ばすことになる。

 で、現時点では、以下のような章立てを考えてみた。(書いている途中で膨らんで大変なことになった・・・)

  1. インストール
    • ver.1.6.0 の入手方法とインストール手順
  2. 立ち上げ直後のおまじない
    • CRS の設定(おまじないとして。キチンとした CRS の解説は後ほど改めて)
    • その他、オプションの設定など
  3. 表示例を見せ、簡単な操作を示す
    • ありものの背景地図:地球地図、小縮尺図として
    • ありものの背景地図:基盤地図情報25000、中縮尺として
    • これらがタダで入手できる地図であることを示す
    • 背景地図として使う用途で調製していることを示す
    • 施設位置の配置を見るために使えることを示す
    • 通勤経路の申告に使えることを示す
    • GPSの軌跡を重ね書きできることを示す
    • 写真を貼り付けることができることを示す
    • 個別地物の属性を調べることができることを示す
  4. 背景地図の作り方(1)地球地図
    • shape ファイルの読み込み
    • 属性テーブルを眺める
    • プロパティをいじって見栄えを変える
    • 行政区域、行政区域界線、交通網のみのシンプルな図としてプロジェクトを保存する
  5. 背景地図の作り方(2)基盤地図情報25,000WMS
    • WMS サーバへの接続
    • 読み込み
    • WMS の得失(これは参考として示すに留める)
  6. 背景地図の作り方(3)基盤地図情報25,000ベクタ
    • データのダウンロード
    • 解凍、変換
    • shape ファイルの読み込み
    • プロパティをいじって見栄えを変える
    • 空間インデックスを付与する(そのための小細工)→この小細工は枝葉の技術なので、時間がない場合は端折る。中味は 9/10 の eat-up の LT で話した内容である
  7. 背景地図の作り方(4)電子国土webタイル
  8. GPS 軌跡の読み込み
    • ロガーの説明
    • データのパソコンへの取り込み
    • GPX ファイルの track point を読む)
    • 表示の方法(手の込んだ変更を掛けたい場合は、一旦 shp に吐き出す)
  9. 写真の管理、地図上での管理
    • デジカメの特性(特に iPhone)→GPS の内蔵、傾きセンサの内蔵について触れる
    • 入手が難しいプラグイン photo2shape と、その入手
    • プラグインの操作→撮影位置にカメラのアイコンが出るまで
    • プロパティ操作による、撮影方向の表示→矢印のアイコンに切り替えて、フィールド【direction】でアイコンを回転させる
    • アクションの設定→点シンボルをクリックすると写真が出るように
    • ロガーと iPhone があれば現地調査が効率化できることを簡単に示す
  10. 表形式データの管理、地図上での表示
    • スーパーマーケットのサイト(一般的なサイトから適当に見繕う)
    • 店舗一覧表を取得する(サイトから Excel にコピーする)
    • 地理院のマップシートでジオコーディング(マップシートが Excel のマクロを使うので、現状 OpenOffice では実現できない)
    • デリミテッドテキストレイヤへ変換
    • プラグインで読み込む
    • 表示の具合を見る
  11. 点タイプレイヤの作成
    • 属性テーブルの設計
    • 位置の入力
    • 属性テーブルの拡張
    • フィールド計算機について、余裕があれば触れる
  12. 線タイプレイヤの作成
    • 属性テーブルの設計
    • 位置の入力
    • 途中でスクロール
    • 属性テーブルの拡張
    • 実習させる場合は、通勤経路を作成させてみる
  13. 面タイプレイヤの作成
    • 属性テーブルの設計
    • 位置の入力
    • 途中でスクロール
    • 属性テーブルの拡張
    • 線タイフのレイヤと手法が殆ど変わらないことを示す
    • 言い換えると、面としてのトポロジは(shape では)弱いことを示す
  14. ラスタの取扱、基礎
    • (ありものの)陰影段彩図、旧版地形図などを表示させてみる
    • ラスタの特徴、面タイプレイヤとの違い
    • ジオリファレンシングプラグインの操作)
    • GeoTiff 画像の地図上への貼り付け
    • 陰影段彩図を DEM から作成してみる
  15. CRS
    • 地理座標系(経緯度の基準)の意味
    • 投影座標系の意味と種類
    • 暗黙裏に使用されている画面座標系
    • ファイルの CRS、画面の CRS、自動変換
    • GISに向いている座標系、向いていない座標系
    • 疑似メルカトルの利用上の注意
    • Tissot の指示楕円(時間的に余裕がある場合のみ)
  16. ベクタ解析(1)基本的な集合演算、位相演算
    • バッファ(位相演算、図形の近傍)
    • 共通部分の取得(集合演算)
    • 差分の取得(集合演算)
    • 合併の取得(集合演算)
    • マルチポリゴン化(位相演算、連結でない図形の承認)
    • 穴あきポリゴン(位相演算、単連結でない図形の承認)
  17. ベクタ解析(2)より進んだ演算
    • 以下は詳しい理論には踏み込まず、概要を紹介するに留める。興味を持つ者のためには参考文献を紹介する。多分現実的には時間が足りない
    • ボロノイ分割(位相演算、最近点分割)
    • 単体分割(位相演算、TIN の発生)
    • TIN を用いたスカラ場の補間、それによるラスタレイヤの発生
    • 経路探索
    • ベクトル場の表現と流路解析
  18. 参考になる話(難しすぎて参考にならないというツッコミはナシで)

 最初の方は操作説明の要素が強いが、次第に概念を理解させる部分が増えていく。概念が理解できてから、初めて対応する操作を紹介することになるだろう(でないと、操作だけ示されても、使いこなせないことは確実であるから)。
 それにしても、ベクタ解析の(2)までくると、これはもはや Quantum GIS マニュアルの守備範囲ではないような気もする。このレベルの概念の説明は、ワープロのマニュアルなのに修辞学が記載されているかのような話だもんね。

最近のはてなは広告を載せるようになったのね

 面倒だから、twitterFacebook だけに絞ろうかなぁ。
 いや、SNSだって広告も載っているのだけど、はてなの広告の載せ方はちょっと今ひとつ感が大きい。何よりも目立ちすぎだし、なぁ。