edu.umn.cs.spatialHadoop.osm.OSMToKML.java Source code

Java tutorial

Introduction

Here is the source code for edu.umn.cs.spatialHadoop.osm.OSMToKML.java

Source

/***********************************************************************
* Copyright (c) 2015 by Regents of the University of Minnesota.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Apache License, Version 2.0 which 
* accompanies this distribution and is available at
* http://www.opensource.org/licenses/apache2.0.php.
*
*************************************************************************/
package edu.umn.cs.spatialHadoop.osm;

import java.io.IOException;
import java.io.PrintWriter;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;

import org.apache.hadoop.fs.FSDataOutputStream;
import org.apache.hadoop.fs.FileSystem;
import org.apache.hadoop.fs.Path;
import org.apache.hadoop.io.ArrayWritable;
import org.apache.hadoop.mapred.FileSplit;
import org.apache.hadoop.util.GenericOptionsParser;

import com.vividsolutions.jts.geom.Coordinate;
import com.vividsolutions.jts.geom.Geometry;
import com.vividsolutions.jts.geom.GeometryCollection;
import com.vividsolutions.jts.geom.LineString;
import com.vividsolutions.jts.geom.LinearRing;
import com.vividsolutions.jts.geom.Point;
import com.vividsolutions.jts.geom.Polygon;

import edu.umn.cs.spatialHadoop.OperationsParams;
import edu.umn.cs.spatialHadoop.core.Rectangle;
import edu.umn.cs.spatialHadoop.core.Shape;
import edu.umn.cs.spatialHadoop.mapred.ShapeArrayRecordReader;

/**
 * Converts a text file containing shapes to a KML file
 * @author Ahmed Eldawy
 *
 */
public class OSMToKML {

    /**
     * Returns the style name that should be used to draw the given object.
     * @param polygon
     * @return
     */
    public static String getStyle(OSMPolygon polygon) {
        if (HasTag.hasTag(polygon.tags, "amenity,building", "yes"))
            return "building";
        if (HasTag.hasTag(polygon.tags, "natural,waterway", "bay,wetland,water,coastline,riverbank,dock,boatyard"))
            return "lake";
        if (HasTag.hasTag(polygon.tags, "leisure,boundary,landuse,natural",
                "wood,tree_row,grassland,park,golf_course,national_park,garden,nature_reserve,forest,grass,tree,orchard,farmland,protected_area"))
            return "park";
        if (HasTag.hasTag(polygon.tags, "landuse", "cemetery"))
            return "cemetery";
        if (HasTag.hasTag(polygon.tags, "leisure,landuse",
                "sports_centre,stadium,track,pitch,golf_course,water_park,swimming_pool,recreation_ground,piste"))
            return "sport";
        if (HasTag.hasTag(polygon.tags, "admin_level", "8"))
            return "postal_code";
        return null;
    }

    public static void writeAllStyles(PrintWriter out) {
        out.println("<Style id='lake'>");
        out.println("<LineStyle>");
        out.println("<color>ffff0000</color>");
        out.println("<width>3.0</width>");
        out.println("</LineStyle>");
        out.println("<PolyStyle>");
        out.println("<color>3dff0000</color>");
        out.println("</PolyStyle>");
        out.println("</Style>");

        out.println("<Style id='park'>");
        out.println("<LineStyle>");
        out.println("<color>ff00ff00</color>");
        out.println("<width>2.0</width>");
        out.println("</LineStyle>");
        out.println("<PolyStyle>");
        out.println("<color>3d00ff00</color>");
        out.println("</PolyStyle>");
        out.println("</Style>");

        out.println("<Style id='cemetery'>");
        out.println("<LineStyle>");
        out.println("<color>ff000000</color>");
        out.println("<width>2.0</width>");
        out.println("</LineStyle>");
        out.println("<PolyStyle>");
        out.println("<color>1d000000</color>");
        out.println("</PolyStyle>");
        out.println("</Style>");

        out.println("<Style id='postal_code'>");
        out.println("<LineStyle>");
        out.println("<color>ffffffff</color>");
        out.println("<width>2.0</width>");
        out.println("</LineStyle>");
        out.println("<PolyStyle>");
        out.println("<color>00000000</color>");
        out.println("</PolyStyle>");
        out.println("</Style>");

        out.println("<Style id='sport'>");
        out.println("<LineStyle>");
        out.println("<color>ff0ec9ff</color>");
        out.println("<width>2.0</width>");
        out.println("</LineStyle>");
        out.println("<PolyStyle>");
        out.println("<color>3d0ec9ff</color>");
        out.println("</PolyStyle>");
        out.println("</Style>");

        out.println("<Style id='building'>");
        out.println("<LineStyle>");
        out.println("<color>ff000000</color>");
        out.println("<width>2.0</width>");
        out.println("</LineStyle>");
        out.println("<PolyStyle>");
        out.println("<color>7fffffff</color>");
        out.println("</PolyStyle>");
        out.println("</Style>");
    }

    public static void geometryToKML(StringBuilder str, Geometry geom) {
        if (geom instanceof Point) {
            Point pt = (Point) geom;
            str.append("<Point>");
            str.append("<coordinates>");
            str.append(pt.getX() + "," + pt.getY());
            str.append("</coordinates>");
            str.append("</Point>");
        } else if (geom instanceof LinearRing) {
            LinearRing linearRing = (LinearRing) geom;
            str.append("<LinearRing>");
            str.append("<coordinates>");
            for (Coordinate coord : linearRing.getCoordinates())
                str.append(coord.x + "," + coord.y + " ");
            str.append("</coordinates>");
            str.append("</LinearRing>");
        } else if (geom instanceof LineString) {
            LineString linestring = (LineString) geom;
            str.append("<LineString>");
            str.append("<coordinates>");
            for (Coordinate coord : linestring.getCoordinates())
                str.append(coord.x + "," + coord.y + " ");
            str.append("</coordinates>");
            str.append("</LineString>");
        } else if (geom instanceof Polygon) {
            Polygon polygon = (Polygon) geom;
            str.append("<Polygon>");

            // Write exterior boundary
            str.append("<outerBoundaryIs>");
            geometryToKML(str, polygon.getExteriorRing());
            str.append("</outerBoundaryIs>");

            // Write all interior boundaries
            for (int n = 0; n < polygon.getNumInteriorRing(); n++) {
                str.append("<innerBoundaryIs>");
                geometryToKML(str, polygon.getInteriorRingN(n));
                str.append("</innerBoundaryIs>");
            }
            str.append("</Polygon>");
        } else if (geom instanceof GeometryCollection) {
            GeometryCollection geomCollection = (GeometryCollection) geom;
            str.append("<GeometryCollection>");
            for (int n = 0; n < geomCollection.getNumGeometries(); n++) {
                geometryToKML(str, geomCollection.getGeometryN(n));
            }
            str.append("</GeometryCollection>");
        } else if (geom != null) {
            throw new RuntimeException("Cannot generate KML from '" + geom.getClass() + "'");
        }
    }

    /**
     * Returns a KML representation of this object.
     * @return
     */
    public static String OSMtoKMLElement(OSMPolygon osm) {
        StringBuilder str = new StringBuilder();
        str.append("<Placemark>");
        str.append("<styleUrl>#" + getStyle(osm) + "</styleUrl>");
        if (osm.tags != null) {
            if (osm.tags.containsKey("name")) {
                str.append("<name>");
                str.append("<![CDATA[");
                str.append(osm.tags.get("name"));
                str.append("]]>");
                str.append("</name>");
            }
            str.append("<description>");
            str.append("<![CDATA[");
            str.append(osm.tags.toString());
            str.append("]]>");
            str.append("</description>");

            geometryToKML(str, osm.geom);
        }
        str.append("</Placemark>");
        return str.toString();
    }

    /**
     * @param args
     * @throws IOException 
     */
    public static void main(String[] args) throws IOException {
        final OperationsParams params = new OperationsParams(new GenericOptionsParser(args), false);
        if (!params.checkInputOutput()) {
            System.err.println("Please specify input and output");
            System.exit(1);
        }
        params.setClass("shape", OSMPolygon.class, Shape.class);
        Path inputPath = params.getInputPath();
        FileSystem inFs = inputPath.getFileSystem(params);
        ShapeArrayRecordReader in = new ShapeArrayRecordReader(params,
                new FileSplit(inputPath, 0, inFs.getFileStatus(inputPath).getLen(), new String[0]));
        Path outPath = params.getOutputPath();
        FileSystem outFs = outPath.getFileSystem(params);
        PrintWriter out;
        ZipOutputStream zipOut = null;
        if (outPath.getName().toLowerCase().endsWith(".kmz")) {
            // Create a KMZ file
            FSDataOutputStream kmzOut = outFs.create(outPath);
            zipOut = new ZipOutputStream(kmzOut);
            zipOut.putNextEntry(new ZipEntry("osm.kml"));
            out = new PrintWriter(zipOut);
        } else {
            out = new PrintWriter(outFs.create(outPath));
        }
        out.println("<?xml version='1.0' encoding='UTF-8'?>");
        out.println("<kml xmlns='http://www.opengis.net/kml/2.2'>");
        out.println("<Document>");
        writeAllStyles(out);
        Rectangle key = in.createKey();
        ArrayWritable values = in.createValue();
        while (in.next(key, values)) {
            System.out.println("Read " + values.get().length);
            for (Shape shape : (Shape[]) values.get()) {
                if (shape instanceof OSMPolygon) {
                    out.println(OSMtoKMLElement((OSMPolygon) shape));
                }
            }
            out.println();
        }
        out.println("</Document>");
        out.println("</kml>");
        in.close();
        if (zipOut != null) {
            // KMZ file
            out.flush();
            zipOut.closeEntry();
            zipOut.close();
        } else {
            // KML file
            out.close();
        }
    }

}