001: /*
002: * GeoTools - OpenSource mapping toolkit
003: * http://geotools.org
004: * (C) 2003-2006, GeoTools Project Managment Committee (PMC)
005: *
006: * This library is free software; you can redistribute it and/or
007: * modify it under the terms of the GNU Lesser General Public
008: * License as published by the Free Software Foundation;
009: * version 2.1 of the License.
010: *
011: * This library is distributed in the hope that it will be useful,
012: * but WITHOUT ANY WARRANTY; without even the implied warranty of
013: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
014: * Lesser General Public License for more details.
015: */
016: package org.geotools.data.crs;
017:
018: import java.io.IOException;
019: import java.util.Iterator;
020: import java.util.NoSuchElementException;
021:
022: import org.geotools.feature.Feature;
023: import org.geotools.feature.FeatureCollection;
024: import org.geotools.feature.FeatureIterator;
025: import org.geotools.feature.FeatureType;
026: import org.geotools.feature.FeatureTypes;
027: import org.geotools.feature.SchemaException;
028: import org.geotools.feature.collection.AbstractFeatureCollection;
029: import org.geotools.geometry.jts.ReferencedEnvelope;
030: import org.geotools.referencing.CRS;
031: import org.opengis.referencing.FactoryException;
032: import org.opengis.referencing.crs.CoordinateReferenceSystem;
033: import org.opengis.referencing.operation.MathTransform;
034: import org.opengis.referencing.operation.OperationNotFoundException;
035: import org.opengis.referencing.operation.TransformException;
036:
037: import com.vividsolutions.jts.geom.Envelope;
038: import com.vividsolutions.jts.geom.Geometry;
039:
040: /**
041: * ReprojectFeatureReader provides a reprojection for FeatureTypes.
042: *
043: * <p>
044: * ReprojectFeatureResults is a wrapper used to reproject GeometryAttributes
045: * to a user supplied CoordinateReferenceSystem from the original
046: * CoordinateReferenceSystem supplied by the original FeatureResults.
047: * </p>
048: *
049: * <p>
050: * Example Use:
051: * <pre><code>
052: * ReprojectFeatureResults results =
053: * new ReprojectFeatureResults( originalResults, reprojectCS );
054: *
055: * CoordinateReferenceSystem originalCS =
056: * originalResults.getFeatureType().getDefaultGeometry().getCoordinateSystem();
057: *
058: * CoordinateReferenceSystem newCS =
059: * results.getFeatureType().getDefaultGeometry().getCoordinateSystem();
060: *
061: * assertEquals( reprojectCS, newCS );
062: * </code></pre>
063: * </p>
064: *
065: * @author aaime
066: * @author $Author: jive $ (last modification)
067: * @source $URL: http://svn.geotools.org/geotools/tags/2.4.1/modules/library/main/src/main/java/org/geotools/data/crs/ReprojectFeatureResults.java $
068: * @version $Id: ReprojectFeatureResults.java 28366 2007-12-14 11:46:16Z aaime $ TODO: handle the case where there is more than one geometry and the other geometries have a different CS than the default geometry
069: */
070: public class ReprojectFeatureResults extends AbstractFeatureCollection {
071: FeatureCollection results;
072: MathTransform transform;
073:
074: /**
075: * Creates a new reprojecting feature results
076: *
077: * @param results
078: * @param destinationCS
079: *
080: * @throws IOException
081: * @throws SchemaException
082: * @throws TransformException
083: * @throws FactoryException
084: * @throws NoSuchElementException
085: * @throws OperationNotFoundException
086: * @throws CannotCreateTransformException
087: * @throws NullPointerException DOCUMENT ME!
088: * @throws IllegalArgumentException
089: */
090: public ReprojectFeatureResults(FeatureCollection results,
091: CoordinateReferenceSystem destinationCS)
092: throws IOException, SchemaException, TransformException,
093: OperationNotFoundException, NoSuchElementException,
094: FactoryException {
095:
096: super (forceType(origionalType(results), destinationCS));
097:
098: this .results = origionalCollection(results);
099:
100: CoordinateReferenceSystem originalCs = null;
101: if (results instanceof ForceCoordinateSystemFeatureResults)
102: originalCs = results.getSchema().getDefaultGeometry()
103: .getCoordinateSystem();
104: else
105: originalCs = this .results.getSchema().getDefaultGeometry()
106: .getCoordinateSystem();
107: this .transform = CRS.findMathTransform(originalCs,
108: destinationCS, true);
109: }
110:
111: private static FeatureCollection origionalCollection(
112: FeatureCollection results) {
113: while (true) {
114: if (results instanceof ReprojectFeatureResults) {
115: results = ((ReprojectFeatureResults) results)
116: .getOrigin();
117: }
118: if (results instanceof ForceCoordinateSystemFeatureResults) {
119: results = ((ForceCoordinateSystemFeatureResults) results)
120: .getOrigin();
121: }
122: break;
123: }
124: return results;
125: }
126:
127: private static FeatureType origionalType(FeatureCollection results) {
128: while (true) {
129: if (results instanceof ReprojectFeatureResults) {
130: results = ((ReprojectFeatureResults) results)
131: .getOrigin();
132: }
133: if (results instanceof ForceCoordinateSystemFeatureResults) {
134: results = ((ForceCoordinateSystemFeatureResults) results)
135: .getOrigin();
136: }
137: break;
138: }
139: return results.getSchema();
140: }
141:
142: private static FeatureType forceType(FeatureType startingType,
143: CoordinateReferenceSystem forcedCS) throws SchemaException {
144: if (forcedCS == null) {
145: throw new NullPointerException("CoordinateSystem required");
146: }
147: CoordinateReferenceSystem originalCs = startingType
148: .getDefaultGeometry().getCoordinateSystem();
149:
150: if (forcedCS.equals(originalCs)) {
151: return startingType;
152: } else {
153: return FeatureTypes.transform(startingType, forcedCS);
154: }
155: }
156:
157: protected Iterator openIterator() {
158: return new ReprojectFeatureIterator(results.features(),
159: getSchema(), this .transform);
160: }
161:
162: protected void closeIterator(Iterator close) {
163: if (close == null)
164: return;
165: if (close instanceof ReprojectFeatureIterator) {
166: ReprojectFeatureIterator iterator = (ReprojectFeatureIterator) close;
167: iterator.close();
168: }
169: }
170:
171: /**
172: * This method computes reprojected bounds the hard way, but computing them
173: * feature by feature. This method could be faster if computed the
174: * reprojected bounds by reprojecting the original feature bounds a Shape
175: * object, thus getting the true shape of the reprojected envelope, and
176: * then computing the minumum and maximum coordinates of that new shape.
177: * The result would not a true representation of the new bounds, but it
178: * would be guaranteed to be larger that the true representation.
179: *
180: * @see org.geotools.data.FeatureResults#getBounds()
181: */
182: public ReferencedEnvelope getBounds() {
183: FeatureIterator r = features();
184: try {
185: Envelope newBBox = new Envelope();
186: Envelope internal;
187: Feature feature;
188:
189: while (r.hasNext()) {
190: feature = r.next();
191: final Geometry geometry = feature.getDefaultGeometry();
192: if (geometry != null) {
193: internal = geometry.getEnvelopeInternal();
194: newBBox.expandToInclude(internal);
195: }
196: }
197: return ReferencedEnvelope.reference(newBBox);
198: } catch (Exception e) {
199: throw new RuntimeException(
200: "Exception occurred while computing reprojected bounds",
201: e);
202: } finally {
203: r.close();
204: }
205: }
206:
207: /**
208: * @see org.geotools.data.FeatureResults#getCount()
209: */
210: public int size() {
211: return results.size();
212: }
213:
214: /**
215: * @see org.geotools.data.FeatureResults#collection()
216: *
217: public FeatureCollection collection() throws IOException {
218: FeatureCollection collection = FeatureCollections.newCollection();
219:
220: try {
221: FeatureReader reader = reader();
222:
223: while (reader.hasNext()) {
224: collection.add(reader.next());
225: }
226: } catch (NoSuchElementException e) {
227: throw new DataSourceException("This should not happen", e);
228: } catch (IllegalAttributeException e) {
229: throw new DataSourceException("This should not happen", e);
230: }
231:
232: return collection;
233: }*/
234:
235: /**
236: * Returns the feature results wrapped by this reprojecting feature results
237: *
238: */
239: public FeatureCollection getOrigin() {
240: return results;
241: }
242: }
|