Oracle Spatialの楽しみ方: 一定時間内にどこまで走れるか? (2022/09/29)
Oracle Spatialの楽しみ方: 一定時間内にどこまで走れるか? (2022/09/29)
その答えはドライブタイムポリゴン(DTP)と呼ばれ、Oracle Spatialを使って計算することができます、この記事ではその方法を学びます。
NetflixのTVシリーズ「La casa de papel」を覚えていますか?もし、強盗が建物の中でお金を印刷しているのではなく、車を運転して逃げることにしたらどうでしょう?それなら、DTPは確かに役に立つでしょう。
La casa de papel(クレジット Netflix ウェブサイト)
必要なのは、Oracle Spatialルーティングエンジンが動作していることです。DTPを計算してくれるXMLベースのウェブサービスが提供されている。リクエストに必要な情報は以下の通りです。
- 出発地(郵便番号住所形式)
- 運転にかかる時間
実際、次のXML文書は、マドリードのCalle de Jorge Juan 106を出発点とし、車で20分のDTPの有効なリクエストとなるはずです。このように単純で、緯度と経度の座標を提供する必要がなく、Oracle Spatialサービスが私たちのために仕事をしてくれます(郵便番号が地図上で見つけられる限り)。
<xml_request=<?xml version=1.0 standalone=yes?>
<route_request id=1
route_preference=fastest compute_drive_time_polygon=true
drive_time_polygon_cost="20"
cost_unit="min" >
<start_location>
<input_location id=1>
<input_address>
<gen_form country="Spain" street="Calle de Jorge Juan 106" region="Madrid" postal_code="28009" city="Madrid"/></input_address>
</input_location>
</start_location>
</route_request>
不思議に思うかもしれません。なぜその住所なのか?NetflixのTVシリーズ「La casa de papel」で実際にアクションが起こる場所、Fábrica Nacional de Modeda y Timbreの場所なんです。
FNMT (クレジット maps.google.com)
XMLドキュメントを使ってリクエストを行い、レスポンスを印刷するJavaコードを書いてみましょう。教授がちょっとしたギークで、暇さえあればコードを書いていることを祈ります。
Does the professor like Java? I’d say yes!URL url = new URL("https://spatial.server/routeserver/servlet/RouteServerServlet");
URLConnection con = url.openConnection();
HttpURLConnection http = (HttpURLConnection)con;
http.setRequestMethod("POST");
http.setDoOutput(true);
String time="20";
String timeUnit="min";
String body = "xml_request=<?xml version=\"1.0\""
+ " standalone=\"yes\"?>"
+ "<route_request id=\"1\" "
+ " route_preference=\"fastest\" "
+ " compute_drive_time_polygon=\"true\""
+ " drive_time_polygon_cost=\""+time+"\""
+ " cost_unit=\""+timeUnit+"\" >"
+ " <start_location>"
+ " <input_location id=\"1\">"
+ " <input_address>"
+ " <gen_form country=\"Spain\" street=\"Calle de Jorge Juan 106\" region=\"Madrid\" postal_code=\"28009\" city=\"Madrid\"/></input_address>\n"
+ " </input_location>"
+ " </start_location>"
+ "</route_request>";
byte[] postData = body.getBytes(StandardCharsets.UTF_8);
int length = postData.length;
http.setFixedLengthStreamingMode(length);
http.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");
http.connect();try(OutputStream os = http.getOutputStream()) {
os.write(postData);
}
try (InputStream is =http.getInputStream()) {
StringBuilder sb = new StringBuilder();
for (int ch; (ch = is.read()) != -1; ) {
sb.append((char) ch);
}
System.out.println("Response" + sb.toString());
コンパイルして実行すると、以下のようなXML文書になります。
Response<?xml version="1.0" encoding="UTF-8" ?>
<!-- Oracle Routeserver version 21.0.0.0.0 (data version 12.0.0.0.0) -->
<route_response>
<drive_time_polygon id="1" cost="20.00" unit="min" start_location="1"><route_geometry>
<Polygon>
<coordinates> -3.89618,40.31948 -3.87919,40.27624 -3.87891,40.27669 -3.82293,40.30475 -3.80997,40.30536 -3.75959,40.27475 -3.75894,40.26393 -3.74624,40.22144 -3.68718,40.21083 -3.67756,40.19911 -3.67687,40.19832 -3.65959,40.23336 -3.6634,40.25629 -3.59535,40.26571 -3.52669,40.26438 -3.49416,40.26225 -3.44971,40.26636 -3.41382,40.26445 -3.39041,40.26552 -3.43912,40.30763 -3.41248,40.32486 -3.40996,40.32548 -3.40121,40.33173 -3.40586,40.38787 -3.40757,40.39817 -3.40913,40.43747 -3.3813,40.46965 -3.36369,40.50517 -3.37982,40.49743 -3.44171,40.507 -3.47789,40.52613 -3.48589,40.52929 -3.53683,40.54193 -3.55642,40.58445 -3.58598,40.62601 -3.58859,40.63004 -3.60305,40.58138 -3.6412,40.56177 -3.70169,40.59126 -3.72068,40.60702 -3.71829,40.5964 -3.72279,40.54939 -3.76572,40.515 -3.76917,40.50972 -3.80045,40.48468 -3.86869,40.49482 -3.86994,40.48789 -3.84197,40.453 -3.85352,40.39761 -3.87489,40.37841 -3.88822,40.33577 -3.89618,40.31948 </coordinates
</Polygon>
</route_geometry></drive_time_polygon>
</route_response>
うーん、これは教授が探している情報なんだけど、地図上に描いて、チームと共有できたらいいんですけど(彼らはあまり数字が多いのを好まない)。
多くのマップビジュアライゼーションフレームワークはGeoJSONをサポートしていますが、このXMLドキュメントはサポートしていません。次に、応答を解析して GeoJSON ドキュメントを作成するコードをいくつか追加してみましょう。
まず、XML から座標のペアを配列に取得しましょう。
String coordetaes = sb.toString();
coordetaes = coordetaes.substring(coordetaes.indexOf("<coordinates>") + 13);
coordetaes = coordetaes.substring(0, coordetaes.indexOf("</coordinates>"));coordetaes = coordetaes.trim().replaceAll("[^0-9, .-]","");
String [] coords = coordetaes.split(" ");
それでは、simpleJSON Java ライブラリ、いくつかの LinkedHashMaps、および RFC 7946 を使用して GeoJSON ドキュメントを構築してみましょう。教授にとっては簡単なことです。
JSONArray coordinates = new JSONArray();JSONArray outerCoordinates = new JSONArray();for (int i = 0; i < coords.length; i++)
{
JSONArray p = new JSONArray();
p.add(Float.parseFloat(coords[i].split(",")[0]));
p.add(Float.parseFloat(coords[i].split(",")[1]));
coordinates.add(p);
}outerCoordinates.add(coordinates);Map geometrym = new LinkedHashMap();
geometrym.put("type", "Polygon");
geometrym.put("coordinates", outerCoordinates);Map propertiesm = new LinkedHashMap();
propertiesm.put("created by", "the professor");
propertiesm.put("time", time);
propertiesm.put("timeUnit", timeUnit);
propertiesm.put("generatedby", "oracle route engine")Map featurem = new LinkedHashMap();
featurem.put("type", "Feature");
featurem.put("properties", propertiesm);
featurem.put("geometry", geometrym);JSONArray features = new JSONArray();
features.add(featurem);Map geojsonm = new LinkedHashMap();
geojsonm.put("type", "FeatureCollection");
geojsonm.put("features",features);
String jsonText = JSONValue.toJSONString(geojsonm);System.out.println(jsonText);
ほらね。これでGeoJSONの出力は次のようになります。
{"type":"FeatureCollection","features":[{"type":"Feature","properties":{"created by":"the professor","time":"20","timeUnit":"min","generatedby":"oracle route engine"},"geometry":{"type":"Polygon","coordinates":[[[-3.89618,40.31948],[-3.87919,40.27624],[-3.87891,40.27669],[-3.82293,40.30475],[-3.80997,40.30536],[-3.75959,40.27475],[-3.75894,40.26393],[-3.74624,40.22144],[-3.68718,40.21083],[-3.67756,40.19911],[-3.67687,40.19832],[-3.65959,40.23336],[-3.6634,40.25629],[-3.59535,40.26571],[-3.52669,40.26438],[-3.49416,40.26225],[-3.44971,40.26636],[-3.41382,40.26445],[-3.39041,40.26552],[-3.43912,40.30763],[-3.41248,40.32486],[-3.40996,40.32548],[-3.40121,40.33173],[-3.40586,40.38787],[-3.40757,40.39817],[-3.40913,40.43747],[-3.3813,40.46965],[-3.36369,40.50517],[-3.37982,40.49743],[-3.44171,40.507],[-3.47789,40.52613],[-3.48589,40.52929],[-3.53683,40.54193],[-3.55642,40.58445],[-3.58598,40.62601],[-3.58859,40.63004],[-3.60305,40.58138],[-3.6412,40.56177],[-3.70169,40.59126],[-3.72068,40.60702],[-3.71829,40.5964],[-3.72279,40.54939],[-3.76572,40.515],[-3.76917,40.50972],[-3.80045,40.48468],[-3.86869,40.49482],[-3.86994,40.48789],[-3.84197,40.453],[-3.85352,40.39761],[-3.87489,40.37841],[-3.88822,40.33577],[-3.89618,40.31948]]]}}]}
このGeoJSONドキュメントが貼り付けられるgeojson.ioを使ってプロットしてみましょう。実際に、20分、30分、40分のDTPを計算し、地図上に重ねてみましょう。結果はこのようになるはずです。
20分、30分、40分のドライブタイムポリゴン
これで教授は、Oracle Routeエンジンとインターネット接続があれば、チームの残りのメンバーに講演をすることができます。
これはすべて遊びであることをお忘れなく :-)
Oracle Route Engineの詳細については、こちらをご覧ください。
GeoJSONの詳細については、こちらをご覧ください。
コメント
コメントを投稿