<\/HEAD>
L'acquisition de données géographiques est une tâche chronophage dans de nombreux projets. Il n'est pas toujours nécessaire que ces données soient très précises. Pour certaines questions, les données d'entrée d'Open Streetmap suffisent également. Que ce soit pour des projets étudiants, pour obtenir un aperçu d'un sujet ou pour fournir des informations à un groupe cible. Il est possible de télécharger ces données, de les importer dans ArcMap ou ArcGIS Pro, de filtrer les données souhaitées et ensuite, par exemple, de les publier en tant que service. Cette méthode est très longue et nécessite donc une solution pour connecter directement la source de données Open Streetmap à la plateforme ArcGIS, sans devoir passer par un produit desktop.<\/P>
<\/P>
<\/P>
<\/P>
Pour réaliser cette idée, l'ArcGIS API for Python<\/A> est appropriée, car elle offre, en plus de divers outils d'analyse, un accès polyvalent à ArcGIS Online et ArcGIS for Portal. Sur la base de cette technologie, plusieurs scripts Python ont été créés et publiés sur GitHub. L'objectif de ce projet est que les données situées dans une zone définie soient automatiquement publiées en tant que Feature Service.<\/P> <\/P>
La mise en œuvre a été réalisée en deux scripts Python, qui peuvent également être utilisés séparément. Avant que le processus avec les données puisse commencer, l'utilisateur doit toutefois modifier deux fichiers de configuration. L'un de ces fichiers définit la configuration des données OSM à publier via un
fichier JSON<\/A>. Pour pouvoir lancer le script, différents paramètres doivent être définis comme décrit dans le tableau.<\/P> <\/P>
<\/P>
<\/P>
En plus d'une liste de catégories représentées dans OSM comme une paire de
Key et Value<\/A>, d'autres attributs<\/A> peuvent également être repris des ensembles de données. De plus, une Bounding Box<\/A> ainsi que les géométries souhaitées doivent être spécifiées. Sur la base de ces entrées, un script Python<\/A> est exécuté, qui récupère les données souhaitées via des requêtes aux Overpass<\/A> et OSM API<\/A>.<\/P><\/P>
response <SPAN class="operator token">=<\/SPAN> api<SPAN class="punctuation token">.<\/SPAN>Get<SPAN class="punctuation token">(<\/SPAN><SPAN class="string token">'node['<SPAN class='do-not-translate'> + </SPAN> category <SPAN class='do-not-translate'> + </SPAN> <SPAN class='do-not-translate'>'('</SPAN> <SPAN class='do-not-translate'> + </SPAN> minLat <SPAN class='do-not-translate'> + </SPAN> <SPAN class='do-not-translate'>','</SPAN> <SPAN class='do-not-translate'> + </SPAN> minLon <SPAN class='do-not-translate'> + </SPAN> <SPAN class='do-not-translate'>','</SPAN>
<SPAN class='do-not-translate'> + </SPAN> maxLat <SPAN class='do-not-translate'> + </SPAN> <SPAN class='do-not-translate'>','</SPAN> <SPAN class='do-not-translate'> + </SPAN> maxLon <SPAN class='do-not-translate'> + </SPAN> <SPAN class='do-not-translate'>')</span><span>,</span> responseformat<span>=</span><span>"json"</span><span>)</span>
elements <span>=</span> response<span>[</span><span>"elements"</span><span>]</span>
<span>for</span> element <span>in</span> elements<span>:</span>
dictElement <span>=</span> <span>{}</span>
tags <span>=</span> [element<span>[</span><span>"tags"</span><span>]</span>]<br>                tags <span>=</span> tags[0]
         <span>for</span> key_att <span>in</span> attributes<span>:<br></span>                val_att = attributes[key_att]
         <span>if</span> val_att in tags:<br>&#​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ 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">si</SPAN> <SPAN class="string token">"user"</SPAN> <SPAN class="keyword token">dans</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>
00 if <SPAN class="string token">"timestamp"</SPAN> <SPAN class="keyword token">dans</SPAN> attributes<SPAN class="punctuation token">:</SPAN>
if <SPAN class="string token">"timestamp"</SPAN> <SPAN class="keyword token">dans</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>
except<SPAN class="punctuation token">:</SPAN>
print<SPAN class="punctuation token">(</SPAN><SPAN class="string token">"Node for this element not available"</SPAN><SPAN class="punctuation token">)</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>
Ces données sont maintenant structurées dans un dictionnaire, converties en un DataFrame pandas et retournées pour une utilisation ultérieure. Dans un second
fichier JSON, les configurations pour ArcGIS Online ou ArcGIS for Portal sont définies.

Lorsque les données nécessaires sont disponibles, elles sont vérifiées pour leur exactitude. Cela signifie qu'une connexion est établie à l'aide des informations de connexion. Ceci est nécessaire pour s'assurer que l'ID du Feature Service est correcte si celui-ci doit être écrasé. Si l'entrée est complète et correcte, un autre script Python sera lancé. Lors de la mise à jour d'un Feature Service, celui-ci est vidé, le DataFrame est divisé en blocs et ajouté par lots de 100 features dans le Feature Service.
listAddFeatures <span class="operator token">=</span> <span class="punctuation token">[]</span>
i <span class="operator token">=</span> 0
dataAvailable <span class="operator token">=</span> True
dataUploaded <span class="operator token">=</span> False
dataQuery <span class="operator token">=</span> fc_dataAdd.query()
<span class="keyword token">while</span> dataAvailable:
modulo_i <span class="operator token">=</span> i % 100
<span class="keyword token">if</span> modulo_i == 0 and i != 0 and not dataUploaded:
layer.edit_features(adds=listAddFeatures)
listAddFeatures.clear()
dataUploaded = True
print(str(i) + " Features of " + str(len(dataQuery)) + " added.")
else:
try:
listAddFeatures.append(dataQuery.features[i])
i = i + 1
dataUploaded = False
except:
dataAvailable = False
layer.edit_features(adds=listAddFeatures)
print("All " + str(len(dataQuery)) + " Features added.") 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;">Lors de la création d'un nouveau Feature Service, plusieurs étapes supplémentaires sont nécessaires avant le téléchargement des données, car un Feature Service vide avec les champs requis doit être créé. Pour cela, on crée un nouveau DataFrame qui ne contient que la ligne d'en-tête du fichier transmis. Ensuite, on itère sur tous les champs existants et les champs de type de données "int64" sont ajoutés à une nouvelle liste.<\/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 >< <EMOJI_32>> </SP an >< < EM O J I _33 > > < / S P A N > < S P A N > < < E M O J I _34 > > < / S P A N > < S P A N > < < E M O J I _35 > > < / S P A N > < S P A N > < < E M O J I _36 > > < / S P A N > < S P A N > < < E M O J I _37 > > < / S P A N > < S P A N > < < E M O J I _38 > > < / S P A N > < S P A N > < < E M O J I _39 > > < / S P A N > < S P A N > < < E M O J I _40 > > < / S P A N > < S P A N > < < E M O J I _41 > > < / S P A N > < S P A N > < < E M O J I _42 > > < / S P A N > < S P A N > < < E M O J I _43 > > < / S P A N > < S P A N > < < E M O J I _44 > > < / S P A N > < S P A N > < < E M O J I _45 > > < / S P A N ><S PAN >< << 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;">Cette étape est importante car lors de la publication d'un Feature Service via l'ArcGIS API for Python, les champs Integer sont créés uniquement en tant que "int32" et des erreurs surviennent pour des valeurs plus élevées. Maintenant, un Feature Service est créé et les champs "int64" sont ajoutés via une requête à l'API Portal, car cette méthode permet de stocker des valeurs entières plus grandes.<\/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> 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
Le service est maintenant créé avec tous les attributs nécessaires et les entités peuvent être ajoutées par blocs, comme lors de la mise à jour.<\/p>P
Le résultat est un dépôt GitHub, qui contient les différents scripts. Ceux-ci peuvent être utilisés dans leur état actuel ou individuellement. Il est également possible d'adapter les processus aux besoins personnels. Par exemple, on pourrait étendre le script avec des méthodes pour enregistrer les données non pas en tant que Feature Service mais en tant que Shape File ou Geodatabase.<\/p>P
Avec cet outil, il a été possible de créer un pont entre la riche base de données Open Streetmap et la puissante plateforme ArcGIS.<\/STRONG> <\/p>