見出し画像

OpenStreetMapベースのユーザー地図作成サービスuMapの使い方メモ

Googleマイマップみたいなサービス。手軽なカスタマイズと再利用性。

動機: Google マイマップが定番ですが

Google マイマップでGoogle Map上にユーザー地図(地図の上に目的に応じてマーカーやら線やらを置いたもの)を作成することができます。とても便利なんですがちょっと想定と違う使い方をしたくなってつまってしまいました。具体的には以下のような点です。

  • ラベルを常時表示にしたい。

  • 地図を切り出して使いたい。

見ての通り、note.comはGoogle Mapの埋め込みに対応していますが、マーカーのラベルがズームレベルによって表示されたりされなかったりで、悩ましいです。それで別のサービスを使ってみました。

uMapの基本的な使い方

uMap https://umap.openstreetmap.fr/ja/

uMapはOpenStreetMap (OSM)の地図データの上にユーザー地図を作成するオンラインサービスです。ユーザー地図を作成するにはログインする必要があり、最初に会員登録が必要です。Twitterなどの外部サービスとの連携ログインに対応しています。

手動での編集

トップ画面から「マップを作成」ボタンをクリックして新規作成するか、以前に作成したものがあればヘッダー部分のメニューから「自分のマップ」をクリックしてそのマップにアクセスします。マップにアクセスしたら、右上のペンのアイコンをクリックして編集モードに入ります(新規作成時はこれが初期モードです)。ツールボックスが画面右側に黒く表示されます(左側のは編集用ではありません)。

uMapの編集モード。ラベルの表示方法などは後述。Map tiles by CartoDB, under CC BY 3.0. map data © OpenStreetMap contributors under ODbL

基本的な使い方はこちらのブログなどが参考になります。

おおまかには、Googleマイマップと方法は同じで、地図上でマーカーを設置し、プロパティを編集するだけです。また、「タイル」(背景地図の表示スタイル)を変更することができます。ツールボックスの「タイルレイヤの変更」ボタンを押すとタイルの選択肢が表示されます。

データの取り込み

データを手元のファイルから一括で地図上のマーカーに変換することができます。以下のようなCSVファイルをサンプルとして利用してみましょう。これは日本100名城リストを作ろうとして途中で挫折したものです。

利用できるcsvデータファイルの要件は以下のようです(正確な仕様は不明)。

  • 1行目がヘッダーで2行目以降がデータ本体となる。

  • 緯度・経度に使用できる列名は固定。それ以外の列は後述の設定をするとマーカーのプロパティで表示される。

    • 緯度列名: lat, latitude

    • 経度列名: long, longitude

    • ラベル列名: name

    • 説明列名: description

  • 文字コードはutf8なら大丈夫だった。

編集モードの時に、ツールボックスから「データインポート」ボタン(上矢印)を押して現れたプロパティ画面から「参照…」ボタンをおしてファイルを選択します。データ形式はcsvを選択します。レイヤーはデフォルトのままでもいいし適宜作成しても良いです。「インポート」ボタンを押します。

インポートしたマーカーのアイコンを一括変更する場合は、先ほどデータをインポートしたレイヤーの設定画面を使います。ツールボックスから「レイヤ管理」アイコンをクリックし出てきたレイヤーの一覧から、先ほどデータをインポートするのに使ったレイヤのペンのアイコン(編集ボタン)を押します。レイヤープロパティ画面が開くので「シェイプ表示プロパティ」をクリックするとアイコンの設定が変更できます。

同様に、ラベルを常に表示させるにはレイヤープロパティ画面の「ポップアップオプション」で「ラベルを表示」のところで設定します。ラベルとして表示させる列名を変更するには「拡張プロパティ」の「ラベル表示するキー」をその列名に変更します。

同様に、マーカーをクリックしたときのポップアップにインポートしたデータの各列を表示するには、「ポップアップオプション」の「ポップアップコンテンツのテンプレート」で{列名}のような指定を追加するか、全部表示したければ「Popup content style」をテーブルに設定します。

最後に、ヘッダー部分の「保存」および「編集を終了」を押して編集モードを終了し閲覧モードに戻ります。表示を確かめましょう。

利用のためのライセンスなど

uMapのライセンスについてもこちらのブログの解説が分かりやすいです。

筆者の理解(詳しいことは分かってない)では、今回のケースでuMapで作成した地図を利用する際に考慮すべきライセンスは以下の3つです (用語:ユーザー==ユーザー地図作成者、最終ユーザー==ユーザー地図利用者、作成物==ユーザー地図)。

  1. 元のOpenStreetMap => ODbL

    1. OpenStreetMapデータベースをそのまま地図にレンダリングして使用する場合 (今回が該当)

      • 作成物の最終ユーザーに対し帰属表示が必要。典型的には「Map data © OpenStreetMap contributors」となります。

      • uMapはOSMの上に構築されたサービスなのでOSMデータベースの利用にあたると理解しました。この形態ではデータベースの共有、データベースからの創作にあたり、帰属表示をしたうえでユーザー地図作成者は地図を最終ユーザーに配布できる、となります。

    2. OpenStreetMapデータベース(生データ)を複製または改変する場合 (今回は該当せず)

      • 複製または改変して作成した派生データベースのユーザーについても同じライセンス(すなわちODbL)を適用しなければならない。

      • その派生データベースを無償公開しなければならない。

  2. タイル => タイルによる

    • uMapのタイル(背景地図のデザイン)はサードパーティから提供されたものが含まれているので、そのライセンスは個別に異なります。ライセンス情報は、実際にタイルを適用すると、地図画面の右下にOSMのマップデータの帰属に加えて「tiles by …. under … 」と表示されていますのでそれを読んで判断します。

    • 例えば「Map tiles by CartoDB, under CC BY 3.0.」であれば同じ帰属表示を作成物の最終ユーザーに対してもリンク付きで行うことでユーザー地図作成者はタイルを無償で利用でき、作成物のライセンスには影響しません (CC BY 3.0の規定もご確認ください)。

    • この表示がないものはOpenStreetMapが提供しているものでCC BY-SAとなる、と思います。つまりユーザーの作成物も同じ条件で配布しなければならない、はずです。

    • 「tiles courtesy of …」の場合は、個別判断???

    • ので作成物の用途に応じてタイルの提供元とライセンスを確認してタイルを選択しておく必要があります。

  3. 今回作成するユーザー地図 => タイルライセンスを継承 or ユーザーが決める

    • OSMデータベースの影響については、上記1.2の場合と違い、今回は1.1に該当するため、作成するユーザー地図には「集合データベース」なる概念が適用され、ユーザー地図やユーザーが提供したマーカーの位置や属性のデータなどはODbL適用する必要はありません。

    • タイルの影響については、例えばタイルのライセンスがGPLやCC BY-SA (Share-Alike、継承)でなければ、ユーザーの作成物の最終ユーザーに対するライセンスはユーザーが決めることになると思います。

    • 先ほどのタイルの例「Map tiles by CartoDB, under CC BY 3.0.」であればShare-Alike条件はないのでタイルのライセンスとは異なる作成物ライセンスが選択可能です。

付け焼刃です。解釈がおかしいところや微妙なケースがあればご指摘ください。個人的にはODbLはLGPLに性質が似ているという印象です。

帰属表示の方法と場所ですが、「媒体や手段に対して適切な場所」とされており、必ずしも地図画像内に固執するものではないようです。リンクや埋め込みで提供する場合は、地図画面の右下に常に表示されるため自動的に満たされます。

利用のための出力や設定

デフォルトでは地図は公開状態になっています! 作成中やプライベートなものなど、アクセス制限が必要な場合は、編集モードに入り右の黒いツールボックスから「権限設定とエディタを更新」を選択して設定します。公開の準備ができたら再度アクセス権限を設定します。

ユーザー地図をオンラインで共有するためのリンクは左側の白い白いボタン群から「サイトへのマップ埋め込みと共有」を押して取得します。残念ながら note.com (このブログ)は埋め込みに対応してないようです。

さらに残念ながら図として出力する機能はないようですので、スクリーンショットをとるしかありません。

ローカルに地理情報データ(geojsonなど)を保存する場合はツールボックスの「マップ設定を編集」を押して「拡張アクション」から「ダウンロード」を押します。これの使いどころはイマイチ分かっていません (他のサービスへの引っ越しでしょうか?)。

現状での問題点

  • データの特定列の条件でマーカーの種類や色を変えられない。

    • (後述)

    • 種類が少なければ、ファイルを種類ごとに分けておきレイヤーで切り替えるという手はある(レイヤーごとの一括色変更は可能)。

  • データとして取り込んだマーカーの種類や色を手動で変えられない。

    • これは謎。手動で設置したマーカーは編集することができます。またレイヤーごとの一括変更は可能なので、あまり利用頻度は高くないので今のところあきらめています。

  • データを取り込み後に修正することができない。

    • これも手動で設置したマーカーは編集できます。代替策としては、データの方を編集して再アップロードですかね。

  • 住所で位置を指定してマーカーを刺すことができない。

uMapでのデータの条件による図形の変更

お店のカテゴリーやレーティングで色を変えたいということは多いと思われるので「データの特定列の条件でマーカーの種類や色を変えられない。」を何とかしたいと思います。

このセクションの方法を適用して条件による色付きマーカーを表示した例。Map tiles by CartoDB, under CC BY 3.0. map data © OpenStreetMap contributors under ODbL

uMapではCSV以外にgeojson形式でのデータのインポートに対応しています。geojsonをよくわかっていないのですが、マーカーの位置、形状、色など見た目にかかわる情報を直接制御できますので、ややローレベルになりますがCSVデータをあらかじめ自前のスクリプトでgeojsonに変換してインポートすることにします。

csv2umap_sample.py

import pandas as pd
import json
import sys

UMAP_COLORMAP_RANK1 = {
    "古代":"DarkRed",
    "中世":"Red",
    "戦国":"DarkOrange",
    "近世":"Orange",
    "近代":"LightOrange",
}
UMAP_COLOR_KEY = "era"
UMAP_LONG_KEY = "longitude"
UMAP_LAT_KEY = "latitude"

def gen_geojson_one(row_sr : pd.Series, color_col_str : str, colormap_dict : dict) -> dict:

    color_str = colormap_dict[row_sr[UMAP_COLOR_KEY]] if not (row_sr.isna()[UMAP_COLOR_KEY]) else "White"
    umap_dict = {
        "color":  color_str,
        # "iconClass": "Circle",
        # "labelDirection": "left"
    }
    umap_tmp_dict = { "_umap_options": umap_dict }
    filled_row_sr = row_sr.fillna("")
    properties_dict = filled_row_sr.to_dict()
    feature_dict = {
      "type": "Feature",
      "properties": dict(properties_dict, **umap_tmp_dict), 
      "geometry": {
        "type": "Point",
        "coordinates": [
          row_sr[UMAP_LONG_KEY],
          row_sr[UMAP_LAT_KEY],
        ]
      }
    }
    return feature_dict

def gen_geojson(df : pd.DataFrame, color_col_str : str, colormap_dict : dict) -> dict:

    # conv each entry in df to dict and put those in an list
    geojson_sr = df.apply(lambda x: gen_geojson_one(x, color_col_str, colormap_dict), axis=1)
    # gen envelope dict
    geojson_dict = {
        "type": "FeatureCollection",
        "features": geojson_sr.values.tolist(),
    }
    return geojson_dict

def proc_main(input_file, output_file) -> int:

    # load input
    input_df = pd.read_csv(input_file, encoding='utf8')
    # generate geojson for umap
    rank1_dict = gen_geojson(input_df, UMAP_COLOR_KEY, UMAP_COLORMAP_RANK1)
    # write output
    with open(output_file, 'w', encoding='utf8') as f:
        json.dump(rank1_dict, f, indent=2, ensure_ascii=False)

    return 0

##################################################
retcode = proc_main(sys.argv[1], sys.argv[2])
exit(retcode)

上記はPython 3.6以上でpandasモジュールが必要です。実行は以下のようにします。

  • python csv2umap_sample.py castle-sample.csv castle-sample.geojson

出力ファイル(castle-sample.geojson)の断片

{
  "type": "FeatureCollection",
  "features": [
    {
      "type": "Feature",
      "properties": {
        "name": "福岡城",
        "latitude": 33.584381,
        "longitude": 130.383103,
        "era": "近世",
        "i_have_been_to": 1,
        "description": "",
        "_umap_options": {
          "color": "Orange"
        }
      },
      "geometry": {
        "type": "Point",
        "coordinates": [
          130.383103,
          33.584381
        ]
      }
    },
    {
      "type": "Feature",
      "properties": {
        "name": "大野城",
        "latitude": 33.539916999999996,
        "longitude": 130.521556,
        "era": "古代",
        "i_have_been_to": 0,
        "description": "国の特別史跡",
        "_umap_options": {
          "color": "DarkRed"
        }
      },
      "geometry": {
        "type": "Point",
        "coordinates": [
          130.521556,
          33.539916999999996
        ]
      }
    },
...

生成されたgeojsonファイルを、前述のデータのインポートの手続きと同じようにアップロードします。データ形式はgeojsonを指定します。このサンプルではcsvファイルの"era"列 (時代)で色分けしています。

要は、geojsonファイルの中に _umap_options という属性があってベンダー固有の属性を埋め込んでいるらしいです(仕様は不明)。何が変更出来て何の値をとりうるかは、手でweb UI上で編集してgeojsonでエクスポートしてみないとわかりません (仕様があれば教えてください)。

他のサービスとの比較

  • uMap

  • Google マイマップ

    • マーカーのラベルの表示非表示はズームレベルや周辺のオブジェクトの配置に応じて自動で決定されるためユーザー側では変更できないものと認識。またそもそもデザインが見づらい。

    • インポート済みデータをウェブ上で編集したり、マーカーの属性値から自動的に色を変えたりといった機能が便利なので、再利用を考えなければやはり手っ取り早くユーザー地図を作れる選択肢である。

    • 地図がGoogle Mapなので最新の民間の店の情報などが入っているのがウリだと思うが用途によっては不要な情報が多すぎになる。

    • タイルの変更は限定的(プリセットの範囲内)に可能。表示物(道路、河川、地名 etc.)の制御はできない(たぶん)。

      • これに関してはGoogle Maps Platformで新規のスタイルを作成すると細かい制御ができるようだが使い方とかお値段などは分かっていない。もちろんAPIを駆使すれば色々できるんだとは思う。

    • ユーザー地図利用時のライセンスも結構難しく、地図の表示中に帰属とライセンスが表示されることを保障する必要がある。書籍などでの利用も諸々規定がある。また地図データは世界中の地図会社から提供されているため表示場所によって著作権者が違う。よって基本的には埋め込みによる利用が推奨される。

  • 地理院地図

    • 「Vector」なる新バージョンが登場し、河川や道路、地名などの表示物のオン・オフ設定を細かく制御できるようになった。

    • 当然のことながら地図には民間施設の営業時間とかレビューとかの情報は入っていない。地形や標高などのデータは豊富。教育・学術用途には強そう。

    • サーバーにユーザー地図を保存する機能はない(と思う)。ローカルにマーカーやタイルの設定をファイルで保存して次回編集時に再度アップロードする形になると思う。出力・利用は画像データが基本か。言い換えれば、会員登録する必要はない。

    • ズームアウトすると海が白くなる。海外地域の地図が表示されない。(前のバージョンではこんなことはなかったはず・・・)

    • 地図の再利用ライセンスは緩めで「一般の方が利用するようなケース」「成果物が地図としての利用を想定していないもの」は「出典明示だけで使える」という要領を得ない説明があるが、具体例を見るとかなり広い。(おそらく地図を使った運転・工事・調査・契約などのクリティカルな用途に使われないとはっきりしていればというニュアンスと思う(個人意見)。届け出が必要なケースは測量法に基づく措置らしい。)

      • ハンカチやTシャツ、紙袋などの製品にデザインとして印刷したもの

      • イラストや絵地図、作図ソフトで作った簡易的なもの

      • 一般的な資料(利用後は保管せずに廃棄する場合など)や論文、試験問題での利用

      • 書籍やパンフレット等への地図の挿入(一枚ものの地図、地図帳、折り込み地図、付録の地図等は除く)

  • MapBox

    • 多機能すぎて使い方がよく分かってない(また後日・・・)。基本的には他社ウェブサービスのバックエンドとして使う想定か。ユーザーマップというよりGoogle Maps Platformのレイヤーに相当するサービスかと思う。

    • 地図データはOSMを選択できるのでそこに関しては利用条件はおおむね同じ。有償サービスもある。

この記事が気に入ったらサポートをしてみませんか?