package org.ianturton.cookbook.projections; import java.io.File; import java.io.IOException; import java.net.MalformedURLException; import java.util.ArrayList; import java.util.List; import org.geotools.data.DefaultTransaction; import org.geotools.data.FeatureStore; import org.geotools.data.FileDataStore; import org.geotools.data.Transaction; import org.geotools.data.collection.ListFeatureCollection; import org.geotools.data.shapefile.ShapefileDataStoreFactory; import org.geotools.data.simple.SimpleFeatureCollection; import org.geotools.data.simple.SimpleFeatureIterator; import org.geotools.data.simple.SimpleFeatureSource; import org.geotools.feature.NameImpl; import org.geotools.feature.simple.SimpleFeatureBuilder; import org.geotools.feature.simple.SimpleFeatureTypeImpl; import org.geotools.feature.type.GeometryDescriptorImpl; import org.geotools.feature.type.GeometryTypeImpl; import org.geotools.geometry.jts.JTS; import org.geotools.referencing.CRS; import org.opengis.feature.simple.SimpleFeature; import org.opengis.feature.simple.SimpleFeatureType; import org.opengis.feature.type.AttributeDescriptor; import org.opengis.feature.type.AttributeType; import org.opengis.feature.type.GeometryDescriptor; import org.opengis.feature.type.GeometryType; import org.opengis.referencing.FactoryException; import org.opengis.referencing.NoSuchAuthorityCodeException; import org.opengis.referencing.crs.CoordinateReferenceSystem; import org.opengis.referencing.operation.MathTransform; import com.vividsolutions.jts.geom.Geometry; public class ReprojectShapeFile { public static void main(String[] args) throws MalformedURLException, IOException, NoSuchAuthorityCodeException, FactoryException { if (args.length < 3) { System.err.println("Usage: ReprojectShapeFile in.shp out.shp epsg:code"); System.exit(3); } File in = new File(args[0]); File out = new File(args[1]); CoordinateReferenceSystem crs = CRS.decode(args[2]); ShapefileDataStoreFactory fac = new ShapefileDataStoreFactory(); FileDataStore inStore = fac.createDataStore(in.toURI().toURL()); FileDataStore outStore = fac.createDataStore(out.toURI().toURL()); SimpleFeatureCollection inFeatures = inStore.getFeatureSource() .getFeatures(); ReprojectShapeFile reprojector = new ReprojectShapeFile(); SimpleFeatureCollection outFeatures = reprojector .reproject(inFeatures, crs); outStore.createSchema(outFeatures.getSchema()); Transaction transaction = new DefaultTransaction("create"); String outName = outStore.getNames().get(0).getLocalPart(); SimpleFeatureSource featureSource = outStore.getFeatureSource(outName); FeatureStore featureStore = (FeatureStore) featureSource; featureStore.setTransaction(transaction); featureStore.addFeatures(outFeatures); transaction.commit(); outStore.dispose(); } public SimpleFeatureCollection reproject(SimpleFeatureCollection features, CoordinateReferenceSystem target) throws FactoryException { SimpleFeatureCollection projFeatures = null; CoordinateReferenceSystem source = features.getSchema() .getCoordinateReferenceSystem(); SimpleFeatureType outSchema = rewriteSchema(features.getSchema(), target); boolean lenient = true; // allow for some error due to different datums MathTransform transform = CRS.findMathTransform(source, target, lenient); SimpleFeatureIterator iterator = features.features(); List<SimpleFeature> feats = new ArrayList<SimpleFeature>(); SimpleFeatureBuilder builder = new SimpleFeatureBuilder(outSchema); try { while (iterator.hasNext()) { // copy the contents of each feature and transform the geometry SimpleFeature feature = iterator.next(); SimpleFeature copy = builder.buildFeature(null, feature.getAttributes() .toArray()); Geometry geometry = (Geometry) feature.getDefaultGeometry(); Geometry geometry2 = JTS.transform(geometry, transform); copy.setDefaultGeometry(geometry2); feats.add(copy); } } catch (Exception problem) { problem.printStackTrace(); return null; } finally { iterator.close(); } System.err.println("got " + feats.size() + " output"); projFeatures = new ListFeatureCollection(outSchema, feats); return projFeatures; } /** * copy the schema provided and change the geometry descriptor to reflect the * new CRS. * * @param schema * @return */ private SimpleFeatureType rewriteSchema(SimpleFeatureType schema, CoordinateReferenceSystem crs) { GeometryDescriptor geom = schema.getGeometryDescriptor(); List<AttributeDescriptor> attributes = schema.getAttributeDescriptors(); GeometryType geomType = null; List<AttributeDescriptor> attribs = new ArrayList<AttributeDescriptor>(); for (AttributeDescriptor attrib : attributes) { AttributeType type = attrib.getType(); if (type instanceof GeometryType) { geomType = (GeometryType) type; } else { attribs.add(attrib); } } GeometryTypeImpl gt = new GeometryTypeImpl(new NameImpl("the_geom"), geomType.getBinding(), crs, geomType.isIdentified(), geomType.isAbstract(), geomType.getRestrictions(), geomType.getSuper(), geomType.getDescription()); GeometryDescriptor geomDesc = new GeometryDescriptorImpl(gt, new NameImpl( "the_geom"), geom.getMinOccurs(), geom.getMaxOccurs(), geom.isNillable(), geom.getDefaultValue()); attribs.add(0, geomDesc); SimpleFeatureType shpType = new SimpleFeatureTypeImpl(schema.getName(), attribs, geomDesc, schema.isAbstract(), schema.getRestrictions(), schema.getSuper(), schema.getDescription()); return shpType; } }