├── .github
└── workflows
│ └── maven.yml
├── .gitignore
├── LICENSE.md
├── README.md
├── pom.xml
└── src
├── main
└── java
│ └── org
│ └── wololo
│ ├── geojson
│ ├── Feature.java
│ ├── FeatureCollection.java
│ ├── GeoJSON.java
│ ├── GeoJSONFactory.java
│ ├── Geometry.java
│ ├── GeometryCollection.java
│ ├── LineString.java
│ ├── MultiLineString.java
│ ├── MultiPoint.java
│ ├── MultiPolygon.java
│ ├── Point.java
│ └── Polygon.java
│ └── jts2geojson
│ ├── GeoJSONReader.java
│ └── GeoJSONWriter.java
└── test
├── java
└── org
│ └── wololo
│ └── jts2geojson
│ ├── Data.java
│ └── DataFactory.java
└── scala
└── org
└── wololo
└── jts2geojson
├── DeserializeGeometryCollectionSpec.scala
├── GeoJSONFactorySpec.scala
├── GeoJSONReaderSpec.scala
└── GeoJSONWriterSpec.scala
/.github/workflows/maven.yml:
--------------------------------------------------------------------------------
1 | name: Java CI with Maven
2 |
3 | on:
4 | push:
5 | branches: [ master ]
6 | pull_request:
7 | branches: [ master ]
8 |
9 | jobs:
10 | build-jdk11:
11 | runs-on: ubuntu-latest
12 | steps:
13 | - uses: actions/checkout@v2
14 | - name: Set up JDK 11
15 | uses: actions/setup-java@v2
16 | with:
17 | java-version: '11'
18 | distribution: 'temurin'
19 | cache: maven
20 | - name: Test with Maven
21 | run: mvn -Dmaven.javadoc.skip=true -Dgpg.skip=true -B test
22 | build-jdk17:
23 | runs-on: ubuntu-latest
24 | steps:
25 | - uses: actions/checkout@v2
26 | - name: Set up JDK 17
27 | uses: actions/setup-java@v2
28 | with:
29 | java-version: '17'
30 | distribution: 'temurin'
31 | cache: maven
32 | - name: Test with Maven
33 | run: mvn -Dmaven.javadoc.skip=true -Dgpg.skip=true -B test
34 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | .cache
2 | .classpath
3 | .project
4 | .settings
5 | target
6 |
--------------------------------------------------------------------------------
/LICENSE.md:
--------------------------------------------------------------------------------
1 | The MIT License (MIT)
2 |
3 | Copyright (c) 2013 Björn Harrtell
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy of
6 | this software and associated documentation files (the "Software"), to deal in
7 | the Software without restriction, including without limitation the rights to
8 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
9 | the Software, and to permit persons to whom the Software is furnished to do so,
10 | subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
17 | FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
18 | COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
19 | IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
20 | CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
21 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | ## Introduction
2 |
3 | This Java library can convert JTS geometries to GeoJSON and back. Its API is similar to other io.* classes in JTS.
4 |
5 | [](https://github.com/bjornharrtell/jts2geojson/actions/workflows/maven.yml)
6 |
7 | ## Maven
8 |
9 | ```xml
10 |
11 | org.wololo
12 | jts2geojson
13 | 0.18.1
14 |
15 | ```
16 |
17 | ## Usage
18 |
19 | ```java
20 | GeoJSONWriter writer = new GeoJSONWriter();
21 | GeoJSON json = writer.write(geometry);
22 | String jsonstring = json.toString();
23 |
24 | GeoJSONReader reader = new GeoJSONReader();
25 | Geometry geometry = reader.read(json);
26 | ```
27 |
28 | ## Features and FeatureCollections
29 |
30 | JTS does not have anything like GeoJSON Feature or FeatureCollection but they can be parsed by this library. Example:
31 |
32 | ```java
33 | // parse Feature or FeatureCollection
34 | Feature feature = (Feature) GeoJSONFactory.create(json);
35 | FeatureCollection featureCollection = (FeatureCollection) GeoJSONFactory.create(json);
36 |
37 | // parse Geometry from Feature
38 | GeoJSONReader reader = new GeoJSONReader();
39 | Geometry geometry = reader.read(feature.getGeometry());
40 | geometry = reader.read(featureCollection.getFeatures()[0].getGeometry());
41 |
42 | // create and serialize a FeatureCollection
43 | List features = new ArrayList();
44 | Map properties = new HashMap();
45 | features.add(new Feature(geometry, properties));
46 | GeoJSONWriter writer = new GeoJSONWriter();
47 | GeoJSON json = writer.write(features);
48 | ```
49 |
50 |
--------------------------------------------------------------------------------
/pom.xml:
--------------------------------------------------------------------------------
1 |
3 | 4.0.0
4 | org.wololo
5 | jts2geojson
6 | 0.18.1
7 | jar
8 | jts2geojson
9 | JTS to GeoJSON converter
10 | https://github.com/bjornharrtell/jts2geojson
11 |
12 |
13 |
14 | MIT license
15 | http://www.opensource.org/licenses/mit-license.php
16 |
17 |
18 |
19 |
20 | https://github.com/bjornharrtell/jts2geojson
21 | scm:git:https://github.com/bjornharrtell/jts2geojson.git
22 | scm:git:https://github.com/bjornharrtell/jts2geojson.git
23 |
24 |
25 |
26 |
27 | bjornharrtell
28 | Björn Harrtell
29 |
30 |
31 |
32 |
33 | 3.0.4
34 |
35 |
36 |
37 | 11
38 |
39 |
40 |
41 |
42 | org.scala-lang
43 | scala-library
44 | 2.13.10
45 | test
46 |
47 |
48 | org.scalatest
49 | scalatest_2.13
50 | 3.2.14
51 | test
52 |
53 |
54 | org.locationtech.jts
55 | jts-core
56 | 1.18.1
57 |
58 |
59 | com.fasterxml.jackson.core
60 | jackson-databind
61 | 2.13.4.2
62 |
63 |
64 | com.fasterxml.jackson.core
65 | jackson-annotations
66 | 2.13.4
67 |
68 |
69 |
70 |
71 |
72 | ossrh
73 | https://oss.sonatype.org/content/repositories/snapshots
74 |
75 |
76 |
77 |
78 |
79 |
80 | org.apache.maven.plugins
81 | maven-compiler-plugin
82 | 3.10.1
83 |
84 | 11
85 |
86 |
87 |
88 | net.alchim31.maven
89 | scala-maven-plugin
90 | 4.7.2
91 |
92 |
93 |
94 | compile
95 | testCompile
96 |
97 |
98 |
99 |
100 |
101 | org.apache.maven.plugins
102 | maven-surefire-plugin
103 | 2.22.2
104 |
105 | true
106 |
107 |
108 |
109 | org.scalatest
110 | scalatest-maven-plugin
111 | 2.2.0
112 |
113 |
114 | test
115 |
116 | test
117 |
118 |
119 |
120 |
121 |
122 | org.apache.maven.plugins
123 | maven-source-plugin
124 | 3.2.1
125 |
126 |
127 | attach-sources
128 |
129 | jar-no-fork
130 |
131 |
132 |
133 |
134 |
135 | org.apache.maven.plugins
136 | maven-javadoc-plugin
137 | 3.4.1
138 |
139 |
140 | attach-javadocs
141 |
142 | jar
143 |
144 |
145 |
146 |
147 |
148 | org.apache.maven.plugins
149 | maven-gpg-plugin
150 | 3.0.1
151 |
152 |
153 | sign-artifacts
154 | verify
155 |
156 | sign
157 |
158 |
159 |
160 |
161 |
162 | org.sonatype.plugins
163 | nexus-staging-maven-plugin
164 | 1.6.13
165 | true
166 |
167 | ossrh
168 | https://oss.sonatype.org/
169 | true
170 |
171 |
172 |
173 |
174 |
175 |
176 |
--------------------------------------------------------------------------------
/src/main/java/org/wololo/geojson/Feature.java:
--------------------------------------------------------------------------------
1 | package org.wololo.geojson;
2 |
3 | import java.util.Map;
4 |
5 | import com.fasterxml.jackson.annotation.JsonCreator;
6 | import com.fasterxml.jackson.annotation.JsonProperty;
7 | import com.fasterxml.jackson.annotation.JsonPropertyOrder;
8 | import com.fasterxml.jackson.annotation.JsonInclude;
9 | import com.fasterxml.jackson.annotation.JsonInclude.Include;
10 |
11 | @JsonPropertyOrder({"type", "id", "geometry", "properties"})
12 | public class Feature extends GeoJSON {
13 | @JsonInclude(Include.NON_EMPTY)
14 | private final Object id;
15 | private final Geometry geometry;
16 | private final Map properties;
17 |
18 | public Feature(
19 | @JsonProperty("geometry") Geometry geometry,
20 | @JsonProperty("properties") Map properties) {
21 | this(null, geometry, properties);
22 | }
23 |
24 | @JsonCreator
25 | public Feature(
26 | @JsonProperty("id") Object id,
27 | @JsonProperty("geometry") Geometry geometry,
28 | @JsonProperty("properties") Map properties) {
29 | super();
30 | this.id = id;
31 | this.geometry = geometry;
32 | this.properties = properties;
33 | }
34 |
35 | public Object getId() {
36 | return id;
37 | }
38 |
39 | public Geometry getGeometry() {
40 | return geometry;
41 | }
42 |
43 | public Map getProperties() {
44 | return properties;
45 | }
46 | }
47 |
--------------------------------------------------------------------------------
/src/main/java/org/wololo/geojson/FeatureCollection.java:
--------------------------------------------------------------------------------
1 | package org.wololo.geojson;
2 |
3 | import com.fasterxml.jackson.annotation.JsonCreator;
4 | import com.fasterxml.jackson.annotation.JsonProperty;
5 | import com.fasterxml.jackson.annotation.JsonPropertyOrder;
6 |
7 | @JsonPropertyOrder({"type", "features"})
8 | public class FeatureCollection extends GeoJSON {
9 | private final Feature[] features;
10 |
11 | @JsonCreator
12 | public FeatureCollection(@JsonProperty("features") Feature[] features) {
13 | super();
14 | this.features = features;
15 | }
16 |
17 | public Feature[] getFeatures() {
18 | return features;
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/src/main/java/org/wololo/geojson/GeoJSON.java:
--------------------------------------------------------------------------------
1 | package org.wololo.geojson;
2 |
3 | import java.io.IOException;
4 |
5 | import com.fasterxml.jackson.annotation.JsonSubTypes;
6 | import com.fasterxml.jackson.annotation.JsonTypeInfo;
7 | import com.fasterxml.jackson.core.JsonGenerationException;
8 | import com.fasterxml.jackson.annotation.JsonCreator;
9 | import com.fasterxml.jackson.annotation.JsonProperty;
10 | import com.fasterxml.jackson.databind.JsonMappingException;
11 | import com.fasterxml.jackson.databind.ObjectMapper;
12 | @JsonTypeInfo(
13 | use = JsonTypeInfo.Id.NAME,
14 | include = JsonTypeInfo.As.EXISTING_PROPERTY,
15 | property = "type"
16 | )
17 | @JsonSubTypes( {
18 | @JsonSubTypes.Type(value=Point.class, name="Point" ),
19 | @JsonSubTypes.Type(value=LineString.class, name="LineString" ),
20 | @JsonSubTypes.Type(value=Polygon.class, name="Polygon" ),
21 | @JsonSubTypes.Type(value=MultiPoint.class, name="MultiPoint" ),
22 | @JsonSubTypes.Type(value=MultiLineString.class, name="MultiLineString" ),
23 | @JsonSubTypes.Type(value=MultiPolygon.class, name="MultiPolygon" ),
24 | @JsonSubTypes.Type(value=Feature.class, name="Feature" ),
25 | @JsonSubTypes.Type(value=FeatureCollection.class, name="FeatureCollection" ),
26 | @JsonSubTypes.Type(value=GeometryCollection.class, name="GeometryCollection" )
27 | })
28 | public abstract class GeoJSON {
29 | private static final ObjectMapper mapper = new ObjectMapper();
30 |
31 | @JsonProperty("type")
32 | private String type;
33 |
34 | @JsonCreator
35 | public GeoJSON() {
36 | setType(getClass().getSimpleName());
37 | }
38 |
39 | public String toString() {
40 | try {
41 | return mapper.writeValueAsString(this);
42 | } catch (JsonGenerationException e) {
43 | return "Unhandled exception occured when serializing this instance";
44 | } catch (JsonMappingException e) {
45 | return "Unhandled exception occured when serializing this instance";
46 | } catch (IOException e) {
47 | return "Unhandled exception occured when serializing this instance";
48 | }
49 | }
50 |
51 | public String getType() {
52 | return type;
53 | }
54 |
55 | public void setType(String type) {
56 | this.type = type;
57 | }
58 | }
59 |
--------------------------------------------------------------------------------
/src/main/java/org/wololo/geojson/GeoJSONFactory.java:
--------------------------------------------------------------------------------
1 | package org.wololo.geojson;
2 |
3 | import java.io.IOException;
4 | import java.util.Map;
5 | import java.util.ArrayList;
6 |
7 | import com.fasterxml.jackson.core.JsonParseException;
8 | import com.fasterxml.jackson.databind.JsonMappingException;
9 | import com.fasterxml.jackson.databind.JsonNode;
10 | import com.fasterxml.jackson.databind.ObjectMapper;
11 |
12 | public class GeoJSONFactory {
13 | private static final ObjectMapper mapper = new ObjectMapper();
14 |
15 | public static GeoJSON create(String json) {
16 | try {
17 | var node = mapper.readTree(json);
18 | var type = node.get("type").asText();
19 | if (type.equals("FeatureCollection"))
20 | return readFeatureCollection(node);
21 | else if (type.equals("Feature"))
22 | return readFeature(node);
23 | else
24 | return readGeometry(node, type);
25 | } catch (Exception e) {
26 | throw new RuntimeException(e);
27 | }
28 | }
29 |
30 | private static FeatureCollection readFeatureCollection(JsonNode node)
31 | throws JsonParseException, JsonMappingException, IOException, ClassNotFoundException {
32 | var it = node.get("features").iterator();
33 | var features = new ArrayList();
34 | while (it.hasNext())
35 | features.add(readFeature(it.next()));
36 | return new FeatureCollection(features.toArray(new Feature[features.size()]));
37 | }
38 |
39 | private static Feature readFeature(JsonNode node)
40 | throws JsonParseException, JsonMappingException, IOException, ClassNotFoundException {
41 | var geometryNode = node.get("geometry");
42 | var javaType = mapper.getTypeFactory().constructMapType(Map.class, String.class, Object.class);
43 | var id = node.get("id");
44 | Map properties = mapper.readValue(node.get("properties").traverse(), javaType);
45 | var geometry = readGeometry(geometryNode);
46 | return new Feature(id, geometry, properties);
47 | }
48 |
49 | private static Geometry readGeometry(JsonNode node)
50 | throws JsonParseException, JsonMappingException, IOException, ClassNotFoundException {
51 | if (node != null && !node.isNull())
52 | return readGeometry(node, node.get("type").asText());
53 | else
54 | return null;
55 | }
56 |
57 | private static Geometry readGeometry(JsonNode node, String type)
58 | throws JsonParseException, JsonMappingException, IOException, ClassNotFoundException {
59 | return (Geometry) mapper.readValue(node.traverse(), Class.forName("org.wololo.geojson." + type));
60 | }
61 |
62 | }
63 |
--------------------------------------------------------------------------------
/src/main/java/org/wololo/geojson/Geometry.java:
--------------------------------------------------------------------------------
1 | package org.wololo.geojson;
2 |
3 | import com.fasterxml.jackson.annotation.JsonCreator;
4 | import com.fasterxml.jackson.annotation.JsonPropertyOrder;
5 | import com.fasterxml.jackson.annotation.JsonSubTypes;
6 | import com.fasterxml.jackson.annotation.JsonTypeInfo;
7 | import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
8 |
9 | @JsonTypeInfo(
10 | use = JsonTypeInfo.Id.NAME,
11 | include = JsonTypeInfo.As.EXISTING_PROPERTY,
12 | property = "type"
13 | )
14 | @JsonSubTypes( {
15 | @JsonSubTypes.Type(value=Point.class, name="Point" ),
16 | @JsonSubTypes.Type(value=LineString.class, name="LineString" ),
17 | @JsonSubTypes.Type(value=Polygon.class, name="Polygon" ),
18 | @JsonSubTypes.Type(value=MultiPoint.class, name="MultiPoint" ),
19 | @JsonSubTypes.Type(value=MultiLineString.class, name="MultiLineString" ),
20 | @JsonSubTypes.Type(value=MultiPolygon.class, name="MultiPolygon" ),
21 | @JsonSubTypes.Type(value=Feature.class, name="Feature" ),
22 | @JsonSubTypes.Type(value=FeatureCollection.class, name="FeatureCollection" ),
23 | @JsonSubTypes.Type(value=GeometryCollection.class, name="GeometryCollection" )
24 | } )
25 |
26 | @JsonIgnoreProperties(ignoreUnknown = true)
27 | @JsonPropertyOrder({"type", "coordinates", "bbox"})
28 | public abstract class Geometry extends GeoJSON {
29 | @JsonCreator
30 | public Geometry() {
31 | super();
32 | }
33 | }
34 |
--------------------------------------------------------------------------------
/src/main/java/org/wololo/geojson/GeometryCollection.java:
--------------------------------------------------------------------------------
1 | package org.wololo.geojson;
2 |
3 | import com.fasterxml.jackson.annotation.JsonCreator;
4 | import com.fasterxml.jackson.annotation.JsonProperty;
5 | import com.fasterxml.jackson.annotation.JsonPropertyOrder;
6 |
7 | @JsonPropertyOrder({"type", "geometries"})
8 | public class GeometryCollection extends Geometry {
9 | private final Geometry[] geometries;
10 |
11 | @JsonCreator
12 | public GeometryCollection(@JsonProperty("geometries") Geometry[] geometries) {
13 | super();
14 | this.geometries = geometries;
15 | }
16 |
17 | public Geometry[] getGeometries() {
18 | return geometries;
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/src/main/java/org/wololo/geojson/LineString.java:
--------------------------------------------------------------------------------
1 | package org.wololo.geojson;
2 |
3 | import com.fasterxml.jackson.annotation.JsonCreator;
4 | import com.fasterxml.jackson.annotation.JsonProperty;
5 | import com.fasterxml.jackson.annotation.JsonInclude;
6 | import com.fasterxml.jackson.annotation.JsonInclude.Include;
7 |
8 | @JsonInclude(Include.NON_NULL)
9 | public class LineString extends Geometry {
10 | private final double[][] coordinates;
11 | private final double[] bbox;
12 |
13 | @JsonCreator
14 | public LineString(@JsonProperty("coordinates") double [][] coordinates) {
15 | super();
16 | this.coordinates = coordinates;
17 | this.bbox = null;
18 | }
19 |
20 | public double[][] getCoordinates() {
21 | return coordinates;
22 | }
23 |
24 | public double[] getBbox() {
25 | return bbox;
26 | }
27 | }
28 |
--------------------------------------------------------------------------------
/src/main/java/org/wololo/geojson/MultiLineString.java:
--------------------------------------------------------------------------------
1 | package org.wololo.geojson;
2 |
3 | import com.fasterxml.jackson.annotation.JsonCreator;
4 | import com.fasterxml.jackson.annotation.JsonProperty;
5 | import com.fasterxml.jackson.annotation.JsonInclude;
6 | import com.fasterxml.jackson.annotation.JsonInclude.Include;
7 |
8 | @JsonInclude(Include.NON_NULL)
9 | public class MultiLineString extends Geometry {
10 | private final double[][][] coordinates;
11 | private final double[] bbox;
12 |
13 | @JsonCreator
14 | public MultiLineString(@JsonProperty("coordinates") double [][][] coordinates) {
15 | super();
16 | this.coordinates = coordinates;
17 | this.bbox = null;
18 | }
19 |
20 | public double[][][] getCoordinates() {
21 | return coordinates;
22 | }
23 |
24 | public double[] getBbox() {
25 | return bbox;
26 | }
27 | }
28 |
--------------------------------------------------------------------------------
/src/main/java/org/wololo/geojson/MultiPoint.java:
--------------------------------------------------------------------------------
1 | package org.wololo.geojson;
2 |
3 | import com.fasterxml.jackson.annotation.JsonCreator;
4 | import com.fasterxml.jackson.annotation.JsonProperty;
5 | import com.fasterxml.jackson.annotation.JsonInclude;
6 | import com.fasterxml.jackson.annotation.JsonInclude.Include;
7 |
8 | @JsonInclude(Include.NON_NULL)
9 | public class MultiPoint extends Geometry {
10 | private final double[][] coordinates;
11 | private final double[] bbox;
12 |
13 | @JsonCreator
14 | public MultiPoint(@JsonProperty("coordinates") double [][] coordinates) {
15 | super();
16 | this.coordinates = coordinates;
17 | this.bbox = null;
18 | }
19 |
20 | public double[][] getCoordinates() {
21 | return coordinates;
22 | }
23 |
24 | public double[] getBbox() {
25 | return bbox;
26 | }
27 | }
28 |
--------------------------------------------------------------------------------
/src/main/java/org/wololo/geojson/MultiPolygon.java:
--------------------------------------------------------------------------------
1 | package org.wololo.geojson;
2 |
3 | import com.fasterxml.jackson.annotation.JsonCreator;
4 | import com.fasterxml.jackson.annotation.JsonProperty;
5 | import com.fasterxml.jackson.annotation.JsonInclude;
6 | import com.fasterxml.jackson.annotation.JsonInclude.Include;
7 |
8 | @JsonInclude(Include.NON_NULL)
9 | public class MultiPolygon extends Geometry {
10 | private final double[][][][] coordinates;
11 | private final double[] bbox;
12 |
13 | @JsonCreator
14 | public MultiPolygon(@JsonProperty("coordinates") double [][][][] coordinates) {
15 | super();
16 | this.coordinates = coordinates;
17 | this.bbox = null;
18 | }
19 |
20 | public double[][][][] getCoordinates() {
21 | return coordinates;
22 | }
23 |
24 | public double[] getBbox() {
25 | return bbox;
26 | }
27 | }
28 |
--------------------------------------------------------------------------------
/src/main/java/org/wololo/geojson/Point.java:
--------------------------------------------------------------------------------
1 | package org.wololo.geojson;
2 |
3 | import com.fasterxml.jackson.annotation.JsonCreator;
4 | import com.fasterxml.jackson.annotation.JsonProperty;
5 | import com.fasterxml.jackson.annotation.JsonInclude;
6 | import com.fasterxml.jackson.annotation.JsonInclude.Include;
7 |
8 | @JsonInclude(Include.NON_NULL)
9 | public class Point extends Geometry {
10 | private final double[] coordinates;
11 | private final double[] bbox;
12 |
13 | @JsonCreator
14 | public Point(@JsonProperty("coordinates") double [] coordinates) {
15 | super();
16 | this.coordinates = coordinates;
17 | this.bbox = null;
18 | }
19 |
20 | public double[] getCoordinates() {
21 | return coordinates;
22 | }
23 |
24 | public double[] getBbox() {
25 | return bbox;
26 | }
27 | }
28 |
--------------------------------------------------------------------------------
/src/main/java/org/wololo/geojson/Polygon.java:
--------------------------------------------------------------------------------
1 | package org.wololo.geojson;
2 |
3 | import com.fasterxml.jackson.annotation.JsonCreator;
4 | import com.fasterxml.jackson.annotation.JsonProperty;
5 | import com.fasterxml.jackson.annotation.JsonInclude;
6 | import com.fasterxml.jackson.annotation.JsonInclude.Include;
7 |
8 | @JsonInclude(Include.NON_NULL)
9 | public class Polygon extends Geometry {
10 | private final double[][][] coordinates;
11 | private final double[] bbox;
12 |
13 | @JsonCreator
14 | public Polygon(@JsonProperty("coordinates") double [][][] coordinates) {
15 | super();
16 | this.coordinates = coordinates;
17 | this.bbox = null;
18 | }
19 |
20 | public double[][][] getCoordinates() {
21 | return coordinates;
22 | }
23 |
24 | public double[] getBbox() {
25 | return bbox;
26 | }
27 | }
28 |
--------------------------------------------------------------------------------
/src/main/java/org/wololo/jts2geojson/GeoJSONReader.java:
--------------------------------------------------------------------------------
1 | package org.wololo.jts2geojson;
2 |
3 | import org.wololo.geojson.*;
4 |
5 | import org.locationtech.jts.geom.Coordinate;
6 | import org.locationtech.jts.geom.Geometry;
7 | import org.locationtech.jts.geom.GeometryFactory;
8 | import org.locationtech.jts.geom.LinearRing;
9 | import org.locationtech.jts.geom.PrecisionModel;
10 |
11 | public class GeoJSONReader {
12 | final static GeometryFactory FACTORY = new GeometryFactory(
13 | new PrecisionModel(PrecisionModel.FLOATING));
14 |
15 | public Geometry read(String json) {
16 | return read(json, null);
17 | }
18 |
19 | public Geometry read(String json, GeometryFactory geomFactory) {
20 | return read(GeoJSONFactory.create(json), geomFactory);
21 | }
22 |
23 | public Geometry read(GeoJSON geoJSON) {
24 | return read(geoJSON, null);
25 | }
26 |
27 | public Geometry read(GeoJSON geoJSON, GeometryFactory geomFactory) {
28 | var factory = geomFactory != null ? geomFactory : FACTORY;
29 | if (geoJSON instanceof Point)
30 | return convert((Point) geoJSON, factory);
31 | else if (geoJSON instanceof LineString)
32 | return convert((LineString) geoJSON, factory);
33 | else if (geoJSON instanceof Polygon)
34 | return convert((Polygon) geoJSON, factory);
35 | else if (geoJSON instanceof MultiPoint)
36 | return convert((MultiPoint) geoJSON, factory);
37 | else if (geoJSON instanceof MultiLineString)
38 | return convert((MultiLineString) geoJSON, factory);
39 | else if (geoJSON instanceof MultiPolygon)
40 | return convert((MultiPolygon) geoJSON, factory);
41 | else if (geoJSON instanceof GeometryCollection)
42 | return convert((GeometryCollection) geoJSON, factory);
43 | else
44 | throw new UnsupportedOperationException();
45 | }
46 |
47 | Geometry convert(Point point, GeometryFactory factory) {
48 | return factory.createPoint(convert(point.getCoordinates()));
49 | }
50 |
51 | Geometry convert(MultiPoint multiPoint, GeometryFactory factory) {
52 | return factory.createMultiPointFromCoords(convert(multiPoint.getCoordinates()));
53 | }
54 |
55 | Geometry convert(LineString lineString, GeometryFactory factory) {
56 | return factory.createLineString(convert(lineString.getCoordinates()));
57 | }
58 |
59 | Geometry convert(MultiLineString multiLineString, GeometryFactory factory) {
60 | var size = multiLineString.getCoordinates().length;
61 | var lineStrings = new org.locationtech.jts.geom.LineString[size];
62 | for (int i = 0; i < size; i++)
63 | lineStrings[i] = factory.createLineString(convert(multiLineString.getCoordinates()[i]));
64 | return factory.createMultiLineString(lineStrings);
65 | }
66 |
67 | Geometry convert(Polygon polygon, GeometryFactory factory) {
68 | return convertToPolygon(polygon.getCoordinates(), factory);
69 | }
70 |
71 | org.locationtech.jts.geom.Polygon convertToPolygon(double[][][] coordinates, GeometryFactory factory) {
72 | var shell = factory.createLinearRing(convert(coordinates[0]));
73 | if (coordinates.length > 1) {
74 | var size = coordinates.length - 1;
75 | var holes = new LinearRing[size];
76 | for (var i = 0; i < size; i++)
77 | holes[i] = factory.createLinearRing(convert(coordinates[i + 1]));
78 | return factory.createPolygon(shell, holes);
79 | } else {
80 | return factory.createPolygon(shell);
81 | }
82 | }
83 |
84 | Geometry convert(MultiPolygon multiPolygon, GeometryFactory factory) {
85 | var size = multiPolygon.getCoordinates().length;
86 | var polygons = new org.locationtech.jts.geom.Polygon[size];
87 | for (int i = 0; i < size; i++)
88 | polygons[i] = convertToPolygon(multiPolygon.getCoordinates()[i], factory);
89 | return factory.createMultiPolygon(polygons);
90 | }
91 |
92 | Geometry convert(GeometryCollection gc, GeometryFactory factory) {
93 | var size = gc.getGeometries().length;
94 | var geometries = new org.locationtech.jts.geom.Geometry[size];
95 | for (var i = 0; i < size; i++)
96 | geometries[i] = read(gc.getGeometries()[i], factory);
97 | return factory.createGeometryCollection(geometries);
98 | }
99 |
100 | Coordinate convert(double[] c) {
101 | if (c.length == 2)
102 | return new Coordinate(c[0], c[1]);
103 | else
104 | return new Coordinate(c[0], c[1], c[2]);
105 | }
106 |
107 | Coordinate[] convert(double[][] ca) {
108 | var coordinates = new Coordinate[ca.length];
109 | for (int i = 0; i < ca.length; i++)
110 | coordinates[i] = convert(ca[i]);
111 | return coordinates;
112 | }
113 | }
114 |
--------------------------------------------------------------------------------
/src/main/java/org/wololo/jts2geojson/GeoJSONWriter.java:
--------------------------------------------------------------------------------
1 | package org.wololo.jts2geojson;
2 |
3 | import java.util.List;
4 |
5 | import org.locationtech.jts.geom.*;
6 | import org.wololo.geojson.Feature;
7 |
8 | public class GeoJSONWriter {
9 |
10 | final static GeoJSONReader reader = new GeoJSONReader();
11 |
12 | public org.wololo.geojson.Geometry write(Geometry geometry) {
13 | Class extends Geometry> c = geometry.getClass();
14 | if (c.equals(Point.class))
15 | return convert((Point) geometry);
16 | else if (c.equals(LineString.class))
17 | return convert((LineString) geometry);
18 | else if (c.equals(LinearRing.class))
19 | return convert((LinearRing) geometry);
20 | else if (c.equals(Polygon.class))
21 | return convert((Polygon) geometry);
22 | else if (c.equals(MultiPoint.class))
23 | return convert((MultiPoint) geometry);
24 | else if (c.equals(MultiLineString.class))
25 | return convert((MultiLineString) geometry);
26 | else if (c.equals(MultiPolygon.class))
27 | return convert((MultiPolygon) geometry);
28 | else if (c.equals(GeometryCollection.class))
29 | return convert((GeometryCollection) geometry);
30 | else
31 | throw new UnsupportedOperationException();
32 | }
33 |
34 | public org.wololo.geojson.FeatureCollection write(List features) {
35 | var size = features.size();
36 | var featuresJson = new org.wololo.geojson.Feature[size];
37 | for (var i = 0; i < size; i++)
38 | featuresJson[i] = features.get(i);
39 | return new org.wololo.geojson.FeatureCollection(featuresJson);
40 | }
41 |
42 | org.wololo.geojson.Point convert(Point point) {
43 | return new org.wololo.geojson.Point(convert(point.getCoordinate()));
44 | }
45 |
46 | org.wololo.geojson.MultiPoint convert(MultiPoint multiPoint) {
47 | return new org.wololo.geojson.MultiPoint(
48 | convert(multiPoint.getCoordinates()));
49 | }
50 |
51 | org.wololo.geojson.LineString convert(LineString lineString) {
52 | return new org.wololo.geojson.LineString(
53 | convert(lineString.getCoordinates()));
54 | }
55 |
56 | org.wololo.geojson.LineString convert(LinearRing ringString) {
57 | return new org.wololo.geojson.LineString(
58 | convert(ringString.getCoordinates()));
59 | }
60 |
61 | org.wololo.geojson.MultiLineString convert(MultiLineString multiLineString) {
62 | var size = multiLineString.getNumGeometries();
63 | var lineStrings = new double[size][][];
64 | for (int i = 0; i < size; i++)
65 | lineStrings[i] = convert(multiLineString.getGeometryN(i).getCoordinates());
66 | return new org.wololo.geojson.MultiLineString(lineStrings);
67 | }
68 |
69 | org.wololo.geojson.Polygon convert(Polygon polygon) {
70 | var size = polygon.getNumInteriorRing() + 1;
71 | var rings = new double[size][][];
72 | rings[0] = convert(polygon.getExteriorRing().getCoordinates());
73 | for (int i = 0; i < size - 1; i++)
74 | rings[i + 1] = convert(polygon.getInteriorRingN(i).getCoordinates());
75 | return new org.wololo.geojson.Polygon(rings);
76 | }
77 |
78 | org.wololo.geojson.MultiPolygon convert(MultiPolygon multiPolygon) {
79 | var size = multiPolygon.getNumGeometries();
80 | var polygons = new double[size][][][];
81 | for (int i = 0; i < size; i++)
82 | polygons[i] = convert((Polygon) multiPolygon.getGeometryN(i)).getCoordinates();
83 | return new org.wololo.geojson.MultiPolygon(polygons);
84 | }
85 |
86 | org.wololo.geojson.GeometryCollection convert(GeometryCollection gc) {
87 | var size = gc.getNumGeometries();
88 | var geometries = new org.wololo.geojson.Geometry[size];
89 | for (int i = 0; i < size; i++)
90 | geometries[i] = write((Geometry) gc.getGeometryN(i));
91 | return new org.wololo.geojson.GeometryCollection(geometries);
92 | }
93 |
94 | double[] convert(Coordinate coordinate) {
95 | if (Double.isNaN( coordinate.getZ() ))
96 | return new double[] { coordinate.x, coordinate.y };
97 | else
98 | return new double[] { coordinate.x, coordinate.y, coordinate.getZ() };
99 | }
100 |
101 | double[][] convert(Coordinate[] coordinates) {
102 | var array = new double[coordinates.length][];
103 | for (int i = 0; i < coordinates.length; i++)
104 | array[i] = convert(coordinates[i]);
105 | return array;
106 | }
107 | }
108 |
--------------------------------------------------------------------------------
/src/test/java/org/wololo/jts2geojson/Data.java:
--------------------------------------------------------------------------------
1 | package org.wololo.jts2geojson;
2 |
3 | import org.wololo.geojson.GeoJSON;
4 |
5 | class Data {
6 |
7 | public GeoJSON geometry;
8 |
9 | }
10 |
--------------------------------------------------------------------------------
/src/test/java/org/wololo/jts2geojson/DataFactory.java:
--------------------------------------------------------------------------------
1 | package org.wololo.jts2geojson;
2 |
3 | import com.fasterxml.jackson.core.JsonProcessingException;
4 | import com.fasterxml.jackson.databind.ObjectMapper;
5 |
6 | class DataFactory {
7 |
8 | private final static ObjectMapper mapper = new ObjectMapper();
9 |
10 | public static Data fromJson(String json) {
11 | try {
12 | return mapper.readerFor(Data.class).readValue(json);
13 | } catch (JsonProcessingException e) {
14 | throw new RuntimeException(e);
15 | }
16 | }
17 |
18 | }
19 |
--------------------------------------------------------------------------------
/src/test/scala/org/wololo/jts2geojson/DeserializeGeometryCollectionSpec.scala:
--------------------------------------------------------------------------------
1 | package org.wololo.jts2geojson
2 |
3 | import java.util.HashMap
4 |
5 | import org.scalatest.wordspec.AnyWordSpec
6 | import org.wololo.geojson._
7 |
8 | class DeserializeGeometryCollectionSpec extends AnyWordSpec {
9 | "GeoJSONFactory" when {
10 | "parsing GeoJSON to object" should {
11 | val geometry = new Point(Array(1, 1))
12 | val properties = new HashMap[String, Object]()
13 | properties.put("test", 1.asInstanceOf[Object])
14 | val feature = new Feature(geometry, properties)
15 |
16 |
17 | "deserialize GeometryCollection successfully" in {
18 | val geoJSON = """{"type": "GeometryCollection", "geometries": [{"type": "Point", "coordinates": [1.1, 2.2] }]}"""
19 | val json = GeoJSONFactory.create(geoJSON)
20 | assert(json.isInstanceOf[GeometryCollection])
21 | val gc = json.asInstanceOf[GeometryCollection]
22 | assert(gc.getGeometries.nonEmpty)
23 | val g = gc.getGeometries.head
24 | assert(g != null)
25 | assert(g.isInstanceOf[Point])
26 | val point = g.asInstanceOf[Point]
27 | assert(point.getCoordinates.toSeq == Seq(1.1, 2.2))
28 | }
29 |
30 | "deserialize GeometryCollection successfully if using ObjectMapper" in {
31 | val geoJSON = """{ "geometry" : {"type": "GeometryCollection", "geometries": [{"type": "Point", "coordinates": [1.1, 2.2] }]}}"""
32 | val value = DataFactory.fromJson(geoJSON)
33 | assert(value.isInstanceOf[Data])
34 | }
35 |
36 | }
37 |
38 | }
39 | }
40 |
--------------------------------------------------------------------------------
/src/test/scala/org/wololo/jts2geojson/GeoJSONFactorySpec.scala:
--------------------------------------------------------------------------------
1 | package org.wololo.jts2geojson
2 |
3 | import org.scalatest.wordspec.AnyWordSpec
4 | import org.wololo.geojson._
5 | import java.util.HashMap
6 |
7 | class GeoJSONFactorySpec extends AnyWordSpec {
8 | "GeoJSONFactory" when {
9 | "dealing with badly encoded file" should {
10 | "read missing geometry field as null" in {
11 | val json = """{"type":"Feature","properties":{"test":1}}"""
12 | val expected = """{"type":"Feature","geometry":null,"properties":{"test":1}}"""
13 |
14 | val geojson = GeoJSONFactory.create(json)
15 | assert(geojson.toString == expected)
16 | }
17 | }
18 |
19 | "parsing GeoJSON to object" should {
20 | val geometry = new Point(Array(1, 1))
21 | val properties = new HashMap[String, Object]()
22 | properties.put("test", 1.asInstanceOf[Object])
23 | val feature = new Feature(geometry, properties)
24 |
25 | "be identical to programmatically created Feature" in {
26 | val expected = """{"type":"Feature","geometry":{"type":"Point","coordinates":[1.0,1.0]},"properties":{"test":1}}"""
27 |
28 | val json = feature.toString
29 | assert(expected == json)
30 |
31 | val geoJSON = GeoJSONFactory.create(json)
32 | assert(expected == geoJSON.toString)
33 | }
34 |
35 | "be identical to programmatically created Feature with id" in {
36 | val feature = new Feature(1, geometry, properties)
37 |
38 | val expected = """{"type":"Feature","id":1,"geometry":{"type":"Point","coordinates":[1.0,1.0]},"properties":{"test":1}}"""
39 |
40 | val json = feature.toString
41 | assert(expected == json)
42 |
43 | val geoJSON = GeoJSONFactory.create(json)
44 |
45 | assert(expected == geoJSON.toString)
46 | }
47 |
48 | "be identical to programmatically created Feature without geometry" in {
49 | val feature = new Feature(null, properties)
50 |
51 | val expected = """{"type":"Feature","geometry":null,"properties":{"test":1}}"""
52 |
53 | val json = feature.toString
54 | assert(expected == json)
55 |
56 | val geoJSON = GeoJSONFactory.create(json)
57 |
58 | assert(expected == geoJSON.toString)
59 | }
60 |
61 | "be identical to programmatically created FeatureCollection" in {
62 | val expected = """{"type":"FeatureCollection","features":[{"type":"Feature","geometry":{"type":"Point","coordinates":[1.0,1.0]},"properties":{"test":1}},{"type":"Feature","geometry":{"type":"Point","coordinates":[1.0,1.0]},"properties":{"test":1}}]}"""
63 |
64 | val fc = new FeatureCollection(Array(feature, feature))
65 | assert(expected == fc.toString)
66 | }
67 |
68 | "take care of bbox property" in {
69 | val geoJSON = """{"type": "FeatureCollection", "features": [{"type": "Feature", "id": 1, "geometry": {"type": "Point", "coordinates": [-8.311419016226296, 53.894485921596285], "bbox": [-8.311419016226296, 53.894485921596285, -8.311419016226296, 53.894485921596285] }, "properties": {"FID": 335, "PLAN_REF": "151", "APP_TYPE": "RETENTION", "LOCATION": "Knockglass, Ballinameen, Co. Roscommon.", "REC_DATE": "05/01/2015", "DESCRIPT": "Of entrance to existing forest plantation for extraction of timber at various times at ", "APPSTATUS": "Application Finalised", "DEC_DATE": "20/02/2015", "DECISION": "Granted (Conditional)", "APPE_DEC": "n/a", "APPE_DAT": "n/a", "MOREINFO": "http://www.eplanning.ie/roscommoneplan/FileRefDetails.aspx?file_number=151", "WGS_LONG": "-8.31141", "WGS_LAT": "53.89448"} }] }"""
70 | val json = GeoJSONFactory.create(geoJSON)
71 | assert(json.isInstanceOf[FeatureCollection])
72 | val fc = json.asInstanceOf[FeatureCollection]
73 | assert(fc.getFeatures.nonEmpty)
74 | val f = fc.getFeatures.head
75 | assert(f.getGeometry != null)
76 | assert(f.getGeometry.isInstanceOf[Point])
77 | val point = f.getGeometry.asInstanceOf[Point]
78 | assert(point.getBbox != null)
79 | assert(point.getBbox.toSeq == Seq(-8.311419016226296, 53.894485921596285, -8.311419016226296, 53.894485921596285))
80 | }
81 |
82 | "take care of MultiPoint bbox property" in {
83 | val geoJSON = """{"type": "FeatureCollection", "features": [{"type": "Feature", "id": 1, "geometry": {"type": "MultiPoint", "coordinates": [[-8.311419016226296, 53.894485921596285]], "bbox": [-8.311419016226296, 53.894485921596285, -8.311419016226296, 53.894485921596285] }, "properties": {"FID": 335, "PLAN_REF": "151", "APP_TYPE": "RETENTION", "LOCATION": "Knockglass, Ballinameen, Co. Roscommon.", "REC_DATE": "05/01/2015", "DESCRIPT": "Of entrance to existing forest plantation for extraction of timber at various times at ", "APPSTATUS": "Application Finalised", "DEC_DATE": "20/02/2015", "DECISION": "Granted (Conditional)", "APPE_DEC": "n/a", "APPE_DAT": "n/a", "MOREINFO": "http://www.eplanning.ie/roscommoneplan/FileRefDetails.aspx?file_number=151", "WGS_LONG": "-8.31141", "WGS_LAT": "53.89448"} }] }"""
84 | val json = GeoJSONFactory.create(geoJSON)
85 | assert(json.isInstanceOf[FeatureCollection])
86 | val fc = json.asInstanceOf[FeatureCollection]
87 | assert(fc.getFeatures.nonEmpty)
88 | val f = fc.getFeatures.head
89 | assert(f.getGeometry != null)
90 | assert(f.getGeometry.isInstanceOf[MultiPoint])
91 | val point = f.getGeometry.asInstanceOf[MultiPoint]
92 | assert(point.getBbox != null)
93 | assert(point.getBbox.toSeq == Seq(-8.311419016226296, 53.894485921596285, -8.311419016226296, 53.894485921596285))
94 | }
95 |
96 | "take care of LineString bbox property" in {
97 | val geoJSON = """{"type": "FeatureCollection", "features": [{"type": "Feature", "id": 1, "geometry": {"type": "LineString", "coordinates": [[0.0,0.0],[1.0,1.0]], "bbox": [0.0,0.0,1.0,1.0] }, "properties": {"FID": 335, "PLAN_REF": "151", "APP_TYPE": "RETENTION", "LOCATION": "Knockglass, Ballinameen, Co. Roscommon.", "REC_DATE": "05/01/2015", "DESCRIPT": "Of entrance to existing forest plantation for extraction of timber at various times at ", "APPSTATUS": "Application Finalised", "DEC_DATE": "20/02/2015", "DECISION": "Granted (Conditional)", "APPE_DEC": "n/a", "APPE_DAT": "n/a", "MOREINFO": "http://www.eplanning.ie/roscommoneplan/FileRefDetails.aspx?file_number=151", "WGS_LONG": "-8.31141", "WGS_LAT": "53.89448"} }] }"""
98 | val json = GeoJSONFactory.create(geoJSON)
99 | assert(json.isInstanceOf[FeatureCollection])
100 | val fc = json.asInstanceOf[FeatureCollection]
101 | assert(fc.getFeatures.nonEmpty)
102 | val f = fc.getFeatures.head
103 | assert(f.getGeometry != null)
104 | assert(f.getGeometry.isInstanceOf[LineString])
105 | val point = f.getGeometry.asInstanceOf[LineString]
106 | assert(point.getBbox != null)
107 | assert(point.getBbox.toSeq == Seq(0.0, 0.0, 1.0, 1.0))
108 | }
109 |
110 | "take care of MultiLineString bbox property" in {
111 | val geoJSON = """{"type": "FeatureCollection", "features": [{"type": "Feature", "id": 1, "geometry": {"type": "MultiLineString", "coordinates": [[[0.0,0.0],[1.0,1.0]]], "bbox": [0.0,0.0,1.0,1.0] }, "properties": {"FID": 335, "PLAN_REF": "151", "APP_TYPE": "RETENTION", "LOCATION": "Knockglass, Ballinameen, Co. Roscommon.", "REC_DATE": "05/01/2015", "DESCRIPT": "Of entrance to existing forest plantation for extraction of timber at various times at ", "APPSTATUS": "Application Finalised", "DEC_DATE": "20/02/2015", "DECISION": "Granted (Conditional)", "APPE_DEC": "n/a", "APPE_DAT": "n/a", "MOREINFO": "http://www.eplanning.ie/roscommoneplan/FileRefDetails.aspx?file_number=151", "WGS_LONG": "-8.31141", "WGS_LAT": "53.89448"} }] }"""
112 | val json = GeoJSONFactory.create(geoJSON)
113 | assert(json.isInstanceOf[FeatureCollection])
114 | val fc = json.asInstanceOf[FeatureCollection]
115 | assert(fc.getFeatures.nonEmpty)
116 | val f = fc.getFeatures.head
117 | assert(f.getGeometry != null)
118 | assert(f.getGeometry.isInstanceOf[MultiLineString])
119 | val point = f.getGeometry.asInstanceOf[MultiLineString]
120 | assert(point.getBbox != null)
121 | assert(point.getBbox.toSeq == Seq(0.0, 0.0, 1.0, 1.0))
122 | }
123 |
124 | "take care of Polygon bbox property" in {
125 | val geoJSON = """{"type": "FeatureCollection", "features": [{"type": "Feature", "id": 1, "geometry": {"type": "Polygon", "coordinates": [[[0.0,0.0],[0.0,1.0],[1.0,1.0],[0.0,1.0],[0.0,0.0]]], "bbox": [0.0,0.0,1.0,1.0] }, "properties": {"FID": 335, "PLAN_REF": "151", "APP_TYPE": "RETENTION", "LOCATION": "Knockglass, Ballinameen, Co. Roscommon.", "REC_DATE": "05/01/2015", "DESCRIPT": "Of entrance to existing forest plantation for extraction of timber at various times at ", "APPSTATUS": "Application Finalised", "DEC_DATE": "20/02/2015", "DECISION": "Granted (Conditional)", "APPE_DEC": "n/a", "APPE_DAT": "n/a", "MOREINFO": "http://www.eplanning.ie/roscommoneplan/FileRefDetails.aspx?file_number=151", "WGS_LONG": "-8.31141", "WGS_LAT": "53.89448"} }] }"""
126 | val json = GeoJSONFactory.create(geoJSON)
127 | assert(json.isInstanceOf[FeatureCollection])
128 | val fc = json.asInstanceOf[FeatureCollection]
129 | assert(fc.getFeatures.nonEmpty)
130 | val f = fc.getFeatures.head
131 | assert(f.getGeometry != null)
132 | assert(f.getGeometry.isInstanceOf[Polygon])
133 | val point = f.getGeometry.asInstanceOf[Polygon]
134 | assert(point.getBbox != null)
135 | assert(point.getBbox.toSeq == Seq(0.0, 0.0, 1.0, 1.0))
136 | }
137 |
138 | "take care of MultiPolygon bbox property" in {
139 | val geoJSON = """{"type": "FeatureCollection", "features": [{"type": "Feature", "id": 1, "geometry": {"type": "MultiPolygon", "coordinates": [[[[0.0,0.0],[0.0,1.0],[1.0,1.0],[0.0,1.0],[0.0,0.0]]]], "bbox": [0.0,0.0,1.0,1.0] }, "properties": {"FID": 335, "PLAN_REF": "151", "APP_TYPE": "RETENTION", "LOCATION": "Knockglass, Ballinameen, Co. Roscommon.", "REC_DATE": "05/01/2015", "DESCRIPT": "Of entrance to existing forest plantation for extraction of timber at various times at ", "APPSTATUS": "Application Finalised", "DEC_DATE": "20/02/2015", "DECISION": "Granted (Conditional)", "APPE_DEC": "n/a", "APPE_DAT": "n/a", "MOREINFO": "http://www.eplanning.ie/roscommoneplan/FileRefDetails.aspx?file_number=151", "WGS_LONG": "-8.31141", "WGS_LAT": "53.89448"} }] }"""
140 | val json = GeoJSONFactory.create(geoJSON)
141 | assert(json.isInstanceOf[FeatureCollection])
142 | val fc = json.asInstanceOf[FeatureCollection]
143 | assert(fc.getFeatures.nonEmpty)
144 | val f = fc.getFeatures.head
145 | assert(f.getGeometry != null)
146 | assert(f.getGeometry.isInstanceOf[MultiPolygon])
147 | val point = f.getGeometry.asInstanceOf[MultiPolygon]
148 | assert(point.getBbox != null)
149 | assert(point.getBbox.toSeq == Seq(0.0, 0.0, 1.0, 1.0))
150 | }
151 |
152 | }
153 |
154 | "parsing XYZ GeoJSON to object" should {
155 | val geometry = new Point(Array(1, 1, 1))
156 | val properties = new HashMap[String, Object]()
157 | properties.put("test", 1.asInstanceOf[Object])
158 | val feature = new Feature(geometry, properties)
159 |
160 | "be identical to programmatically created Feature" in {
161 | val expected = """{"type":"Feature","geometry":{"type":"Point","coordinates":[1.0,1.0,1.0]},"properties":{"test":1}}"""
162 |
163 | val json = feature.toString
164 | assert(expected == json)
165 |
166 | val geoJSON = GeoJSONFactory.create(json)
167 | assert(expected == geoJSON.toString)
168 | }
169 |
170 | "be identical to programmatically created Feature with id" in {
171 | val feature = new Feature(1, geometry, properties)
172 |
173 | val expected = """{"type":"Feature","id":1,"geometry":{"type":"Point","coordinates":[1.0,1.0,1.0]},"properties":{"test":1}}"""
174 |
175 | val json = feature.toString
176 | assert(expected == json)
177 |
178 | val geoJSON = GeoJSONFactory.create(json)
179 |
180 | assert(expected == geoJSON.toString)
181 | }
182 |
183 | "be identical to programmatically created Feature without geometry" in {
184 | val feature = new Feature(null, properties)
185 |
186 | val expected = """{"type":"Feature","geometry":null,"properties":{"test":1}}"""
187 |
188 | val json = feature.toString
189 | assert(expected == json)
190 |
191 | val geoJSON = GeoJSONFactory.create(json)
192 |
193 | assert(expected == geoJSON.toString)
194 | }
195 |
196 | "be identical to programmatically created FeatureCollection" in {
197 | val expected = """{"type":"FeatureCollection","features":[{"type":"Feature","geometry":{"type":"Point","coordinates":[1.0,1.0,1.0]},"properties":{"test":1}},{"type":"Feature","geometry":{"type":"Point","coordinates":[1.0,1.0,1.0]},"properties":{"test":1}}]}"""
198 |
199 | val fc = new FeatureCollection(Array(feature, feature))
200 | assert(expected == fc.toString)
201 | }
202 |
203 | "take care of bbox property" in {
204 | val geoJSON = """{"type": "FeatureCollection", "features": [{"type": "Feature", "id": 1, "geometry": {"type": "Point", "coordinates": [-8.311419016226296, 53.894485921596285], "bbox": [-8.311419016226296, 53.894485921596285, -8.311419016226296, 53.894485921596285] }, "properties": {"FID": 335, "PLAN_REF": "151", "APP_TYPE": "RETENTION", "LOCATION": "Knockglass, Ballinameen, Co. Roscommon.", "REC_DATE": "05/01/2015", "DESCRIPT": "Of entrance to existing forest plantation for extraction of timber at various times at ", "APPSTATUS": "Application Finalised", "DEC_DATE": "20/02/2015", "DECISION": "Granted (Conditional)", "APPE_DEC": "n/a", "APPE_DAT": "n/a", "MOREINFO": "http://www.eplanning.ie/roscommoneplan/FileRefDetails.aspx?file_number=151", "WGS_LONG": "-8.31141", "WGS_LAT": "53.89448"} }] }"""
205 | val json = GeoJSONFactory.create(geoJSON)
206 | assert(json.isInstanceOf[FeatureCollection])
207 | val fc = json.asInstanceOf[FeatureCollection]
208 | assert(fc.getFeatures.nonEmpty)
209 | val f = fc.getFeatures.head
210 | assert(f.getGeometry != null)
211 | assert(f.getGeometry.isInstanceOf[Point])
212 | val point = f.getGeometry.asInstanceOf[Point]
213 | assert(point.getBbox != null)
214 | assert(point.getBbox.toSeq == Seq(-8.311419016226296, 53.894485921596285, -8.311419016226296, 53.894485921596285))
215 | }
216 |
217 | "take care of MultiPoint bbox property" in {
218 | val geoJSON = """{"type": "FeatureCollection", "features": [{"type": "Feature", "id": 1, "geometry": {"type": "MultiPoint", "coordinates": [[-8.311419016226296, 53.894485921596285]], "bbox": [-8.311419016226296, 53.894485921596285, -8.311419016226296, 53.894485921596285] }, "properties": {"FID": 335, "PLAN_REF": "151", "APP_TYPE": "RETENTION", "LOCATION": "Knockglass, Ballinameen, Co. Roscommon.", "REC_DATE": "05/01/2015", "DESCRIPT": "Of entrance to existing forest plantation for extraction of timber at various times at ", "APPSTATUS": "Application Finalised", "DEC_DATE": "20/02/2015", "DECISION": "Granted (Conditional)", "APPE_DEC": "n/a", "APPE_DAT": "n/a", "MOREINFO": "http://www.eplanning.ie/roscommoneplan/FileRefDetails.aspx?file_number=151", "WGS_LONG": "-8.31141", "WGS_LAT": "53.89448"} }] }"""
219 | val json = GeoJSONFactory.create(geoJSON)
220 | assert(json.isInstanceOf[FeatureCollection])
221 | val fc = json.asInstanceOf[FeatureCollection]
222 | assert(fc.getFeatures.nonEmpty)
223 | val f = fc.getFeatures.head
224 | assert(f.getGeometry != null)
225 | assert(f.getGeometry.isInstanceOf[MultiPoint])
226 | val point = f.getGeometry.asInstanceOf[MultiPoint]
227 | assert(point.getBbox != null)
228 | assert(point.getBbox.toSeq == Seq(-8.311419016226296, 53.894485921596285, -8.311419016226296, 53.894485921596285))
229 | }
230 |
231 | "take care of LineString bbox property" in {
232 | val geoJSON = """{"type": "FeatureCollection", "features": [{"type": "Feature", "id": 1, "geometry": {"type": "LineString", "coordinates": [[0.0,0.0],[1.0,1.0]], "bbox": [0.0,0.0,1.0,1.0] }, "properties": {"FID": 335, "PLAN_REF": "151", "APP_TYPE": "RETENTION", "LOCATION": "Knockglass, Ballinameen, Co. Roscommon.", "REC_DATE": "05/01/2015", "DESCRIPT": "Of entrance to existing forest plantation for extraction of timber at various times at ", "APPSTATUS": "Application Finalised", "DEC_DATE": "20/02/2015", "DECISION": "Granted (Conditional)", "APPE_DEC": "n/a", "APPE_DAT": "n/a", "MOREINFO": "http://www.eplanning.ie/roscommoneplan/FileRefDetails.aspx?file_number=151", "WGS_LONG": "-8.31141", "WGS_LAT": "53.89448"} }] }"""
233 | val json = GeoJSONFactory.create(geoJSON)
234 | assert(json.isInstanceOf[FeatureCollection])
235 | val fc = json.asInstanceOf[FeatureCollection]
236 | assert(fc.getFeatures.nonEmpty)
237 | val f = fc.getFeatures.head
238 | assert(f.getGeometry != null)
239 | assert(f.getGeometry.isInstanceOf[LineString])
240 | val point = f.getGeometry.asInstanceOf[LineString]
241 | assert(point.getBbox != null)
242 | assert(point.getBbox.toSeq == Seq(0.0, 0.0, 1.0, 1.0))
243 | }
244 |
245 | "take care of MultiLineString bbox property" in {
246 | val geoJSON = """{"type": "FeatureCollection", "features": [{"type": "Feature", "id": 1, "geometry": {"type": "MultiLineString", "coordinates": [[[0.0,0.0],[1.0,1.0]]], "bbox": [0.0,0.0,1.0,1.0] }, "properties": {"FID": 335, "PLAN_REF": "151", "APP_TYPE": "RETENTION", "LOCATION": "Knockglass, Ballinameen, Co. Roscommon.", "REC_DATE": "05/01/2015", "DESCRIPT": "Of entrance to existing forest plantation for extraction of timber at various times at ", "APPSTATUS": "Application Finalised", "DEC_DATE": "20/02/2015", "DECISION": "Granted (Conditional)", "APPE_DEC": "n/a", "APPE_DAT": "n/a", "MOREINFO": "http://www.eplanning.ie/roscommoneplan/FileRefDetails.aspx?file_number=151", "WGS_LONG": "-8.31141", "WGS_LAT": "53.89448"} }] }"""
247 | val json = GeoJSONFactory.create(geoJSON)
248 | assert(json.isInstanceOf[FeatureCollection])
249 | val fc = json.asInstanceOf[FeatureCollection]
250 | assert(fc.getFeatures.nonEmpty)
251 | val f = fc.getFeatures.head
252 | assert(f.getGeometry != null)
253 | assert(f.getGeometry.isInstanceOf[MultiLineString])
254 | val point = f.getGeometry.asInstanceOf[MultiLineString]
255 | assert(point.getBbox != null)
256 | assert(point.getBbox.toSeq == Seq(0.0, 0.0, 1.0, 1.0))
257 | }
258 |
259 | "take care of Polygon bbox property" in {
260 | val geoJSON = """{"type": "FeatureCollection", "features": [{"type": "Feature", "id": 1, "geometry": {"type": "Polygon", "coordinates": [[[0.0,0.0],[0.0,1.0],[1.0,1.0],[0.0,1.0],[0.0,0.0]]], "bbox": [0.0,0.0,1.0,1.0] }, "properties": {"FID": 335, "PLAN_REF": "151", "APP_TYPE": "RETENTION", "LOCATION": "Knockglass, Ballinameen, Co. Roscommon.", "REC_DATE": "05/01/2015", "DESCRIPT": "Of entrance to existing forest plantation for extraction of timber at various times at ", "APPSTATUS": "Application Finalised", "DEC_DATE": "20/02/2015", "DECISION": "Granted (Conditional)", "APPE_DEC": "n/a", "APPE_DAT": "n/a", "MOREINFO": "http://www.eplanning.ie/roscommoneplan/FileRefDetails.aspx?file_number=151", "WGS_LONG": "-8.31141", "WGS_LAT": "53.89448"} }] }"""
261 | val json = GeoJSONFactory.create(geoJSON)
262 | assert(json.isInstanceOf[FeatureCollection])
263 | val fc = json.asInstanceOf[FeatureCollection]
264 | assert(fc.getFeatures.nonEmpty)
265 | val f = fc.getFeatures.head
266 | assert(f.getGeometry != null)
267 | assert(f.getGeometry.isInstanceOf[Polygon])
268 | val point = f.getGeometry.asInstanceOf[Polygon]
269 | assert(point.getBbox != null)
270 | assert(point.getBbox.toSeq == Seq(0.0, 0.0, 1.0, 1.0))
271 | }
272 |
273 | "take care of MultiPolygon bbox property" in {
274 | val geoJSON = """{"type": "FeatureCollection", "features": [{"type": "Feature", "id": 1, "geometry": {"type": "MultiPolygon", "coordinates": [[[[0.0,0.0],[0.0,1.0],[1.0,1.0],[0.0,1.0],[0.0,0.0]]]], "bbox": [0.0,0.0,1.0,1.0] }, "properties": {"FID": 335, "PLAN_REF": "151", "APP_TYPE": "RETENTION", "LOCATION": "Knockglass, Ballinameen, Co. Roscommon.", "REC_DATE": "05/01/2015", "DESCRIPT": "Of entrance to existing forest plantation for extraction of timber at various times at ", "APPSTATUS": "Application Finalised", "DEC_DATE": "20/02/2015", "DECISION": "Granted (Conditional)", "APPE_DEC": "n/a", "APPE_DAT": "n/a", "MOREINFO": "http://www.eplanning.ie/roscommoneplan/FileRefDetails.aspx?file_number=151", "WGS_LONG": "-8.31141", "WGS_LAT": "53.89448"} }] }"""
275 | val json = GeoJSONFactory.create(geoJSON)
276 | assert(json.isInstanceOf[FeatureCollection])
277 | val fc = json.asInstanceOf[FeatureCollection]
278 | assert(fc.getFeatures.nonEmpty)
279 | val f = fc.getFeatures.head
280 | assert(f.getGeometry != null)
281 | assert(f.getGeometry.isInstanceOf[MultiPolygon])
282 | val point = f.getGeometry.asInstanceOf[MultiPolygon]
283 | assert(point.getBbox != null)
284 | assert(point.getBbox.toSeq == Seq(0.0, 0.0, 1.0, 1.0))
285 | }
286 |
287 | }
288 |
289 | }
290 |
291 | }
292 |
--------------------------------------------------------------------------------
/src/test/scala/org/wololo/jts2geojson/GeoJSONReaderSpec.scala:
--------------------------------------------------------------------------------
1 | package org.wololo.jts2geojson
2 |
3 | import org.locationtech.jts.geom.Coordinate
4 | import org.locationtech.jts.geom.GeometryFactory
5 | import org.locationtech.jts.geom.PrecisionModel
6 |
7 | import org.scalatest.wordspec.AnyWordSpec
8 |
9 | class GeoJSONReaderSpec extends AnyWordSpec {
10 | "GeoJSONReader" when {
11 | "reading JTS object from GeoJSON" should {
12 |
13 | val reader = new GeoJSONReader()
14 | val writer = new GeoJSONWriter()
15 | val factory = new GeometryFactory()
16 | val srid = 25832
17 | val factorySrid = new GeometryFactory(new PrecisionModel(), srid)
18 |
19 | val coordArray = Array(
20 | new Coordinate(1, 1),
21 | new Coordinate(1, 2),
22 | new Coordinate(2, 2),
23 | new Coordinate(1, 1))
24 |
25 | "expected result for Point" in {
26 | val expected = factory.createPoint(new Coordinate(1, 1));
27 | val expectedSrid = factorySrid.createPoint(new Coordinate(1, 1));
28 | val json = """{"type":"Point","coordinates":[1.0,1.0]}"""
29 |
30 | var geometry = reader.read(json)
31 | assert(expected === geometry)
32 | assert(0 === geometry.getSRID())
33 |
34 | geometry = reader.read(json, factorySrid)
35 | assert(expectedSrid === geometry)
36 | assert(srid === geometry.getSRID())
37 | }
38 |
39 | "expected result for MultiPoint" in {
40 | val expected = factory.createMultiPointFromCoords(coordArray)
41 | val expectedSrid = factorySrid.createMultiPointFromCoords(coordArray)
42 | val json = """{"type":"MultiPoint","coordinates":[[1.0,1.0],[1.0,2.0],[2.0,2.0],[1.0,1.0]]}"""
43 |
44 | var geometry = reader.read(json)
45 | assert(expected === geometry)
46 | assert(0 === geometry.getSRID())
47 |
48 | geometry = reader.read(json, factorySrid)
49 | assert(expectedSrid === geometry)
50 | assert(srid === geometry.getSRID())
51 | }
52 | }
53 |
54 | "reading XYZ JTS object from GeoJSON" should {
55 |
56 | val reader = new GeoJSONReader()
57 | val writer = new GeoJSONWriter()
58 | val factory = new GeometryFactory()
59 | val srid = 25832
60 | val factorySrid = new GeometryFactory(new PrecisionModel(), srid)
61 |
62 | val coordArray = Array(
63 | new Coordinate(1, 1, 1),
64 | new Coordinate(1, 2, 1),
65 | new Coordinate(2, 2, 2),
66 | new Coordinate(1, 1, 1))
67 |
68 | "expected result for Point" in {
69 | val expected = factory.createPoint(new Coordinate(1, 1, 1));
70 | val expectedSrid = factorySrid.createPoint(new Coordinate(1, 1, 1));
71 | val json = """{"type":"Point","coordinates":[1.0,1.0,1.0]}"""
72 |
73 | var geometry = reader.read(json)
74 | assert(expected === geometry)
75 | assert(0 === geometry.getSRID())
76 |
77 | geometry = reader.read(json, factorySrid)
78 | assert(expectedSrid === geometry)
79 | assert(srid === geometry.getSRID())
80 | }
81 |
82 | "expected result for MultiPoint" in {
83 | val expected = factory.createMultiPointFromCoords(coordArray)
84 | val expectedSrid = factorySrid.createMultiPointFromCoords(coordArray)
85 | val json = """{"type":"MultiPoint","coordinates":[[1.0,1.0,1.0],[1.0,2.0,1.0],[2.0,2.0,2.0],[1.0,1.0,1.0]]}"""
86 |
87 | var geometry = reader.read(json)
88 | assert(expected === geometry)
89 | assert(0 === geometry.getSRID())
90 |
91 | geometry = reader.read(json, factorySrid)
92 | assert(expectedSrid === geometry)
93 | assert(srid === geometry.getSRID())
94 | }
95 | }
96 |
97 | }
98 | }
--------------------------------------------------------------------------------
/src/test/scala/org/wololo/jts2geojson/GeoJSONWriterSpec.scala:
--------------------------------------------------------------------------------
1 | package org.wololo.jts2geojson
2 |
3 | import org.scalatest.wordspec.AnyWordSpec
4 | import org.locationtech.jts.geom.GeometryFactory
5 | import org.locationtech.jts.geom.Coordinate
6 | import org.wololo.geojson.Feature
7 | import org.wololo.geojson.FeatureCollection
8 |
9 | class GeoJSONWriterSpec extends AnyWordSpec {
10 | "GeoJSONWriter" when {
11 | "writing GeoJSON from JTS object" should {
12 |
13 | val reader = new GeoJSONReader()
14 | val writer = new GeoJSONWriter()
15 | val factory = new GeometryFactory()
16 |
17 | val point = factory.createPoint(new Coordinate(1, 1))
18 | val lineString = factory.createLineString(Array(
19 | new Coordinate(1, 1),
20 | new Coordinate(1, 2),
21 | new Coordinate(2, 2),
22 | new Coordinate(1, 1)))
23 |
24 | val polygon = factory.createPolygon(lineString.getCoordinates())
25 |
26 | "expected result for Point" in {
27 | val expected = """{"type":"Point","coordinates":[1.0,1.0]}"""
28 |
29 | val json = writer.write(point)
30 | assert(expected === json.toString)
31 |
32 | val geometry = reader.read(json)
33 | assert("POINT (1 1)" === geometry.toString)
34 | }
35 |
36 | "expected result for LineString" in {
37 | val json = writer.write(lineString)
38 | assert("""{"type":"LineString","coordinates":[[1.0,1.0],[1.0,2.0],[2.0,2.0],[1.0,1.0]]}""" === json.toString)
39 | }
40 |
41 | "expected result for LineString with id" in {
42 | val json = writer.write(lineString)
43 | assert("""{"type":"LineString","coordinates":[[1.0,1.0],[1.0,2.0],[2.0,2.0],[1.0,1.0]]}""" === json.toString)
44 | }
45 |
46 | "expected result for LinearString with id" in {
47 | val ring = factory.createLinearRing(lineString.getCoordinates)
48 | val json = writer.write(ring)
49 | assert("""{"type":"LineString","coordinates":[[1.0,1.0],[1.0,2.0],[2.0,2.0],[1.0,1.0]]}""" === json.toString)
50 | }
51 |
52 | "expected result for Polygon" in {
53 | val json = writer.write(polygon);
54 | assert("""{"type":"Polygon","coordinates":[[[1.0,1.0],[1.0,2.0],[2.0,2.0],[1.0,1.0]]]}""" === json.toString)
55 | }
56 |
57 | "expected result for MultiPoint" in {
58 | val multiPoint = factory.createMultiPointFromCoords(lineString.getCoordinates())
59 | val json = writer.write(multiPoint)
60 | assert("""{"type":"MultiPoint","coordinates":[[1.0,1.0],[1.0,2.0],[2.0,2.0],[1.0,1.0]]}""" === json.toString)
61 | }
62 |
63 | "expected result for MultiLineString" in {
64 | val multiLineString = factory.createMultiLineString(Array(lineString, lineString))
65 | val json = writer.write(multiLineString)
66 | assert("""{"type":"MultiLineString","coordinates":[[[1.0,1.0],[1.0,2.0],[2.0,2.0],[1.0,1.0]],[[1.0,1.0],[1.0,2.0],[2.0,2.0],[1.0,1.0]]]}""" === json.toString)
67 | }
68 |
69 | "expected result for MultiPolygon" in {
70 | val multiPolygon = factory.createMultiPolygon(Array(polygon, polygon))
71 | val json = writer.write(multiPolygon)
72 | assert("""{"type":"MultiPolygon","coordinates":[[[[1.0,1.0],[1.0,2.0],[2.0,2.0],[1.0,1.0]]],[[[1.0,1.0],[1.0,2.0],[2.0,2.0],[1.0,1.0]]]]}""" === json.toString)
73 | }
74 |
75 | "expected result for FeatureCollection" in {
76 | val json = writer.write(point)
77 | val feature1 = new Feature(json, null)
78 | val feature2 = new Feature(json, null)
79 | val featureCollection = new FeatureCollection(Array(feature1, feature2))
80 | assert("""{"type":"FeatureCollection","features":[{"type":"Feature","geometry":{"type":"Point","coordinates":[1.0,1.0]},"properties":null},{"type":"Feature","geometry":{"type":"Point","coordinates":[1.0,1.0]},"properties":null}]}""" === featureCollection.toString)
81 | }
82 | }
83 |
84 | "writing XYZ GeoJSON from JTS object" should {
85 |
86 | val reader = new GeoJSONReader()
87 | val writer = new GeoJSONWriter()
88 | val factory = new GeometryFactory()
89 |
90 | val point = factory.createPoint(new Coordinate(1, 1, 1))
91 | val lineString = factory.createLineString(Array(
92 | new Coordinate(1, 1, 1),
93 | new Coordinate(1, 2, 1),
94 | new Coordinate(2, 2, 2),
95 | new Coordinate(1, 1, 1)))
96 | val polygon = factory.createPolygon(lineString.getCoordinates())
97 |
98 | "expected result for Point" in {
99 | val expected = """{"type":"Point","coordinates":[1.0,1.0,1.0]}"""
100 |
101 | val json = writer.write(point)
102 | assert(expected === json.toString)
103 |
104 | val geometry = reader.read(json)
105 | assert("POINT (1 1)" === geometry.toString)
106 | }
107 |
108 | "expected result for LineString" in {
109 | val json = writer.write(lineString)
110 | assert("""{"type":"LineString","coordinates":[[1.0,1.0,1.0],[1.0,2.0,1.0],[2.0,2.0,2.0],[1.0,1.0,1.0]]}""" === json.toString)
111 | }
112 |
113 | "expected result for LineString with id" in {
114 | val json = writer.write(lineString)
115 | assert("""{"type":"LineString","coordinates":[[1.0,1.0,1.0],[1.0,2.0,1.0],[2.0,2.0,2.0],[1.0,1.0,1.0]]}""" === json.toString)
116 | }
117 |
118 | "expected result for Polygon" in {
119 | val json = writer.write(polygon);
120 | assert("""{"type":"Polygon","coordinates":[[[1.0,1.0,1.0],[1.0,2.0,1.0],[2.0,2.0,2.0],[1.0,1.0,1.0]]]}""" === json.toString)
121 | }
122 |
123 | "expected result for MultiPoint" in {
124 | val multiPoint = factory.createMultiPointFromCoords(lineString.getCoordinates())
125 | val json = writer.write(multiPoint)
126 | assert("""{"type":"MultiPoint","coordinates":[[1.0,1.0,1.0],[1.0,2.0,1.0],[2.0,2.0,2.0],[1.0,1.0,1.0]]}""" === json.toString)
127 | }
128 |
129 | "expected result for MultiLineString" in {
130 | val multiLineString = factory.createMultiLineString(Array(lineString, lineString))
131 | val json = writer.write(multiLineString)
132 | assert("""{"type":"MultiLineString","coordinates":[[[1.0,1.0,1.0],[1.0,2.0,1.0],[2.0,2.0,2.0],[1.0,1.0,1.0]],[[1.0,1.0,1.0],[1.0,2.0,1.0],[2.0,2.0,2.0],[1.0,1.0,1.0]]]}""" === json.toString)
133 | }
134 |
135 | "expected result for MultiPolygon" in {
136 | val multiPolygon = factory.createMultiPolygon(Array(polygon, polygon))
137 | val json = writer.write(multiPolygon)
138 | assert("""{"type":"MultiPolygon","coordinates":[[[[1.0,1.0,1.0],[1.0,2.0,1.0],[2.0,2.0,2.0],[1.0,1.0,1.0]]],[[[1.0,1.0,1.0],[1.0,2.0,1.0],[2.0,2.0,2.0],[1.0,1.0,1.0]]]]}""" === json.toString)
139 | }
140 |
141 | "expected result for FeatureCollection" in {
142 | val json = writer.write(point)
143 | val feature1 = new Feature(json, null)
144 | val feature2 = new Feature(json, null)
145 | val featureCollection = new FeatureCollection(Array(feature1, feature2))
146 | assert("""{"type":"FeatureCollection","features":[{"type":"Feature","geometry":{"type":"Point","coordinates":[1.0,1.0,1.0]},"properties":null},{"type":"Feature","geometry":{"type":"Point","coordinates":[1.0,1.0,1.0]},"properties":null}]}""" === featureCollection.toString)
147 | }
148 | }
149 |
150 | }
151 | }
152 |
--------------------------------------------------------------------------------