/*
* GeoTools - The Open Source Java GIS Toolkit
* http://geotools.org
*
* (C) 2004-2008, Open Source Geospatial Foundation (OSGeo)
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation;
* version 2.1 of the License.
*
* This library 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
* Lesser General Public License for more details.
*/
package org.geotools.geometry.jts;
import com.vividsolutions.jts.geom.CoordinateSequence;
import com.vividsolutions.jts.geom.Geometry;
import com.vividsolutions.jts.geom.GeometryCollection;
import com.vividsolutions.jts.geom.GeometryFactory;
import com.vividsolutions.jts.geom.LineString;
import com.vividsolutions.jts.geom.LinearRing;
import com.vividsolutions.jts.geom.MultiLineString;
import com.vividsolutions.jts.geom.MultiPoint;
import com.vividsolutions.jts.geom.MultiPolygon;
import com.vividsolutions.jts.geom.Point;
import com.vividsolutions.jts.geom.Polygon;
import org.opengis.referencing.crs.CoordinateReferenceSystem;
import org.opengis.referencing.operation.MathTransform;
import org.opengis.referencing.operation.TransformException;
/**
* Service object that takes a geometry an applies a MathTransform on top
* of it.
* @author Andrea Aime
* @source $URL$
*/
public class GeometryCoordinateSequenceTransformer {
private MathTransform transform;
private CoordinateSequenceTransformer csTransformer;
private CoordinateReferenceSystem crs;
public GeometryCoordinateSequenceTransformer() {
csTransformer = new DefaultCoordinateSequenceTransformer();
}
public GeometryCoordinateSequenceTransformer(CoordinateSequenceTransformer transformer) {
csTransformer = transformer;
}
/**
* Sets the math transform to be used for transformation
* @param transform
*/
public void setMathTransform(MathTransform transform) {
this.transform = transform;
}
/**
* Sets the target coordinate reference system.
* <p>
* This value is used to set the coordinate reference system of geometries
* after they have been transformed.
* </p>
* @param crs The target coordinate reference system.
*/
public void setCoordinateReferenceSystem(CoordinateReferenceSystem crs) {
this.crs = crs;
}
/**
* Applies the transform to the provided geometry, given
* @param g
* @throws TransformException
*/
public Geometry transform(Geometry g) throws TransformException {
GeometryFactory factory = g.getFactory();
Geometry transformed = null;
if (g instanceof Point) {
transformed = transformPoint((Point) g, factory);
} else if (g instanceof MultiPoint) {
MultiPoint mp = (MultiPoint) g;
Point[] points = new Point[mp.getNumGeometries()];
for (int i = 0; i < points.length; i++) {
points[i] = transformPoint((Point) mp.getGeometryN(i), factory);
}
transformed = factory.createMultiPoint(points);
} else if (g instanceof LineString) {
transformed = transformLineString((LineString) g, factory);
} else if (g instanceof MultiLineString) {
MultiLineString mls = (MultiLineString) g;
LineString[] lines = new LineString[mls.getNumGeometries()];
for (int i = 0; i < lines.length; i++) {
lines[i] = transformLineString((LineString) mls.getGeometryN(i), factory);
}
transformed = factory.createMultiLineString(lines);
} else if (g instanceof Polygon) {
transformed = transformPolygon((Polygon) g, factory);
} else if (g instanceof MultiPolygon) {
MultiPolygon mp = (MultiPolygon) g;
Polygon[] polygons = new Polygon[mp.getNumGeometries()];
for (int i = 0; i < polygons.length; i++) {
polygons[i] = transformPolygon((Polygon) mp.getGeometryN(i), factory);
}
transformed = factory.createMultiPolygon(polygons);
} else if (g instanceof GeometryCollection) {
GeometryCollection gc = (GeometryCollection) g;
Geometry[] geoms = new Geometry[gc.getNumGeometries()];
for (int i = 0; i < geoms.length; i++) {
geoms[i] = transform(gc.getGeometryN(i));
}
transformed = factory.createGeometryCollection(geoms);
} else {
throw new IllegalArgumentException("Unsupported geometry type " + g.getClass());
}
//copy over user data, do a special check for coordinate reference
// systme
transformed.setUserData(g.getUserData());
if ((g.getUserData() == null) || g.getUserData() instanceof CoordinateReferenceSystem) {
//set the new one to be the target crs
if (crs != null) {
transformed.setUserData(crs);
}
}
return transformed;
}
/**
*
* @throws TransformException
*/
public LineString transformLineString(LineString ls, GeometryFactory gf)
throws TransformException {
CoordinateSequence cs = projectCoordinateSequence(ls.getCoordinateSequence());
LineString transformed = null;
if (ls instanceof LinearRing) {
transformed = gf.createLinearRing(cs);
} else {
transformed = gf.createLineString(cs);
}
transformed.setUserData( ls.getUserData() );
return transformed;
}
/**
* @param point
*
* @throws TransformException
*/
public Point transformPoint(Point point, GeometryFactory gf)
throws TransformException {
CoordinateSequence cs = projectCoordinateSequence(point.getCoordinateSequence());
Point transformed = gf.createPoint(cs);;
transformed.setUserData( point.getUserData() );
return transformed;
}
/**
* @param cs a CoordinateSequence
*
* @throws TransformException
*/
public CoordinateSequence projectCoordinateSequence(CoordinateSequence cs)
throws TransformException {
return csTransformer.transform(cs, transform);
}
/**
* @param polygon
* @throws TransformException
*/
public Polygon transformPolygon(Polygon polygon, GeometryFactory gf)
throws TransformException {
LinearRing exterior = (LinearRing) transformLineString(polygon.getExteriorRing(), gf);
LinearRing[] interiors = new LinearRing[polygon.getNumInteriorRing()];
for (int i = 0; i < interiors.length; i++) {
interiors[i] = (LinearRing) transformLineString(polygon.getInteriorRingN(i), gf);
}
Polygon transformed = gf.createPolygon(exterior, interiors);
transformed.setUserData( polygon.getUserData() );
return transformed;
}
}