view flys-artifacts/src/main/java/de/intevation/flys/utils/GeometryUtils.java @ 4221:480de0dbca8e

Extended location input helper. The locationpicker has now an attribute whether the input is distance or location to display one or two clickable columns. Replaced the record click handler with cell click handler.
author Raimund Renkert <rrenkert@intevation.de>
date Tue, 23 Oct 2012 13:17:20 +0200
parents 1b41dc00b1f7
children c1b60f8c3390
line wrap: on
line source
package de.intevation.flys.utils;

import com.vividsolutions.jts.geom.Coordinate;
import com.vividsolutions.jts.geom.Envelope;
import com.vividsolutions.jts.geom.Geometry;

import de.intevation.flys.model.RiverAxis;

import java.io.File;
import java.io.IOException;
import java.io.Serializable;
import java.net.MalformedURLException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.apache.log4j.Logger;
import org.geotools.data.DataStoreFactorySpi;
import org.geotools.data.DefaultTransaction;
import org.geotools.data.FeatureWriter;
import org.geotools.data.Transaction;
import org.geotools.data.shapefile.ShapefileDataStore;
import org.geotools.data.shapefile.ShapefileDataStoreFactory;
import org.geotools.data.simple.SimpleFeatureIterator;
import org.geotools.feature.FeatureCollection;
import org.geotools.feature.FeatureIterator;
import org.geotools.feature.simple.SimpleFeatureTypeBuilder;
import org.geotools.geojson.feature.FeatureJSON;
import org.geotools.geometry.jts.JTS;
import org.geotools.geometry.jts.ReferencedEnvelope;
import org.geotools.referencing.CRS;
import org.opengis.feature.simple.SimpleFeature;
import org.opengis.feature.simple.SimpleFeatureType;
import org.opengis.referencing.FactoryException;
import org.opengis.referencing.NoSuchAuthorityCodeException;
import org.opengis.referencing.crs.CoordinateReferenceSystem;
import org.opengis.referencing.operation.MathTransform;
import org.opengis.referencing.operation.TransformException;

public class GeometryUtils {

    private static final Logger logger = Logger.getLogger(GeometryUtils.class);

    public static final String PREFIX_EPSG  = "EPSG:";

    public static final String DEFAULT_EPSG = "EPSG:31467";

    private GeometryUtils() {
    }

    public static Envelope getRiverBoundary(String rivername) {
        List<RiverAxis> axes = RiverAxis.getRiverAxis(rivername);
        if (axes != null && axes.size() > 0) {
            Envelope max = null;

            for (RiverAxis axis: axes) {
                // TODO Take the correct EPSG into account. Maybe, we need to
                // reproject the geometry.
                Envelope env = axis.getGeom().getEnvelopeInternal();

                if (max == null) {
                    max = env;
                }
                else {
                    max.expandToInclude(env);
                }
            }

            return max;
        }

        return null;
    }

    public static String getRiverBounds(String rivername) {
        Envelope env = getRiverBoundary(rivername);

        if (env != null) {
            return jtsBoundsToOLBounds(env);
        }

        return null;
    }

    /**
     * Returns the boundary of Envelope <i>env</i> in OpenLayers representation.
     *
     * @param env The envelope of a geometry.
     *
     * @return the OpenLayers boundary of <i>env</i>.
     */
    public static String jtsBoundsToOLBounds(Envelope env) {
        StringBuilder buf = new StringBuilder();
        buf.append(env.getMinX()); buf.append(' ');
        buf.append(env.getMinY()); buf.append(' ');
        buf.append(env.getMaxX()); buf.append(' ');
        buf.append(env.getMaxY());
        return buf.toString();
    }

    public static String createOLBounds(Geometry a, Geometry b) {
        Coordinate[] ca = a.getCoordinates();
        Coordinate[] cb = b.getCoordinates();

        double lowerX = Double.MAX_VALUE;
        double lowerY = Double.MAX_VALUE;
        double upperX = -Double.MAX_VALUE;
        double upperY = -Double.MAX_VALUE;

        for (Coordinate c: ca) {
            lowerX = lowerX < c.x ? lowerX : c.x;
            lowerY = lowerY < c.y ? lowerY : c.y;

            upperX = upperX > c.x ? upperX : c.x;
            upperY = upperY > c.y ? upperY : c.y;
        }

        for (Coordinate c: cb) {
            lowerX = lowerX < c.x ? lowerX : c.x;
            lowerY = lowerY < c.y ? lowerY : c.y;

            upperX = upperX > c.x ? upperX : c.x;
            upperY = upperY > c.y ? upperY : c.y;
        }

        return "" + lowerX + " " + lowerY + " " + upperX + " " + upperY;
    }

    public static SimpleFeatureType buildFeatureType(
        String name, String srs, Class<?> geometryType)
    {
        return buildFeatureType(name, srs, geometryType, null);
    }

    /**
     * Creates a new SimpleFeatureType using a SimpleFeatureTypeBuilder.
     *
     * @param name The name of the FeatureType.
     * @param srs The SRS (e.g. "EPSG:31466").
     * @param geometryType The geometry type's class (e.g. Polygon.class).
     * @param attrs Optional. An object with attribute-name/attribute-class pairs
     * where index 0 specifies the name as string and index 1 the
     * ype as class.
     *
     * @return a new SimpleFeatureType.
     */
    public static SimpleFeatureType buildFeatureType(String name, String srs,
        Class<?> geometryType, Object[][] attrs) {
        try {
            SimpleFeatureTypeBuilder builder = new SimpleFeatureTypeBuilder();
            CoordinateReferenceSystem crs    = CRS.decode(srs);

            builder.setName("flys");
            builder.setNamespaceURI("http://www.intevation.de/");
            builder.setCRS(crs);
            builder.setSRS(srs);

            builder.add("geometry", geometryType, crs);

            if (attrs != null) {
                for (Object[] attr: attrs) {
                    builder.add((String) attr[0], (Class<?>) attr[1]);
                }
            }

            return builder.buildFeatureType();
        }
        catch (NoSuchAuthorityCodeException nsae) {
        }
        catch (FactoryException fe) {
        }

        return null;
    }

    public static List<SimpleFeature> parseGeoJSON(
        String geojson, SimpleFeatureType ft
    ) {
        List<SimpleFeature> collection = new ArrayList<SimpleFeature>();

        try {
            FeatureJSON fjson = new FeatureJSON();
            fjson.setFeatureType(ft);

            FeatureIterator<SimpleFeature> iterator =
                fjson.streamFeatureCollection(geojson);

            while (iterator.hasNext()) {
                collection.add(iterator.next());
            }
        }
        catch (IOException ioe) {
            // TODO handle exception
        }

        return collection;
    }


    /**
     * This method returns the {@link CoordinateReferenceSystem} by the
     * {@link String} <i>epsg</i>.
     *
     * @param epsg An EPSG code like <b>EPSG:31466</b>
     *
     * @return the {@link CoordinateReferenceSystem} specified by <i>epsg</i>.
     */
    public static CoordinateReferenceSystem getCoordinateReferenceSystem(
        String epsg
    ) {
        if (epsg == null) {
            logger.warn("cannot create CoordinateReferenceSystem with null");
            return null;
        }

        if (!epsg.startsWith(PREFIX_EPSG)) {
            epsg = PREFIX_EPSG + epsg;
        }

        try {
            return CRS.decode(epsg);
        }
        catch (FactoryException fe) {
            logger.error(
                "unable to get CoordinateReferenceSystem for: " + epsg,
                fe);
        }

        return null;
    }


    public static Envelope transform(Envelope orig, String targetSrs) {
        return transform(orig, targetSrs, DEFAULT_EPSG);
    }


    public static Envelope transform(
        Envelope orig,
        String   targetSrs,
        String   origSrs
    ) {
        if (targetSrs == null || orig == null || origSrs == null) {
            logger.warn("unable to transform envelope: empty parameters");
            return orig;
        }

        logger.debug("Transform envlope to '" + targetSrs + "'");
        try {
            CoordinateReferenceSystem sourceCRS =
                getCoordinateReferenceSystem(origSrs);

            CoordinateReferenceSystem targetCRS =
                getCoordinateReferenceSystem(targetSrs);

            if (sourceCRS != null && targetCRS != null) {
                ReferencedEnvelope tmpEnv =
                    new ReferencedEnvelope(orig, CRS.decode(origSrs));

                Envelope target = tmpEnv.transform(targetCRS, false);

                if (logger.isDebugEnabled()) {
                    logger.debug("   orig envelope       : " + orig);
                    logger.debug("   transformed envelope: " + target);
                }

                return target;
            }
        }
        catch (NoSuchAuthorityCodeException nsae) {
            logger.error("Cannot get CoordinateReferenceSystem!", nsae);
        }
        catch (FactoryException fe) {
            logger.error("Cannot get CoordinateReferenceSystem!", fe);
        }
        catch (TransformException te) {
            logger.error("Cannot transform envelope from source "
                + origSrs + " to target srs " + targetSrs);
        }

        return null;
    }


    public static boolean writeShapefile(File shape,
        SimpleFeatureType featureType, FeatureCollection<?, ?> collection) {
        return writeShapefile(shape, featureType, collection,
            featureType.getCoordinateReferenceSystem());
    }


    public static boolean writeShapefile(File shape,
        SimpleFeatureType featureType, FeatureCollection<?, ?> collection,
        CoordinateReferenceSystem crs) {
        if (collection.isEmpty()) {
            logger.warn("Shapefile is not written - no features given!");
            return false;
        }

        Transaction   transaction = null;

        try {
            MathTransform transform = CRS.findMathTransform(
                CRS.decode(DEFAULT_EPSG), crs);

            Map<String, Serializable> params =
                new HashMap<String, Serializable>();

            params.put("url", shape.toURI().toURL());
            params.put("create spatial index", Boolean.TRUE);

            DataStoreFactorySpi dataStoreFactory =
                new ShapefileDataStoreFactory();

            ShapefileDataStore newDataStore =
                (ShapefileDataStore)dataStoreFactory.createNewDataStore(params);
            newDataStore.createSchema(featureType);

            transaction = new DefaultTransaction("create");

            String typeName = newDataStore.getTypeNames()[0];

            FeatureWriter<SimpleFeatureType, SimpleFeature> writer =
                newDataStore.getFeatureWriter(typeName, transaction);

            SimpleFeatureIterator iterator = (SimpleFeatureIterator) collection.features();

            while (iterator.hasNext()){
                SimpleFeature feature = iterator.next();
                SimpleFeature copy    = writer.next();

                copy.setAttributes(feature.getAttributes());

                Geometry orig        = (Geometry) feature.getDefaultGeometry();
                Geometry reprojected = JTS.transform(orig, transform);

                copy.setDefaultGeometry(reprojected);
                writer.write();
            }

            transaction.commit();

            return true;
        }
        catch (MalformedURLException mue) {
            logger.error("Unable to prepare shapefile: " + mue.getMessage());
        }
        catch (IOException ioe) {
            logger.error("Unable to write shapefile: " + ioe.getMessage());
        }
        catch (NoSuchAuthorityCodeException nsae) {
            logger.error("Cannot get CoordinateReferenceSystem for '"
                + DEFAULT_EPSG + "'");
        }
        catch (FactoryException fe) {
            logger.error("Cannot get CoordinateReferenceSystem for '"
                + DEFAULT_EPSG + "'");
        }
        catch (TransformException te) {
            logger.error("Was not able to transform geometry!", te);
        }
        finally {
            if (transaction != null) {
                try {
                    transaction.close();
                }
                catch (IOException ioe) { /* do nothing */ }
            }
        }

        return false;
    }
}
// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 :

http://dive4elements.wald.intevation.org