GIS奮闘記

元GISエンジニアの技術紹介ブログ。主にPythonを使用。

スポンサーリンク

Python で地域メッシュコードを緯度経度に変換する方法

最近は ArcGIS API for JavaScript の話が続いてしまっていたので、今回は気分を変えて Python を使って地域メッシュコードを緯度経度に変換してみようと思います。緯度経度を地域メッシュコードに変換したい方は以下のエントリーを参考にしてみてください。

www.gis-py.com

地域メッシュとは

地域メッシュ(ちいきメッシュ)とは、統計に利用するために、緯度・経度に基づいて地域をほぼ同じ大きさの網の目(メッシュ)に分けたものである。メッシュを識別するためのコードを地域メッシュコードと言う。(地域メッシュ - Wikipedia

地域メッシュは区分の方法により、大きさの異なるいくつかの区画が定められています。

・1次メッシュ: 一辺約80km.
・2次メッシュ: 一辺約10km. 1次メッシュを縦横8分割したもの。
・3次メッシュ: 一辺約1km. 2次メッシュを縦横10分割したもの。
・4次メッシュ: 一辺約500m. 3次メッシュを縦横2分割したもの。
・5次メッシュ: 一辺約250m. 4次メッシュを縦横2分割したもの。
・6次メッシュ: 一辺約125m. 5次メッシュを縦横2分割したもの。

ESRIジャパンさんが詳しく説明してくれているので、気になる方はぜひ以下を読んでみてください。

標準地域メッシュ | ESRIジャパン

実行環境

Windows 10
Python 3.6.6

地域メッシュから緯度経度を割り出すサンプルコード

1~3次メッシュまで対応させたサンプルコードを作成しました。

def get_latlon(meshCode):

    # 文字列に変換
    meshCode = str(meshCode)

    # 1次メッシュ用計算
    code_first_two = meshCode[0:2]
    code_last_two = meshCode[2:4]
    code_first_two = int(code_first_two)
    code_last_two = int(code_last_two)
    lat  = code_first_two * 2 / 3
    lon = code_last_two + 100

    if len(meshCode) > 4:
        # 2次メッシュ用計算
        if len(meshCode) >= 6:
            code_fifth = meshCode[4:5]
            code_sixth = meshCode[5:6]
            code_fifth = int(code_fifth)
            code_sixth = int(code_sixth)
            lat += code_fifth * 2 / 3 / 8
            lon += code_sixth / 8

        # 3次メッシュ用計算
        if len(meshCode) == 8:
            code_seventh = meshCode[6:7]
            code_eighth = meshCode[7:8]
            code_seventh = int(code_seventh)
            code_eighth = int(code_eighth)
            lat += code_seventh * 2 / 3 / 8 / 10
            lon += code_eighth / 8 / 10

    print(lat, lon)

if __name__ == '__main__':
    get_latlon(52396594)

例えば、52396594 を引数にして実行すると「35.24166666666667 139.675」という形で緯度経度を取得することができます。これがどこかといいますと、横須賀のとある地域ですね。

f:id:sanvarie:20200229221902p:plain

それではこの結果が本当に正しいか確認してみます。以下のサイトで地域メッシュコードの一覧を入手することができます。

統計局ホームページ/市区町村別メッシュ・コード一覧

地名までは載っていないのですが、52396594 は横須賀市ということがわかります。

f:id:sanvarie:20200229222512p:plain

意外と簡単に地域メッシュコードを緯度経度に変換することができるということがわかりました。今度は地域メッシュコードからその範囲のポリゴンを作成させたり、あとは、緯度経度から地域メッシュコードに変換したりしてみたいですね。本日は以上です。

ArcGIS API for JavaScript でレイヤーにフィルターをかける方法

最近 ArcGIS API for JavaScript について書くことが多いのですが、本日も ArcGIS API for JavaScript について書いてみようと思います。前回のエントリーでは レイヤーのセレクトボックスを選択した際にそのレイヤーのフィールドを別のセレクトボックスに格納する方法について書いてみました。今回はその続きです。選択したレイヤーとフィールドを使用して、レイヤーにフィルターをかける方法について書いてみようと思います。前回のエントリーに興味がある方はぜひ読んでみてください。

www.gis-py.com

完成イメージ

ちょっと見づらいのですが、実行ボタンを押下すると「神奈川」レイヤーの「SIKUCHOSON」フィールドが「横須賀市」のフィーチャが抽出されます。

f:id:sanvarie:20200211215003p:plain

f:id:sanvarie:20200211215212p:plain

フィルターを解除する場合は、「フィルター」項目を空白にして実行ボタンを押下します。

f:id:sanvarie:20200211215305p:plain

実行環境

ArcGIS API for JavaScript 4.14
Google Chrome 最新版(2020/2/11 時点)

フィルター処理について解説

FeatureLayer クラスの definitionExpression プロパティを使用してフィルター処理を行います。getActiveField() メソッドで選択しているフィールドのオブジェクトを取得し、それを利用してフィルター用の式を作成しています。

// 選択したフィールドを取得
function getActiveField() {
    var ddFieldList = document.getElementById("ddFieldList");
    var selectedIndex = ddFieldList.options.selectedIndex;
    return ddFieldList.options[selectedIndex].field;
}

// フィルター処理
function filterFeatures() {
    var txtSearch = document.getElementById("txtSearch");
    var featureLayer = getActiveLayer();

    // 空だったらフィルター解除
    if (txtSearch.value == "") {
        featureLayer.definitionExpression = txtSearch.value
    } else {
        var activeField = getActiveField();
        var type = activeField.type;
        var expression;

        if (type = "string"){
            expression = activeField.name + "=" + "'" + txtSearch.value + "'";
        } else {
            expression = activeField.name + "=" + txtSearch.value;
        }
        featureLayer.definitionExpression = expression;
    }      
}

サンプルコード

以下に全コードを記載します。

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <style>
    html,
    body,
    #divMapView {
        padding: 0;
        margin: 0;
        width:100%;
        height:100%;
    }
    #divToolbar {
        top:0;
        width:100%;
        position: fixed;
        background:rgba(0,0,0,0.6);
        color: white;
    }
    #searchBox {
        width:100px;
        right:0;
        position: absolute;
        background-color: rgba(255,255,255);
        color: black;
    }

    </style>
    <title>レイヤー一覧</title>
    <link rel="stylesheet" href="https://js.arcgis.com/4.14/esri/css/main.css">
    <script src="https://js.arcgis.com/4.14/"></script> 
    <script>
    
     // WebMapのレイヤーをセレクトボックスに格納する
     function loadLayers(layers) {
      var ddLayerList = document.getElementById("ddLayerList");
       layers.forEach(l => {
            let o = document.createElement("option");
            o.textContent = l.title;
            o.layer = l;
            ddLayerList.appendChild(o)
       });

       // 最初は未選択の状態にする
       ddLayerList.selectedIndex = -1;
     }

     // レイヤーセレクトボックス変更時の処理
     function onLayerChange(e) {
        var layer = getActiveLayer(); 
        getFieldName(layer);
     }

     // レイヤーのカラムを取得
     function getFieldName(layer) {
        var ddFieldList = document.getElementById("ddFieldList");

        // セレクトボックスの要素を削除
        removeOptions(ddFieldList);

        // セレクトボックスに要素を追加
        layer.fields.forEach(function(field){
            let o = document.createElement("option");
            o.textContent = field.name;
            o.field = field;
            ddFieldList.appendChild(o);
      });
     }

     // セレクトボックスの要素削除
     function removeOptions(selectBox){
        var i;
        for(i = selectBox.options.length - 1 ; i >= 0 ; i--)
        {
            selectBox.remove(i);
        }
     }

     // 選択したレイヤーを取得
     function getActiveLayer() {
        var ddLayerList = document.getElementById("ddLayerList");
        var selectedIndex = ddLayerList.options.selectedIndex;
        return ddLayerList.options[selectedIndex].layer;
     }

     // 選択したフィールドを取得
     function getActiveField() {
        var ddFieldList = document.getElementById("ddFieldList");
        var selectedIndex = ddFieldList.options.selectedIndex;
        return ddFieldList.options[selectedIndex].field;
     }

     // フィルター処理
     function filterFeatures() {
        var txtSearch = document.getElementById("txtSearch");
        var featureLayer = getActiveLayer();

        // 空だったらフィルター解除
        if (txtSearch.value == "") {
            featureLayer.definitionExpression = txtSearch.value
        } else {
            var activeField = getActiveField();
            var type = activeField.type;
            var expression;

            if (type = "string"){
                expression = activeField.name + "=" + "'" + txtSearch.value + "'";
            } else {
                expression = activeField.name + "=" + txtSearch.value;
            }
            featureLayer.definitionExpression = expression;
        }      
     }
      
     require (["esri/WebMap", "esri/views/MapView"],
     (WebMap,MapView) => {
        const map = new WebMap({
            "portalItem" : {
                "id" : "adfcbd5d28174451b61ec8c0195af577"
            }
        });
        const mapView = new MapView({ 
            "container" : "divMapView",
            "map" : map
        })
        
        map.when(() => {
            loadLayers(map.layers);
            var ddLayerList = document.getElementById("ddLayerList");
            ddLayerList.addEventListener("change", onLayerChange);
        })
     })  
    </script>
</head>
<body>
    <div id = 'divMapView'></div>
    <div id = 'divToolbar'>
        <label>レイヤー</label>
        <select id = 'ddLayerList'>
        </select>
        <label>フィールド</label>
        <select id = 'ddFieldList'>
        </select>
        <label>フィルター</label>
        <input type = 'text' id = 'txtSearch' class = 'searchBox'>
        <button id="executeFilter" type="button" onClick="filterFeatures()">実行</button>
    </div>
</body>
</html>

他のレイヤーにもフィルターをかけてみました。

f:id:sanvarie:20200211220406p:plain

f:id:sanvarie:20200211220510p:plain

いい感じですね!

機能的には大したことはないと思いますが、地道に勉強してみようと思います。やはりこれからは Web GIS の時代なので、ArcGIS API for JavaScript について覚えておいて損は無いかと思います。本ブログでは ArcGIS API for JavaScript について色々紹介しているので、興味のある方は以下エントリーをぜひ読んでみてください。

www.gis-py.com

www.gis-py.com

www.gis-py.com

本日は以上です。

ArcGIS API for JavaScript でレイヤーのフィールドをセレクトボックスに格納する方法

さて、本日も ArcGIS API for JavaScript について書いてみようと思います。前回のエントリーでは Web Map のレイヤーをセレクトボックスに格納する方法について書いてみました。今回はその続きです。レイヤーのセレクトボックスを選択した際にそのレイヤーのフィールドを別のセレクトボックスに格納するというものです。前回のエントリーに興味がある方はぜひ読んでみてください。

www.gis-py.com

完成イメージ

以下のように「レイヤー」「フィールド」セレクトボックスを作成します。

f:id:sanvarie:20200202200006p:plain

「レイヤー」セレクトボックスの選択時に「フィールド」セレクトボックスにそのレイヤーのフィールドを格納します。 f:id:sanvarie:20200202200059p:plain

f:id:sanvarie:20200202200241p:plain

実行環境

ArcGIS API for JavaScript 4.14
Google Chrome 最新版(2020/2/2 時点)

ポイントとなる処理

  1. Web Mapのレイヤーをセレクトボックスに格納する
  2. レイヤーセレクトボックス変更時の処理
  3. レイヤーのカラムを取得

WebMapのレイヤーをセレクトボックスに格納する

こちらは前回のエントリーでも紹介しましたが、大事な部分なので本エントリーでも紹介します。マップ読み込み時に map.when が実行され、その中で loadLayers() が実行され、「レイヤー」セレクトボックスにレイヤー名が格納されます。

// マップ読み込み時
map.when(() => {
    loadLayers(map.layers);
    var ddLayerList = document.getElementById("ddLayerList");
    ddLayerList.addEventListener("change", onLayerChange);
})

function loadLayers(layers) {
  var ddLayerList = document.getElementById("ddLayerList");
  layers.forEach(l => {
       let o = document.createElement("option");
       o.textContent = l.title;
       o.layer = l;
       ddLayerList.appendChild(o)
  });

  // 最初は未選択の状態にする
  ddLayerList.selectedIndex = -1;
}

レイヤーセレクトボックス変更時の処理

レイヤーセレクトボックス変更時に onLayerChange() が実行されるように設定します。設定は上記ソース参照(map.when でマップ読み込み時に addEventListener() で設定)

// レイヤーセレクトボックス変更時の処理
function onLayerChange(e) {
  var layer = getActiveLayer(); 
  getFieldName(layer);
}

// 選択したレイヤーを取得
function getActiveLayer() {
  var ddLayerList = document.getElementById("ddLayerList");
  var selectedIndex = ddLayerList.options.selectedIndex;
  return ddLayerList.options[selectedIndex].layer;
}

レイヤーのカラムを取得

最初に removeOptions() でセレクトボックスの要素を削除してから要素の追加を行います。

// レイヤーのカラムを取得
function getFieldName(layer) {
   var ddFieldList = document.getElementById("ddFieldList");
   // セレクトボックスの要素を削除
   removeOptions(ddFieldList);
   // セレクトボックスに要素を追加
   layer.fields.forEach(function(field){
       let o = document.createElement("option");
       o.textContent = field.name;
       ddFieldList.appendChild(o);
  });
}
// セレクトボックスの要素削除
function removeOptions(selectBox){
   var i;
   for(i = selectBox.options.length - 1 ; i >= 0 ; i--)
   {
       selectBox.remove(i);
   }
}

サンプルコード

以下に全コードを記載します。

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <style>
    html,
    body,
    #divMapView {
        padding: 0;
        margin: 0;
        width:100%;
        height:100%;
    }
    #divToolbar {
        top:0;
        width:100%;
        position: fixed;
        background:rgba(0,0,0,0.6);
        color: white;
    }

    </style>
    <title>レイヤー一覧</title>
    <link rel="stylesheet" href="https://js.arcgis.com/4.14/esri/css/main.css">
    <script src="https://js.arcgis.com/4.14/"></script> 
    <script>
    
     // WebMapのレイヤーをセレクトボックスに格納する
     function loadLayers(layers) {
      var ddLayerList = document.getElementById("ddLayerList");
       layers.forEach(l => {
            let o = document.createElement("option");
            o.textContent = l.title;
            o.layer = l;
            ddLayerList.appendChild(o)
       });

       // 最初は未選択の状態にする
       ddLayerList.selectedIndex = -1;
     }

     // レイヤーセレクトボックス変更時の処理
     function onLayerChange(e) {
        var layer = getActiveLayer(); 
        getFieldName(layer);
     }

     // レイヤーのカラムを取得
     function getFieldName(layer) {
        var ddFieldList = document.getElementById("ddFieldList");

        // セレクトボックスの要素を削除
        removeOptions(ddFieldList);

        // セレクトボックスに要素を追加
        layer.fields.forEach(function(field){
            let o = document.createElement("option");
            o.textContent = field.name;
            ddFieldList.appendChild(o);
      });
     }

     // セレクトボックスの要素削除
     function removeOptions(selectBox){
        var i;
        for(i = selectBox.options.length - 1 ; i >= 0 ; i--)
        {
            selectBox.remove(i);
        }
     }

     // 選択したレイヤーを取得
     function getActiveLayer() {
        var ddLayerList = document.getElementById("ddLayerList");
        var selectedIndex = ddLayerList.options.selectedIndex;
        return ddLayerList.options[selectedIndex].layer;
     }
      
     require (["esri/WebMap", "esri/views/MapView"],
     (WebMap,MapView) => {
        const map = new WebMap({
            "portalItem" : {
                "id" : "adfcbd5d28174451b61ec8c0195af577"
            }
        });
        const mapView = new MapView({ 
            "container" : "divMapView",
            "map" : map
        })
        
        map.when(() => {
            loadLayers(map.layers);
            var ddLayerList = document.getElementById("ddLayerList");
            ddLayerList.addEventListener("change", onLayerChange);
        })
     })  
    </script>
</head>
<body>
    <div id = 'divMapView'></div>
    <div id = 'divToolbar'>
        <label>レイヤー</label>
        <select id = 'ddLayerList'>
        </select>
        <label>フィールド</label>
        <select id = 'ddFieldList'>
        </select>
    </div>
</body>
</html>

動きを確認してみると以下のようになるかと思います。

f:id:sanvarie:20200202201458p:plain

f:id:sanvarie:20200202201527p:plain

f:id:sanvarie:20200202201558p:plain

意外とすんなり完成しました。私は正直 Web プログラミングは得意ではないので、あまり複雑なことはできないのですが、拙いながらも一応目的は達成することができました。今後も ArcGIS API for JavaScript を使っていき、Web GIS の時代から取り残されないように頑張ろうと思います。本ブログでは ArcGIS API for JavaScript について色々紹介しているので、興味のある方は以下エントリーをぜひ読んでみてください。

www.gis-py.com

www.gis-py.com

www.gis-py.com

本日は以上です。

ArcGIS API for JavaScript でWeb Map にあるレイヤーをセレクトボックスに格納する方法

さて、本日は ArcGIS API for JavaScript を使ってみたいと思います。レイヤーをArcGIS Online に共有することはよくあると思いますが、それと同じくらい マップを 共有することもあるかと思います。今回は Web Map として共有したマップに含まれているレイヤーをセレクトボックスに格納する方法について紹介します。

実行環境

ArcGIS API for JavaScript 4.14
Chrome

データ

以下エントリーで使用した神奈川県のデータを使用しました。

www.gis-py.com

上記データを Web Map としてArcGIS Online に共有しました。

f:id:sanvarie:20200201224639p:plain

f:id:sanvarie:20200201230012p:plain

ポイント

セレクトボックスの作成

以下のようにセレクトボックスを作成します。

<div id = 'divToolbar'>
    <label>レイヤー</label>
    <select id = 'ddLayerList'>
    </select>
</div>

Web Map の読み込み

以下のように WebMap クラスを使用します。そして、作成した Web Map の ID を設定してください。

const map = new WebMap({
    "portalItem" : {
        "id" : "adfcbd5d28174451b61ec8c0195af577"
    }
});

Web Map に格納されているレイヤーの取得

loadLayers というメソッドを作成します。その中でセレクトボックスに各レイヤー名称を格納しています。

map.when(() => loadLayers(map.layers))

function loadLayers(layers) {
  const ddLayerList = document.getElementById("ddLayerList");
   layers.forEach(l => {
        let o = document.createElement("option");
        o.textContent = l.title;
        o.layer = l;
        ddLayerList.appendChild(o)
   });
 }

サンプルコード

こちらがすべてのコードです。

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <style>
    html,
    body,
    #divMapView {
        padding: 0;
        margin: 0;
        width:100%;
        height:100%;
    }
    #divToolbar {
        top:0;
        width:100%;
        position: fixed;
        background:rgba(0,0,0,0.6);
        color: white;
    }

    </style>
    <title>レイヤー一覧</title>
    <link rel="stylesheet" href="https://js.arcgis.com/4.14/esri/css/main.css">
    <script src="https://js.arcgis.com/4.14/"></script> 
    <script>
    
     function loadLayers(layers) {
      const ddLayerList = document.getElementById("ddLayerList");
       layers.forEach(l => {
            let o = document.createElement("option");
            o.textContent = l.title;
            o.layer = l;
            ddLayerList.appendChild(o)
       });
     }
     
     require (["esri/WebMap", "esri/views/MapView"],
     (WebMap,MapView) => {
        const map = new WebMap({
            "portalItem" : {
                "id" : "adfcbd5d28174451b61ec8c0195af577"
            }
        });
        const mapView = new MapView({ 
            "container" : "divMapView",
            "map" : map
        })
        
        map.when(() => loadLayers(map.layers))
          
     })  
    </script>
</head>
<body>
    <div id = 'divMapView'></div>
    <div id = 'divToolbar'>
        <label>レイヤー</label>
        <select id = 'ddLayerList'>
        </select>
    </div>
</body>
</html>

ばっちりレイヤー名がセレクトボックスに格納されました!○○名というレイヤーは実はポイントレイヤーだったりと少々わかりづらいところがあるデータですが、今回は各レイヤー名の取得にフォーカスを置いているのでとりあえずよしとします。 f:id:sanvarie:20200201231015p:plain

Web GIS が主流になりつつあるため、今後ますます ArcGIS API for JavaScript の重要性が高まるかと思います。自分ももう少し色々勉強しなければならないと感じています。これからもどんどん ArcGIS API for JavaScript について書いていこうと思います。本日は以上です。

ArcGIS Runtime SDK for .NET を使ってみよう!

さて、本日は ArcGIS Runtime SDK for .NET を使ってみようと思います。今まで興味はあったもののなかなか触る機会のなかった SDK なのでとても楽しみです。

ArcGIS Runtime SDK for .NET とは

ArcGIS Runtime SDK for .NET は Windows 及び iOS、Android プラットフォーム上で動作するネイティブ GIS アプリケーションの開発キットであり、Windows デスクトップや Windows タブレット、iOS、Android などの多様なプラットフォーム向けに様々な GIS 機能を持ったアプリケーションを開発することができます。

ArcGIS Runtime SDK for .NET | ESRIジャパン

特徴

ArcGIS Runtime SDK for .NET はファイルジオデータベースを読み込んで SA アプリを開発することもできるのですが、どちらかというと Web のデータにアクセスすることを前提にしている SDK だと思います。GIS は Web 化の傾向にあるので、時代のニーズにあった SDK といえるのではないでしょうか。

Web に重きを置いているので、バリバリデータを編集するようなアプリの開発を検討しているという方は ArcGIS Runtime SDK for .NET よりも ArcGIS Pro SDK を使用した方がいいかと思います。興味のある方は以下のエントリーを読んでみてください。

www.gis-py.com

当ブログでは ArcGIS Pro SDK のサンプルなどは公開していないのですが、以下サイトでサンプルコードを公開しているので、ぜひ参考にしてみてください。

1−ArcGIS Pro SDK for .NET を使用した機能開発 ~マップと... | GeoNet, The Esri Community | GIS and Geospatial Professional Community

開発の前に必要なこと

ArcGIS Developer Subscription というサブスクリプションプログラムに登録する必要があります(無料)。製品詳細 | ESRIジャパン
また、SDK のインストールも行います。https://developers.arcgis.com/downloads/apis-and-sdks

今回やってみること

マップの作成とレイヤーの読み込み(始めてなのでまずは簡単なところから挑戦してみようと思います)

読み込むレイヤーは以下の日本地図です(ArcGIS Online で表示)。 f:id:sanvarie:20200119204052p:plain

実行環境

Windows10 64bit
Visual Studio 2017
ArcGIS Runtime SDK for .NET 100.7.0

サンプル

以下のサイトを参考にしてみました。 Add layers to a map | ArcGIS for Developers

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Runtime.CompilerServices;
using Esri.ArcGISRuntime.Data;
using Esri.ArcGISRuntime.Geometry;
using Esri.ArcGISRuntime.Location;
using Esri.ArcGISRuntime.Mapping;
using Esri.ArcGISRuntime.Security;
using Esri.ArcGISRuntime.Symbology;
using Esri.ArcGISRuntime.Tasks;
using Esri.ArcGISRuntime.UI;

namespace RuntimeTest
{
    /// <summary>
    /// Provides map data to an application
    /// </summary>
    public class MapViewModel : INotifyPropertyChanged
    {
        public MapViewModel()
        {
            CreateNewMap();
        }

        private async void CreateNewMap()
        {
            // オープンストリートマップをベースマップにする
            Map newMap = new Map(Basemap.CreateOpenStreetMap());

            // フィーチャレイヤーを読込
            FeatureLayer featurelayer = new FeatureLayer(new Uri("https://services.arcgis.com/P3ePLMYs2RVChkJx/ArcGIS/rest/services/JPN_Boundaries_ECM/FeatureServer/0"));
            await featurelayer.LoadAsync();

            // フィーチャレイヤーをマップに追加
            newMap.OperationalLayers.Add(featurelayer);

            // 起動時の表示範囲を設定
            newMap.InitialViewpoint = new Viewpoint(featurelayer.FullExtent);

            Map = newMap;
        }

        private Map _map = new Map(Basemap.CreateStreetsVector());

        /// <summary>
        /// Gets or sets the map
        /// </summary>
        public Map Map
        {
            get { return _map; }
            set { _map = value; OnPropertyChanged(); }
        }

        /// <summary>
        /// Raises the <see cref="MapViewModel.PropertyChanged" /> event
        /// </summary>
        /// <param name="propertyName">The name of the property that has changed</param>
        protected void OnPropertyChanged([CallerMemberName] string propertyName = null)
        {
            var propertyChangedHandler = PropertyChanged;
            if (propertyChangedHandler != null)
                propertyChangedHandler(this, new PropertyChangedEventArgs(propertyName));
        }

        public event PropertyChangedEventHandler PropertyChanged;
    }
}

アプリが起動し、想定通りレイヤーも読み込まれました。ほとんど時間をかけずにここまでできました。本当に素晴らしいですね。自分でやったこととしては CreateNewMap() の作成とそれをコンストラクタで呼び出すことくらいです。あとはデフォルトのままで問題ありません。

f:id:sanvarie:20200119203905p:plain

今回初めて ArcGIS Runtime SDK for .NET を使ってみたのですが、単純にレイヤーを読み込んで少しカスタマイズするくらいだったら一日二日あればそれなりのものが作れてしまうのでは思うくらい簡単に扱える SDK だと思いました。さすが ArcGIS といったところでしょうか。次回以降はもっと機能を作りこもうと思います。本日は以上です。

ezdxf を使って Python で DXF を扱ってみよう!

さて、本日は ezdxf を使って Python で DXF を扱ってみようと思います。

DXF とは

以下エントリーでも少し紹介しているのですが、DXFは、Autodesk社が開発したファイル形式の1つで、CAD 系のデータですね。しかし、GIS の世界でも DXF はよく使われます。

www.gis-py.com

ezdxf とは

DXF を扱うための Python ライブラリです。データの読み書きを行うことができます。

pypi.org

サンプルデータ

ArcGIS Pro で以下のようなデータを用意しました。

1.浄水場名(アノテーション)
2.浄水場(ポイント)
3.河川(ライン)
4.神奈川県(ポリゴン)

f:id:sanvarie:20200118081144p:plain

f:id:sanvarie:20200118081240p:plain

これをジオプロで「ExportCAD.dxf」という名称のDXFに出力します。

f:id:sanvarie:20200118081650p:plain

できあがった DXF を ArcGIS Pro で読み込むとこのようになります。 f:id:sanvarie:20200118082247p:plain

ちなみにですが、「2.浄水場(ポイント) 」「3.河川(ライン) 」は国土数値情報からダウンロードしてきました。

国土数値情報 上水道関連施設データの詳細

国土数値情報 河川データの詳細

ダウンロードの自動化について過去に紹介しているので、興味のある方はぜひ読んでみてください。 www.gis-py.com

また、「1.浄水場名(アノテーション) 」ですが、「2.浄水場(ポイント) 」から作成しました。作成方法は以下のエントリーで紹介しているので、ぜひ読んでみてください。

www.gis-py.com

実行環境

Windows10 64bit
Python3.6.6
ezdxf 0.10.2
Jupyter 6.0.1

サンプルコード

ezdxf の使い方を紹介します。

レイヤー名称一覧を抽出

import ezdxf

doc = ezdxf.readfile(r"D:\python\data\CAD\ExportCAD.dxf")
for layer in doc.layers: 
    print(layer.dxf.name)

このようになります。「0」と「Defpoints」というレイヤーが抽出されていますが、これは フィーチャクラスを DXF に変換する際にできたもので、特に気にする必要はありません。

f:id:sanvarie:20200118084615p:plain

特定のレイヤのデータを抽出する

「河川」レイヤーのデータを抽出します。

import ezdxf

doc = ezdxf.readfile(r"D:\python\data\CAD\ExportCAD.dxf")
msp = doc.modelspace()

rivers = msp.query('*[layer=="河川"]')
for river in rivers:
    print(river)

こんな感じで結果の結果になりました。

f:id:sanvarie:20200118100421p:plain

色々調べてみたのですが、一つ一つのアイテムの属性にアクセスすることはできませんでした。何かやり方があるのかもしれませんが、今回はあきらめます。

DXF を作成する

ラインを一本作図してそれを DXF として出力します。

import ezdxf

doc = ezdxf.new()
msp = doc.modelspace()
doc.layers.new(name='MyLines', dxfattribs={'linetype': 'DASHED', 'color': 7})
msp.add_line((0, 0), (10, 0), dxfattribs={'layer': 'MyLines'})
doc.saveas(r"D:\python\data\CAD\ExportCAD2.dxf")

想定通りラインが作図された状態で DXF を作成することができました。 f:id:sanvarie:20200118101319p:plain

まとめ

使ってみた感想としては、簡易的に DXF を扱う分には十分だけど、細かな操作を行いたい場合はちょっと厳しいかもしれないと思いました。DXF は専用のソフトで を扱うのが一番かと思います。ただ、今回初めて Python で DXF を扱ってみたのでそれ自体はとてもいい経験になったと思います。興味のある方はぜひ ezdxf を使ってみてください。本日は以上です。

ArcGIS Pro でレイヤーにフィルターをかける方法

さて、本日は ArcGIS Pro の機能紹介になります。レイヤーを参照している際、特定のフィーチャのみを表示したいということはないでしょうか?例えば、日本地図を表示している際に東京都のフィーチャのみを表示したいといった感じです。ご存知の方も多いかと思うのですが、意外とご存じない方もいらっしゃるので、ここで紹介したいと思います。

対象データ

「日本地図」というレイヤーを使用します。こちらは以下のエントリーでも紹介しているESRIジャパンさんの「全国市区町村界データ」をフィーチャクラスに変換したものです。

www.gis-py.com

f:id:sanvarie:20200115205554p:plain

実行環境

Windows10 64bit
ArcGIS Pro 2.3.3

操作方法

1.「日本地図」レイヤーを右クリックして「プロパティ」を押下
f:id:sanvarie:20200115205000p:plain

2.フィルター設定 > 「新しいフィルター設定」ボタンを押下
f:id:sanvarie:20200115205620p:plain

3.「KEN が 東京都 と等しい」 と設定し、OK。
f:id:sanvarie:20200115205649p:plain

東京都のポリゴンだけが表示されました。
f:id:sanvarie:20200115205358p:plain

まとめ

レイヤーのフィルター設定はこのように簡単に行うことができます。状況に応じて、必要なフィーチャの表示/非表示を切り替えることによって、より効率的に作業を進めることができるようになるかと思います。

本日は以上です。