# HG changeset patch # User Sascha L. Teichmann # Date 1263936208 0 # Node ID 4080b57dcb529f60ea27ddff811285517ce5f082 # Parent 75306d85600458f0d416cd3d5f3b34ba41fc7ed5 Upgraded to Geotools 2.5.8. Write polygons and line strings to shape files. gnv-artifacts/trunk@578 c6561f87-3c4e-4783-a992-168aeb5c3f6f diff -r 75306d856004 -r 4080b57dcb52 gnv-artifacts/ChangeLog --- a/gnv-artifacts/ChangeLog Tue Jan 19 17:55:08 2010 +0000 +++ b/gnv-artifacts/ChangeLog Tue Jan 19 21:23:28 2010 +0000 @@ -1,3 +1,32 @@ +2010-01-19 Sascha L. Teichmann + + * trunk/pom.xml: Upgraded Geotools to 2.5.8 + + * trunk/src/main/java/de/intevation/gnv/utils/ShapeFileWriter.java: + Ported to Geotools 2.5.8 API. Write parameter id, date and layer + to shape files, too. + + * trunk/src/main/java/de/intevation/gnv/math/AreaInterpolation.java: + Flip upside down again because its not necessary. + + * trunk/src/main/java/de/intevation/gnv/raster/JTSMultiPolygonProducer.java: + XXX: There is a Geotools bug when writing multi lines strings + to shape files when the internal data representation are + packed 2-tuples. 2-tuples are enough in our use case but we + use 3-tuples for multi line line strings. multi polygons work + fine with 2-tuples. + Removed needless bug output. + + * src/main/java/de/intevation/gnv/raster/JTSMultiLineStringProducer.java: + Use packed 3-tuples as the internal representation. + + * src/test/java/de/intevation/gnv/artifacts/GNVArtifactsTestCaseBase.java, + src/main/java/de/intevation/gnv/state/timeseries/TimeSeriesOutputState.java: + Removed needless imports. + + * src/main/java/de/intevation/gnv/state/profile/horizontalcrosssection/HorizontalCrossSectionMeshOutputState.java: Write polygons and lines strings to + shape files. + 2010-01-19 Sascha L. Teichmann * src/main/java/de/intevation/gnv/math/AreaInterpolation.java: diff -r 75306d856004 -r 4080b57dcb52 gnv-artifacts/pom.xml --- a/gnv-artifacts/pom.xml Tue Jan 19 17:55:08 2010 +0000 +++ b/gnv-artifacts/pom.xml Tue Jan 19 21:23:28 2010 +0000 @@ -115,8 +115,13 @@ org.geotools - gt2-shapefile - 2.4.5 + gt-shapefile + 2.5.8 + + + org.geotools + gt-epsg-wkt + 2.5.8 com.vividsolutions @@ -133,7 +138,7 @@ gt2.repo GeoTools2 Repository including JTS - http://maven.geotools.fr/repository + http://download.osgeo.org/webdav/geotools repository.jboss.org diff -r 75306d856004 -r 4080b57dcb52 gnv-artifacts/src/main/java/de/intevation/gnv/math/AreaInterpolation.java --- a/gnv-artifacts/src/main/java/de/intevation/gnv/math/AreaInterpolation.java Tue Jan 19 17:55:08 2010 +0000 +++ b/gnv-artifacts/src/main/java/de/intevation/gnv/math/AreaInterpolation.java Tue Jan 19 21:23:28 2010 +0000 @@ -111,8 +111,8 @@ double minX = boundingBox.getMinX(); double minY = boundingBox.getMinY(); - int row = (H-1)*W; - for (int j = 0; j < H; ++j, row -= W) { + int row = 0; + for (int j = 0; j < H; ++j, row += W) { double y = j*cellHeight + 0.5d*cellHeight + minY; double x = 0.5d*cellWidth + minX; for (int i = 0; i < W; ++i, x += cellWidth) { diff -r 75306d856004 -r 4080b57dcb52 gnv-artifacts/src/main/java/de/intevation/gnv/raster/JTSMultiLineStringProducer.java --- a/gnv-artifacts/src/main/java/de/intevation/gnv/raster/JTSMultiLineStringProducer.java Tue Jan 19 17:55:08 2010 +0000 +++ b/gnv-artifacts/src/main/java/de/intevation/gnv/raster/JTSMultiLineStringProducer.java Tue Jan 19 21:23:28 2010 +0000 @@ -34,7 +34,8 @@ double maxX, double maxY ) { this( - JTSMultiPolygonProducer.createDefaultGeometryFactory(), + // XXX: Geotools crashes if only using a 2d packed data format! + JTSMultiPolygonProducer.createDefaultGeometryFactory(3), minX, minY, maxX, maxY); } diff -r 75306d856004 -r 4080b57dcb52 gnv-artifacts/src/main/java/de/intevation/gnv/raster/JTSMultiPolygonProducer.java --- a/gnv-artifacts/src/main/java/de/intevation/gnv/raster/JTSMultiPolygonProducer.java Tue Jan 19 17:55:08 2010 +0000 +++ b/gnv-artifacts/src/main/java/de/intevation/gnv/raster/JTSMultiPolygonProducer.java Tue Jan 19 21:23:28 2010 +0000 @@ -66,13 +66,17 @@ } public static GeometryFactory createDefaultGeometryFactory() { + return createDefaultGeometryFactory(2); + } + + public static GeometryFactory createDefaultGeometryFactory(int dim) { return new GeometryFactory( new PrecisionModel( PrecisionModel.FLOATING), SRID_WGS84, new PackedCoordinateSequenceFactory( PackedCoordinateSequenceFactory.DOUBLE, - 2)); + dim)); } public void handleRings( @@ -141,8 +145,6 @@ return; } - log.debug("polygon has a shell"); - Polygon polygon = geometryFactory.createPolygon( shell, holes.toArray(new LinearRing[holes.size()])); diff -r 75306d856004 -r 4080b57dcb52 gnv-artifacts/src/main/java/de/intevation/gnv/state/profile/horizontalcrosssection/HorizontalCrossSectionMeshOutputState.java --- a/gnv-artifacts/src/main/java/de/intevation/gnv/state/profile/horizontalcrosssection/HorizontalCrossSectionMeshOutputState.java Tue Jan 19 17:55:08 2010 +0000 +++ b/gnv-artifacts/src/main/java/de/intevation/gnv/state/profile/horizontalcrosssection/HorizontalCrossSectionMeshOutputState.java Tue Jan 19 21:23:28 2010 +0000 @@ -45,22 +45,21 @@ import de.intevation.gnv.state.exception.StateException; -import de.intevation.gnv.state.timeseries.TimeSeriesOutputState; - import de.intevation.gnv.utils.FileUtils; import de.intevation.gnv.utils.Pair; +import de.intevation.gnv.utils.ShapeFileWriter; import de.intevation.gnv.utils.StringUtils; import de.intevation.gnv.utils.WKTUtils; import java.awt.Dimension; import java.io.File; -import java.io.FileOutputStream; import java.io.IOException; import java.io.OutputStream; import java.util.ArrayList; import java.util.Collection; +import java.util.Date; import java.util.HashMap; import java.util.List; import java.util.Map; @@ -250,25 +249,66 @@ File shapeDir = new File(baseDir, uuid); - int count = 0; + boolean success = false; + boolean createdDir = false; - synchronized (shapeFileLock) { - while (shapeDir.exists()) { - shapeDir = new File(baseDir, uuid + "-" + count); - ++count; + try { + synchronized (shapeFileLock) { + int count = 0; + while (shapeDir.exists()) { + shapeDir = new File(baseDir, uuid + "-" + count); + ++count; + } + + if (!shapeDir.mkdirs()) { + log.error("cannot create directory '" + + shapeDir.getAbsolutePath() + "'"); + return null; + } + createdDir = true; } - if (!shapeDir.mkdirs()) { - log.error("cannot create directory '" - + shapeDir.getAbsolutePath() + "'"); + Map polygons = result.getPolygons(); + + List> isolines = + result.getLineStrings(); + + File polygonsFile = new File(shapeDir, "polygons.shp"); + File isolinesFile = new File(shapeDir, "isolines.shp"); + + if (!ShapeFileWriter.writeMultiPolygonsToFile( + polygonsFile, + (Integer)result.getAttribute("parameter"), + (Integer)result.getAttribute("layer"), + (Date) result.getAttribute("date"), + polygons) + ) { + log.error("writing polygons failed"); return null; } - shapeFilePath = shapeDir.getAbsolutePath(); + + if (!ShapeFileWriter.writeMultiLineStringsToFile( + isolinesFile, + (Integer)result.getAttribute("parameter"), + (Integer)result.getAttribute("layer"), + (Date) result.getAttribute("date"), + isolines) + ) { + log.error("writing isolines failed"); + return null; + } + + + success = true; + } + finally { + if (!success && createdDir) { + FileUtils.deleteRecursive(shapeDir); + + } } - // TODO: Do the writing - - return shapeFilePath; + return shapeFilePath = shapeDir.getAbsolutePath(); } protected AttributedPoint2ds getResult(String uuid, CallContext callContext) @@ -371,7 +411,6 @@ int iIdx = -1; int jIdx = -1; int vIdx = -1; - int kIdx = -1; boolean firstWarn = true; @@ -382,8 +421,8 @@ sIdx = rd.getColumnIndex("SHAPE"); iIdx = rd.getColumnIndex("IPOSITION"); jIdx = rd.getColumnIndex("JPOSITION"); - kIdx = rd.getColumnIndex("KPOSITION"); vIdx = rd.getColumnIndex("YORDINATE"); + int kIdx = rd.getColumnIndex("KPOSITION"); int tIdx = rd.getColumnIndex("TIMEVALUE"); int pIdx = rd.getColumnIndex("PARAMETERID"); @@ -398,6 +437,7 @@ ap2ds.setAttribute("date", result.getDate(tIdx)); ap2ds.setAttribute("parameter", result.getInteger(pIdx)); + ap2ds.setAttribute("layer", result.getInteger(kIdx)); } Coordinate coord = WKTUtils.toCoordinate(result.getString(sIdx)); if (coord == null) { diff -r 75306d856004 -r 4080b57dcb52 gnv-artifacts/src/main/java/de/intevation/gnv/state/timeseries/TimeSeriesOutputState.java --- a/gnv-artifacts/src/main/java/de/intevation/gnv/state/timeseries/TimeSeriesOutputState.java Tue Jan 19 17:55:08 2010 +0000 +++ b/gnv-artifacts/src/main/java/de/intevation/gnv/state/timeseries/TimeSeriesOutputState.java Tue Jan 19 21:23:28 2010 +0000 @@ -56,7 +56,6 @@ import de.intevation.gnv.utils.ArtifactXMLUtilities; import java.io.File; -import java.io.FileOutputStream; import java.io.IOException; import java.io.OutputStream; import java.io.UnsupportedEncodingException; diff -r 75306d856004 -r 4080b57dcb52 gnv-artifacts/src/main/java/de/intevation/gnv/utils/ShapeFileWriter.java --- a/gnv-artifacts/src/main/java/de/intevation/gnv/utils/ShapeFileWriter.java Tue Jan 19 17:55:08 2010 +0000 +++ b/gnv-artifacts/src/main/java/de/intevation/gnv/utils/ShapeFileWriter.java Tue Jan 19 21:23:28 2010 +0000 @@ -1,31 +1,40 @@ package de.intevation.gnv.utils; -import java.util.Map; -import java.util.List; -import java.util.HashMap; +import com.vividsolutions.jts.geom.MultiLineString; +import com.vividsolutions.jts.geom.MultiPolygon; import java.io.File; import java.io.IOException; +import java.io.Serializable; import java.net.MalformedURLException; -import com.vividsolutions.jts.geom.MultiPolygon; -import com.vividsolutions.jts.geom.MultiLineString; +import java.util.Date; +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.DataUtilities; -import org.geotools.data.Transaction; import org.geotools.data.DefaultTransaction; -import org.geotools.data.FeatureWriter; - -import org.geotools.feature.Feature; -import org.geotools.feature.FeatureType; -import org.geotools.feature.SchemaException; -import org.geotools.feature.IllegalAttributeException; +import org.geotools.data.FeatureStore; +import org.geotools.data.Transaction; import org.geotools.data.shapefile.ShapefileDataStore; import org.geotools.data.shapefile.ShapefileDataStoreFactory; -import org.apache.log4j.Logger; +import org.geotools.feature.FeatureCollection; +import org.geotools.feature.FeatureCollections; +import org.geotools.feature.SchemaException; + +import org.geotools.feature.simple.SimpleFeatureBuilder; + +import org.geotools.referencing.crs.DefaultGeographicCRS; + +import org.opengis.feature.simple.SimpleFeature; +import org.opengis.feature.simple.SimpleFeatureType; /** * @author Sascha L. Teichmann (sascha.teichmann@intevation.de) @@ -40,178 +49,245 @@ public static boolean writeMultiLineStringsToFile( File shapeFile, + Integer parameterId, + Integer layer, + Date date, List> multiLineStrings ) { - return writeMultiLineStringsToFile(shapeFile, multiLineStrings, null); + return writeMultiLineStringsToFile( + shapeFile, + parameterId, + layer, + date, + multiLineStrings, + "isolines"); } public static boolean writeMultiLineStringsToFile( File shapeFile, + Integer parameterId, + Integer layer, + Date date, List> multiLineStrings, - String typeName + String name ) { - HashMap params = new HashMap(); + Map params = new HashMap(); try { - params.put( - ShapefileDataStoreFactory.URLP.key, - shapeFile.toURI().toURL()); + params.put("url", shapeFile.toURI().toURL()); } catch (MalformedURLException mue) { log.error(mue.getLocalizedMessage(), mue); return false; } - boolean success = false; - Transaction tx = null; - - try { - ShapefileDataStoreFactory sfdsf = - new ShapefileDataStoreFactory(); - - ShapefileDataStore sfds = - (ShapefileDataStore)sfdsf.createNewDataStore(params); - - if (typeName == null) { - typeName = shapeFile.getName(); - } - - FeatureType featureType = DataUtilities.createType( - typeName, - "geom:MultiLineString,VALUE:Double"); + params.put("create spatial index", Boolean.TRUE); - sfds.createSchema(featureType); - - tx = new DefaultTransaction(); - - FeatureWriter featureWriter = sfds.getFeatureWriter( - typeName, tx); - for (Pair pair: multiLineStrings) { - log.debug("00000000000000000 -> " + pair.getA()); - Feature feature = featureWriter.next(); - feature.setAttribute("geom", pair.getB()); - feature.setAttribute("VALUE", asDouble(pair.getA())); - featureWriter.write(); - } + if (name == null) { + name = shapeFile.getName(); + } - tx.commit(); - success = true; - } - catch (IllegalAttributeException iae) { - log.error(iae.getLocalizedMessage(), iae); + SimpleFeatureType TYPE; + + try { + TYPE = DataUtilities.createType( + name, + "geom:MultiLineString:srid=4326," + + "PARAMETER:Integer," + + "LAYER:Integer," + + "DATE:Date," + + "VALUE:Double"); } catch (SchemaException se) { log.error(se.getLocalizedMessage(), se); + return false; } + + SimpleFeatureBuilder featureBuilder = + new SimpleFeatureBuilder(TYPE); + + FeatureCollection collection = + FeatureCollections.newCollection(); + + for (Pair pair: multiLineStrings) { + featureBuilder.add(pair.getB()); + featureBuilder.add(parameterId); + featureBuilder.add(layer); + featureBuilder.add(date); + featureBuilder.add(pair.getA()); + SimpleFeature feature = featureBuilder.buildFeature(null); + collection.add(feature); + } + + DataStoreFactorySpi dataStoreFactory = new ShapefileDataStoreFactory(); + + Transaction transaction = null; + + boolean success = false; + try { + ShapefileDataStore newDataStore = + (ShapefileDataStore)dataStoreFactory.createNewDataStore(params); + + newDataStore.createSchema(TYPE); + newDataStore.forceSchemaCRS(DefaultGeographicCRS.WGS84); + + transaction = new DefaultTransaction("create"); + + String typeName = newDataStore.getTypeNames()[0]; + + FeatureStore featureStore = + (FeatureStore) + newDataStore.getFeatureSource(typeName); + + featureStore.setTransaction(transaction); + + featureStore.addFeatures(collection); + transaction.commit(); + success = true; + } catch (IOException ioe) { log.error(ioe.getLocalizedMessage(), ioe); } finally { - if (!success && tx != null) { - try { tx.rollback(); } + if (transaction != null) { + if (!success) { + try { transaction.rollback(); } + catch (IOException ioe) {} + } + try { transaction.close(); } catch (IOException ioe) {} } } - if (tx != null) { - try { tx.close(); } - catch (IOException ioe) {} - } - return success; } public static boolean writeMultiPolygonsToFile( File shapeFile, + Integer parameterId, + Integer layer, + Date date, Map multiPolygons ) { - return writeMultiPolygonsToFile(shapeFile, multiPolygons, null); + return writeMultiPolygonsToFile( + shapeFile, + parameterId, + layer, + date, + multiPolygons, + "polygons"); } public static boolean writeMultiPolygonsToFile( File shapeFile, + Integer parameterId, + Integer layer, + Date date, Map multiPolygons, - String typeName + String name ) { - HashMap params = new HashMap(); + Map params = new HashMap(); try { - params.put( - ShapefileDataStoreFactory.URLP.key, - shapeFile.toURI().toURL()); + params.put("url", shapeFile.toURI().toURL()); } catch (MalformedURLException mue) { log.error(mue.getLocalizedMessage(), mue); return false; } - boolean success = false; - Transaction tx = null; - - try { - ShapefileDataStoreFactory sfdsf = - new ShapefileDataStoreFactory(); - - ShapefileDataStore sfds = - (ShapefileDataStore)sfdsf.createNewDataStore(params); - - if (typeName == null) { - typeName = shapeFile.getName(); - } - - FeatureType featureType = DataUtilities.createType( - typeName, - "geom:MultiPolygon,CLASS:Integer"); + params.put("create spatial index", Boolean.TRUE); - sfds.createSchema(featureType); - - tx = new DefaultTransaction(); - - FeatureWriter featureWriter = sfds.getFeatureWriter( - typeName, tx); - for (Map.Entry entry: - multiPolygons.entrySet() - ) { - Feature feature = featureWriter.next(); - feature.setAttribute("geom", entry.getValue()); - feature.setAttribute("CLASS", entry.getKey()); - featureWriter.write(); - } + if (name == null) { + name = shapeFile.getName(); + } - tx.commit(); - success = true; - } - catch (IllegalAttributeException iae) { - log.error(iae.getLocalizedMessage(), iae); + SimpleFeatureType TYPE; + + try { + TYPE = DataUtilities.createType( + name, + "geom:MultiPolygon:srid=4326," + + "PARAMETER:Integer," + + "LAYER:Integer," + + "DATE:Date," + + "CLASS:Integer"); } catch (SchemaException se) { log.error(se.getLocalizedMessage(), se); + return false; } + + SimpleFeatureBuilder featureBuilder = + new SimpleFeatureBuilder(TYPE); + + FeatureCollection collection = + FeatureCollections.newCollection(); + + for (Map.Entry entry: + multiPolygons.entrySet() + ) { + featureBuilder.add(entry.getValue()); + featureBuilder.add(parameterId); + featureBuilder.add(layer); + featureBuilder.add(date); + featureBuilder.add(entry.getKey()); + SimpleFeature feature = featureBuilder.buildFeature(null); + collection.add(feature); + } + + DataStoreFactorySpi dataStoreFactory = new ShapefileDataStoreFactory(); + + Transaction transaction = null; + + boolean success = false; + try { + ShapefileDataStore newDataStore = + (ShapefileDataStore)dataStoreFactory.createNewDataStore(params); + + newDataStore.createSchema(TYPE); + newDataStore.forceSchemaCRS(DefaultGeographicCRS.WGS84); + + transaction = new DefaultTransaction("create"); + + String typeName = newDataStore.getTypeNames()[0]; + + FeatureStore featureStore = + (FeatureStore) + newDataStore.getFeatureSource(typeName); + + featureStore.setTransaction(transaction); + + featureStore.addFeatures(collection); + transaction.commit(); + success = true; + } catch (IOException ioe) { log.error(ioe.getLocalizedMessage(), ioe); } finally { - if (!success && tx != null) { - try { tx.rollback(); } + if (transaction != null) { + if (!success) { + try { transaction.rollback(); } + catch (IOException ioe) {} + } + try { transaction.close(); } catch (IOException ioe) {} } } - if (tx != null) { - try { tx.close(); } - catch (IOException ioe) {} - } - return success; } private static final Double asDouble(Object a) { - if (a instanceof Double) + if (a instanceof Double) { return (Double)a; - if (a instanceof Number) + } + if (a instanceof Number) { return Double.valueOf(((Number)a).doubleValue()); + } return 0d; } } diff -r 75306d856004 -r 4080b57dcb52 gnv-artifacts/src/test/java/de/intevation/gnv/artifacts/GNVArtifactsTestCaseBase.java --- a/gnv-artifacts/src/test/java/de/intevation/gnv/artifacts/GNVArtifactsTestCaseBase.java Tue Jan 19 17:55:08 2010 +0000 +++ b/gnv-artifacts/src/test/java/de/intevation/gnv/artifacts/GNVArtifactsTestCaseBase.java Tue Jan 19 21:23:28 2010 +0000 @@ -9,7 +9,6 @@ import java.io.FileOutputStream; import java.io.IOException; -import javax.smartcardio.ATR; import javax.xml.parsers.DocumentBuilder; import javax.xml.parsers.DocumentBuilderFactory; import javax.xml.parsers.ParserConfigurationException;