Skip to content

Commit 7d70a86

Browse files
christophstroblmp911de
authored andcommitted
DATAMONGO-1399 - Allow adding hole to GeoJSON Polygon.
We now allow creation of GeoJsonPolygon having an outer and multiple inner rings. Original pull request: #352.
1 parent 13a52b5 commit 7d70a86

File tree

2 files changed

+90
-2
lines changed

2 files changed

+90
-2
lines changed

spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/geo/GeoJsonPolygon.java

Lines changed: 50 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2015 the original author or authors.
2+
* Copyright 2015-2016 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -18,10 +18,12 @@
1818
import java.util.ArrayList;
1919
import java.util.Arrays;
2020
import java.util.Collections;
21+
import java.util.Iterator;
2122
import java.util.List;
2223

2324
import org.springframework.data.geo.Point;
2425
import org.springframework.data.geo.Polygon;
26+
import org.springframework.util.Assert;
2527

2628
/**
2729
* {@link GeoJson} representation of {@link Polygon}. Unlike {@link Polygon} the {@link GeoJsonPolygon} requires a
@@ -62,6 +64,53 @@ public GeoJsonPolygon(List<Point> points) {
6264
this.coordinates.add(new GeoJsonLineString(points));
6365
}
6466

67+
/**
68+
* Creates a new {@link GeoJsonPolygon} with an inner ring defined be the given {@link Point}s.
69+
*
70+
* @param first must not be {@literal null}.
71+
* @param second must not be {@literal null}.
72+
* @param third must not be {@literal null}.
73+
* @param fourth must not be {@literal null}.
74+
* @param others can be {@literal null}.
75+
* @return new {@link GeoJsonPolygon}.
76+
* @since 1.9
77+
*/
78+
public GeoJsonPolygon withInnerRing(Point first, Point second, Point third, Point fourth, final Point... others) {
79+
return withInnerRing(asList(first, second, third, fourth, others));
80+
}
81+
82+
/**
83+
* Creates a new {@link GeoJsonPolygon} with an inner ring defined be the given {@link List} of {@link Point}s.
84+
*
85+
* @param points must not be {@literal null}.
86+
* @return new {@link GeoJsonPolygon}.
87+
*/
88+
public GeoJsonPolygon withInnerRing(List<Point> points) {
89+
return withInnerRing(new GeoJsonLineString(points));
90+
}
91+
92+
/**
93+
* Creates a new {@link GeoJsonPolygon} with an inner ring defined be the given {@link GeoJsonLineString}.
94+
*
95+
* @param lineString must not be {@literal null}.
96+
* @return new {@link GeoJsonPolygon}.
97+
* @since 1.9
98+
*/
99+
public GeoJsonPolygon withInnerRing(GeoJsonLineString lineString) {
100+
101+
Assert.notNull(lineString, "LineString must not be null!");
102+
103+
Iterator<GeoJsonLineString> it = this.coordinates.iterator();
104+
GeoJsonPolygon polygon = new GeoJsonPolygon(it.next().getCoordinates());
105+
106+
while (it.hasNext()) {
107+
polygon.coordinates.add(it.next());
108+
}
109+
110+
polygon.coordinates.add(lineString);
111+
return polygon;
112+
}
113+
65114
/*
66115
* (non-Javadoc)
67116
* @see org.springframework.data.mongodb.core.geo.GeoJson#getType()

spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/GeoJsonConverterUnitTests.java

Lines changed: 40 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2015 the original author or authors.
2+
* Copyright 2015-2016 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -73,11 +73,18 @@ public class GeoJsonConverterUnitTests {
7373
static final Point POINT_2 = new Point(100, 100);
7474
static final Point POINT_3 = new Point(0, 100);
7575

76+
static final Point INNER_POINT_0 = new Point(10, 10);
77+
static final Point INNER_POINT_1 = new Point(90, 10);
78+
static final Point INNER_POINT_2 = new Point(90, 90);
79+
static final Point INNER_POINT_3 = new Point(10, 90);
80+
7681
static final GeoJsonMultiPoint MULTI_POINT = new GeoJsonMultiPoint(POINT_0, POINT_2, POINT_3);
7782
static final GeoJsonLineString LINE_STRING = new GeoJsonLineString(POINT_0, POINT_1, POINT_2);
7883
@SuppressWarnings("unchecked") static final GeoJsonMultiLineString MULTI_LINE_STRING = new GeoJsonMultiLineString(
7984
Arrays.asList(POINT_0, POINT_1, POINT_2), Arrays.asList(POINT_3, POINT_0));
8085
static final GeoJsonPolygon POLYGON = new GeoJsonPolygon(POINT_0, POINT_1, POINT_2, POINT_3, POINT_0);
86+
static final GeoJsonPolygon POLYGON_WITH_2_RINGS = POLYGON.withInnerRing(INNER_POINT_0, INNER_POINT_1, INNER_POINT_2,
87+
INNER_POINT_3, INNER_POINT_0);
8188
static final GeoJsonMultiPolygon MULTI_POLYGON = new GeoJsonMultiPolygon(Arrays.asList(POLYGON));
8289
static final GeoJsonGeometryCollection GEOMETRY_COLLECTION = new GeoJsonGeometryCollection(
8390
Arrays.<GeoJson<?>> asList(SINGLE_POINT, POLYGON));
@@ -114,12 +121,28 @@ public class GeoJsonConverterUnitTests {
114121
.add(new BasicDbListBuilder().add(POINT_3.getX()).add(POINT_3.getY()).get()) //
115122
.add(new BasicDbListBuilder().add(POINT_0.getX()).add(POINT_0.getY()).get()) //
116123
.get();
124+
125+
static final BasicDBList POLYGON_INNER_CORDS = new BasicDbListBuilder() //
126+
.add(new BasicDbListBuilder().add(INNER_POINT_0.getX()).add(INNER_POINT_0.getY()).get()) //
127+
.add(new BasicDbListBuilder().add(INNER_POINT_1.getX()).add(INNER_POINT_1.getY()).get()) //
128+
.add(new BasicDbListBuilder().add(INNER_POINT_2.getX()).add(INNER_POINT_2.getY()).get()) //
129+
.add(new BasicDbListBuilder().add(INNER_POINT_3.getX()).add(INNER_POINT_3.getY()).get()) //
130+
.add(new BasicDbListBuilder().add(INNER_POINT_0.getX()).add(INNER_POINT_0.getY()).get()) //
131+
.get();
132+
117133
static final BasicDBList POLYGON_CORDS = new BasicDbListBuilder().add(POLYGON_OUTER_CORDS).get();
118134
static final DBObject POLYGON_DBO = new BasicDBObjectBuilder() //
119135
.add("type", "Polygon") //
120136
.add("coordinates", POLYGON_CORDS) //
121137
.get();
122138

139+
static final BasicDBList POLYGON_WITH_2_RINGS_CORDS = new BasicDbListBuilder().add(POLYGON_OUTER_CORDS)
140+
.add(POLYGON_INNER_CORDS).get();
141+
static final DBObject POLYGON_WITH_2_RINGS_DBO = new BasicDBObjectBuilder() //
142+
.add("type", "Polygon") //
143+
.add("coordinates", POLYGON_WITH_2_RINGS_CORDS) //
144+
.get();
145+
123146
// LineString
124147
static final BasicDBList LINE_STRING_CORDS_0 = new BasicDbListBuilder() //
125148
.add(new BasicDbListBuilder().add(POINT_0.getX()).add(POINT_0.getY()).get()) //
@@ -190,6 +213,14 @@ public void shouldThrowExceptionWhenTypeDoesNotMatchPolygon() {
190213
converter.convert(new BasicDBObject("type", "YouDontKonwMe"));
191214
}
192215

216+
/**
217+
* @see DATAMONGO-1399
218+
*/
219+
@Test
220+
public void shouldConvertDboWithMultipleRingsCorrectly() {
221+
assertThat(converter.convert(POLYGON_WITH_2_RINGS_DBO), equalTo(POLYGON_WITH_2_RINGS));
222+
}
223+
193224
}
194225

195226
/**
@@ -446,5 +477,13 @@ public void shouldConvertGeoJsonMultiPolygonCorrectly() {
446477
public void shouldConvertGeometryCollectionCorrectly() {
447478
assertThat(converter.convert(GEOMETRY_COLLECTION), equalTo(GEOMETRY_COLLECTION_DBO));
448479
}
480+
481+
/**
482+
* @see DATAMONGO-1399
483+
*/
484+
@Test
485+
public void shouldConvertGeoJsonPolygonWithMultipleRingsCorrectly() {
486+
assertThat(converter.convert(POLYGON_WITH_2_RINGS), equalTo(POLYGON_WITH_2_RINGS_DBO));
487+
}
449488
}
450489
}

0 commit comments

Comments
 (0)