1 package org
.argeo
.app
.geo
.acr
;
3 import java
.io
.IOException
;
4 import java
.io
.InputStream
;
5 import java
.io
.InputStreamReader
;
6 import java
.io
.OutputStream
;
8 import java
.io
.UncheckedIOException
;
9 import java
.nio
.charset
.StandardCharsets
;
10 import java
.util
.ArrayList
;
11 import java
.util
.Collections
;
12 import java
.util
.List
;
14 import javax
.xml
.namespace
.QName
;
16 import org
.argeo
.api
.acr
.Content
;
17 import org
.argeo
.api
.acr
.ContentName
;
18 import org
.argeo
.api
.acr
.DName
;
19 import org
.argeo
.api
.acr
.QNamed
;
20 import org
.argeo
.app
.api
.EntityName
;
21 import org
.argeo
.app
.api
.EntityType
;
22 import org
.argeo
.app
.api
.WGS84PosName
;
23 import org
.argeo
.app
.geo
.GeoJson
;
24 import org
.argeo
.app
.geo
.JTS
;
25 import org
.locationtech
.jts
.geom
.Coordinate
;
26 import org
.locationtech
.jts
.geom
.Envelope
;
27 import org
.locationtech
.jts
.geom
.Geometry
;
28 import org
.locationtech
.jts
.geom
.GeometryCollection
;
29 import org
.locationtech
.jts
.geom
.Point
;
31 import jakarta
.json
.Json
;
32 import jakarta
.json
.JsonObject
;
33 import jakarta
.json
.JsonReader
;
34 import jakarta
.json
.stream
.JsonGenerator
;
36 /** Utilities around entity types related to geography. */
37 public class GeoEntityUtils
{
38 public static final String PLACE_GEOM_JSON
= "place.geom.json";
39 public static final String _GEOM_JSON
= ".geom.json";
41 public static void putGeometry(Content c
, QNamed name
, Geometry geometry
) {
42 putGeometry(c
, name
.qName(), geometry
);
45 public static void putGeometry(Content c
, QName name
, Geometry geometry
) {
46 QName jsonFileName
= new ContentName(name
.getNamespaceURI(), name
.getLocalPart() + _GEOM_JSON
);
47 Content geom
= c
.soleChild(jsonFileName
).orElseGet(
48 () -> c
.add(jsonFileName
, Collections
.singletonMap(DName
.getcontenttype
.qName(), "application/json")));
49 try (OutputStream out
= geom
.open(OutputStream
.class)) {
50 JsonGenerator g
= Json
.createGenerator(out
);
52 GeoJson
.writeGeometry(g
, geometry
);
55 } catch (IOException e
) {
56 throw new UncheckedIOException("Cannot add geometry " + name
+ " to " + c
, e
);
58 // updateBoundingBox(c);
61 public static <T
extends Geometry
> T
getGeometry(Content c
, QNamed name
, Class
<T
> clss
) {
62 return getGeometry(c
, name
.qName(), clss
);
65 public static <T
extends Geometry
> T
getGeometry(Content c
, QName name
, Class
<T
> clss
) {
66 QName jsonFileName
= new ContentName(name
.getNamespaceURI(), name
.getLocalPart() + _GEOM_JSON
);
67 Content geom
= c
.soleChild(jsonFileName
).orElse(null);
70 try (Reader in
= new InputStreamReader(geom
.open(InputStream
.class), StandardCharsets
.UTF_8
)) {
71 JsonReader jsonReader
= Json
.createReader(in
);
72 JsonObject jsonObject
= jsonReader
.readObject();
73 T readGeom
= GeoJson
.readGeometry(jsonObject
, clss
);
75 } catch (IOException e
) {
76 throw new UncheckedIOException("Cannot parse " + c
, e
);
80 public static Point
toPoint(Content c
) {
81 if (c
.hasContentClass(EntityType
.geopoint
)) {
82 Double lat
= c
.get(WGS84PosName
.lat
, Double
.class).orElseThrow();
83 Double lon
= c
.get(WGS84PosName
.lon
, Double
.class).orElseThrow();
84 return JTS
.GEOMETRY_FACTORY_WGS84
.createPoint(new Coordinate(lat
, lon
));
85 // Double alt = c.get(WGS84PosName.alt, Double.class).orElse(null);
86 // return JTS.GEOMETRY_FACTORY_WGS84
87 // .createPoint(alt != null ? new Coordinate(lat, lon, alt) : new Coordinate(lat, lon));
92 public static GeometryCollection
getGeometries(Content entity
) {
93 List
<Geometry
> geoms
= new ArrayList
<>();
94 Point geoPoint
= toPoint(entity
);
98 Geometry place
= getGeometry(entity
, EntityName
.place
.qName(), Geometry
.class);
104 GeometryCollection geometryCollection
= JTS
.GEOMETRY_FACTORY_WGS84
105 .createGeometryCollection(geoms
.toArray(new Geometry
[geoms
.size()]));
106 return geometryCollection
;
109 public static void updateBoundingBox(Content entity
) {
110 GeometryCollection geometryCollection
= getGeometries(entity
);
111 if (geometryCollection
== null)
113 entity
.addContentClasses(EntityType
.geobounded
.qName());
115 Envelope bbox
= geometryCollection
.getEnvelopeInternal();
116 entity
.put(EntityName
.minLat
, bbox
.getMinX());
117 entity
.put(EntityName
.minLon
, bbox
.getMinY());
118 entity
.put(EntityName
.maxLat
, bbox
.getMaxX());
119 entity
.put(EntityName
.maxLon
, bbox
.getMaxY());
122 public static void updateBoundingBox(Content entity
, QName prop
) {
123 Geometry geom
= getGeometry(entity
, prop
, Geometry
.class);
126 entity
.addContentClasses(EntityType
.geobounded
.qName());
128 Envelope bbox
= geom
.getEnvelopeInternal();
129 entity
.put(EntityName
.minLat
, bbox
.getMinX());
130 entity
.put(EntityName
.minLon
, bbox
.getMinY());
131 entity
.put(EntityName
.maxLat
, bbox
.getMaxX());
132 entity
.put(EntityName
.maxLon
, bbox
.getMaxY());
136 private GeoEntityUtils() {