/* * Copyright (C) 2006, 2011. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 3 or * version 2 as published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. */ package uk.me.parabola.mkgmap.reader.osm.boundary; import java.awt.geom.Area; import java.io.File; import java.util.ArrayList; import java.util.Collections; import java.util.HashSet; import java.util.List; import java.util.ListIterator; import java.util.Queue; import java.util.Set; import java.util.concurrent.Callable; import java.util.concurrent.ExecutionException; import java.util.concurrent.ExecutorCompletionService; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.Future; import java.util.concurrent.LinkedBlockingQueue; import java.util.concurrent.atomic.AtomicInteger; import uk.me.parabola.imgfmt.app.Coord; import uk.me.parabola.mkgmap.reader.osm.Way; import uk.me.parabola.util.GpxCreator; import uk.me.parabola.util.Java2DConverter; public class BoundaryCoverageUtil { private final BoundaryQuadTree bqt; public BoundaryCoverageUtil(String boundaryDirName, String boundaryFileName) { bqt = BoundaryUtil.loadQuadTree(boundaryDirName, boundaryFileName); } public Area getCoveredArea(int admLevel) { return bqt.getCoveredArea(admLevel); } private static void saveArea(String attribute, Integer level, Area covered) { String gpxBasename = "gpx/summary/" + attribute + "/admin_level=" + level; List<List<Coord>> coveredPolys = Java2DConverter.areaToShapes(covered); Collections.reverse(coveredPolys); int i = 0; for (List<Coord> coveredPart : coveredPolys) { String attr = Way.clockwise(coveredPart) ? "o" : "i"; GpxCreator.createGpx(gpxBasename + "/" + i + "_" + attr, coveredPart); i++; } } public static void main(String[] args) throws InterruptedException { int processors = Runtime.getRuntime().availableProcessors(); ExecutorService excSvc = Executors.newFixedThreadPool(processors); ExecutorCompletionService<Area> executor = new ExecutorCompletionService<Area>( excSvc); String workDirName = args[0]; System.out.println(workDirName); File boundaryDir = new File(workDirName); final Set<String> boundsFileNames = new HashSet<String>(); if (boundaryDir.isFile() && boundaryDir.getName().endsWith(".bnd")) { workDirName = boundaryDir.getParent(); if (workDirName == null) workDirName = "."; boundsFileNames.add(boundaryDir.getName()); } else { boundsFileNames.addAll(BoundaryUtil .getBoundaryDirContent(workDirName)); } int minLat = Integer.MAX_VALUE; int maxLat = Integer.MIN_VALUE; int minLon = Integer.MAX_VALUE; int maxLon = Integer.MIN_VALUE; for (String fileName : boundsFileNames) { String[] parts = fileName.substring("bounds_".length(), fileName.length() - 4).split("_"); int lat = Integer.valueOf(parts[0]); int lon = Integer.valueOf(parts[1]); if (lat < minLat) minLat = lat; if (lat > maxLat) maxLat = lat; if (lon < minLon) minLon = lon; if (lon > maxLon) maxLon = lon; } System.out.format("Covered area: (%d,%d)-(%d,%d)\n", minLat, minLon, maxLat, maxLon); int maxSteps = 2; final String boundaryDirName = workDirName; for (int adminlevel = 2; adminlevel < 12; adminlevel++) { final Set<String> boundaryFileNames = Collections.synchronizedSet(new HashSet<String>(boundsFileNames)); final int adminLevel = adminlevel; final Queue<Future<Area>> areas = new LinkedBlockingQueue<Future<Area>>(); for (int lat = minLat; lat <= maxLat; lat += maxSteps * BoundaryUtil.RASTER) { for (int lon = minLon; lon <= maxLon; lon += maxSteps * BoundaryUtil.RASTER) { for (int latStep = 0; latStep < maxSteps && lat + latStep * BoundaryUtil.RASTER <= maxLat; latStep++) { for (int lonStep = 0; lonStep < maxSteps && lon + lonStep * BoundaryUtil.RASTER <= maxLon; lonStep++) { final int fLat = lat + latStep * BoundaryUtil.RASTER; final int fLon = lon + lonStep * BoundaryUtil.RASTER; areas.add(executor.submit(new Callable<Area>() { public Area call() { String filename = "bounds_" + fLat + "_" + fLon + ".bnd"; if (boundaryFileNames.contains(filename) == false) { return new Area(); } BoundaryCoverageUtil converter = new BoundaryCoverageUtil( boundaryDirName, filename); boundaryFileNames.remove(filename); System.out.format("%5d bounds files remaining\n", boundaryFileNames.size()); return converter.getCoveredArea(adminLevel); } })); } } } } final AtomicInteger mergeSteps = new AtomicInteger(); while (areas.size() > 1) { final List<Future<Area>> toMerge = new ArrayList<Future<Area>>(); for (int i = 0; i < maxSteps * 2 && areas.isEmpty() == false; i++) { toMerge.add(areas.poll()); } mergeSteps.incrementAndGet(); areas.add(executor.submit(new Callable<Area>() { public Area call() { Area a = new Area(); ListIterator<Future<Area>> mergeAreas = toMerge .listIterator(); while (mergeAreas.hasNext()) { try { a.add(mergeAreas.next().get()); } catch (InterruptedException exp) { System.err.println(exp); } catch (ExecutionException exp) { System.err.println(exp); } mergeAreas.remove(); } System.out.format("%5d merges remaining\n",mergeSteps.decrementAndGet()); return a; } })); } try { Area finalArea = areas.poll().get(); System.out.println("Joining finished. Saving results."); saveArea("covered", adminlevel, finalArea); } catch (Exception exp) { System.err.println(exp); } // } } excSvc.shutdown(); } }