diff --git a/catalog/core/catalog-core-commons/src/test/java/ddf/util/AntimeridianTest.java b/catalog/core/catalog-core-commons/src/test/java/ddf/util/AntimeridianTest.java index d4d7b48ea4b2..ce11ae4bb298 100644 --- a/catalog/core/catalog-core-commons/src/test/java/ddf/util/AntimeridianTest.java +++ b/catalog/core/catalog-core-commons/src/test/java/ddf/util/AntimeridianTest.java @@ -19,6 +19,7 @@ import java.util.List; import org.junit.Test; +import org.locationtech.jts.geom.Coordinate; import org.locationtech.jts.geom.Geometry; import org.locationtech.jts.io.ParseException; import org.locationtech.jts.io.WKTReader; @@ -84,4 +85,48 @@ public void testNonCrossingShapesAreNotSplit() { String outputWkt = Antimeridian.unwrapAndSplitWkt(inputWkt); assertThat(outputWkt, is(inputWkt)); } + + @Test + public void testAntimeridianCrossingIsSplitWithNegativeLongtitude() { + String originalWkt = + "POLYGON ((167.422137 -37.935528, -173.149957 -49.494589, -166.265735 -32.563561, -176.051446 -24.815088, 167.422137 -37.935528))"; + String expectedWkt = + "MULTIPOLYGON (((180 -27.949873104584977, 167.422137 -37.935528, 180 -45.419004894866745, 180 -27.949873104584977)), ((-180 -45.419004894866745, -173.149957 -49.494589, -166.265735 -32.563561, -176.051446 -24.815088, -180 -27.949873104584977, -180 -45.419004894866745)))"; + String actualWkt = Antimeridian.unwrapAndSplitWkt(originalWkt); + assertWktTopologicallyEqual(actualWkt, expectedWkt); + assertCoordinatesWithinBounds(actualWkt); + Geometry originalBounds = getBoundaryFromWkt(originalWkt); + Geometry updatedBounds = getBoundaryFromWkt(actualWkt); + assertThat(originalBounds.getArea(), is(updatedBounds.getArea())); + } + + @Test(expected = ParseException.class) + public void testInvalidWktFormatFailsToParse() throws ParseException { + String invalidWkt = + "MULTIPOLYGON (((180 10, 170 10, 170 -10, 180 -10, 180 10)), ((-180 -10, -170 -10, -170, 10, -180 10, -180 -10)))"; + WKT_READER.read(invalidWkt); + } + + private void assertCoordinatesWithinBounds(String wkt) { + Geometry geometry; + try { + geometry = WKT_READER.read(wkt); + } catch (ParseException e) { + throw new IllegalArgumentException("Unable to parse WKT", e); + } + for (Coordinate coordinate : geometry.getCoordinates()) { + assertThat(coordinate.x >= -180.0 && coordinate.x <= 180.0, is(true)); + assertThat(coordinate.y >= -90.0 && coordinate.y <= 90.0, is(true)); + } + } + + private void assertWktTopologicallyEqual(String actualWkt, String expectedWkt) { + try { + Geometry actual = WKT_READER.read(actualWkt); + Geometry expected = WKT_READER.read(expectedWkt); + assertThat(actual.equalsTopo(expected), is(true)); + } catch (ParseException e) { + throw new IllegalArgumentException("Unable to parse WKT", e); + } + } } diff --git a/catalog/spatial/wfs/1.1.0/spatial-wfs-v1_1_0-source/src/main/java/org/codice/ddf/spatial/ogc/wfs/v110/catalog/source/WfsFilterDelegate.java b/catalog/spatial/wfs/1.1.0/spatial-wfs-v1_1_0-source/src/main/java/org/codice/ddf/spatial/ogc/wfs/v110/catalog/source/WfsFilterDelegate.java index cc3395fc9da2..f2e4458f2dbd 100644 --- a/catalog/spatial/wfs/1.1.0/spatial-wfs-v1_1_0-source/src/main/java/org/codice/ddf/spatial/ogc/wfs/v110/catalog/source/WfsFilterDelegate.java +++ b/catalog/spatial/wfs/1.1.0/spatial-wfs-v1_1_0-source/src/main/java/org/codice/ddf/spatial/ogc/wfs/v110/catalog/source/WfsFilterDelegate.java @@ -1073,7 +1073,7 @@ private FilterType buildSingleGeospatialFilter( private JAXBElement createSpatialOpType( String operation, String propertyName, String wkt, Double distance) { - String adjustedWkt = Antimeridian.normalizeWkt(wkt); + String adjustedWkt = Antimeridian.unwrapAndSplitWkt(wkt); switch (SPATIAL_OPERATORS.valueOf(operation)) { case BBOX: return buildBBoxType(propertyName, adjustedWkt);