org.opensha2.geo.RegionUtils.java Source code

Java tutorial

Introduction

Here is the source code for org.opensha2.geo.RegionUtils.java

Source

/*******************************************************************************
 * Copyright 2009 OpenSHA.org in partnership with
 * the Southern California Earthquake Center (SCEC, http://www.scec.org)
 * at the University of Southern California and the UnitedStates Geological
 * Survey (USGS; http://www.usgs.gov)
 * 
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * 
 *   http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 ******************************************************************************/

package org.opensha2.geo;

import java.awt.Color;
import java.awt.geom.Area;
import java.io.File;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.transform.OutputKeys;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerConfigurationException;
import javax.xml.transform.TransformerException;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;

import org.opensha2.eq.fault.surface.GriddedSurface;
import org.opensha2.eq.model.SourceElement;
//import org.opensha2.sha.faultSurface.AbstractEvenlyGriddedSurface;
import org.w3c.dom.Document;
import org.w3c.dom.Element;

import com.google.common.base.Preconditions;
import com.google.common.base.Strings;

/**
 * Region export utilities.
 * 
 * @author Peter Powers
 */
public class RegionUtils {

    // TODO clean and cull

    private static final String NL = System.getProperty("line.separator");

    enum Style {
        BORDER, BORDER_VERTEX, GRID_NODE;
    }

    // write region
    public static void regionToKML(Region region, String filename, Color c)
            throws ParserConfigurationException, TransformerConfigurationException, TransformerException {
        String kmlFileName = filename + ".kml";

        DocumentBuilderFactory docFactory = DocumentBuilderFactory.newInstance();
        DocumentBuilder docBuilder = docFactory.newDocumentBuilder();
        Document doc = docBuilder.newDocument();
        Element root = doc.createElementNS("http://www.opengis.net/kml/2.2", "kml");
        doc.appendChild(root);

        Element e_doc = addElement("Document", root);
        Element e_doc_name = addElement("name", e_doc);
        e_doc_name.setTextContent(kmlFileName);

        addBorderStyle(e_doc, c);
        addBorderVertexStyle(e_doc);
        addGridNodeStyle(e_doc, c);

        Element e_folder = addElement("Folder", e_doc);
        Element e_folder_name = addElement("name", e_folder);
        e_folder_name.setTextContent("region");
        Element e_open = addElement("open", e_folder);
        e_open.setTextContent("1");

        addBorder(e_folder, region);
        addPoints(e_folder, "Border Nodes", region.border(), Style.BORDER_VERTEX);
        if (region.interiors() != null) {
            for (LocationList interior : region.interiors()) {
                addPoints(e_folder, "Interior Nodes", interior, Style.BORDER_VERTEX);
            }
        }

        if (region instanceof GriddedRegion) {
            addPoints(e_folder, "Grid Nodes", ((GriddedRegion) region).nodes(), Style.GRID_NODE);
        }

        // TODO absolutely need to create seom platform specific output directory
        // that is not in project space (e.g. desktop, Decs and Settings);

        String outDirName = "tmp/sha_kml/";
        File outDir = new File(outDirName);
        outDir.mkdirs();
        String tmpFile = outDirName + kmlFileName;

        // write the content into xml file
        TransformerFactory transformerFactory = TransformerFactory.newInstance();
        Transformer trans = transformerFactory.newTransformer();
        trans.setOutputProperty(OutputKeys.INDENT, "yes");
        trans.setOutputProperty("{http://xml.apache.org/xslt}indent-amount", "2");
        DOMSource source = new DOMSource(doc);
        StreamResult result = new StreamResult(tmpFile);
        trans.transform(source, result);
    }

    // write region
    public static void locListToKML(LocationList locs, String filename, Color c)
            throws ParserConfigurationException, TransformerConfigurationException, TransformerException {
        String kmlFileName = filename + ".kml";

        DocumentBuilderFactory docFactory = DocumentBuilderFactory.newInstance();
        DocumentBuilder docBuilder = docFactory.newDocumentBuilder();
        Document doc = docBuilder.newDocument();
        Element root = doc.createElementNS("http://www.opengis.net/kml/2.2", "kml");
        doc.appendChild(root);

        Element e_doc = addElement("Document", root);
        Element e_doc_name = addElement("name", e_doc);
        e_doc_name.setTextContent(kmlFileName);

        addBorderStyle(e_doc, c);
        addBorderVertexStyle(e_doc);
        addGridNodeStyle(e_doc, c);

        Element e_folder = addElement("Folder", e_doc);
        Element e_folder_name = addElement("name", e_folder);
        e_folder_name.setTextContent("region");
        Element e_open = addElement("open", e_folder);
        e_open.setTextContent("1");

        //      addLocationPoly(e_folder, locs);
        addLocationLine(e_folder, locs);
        addPoints(e_folder, "Border Nodes", locs, Style.BORDER_VERTEX);

        // TODO absolutely need to create seom platform specific output directory
        // that is not in project space (e.g. desktop, Decs and Settings);

        String outDirName = "tmp/sha_kml/";
        File outDir = new File(outDirName);
        outDir.mkdirs();
        String tmpFile = outDirName + kmlFileName;

        // write the content into xml file
        TransformerFactory transformerFactory = TransformerFactory.newInstance();
        Transformer trans = transformerFactory.newTransformer();
        trans.setOutputProperty(OutputKeys.INDENT, "yes");
        trans.setOutputProperty("{http://xml.apache.org/xslt}indent-amount", "2");
        DOMSource source = new DOMSource(doc);
        StreamResult result = new StreamResult(tmpFile);
        trans.transform(source, result);
    }

    // border polygon
    private static Element addBorder(Element e, Region region) {
        Element e_placemark = addElement("Placemark", e);
        Element e_name = addElement("name", e_placemark);
        e_name.setTextContent("Border");
        Element e_style = addElement("styleUrl", e_placemark);
        e_style.setTextContent("#" + Style.BORDER.toString());
        Element e_poly = addElement("Polygon", e_placemark);
        Element e_tessellate = addElement("tessellate", e_poly);
        e_tessellate.setTextContent("1");

        addPoly(e_poly, "outerBoundaryIs", region.border());
        if (region.interiors() != null) {
            for (LocationList interior : region.interiors()) {
                addPoly(e_poly, "innerBoundaryIs", interior);
            }
        }

        return e;
    }

    // standalone location list
    private static Element addLocationPoly(Element e, LocationList locs) {
        Element e_placemark = addElement("Placemark", e);
        Element e_name = addElement("name", e_placemark);
        e_name.setTextContent("Border");
        Element e_style = addElement("styleUrl", e_placemark);
        e_style.setTextContent("#" + Style.BORDER.toString());
        Element e_poly = addElement("Polygon", e_placemark);
        Element e_tessellate = addElement("tessellate", e_poly);
        e_tessellate.setTextContent("1");

        addPoly(e_poly, "outerBoundaryIs", locs);
        return e;
    }

    // create a closed polygon Element from a LocationList
    private static Element addPoly(Element e, String polyName, LocationList locs) {

        Element e_BI = addElement(polyName, e);
        Element e_LR = addElement("LinearRing", e_BI);
        Element e_coord = addElement("coordinates", e_LR);
        String locStr = locs.toString() + locs.get(0).toString() + NL;
        e_coord.setTextContent(locStr);

        return e;
    }

    // standalone location list
    private static Element addLocationLine(Element e, LocationList locs) {
        Element e_placemark = addElement("Placemark", e);
        Element e_name = addElement("name", e_placemark);
        e_name.setTextContent("Trace");
        Element e_style = addElement("styleUrl", e_placemark);
        e_style.setTextContent("#" + Style.BORDER.toString());
        Element e_line = addElement("LineString", e_placemark);
        Element e_tessellate = addElement("tessellate", e_line);
        e_tessellate.setTextContent("1");
        Element e_coord = addElement("coordinates", e_line);
        e_coord.setTextContent(locs.toString());
        return e;
    }

    //   // create lat-lon data string
    //   private static String parseBorderCoords(Region region) {
    //      LocationList ll = region.getBorder();
    //      StringBuffer sb = new StringBuffer(NL);
    //      //System.out.println("parseBorderCoords: "); // TODO clean
    //      for (Location loc: ll) {
    //         sb.append(loc.toKML() + NL);
    //         //System.out.println(loc.toKML()); // TODO clean
    //      }
    //      // region borders do not repeat the first
    //      // vertex, but kml closed polygons do
    //      sb.append(ll.getLocationAt(0).toKML() + NL);
    //      //System.out.println("---"); // TODO clean
    //      return sb.toString();
    //   }

    // node placemarks
    private static Element addPoints(Element e, String folderName, LocationList locations, Style style) {
        Element e_folder = addElement("Folder", e);
        Element e_folder_name = addElement("name", e_folder);
        e_folder_name.setTextContent(folderName);
        Element e_open = addElement("open", e_folder);
        e_open.setTextContent("0");
        // loop nodes
        for (Location loc : locations) {
            Element e_placemark = addElement("Placemark", e_folder);
            Element e_style = addElement("styleUrl", e_placemark);
            e_style.setTextContent("#" + style.toString());
            Element e_poly = addElement("Point", e_placemark);
            Element e_coord = addElement("coordinates", e_poly);
            //System.out.println(loc.toKML()); // TODO clean
            e_coord.setTextContent(loc.toString());
        }
        return e;
    }

    //<Folder>
    //   <name>region</name>
    //   <open>1</open>
    //   <Placemark>
    //      <name>test region</name>
    //      <styleUrl>#msn_ylw-pushpin</styleUrl>
    //      <Polygon>
    //         <tessellate>1</tessellate>
    //         <outerBoundaryIs>
    //            <LinearRing>
    //               <coordinates>
    //-118.494013126698,34.12890715714403,0 -118.2726369206852,34.02666906748863,0 -117.9627114364491,34.07186823617815,0 -117.9620310910423,34.2668764027905,0 -118.3264939969918,34.39919060861001,0 -118.5320559633752,34.23801999324961,0 -118.494013126698,34.12890715714403,0 </coordinates>
    //            </LinearRing>
    //         </outerBoundaryIs>

    //    <innerBoundaryIs>
    //    <LinearRing>
    //      <coordinates>
    //        -122.366212,37.818977,30
    //        -122.365424,37.819294,30
    //        -122.365704,37.819731,30
    //        -122.366488,37.819402,30
    //        -122.366212,37.818977,30
    //      </coordinates>
    //    </LinearRing>
    //  </innerBoundaryIs>

    //      </Polygon>
    //   </Placemark>
    //   <Placemark>
    //      <LookAt>
    //         <longitude>-118.247043582626</longitude>
    //         <latitude>34.21293007086929</latitude>
    //         <altitude>0</altitude>
    //         <range>60381.34272309824</range>
    //         <tilt>0</tilt>
    //         <heading>-3.115946006858405e-08</heading>
    //         <altitudeMode>relativeToGround</altitudeMode>
    //      </LookAt>
    //      <styleUrl>#msn_placemark_circle</styleUrl>
    //      <Point>
    //         <coordinates>-118.3897877691312,34.24834787236836,0</coordinates>
    //      </Point>
    //   </Placemark>
    //</Folder>

    //    <innerBoundaryIs>
    //    <LinearRing>
    //      <coordinates>
    //        -122.366212593918,37.81897719083808,30 
    //        -122.3654241733188,37.81929450992014,30 
    //        -122.3657048517827,37.81973175302663,30 
    //        -122.3664882465854,37.81940249291773,30 
    //        -122.366212593918,37.81897719083808,30 
    //      </coordinates>
    //    </LinearRing>
    //  </innerBoundaryIs>

    // border style elements
    private static Element addBorderStyle(Element e, Color c) {
        Element e_style = addElement("Style", e);
        e_style.setAttribute("id", Style.BORDER.toString());

        // line style
        Element e_lineStyle = addElement("LineStyle", e_style);
        Element e_color = addElement("color", e_lineStyle);
        e_color.setTextContent(colorToHex(c));
        Element e_width = addElement("width", e_lineStyle);
        e_width.setTextContent("3");

        // poly style
        Element e_polyStyle = addElement("PolyStyle", e_style);
        e_polyStyle.appendChild((Element) e_color.cloneNode(true));
        Element e_fill = addElement("fill", e_polyStyle);
        e_fill.setTextContent("0");

        return e;
    }

    // border vertex style elements
    private static Element addBorderVertexStyle(Element e) {
        Element e_style = addElement("Style", e);
        e_style.setAttribute("id", Style.BORDER_VERTEX.toString());

        // icon style
        Element e_iconStyle = addElement("IconStyle", e_style);
        Element e_color = addElement("color", e_iconStyle);
        e_color.setTextContent(colorToHex(Color.RED));
        Element e_scale = addElement("scale", e_iconStyle);
        e_scale.setTextContent("0.6");
        Element e_icon = addElement("Icon", e_iconStyle);
        Element e_href = addElement("href", e_icon);
        e_href.setTextContent("http://maps.google.com/mapfiles/kml/shapes/open-diamond.png");
        return e;
    }

    // node style elements
    private static Element addGridNodeStyle(Element e, Color c) {
        Element e_style = addElement("Style", e);
        e_style.setAttribute("id", Style.GRID_NODE.toString());

        // icon style
        Element e_iconStyle = addElement("IconStyle", e_style);
        Element e_color = addElement("color", e_iconStyle);
        e_color.setTextContent(colorToHex(c));
        Element e_scale = addElement("scale", e_iconStyle);
        e_scale.setTextContent("0.6");
        Element e_icon = addElement("Icon", e_iconStyle);
        Element e_href = addElement("href", e_icon);
        e_href.setTextContent("http://maps.google.com/mapfiles/kml/shapes/placemark_circle.png");
        return e;
    }

    private static Element createElement(Document doc, SourceElement id) {
        return doc.createElement(id.toString());
    }

    private static Element addElement(String name, Element parent) {
        Element e = parent.getOwnerDocument().createElement(name);
        parent.appendChild(e);
        return e;
    }

    // converts Color to KML compatible ABGR hex value
    private static String colorToHex(Color c) {
        StringBuffer sb = new StringBuffer();
        sb.append(toHex(c.getAlpha()));
        sb.append(toHex(c.getBlue()));
        sb.append(toHex(c.getGreen()));
        sb.append(toHex(c.getRed()));
        return sb.toString();
    }

    // converts ints to hex values, padding single digits as necessary
    private static String toHex(int i) {
        return Strings.padStart(Integer.toHexString(i), 2, '0');
    }

    /**
     * The returns the fraction of points in the given collection of locations that is inside
     * the given region. This will commonly be used with the {@link GriddedSurface}s
     * to determine the fraction of a fault surface that is inside of a region.
     * 
     * @param region the region for which to test
     * @param locs any instance of Iterable<Location>, for example, ArrayList<Location> or GriddedSurface.
     * @return fraction of locations inside the given region
     * @throws NullPointerException if region or locs is null
     * @throws IllegalArgumentException if locs is empty
     */
    public static double getFractionInside(Region region, Iterable<Location> locs)
            throws NullPointerException, IllegalArgumentException {
        Preconditions.checkNotNull(region, "region cannot be null");
        Preconditions.checkNotNull(locs, "locations cannot be null");
        int numInside = 0;
        int cnt = 0;
        for (Location loc : locs) {
            if (region.contains(loc))
                numInside++;
            cnt++;
        }
        Preconditions.checkArgument(cnt > 0, "locs must contain at least one location!");
        return (double) numInside / (double) cnt;
    }

    /**
     * Returns the {@code Region} spanned by a node centered at the supplied
     * location with the given width and height.
     * @param p {@code Location} at center of a grid node
     * @param w node width
     * @param h node height
     * @return the node's {@code Region}
     */
    public static Area getNodeShape(Location p, double w, double h) {
        double halfW = w / 2;
        double halfH = h / 2;
        double nodeLat = p.lat();
        double nodeLon = p.lon();
        LocationList locs = LocationList.create(Location.create(nodeLat + halfH, nodeLon + halfW), // top right
                Location.create(nodeLat - halfH, nodeLon + halfW), // bot right
                Location.create(nodeLat - halfH, nodeLon - halfW), // bot left
                Location.create(nodeLat + halfH, nodeLon - halfW)); // top left
        return new Area(locs.toPath());
    }

    //   private String convertLocations(LocationList ll) {
    //      
    //   }

    public static void main(String[] args) throws Exception {

        //      LocationList ll = LocationList.create(
        //         Location.create(35,-125),
        //         Location.create(38,-117),
        //         Location.create(37,-109),
        //         Location.create(41,-95));
        //      
        //      locListToKML(ll, "Sausage", Color.ORANGE);

        //      // visual verification tests for GeographiRegionTest
        //      Region gr;
        //      
        //      Location L1 = new Location(32,112);
        //      Location L3 = new Location(34,118);
        //      gr = new Region(L1,L3);
        //      RegionUtils.regionToKML(gr, "RegionLocLoc", Color.ORANGE);
        //      

        //      GriddedRegion rect_gr = 
        //         new GriddedRegion(
        //               new Location(40.0,-113),
        //               new Location(42.0,-117),
        //               0.2,null);
        //      KML.regionToKML(
        //            rect_gr,
        //            "RECT_REGION2",
        //            Color.ORANGE);

        //      GriddedRegion relm_gr = new CaliforniaRegions.RELM_TESTING_GRIDDED();
        //      KML.regionToKML(
        //            relm_gr,
        //            "RELM_TESTanchor",
        //            Color.ORANGE);

        //      System.out.println(relm_gr.getMinLat());
        //      System.out.println(relm_gr.getMinGridLat());
        //      System.out.println(relm_gr.getMinLon());
        //      System.out.println(relm_gr.getMinGridLon());
        //      System.out.println(relm_gr.getMaxLat());
        //      System.out.println(relm_gr.getMaxGridLat());
        //      System.out.println(relm_gr.getMaxLon());
        //      System.out.println(relm_gr.getMaxGridLon());

        //      GriddedRegion eggr1 = new CaliforniaRegions.WG02_GRIDDED();
        //      KML.regionToKML(
        //            eggr1, 
        //            "WG02anchor",
        //            Color.ORANGE);

        //      GriddedRegion eggr2 = new CaliforniaRegions.WG07_GRIDDED();
        //      KML.regionToKML(
        //            eggr2, 
        //            "WG07anchor",
        //            Color.ORANGE);

        // TODO test that borders for diff constructors end up the same.

        // test mercator/great-circle region
        //      GriddedRegion eggr3 = new GriddedRegion(
        //            new Location(35,-125),
        //            new Location(45,-90),
        //            0.5);
        //      KML.regionToKML(
        //            eggr3, 
        //            "TEST1_box",
        //            Color.ORANGE);

        // SAUSAGE
        LocationList ll = LocationList.create(Location.create(35, -125), Location.create(38, -117),
                Location.create(37, -109), Location.create(41, -95));

        Region sausage = Regions.createBuffered("Test Buffer", ll, 100.0);
        //      regionToKML(sausage, "Sausage", Color.ORANGE);
        locListToKML(ll, "Sausage", Color.ORANGE);

        //      GriddedRegion sausageAnchor = 
        //         new GriddedRegion(ll,100,0.5,new Location(0,0));
        //      KML.regionToKML(
        //            sausageAnchor,
        //            "SausageAnchor",
        //            Color.BLUE);

        // CIRCLE
        //      Location loc = new Location(35, -125);
        //      GriddedRegion circle =
        //            new GriddedRegion(loc, 400, 0.2, null);
        //      KML.regionToKML(circle, "Circle", Color.ORANGE);
        //
        //      GriddedRegion circleAnchor =
        //            new GriddedRegion(loc, 400, 0.2, new Location(0,0));
        //      KML.regionToKML(circleAnchor, "CircleAnchor", Color.BLUE);

        //      
        //      GriddedRegion eggr4 = new GriddedRegion(
        //            ll,BorderType.MERCATOR_LINEAR,0.5);
        //      KML.regionToKML(
        //            eggr4, 
        //            "TEST1_loclist_lin",
        //            Color.ORANGE);
        //      
        //      
        //      GriddedRegion eggr5 = new GriddedRegion(
        //            ll,BorderType.GREAT_CIRCLE,0.5);
        //      KML.regionToKML(
        //            eggr5, 
        //            "TEST1_loclist_gc",
        //            Color.ORANGE);

    }
}