<\/HEAD>
多くのプロジェクトにおいて、ジオデータの取得は時間のかかる作業です。必ずしもすべての場合で高精度なデータが必要なわけではありません。ある種の課題に対しては、Open Streetmapからの入力でも十分です。学生プロジェクトであったり、テーマの概要を把握したり、ターゲットグループに情報を提供したりする場合などです。これらのデータをダウンロードし、ArcMapやArcGIS Proにインポートし、必要なデータをフィルタリングして、例えばサービスとして公開することが可能です。この方法は非常に時間がかかるため、デスクトップ製品を経由せずにOpen StreetmapのデータソースをArcGISプラットフォームに直接接続するソリューションが求められています。<\/P>
<\/P>
<\/P>
<\/P>
このアイデアの実現にはArcGIS API for Python<\/A>が適しています。これは様々な分析ツールに加え、ArcGIS OnlineやArcGIS for Portalへの多様なアクセスを提供するためです。この技術を基に複数のPythonスクリプトが作成されGitHubで公開されています。本プロジェクトの目的は、指定された範囲内のデータを自動的にFeature Serviceとして公開することです。<\/P> <\/P>
実装は2つのPythonスクリプトで行われており、それぞれ単独でも使用可能です。ただし、処理を開始する前にユーザーは2つの設定ファイルを編集する必要があります。そのうち1つは
JSONファイル<\/A>でOSMデータ公開の設定を行います。スクリプトを起動するには、表に記載された各種パラメーターを設定しなければなりません。<\/P> <\/P>
<\/P>
<\/P>
OSMでKeyとValueのペアとして表されるカテゴリリストに加え、
属性<\/A>もデータセットから引き継ぐことができます。また、バウンディングボックス<\/A>と希望するジオメトリも指定する必要があります。この入力に基づき、Pythonスクリプト<\/A>が実行され、Requestsを使ってOverpass<\/A>およびOSM API<\/A>から必要なデータを取得します。<\/P><\/P>
response <SPAN class="operator token">=<\/<SPAN> api<SPAN class="punctuation token">.<\/<SPAN>Get<SPAN class="punctuation token">(<\/<SPAN>'node['<SPAN class="operator token">+<\/<SPAN> category <SPAN class="operator token">+<\/<SPAN> ']<\/<SPAN> <SPAN class="operator token">+<\/<SPAN> minLat <SPAN class="operator token">+<\/<SPAN> ','<SPAN class="operator token">+<\/<SPAN> minLon <SPAN class="operator token">+<\/<SPAN> ','
<SPAN class="operator token">+<\/<SPAN> maxLat <SPAN class="operator token">+<\/<SPAN> ','<SPAN class="operator token">+<\/<SPAN> maxLon <SPAN class="operator token">+<\/<SPAN> ')'<SPAN class="punctuation token">,<\/<SPAN> responseformat<SPAN class="operator token">=<\/<SPAN>"json"<SPAN class="punctuation token">)<\/<SPAN>
elements <SPAN class="operator token">=<\/<SPAN> response<SPAN class="punctuation token">[<\/<SPAN>"elements"<SPAN class="punctuation token">]<\/<SPAN>
<SPAN class="keyword token">for<\/<SPAN> element <SPAN class="keyword token">in<\/<SPAN> elements<SPAN class="punctuation token">:<\/<SPAN>
dictElement <SPAN class="operator token">=<\/<SPAN> <SPAN class="punctuation token">{<\/<SPAN>}<SPAn>
 . . . . . . . . . . . . . tags <span class= "operator token "> = </span > [element[ "tags " ] ]
 . . . . . . . . . . . . .; tags = tags[0]
 . . . . . .; for key_att in attributes:
 . .; val_att = attributes[key_att]
 .; if val_att in tags:
 .; dictElement[key_att] = tags[val_att]
 .; id = element[ "id"]
 .; #id = float(id)
 .; dictElement[ "id"] = id
 .; dictElement[ "lon"] = element[ "lon"]
 .; dictElement[ "lat"] = element[ "lat"]
 .; if "user" in attributes or "timestamp" in attributes:
 .; try:
 .; node = oApi.NodeGet(element[ "id"])
 .; if "user" in attributes:
 .; <SPAN class="keyword token">もし</SPAN> <SPAN class="string token">"user"</SPAN> <SPAN class="keyword token">が</SPAN> node<SPAN class="punctuation token">.</SPAN>keys<SPAN class="punctuation token">()</SPAN><SPAN class="punctuation token">に存在するなら:</SPAN>
dictElement<SPAN class="punctuation token">[</SPAN><SPAN class="string token">"user_"</SPAN><SPAN class="punctuation token">]</SPAN> <SPAN class="operator token">=</SPAN> node<SPAN class="punctuation token">[</SPAN><SPAN class="string token">"user"</SPAN><SPAN class="punctuation token">]</SPAN>
<SPAN class="keyword token">もし</SPAN> <SPAN class="string token">"timestamp"</SPAN> <SPAN class="keyword token">が</SPAN> attributes<SPAN class="punctuation token">に存在するなら:</SPAN>
<SPAN class="keyword token">もし</SPAN> <SPAN class="string token">"timestamp"</SPAN> <SPAN class="keyword token">が</SPAN> node<SPAN class="punctuation token">.</SPAN>keys<SPAN class="punctuation token">()</SPAN><SPAN class="punctuation token">に存在するなら:</SPAN>
dictElement<SPAN class="punctuation token">[</SPAN><SPAN class="string token">"timestamp"</SPAN><SPAN class="punctuation token">]</SPAN> <SPAN class="operator token">=</SPAN> node<SPAN class="punctuation token">[</SPAN><SPAN class="string token">"timestamp"</SPAN><SPAN class="punctuation token">]</SPAN>
<SPAN class="keyword token">例外の場合:</SPAN>
<SPAN class="keyword token">print(</SPAN><SPAN class="string token">"この要素のノードは利用できません"</SPAN><span>)</span>
dictElement<Span class="punctuation token">[</Span><Span class="string token">"attribute"</Span><Span class="punctuation token">]</Span> <Span class="operator token">=</Span> key_cat <Span class="operator token">+</Span> <Span class="string token">"-"</Span> <Span class="operator token">+</Span> val_cat
dictData<Span class="punctuation token">.</Span>append<Span class="punctuation token">(</Span>dictElement<Span class="punctuation token">)</Span><span class="line-numbers-rows"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span>
これらのデータは現在、辞書形式で構造化され、pandas Dataframeに変換され、さらなる使用のために返されます。2つ目の
JSONファイル では、ArcGIS OnlineまたはArcGIS for Portalの設定が定義されています。

必要なデータが存在する場合、それらは正確性を確認されます。これはログイン情報を使って接続を確立することを意味します。これは、Feature Service IDが上書きされる場合に正しいことを保証するために必要です。入力が完全かつ正確であれば、別のPythonスクリプト が起動されます。Feature Serviceを更新するときは、その内容がクリアされ、Dataframeはブロックに分割され、それぞれ100フィーチャーずつFeature Serviceに追加されます。
listAddFeatures <Span class="operator token">=</Span> <Span class="punctuation token">[]</Span>
i <Span class="operator token">=</Span> <Span class="number token">0</Span>
dataAvailable <Span class="operator token">=</Span> <Span class="token boolean">True</Span>
dataUploaded <Span class="operator token">=</Span> <Span class="token boolean">False</Span>
dataQuery <Span class="operator token">=</Span> fc_dataAdd<span class="punctuation token">.</span>query<span class="punctuation token">()</span>
<Span class="keyword token">while</Span> dataAvailable<span class="punctuation token">:</span>
modulo_i <Span class="operator token">=</Span> i <Span class="operator token">%</Span> <Span class="number token">100</Span>
<Span class="keyword token">if</Span> modulo_i <Span class="operator token">==</Span> <Span class="number token">0</Span> <Span class="operator token">and</Span> i <Span class="operator token">!=</Span> <Span class="number token">0</Span> <Span class="operator token">and not </Span>dataUploaded<span>: </span>
layer<span>.</span>EditFeatures<span>(adds=)</span> listAddFeatures
listAddFeatures<span>.</span>.clear<span>()
dataUploaded = True
<Spin keyword= class="line-numbers-rows"><SPAN><\/SPAN><SPAN><\/SPAN><SPAN><\/SPAN><SPAN><\/SPAN><SPAN><\/SPAN><SPAN><\/SPAN><SPAN><\/SPAN><SPAN><\/SPAN><SPAN><\/SPAN><SPAN><\/SPAN><SPAN><\/SPAN><SPAN><\/SPAN><SPAN><\/SPAN><SPAN><\/SPAN><SPAN><\/SPAN><SPAN><\/SPAN><SPAN><\/SPAN><SPAN><\/SPAN><SPAN><\/SPAN><SPAN><\/SPAN><SPAN><\/SPAN><SPAN><\/SPAN><SPAN><\/SPAN><\/SPAN><\/CODE><\/PRE><P><\/P><P style="text-align: justify;">新しいFeature Serviceを作成する際、データのアップロード前にさらに作業手順が必要です。必要なフィールドを持つ空のFeature Serviceを作成しなければなりません。そのために、渡されたデータのタイトル行のみを含む新しいDataframeを作成します。次に、存在するすべてのフィールドを反復処理し、データ型が「int64」のフィールドを新しいリストに追加します。<\/P><P style="text-align: justify;"><\/P><PRE class="lia-code-sample line-numbers language-none"><CODE>newField = {
"name" : intFieldName,
"type" : "esriFieldTypeInteger",
"alias" : intFieldName,
"sqlType" : "sqlTypeBigInt",
"nullable" : True,
"editable" : True,
"visible" : True
}
token_URL = "{}\/sharing\/generateToken".format(portal)
token_params = {'username' : user,
'password' : password,
'client' : 'referer',
'referer': portal,
'expiration': 60,
'f' : 'json'
}
r = requests.post(token_URL,token_params)
token_obj = r.json()
token = token_obj['token']
expires = token_obj['expires']
tokenExpires = datetime.datetime.fromtimestamp(int(expires)\/1000)
featureLayerAdminUrl = layerURL.replace("\/rest\/", "\/rest\/admin\/")
params = {"f":"json", "token":token}
params["addToDefinition"] = json.dumps({"fields":[newField]})
layerUpdateUrl = "{}\/addToDefinition".format(featureLayerAdminUrl)
layerResult = requests.post(layerUpdateUrl, params)
<SPAN class="line-numbers-rows"><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN ><SPAN >< < EM O J I _ 3 2 > > < / S P A N > < S P A N > < < E M O J I _ 3 3 > > < / S P A N > < S P A N > < < E M O J I _ 3 4 > > < / S P A N > < S P A N > < < E M O J I _ 3 5 > > < / S P A N > < S P A N > < < E M O J I _ 3 6 > > < / S P A N > < S P A N > < < E M O J I _ 3 7 > > < / S P A N > < S P A N > < < E M O J I _ 3 8 > > < / S P A N > < S P A N > < < E M O J I _ 3 9 > > < / S P A N > < S P A N > < < E M O J I _ 4 0 > > < / S P A N > < S P A N > < < E M O J I _ 4 1 > > < / S P A N > < S P A N > < < E M O J I _ 4 2 > > < / S P A N > < S P A N > < < E M O J I _ 4 3 > > < / S P A N > < S P A N > < < E M O J I _ 4 4 > > < / S P A N ><S PAN >< << EMOJ I _45 >> </ SPAN >< SPAN >< << EMOJ I _46 >> </ SPAN >< SPAN >< << EMOJ I _47 >> </ SPAN >< SPAN >< << EMOJ I _48 >> </ SPAN >< SPAN >< << EMOJ I _49 >> </ SPAN >< SPAN >< << EMOJ I _50 >> </ SPAN >< SPAN >< << EMOJ I _51 >> </ SPAN >< SPAN >< << EMOJ I _52 >> </ SPAN >< SPAN >< << EMOJ I _53 >> </ SPAN >< SPAN >< << EMOJ I _54 >> </ SPAN >< SPAN >< << EMOJ I _55 >> </ SPAN >< SPAN >< << EMOJ I _56 >> </ SPAN >< SPAN >< << EMOJ I _57 >> </ SPAN >< SPAN >< << EMOJ I _58 >> </ SPAN >< SPAN >< << EMOJ I _59 >> </ SPAN ></ CODE ></ PRE ><P style="text-align: justify;"><\/P ><P style="text-align: justify;">このステップは重要です。なぜなら、ArcGIS API for Pythonを使ってFeature Serviceを公開すると、整数フィールドは「int32」としてのみ作成され、高い値の場合にエラーが発生するからです。そこで、Feature Serviceを作成し、「int64」フィールドをPortal APIへのリクエストで追加します。この方法でより大きな整数値を保存できます。<\/P ><P ><\/P ><PRE class="lia-code-sample line-numbers language-none"><CODE ><SP AN class="keyword token">for</SP AN> field <SP AN class="keyword token">in</SP AN> listBigInt:<BR> del dataframe_total_title[field]<BR> <BR> fc = gis.content.import_data(dataframe_total_title)<BR> item_properties_input = {<BR> "title": title,<BR> "tags" : tags,<BR> "description": description,<BR> "text": json.dumps({"featureCollection": {"layers": [dict(fc.layer)]}}),<BR> "type": "Feature Collection",<BR>}<BR>
item = gis.content.add(item_properties_input)<BR>new_item = item.publish()<
これで必要なすべての属性を持つサービスが作成され、更新時と同様にブロック単位でフィーチャを追加できます。<\/P>
結果として、さまざまなスクリプトを含むGitHubリポジトリが得られます。これらは現在の状態でも個別にも使用可能で、自分のニーズに合わせてワークフローを調整することも可能です。例えば、このスクリプトにメソッドを追加して、データをFeature ServiceではなくShape FileやGeodatabaseとして保存することもできます。<\/P>
このツールによって、豊富なOpen Streetmapデータベースと強力なArcGISプラットフォームとの橋渡しが成功しました。<\/STRONG> <\/P>