Newer
Older
osmCoverage / src / osm / jp / api / OsmExist.java
@yuu yuu on 23 Nov 2018 10 KB fixed:
  1. package osm.jp.api;
  2.  
  3. import java.io.*;
  4. import java.sql.Connection;
  5. import java.sql.SQLException;
  6. import java.text.SimpleDateFormat;
  7. import java.util.ArrayList;
  8. import java.util.Calendar;
  9. import javax.xml.parsers.DocumentBuilder;
  10. import javax.xml.parsers.DocumentBuilderFactory;
  11. import org.w3c.dom.Document;
  12. import org.w3c.dom.Node;
  13.  
  14. public abstract class OsmExist extends Osmdb {
  15. public ArrayList<OsmnodeNode> nodelist = new ArrayList<>();
  16.  
  17.  
  18. public OsmExist(Connection hsqldb, String tableName) {
  19. super(hsqldb, tableName);
  20. }
  21. /**
  22. * 'HSQLDB.table.OSM_EXIST'を新規に作る
  23. * 'HSQLDB.table.AREA_NODE'を新規に作る
  24. * 既にテーブルが存在する時にはERROR
  25. * @throws SQLException
  26. */
  27. @Override
  28. public void create() throws SQLException {
  29. String createSt;
  30. sql("DROP TABLE IF EXISTS "+ tableName +" CASCADE");
  31. sql("DROP INDEX IF EXISTS "+ tableName +"_index;");
  32. sql("DROP TABLE IF EXISTS AREA_NODE CASCADE");
  33.  
  34. // 'table.OSM_EXIST'を新規に作る
  35. createSt = "CREATE TABLE "+ tableName
  36. + " ("
  37. + "idref VARCHAR(12) NOT NULL, "
  38. + "name VARCHAR(128), "
  39. + "lat DOUBLE, "
  40. + "lon DOUBLE, "
  41. + "score INT, "
  42. + "gmlid VARCHAR(12), "
  43. + "area INT, "
  44. + "PRIMARY KEY(idref), "
  45. + "removed BOOLEAN DEFAULT FALSE NOT NULL"
  46. + ");";
  47. Db.updateSQL(hsqldb, createSt);
  48. createSt = "CREATE INDEX "+ tableName +"_index ON "+ tableName
  49. + " (lat, lon);";
  50. Db.updateSQL(hsqldb, createSt);
  51.  
  52. // 'table.AREA_NODE'を新規に作る
  53. createSt = "CREATE TABLE AREA_NODE "
  54. + "("
  55. + "idref VARCHAR(12) NOT NULL, "
  56. + "pid VARCHAR(12), "
  57. + "lat DOUBLE, "
  58. + "lon DOUBLE"
  59. + ");";
  60. Db.updateSQL(hsqldb, createSt);
  61. }
  62. /*
  63. Test data:
  64. ノード: エネオス (2015835273) 場所: 35.4367770, 139.403571TABLE_NAME0
  65. ノード: ENEOS (1769261234) 場所: 35.4330583, 139.4006876 brand=no
  66. ノード: 出光 (3877535257) 場所: 45.3985390, 141.6882450 brand=no
  67. select osm_id,amenity,brand,disused,name,
  68. ST_Y(ST_Transform(way,4326)) as lat,
  69. ST_X(ST_Transform(way,4326)) as lon
  70. from planet_osm_point
  71. where amenity='fuel';
  72. ウェイ: 出光 (161877397) ノード
  73. 1738352013
  74. 1738351984
  75. 1738352019
  76. 1738352024
  77. 1738352017
  78. 1738352013
  79. select osm_id,amenity,brand,name,way_area,
  80. ST_Astext(ST_Transform(way,4326)) ,
  81. ST_Y(ST_Transform(ST_Centroid(way),4326)) as lat,
  82. ST_X(ST_Transform(ST_Centroid(way),4326)) as lon
  83. from planet_osm_polygon
  84. where amenity='fuel';
  85. 161877397;"fuel";"出光";"出光";1415.14;"POLYGON((139.402982078119 35.4372453832977,139.403208992559 35.4373490207424,139.4033330499 35.4371591650393,139.403407160911 35.4370741177365,139.403148446109 35.4369273706731,139.402982078119 35.4372453832977))"
  86. ST_Centroid(way)
  87. */
  88. /**
  89. *
  90. * <pre>{@code
  91. * (
  92. * node[disused:amenity=fuel](35.42,139.39,35.45,139.42);
  93. * way[amenity=fuel](35.42,139.39,35.45,139.42);
  94. * node[amenity=fuel](35.42,139.39,35.45,139.42);
  95. * (way[amenity=fuel](35.42,139.39,35.45,139.42);>;);
  96. * );
  97. * out;
  98. * }</pre>
  99. *
  100. * <pre>{@code
  101. * select osm_id,amenity,brand,disused,name from planet_osm_point where amenity='fuel';
  102. * }</pre>
  103. *
  104. * <pre>{@code
  105. * select osm_id,amenity,brand,name,way_area,ST_Astext(ST_Transform(way,4326)) from planet_osm_polygon where amenity='fuel';
  106. *
  107. * 168977587;"fuel";"JA";"兼城SS";1378;"POLYGON((127.692529751123 26.1483225993078,127.692852156479 26.1482644594179,127.692800683013 26.1478020809547,127.692690280065 26.1478324815483,127.692623984397 26.1480452048431,127.692529751123 26.1483225993078))"
  108. *
  109. *
  110. * select id,nodes,tags from planet_osm_ways;
  111. * }</pre>
  112. *
  113. * @param hsqldb
  114. * @param osmdb
  115. * @param features
  116. * @return XML
  117. * @throws Exception
  118. */
  119. /**
  120. * File(HttpPOST.EXIST_FILE)を読み取って、データベースに反映させる。<br>
  121. * その際に、OSMノードを評価し、scoreを算定する
  122. *
  123. * @param features
  124. * @param boxes
  125. * @throws Exception
  126. */
  127. public void getJapanCapabilities(ArrayList<Feature> features, Japan[] boxes) throws Exception {
  128. /*
  129. ```
  130. (node(changed:"2018-05-20T09:00:00Z")(34.0,138.0,36.0,140.0);)->.a;
  131. (node(newer:"2018-05-20T09:00:00Z")(34.0,138.0,36.0,140.0);)->.b;
  132. (way(changed:"2018-05-20T09:00:00Z")(34.0,138.0,36.0,140.0);)->.c;
  133. (way(newer:"2018-05-20T09:00:00Z")(34.0,138.0,36.0,140.0);)->.d;
  134. (
  135. node.a.b["amenity"="fuel"];
  136. node.a.b["disused:amenity"="fuel"];
  137. node.a.b["abandoned:amenity"="fuel"];
  138. node.a.b["demolished:amenity"="fuel"];
  139. node.a.b["historic:amenity"="fuel"];
  140. node.a.b["was:amenity"="fuel"];
  141. node.a.b["removed:amenity"="fuel"];
  142. node.a.b["no:amenity"="fuel"];
  143. way.c.d["amenity"="fuel"];
  144. way.c.d["disused:amenity"="fuel"];
  145. way.c.d["abandoned:amenity"="fuel"];
  146. way.c.d["demolished:amenity"="fuel"];
  147. way.c.d["historic:amenity"="fuel"];
  148. way.c.d["was:amenity"="fuel"];
  149. way.c.d["removed:amenity"="fuel"];
  150. way.c.d["no:amenity"="fuel"];
  151. );
  152. (._;>;);
  153. out meta;
  154. ```
  155. */
  156. Calendar now = Calendar.getInstance();
  157. now.add(Calendar.DATE, -7); // before 1 week
  158. SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
  159. String startDate = sdf.format(now.getTime()) +"T09:00:00Z";
  160. StringBuilder sb = new StringBuilder();
  161. for (Japan box : boxes) {
  162. String boxq = String.format("(%2.1f,%3.1f,%2.1f,%3.1f)", box.minLat, box.minLon, box.maxLat, box.maxLon);
  163. sb.append(String.format("(node(changed:\"%s\")%s;)->.a;\n", startDate, boxq));
  164. sb.append(String.format("(node(newer:\"%s\")%s;)->.b;\n", startDate, boxq));
  165. sb.append(String.format("(way(changed:\"%s\")%s;)->.c;\n", startDate, boxq));
  166. sb.append(String.format("(way(newer:\"%s\")%s;)->.d;\n", startDate, boxq));
  167. sb.append("(");
  168. int point = 0;
  169. for (Feature f : features) {
  170. if (f.node == Feature.NODE) {
  171. sb.append("node.a.b");
  172. }
  173. else if (f.node == Feature.AREA) {
  174. sb.append("way.c.d");
  175. }
  176. sb.append(String.format("[\"%s\"=\"%s\"];\n", f.key, f.v));
  177. point += f.point;
  178. }
  179. sb.append(");\n");
  180. sb.append("(._;>;);\n");
  181. sb.append("out body;");
  182.  
  183. /*--------------------------------------------
  184. Overpass API を実行して XMLを受信する
  185. ---------------------------------------------*/
  186. HttpPOST.getQuery(sb.toString());
  187. File xmlFile = new File(HttpPOST.EXIST_FILE);
  188.  
  189. /*--------------------------------------------
  190. 受信したXMLファイルをパースする
  191. ---------------------------------------------*/
  192. DocumentBuilderFactory documentBuilderFactory = DocumentBuilderFactory.newInstance();
  193. DocumentBuilder documentBuilder = documentBuilderFactory.newDocumentBuilder();
  194. Document document = documentBuilder.parse(xmlFile);
  195. Node osmNode = document.getDocumentElement();
  196. Node itemNodes = osmNode.getFirstChild();
  197. while(itemNodes != null) {
  198. String nodeName = itemNodes.getNodeName();
  199. switch (nodeName) {
  200. case "node":
  201. OsmnodeNode osmnode = new OsmnodeNode(itemNodes);
  202. nodelist.add(osmnode);
  203. if (osmnode.tags.size() > 0) {
  204. insertExistingNode(osmnode.id, Double.parseDouble(osmnode.latStr), Double.parseDouble(osmnode.lonStr), score(point, osmnode.tags), "", osmnode.isRemoved());
  205. }
  206. break;
  207. case "way":
  208. OsmnodeArea osmway = new OsmnodeArea(itemNodes);
  209. osmway.setPosition(nodelist);
  210. if (osmway.tags.size() > 0) {
  211. insertExistingNode(osmway.id, Double.parseDouble(osmway.latStr), Double.parseDouble(osmway.lonStr), score(point, osmway.tags), "", osmway.isRemoved());
  212. }
  213. break;
  214. }
  215. itemNodes = itemNodes.getNextSibling();
  216. }
  217. }
  218. }
  219. /**
  220. *
  221. * @param point
  222. * @param tags
  223. * @return
  224. */
  225. int score(int point, ArrayList<OsmnodeTag> tags) {
  226. int score = 50;
  227. if (tags == null) {
  228. return 0;
  229. }
  230. boolean brandYes = false;
  231. boolean busYes = false;
  232. boolean fixmeYes = false;
  233. boolean nameYes = false;
  234. for (OsmnodeTag tag : tags) {
  235. if (tag.key.startsWith("fixme")) {
  236. fixmeYes = true;
  237. }
  238. else if (tag.key.equals("bus")) {
  239. if (tag.value.equals("yes")) {
  240. busYes = true;
  241. }
  242. }
  243. else if (tag.key.equals("brand")) {
  244. brandYes = true;
  245. }
  246. else if (tag.key.startsWith("name")) {
  247. nameYes = true;
  248. }
  249. }
  250. if (((point & POINT_NO_BRAND) != 0) && !brandYes) {
  251. score = 1;
  252. }
  253. if (((point & POINT_NO_NAME) != 0) && !nameYes) {
  254. score = 1;
  255. }
  256. if (((point & POINT_FIXME) != 0) && fixmeYes) {
  257. score = 1;
  258. }
  259. if (((point & POINT_BUS_NO) != 0) && !busYes) {
  260. score = 0;
  261. }
  262. return score;
  263. }
  264. }