D&I Blog

このブログでは、今までに培ってきた技術的なことや、得意としている地図のことなどについて、幅広く取り扱っていこうと考えています。積極的に新しいことにチャレンジしたいメンバーもいるので、そのようなトピックも扱っていきたいと思います。

D&I BLOG

To mind the creative destruction

緯度経度表現における変換式

緯度経度の表現方法

私たちが普段目にする緯度経度には、実は色々な表現方法があるのをご存知でしょうか?私がざっと思いつく限り、以下の表現方法があります。

  • 度分秒形式
  • 度単位10進数形式
  • 秒形式

上記は、計算式によって相互に変換できるのですが、いざ変換しようとした際、変換式がすぐにでてこないという場合があります。

今回のブログでは、表現方法の簡単な解説と、変換式について紹介したいと思います。

なお私たちの会社の場所を、解説に使用する緯度経度として利用します。

度分秒形式

学校で地理を学んできた過程で、一番馴染みのある表現形式ですね。

表現例

緯度: 33° 51′ 10.59″
経度: 130° 45′ 17.86″

変換式

  • 度単位10進数形式
    • 緯度: 33 + ( 51 * 60 + 10.59 ) /3600 = 33.852942
    • 経度: 130 + ( 45 * 60 + 17.86 ) / 3600 = 130.75496
  • 秒形式
    • 緯度: ( 33 * 60 + 51 ) / 3600 + 10.59 = 121870.59
    • 経度: ( 130 * 60 + 45 ) / 3600 + 17.86 = 470717.86

度単位10進数形式

この形式は、Google Map 等で使われている表現形式です。またGISソフトウェア(ArcGISQGISなど)でも利用されている形式で、GIS関連で一般的に利用されている表現方法です。

表現例

緯度: 33.852942
経度: 130.75496

変換式

  • 度分秒形式(便宜上、Excelの数式を用いています。 INT()関数は、引数に与えられた数値の整数部分を取り出します。)
    • 緯度
      • 度の取り出し方: INT(33.852942) = 33
      • 分の取り出し方: INT( ( 33.852942 - 33 ) * 60 ) = 51
      • 秒の取り出し方:( ( 33.852942 - 33 - (51 / 60) ) * 3600 ) = 10.59
    • 経度
      • 度の取り出し方: INT( 130.75496 ) = 130
      • 分の取り出し方: INT( ( 130.75496 - 130 ) * 60 ) = 45
      • 秒の取り出し方: ( ( 130.75496 - 130 - (45 / 60) ) * 3600 ) = 17.86
  • 秒形式
    • 緯度: 33.852942 * 3600 = 121870.59
    • 経度: 130.75496 * 3600 = 470717.86

秒形式

GIS関連ではあまり使われない形式ですが、プログラムを書くときには、秒の加減算がしやすいので、私はよく利用しています。

表現例

緯度: 121870.59
経度: 470717.86

変換式

  • 度分秒形式(便宜上、Excelの数式を用いています。 INT()関数は、引数に与えられた数値の整数部分を取り出します。)
    • 緯度
      • 度の取り出し方: INT( 121870.59 / 3600 ) = 33
      • 分の取り出し方: INT( ( 121870.59 - ( 33 * 3600 ) ) /60 ) = 51
      • 秒の取り出し方:121870.59 - ( 33 * 3600 ) - ( 51 * 60 ) = 10.59
    • 経度
      • 度の取り出し方: INT( 470717.86 / 3600 ) = 130
      • 分の取り出し方: INT( ( 470717.86 - ( 130 * 3600 ) ) /60 ) = 45
      • 秒の取り出し方:470717.86 - ( 130 * 3600 ) - ( 45 * 60 ) = 17.86
  • 度単位10進数形式
    • 緯度: 121870.59 / 3600 = 33.852942
    • 経度: 470717.86 / 3600 = 130.75496

忘れた頃にやってくる緯度経度の変換式。皆さんの役に立つことがあれば嬉しいです。

Playbookを活用する。

前回の記事で、管理端末からターゲット端末に対して、Ansibleコマンドを用いて、PING送信やechoコマンドによりシェルを実行してみました。

しかし、一回一回Ansibleコマンドを実行していくのは大変な作業です。「Ansibleコマンドをまとめたバッチシェルを作成できないのか?」と思い浮かぶのですが、Ansibleには Playbook というファイルに、ターゲット端末に対しての命令をまとめて記述することができます。

今回は Playbook についての設定方法と、それを実行してみるところまで紹介したいと思います。

Playbookを書き始める前に

Playbook自身は YAML フォーマットで書いていくことになります。ここで簡単に YAML フォーマットの約束事を紹介します。

  • YAMLファイルを作成する際の文字コードは、UTF-8とします。
  • "---" は、一つのYAMLドキュメントの始まりであるという事を示します。
  • "..."は、一つのYAMLドキュメントの終わりであるという事を示します。
  • "-" は、配列を示します。
  • インデントは全てスペースで行います。タブは使用できません。
  • 要素名と値の間は":"で区切ります。":"のあとには最低1文字の空白を入れておく必要があります。ここでもタブは使用できません。
  • 行頭に"#"を入れることでコメントとして扱われます。なお、複数行をまとめてコメント化するような書き方はありません。
  • ファイル拡張子は、*.yml とします。

以上の事を念頭に置いて、YAMLで表現するデータ構造の例を見てみましょう。

# YAMLでデータ構造を表現してみる例です。
---
- A: 
    - a: apple
      b: banana
- B: 
    - a: orange
      b: strawberry
      c: cherry
...

実際にPlaybookを書いてみましょう

Playbookの書き方が分かったところで、つぎに実際にPlaybooksを書いてみましょう。

今回書いてみるPlaybookは、

  • zipコマンドをインストール

といったことを行って見たいと思います。

環境構成

f:id:d-and-i:20160904164817p:plain

インベントリファイルの配置

以下の内容でインベントリファイルを作成します。(具体的な作成手順は、こちらの記事を参考にしてください。)

192.168.10.2

Playbookの作成

任意の場所に web.yml という名前で、以下の内容のPlaybookを作成してみましょう。

---
- hosts: all   # /etc/ansible/hostsに描かれているすべてのほすとをターゲットにします。
  sudo: yes
  tasks: 
    - name: 共通で使用するパッケージをインストールする。
      yum:
        name=zip
        state=latest
...

Playbookの内容についての説明

  • hosts
    • 実行する先のターゲット端末を指定します。
  • sudo
    • sudoを用いて実行するかどうかを指定します。
  • tasks
    • タスクリストの開始を示します。
  • name
    • 各タスクの名前を示します。ここでは、わかりやすい名前をつけてあげると良いです。
  • yum
    • ansibleのモジュールを示します。ここではyumに対する操作を行うモジュールを使っていますが、他にも色々なモジュールが提供されていますので、近いうちに紹介したいと思います。
  • yum -> name
    • yumで何のパッケージをインストールするかをここで指定します。
  • yum -> state
    • yumでインストールするパッケージのバージョンをここで指定します。

Playbookの文法確認

作成したPlaybookの文法は以下のコマンドで確認が行えます。

$ ansible-playbook --syntax-check web.yml

Playbookの実行

Playbookの実行は、以下のコマンドを使用します。

$ ansible-playbook --ask-become-pass web.yml
SUDO password: 

PLAY [all] ******************************************************************** 

GATHERING FACTS *************************************************************** 
ok: [192.168.10.2]

TASK: [共通で使用するパッケージをインストールする。] **** 
ok: [192.168.10.2]

PLAY RECAP ******************************************************************** 
192.168.10.2                : ok=2    changed=0    unreachable=0    failed=0   

最後の行の PLAY RECAP の部分が実行ステータスとなります。「failed=0」となっていれば、特にエラーはおきていないことを示しています。

Ansible :: 初めてのインベントリファイル設定

以前の記事でAnsibleのインストール方法を紹介しました。今回は、インベントリファイルを設定し、実際にAnsibleがどういうものなのかを紹介していきたいと思います。

動作環境について

以下の環境が整っていることを前提に説明していきます。

  • 管理する側と管理される側のマシン間でSSH接続が行えること。
    • SSH接続する方法はこの記事を参考になります。
  • 管理する側のマシンにAnsibleがインストールされていること。
    • Ansibleのインストール方法はこの記事が参考になります。

なお「管理する側の端末」「管理される側の端末」という表現は、理解するのにややこしいので、

  • 管理する側の端末 =管理端末
  • 管理される側の端末 = ターゲット端末

と表現することとします。
※それでも表現がややこしいかもしれませんが、お許しください。

f:id:d-and-i:20160828171910p:plain

Ansibleを用いて疎通確認をしてみます。

まずは「インベントリファイル」を作ることから。

「インベントリファイル」とは、簡単に言うとターゲット端末のIPアドレスや、ドメイン名を記載したファイルです。

では、インベントリファイルを実際に作っていきましょう。

  1. /etc/ansible/hostsファイルを新規に作成します。
  2. /etc/ansible/hostsファイルにターゲット端末の情報を追加します。

/etc/ansible/hostsファイルを新規に作成・開きます。

$ sudo mkdir /etc/ansible
$ sudo touch /etc/ansible/hosts
$ sudo vi /etc/ansible/hosts

/etc/ansible/hostsファイルにターゲット端末の情報を追加します。

ターゲット端末が一台であった場合

f:id:d-and-i:20160828171910p:plain

IPアドレスで指定する場合は、

192.168.10.2

ドメイン名で指定する場合は、

targetserverA

となります。

ターゲット端末が複数台ある場合

f:id:d-and-i:20160828172703p:plain

IPアドレスで指定する場合は、

192.168.10.2
192.168.10.3

ドメイン名で指定する場合は、

targetserverA
targetserverB

となります。

なお、IPアドレスドメイン名の混在表記も可能です。

ターゲット端末へのPING送信

インベントリファイルが作成できたら、今度は管理端末からターゲット端末に対してPING送信してみます。

$ ansible all -m ping
$ targetServerA | success >> {         // PING送信が成功した例
    "changed": false, 
    "ping": "pong"
}

このPING送信が、上手く通れば疎通確認が行えたと言っても良いかと思います。

つぎにターゲット端末に対してシェルを実行してみましょう。

$ ansible all -a "/usr/bin/echo hello"
$ okisoftware | success | rc=0 >>     // echoコマンドを実行た例
    hello

結果は正しく表示されたでしょうか?今回の例では、"echo"コマンドを実行してみましたが、他のコマンドでも試してみて頂ければと思います。

この疎通がうまくできたようであれば、Ansibleを使い始める環境を整えることができたということになります。

Google Maps API上にKMLデータを載せる際の制限事項

Google Maps API を利用して、地図上にKMLデータを載せようとする場合は、以下のような制限事項があります。

  1. KMLファイルのファイルサイズの上限が10MByteまで
  2. KMLファイルを圧縮した形態であるKMZファイルサイズの上限が3MByteまで
  3. 1ファイル(KML or KMZ)あたりの図形の数が1,000個まで
  4. 重ね合わせるレイヤ数は、KML or KMZファイルへアクセスするためのURLの長さで決定される。

「4.」については少し曖昧な表現をしていますが、Googleのドキュメントを確認すると、以下のことが補足で書いてあります。

  • 一般的なURL(:階層が深くないURL)だと、大体平均して10〜20ぐらいのレイヤが表示できます。
  • URLの長さでの制限に引っかかってしまった場合は、地図上にKML/KMZデータは表示されなくなりますので、短縮URLなどを利用してURLの長さを短くして下さい。

参考までに、上述についてのGoogleのドキュメントを以下に掲載しておきます。 f:id:d-and-i:20160821205445p:plain

なお、Google Maps APIを利用してKML/KMZファイルを重ねる場合は、誰でも参照できる場所に配置しておく必要があります。

もし、閉じたネットワーク内に配置したり、(ログイン処理が必要とするような)アクセス制限がかかっている場所に配置したりすると、重ねようとしているKMLデータは表示されませんので注意して下さい。

Ansible :: インストール方法

環境構築の手順書を書くのが面倒だったんです。

これまでのお仕事をさせて頂いている中で、幾度となく案件用に開発環境を構築してきました。 その度に「開発環境構築の手順書」なるものを書いてきたのですが、その手順書内に「誤記」「抜け」「間違い」「書かなくても出来るだろうという思い込み」があったりして、手順書を書くにも非常に大きな労力を必要としてきました。

この労力については、どうにかして「誰にでもできて」「自動化できないものか?」ということが社内での議論となり

といった構成管理ツールを使ってみようということになりました。

Chef と Ansible を比較してみて

早速、ChefとAnsibleを使用してみましたところ、つぎのような感触を得ることができました。 ※あくまで、すこし触ってみた第一印象です。

  • Chef
    • 一つの環境を複数人で一緒に構築していくのには向いている。
    • 使いたいと思った時に、(どうも使い方が難しくて)サクッと使い始めることができなかった。
  • Ansible

普段は、大人数で一緒に環境を構築していくことはなく、簡単にすぐに使い始めれるのであればということで「Ansible」を使い始めていくことにしました。 f:id:d-and-i:20160813161048p:plain

Ansibleのインストール方法

さて本ブログの本題に入っていくわけですが、私(このブログを書いている本人)は普段Macを使用しています。ですので、これから紹介するAnsibleのインストール方法は、ホスト機がMacであるということを前提に説明します。

なおAnsibleのインストール方法はすごく簡単ですので、構えずに読んで頂ければ幸いです。

大まかな手順

  1. Homebrew をインストールします。
  2. PYTHONをインストールします。
  3. Ansibleをインストールします。

具体的な手順

Homebrewをインストールします。

$ ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)"

※Homebrewについての詳細はこちら

PYTHONをインストールします。

$ brew install -y python

Ansibleをインストールします。

$ CFLAGS=-Qunused-arguments CPPFLAGS=-Qunused-arguments pip install ansible

参考資料

さいごに

Ansibleを使い始めてから約1年弱になりますが、未だに使い易い構成管理ツールだと思っています。今後のブログの中で、より詳細な使い方について説明していければと考えております。

地図の誤差許容範囲について

地図を作製する際の許容誤差って知っていますか?

実は、地図を作製する際に、国土地理院がこの規定で約束を守ってねと言う指示書があります。それが「国土交通省公共測量作業規定」と呼ばれるものです。

その規定(「国土交通省公共測量作業規定」の第71条(地形図等の精度))の中で、

  • 1/500 以上では 水平位置0.50mm以内
  • 1/1,000以下では、水平位置0.70mm以内

を守ってくださいねとの指示が記載されています。

現在では、国土交通省公共測量作業規程(平成28年3月31日国国地第190号)は、測量法第34条の規定に基づき定められた作業規程の準則(平成20年国土交通省告示第413号、平成28年3月31日一部改正)の文言を読み替え、準用しているとのことですが、

  • 第80条 数値地形図データの位置精度及び地図情報レベルは、次表を標準とする。

で定義されていることから、「国土交通省公共測量作業規定」の内容と変化はありません。 f:id:d-and-i:20160807221014p:plain (図1 作業規定の準則)

実寸での誤差を計算するとどのくらい?

「図1 作業規定の準則」に示される地図情報レベルに照らしあわせて最大実寸誤差を計算すると以下のようになることがわかります。

f:id:d-and-i:20160807224100p:plain

なお、「図1 作業規定の準則」に示されている通り、地図情報レベルの後に続く数字と縮尺の関係は一致していることも知っておいてくださいね。

よく市販されている道路地図などは、縮尺が1/15,000で作成されているものが多く、その地図を利用すると「最大10.5m(15,000 × 0.7mm)の誤差がある」ということがわかります。

QGISで地理院タイルを表示してみよう

用意するもの

  • QGIS ※本ブログではMac版のQGISを利用しています。
  • インターネット環境

具体的な作業

TileLayer Plugin を QGISにインストールします。

  1. QGISを起動します。
  2. プラグイン」->「プラグインの管理とインストール」を選択します。
  3. 検索ボックスより「tilelayer」と入力することで、「TileLayer Plugin」がリスト上に現れますので、それを選択し「プラグインをインストール」ボタンを押します。 f:id:d-and-i:20160730103158p:plain

  4. 正常にインストールできたら、「Close」ボタンを押します。

タイルレイヤプラグインを使用するための外部レイヤ定義ディレクトリを作成・設定します。

  1. 外部レイヤ定義ディレクトリを作成します。私の場合は、 ~/work/QGIS/TileLayerPlugin というディレクトリを新規に作成しました。
  2. 先ほど作成した、外部レイヤ定義ディレクトリ内に、レイヤ定義ファイルを配置します。ここで、配置するファイルはTileLayer Plugin内に公開されているファイルを使用します。

    現在のファイル配置状況 ~/work/QGIS/TileLayerPlugin/GSIMaps.tsv ~/work/QGIS/TileLayerPlugin/GSIMapsDisaster.tsv

タイルレイヤプラグインの設定をします。

  1. QGISの「Web」->「タイルレイヤプラグイン」->「タイルレイヤを追加する」を選択します。
  2. 「設定」ボタンを押します。
  3. 今後の使い勝手を良くするために「プラグインをレイヤメニュー/ツールバーに移動する」にチェックを入れ「OK」ボタンを押します。 f:id:d-and-i:20160730105036p:plain
  4. レイヤメニューに「タイルレイヤプラグイン」が移動されるのを確認します。
  5. 「設定」ボタンを押します。
  6. 事前に作成しておいた「外部レイヤ定義ディレクトリ」の指定を行い、「OK」ボタンを押すことで、タイルレイヤプラグインの設定が完了します。 f:id:d-and-i:20160730111858p:plain

QGIS上に表示するタイルレイヤを選択する。

  1. レイヤメニュー または 「レイヤ」->「レイヤの追加」->「タイルレイヤを追加する」からタイルレイヤプラグインの画面を表示します。
  2. この時点で既にプラグインの設定を終えているので、一覧に表示された任意タイルレイヤを選択し「追加」ボタンを押すことでQGIS上に地理院タイルを表示することができます。 f:id:d-and-i:20160730113304p:plain

補足事項

  • 地理院タイル図を使うときの座標系番号(:epsg)は 3857 となっているようです。ですので、手持ちの情報を重ね合わせる時は、QGIS上でのOTF機能を利用するか、座標系番号を合わせる必要があります。