1 package org
.argeo
.app
.geo
;
3 import java
.io
.IOException
;
4 import java
.io
.Serializable
;
6 import java
.nio
.file
.Path
;
7 import java
.util
.ArrayList
;
8 import java
.util
.HashMap
;
12 import javax
.measure
.Quantity
;
13 import javax
.measure
.quantity
.Area
;
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
;
39 import tech
.units
.indriya
.quantity
.Quantities
;
41 /** Utilities around geographical format, mostly wrapping GeoTools patterns. */
42 public class GeoUtils
{
44 /** In square meters. */
45 public static Quantity
<Area
> calcArea(SimpleFeature feature
) {
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
);
52 MathTransform transform
= CRS
.findMathTransform(DefaultGeographicCRS
.WGS84
, auto
);
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");
61 public static void exportToSvg(SimpleFeatureCollection features
, Writer out
, int width
, int height
) {
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=\"");
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
);
78 MathTransform transform
= CRS
.findMathTransform(DefaultGeographicCRS
.WGS84
, auto
);
80 Polygon projed
= (Polygon
) JTS
.transform(p
, transform
);
82 for (Coordinate coord
: projed
.getCoordinates()) {
93 sb
.append(x
+ "," + y
+ " ");
96 sb
.append("</polyline>\n");
97 shapes
.add(sb
.toString());
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");
108 for (String shape
: shapes
) {
113 } catch (IOException
| FactoryException
| MismatchedDimensionException
| TransformException e
) {
114 throw new RuntimeException("Cannot export to SVG", e
);
118 /** Write a list of simple features to a shapefile. */
119 public static void saveFeaturesAsShapefile(SimpleFeatureType featureType
, List
<SimpleFeature
> features
,
122 ShapefileDataStoreFactory dataStoreFactory
= new ShapefileDataStoreFactory();
124 Map
<String
, Serializable
> params
= new HashMap
<>();
125 params
.put("url", shpFile
.toUri().toURL());
127 params
.put("create spatial index", Boolean
.TRUE
);
129 ShapefileDataStore newDataStore
= (ShapefileDataStore
) dataStoreFactory
.createNewDataStore(params
);
130 newDataStore
.createSchema(featureType
);
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
);
138 try (Transaction transaction
= new DefaultTransaction("create")) {
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
);
149 throw new IllegalArgumentException(typeName
+ " does not support read/write access");
151 } catch (IOException e
) {
152 throw new RuntimeException("Cannot write shapefile " + shpFile
, e
);