// cd .\OSMParser // javac OSMParser.java NodeBlock.java OSM.java Relation.java OSMLib.java Tag.java // java -Dfile.encoding=UTF-8 -Xmx5g OSMParser japan import java.io.*; import java.nio.file.*; import java.util.*; public class OSMParser { final static double E7 = 10000000.0; static long start; static DataOutputStream dos; static Map mapKeys = new HashMap<>(); static Map mapVals = new HashMap<>(); static HashMap mapRelations = new HashMap<>(); // key: relation id static HashMap mapWays = new HashMap<>(); static HashSet setBusRoutes = new HashSet<>(); static long idNodeMax=0, idWayMax=0, idRelMax=0; static boolean outLow=false, outMid=false, outHigh=false; static List listTag = new ArrayList<>(); // k,v順。node,way,relation共通 int currBlock=-1; int cntNodes=0, maxNodes=0, totalNodes=0; List listRef = new ArrayList<>(); void parse(String area) throws Exception { boolean fNodeSection = true; boolean fWaySection = false; long idNode=0, idWay = 0; int lon=0, lat=0; BufferedReader br = new BufferedReader(new FileReader("c:/osm/"+area+".osm")); String line; while ((line = br.readLine()) != null) { int ix = line.indexOf('<'); char c1 = line.charAt(ix+1); char c2 = line.charAt(ix+2); char c3 = line.charAt(ix+3); if (c1 == 'w' && c2 == 'a') { // wayオブジェクト開始 if (fNodeSection) { putNodeBlock(currBlock, sids, lonlats, cntNodes); fWaySection = true; fNodeSection = false; // nodeセクション終了 System.out.printf("nodeセクション終了: %.2f分\n", (System.currentTimeMillis()-start)/60000.0); } String sId = OSM.getAttr(" id=", line); idWay = Long.parseLong(sId); listRef.clear(); listTag.clear(); } else if (c1 == '/' && c2 == 'w' && c3 == 'a') { // long[] nids = listRef.stream().mapToLong(i -> i).toArray(); long[] lonlats = null; if (mapWays.containsKey(idWay)) { //mapWays.put(idWay, nids); lonlats = NodeBlock.getLonLat(nids); mapWays.put(idWay, lonlats); } if (listTag.size() > 0) { if (lonlats == null) { lonlats = NodeBlock.getLonLat(nids); } int type = nids[0] != nids[nids.length-1] ? 1 : 2; OSM osm = new OSM(type, idWay, null, lonlats, listTag); dos.write(osm.toBinaryRecord()); // wayレコード出力 } } else if (fWaySection && c1 == 'n' && c2 == 'd') { // = 0) { // 前のブロックをファイルに書き込む putNodeBlock(currBlock, sids, lonlats, cntNodes); if (cntNodes > maxNodes) maxNodes = cntNodes; cntNodes = 0; } currBlock = blockNumber; } sids[cntNodes] = NodeBlock.getSubId(id); lonlats[cntNodes++] = (((long)lon)<<32) + (lat&0xffffffffL); } void putNodeBlock(int blk, int[] sids, long[] lonlats, int size) { NodeBlock block = NodeBlock.blocks[blk] = new NodeBlock(size); System.arraycopy(sids, 0, block.sids, 0, size); System.arraycopy(lonlats, 0, block.lonlats, 0, size); totalNodes += size; } // OSMParser japan norm | high | mid | low public static void main( String[] args ) throws Exception { start = System.currentTimeMillis(); String src = args.length >= 1 ? args[0] : "japan"; String mode = args.length >= 2 ? args[1] : "norm"; System.out.printf("OSMParser %s %s\n", src, mode); OSM.readWords("c:/osm/words_utf16.txt"); String fileOut = "c:/osm/" + src + "_" + mode + ".dat"; dos = new DataOutputStream(new BufferedOutputStream( new FileOutputStream(fileOut))); for (Tag.Key k : Tag.Key.values()) { mapKeys.put(k.name(), k.ordinal()); } for (Tag.Val v : Tag.Val.values()) { mapVals.put(v.name(), v.ordinal()); } // 第1パス Relation.parseRelation(src); // 第2パス OSMParser parser = new OSMParser(); parser.parse(src); // relation処理 Relation.procRelation(); dos.close(); OSM.writeWords("c:/osm/words_utf16.txt"); System.out.printf("ブロック数=%d maxNodes=%d totalNodes=%d\n", parser.currBlock+1, parser.maxNodes, parser.totalNodes); System.out.printf("実行時間: %.2f分\n", (System.currentTimeMillis()-start)/60000.0); } }