]> git.argeo.org Git - gpl/argeo-suite.git/blob - org.argeo.app.core/src/org/argeo/app/geo/GeoUtils.java
Releasing
[gpl/argeo-suite.git] / org.argeo.app.core / src / org / argeo / app / geo / GeoUtils.java
1 package org.argeo.app.geo;
2
3 import java.io.IOException;
4 import java.io.Serializable;
5 import java.io.Writer;
6 import java.nio.file.Path;
7 import java.util.ArrayList;
8 import java.util.HashMap;
9 import java.util.List;
10 import java.util.Map;
11
12 import javax.measure.Quantity;
13 import javax.measure.quantity.Area;
14
15 import org.geotools.data.DefaultTransaction;
16 import org.geotools.data.Transaction;
17 import org.geotools.data.collection.ListFeatureCollection;
18 import org.geotools.data.shapefile.ShapefileDataStore;
19 import org.geotools.data.shapefile.ShapefileDataStoreFactory;
20 import org.geotools.data.simple.SimpleFeatureCollection;
21 import org.geotools.data.simple.SimpleFeatureIterator;
22 import org.geotools.data.simple.SimpleFeatureSource;
23 import org.geotools.data.simple.SimpleFeatureStore;
24 import org.geotools.geometry.jts.JTS;
25 import org.geotools.referencing.CRS;
26 import org.geotools.referencing.crs.DefaultGeographicCRS;
27 import org.locationtech.jts.geom.Coordinate;
28 import org.locationtech.jts.geom.Point;
29 import org.locationtech.jts.geom.Polygon;
30 import org.opengis.feature.simple.SimpleFeature;
31 import org.opengis.feature.simple.SimpleFeatureType;
32 import org.opengis.geometry.MismatchedDimensionException;
33 import org.opengis.referencing.FactoryException;
34 import org.opengis.referencing.crs.CoordinateReferenceSystem;
35 import org.opengis.referencing.operation.MathTransform;
36 import org.opengis.referencing.operation.TransformException;
37
38 import si.uom.SI;
39 import tech.units.indriya.quantity.Quantities;
40
41 /** Utilities around geographical format, mostly wrapping GeoTools patterns. */
42 public class GeoUtils {
43
44 /** In square meters. */
45 public static Quantity<Area> calcArea(SimpleFeature feature) {
46 try {
47 Polygon p = (Polygon) feature.getDefaultGeometry();
48 Point centroid = p.getCentroid();
49 String code = "AUTO:42001," + centroid.getX() + "," + centroid.getY();
50 CoordinateReferenceSystem auto = CRS.decode(code);
51
52 MathTransform transform = CRS.findMathTransform(DefaultGeographicCRS.WGS84, auto);
53
54 Polygon projed = (Polygon) JTS.transform(p, transform);
55 return Quantities.getQuantity(projed.getArea(), SI.SQUARE_METRE);
56 } catch (MismatchedDimensionException | FactoryException | TransformException e) {
57 throw new IllegalStateException("Cannot claculate area of feature");
58 }
59 }
60
61 public static void exportToSvg(SimpleFeatureCollection features, Writer out, int width, int height) {
62 try {
63 double minY = Double.POSITIVE_INFINITY;
64 double maxY = Double.NEGATIVE_INFINITY;
65 double minX = Double.POSITIVE_INFINITY;
66 double maxX = Double.NEGATIVE_INFINITY;
67 List<String> shapes = new ArrayList<>();
68 for (SimpleFeatureIterator it = features.features(); it.hasNext();) {
69 SimpleFeature feature = it.next();
70 StringBuffer sb = new StringBuffer();
71 sb.append("<polyline style=\"stroke-width:1;stroke:#000000;fill:none;\" points=\"");
72
73 Polygon p = (Polygon) feature.getDefaultGeometry();
74 Point centroid = p.getCentroid();
75 String code = "AUTO:42001," + centroid.getX() + "," + centroid.getY();
76 CoordinateReferenceSystem auto = CRS.decode(code);
77
78 MathTransform transform = CRS.findMathTransform(DefaultGeographicCRS.WGS84, auto);
79
80 Polygon projed = (Polygon) JTS.transform(p, transform);
81
82 for (Coordinate coord : projed.getCoordinates()) {
83 double x = coord.x;
84 if (x < minX)
85 minX = x;
86 if (x > maxX)
87 maxX = x;
88 double y = -coord.y;
89 if (y < minY)
90 minY = y;
91 if (y > maxY)
92 maxY = y;
93 sb.append(x + "," + y + " ");
94 }
95 sb.append("\">");
96 sb.append("</polyline>\n");
97 shapes.add(sb.toString());
98
99 }
100 double viewportHeight = maxY - minY;
101 double viewportWidth = maxX - minX;
102 out.write("<svg xmlns=\"http://www.w3.org/2000/svg\"\n");
103 out.write(" width=\"" + width + "\"\n");
104 out.write(" height=\"" + height + "\"\n");
105 out.write(" viewBox=\"" + minX + " " + minY + " " + viewportWidth + " " + viewportHeight + "\"\n");
106 out.write(" preserveAspectRatio=\"xMidYMid meet\"\n");
107 out.write(">\n");
108 for (String shape : shapes) {
109 out.write(shape);
110 out.write("\n");
111 }
112 out.write("</svg>");
113 } catch (IOException | FactoryException | MismatchedDimensionException | TransformException e) {
114 throw new RuntimeException("Cannot export to SVG", e);
115 }
116 }
117
118 /** Write a list of simple features to a shapefile. */
119 public static void saveFeaturesAsShapefile(SimpleFeatureType featureType, List<SimpleFeature> features,
120 Path shpFile) {
121 try {
122 ShapefileDataStoreFactory dataStoreFactory = new ShapefileDataStoreFactory();
123
124 Map<String, Serializable> params = new HashMap<>();
125 params.put("url", shpFile.toUri().toURL());
126
127 params.put("create spatial index", Boolean.TRUE);
128
129 ShapefileDataStore newDataStore = (ShapefileDataStore) dataStoreFactory.createNewDataStore(params);
130 newDataStore.createSchema(featureType);
131
132 String typeName = newDataStore.getTypeNames()[0];
133 SimpleFeatureSource featureSource = newDataStore.getFeatureSource(typeName);
134 if (featureSource instanceof SimpleFeatureStore) {
135 SimpleFeatureStore featureStore = (SimpleFeatureStore) featureSource;
136 SimpleFeatureCollection collection = new ListFeatureCollection(featureType, features);
137
138 try (Transaction transaction = new DefaultTransaction("create")) {
139 try {
140 featureStore.setTransaction(transaction);
141 featureStore.addFeatures(collection);
142 transaction.commit();
143 } catch (Exception problem) {
144 transaction.rollback();
145 throw new RuntimeException("Cannot write shapefile " + shpFile, problem);
146 }
147 }
148 } else {
149 throw new IllegalArgumentException(typeName + " does not support read/write access");
150 }
151 } catch (IOException e) {
152 throw new RuntimeException("Cannot write shapefile " + shpFile, e);
153 }
154 }
155
156 /** Singleton. */
157 private GeoUtils() {
158 }
159 }