Subversion Repositories splitter

Rev

Rev 344 | Blame | Compare with Previous | Last modification | View Log | RSS feed

/*
 * Copyright (c) 2014.
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 3 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.splitter;

import it.unimi.dsi.fastutil.longs.Long2ObjectOpenHashMap;

import java.awt.geom.Path2D;
import java.awt.geom.Area;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

/**
 *
 * Class to read a polygon description file.
 * Expected input are nodes and ways. Ways with
 * tag name=* and mapid=nnnnnnnn should describe polygons
 * which are used to calculate area lists.  
 * @author GerdP
 *
 */

class PolygonDescProcessor extends AbstractMapProcessor {
        private Long2ObjectOpenHashMap<Node> nodes = new Long2ObjectOpenHashMap<>();
        private final List<PolygonDesc> polygonDescriptions = new ArrayList<>();
        final int resolution;

        public PolygonDescProcessor(int resolution) {
                this.resolution = resolution;
        }

        @Override
        public void processNode(Node n){
                // round all coordinates to be on the used grid.
                int lat = getRoundedCoord(n.getMapLat());
                int lon = getRoundedCoord(n.getMapLon());
                double roundedLat = Utils.toDegrees(lat);
                double roundedLon = Utils.toDegrees(lon);
               
                Node rNode = new Node();
                rNode.set(n.getId(),roundedLat,roundedLon);
                nodes.put(rNode.getId(), rNode);
               
        }

        @Override
        public void processWay(Way w){
                String name = w.getTag("name");
                if (name == null){
                        System.out.println("name missing, ignoring way " + w.getId());
                        return;
                }
                String mapIdString = w.getTag("mapid");
                if (mapIdString == null){
                        System.out.println("mapid missing, ignoring way " + w.getId());
                        return;
                }
                int mapId;
                try{
                        mapId = Integer.parseInt(mapIdString);
                } catch (NumberFormatException e){
                        System.out.println("invalid mapid in way " + w.getId());
                        return;
                }
                Path2D path = null;
                for (long ref : w.getRefs()){
                        Node n = nodes.get(ref);
                        if (n != null){
                                if (path == null){
                                        path = new Path2D.Double();
                                        path.moveTo(n.getMapLon(), n.getMapLat());
                                } else
                                        path.lineTo(n.getMapLon(), n.getMapLat());
                        }
                }
                PolygonDesc pd = new PolygonDesc(name, new Area(path), mapId);
                polygonDescriptions.add(pd);
        }

        @Override
        public boolean endMap(){
                nodes = null;
                System.out.println("found " + polygonDescriptions.size() + " named polygons");
                return true;
        }
       
        /**
         * @return the combined polygon
         */

        Area getCombinedPolygon(){
                Area combinedArea = new Area();  
                for (PolygonDesc pd : polygonDescriptions){
                        combinedArea.add(pd.area);
                }
                return combinedArea;
        }
       
        /**
         * Calculate and write the area lists for each named polygon.
         * @param fileOutputDir
         * @param areas the list of all areas
         * @param kmlOutputFile optional kml file name or null
         * @param outputType file name extension of output files
         * @throws IOException
         */

        public void writeListFiles(File fileOutputDir,
                        List<uk.me.parabola.splitter.Area> areas, String kmlOutputFile, String outputType) throws IOException {
                for (PolygonDesc pd : polygonDescriptions){
                        List<uk.me.parabola.splitter.Area> areasPart = new ArrayList<>();
                        for (uk.me.parabola.splitter.Area a : areas){
                                if (pd.area.intersects(a.getRect()))
                                        areasPart.add(a);
                        }
                        AreaList al = new AreaList(areasPart);
                        if (kmlOutputFile != null){
                                File out = new File(kmlOutputFile);
                                String kmlOutputFilePart = pd.name + "-" + out.getName();
                                if (out.getParent() != null)
                                        out = new File(out.getParent(), kmlOutputFilePart);
                                else
                                        out = new File(kmlOutputFilePart);
                                if (out.getParent() == null)
                                        out = new File(fileOutputDir, kmlOutputFilePart);
                                System.out.println("Writing KML file to " + out.getPath());
                                al.writeKml(out.getPath());
                        }
                        al.writePoly(new File(fileOutputDir, pd.name + "-" + "areas.poly").getPath());
                        al.writeArgsFile(new File(fileOutputDir, pd.name + "-" + "template.args").getPath(), outputType, pd.mapId);
                }
        }
       
        private int getRoundedCoord(int val){
                int shift = 24 - resolution;
                int half = 1 << (shift - 1);    // 0.5 shifted
                int mask = ~((1 << shift) - 1); // to remove fraction bits
                return (val + half) & mask;
        }

        public List<PolygonDesc> getPolygons() {
                return polygonDescriptions;
        }
}