開放街圖OSM的公共圖資可以透過overpass-turbo介面查詢獲得。
若想利用Java程式碼查詢,可參考以下查詢範例。
其中,查詢指令可參考overpass-turbo範例指令,測試成功再代入程式。
-
- /*
- QueryOSM.java
- 展示如何用retrofit套件,同步及非同步(適用於Android),存取如下OSM圖資服務
- http://overpass-api.de/api/interpreter?data=xxx
-
- // 建立服務連線客戶端及請求內容
- OverpassService requestClient = OverpassServiceProvider.get();
- String request = composeRequest();
-
- // 非同步查詢圖資,適用於手機平板Android平台
- asyncRequest(requestClient, request);
-
- // 同步查詢圖資,適用於桌機Application應用
- OverpassQueryResult result = syncRequest(requestClient, request);
- postProcess(result);
-
- 執行步驟:
- javac QueryOSM.java
- java QueryOSM
- run:
- [out:json][timeout:25];
- (
- node[tourism](25.1735, 121.446, 25.1775, 121.455);
- relation[!highway][type!='route'][!boundary](25.1735, 121.446, 25.1775, 121.455);
- );
- out center;
- end of asyncRequest()
- 21 elements...
- 1. id:4326372453, type:node, lat:25.1761808, lon:121.4490491, name:五虎碑, wheelchair:limited
- 2. id:4384988658, type:node, lat:25.1750071, lon:121.4522078, name:文錙藝術中心, wheelchair:yes
- 3. id:4492221396, type:node, lat:25.1736267, lon:121.4473809, name:三化牆
- 4. id:4492221397, type:node, lat:25.1744069, lon:121.4474037, name:地球村雕像, wheelchair:limited
- 5. id:4492221399, type:node, lat:25.1735175, lon:121.4484658, name:淡江大學花牆
- 6. id:4492221425, type:node, lat:25.1749949, lon:121.450678, name:閱讀的少女, wheelchair:yes
- 7. id:4502075211, type:node, lat:25.1751384, lon:121.4523232, name:旅者
- 8. id:4502075212, type:node, lat:25.1739938, lon:121.4505047, name:李雙澤紀念碑, wheelchair:yes
- 9. id:4502075213, type:node, lat:25.1761919, lon:121.4499374, name:福園金鷹銅雕, wheelchair:no
- 10. id:4502075222, type:node, lat:25.1738907, lon:121.4475716, name:驚聲銅像, wheelchair:limited
- 11. id:4507662408, type:node, lat:25.1741082, lon:121.4474671, name:溫馨, wheelchair:yes
- 12. id:5012978611, type:node, lat:25.1741784, lon:121.4507282, name:黃河母親, wheelchair:no
- 13. id:5072580167, type:node, lat:25.1769149, lon:121.4495309
- 14. id:5130535622, type:node, lat:25.1757202, lon:121.4496844, name:會文館, wheelchair:yes
- 15. id:5132288341, type:node, lat:25.1741586, lon:121.4508061
- 16. id:5132288342, type:node, lat:25.174208, lon:121.4475417
- 17. id:6050843218, type:node, lat:25.1770813, lon:121.449821
- 18. id:8991981256, type:node, lat:25.1750049, lon:121.4480033, name:淡江願景牆, wheelchair:yes
- 19. id:3974590, type:relation, lat:0.0, lon:0.0, type:multipolygon, name:操場
- 20. id:3983402, type:relation, lat:0.0, lon:0.0, type:multipolygon, name:松濤廣場
- 21. id:7530081, type:relation, lat:0.0, lon:0.0, type:multipolygon
-
- Response{protocol=http/1.1, code=200, message=OK, url=http://overpass-api.de/api/interpreter?data=%5Bout%3Ajson%5D%5Btimeout%3A25%5D%3B%0A%28%0Anode%5Btourism%5D%2825.1735%2C%20121.446%2C%2025.1775%2C%20121.455%29%3B%0Arelation%5B%21highway%5D%5Btype%21%3D%27route%27%5D%5B%21boundary%5D%2825.1735%2C%20121.446%2C%2025.1775%2C%20121.455%29%3B%0A%29%3B%0Aout%20center%3B}
- end of syncRequest()
- 21 elements...
- 1. id:4326372453, type:node, lat:25.1761808, lon:121.4490491, name:五虎碑, wheelchair:limited
- 2. id:4384988658, type:node, lat:25.1750071, lon:121.4522078, name:文錙藝術中心, wheelchair:yes
- 3. id:4492221396, type:node, lat:25.1736267, lon:121.4473809, name:三化牆
- 4. id:4492221397, type:node, lat:25.1744069, lon:121.4474037, name:地球村雕像, wheelchair:limited
- 5. id:4492221399, type:node, lat:25.1735175, lon:121.4484658, name:淡江大學花牆
- 6. id:4492221425, type:node, lat:25.1749949, lon:121.450678, name:閱讀的少女, wheelchair:yes
- 7. id:4502075211, type:node, lat:25.1751384, lon:121.4523232, name:旅者
- 8. id:4502075212, type:node, lat:25.1739938, lon:121.4505047, name:李雙澤紀念碑, wheelchair:yes
- 9. id:4502075213, type:node, lat:25.1761919, lon:121.4499374, name:福園金鷹銅雕, wheelchair:no
- 10. id:4502075222, type:node, lat:25.1738907, lon:121.4475716, name:驚聲銅像, wheelchair:limited
- 11. id:4507662408, type:node, lat:25.1741082, lon:121.4474671, name:溫馨, wheelchair:yes
- 12. id:5012978611, type:node, lat:25.1741784, lon:121.4507282, name:黃河母親, wheelchair:no
- 13. id:5072580167, type:node, lat:25.1769149, lon:121.4495309
- 14. id:5130535622, type:node, lat:25.1757202, lon:121.4496844, name:會文館, wheelchair:yes
- 15. id:5132288341, type:node, lat:25.1741586, lon:121.4508061
- 16. id:5132288342, type:node, lat:25.174208, lon:121.4475417
- 17. id:6050843218, type:node, lat:25.1770813, lon:121.449821
- 18. id:8991981256, type:node, lat:25.1750049, lon:121.4480033, name:淡江願景牆, wheelchair:yes
- 19. id:3974590, type:relation, lat:0.0, lon:0.0, type:multipolygon, name:操場
- 20. id:3983402, type:relation, lat:0.0, lon:0.0, type:multipolygon, name:松濤廣場
- 21. id:7530081, type:relation, lat:0.0, lon:0.0, type:multipolygon
-
- end of main()
- BUILD SUCCESSFUL (total time: 1 minute 2 seconds)
-
- 參考:
- a. Retrofit 2 – Synchronous and asynchronous call example
- https://howtodoinjava.com/retrofit2/retrofit-sync-async-calls/
- b. https://github.com/zsoltk/overpasser
- hu.supercluster.overpasser.adapter
- OverpassQueryResult
- OverpassQueryResult.Element
- OverpassQueryResult.Element.Tags
- OverpassService
- c. 引用函數庫
- compile/run:
- okhttp-3.14.9.jar
- okio-1.17.2.jar
- converter-gson-2.10.2.jar
- gson-2.8.5.jar
- retrofit-2.10.2.jar
- compile/run tests:
- byte-buddy-1.11.3.jar
- byte-buddy-agent-1.11.3.jar
- mockito-core-3.11.2.jar
- objenesis-3.2.jar
- */
- import com.google.gson.Gson;
- import com.google.gson.GsonBuilder;
-
- import retrofit2.Call;
- import retrofit2.Callback;
- import retrofit2.Response;
- import retrofit2.Retrofit;
- import retrofit2.converter.gson.GsonConverterFactory;
-
- import hu.supercluster.overpasser.library.output.OutputFormat;
- import hu.supercluster.overpasser.library.output.OutputModificator;
- import hu.supercluster.overpasser.library.output.OutputOrder;
- import hu.supercluster.overpasser.library.output.OutputVerbosity;
- import hu.supercluster.overpasser.library.query.OverpassQuery;
-
- import hu.supercluster.overpasser.adapter.OverpassQueryResult;
- import hu.supercluster.overpasser.adapter.OverpassQueryResult.Element;
- import hu.supercluster.overpasser.adapter.OverpassQueryResult.Element.Tags;
- import hu.supercluster.overpasser.adapter.OverpassService;
- import hu.supercluster.overpasser.adapter.OverpassServiceProvider;
-
- import java.lang.reflect.Field;
- import java.util.List;
- /**
- *
- * @author seke
- */
-
- public class QueryOSM {
-
- // 可利用下址測試查詢指令
- // http://overpass-turbo.eu/
- public static String composeRequest()
- {
- /* 查詢範例1:
- 在(47.48047027491862,19.039797484874725,47.51331674014172,19.07404761761427)範圍內
- 列出所有非私人停車場
-
- A. 查詢指令
- ["out":"json"]["timeout":"30"];
- (
- node
- ["amenity"="parking"]
- ["access"!="private"]
- (47.48047027491862,19.039797484874725,47.51331674014172,19.07404761761427);
- <;
- );
- out body center qt 100;
-
- B. 組合查詢指令方法
- String query = new OverpassQuery()
- .format(OutputFormat.JSON)
- .timeout(30)
- .filterQuery()
- .node()
- .amenity("parking")
- .tagNot("access", "private")
- .boundingBox(
- 47.48047027491862, 19.039797484874725,
- 47.51331674014172, 19.07404761761427
- )
- .end()
- .output(OutputVerbosity.BODY, OutputModificator.CENTER, OutputOrder.QT, 100)
- .build()
- ;
- */
-
- /* 查詢範例2:
- 在(25.1735, 121.446, 25.1775, 121.455)範圍內,撈取
- 非座椅設施,商店,觀光點,辦公室,繄急設施之節點
- 屬於大學設施之線條,關係
- 不屬於公路、路線、森林、邊界之線條,關係
- 列出其中心位置及相關屬性(標籤)
-
- A. 查詢指令
- [out:json][timeout:25];
- // gather results
- (
- node[amenity][amenity!=bench](25.1735, 121.446, 25.1775, 121.455);
- node[shop](25.1735, 121.446, 25.1775, 121.455);
- node[tourism](25.1735, 121.446, 25.1775, 121.455);
- node[office](25.1735, 121.446, 25.1775, 121.455);
- node[emergency](25.1735, 121.446, 25.1775, 121.455);
- //way[amenity="university"](25.1735, 121.446, 25.1775, 121.455);
- relation[amenity="university"](25.1735, 121.446, 25.1775, 121.455);
- way[!highway][type!="route"][landuse!="forest"][!boundary](25.1735, 121.446, 25.1775, 121.455);
- relation[!highway][type!="route"][!boundary](25.1735, 121.446, 25.1775, 121.455);
- );
- // print results
- out center;
- ---
- 註: 淡江大學之範圍為 25.1735, 121.446, 25.1775, 121.455
- */
- String query = String.join("\n",
- "[out:json][timeout:25];",
- "(",
- // "node[amenity][amenity!=bench](25.1735, 121.446, 25.1775, 121.455);",
- // "node[shop](25.1735, 121.446, 25.1775, 121.455);",
- "node[tourism](25.1735, 121.446, 25.1775, 121.455);",
- // "node[office](25.1735, 121.446, 25.1775, 121.455);",
- // "node[emergency](25.1735, 121.446, 25.1775, 121.455);",
- // "relation[amenity='university'](25.1735, 121.446, 25.1775, 121.455);",
- // "way[!highway][type!='route'][landuse!='forest'][!boundary](25.1735, 121.446, 25.1775, 121.455);",
- "relation[!highway][type!='route'][!boundary](25.1735, 121.446, 25.1775, 121.455);",
- ");",
- "out center;");
-
- System.out.println(query);
- return query;
- }
-
- public static void asyncRequest(OverpassService apiClient, String request)
- {
- //Call
call = service.interpreter(query); apiClient.interpreter(request).enqueue(new Callback() { @Override public void onResponse(Call call, Response response) { if(response.isSuccessful()==false) { System.out.println("asyncRequest: response.isSuccessful(): false"); System.out.println(response.errorBody()); return; } OverpassQueryResult result = response.body(); postProcess(result); } public void onFailure(Call call, Throwable t) { // DO failure handling System.out.println("onFailure"); System.out.println(t.getLocalizedMessage()); } }); System.out.println("end of asyncRequest()"); } public static OverpassQueryResult syncRequest(OverpassService apiClient, String request) { OverpassQueryResult result = null; Call callSync = apiClient.interpreter(request); try { Response response = callSync.execute(); //OverpassQueryResult apiResponse = response.body(); //API response System.out.println(response); result = response.body(); } catch (Exception ex) { ex.printStackTrace(); } System.out.println("end of syncRequest()"); return result; } public static void postProcess(OverpassQueryResult result) { if(result==null) return; // DO success handling StringBuilder sb = new StringBuilder(); System.out.println(result.elements.size() + " elements..."); int count = 1; for (Element p : result.elements) { sb.append(count); count++; sb.append(String.format(". id:%s, type:%s, lat:%s, lon:%s", p.id, p.type, p.lat, p.lon)); Tags tags = p.tags; for (Field f : tags.getClass().getFields()) { f.setAccessible(true); try { if (f.get(tags) != null) { sb.append(String.format(", %s:%s", f.getName(), f.get(tags))); } } catch (IllegalAccessException e) { // shouldn't happen because I used setAccessible } } //if(p.tags. != null) // sb.append(String.format("tags:%s", p.tags.name)); sb.append("\n"); } System.out.println(sb.toString()); } public static void main(String args[]) { // 建立服務連線客戶端及請求內容 OverpassService requestClient = OverpassServiceProvider.get(); String request = composeRequest(); // 非同步請求 asyncRequest(requestClient, request); // 同步請求 OverpassQueryResult result = syncRequest(requestClient, request); postProcess(result); System.out.println("end of main()"); } }
2021年8月27日 星期五
how to query OSM data in Java?
訂閱:
張貼留言 (Atom)
1 則留言:
This post gave me a lot of information on this topic. Keep it up and keep sharing this type of information with us. Try to explore our services towards digital transformation.
Data Analytics Solutions
Data Engineering Solutions
Artificial Intelligence (AI) Solutions
張貼留言