comparison 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
comparison
equal deleted inserted replaced
2987:98c7a46ec5ae 3318:dbe2f85bf160
1 package de.intevation.flys.utils;
2
3 import com.vividsolutions.jts.geom.Coordinate;
4 import com.vividsolutions.jts.geom.Envelope;
5 import com.vividsolutions.jts.geom.Geometry;
6
7 import de.intevation.flys.model.RiverAxis;
8
9 import java.io.File;
10 import java.io.IOException;
11 import java.io.Serializable;
12 import java.net.MalformedURLException;
13 import java.util.ArrayList;
14 import java.util.HashMap;
15 import java.util.List;
16 import java.util.Map;
17
18 import org.apache.log4j.Logger;
19 import org.geotools.data.DataStoreFactorySpi;
20 import org.geotools.data.DefaultTransaction;
21 import org.geotools.data.FeatureWriter;
22 import org.geotools.data.Transaction;
23 import org.geotools.data.shapefile.ShapefileDataStore;
24 import org.geotools.data.shapefile.ShapefileDataStoreFactory;
25 import org.geotools.data.simple.SimpleFeatureIterator;
26 import org.geotools.feature.FeatureCollection;
27 import org.geotools.feature.FeatureIterator;
28 import org.geotools.feature.simple.SimpleFeatureTypeBuilder;
29 import org.geotools.geojson.feature.FeatureJSON;
30 import org.geotools.geometry.jts.JTS;
31 import org.geotools.geometry.jts.ReferencedEnvelope;
32 import org.geotools.referencing.CRS;
33 import org.opengis.feature.simple.SimpleFeature;
34 import org.opengis.feature.simple.SimpleFeatureType;
35 import org.opengis.referencing.FactoryException;
36 import org.opengis.referencing.NoSuchAuthorityCodeException;
37 import org.opengis.referencing.crs.CoordinateReferenceSystem;
38 import org.opengis.referencing.operation.MathTransform;
39 import org.opengis.referencing.operation.TransformException;
40
41 public class GeometryUtils {
42
43 private static final Logger logger = Logger.getLogger(GeometryUtils.class);
44
45 public static final String PREFIX_EPSG = "EPSG:";
46
47 public static final String DEFAULT_EPSG = "EPSG:31467";
48
49 private GeometryUtils() {
50 }
51
52 public static Envelope getRiverBoundary(String rivername) {
53 List<RiverAxis> axes = RiverAxis.getRiverAxis(rivername);
54 if (axes != null && axes.size() > 0) {
55 Envelope max = null;
56
57 for (RiverAxis axis: axes) {
58 // TODO Take the correct EPSG into account. Maybe, we need to
59 // reproject the geometry.
60 Envelope env = axis.getGeom().getEnvelopeInternal();
61
62 if (max == null) {
63 max = env;
64 }
65 else {
66 max.expandToInclude(env);
67 }
68 }
69
70 return max;
71 }
72
73 return null;
74 }
75
76 public static String getRiverBounds(String rivername) {
77 Envelope env = getRiverBoundary(rivername);
78
79 if (env != null) {
80 return jtsBoundsToOLBounds(env);
81 }
82
83 return null;
84 }
85
86 /**
87 * Returns the boundary of Envelope <i>env</i> in OpenLayers representation.
88 *
89 * @param env The envelope of a geometry.
90 *
91 * @return the OpenLayers boundary of <i>env</i>.
92 */
93 public static String jtsBoundsToOLBounds(Envelope env) {
94 StringBuilder buf = new StringBuilder();
95 buf.append(env.getMinX()); buf.append(' ');
96 buf.append(env.getMinY()); buf.append(' ');
97 buf.append(env.getMaxX()); buf.append(' ');
98 buf.append(env.getMaxY());
99 return buf.toString();
100 }
101
102 public static String createOLBounds(Geometry a, Geometry b) {
103 Coordinate[] ca = a.getCoordinates();
104 Coordinate[] cb = b.getCoordinates();
105
106 double lowerX = Double.MAX_VALUE;
107 double lowerY = Double.MAX_VALUE;
108 double upperX = -Double.MAX_VALUE;
109 double upperY = -Double.MAX_VALUE;
110
111 for (Coordinate c: ca) {
112 lowerX = lowerX < c.x ? lowerX : c.x;
113 lowerY = lowerY < c.y ? lowerY : c.y;
114
115 upperX = upperX > c.x ? upperX : c.x;
116 upperY = upperY > c.y ? upperY : c.y;
117 }
118
119 for (Coordinate c: cb) {
120 lowerX = lowerX < c.x ? lowerX : c.x;
121 lowerY = lowerY < c.y ? lowerY : c.y;
122
123 upperX = upperX > c.x ? upperX : c.x;
124 upperY = upperY > c.y ? upperY : c.y;
125 }
126
127 return "" + lowerX + " " + lowerY + " " + upperX + " " + upperY;
128 }
129
130 public static SimpleFeatureType buildFeatureType(
131 String name, String srs, Class<?> geometryType)
132 {
133 return buildFeatureType(name, srs, geometryType, null);
134 }
135
136 /**
137 * Creates a new SimpleFeatureType using a SimpleFeatureTypeBuilder.
138 *
139 * @param name The name of the FeatureType.
140 * @param srs The SRS (e.g. "EPSG:31466").
141 * @param geometryType The geometry type's class (e.g. Polygon.class).
142 * @param attrs Optional. An object with attribute-name/attribute-class pairs
143 * where index 0 specifies the name as string and index 1 the
144 * ype as class.
145 *
146 * @return a new SimpleFeatureType.
147 */
148 public static SimpleFeatureType buildFeatureType(String name, String srs,
149 Class<?> geometryType, Object[][] attrs) {
150 try {
151 SimpleFeatureTypeBuilder builder = new SimpleFeatureTypeBuilder();
152 CoordinateReferenceSystem crs = CRS.decode(srs);
153
154 builder.setName("flys");
155 builder.setNamespaceURI("http://www.intevation.de/");
156 builder.setCRS(crs);
157 builder.setSRS(srs);
158
159 builder.add("geometry", geometryType, crs);
160
161 if (attrs != null) {
162 for (Object[] attr: attrs) {
163 builder.add((String) attr[0], (Class<?>) attr[1]);
164 }
165 }
166
167 return builder.buildFeatureType();
168 }
169 catch (NoSuchAuthorityCodeException nsae) {
170 }
171 catch (FactoryException fe) {
172 }
173
174 return null;
175 }
176
177 public static List<SimpleFeature> parseGeoJSON(
178 String geojson, SimpleFeatureType ft
179 ) {
180 List<SimpleFeature> collection = new ArrayList<SimpleFeature>();
181
182 try {
183 FeatureJSON fjson = new FeatureJSON();
184 fjson.setFeatureType(ft);
185
186 FeatureIterator<SimpleFeature> iterator =
187 fjson.streamFeatureCollection(geojson);
188
189 while (iterator.hasNext()) {
190 collection.add(iterator.next());
191 }
192 }
193 catch (IOException ioe) {
194 // TODO handle exception
195 }
196
197 return collection;
198 }
199
200
201 /**
202 * This method returns the {@link CoordinateReferenceSystem} by the
203 * {@link String} <i>epsg</i>.
204 *
205 * @param epsg An EPSG code like <b>EPSG:31466</b>
206 *
207 * @return the {@link CoordinateReferenceSystem} specified by <i>epsg</i>.
208 */
209 public static CoordinateReferenceSystem getCoordinateReferenceSystem(
210 String epsg
211 ) {
212 if (epsg == null) {
213 logger.warn("cannot create CoordinateReferenceSystem with null");
214 return null;
215 }
216
217 if (!epsg.startsWith(PREFIX_EPSG)) {
218 epsg = PREFIX_EPSG + epsg;
219 }
220
221 try {
222 return CRS.decode(epsg);
223 }
224 catch (FactoryException fe) {
225 logger.error(
226 "unable to get CoordinateReferenceSystem for: " + epsg,
227 fe);
228 }
229
230 return null;
231 }
232
233
234 public static Envelope transform(Envelope orig, String targetSrs) {
235 return transform(orig, targetSrs, DEFAULT_EPSG);
236 }
237
238
239 public static Envelope transform(
240 Envelope orig,
241 String targetSrs,
242 String origSrs
243 ) {
244 if (targetSrs == null || orig == null || origSrs == null) {
245 logger.warn("unable to transform envelope: empty parameters");
246 return orig;
247 }
248
249 logger.debug("Transform envlope to '" + targetSrs + "'");
250 try {
251 CoordinateReferenceSystem sourceCRS =
252 getCoordinateReferenceSystem(origSrs);
253
254 CoordinateReferenceSystem targetCRS =
255 getCoordinateReferenceSystem(targetSrs);
256
257 if (sourceCRS != null && targetCRS != null) {
258 ReferencedEnvelope tmpEnv =
259 new ReferencedEnvelope(orig, CRS.decode(origSrs));
260
261 Envelope target = tmpEnv.transform(targetCRS, false);
262
263 if (logger.isDebugEnabled()) {
264 logger.debug(" orig envelope : " + orig);
265 logger.debug(" transformed envelope: " + target);
266 }
267
268 return target;
269 }
270 }
271 catch (NoSuchAuthorityCodeException nsae) {
272 logger.error("Cannot get CoordinateReferenceSystem!", nsae);
273 }
274 catch (FactoryException fe) {
275 logger.error("Cannot get CoordinateReferenceSystem!", fe);
276 }
277 catch (TransformException te) {
278 logger.error("Cannot transform envelope from source "
279 + origSrs + " to target srs " + targetSrs);
280 }
281
282 return null;
283 }
284
285
286 public static boolean writeShapefile(File shape,
287 SimpleFeatureType featureType, FeatureCollection<?, ?> collection) {
288 return writeShapefile(shape, featureType, collection,
289 featureType.getCoordinateReferenceSystem());
290 }
291
292
293 public static boolean writeShapefile(File shape,
294 SimpleFeatureType featureType, FeatureCollection<?, ?> collection,
295 CoordinateReferenceSystem crs) {
296 if (collection.isEmpty()) {
297 logger.warn("Shapefile is not written - no features given!");
298 return false;
299 }
300
301 Transaction transaction = null;
302
303 try {
304 MathTransform transform = CRS.findMathTransform(
305 CRS.decode(DEFAULT_EPSG), crs);
306
307 Map<String, Serializable> params =
308 new HashMap<String, Serializable>();
309
310 params.put("url", shape.toURI().toURL());
311 params.put("create spatial index", Boolean.TRUE);
312
313 DataStoreFactorySpi dataStoreFactory =
314 new ShapefileDataStoreFactory();
315
316 ShapefileDataStore newDataStore =
317 (ShapefileDataStore)dataStoreFactory.createNewDataStore(params);
318 newDataStore.createSchema(featureType);
319
320 transaction = new DefaultTransaction("create");
321
322 String typeName = newDataStore.getTypeNames()[0];
323
324 FeatureWriter<SimpleFeatureType, SimpleFeature> writer =
325 newDataStore.getFeatureWriter(typeName, transaction);
326
327 SimpleFeatureIterator iterator = (SimpleFeatureIterator) collection.features();
328
329 while (iterator.hasNext()){
330 SimpleFeature feature = iterator.next();
331 SimpleFeature copy = writer.next();
332
333 copy.setAttributes(feature.getAttributes());
334
335 Geometry orig = (Geometry) feature.getDefaultGeometry();
336 Geometry reprojected = JTS.transform(orig, transform);
337
338 copy.setDefaultGeometry(reprojected);
339 writer.write();
340 }
341
342 transaction.commit();
343
344 return true;
345 }
346 catch (MalformedURLException mue) {
347 logger.error("Unable to prepare shapefile: " + mue.getMessage());
348 }
349 catch (IOException ioe) {
350 logger.error("Unable to write shapefile: " + ioe.getMessage());
351 }
352 catch (NoSuchAuthorityCodeException nsae) {
353 logger.error("Cannot get CoordinateReferenceSystem for '"
354 + DEFAULT_EPSG + "'");
355 }
356 catch (FactoryException fe) {
357 logger.error("Cannot get CoordinateReferenceSystem for '"
358 + DEFAULT_EPSG + "'");
359 }
360 catch (TransformException te) {
361 logger.error("Was not able to transform geometry!", te);
362 }
363 finally {
364 if (transaction != null) {
365 try {
366 transaction.close();
367 }
368 catch (IOException ioe) { /* do nothing */ }
369 }
370 }
371
372 return false;
373 }
374 }
375 // vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 :

http://dive4elements.wald.intevation.org