de.bund.bfr.knime.gis.GisUtils.java Source code

Java tutorial

Introduction

Here is the source code for de.bund.bfr.knime.gis.GisUtils.java

Source

/*******************************************************************************
 * Copyright (c) 2016 German Federal Institute for Risk Assessment (BfR)
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * 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.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 *
 * Contributors:
 *     Department Biological Safety - BfR
 *******************************************************************************/
package de.bund.bfr.knime.gis;

import java.awt.geom.Point2D;
import java.awt.geom.Rectangle2D;
import java.io.IOException;
import java.net.MalformedURLException;
import java.nio.file.Files;
import java.nio.file.InvalidPathException;
import java.nio.file.NoSuchFileException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
import java.util.stream.Stream;

import org.apache.commons.io.FilenameUtils;
import org.geotools.data.shapefile.ShapefileDataStore;
import org.geotools.referencing.CRS;
import org.knime.core.data.DataCell;
import org.opengis.referencing.FactoryException;
import org.opengis.referencing.crs.CoordinateReferenceSystem;
import org.openstreetmap.gui.jmapviewer.OsmMercator;

import com.google.common.base.Joiner;
import com.vividsolutions.jts.geom.Coordinate;
import com.vividsolutions.jts.geom.Geometry;
import com.vividsolutions.jts.geom.GeometryFactory;
import com.vividsolutions.jts.geom.LinearRing;
import com.vividsolutions.jts.geom.MultiPolygon;
import com.vividsolutions.jts.geom.Point;
import com.vividsolutions.jts.geom.Polygon;

import de.bund.bfr.knime.KnimeUtils;
import de.bund.bfr.knime.gis.shapecell.ShapeValue;

/**
 * @author Christian Thoens
 */
public class GisUtils {

    private static final GeometryFactory FACTORY = new GeometryFactory();

    private GisUtils() {
    }

    public static Polygon createBorderPolygon(Rectangle2D rect, double d) {
        Coordinate[] outerRing = new Coordinate[] { new Coordinate(rect.getMinX() - d, rect.getMinY() - d),
                new Coordinate(rect.getMaxX() + d, rect.getMinY() - d),
                new Coordinate(rect.getMaxX() + d, rect.getMaxY() + d),
                new Coordinate(rect.getMinX() - d, rect.getMaxY() + d),
                new Coordinate(rect.getMinX() - d, rect.getMinY() - d) };
        Coordinate[] innerRing = new Coordinate[] { new Coordinate(rect.getMinX(), rect.getMinY()),
                new Coordinate(rect.getMaxX(), rect.getMinY()), new Coordinate(rect.getMaxX(), rect.getMaxY()),
                new Coordinate(rect.getMinX(), rect.getMaxY()), new Coordinate(rect.getMinX(), rect.getMinY()) };

        return FACTORY.createPolygon(FACTORY.createLinearRing(outerRing),
                new LinearRing[] { FACTORY.createLinearRing(innerRing) });
    }

    public static Point2D latLonToViz(Point2D p) {
        return new Point2D.Double(new OsmMercator().lonToX(p.getY(), 0), new OsmMercator().latToY(p.getX(), 0));
    }

    public static MultiPolygon latLonToViz(MultiPolygon multiPolygon) {
        return FACTORY.createMultiPolygon(
                getPolygons(multiPolygon).stream().map(p -> latLonToViz(p)).toArray(Polygon[]::new));
    }

    private static Polygon latLonToViz(Polygon polygon) {
        LinearRing exterior = latLonToViz((LinearRing) polygon.getExteriorRing());
        LinearRing[] interior = getInteriorRings(polygon).stream().map(r -> latLonToViz(r))
                .toArray(LinearRing[]::new);

        return FACTORY.createPolygon(exterior, interior);
    }

    private static LinearRing latLonToViz(LinearRing ring) {
        return FACTORY.createLinearRing(Stream.of(ring.getCoordinates())
                .map(c -> new Coordinate(new OsmMercator().lonToX(c.y, 0), new OsmMercator().latToY(c.x, 0)))
                .toArray(Coordinate[]::new));
    }

    public static ShapefileDataStore getDataStore(String shpFile) throws IOException {
        return new ShapefileDataStore(KnimeUtils.getFile(shpFile).toURI().toURL());
    }

    public static CoordinateReferenceSystem getCoordinateSystem(String shpFile)
            throws InvalidPathException, MalformedURLException, IOException, FactoryException, NoSuchFileException {
        try (Stream<String> stream = Files
                .lines(KnimeUtils.getFile(FilenameUtils.removeExtension(shpFile) + ".prj").toPath())) {
            return CRS.parseWKT(stream.collect(Collectors.joining()));
        }
    }

    public static Geometry getShape(DataCell cell) {
        return cell instanceof ShapeValue ? ((ShapeValue) cell).getShape() : null;
    }

    public static Point2D getCenterOfLargestPolygon(MultiPolygon poly) {
        Map<Polygon, Double> areas = new LinkedHashMap<>();

        getPolygons(poly).forEach(p -> areas.put(p, p.getArea()));

        Point center = Collections.max(areas.entrySet(), (p1, p2) -> Double.compare(p1.getValue(), p2.getValue()))
                .getKey().getCentroid();

        return new Point2D.Double(center.getX(), center.getY());
    }

    private static List<Polygon> getPolygons(MultiPolygon multiPolygon) {
        List<Polygon> polygons = new ArrayList<>();

        for (int i = 0; i < multiPolygon.getNumGeometries(); i++) {
            polygons.add((Polygon) multiPolygon.getGeometryN(i));
        }

        return polygons;
    }

    private static List<LinearRing> getInteriorRings(Polygon polygon) {
        List<LinearRing> rings = new ArrayList<>();

        for (int i = 0; i < polygon.getNumInteriorRing(); i++) {
            rings.add((LinearRing) polygon.getInteriorRingN(i));
        }

        return rings;
    }

    public static String getAddress(String street, String houseNumber, String city, String district, String state,
            String country, String postalCode, boolean houseNumberAfterStreet) {
        List<String> parts = new ArrayList<>();

        if (street != null && houseNumber != null) {
            if (houseNumberAfterStreet) {
                parts.add(street + " " + houseNumber);
            } else {
                parts.add(houseNumber + " " + street);
            }
        } else if (street != null) {
            parts.add(street);
        }

        if (city != null) {
            parts.add(city);
        }

        if (postalCode != null) {
            parts.add(postalCode);
        }

        if (district != null) {
            parts.add(district);
        }

        if (state != null) {
            parts.add(state);
        }

        if (country != null) {
            parts.add(country);
        }

        if (parts.isEmpty()) {
            return null;
        }

        return Joiner.on(", ").join(parts);
    }
}