diff --git a/core/src/main/java/geodb/ExtraSpatialFunctions.java b/core/src/main/java/geodb/ExtraSpatialFunctions.java new file mode 100644 index 0000000..a437c69 --- /dev/null +++ b/core/src/main/java/geodb/ExtraSpatialFunctions.java @@ -0,0 +1,131 @@ +package geodb; + +import com.vividsolutions.jts.geom.Geometry; +import com.vividsolutions.jts.geom.IntersectionMatrix; + +public class ExtraSpatialFunctions { + + private ExtraSpatialFunctions() { + } + + public static Integer dimension(byte[] wkb) { + Geometry geometry = GeoDB.gFromWKB(wkb); + if (geometry != null) { + return geometry.getDimension(); + } + return null; + } + + public static byte[] boundary(byte[] wkb) { + Geometry geometry = GeoDB.gFromWKB(wkb); + if (geometry != null) { + Geometry boundary = geometry.getBoundary(); + if (boundary != null) { + return GeoDB.gToWKB(boundary); + } + } + return null; + } + + public static boolean relate(byte[] wkb1, byte[] wkb2, + String intersectionPattern) { + Geometry geometry1 = GeoDB.gFromWKB(wkb1); + Geometry geometry2 = GeoDB.gFromWKB(wkb1); + if (geometry1 != null && geometry2 != null) { + return geometry1.relate(geometry2, intersectionPattern); + } + return false; + } + + public static String relate(byte[] wkb1, byte[] wkb2) { + Geometry geometry1 = GeoDB.gFromWKB(wkb1); + Geometry geometry2 = GeoDB.gFromWKB(wkb1); + if (geometry1 != null && geometry2 != null) { + IntersectionMatrix result = geometry1.relate(geometry2); + return result.toString(); + } + return null; + } + + public static byte[] convexHull(byte[] wkb) { + Geometry geometry = GeoDB.gFromWKB(wkb); + if (geometry != null) { + Geometry boundary = geometry.convexHull(); + if (boundary != null) { + return GeoDB.gToWKB(boundary); + } + } + return null; + } + + public static byte[] difference(byte[] wkb1, byte[] wkb2) { + if (wkb1 == null) { + return null; + } + if (wkb2 == null) { + return wkb1; + } + Geometry geometry1 = GeoDB.gFromWKB(wkb1); + Geometry geometry2 = GeoDB.gFromWKB(wkb2); + if (geometry1 == null) { + return null; + } + if (geometry2 == null) { + return wkb1; + } + + return GeoDB.gToWKB(geometry1.difference(geometry2)); + } + + public static byte[] intersection(byte[] wkb1, byte[] wkb2) { + if (wkb1 == null || wkb2 == null) { + return null; + } + Geometry geometry1 = GeoDB.gFromWKB(wkb1); + Geometry geometry2 = GeoDB.gFromWKB(wkb2); + if (geometry1 == null || geometry2 == null) { + return null; + } + + return GeoDB.gToWKB(geometry1.intersection(geometry2)); + } + + public static byte[] symdifference(byte[] wkb1, byte[] wkb2) { + if (wkb1 == null) { + return wkb2; + } + if (wkb2 == null) { + return wkb1; + } + Geometry geometry1 = GeoDB.gFromWKB(wkb1); + Geometry geometry2 = GeoDB.gFromWKB(wkb2); + if (geometry1 == null) { + return GeoDB.gToWKB(geometry2); + } + if (geometry2 == null) { + return GeoDB.gToWKB(geometry1); + } + + return GeoDB.gToWKB(geometry1.symDifference(geometry2)); + } + + public static byte[] union(byte[] wkb1, byte[] wkb2) { + if (wkb1 == null) { + return wkb2; + } + if (wkb2 == null) { + return wkb1; + } + Geometry geometry1 = GeoDB.gFromWKB(wkb1); + Geometry geometry2 = GeoDB.gFromWKB(wkb2); + if (geometry1 == null) { + return GeoDB.gToWKB(geometry2); + } + if (geometry2 == null) { + return GeoDB.gToWKB(geometry1); + } + + return GeoDB.gToWKB(geometry1.union(geometry2)); + } + +} diff --git a/core/src/main/java/geodb/aggregate/Extent.java b/core/src/main/java/geodb/aggregate/Extent.java new file mode 100644 index 0000000..40035d5 --- /dev/null +++ b/core/src/main/java/geodb/aggregate/Extent.java @@ -0,0 +1,34 @@ +package geodb.aggregate; + +import java.sql.Connection; +import java.sql.SQLException; + +import com.vividsolutions.jts.geom.Geometry; + +public class Extent extends GeoAggregateFunction { + + private Geometry result; + + @Override + protected void add(Geometry geometry) { + if (result == null) { + result = geometry; + } else { + if (geometry != null) { + result=result.union(geometry.getEnvelope()); + } + } + } + + @Override + protected Geometry getGeometryResult() { + if (result!=null){ + return result.getEnvelope(); + } + return null; + } + + public void init(Connection arg0) throws SQLException { + result=null; + } +} diff --git a/core/src/main/java/geodb/aggregate/GeoAggregateFunction.java b/core/src/main/java/geodb/aggregate/GeoAggregateFunction.java new file mode 100644 index 0000000..36e5e9e --- /dev/null +++ b/core/src/main/java/geodb/aggregate/GeoAggregateFunction.java @@ -0,0 +1,58 @@ +package geodb.aggregate; + +import geodb.GeoDB; + +import java.io.ByteArrayInputStream; +import java.io.IOException; +import java.sql.SQLException; +import java.sql.Types; + +import org.h2.api.AggregateFunction; + +import com.vividsolutions.jts.geom.Geometry; +import com.vividsolutions.jts.io.InputStreamInStream; +import com.vividsolutions.jts.io.ParseException; +import com.vividsolutions.jts.io.WKBReader; + +public abstract class GeoAggregateFunction implements AggregateFunction{ + + + private Geometry createGeometry(ByteArrayInputStream stream) { + InputStreamInStream inputStreamInStream = new InputStreamInStream(stream); + Geometry geometry=null; + try { + geometry = new WKBReader().read(inputStreamInStream ); + } catch (IOException e) { + throw new IllegalArgumentException("given geometry can not be found",e); + } catch (ParseException e) { + throw new IllegalArgumentException("given geometry is not valid",e); + } + return geometry; + + } + + protected abstract void add(Geometry geometry); + protected abstract Geometry getGeometryResult(); + + public final void add(Object arg0) throws SQLException { + if (arg0 != null) { + Geometry geometry = createGeometry((ByteArrayInputStream) arg0); + if (geometry!=null){ + add(geometry); + } + } + } + + public final Object getResult() throws SQLException { + Geometry geometryResult = getGeometryResult(); + if (geometryResult!=null){ + return GeoDB.gToWKB(geometryResult); + } + return null; + } + + public final int getType(int[] arg0) throws SQLException { + return Types.BLOB; + } + +} \ No newline at end of file diff --git a/core/src/main/java/geodb/aggregate/Union.java b/core/src/main/java/geodb/aggregate/Union.java new file mode 100644 index 0000000..4db4683 --- /dev/null +++ b/core/src/main/java/geodb/aggregate/Union.java @@ -0,0 +1,31 @@ +package geodb.aggregate; + +import java.sql.Connection; +import java.sql.SQLException; + +import com.vividsolutions.jts.geom.Geometry; + +public class Union extends GeoAggregateFunction { + + private Geometry result; + + @Override + protected void add(Geometry geometry) { + if (result == null) { + result = geometry; + } else { + if (geometry != null) { + result=result.union(geometry); + } + } + } + + @Override + protected Geometry getGeometryResult() { + return result; + } + + public void init(Connection arg0) throws SQLException { + result=null; + } +} diff --git a/core/src/main/resources/geodb/geodb.sql b/core/src/main/resources/geodb/geodb.sql index 8a19106..7f30bf5 100644 --- a/core/src/main/resources/geodb/geodb.sql +++ b/core/src/main/resources/geodb/geodb.sql @@ -11,13 +11,17 @@ CREATE ALIAS ST_AsEWKT FOR "geodb.GeoDB.ST_AsEWKT" CREATE ALIAS ST_AsHexEWKB FOR "geodb.GeoDB.ST_AsHexEWKB" CREATE ALIAS ST_AsText FOR "geodb.GeoDB.ST_AsText" CREATE ALIAS ST_BBOX FOR "geodb.GeoDB.ST_BBox" +CREATE ALIAS ST_Boundary FOR "geodb.ExtraSpatialFunctions.boundary" CREATE ALIAS ST_Buffer FOR "geodb.GeoDB.ST_Buffer" CREATE ALIAS ST_Centroid FOR "geodb.GeoDB.ST_Centroid" CREATE ALIAS ST_Crosses FOR "geodb.GeoDB.ST_Crosses" CREATE ALIAS ST_Contains FOR "geodb.GeoDB.ST_Contains" +CREATE ALIAS ST_ConvexHull FOR "geodb.ExtraSpatialFunctions.convexHull" CREATE ALIAS ST_DWithin FOR "geodb.GeoDB.ST_DWithin" CREATE ALIAS ST_Disjoint FOR "geodb.GeoDB.ST_Disjoint" CREATE ALIAS ST_Distance FOR "geodb.GeoDB.ST_Distance" +CREATE ALIAS ST_Difference FOR "geodb.ExtraSpatialFunctions.difference" +CREATE ALIAS ST_Dimension FOR "geodb.ExtraSpatialFunctions.dimension" CREATE ALIAS ST_Envelope FOR "geodb.GeoDB.ST_Envelope" CREATE ALIAS ST_Equals FOR "geodb.GeoDB.ST_Equals" CREATE ALIAS ST_GeoHash FOR "geodb.GeoDB.ST_GeoHash" @@ -25,6 +29,7 @@ CREATE ALIAS ST_GeomFromEWKB FOR "geodb.GeoDB.ST_GeomFromEWKB" CREATE ALIAS ST_GeomFromEWKT FOR "geodb.GeoDB.ST_GeomFromEWKT" CREATE ALIAS ST_GeomFromText FOR "geodb.GeoDB.ST_GeomFromText" CREATE ALIAS ST_GeomFromWKB FOR "geodb.GeoDB.ST_GeomFromWKB" +CREATE ALIAS ST_Intersection FOR "geodb.ExtraSpatialFunctions.intersection" CREATE ALIAS ST_Intersects FOR "geodb.GeoDB.ST_Intersects" CREATE ALIAS ST_IsEmpty FOR "geodb.GeoDB.ST_IsEmpty" CREATE ALIAS ST_IsSimple FOR "geodb.GeoDB.ST_IsSimple" @@ -32,10 +37,13 @@ CREATE ALIAS ST_IsValid FOR "geodb.GeoDB.ST_IsValid" CREATE ALIAS ST_MakePoint FOR "geodb.GeoDB.ST_MakePoint" CREATE ALIAS ST_MakeBox2D FOR "geodb.GeoDB.ST_MakeBox2D" CREATE ALIAS ST_Overlaps FOR "geodb.GeoDB.ST_Overlaps" +CREATE ALIAS ST_Relate FOR "geodb.ExtraSpatialFunctions.relate" CREATE ALIAS ST_SRID FOR "geodb.GeoDB.ST_SRID" CREATE ALIAS ST_SetSRID FOR "geodb.GeoDB.ST_SetSRID" CREATE ALIAS ST_Simplify FOR "geodb.GeoDB.ST_Simplify" +CREATE ALIAS ST_SymDifference FOR "geodb.ExtraSpatialFunctions.symdifference" CREATE ALIAS ST_Touches FOR "geodb.GeoDB.ST_Touches" +CREATE ALIAS ST_Union FOR "geodb.ExtraSpatialFunctions.union" CREATE ALIAS ST_Within FOR "geodb.GeoDB.ST_Within" CREATE ALIAS Version FOR "geodb.GeoDB.Version" CREATE DOMAIN POINT AS BLOB @@ -46,3 +54,5 @@ CREATE DOMAIN MULTILINESTRING AS BLOB CREATE DOMAIN MULTIPOLYGON AS BLOB CREATE DOMAIN GEOMETRYCOLLECTION AS BLOB CREATE DOMAIN GEOMETRY AS BLOB +CREATE AGGREGATE EXTENT FOR "geodb.aggregate.Extent" +CREATE AGGREGATE ST_UNION FOR "geodb.aggregate.Union" diff --git a/core/src/test/java/geodb/ExtraSpatialFunctionsTest.java b/core/src/test/java/geodb/ExtraSpatialFunctionsTest.java new file mode 100644 index 0000000..e11dea4 --- /dev/null +++ b/core/src/test/java/geodb/ExtraSpatialFunctionsTest.java @@ -0,0 +1,158 @@ +package geodb; + +import static org.hamcrest.CoreMatchers.is; +import static org.junit.Assert.assertThat; +import static org.junit.Assert.assertTrue; + +import java.io.IOException; +import java.io.InputStream; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.sql.Statement; + +import org.junit.Before; +import org.junit.Test; + +import com.vividsolutions.jts.geom.Geometry; +import com.vividsolutions.jts.io.InputStreamInStream; +import com.vividsolutions.jts.io.ParseException; +import com.vividsolutions.jts.io.WKBReader; + +public class ExtraSpatialFunctionsTest extends GeoDBTestSupport { + + @Before + public void setup() throws Exception { + super.setUp(); + Statement st = cx.createStatement(); + st.execute("DROP TABLE IF EXISTS _GEODB"); + st.execute("DROP TABLE IF EXISTS spatial"); + st.execute("DROP TABLE IF EXISTS spatial_hatbox"); + st.execute("DROP TABLE IF EXISTS noindex"); + st.close(); + GeoDB.InitGeoDB(cx); + } + + + @Test + public void test_dimension() throws SQLException, IOException, ParseException { + insert_three_points(); + Statement st = cx.createStatement(); + ResultSet rs = st.executeQuery("select st_dimension(geom) from spatial"); + rs.next(); + int srid = rs.getInt(1); + st.close(); + assertThat(srid, is(0)); + } + + @Test + public void test_boundary() throws SQLException, IOException, ParseException { + insert_three_points(); + Statement st = cx.createStatement(); + ResultSet rs = st.executeQuery("select st_boundary(geom) from spatial"); + rs.next(); + InputStream binaryStream = rs.getBinaryStream(1); + Geometry geometry = new WKBReader().read(new InputStreamInStream(binaryStream)); + st.close(); + assertThat(geometry.getArea(), is(0.0)); + } + + @Test + public void test_relate() throws SQLException, IOException, ParseException { + Statement st = cx.createStatement(); + ResultSet rs = st.executeQuery("SELECT ST_Relate(ST_GeomFromText('POINT(1 2)',4326), ST_Buffer(ST_GeomFromText('POINT(1 2)',4326),2))"); + rs.next(); + String result = rs.getString(1); + st.close(); + //I don't really understand this function so not sure if the result is correct. At least the result of both tests seems consistent. + assertThat(result, is("0FFFFFFF2")); + } + + @Test + public void test_relate_with_matrix() throws SQLException, IOException, ParseException { + Statement st = cx.createStatement(); + ResultSet rs = st.executeQuery("SELECT ST_Relate(ST_GeomFromText('POINT(1 2)',4326), ST_Buffer(ST_GeomFromText('POINT(1 2)',4326),2), '0FFFFFFF2')"); + rs.next(); + boolean result = rs.getBoolean(1); + st.close(); + //I don't really understand this function so not sure if the result is correct. At least the result of both tests seems consistent. + assertTrue(result); + } + + @Test + public void test_convexHull() throws SQLException, IOException, ParseException { + insert_three_points(); + Statement st = cx.createStatement(); + ResultSet rs = st.executeQuery("select st_convexhull(geom) from spatial"); + rs.next(); + InputStream binaryStream = rs.getBinaryStream(1); + Geometry geometry = new WKBReader().read(new InputStreamInStream(binaryStream)); + st.close(); + assertThat(geometry.getArea(), is(0.0)); + } + + + @Test + public void test_difference() throws SQLException, IOException, ParseException { + Statement st = cx.createStatement(); + ResultSet rs = st.executeQuery("select ST_Difference(" + + "ST_GeomFromText('POLYGON((0 0, 0 10, 10 10, 10 0, 0 0))', 4326)," + + "ST_GeomFromText('POLYGON((5 5, 5 10, 10 10, 10 5, 5 5))', 4326))"); + rs.next(); + InputStream binaryStream = rs.getBinaryStream(1); + Geometry geometry = new WKBReader().read(new InputStreamInStream(binaryStream)); + st.close(); + assertThat(geometry.getArea(), is(75.0)); + } + + @Test + public void test_intersection() throws SQLException, IOException, ParseException { + Statement st = cx.createStatement(); + ResultSet rs = st.executeQuery("select ST_Intersection(" + + "ST_GeomFromText('POLYGON((0 0, 0 10, 10 10, 10 0, 0 0))', 4326)," + + "ST_GeomFromText('POLYGON((5 5, 5 10, 10 10, 10 5, 5 5))', 4326))"); + rs.next(); + InputStream binaryStream = rs.getBinaryStream(1); + Geometry geometry = new WKBReader().read(new InputStreamInStream(binaryStream)); + st.close(); + assertThat(geometry.getArea(), is(25.0)); + } + + @Test + public void test_symdifference() throws SQLException, IOException, ParseException { + Statement st = cx.createStatement(); + ResultSet rs = st.executeQuery("select ST_SymDifference(" + + "ST_GeomFromText('POLYGON((0 0, 0 10, 10 10, 10 0, 0 0))', 4326)," + + "ST_GeomFromText('POLYGON((5 5, 5 15, 10 15, 10 5, 5 5))', 4326))"); + rs.next(); + InputStream binaryStream = rs.getBinaryStream(1); + Geometry geometry = new WKBReader().read(new InputStreamInStream(binaryStream)); + st.close(); + assertThat(geometry.getArea(), is(100.0)); + } + + + @Test + public void test_union() throws SQLException, IOException, ParseException { + Statement st = cx.createStatement(); + ResultSet rs = st.executeQuery("select ST_Union(" + + "ST_GeomFromText('POLYGON((0 0, 0 10, 10 10, 10 0, 0 0))', 4326)," + + "ST_GeomFromText('POLYGON((5 5, 5 15, 10 15, 10 5, 5 5))', 4326))"); + rs.next(); + InputStream binaryStream = rs.getBinaryStream(1); + Geometry geometry = new WKBReader().read(new InputStreamInStream(binaryStream)); + st.close(); + assertThat(geometry.getArea(), is(125.0)); + } + + private void insert_three_points() throws SQLException{ + Statement st = cx.createStatement(); + st.execute("CREATE TABLE spatial (id INT AUTO_INCREMENT PRIMARY KEY, geom BLOB)"); + st.execute("INSERT INTO spatial (geom) VALUES (ST_GeomFromText('POINT(0 0)', 4326))"); + st.execute("INSERT INTO spatial (geom) VALUES (ST_GeomFromText('POINT(1 1)', 4326))"); + st.execute("INSERT INTO spatial (geom) VALUES (ST_GeomFromText('POINT(2 2)', 4326))"); + st.close(); + } + + + +} diff --git a/core/src/test/java/geodb/aggregate/AggregateTest.java b/core/src/test/java/geodb/aggregate/AggregateTest.java new file mode 100644 index 0000000..fec94b7 --- /dev/null +++ b/core/src/test/java/geodb/aggregate/AggregateTest.java @@ -0,0 +1,64 @@ +package geodb.aggregate; + +import static org.hamcrest.CoreMatchers.is; +import static org.junit.Assert.assertThat; +import geodb.GeoDB; +import geodb.GeoDBTestSupport; + +import java.io.InputStream; +import java.sql.ResultSet; +import java.sql.Statement; + +import org.junit.Before; +import org.junit.Test; + +import com.vividsolutions.jts.geom.Geometry; +import com.vividsolutions.jts.io.InputStreamInStream; +import com.vividsolutions.jts.io.WKBReader; + +public class AggregateTest extends GeoDBTestSupport { + + @Before + public void setup() throws Exception { + super.setUp(); + + Statement st = cx.createStatement(); + st.execute("DROP TABLE IF EXISTS _GEODB"); + st.execute("DROP TABLE IF EXISTS spatial"); + st.execute("DROP TABLE IF EXISTS spatial_hatbox"); + st.execute("DROP TABLE IF EXISTS noindex"); + st.close(); + GeoDB.InitGeoDB(cx); + + st = cx.createStatement(); + st.execute("CREATE TABLE spatial (id INT AUTO_INCREMENT PRIMARY KEY, geom BLOB)"); + st.execute("INSERT INTO spatial (geom) VALUES (ST_GeomFromText('POINT(0 0)', 4326))"); + st.execute("INSERT INTO spatial (geom) VALUES (ST_GeomFromText('POINT(1 1)', 4326))"); + st.execute("INSERT INTO spatial (geom) VALUES (ST_GeomFromText('POINT(2 2)', 4326))"); + st.close(); + } + + @Test + public void test_extent() throws Exception { + Statement st = cx.createStatement(); + ResultSet rs = st.executeQuery("select extent(geom) from spatial"); + rs.next(); + InputStream binaryStream = rs.getBinaryStream(1); + Geometry geometry = new WKBReader().read(new InputStreamInStream(binaryStream)); + st.close(); + assertThat(geometry.getArea(), is(4.0)); + } + + @Test + public void test_union() throws Exception { + Statement st = cx.createStatement(); + ResultSet rs = st.executeQuery("select st_union(geom) from spatial"); + rs.next(); + InputStream binaryStream = rs.getBinaryStream(1); + Geometry geometry = new WKBReader().read(new InputStreamInStream(binaryStream)); + st.close(); + assertThat(geometry.getArea(), is(0.0)); + } + + +} diff --git a/core/src/test/java/geodb/aggregate/ExtentTest.java b/core/src/test/java/geodb/aggregate/ExtentTest.java new file mode 100644 index 0000000..406280e --- /dev/null +++ b/core/src/test/java/geodb/aggregate/ExtentTest.java @@ -0,0 +1,112 @@ +package geodb.aggregate; + +import static org.hamcrest.CoreMatchers.equalTo; +import static org.hamcrest.CoreMatchers.is; +import static org.hamcrest.CoreMatchers.not; +import static org.hamcrest.CoreMatchers.nullValue; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertThat; +import static org.junit.Assert.assertTrue; + +import geodb.GeoDB; + +import java.sql.SQLException; + +import org.junit.Before; +import org.junit.Test; + +import com.vividsolutions.jts.geom.Coordinate; +import com.vividsolutions.jts.geom.Geometry; +import com.vividsolutions.jts.geom.GeometryFactory; +import com.vividsolutions.jts.geom.LinearRing; +import com.vividsolutions.jts.geom.impl.CoordinateArraySequence; + +public class ExtentTest { + + private Extent extent; + + private GeometryFactory factory; + + + @Before + public void init_extent() throws SQLException{ + extent=new Extent(); + extent.init(null); + } + + @Before + public void init_geometry_factory(){ + factory=new GeometryFactory(); + } + + @Test + public void extent_empty_collection() throws SQLException { + Object result = extent.getResult(); + assertThat(result, is(nullValue())); + } + + @Test + public void extent_one_point() throws SQLException{ + extent.add(createPoint(3, 5)); + Object result = extent.getResult(); + assertThat(result, is(not(nullValue()))); + Geometry envelope = GeoDB.gFromWKB((byte[]) result); + assertThat(envelope.getArea(), is(0.0)); + assertThat(envelope, is(equalTo(createPoint(3, 5)))); + } + + + @Test + public void extent_two_points() throws SQLException{ + extent.add(createPoint(3, 5)); + extent.add(createPoint(5, 3)); + Object result = extent.getResult(); + assertThat(result, is(not(nullValue()))); + Geometry envelope = GeoDB.gFromWKB((byte[]) result); + + assertThat(envelope.getArea(), is(4.0)); + assertTrue(envelope.contains(createPoint(4, 4))); + assertTrue(envelope.contains(createPoint(4.99999, 4.9999))); + assertFalse(envelope.contains(createPoint(5.00001, 5.00001))); + } + + @Test + public void extent_triangle_polygon() throws SQLException{ + extent.add(createPolygon(new Coordinate[]{new Coordinate(0, 1),new Coordinate(2, 2),new Coordinate(2, 0),new Coordinate(0, 1)})); + Object result = extent.getResult(); + assertThat(result, is(not(nullValue()))); + Geometry envelope = GeoDB.gFromWKB((byte[]) result); + + assertThat(envelope.getArea(), is(4.0)); + assertTrue(envelope.contains(createPoint(1, 1))); + assertTrue(envelope.contains(createPoint(1.99999, 1.9999))); + assertFalse(envelope.contains(createPoint(2.00001, 2.00001))); + assertTrue(envelope.contains(createPoint(0.00001, 0.00001))); + } + + @Test + public void extent_two_triangle_polygon() throws SQLException{ + extent.add(createPolygon(new Coordinate[]{new Coordinate(0, 1),new Coordinate(2, 2),new Coordinate(2, 0),new Coordinate(0, 1)})); + extent.add(createPolygon(new Coordinate[]{new Coordinate(1, 1),new Coordinate(3, 2),new Coordinate(3, 0),new Coordinate(1, 1)})); + Object result = extent.getResult(); + assertThat(result, is(not(nullValue()))); + Geometry envelope = GeoDB.gFromWKB((byte[]) result); + + assertThat(envelope.getArea(), is(6.0)); + assertTrue(envelope.contains(createPoint(1, 1))); + assertTrue(envelope.contains(createPoint(2.99999, 1.9999))); + assertFalse(envelope.contains(createPoint(3.00001, 2.00001))); + assertTrue(envelope.contains(createPoint(0.00001, 0.00001))); + } + + + + private Geometry createPoint(double x,double y){ + return factory.createPoint(new Coordinate(x, y)); + } + + private Geometry createPolygon(Coordinate[] coordinates){ + return factory.createPolygon(new LinearRing(new CoordinateArraySequence(coordinates), factory),null); + } + +} diff --git a/core/src/test/java/geodb/aggregate/UnionTest.java b/core/src/test/java/geodb/aggregate/UnionTest.java new file mode 100644 index 0000000..8686c1e --- /dev/null +++ b/core/src/test/java/geodb/aggregate/UnionTest.java @@ -0,0 +1,112 @@ +package geodb.aggregate; + +import static org.hamcrest.CoreMatchers.equalTo; +import static org.hamcrest.CoreMatchers.is; +import static org.hamcrest.CoreMatchers.not; +import static org.hamcrest.CoreMatchers.nullValue; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertThat; +import static org.junit.Assert.assertTrue; + +import geodb.GeoDB; + +import java.sql.SQLException; + +import org.junit.Before; +import org.junit.Test; + +import com.vividsolutions.jts.geom.Coordinate; +import com.vividsolutions.jts.geom.Geometry; +import com.vividsolutions.jts.geom.GeometryFactory; +import com.vividsolutions.jts.geom.LinearRing; +import com.vividsolutions.jts.geom.impl.CoordinateArraySequence; + +public class UnionTest { + + private Union union; + + private GeometryFactory factory; + + + @Before + public void init_extent() throws SQLException{ + union=new Union(); + union.init(null); + } + + @Before + public void init_geometry_factory(){ + factory=new GeometryFactory(); + } + + @Test + public void extent_empty_collection() throws SQLException { + Object result = union.getResult(); + assertThat(result, is(nullValue())); + } + + @Test + public void extent_one_point() throws SQLException{ + union.add(createPoint(3, 5)); + Object result = union.getResult(); + assertThat(result, is(not(nullValue()))); + Geometry envelope = GeoDB.gFromWKB((byte[]) result); + assertThat(envelope.getArea(), is(0.0)); + assertThat(envelope, is(equalTo(createPoint(3, 5)))); + } + + + @Test + public void extent_two_points() throws SQLException{ + union.add(createPoint(3, 5)); + union.add(createPoint(5, 3)); + Object result = union.getResult(); + assertThat(result, is(not(nullValue()))); + Geometry geomResult = GeoDB.gFromWKB((byte[]) result); + + assertThat(geomResult.getArea(), is(0.0)); + assertTrue(geomResult.contains(createPoint(3, 5))); + assertTrue(geomResult.contains(createPoint(5, 3))); + assertFalse(geomResult.contains(createPoint(4, 4))); + } + + @Test + public void extent_triangle_polygon() throws SQLException{ + union.add(createPolygon(new Coordinate[]{new Coordinate(0, 1),new Coordinate(2, 2),new Coordinate(2, 0),new Coordinate(0, 1)})); + Object result = union.getResult(); + assertThat(result, is(not(nullValue()))); + Geometry envelope = GeoDB.gFromWKB((byte[]) result); + + assertThat(envelope.getArea(), is(2.0)); + assertTrue(envelope.contains(createPoint(1, 1))); + assertTrue(envelope.contains(createPoint(1.99999, 1.9999))); + assertFalse(envelope.contains(createPoint(2.00001, 2.00001))); + assertFalse(envelope.contains(createPoint(0, 0))); + } + + @Test + public void extent_two_triangle_polygon() throws SQLException{ + union.add(createPolygon(new Coordinate[]{new Coordinate(0, 1),new Coordinate(2, 2),new Coordinate(2, 0),new Coordinate(0, 1)})); + union.add(createPolygon(new Coordinate[]{new Coordinate(1, 1),new Coordinate(3, 2),new Coordinate(3, 0),new Coordinate(1, 1)})); + Object result = union.getResult(); + assertThat(result, is(not(nullValue()))); + Geometry envelope = GeoDB.gFromWKB((byte[]) result); + + assertThat(envelope.getArea(), is(3.5)); + assertTrue(envelope.contains(createPoint(1, 1))); + assertTrue(envelope.contains(createPoint(2.99999, 1.9999))); + assertFalse(envelope.contains(createPoint(3.00001, 2.00001))); + assertFalse(envelope.contains(createPoint(0, 0))); + } + + + + private Geometry createPoint(double x,double y){ + return factory.createPoint(new Coordinate(x, y)); + } + + private Geometry createPolygon(Coordinate[] coordinates){ + return factory.createPolygon(new LinearRing(new CoordinateArraySequence(coordinates), factory),null); + } + +}