Mercurial > dive4elements > river
diff flys-artifacts/src/main/java/de/intevation/flys/utils/GeometryUtils.java @ 3318:dbe2f85bf160
merged flys-artifacts/2.8
author | Thomas Arendsen Hein <thomas@intevation.de> |
---|---|
date | Fri, 28 Sep 2012 12:14:35 +0200 |
parents | 1b41dc00b1f7 |
children | c1b60f8c3390 |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/de/intevation/flys/utils/GeometryUtils.java Fri Sep 28 12:14:35 2012 +0200 @@ -0,0 +1,375 @@ +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 :