/******************************************************************************* * Copyright (c) 2015 ElasticSearch and MITRE * All rights reserved. This program and the accompanying materials * are made available under the terms of the Apache License, Version 2.0 which * accompanies this distribution and is available at * http://www.apache.org/licenses/LICENSE-2.0.txt ******************************************************************************/ // A derivative of commit 14bc4dee08355048d6a94e33834b919a3999a06e // at https://github.com/chrismale/elasticsearch package org.locationtech.spatial4j.io; import com.carrotsearch.randomizedtesting.RandomizedTest; import org.locationtech.spatial4j.context.SpatialContext; import org.locationtech.spatial4j.shape.Point; import org.locationtech.spatial4j.shape.Rectangle; import org.locationtech.spatial4j.shape.Shape; import org.locationtech.spatial4j.shape.ShapeFactory; import org.junit.Test; import java.text.ParseException; import java.util.Collections; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNull; import static org.junit.Assert.fail; public class WktShapeParserTest extends RandomizedTest { final SpatialContext ctx; protected WktShapeParserTest(SpatialContext ctx) { this.ctx = ctx; } public WktShapeParserTest() { this(SpatialContext.GEO); } protected void assertParses(String wkt, Shape expected) throws ParseException { assertEquals(wkt(wkt), expected); } protected Shape wkt(String wkt) throws ParseException { return wkt(ctx, wkt); } protected Shape wkt(SpatialContext ctx, String wkt) throws ParseException { return ((WKTReader) ctx.getFormats().getWktReader()).parse(wkt); } protected void assertFails(String wkt) { try { wkt(wkt); fail("ParseException expected"); } catch (ParseException e) {//expected } } @Test public void testNoOp() throws ParseException { WKTReader wktShapeParser = (WKTReader) ctx.getFormats().getWktReader(); assertNull(wktShapeParser.parseIfSupported("")); assertNull(wktShapeParser.parseIfSupported(" ")); assertNull(wktShapeParser.parseIfSupported("BogusShape()")); assertNull(wktShapeParser.parseIfSupported("BogusShape")); } @Test public void testParsePoint() throws ParseException { assertParses("POINT (100 90)", ctx.makePoint(100, 90));//typical assertParses(" POINT (100 90) ", ctx.makePoint(100, 90));//trimmed assertParses("point (100 90)", ctx.makePoint(100, 90));//case indifferent assertParses("POINT ( 100 90 )", ctx.makePoint(100, 90));//inner spaces assertParses("POINT(100 90)", ctx.makePoint(100, 90)); assertParses("POINT (-45 90 )", ctx.makePoint(-45, 90)); Point expected = ctx.makePoint(-45.3, 80.4); assertParses("POINT (-45.3 80.4 )", expected); assertParses("POINT (-45.3 +80.4 )", expected); assertParses("POINT (-45.3 8.04e1 )", expected); assertParses("POINT EMPTY", ctx.makePoint(Double.NaN, Double.NaN)); //other dimensions are skipped assertParses("POINT (100 90 2)", ctx.makePoint(100, 90)); assertParses("POINT (100 90 2 3)", ctx.makePoint(100, 90)); assertParses("POINT ZM ( 100 90 )", ctx.makePoint(100, 90));//ignore dimension assertParses("POINT ZM ( 100 90 -3 -4)", ctx.makePoint(100, 90));//ignore dimension } @Test public void testParsePoint_invalidDefinitions() { assertFails("POINT 100 90"); assertFails("POINT (100 90"); assertFails("POINT (100, 90)"); assertFails("POINT 100 90)"); assertFails("POINT (100)"); assertFails("POINT (10f0 90)"); assertFails("POINT (EMPTY)"); assertFails("POINT (1 2), POINT (2 3)"); assertFails("POINT EMPTY (1 2)"); assertFails("POINT ZM EMPTY (1 2)"); assertFails("POINT ZM EMPTY 1"); } @Test public void testParseMultiPoint() throws ParseException { Shape s1 = ctx.getShapeFactory().multiPoint().pointXY(10, 40).build(); assertParses("MULTIPOINT (10 40)", s1); Shape s4 = ctx.getShapeFactory().multiPoint() .pointXY(10, 40).pointXY(40, 30).pointXY(20, 20).pointXY(30, 10).build(); assertParses("MULTIPOINT ((10 40), (40 30), (20 20), (30 10))", s4); assertParses("MULTIPOINT (10 40, 40 30, 20 20, 30 10)", s4); assertParses("MULTIPOINT Z EMPTY", ctx.getShapeFactory().multiPoint().build()); } @Test public void testParseEnvelope() throws ParseException { Rectangle r = ctx.makeRectangle(ctx.makePoint(10, 25), ctx.makePoint(30, 45)); assertParses(" ENVELOPE ( 10 , 30 , 45 , 25 ) ", r); assertParses("ENVELOPE(10,30,45,25) ", r); assertFails("ENVELOPE (10 30 45 25)"); } @Test public void testLineStringShape() throws ParseException { Shape ls = ctx.getShapeFactory().lineString().pointXY(1, 10).pointXY(2, 20).pointXY(3, 30).build(); assertParses("LINESTRING (1 10, 2 20, 3 30)", ls); assertParses("LINESTRING EMPTY", ctx.makeLineString(Collections.<Point>emptyList())); } @Test public void testMultiLineStringShape() throws ParseException { ShapeFactory.MultiLineStringBuilder builder = ctx.getShapeFactory().multiLineString(); builder.add(builder.lineString().pointXY(10, 10).pointXY(20, 20).pointXY(10, 40)); builder.add(builder.lineString().pointXY(40, 40).pointXY(30, 30).pointXY(40, 20).pointXY(30, 10)); Shape s = builder.build(); assertParses("MULTILINESTRING ((10 10, 20 20, 10 40),\n" + "(40 40, 30 30, 40 20, 30 10))", s); assertParses("MULTILINESTRING M EMPTY", ctx.getShapeFactory().multiLineString().build()); } @Test public void testGeomCollection() throws ParseException { ShapeFactory shapeFactory = ctx.getShapeFactory(); Shape s1 = shapeFactory.multiShape(Shape.class).add(shapeFactory.pointXY(1, 2)).build(); Shape s2 = shapeFactory.multiShape(Shape.class) .add(shapeFactory.rect(1, 2, 3, 4)).add(shapeFactory.pointXY(-1, -2)).build(); assertParses("GEOMETRYCOLLECTION (POINT (1 2) )", s1); assertParses("GEOMETRYCOLLECTION ( ENVELOPE(1,2,4,3), POINT(-1 -2)) ", s2); assertParses("GEOMETRYCOLLECTION EMPTY", shapeFactory.multiShape(Shape.class).build()); assertParses("GEOMETRYCOLLECTION ( POINT EMPTY )", shapeFactory.multiShape(Shape.class).add(shapeFactory.pointXY(Double.NaN, Double.NaN)).build()); } @Test public void testBuffer() throws ParseException { assertParses("BUFFER(POINT(1 2), 3)", ctx.makePoint(1, 2).getBuffered(3, ctx)); } }