From: Markus Schaber Date: Wed, 25 May 2005 10:08:56 +0000 (+0000) Subject: JTS binary parser now passes basic regression suite X-Git-Tag: pgis_1_1_0~362 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=e331cdc85ac253719ef743c8eb690e620b6a3608;p=postgis JTS binary parser now passes basic regression suite git-svn-id: http://svn.osgeo.org/postgis/trunk@1729 b70326c6-7e19-0410-871a-916f4a2858ee --- diff --git a/jdbc2/Makefile b/jdbc2/Makefile index 6f04a4bc4..ebb1fc04e 100644 --- a/jdbc2/Makefile +++ b/jdbc2/Makefile @@ -133,7 +133,7 @@ VERSIONPATH=$(BUILD)/org/postgis VERSIONTARGET=$(VERSIONPATH)/version.properties # Output redirect for tests -TESTRD= >>$(TESTOUTPUT) +TESTRD?= >>$(TESTOUTPUT) # Preliminary jts support - not stable yet! JTSDIR=jtssrc @@ -278,7 +278,7 @@ jtscompile: compile stubcompile $(JTSBUILD) $(SRCCONF) $(JTSSRC) touch jtscompile jtstestoffline: jtscompile - $(JAVA) $(EXEC_ADDCP) "$(JTSPATH)" $(EXAMPLES)/JtsTestParser offline + $(JAVA) $(EXEC_ADDCP) "$(JTSPATH)" $(EXAMPLES)/JtsTestParser $(TESTRD) offline jtstest: jtscompile $(JAVA) $(EXEC_ADDCP) "$(JTSPATH)" $(EXAMPLES)/JtsTestParser $(TESTRD) \ diff --git a/jdbc2/jtssrc/examples/JtsTestParser.java b/jdbc2/jtssrc/examples/JtsTestParser.java index 65fb916c3..0452efd28 100644 --- a/jdbc2/jtssrc/examples/JtsTestParser.java +++ b/jdbc2/jtssrc/examples/JtsTestParser.java @@ -26,46 +26,104 @@ package examples; -import com.vividsolutions.jts.geom.Geometry; -import com.vividsolutions.jts.io.WKTReader; - +import org.postgis.binary.ValueSetter; +import org.postgis.jts.JtsBinaryParser; +import org.postgis.jts.JtsBinaryWriter; import org.postgis.jts.JtsGeometry; + import org.postgresql.util.PGtokenizer; +import com.vividsolutions.jts.geom.Geometry; + import java.sql.Connection; import java.sql.DriverManager; +import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; import java.sql.Statement; +import java.sql.Types; public class JtsTestParser { - final static WKTReader reader = new WKTReader(); + + public static String ALL = "ALL", ONLY10 = "ONLY10", EQUAL10 = "EQUAL10"; /** * Our set of geometries to test. */ - public static final String[] testset = new String[]{ - "POINT(10 10 20)", - "MULTIPOINT(10 10 10, 20 20 20)", - "LINESTRING(10 10 20,20 20 20, 50 50 50, 34 34 34)", - "POLYGON((10 10 0,20 10 0,20 20 0,20 10 0,10 10 0),(5 5 0,5 6 0,6 6 0,6 5 0,5 5 0))", - "MULTIPOLYGON(((10 10 0,20 10 0,20 20 0,20 10 0,10 10 0),(5 5 0,5 6 0,6 6 0,6 5 0,5 5 0)),((10 10 0,20 10 0,20 20 0,20 10 0,10 10 0),(5 5 0,5 6 0,6 6 0,6 5 0,5 5 0)))", - "MULTILINESTRING((10 10 0,20 10 0,20 20 0,20 10 0,10 10 0),(5 5 0,5 6 0,6 6 0,6 5 0,5 5 0))", - "GEOMETRYCOLLECTION(POINT(10 10 20),POINT(20 20 20))", - "GEOMETRYCOLLECTION(LINESTRING(10 10 20,20 20 20, 50 50 50, 34 34 34),LINESTRING(10 10 20,20 20 20, 50 50 50, 34 34 34))", - "GEOMETRYCOLLECTION(POLYGON((10 10 0,20 10 0,20 20 0,20 10 0,10 10 0),(5 5 0,5 6 0,6 6 0,6 5 0,5 5 0)),POLYGON((10 10 0,20 10 0,20 20 0,20 10 0,10 10 0),(5 5 0,5 6 0,6 6 0,6 5 0,5 5 0)))", - "GEOMETRYCOLLECTION(MULTIPOINT(10 10 10, 20 20 20),MULTIPOINT(10 10 10, 20 20 20))", - "GEOMETRYCOLLECTION(MULTILINESTRING((10 10 0,20 10 0,20 20 0,20 10 0,10 10 0),(5 5 0,5 6 0,6 6 0,6 5 0,5 5 0)))", - "GEOMETRYCOLLECTION(MULTIPOLYGON(((10 10 0,20 10 0,20 20 0,20 10 0,10 10 0),(5 5 0,5 6 0,6 6 0,6 5 0,5 5 0)),((10 10 0,20 10 0,20 20 0,20 10 0,10 10 0),(5 5 0,5 6 0,6 6 0,6 5 0,5 5 0))),MULTIPOLYGON(((10 10 0,20 10 0,20 20 0,20 10 0,10 10 0),(5 5 0,5 6 0,6 6 0,6 5 0,5 5 0)),((10 10 0,20 10 0,20 20 0,20 10 0,10 10 0),(5 5 0,5 6 0,6 6 0,6 5 0,5 5 0))))", - "GEOMETRYCOLLECTION(POINT(10 10 20),LINESTRING(10 10 20,20 20 20, 50 50 50, 34 34 34),POLYGON((10 10 0,20 10 0,20 20 0,20 10 0,10 10 0),(5 5 0,5 6 0,6 6 0,6 5 0,5 5 0)))", - "GEOMETRYCOLLECTION(POINT(10 10 20),MULTIPOINT(10 10 10, 20 20 20),LINESTRING(10 10 20,20 20 20, 50 50 50, 34 34 34),POLYGON((10 10 0,20 10 0,20 20 0,20 10 0,10 10 0),(5 5 0,5 6 0,6 6 0,6 5 0,5 5 0)),MULTIPOLYGON(((10 10 0,20 10 0,20 20 0,20 10 0,10 10 0),(5 5 0,5 6 0,6 6 0,6 5 0,5 5 0)),((10 10 0,20 10 0,20 20 0,20 10 0,10 10 0),(5 5 0,5 6 0,6 6 0,6 5 0,5 5 0))),MULTILINESTRING((10 10 0,20 10 0,20 20 0,20 10 0,10 10 0),(5 5 0,5 6 0,6 6 0,6 5 0,5 5 0)))", - "GEOMETRYCOLLECTION EMPTY", // new (correct) representation - "POINT EMPTY", // new (correct) representation - "LINESTRING EMPTY", // new (correct) representation - "POLYGON EMPTY", // new (correct) representation - "MULTIPOINT EMPTY", // new (correct) representation - "MULTILINESTRING EMPTY", // new (correct) representation - "MULTIPOLYGON EMPTY", // new (correct) representation + public static final String[][] testset = new String[][]{ + { + ALL, // 2D + "POINT(10 10)"}, + { + ALL, // 3D with 3rd coordinate set to 0 + "POINT(10 10 0)"}, + { + ALL, // 3D + "POINT(10 10 20)"}, + { + ALL, + "MULTIPOINT(11 12, 20 20)"}, + { + ALL, + "MULTIPOINT(11 12 13, 20 20 20)"}, + { + ALL, + "LINESTRING(10 10,20 20,50 50,34 34)"}, + { + ALL, + "LINESTRING(10 10 20,20 20 20,50 50 50,34 34 34)"}, + { + ALL, + "POLYGON((10 10,20 10,20 20,20 10,10 10),(5 5,5 6,6 6,6 5,5 5))"}, + { + ALL, + "POLYGON((10 10 0,20 10 0,20 20 0,20 10 0,10 10 0),(5 5 0,5 6 0,6 6 0,6 5 0,5 5 0))"}, + { + ALL, + "MULTIPOLYGON(((10 10,20 10,20 20,20 10,10 10),(5 5,5 6,6 6,6 5,5 5)),((10 10,20 10,20 20,20 10,10 10),(5 5,5 6,6 6,6 5,5 5)))"}, + { + ALL, + "MULTIPOLYGON(((10 10 0,20 10 0,20 20 0,20 10 0,10 10 0),(5 5 0,5 6 0,6 6 0,6 5 0,5 5 0)),((10 10 0,20 10 0,20 20 0,20 10 0,10 10 0),(5 5 0,5 6 0,6 6 0,6 5 0,5 5 0)))"}, + { + ALL, + "MULTILINESTRING((10 10,20 10,20 20,20 10,10 10),(5 5,5 6,6 6,6 5,5 5))"}, + { + ALL, + "MULTILINESTRING((10 10 5,20 10 5,20 20 0,20 10 0,10 10 0),(5 5 0,5 6 0,6 6 0,6 5 0,5 5 0))"}, + { + ALL, + "GEOMETRYCOLLECTION(POINT(10 10),POINT(20 20))"}, + { + ALL, + "GEOMETRYCOLLECTION(POINT(10 10 20),POINT(20 20 20))"}, + { + ALL, + "GEOMETRYCOLLECTION(LINESTRING(10 10 20,20 20 20, 50 50 50, 34 34 34),LINESTRING(10 10 20,20 20 20, 50 50 50, 34 34 34))"}, + { + ALL, + "GEOMETRYCOLLECTION(POLYGON((10 10 0,20 10 0,20 20 0,20 10 0,10 10 0),(5 5 0,5 6 0,6 6 0,6 5 0,5 5 0)),POLYGON((10 10 0,20 10 0,20 20 0,20 10 0,10 10 0),(5 5 0,5 6 0,6 6 0,6 5 0,5 5 0)))"}, + { + ONLY10, // Cannot be parsed by 0.X servers + "GEOMETRYCOLLECTION(MULTIPOINT(10 10 10, 20 20 20),MULTIPOINT(10 10 10, 20 20 20))"}, + { + EQUAL10, // PostGIs 0.X "flattens" this geometry, so it is not + // equal after reparsing. + "GEOMETRYCOLLECTION(MULTILINESTRING((10 10 0,20 10 0,20 20 0,20 10 0,10 10 0),(5 5 0,5 6 0,6 6 0,6 5 0,5 5 0)))"}, + { + EQUAL10,// PostGIs 0.X "flattens" this geometry, so it is not equal + // after reparsing. + "GEOMETRYCOLLECTION(MULTIPOLYGON(((10 10 0,20 10 0,20 20 0,20 10 0,10 10 0),(5 5 0,5 6 0,6 6 0,6 5 0,5 5 0)),((10 10 0,20 10 0,20 20 0,20 10 0,10 10 0),(5 5 0,5 6 0,6 6 0,6 5 0,5 5 0))),MULTIPOLYGON(((10 10 0,20 10 0,20 20 0,20 10 0,10 10 0),(5 5 0,5 6 0,6 6 0,6 5 0,5 5 0)),((10 10 0,20 10 0,20 20 0,20 10 0,10 10 0),(5 5 0,5 6 0,6 6 0,6 5 0,5 5 0))))"}, + { + ALL, + "GEOMETRYCOLLECTION(POINT(10 10 20),LINESTRING(10 10 20,20 20 20, 50 50 50, 34 34 34),POLYGON((10 10 0,20 10 0,20 20 0,20 10 0,10 10 0),(5 5 0,5 6 0,6 6 0,6 5 0,5 5 0)))"}, + { + ONLY10, // Collections that contain both X and MultiX do not work on + // PostGIS 0.x + "GEOMETRYCOLLECTION(POINT(10 10 20),MULTIPOINT(10 10 10, 20 20 20),LINESTRING(10 10 20,20 20 20, 50 50 50, 34 34 34),POLYGON((10 10 0,20 10 0,20 20 0,20 10 0,10 10 0),(5 5 0,5 6 0,6 6 0,6 5 0,5 5 0)),MULTIPOLYGON(((10 10 0,20 10 0,20 20 0,20 10 0,10 10 0),(5 5 0,5 6 0,6 6 0,6 5 0,5 5 0)),((10 10 0,20 10 0,20 20 0,20 10 0,10 10 0),(5 5 0,5 6 0,6 6 0,6 5 0,5 5 0))),MULTILINESTRING((10 10 0,20 10 0,20 20 0,20 10 0,10 10 0),(5 5 0,5 6 0,6 6 0,6 5 0,5 5 0)))"}, + { + ALL,// new (correct) representation + "GEOMETRYCOLLECTION EMPTY"}, + // end }; /** The srid we use for the srid tests */ @@ -77,8 +135,11 @@ public class JtsTestParser { /** How much tests did fail? */ public static int failcount = 0; + private static JtsBinaryParser bp = new JtsBinaryParser(); + private static final JtsBinaryWriter bw = new JtsBinaryWriter(); + /** The actual test method */ - public static void test(String WKT, Connection[] conns) throws SQLException { + public static void test(String WKT, Connection[] conns, String flags) throws SQLException { System.out.println("Original: " + WKT); Geometry geom = JtsGeometry.geomFromString(WKT); String parsed = geom.toString(); @@ -86,7 +147,7 @@ public class JtsTestParser { Geometry regeom = JtsGeometry.geomFromString(parsed); String reparsed = regeom.toString(); System.out.println("Re-Parsed: " + reparsed); - if (safeGeomUnequal(geom, regeom)) { + if (!geom.equalsExact(regeom)) { System.out.println("--- Geometries are not equal!"); failcount++; } else if (!reparsed.equals(parsed)) { @@ -95,52 +156,222 @@ public class JtsTestParser { } else { System.out.println("Equals: yes"); } + + String hexNWKT = bw.writeHexed(regeom, ValueSetter.NDR.NUMBER); + System.out.println("NDRHex: " + hexNWKT); + regeom = JtsGeometry.geomFromString(hexNWKT); + System.out.println("ReNDRHex: " + regeom.toString()); + if (!geom.equalsExact(regeom)) { + System.out.println("--- Geometries are not equal!"); + failcount++; + } else { + System.out.println("Equals: yes"); + } + + String hexXWKT = bw.writeHexed(regeom, ValueSetter.XDR.NUMBER); + System.out.println("XDRHex: " + hexXWKT); + regeom = JtsGeometry.geomFromString(hexXWKT); + System.out.println("ReXDRHex: " + regeom.toString()); + if (!geom.equalsExact(regeom)) { + System.out.println("--- Geometries are not equal!"); + failcount++; + } else { + System.out.println("Equals: yes"); + } + + byte[] NWKT = bw.writeBinary(regeom, ValueSetter.NDR.NUMBER); + regeom = bp.parse(NWKT); + System.out.println("NDR: " + regeom.toString()); + if (!geom.equalsExact(regeom)) { + System.out.println("--- Geometries are not equal!"); + failcount++; + } else { + System.out.println("Equals: yes"); + } + + byte[] XWKT = bw.writeBinary(regeom, ValueSetter.XDR.NUMBER); + regeom = bp.parse(XWKT); + System.out.println("XDR: " + regeom.toString()); + if (!geom.equalsExact(regeom)) { + System.out.println("--- Geometries are not equal!"); + failcount++; + } else { + System.out.println("Equals: yes"); + } + for (int i = 0; i < conns.length; i++) { - System.out.println("Testing on connection " + i + ": " + conns[i].getCatalog()); - Statement statement = conns[i].createStatement(); - - try { - Geometry sqlGeom = viaSQL(WKT, statement); - System.out.println("SQLin : " + sqlGeom.toString()); - if (safeGeomUnequal(geom, sqlGeom)) { - System.out.println("--- Geometries after SQL are not equal!"); + Connection connection = conns[i]; + Statement statement = connection.createStatement(); + int serverPostgisMajor = TestAutoregister.getPostgisMajor(statement); + + if ((flags == ONLY10) && serverPostgisMajor < 1) { + System.out.println("PostGIS server too old, skipping test on connection " + i + + ": " + connection.getCatalog()); + } else { + System.out.println("Testing on connection " + i + ": " + connection.getCatalog()); + try { + Geometry sqlGeom = viaSQL(WKT, statement); + System.out.println("SQLin : " + sqlGeom.toString()); + if (!geom.equalsExact(sqlGeom)) { + System.out.println("--- Geometries after SQL are not equal!"); + if (flags == EQUAL10 && serverPostgisMajor < 1) { + System.out.println("--- This is expected with PostGIS " + + serverPostgisMajor + ".X"); + } else { + failcount++; + } + } else { + System.out.println("Eq SQL in: yes"); + } + } catch (SQLException e) { + System.out.println("--- Server side error: " + e.toString()); failcount++; - } else { - System.out.println("Eq SQL in: yes"); } - } catch (SQLException e) { - System.out.println("--- Server side error: " + e.toString()); - failcount++; - } - try { - Geometry sqlreGeom = viaSQL(parsed, statement); - System.out.println("SQLout : " + sqlreGeom.toString()); - if (safeGeomUnequal(geom, sqlreGeom)) { - System.out.println("--- reparsed Geometries after SQL are not equal!"); + try { + Geometry sqlreGeom = viaSQL(parsed, statement); + System.out.println("SQLout : " + sqlreGeom.toString()); + if (!geom.equalsExact(sqlreGeom)) { + System.out.println("--- reparsed Geometries after SQL are not equal!"); + if (flags == EQUAL10 && serverPostgisMajor < 1) { + System.out.println("--- This is expected with PostGIS " + + serverPostgisMajor + ".X"); + } else { + failcount++; + } + } else { + System.out.println("Eq SQLout: yes"); + } + } catch (SQLException e) { + System.out.println("--- Server side error: " + e.toString()); + failcount++; + } + + try { + Geometry sqlreGeom = viaPrepSQL(geom, connection); + System.out.println("Prepared: " + sqlreGeom.toString()); + if (!geom.equalsExact(sqlreGeom)) { + System.out.println("--- reparsed Geometries after prepared StatementSQL are not equal!"); + if (flags == EQUAL10 && serverPostgisMajor < 1) { + System.out.println("--- This is expected with PostGIS " + + serverPostgisMajor + ".X"); + } else { + failcount++; + } + } else { + System.out.println("Eq Prep: yes"); + } + } catch (SQLException e) { + System.out.println("--- Server side error: " + e.toString()); + failcount++; + } + + // asEWKT() function is not present on PostGIS 0.X, and the test + // is pointless as 0.X uses EWKT as canonical rep so the same + // functionality was already tested above. + try { + if (serverPostgisMajor >= 1) { + Geometry sqlGeom = ewktViaSQL(WKT, statement); + System.out.println("asEWKT : " + sqlGeom.toString()); + if (!geom.equalsExact(sqlGeom)) { + System.out.println("--- Geometries after EWKT SQL are not equal!"); + failcount++; + } else { + System.out.println("equal : yes"); + } + } + } catch (SQLException e) { + System.out.println("--- Server side error: " + e.toString()); + failcount++; + } + + // asEWKB() function is not present on PostGIS 0.X. + try { + if (serverPostgisMajor >= 1) { + Geometry sqlGeom = ewkbViaSQL(WKT, statement); + System.out.println("asEWKB : " + sqlGeom.toString()); + if (!geom.equalsExact(sqlGeom)) { + System.out.println("--- Geometries after EWKB SQL are not equal!"); + failcount++; + } else { + System.out.println("equal : yes"); + } + } + } catch (SQLException e) { + System.out.println("--- Server side error: " + e.toString()); + failcount++; + } + + // HexEWKB parsing is not present on PostGIS 0.X. + try { + if (serverPostgisMajor >= 1) { + Geometry sqlGeom = viaSQL(hexNWKT, statement); + System.out.println("hexNWKT: " + sqlGeom.toString()); + if (!geom.equalsExact(sqlGeom)) { + System.out.println("--- Geometries after EWKB SQL are not equal!"); + failcount++; + } else { + System.out.println("equal : yes"); + } + } + } catch (SQLException e) { + System.out.println("--- Server side error: " + e.toString()); + failcount++; + } + try { + if (serverPostgisMajor >= 1) { + Geometry sqlGeom = viaSQL(hexXWKT, statement); + System.out.println("hexXWKT: " + sqlGeom.toString()); + if (!geom.equalsExact(sqlGeom)) { + System.out.println("--- Geometries after EWKB SQL are not equal!"); + failcount++; + } else { + System.out.println("equal : yes"); + } + } + } catch (SQLException e) { + System.out.println("--- Server side error: " + e.toString()); failcount++; - } else { - System.out.println("Eq SQLout: yes"); } - } catch (SQLException e) { - System.out.println("--- Server side error: " + e.toString()); - failcount++; - } + // Canonical binary input is not present before 1.0 + try { + if (serverPostgisMajor >= 1) { + Geometry sqlGeom = binaryViaSQL(NWKT, connection); + System.out.println("NWKT: " + sqlGeom.toString()); + if (!geom.equalsExact(sqlGeom)) { + System.out.println("--- Geometries after EWKB SQL are not equal!"); + failcount++; + } else { + System.out.println("equal : yes"); + } + } + } catch (SQLException e) { + System.out.println("--- Server side error: " + e.toString()); + failcount++; + } + try { + if (serverPostgisMajor >= 1) { + Geometry sqlGeom = binaryViaSQL(XWKT, connection); + System.out.println("XWKT: " + sqlGeom.toString()); + if (!geom.equalsExact(sqlGeom)) { + System.out.println("--- Geometries after EWKB SQL are not equal!"); + failcount++; + } else { + System.out.println("equal : yes"); + } + } + } catch (SQLException e) { + System.out.println("--- Server side error: " + e.toString()); + failcount++; + } + + } statement.close(); } System.out.println("***"); } - private static boolean safeGeomUnequal(Geometry geom, Geometry regeom) { - try { - return !geom.equals(regeom); - } catch (java.lang.IllegalArgumentException e) { - System.out.println(".equals call failed: " + e.getMessage()); - return false; - } - } - /** Pass a geometry representation through the SQL server */ private static Geometry viaSQL(String rep, Statement stat) throws SQLException { ResultSet rs = stat.executeQuery("SELECT geometry_in('" + rep + "')"); @@ -148,6 +379,46 @@ public class JtsTestParser { return ((JtsGeometry) rs.getObject(1)).getGeometry(); } + /** + * Pass a geometry representation through the SQL server via prepared + * statement + */ + private static Geometry viaPrepSQL(Geometry geom, Connection conn) throws SQLException { + PreparedStatement prep = conn.prepareStatement("SELECT ?::geometry"); + JtsGeometry wrapper = new JtsGeometry(geom); + prep.setObject(1, wrapper, Types.OTHER); + ResultSet rs = prep.executeQuery(); + rs.next(); + JtsGeometry resultwrapper = ((JtsGeometry) rs.getObject(1)); + return resultwrapper.getGeometry(); + } + + /** Pass a geometry representation through the SQL server via EWKT */ + private static Geometry ewktViaSQL(String rep, Statement stat) throws SQLException { + ResultSet rs = stat.executeQuery("SELECT asEWKT(geometry_in('" + rep + "'))"); + rs.next(); + String resrep = rs.getString(1); + return JtsGeometry.geomFromString(resrep); + } + + /** Pass a geometry representation through the SQL server via EWKB */ + private static Geometry ewkbViaSQL(String rep, Statement stat) throws SQLException { + ResultSet rs = stat.executeQuery("SELECT asEWKB(geometry_in('" + rep + "'))"); + rs.next(); + byte[] resrep = rs.getBytes(1); + return bp.parse(resrep); + } + + /** Pass a EWKB geometry representation through the server */ + private static Geometry binaryViaSQL(byte[] rep, Connection conn) throws SQLException { + PreparedStatement prep = conn.prepareStatement("SELECT ?::bytea::geometry"); + prep.setBytes(1, rep); + ResultSet rs = prep.executeQuery(); + rs.next(); + JtsGeometry resultwrapper = ((JtsGeometry) rs.getObject(1)); + return resultwrapper.getGeometry(); + } + /** * Connect to the databases * @@ -156,21 +427,23 @@ public class JtsTestParser { * * @param dbuser * - * @throws ClassNotFoundException - * * @see org.postgis.DriverWrapper * */ - public static Connection connect(String url, String dbuser, String dbpass) throws SQLException, - ClassNotFoundException { + public static Connection connect(String url, String dbuser, String dbpass) throws SQLException { Connection conn; - Class.forName("org.postgis.jts.JtsWrapper"); conn = DriverManager.getConnection(url, dbuser, dbpass); return conn; } + public static void loadDrivers() throws ClassNotFoundException { + Class.forName("org.postgis.jts.JtsWrapper"); + } + /** Our apps entry point */ public static void main(String[] args) throws SQLException, ClassNotFoundException { + loadDrivers(); + PGtokenizer dburls; String dbuser = null; String dbpass = null; @@ -185,8 +458,8 @@ public class JtsTestParser { dbuser = args[1]; dbpass = args[2]; } else { - System.err.println("Usage: java examples/JtsTestParser dburls user pass [tablename]"); - System.err.println(" or: java examples/JtsTestParser offline"); + System.err.println("Usage: java examples/TestParser dburls user pass [tablename]"); + System.err.println(" or: java examples/TestParser offline"); System.err.println(); System.err.println("dburls has one or more jdbc urls separated by ; in the following format"); System.err.println("jdbc:postgresql://HOST:PORT/DATABASENAME"); @@ -207,8 +480,8 @@ public class JtsTestParser { System.out.println("***"); for (int i = 0; i < testset.length; i++) { - test(testset[i], conns); - test(SRIDPREFIX + testset[i], conns); + test(testset[i][1], conns, testset[i][0]); + test(SRIDPREFIX + testset[i][1], conns, testset[i][0]); } System.out.print("cleaning up..."); @@ -216,7 +489,8 @@ public class JtsTestParser { conns[i].close(); } - // System.out.println("Finished."); System.out.println("Finished, " + failcount + " tests failed!"); + System.err.println("Finished, " + failcount + " tests failed!"); + System.exit(failcount); } } diff --git a/jdbc2/jtssrc/org/postgis/jts/JtsBinaryParser.java b/jdbc2/jtssrc/org/postgis/jts/JtsBinaryParser.java index cb21c4f99..4818d9f6d 100644 --- a/jdbc2/jtssrc/org/postgis/jts/JtsBinaryParser.java +++ b/jdbc2/jtssrc/org/postgis/jts/JtsBinaryParser.java @@ -58,7 +58,7 @@ import org.postgis.binary.ByteGetter.StringByteGetter; * */ public class JtsBinaryParser { - final static GeometryFactory geofac = new GeometryFactory(); + protected final GeometryFactory geofac = new GeometryFactory(); /** * Get the appropriate ValueGetter for my endianness @@ -118,6 +118,7 @@ public class JtsBinaryParser { if (haveS) { srid = data.getInt(); } + Geometry result1; switch (realtype) { case org.postgis.Geometry.POINT : diff --git a/jdbc2/jtssrc/org/postgis/jts/JtsBinaryWriter.java b/jdbc2/jtssrc/org/postgis/jts/JtsBinaryWriter.java index 099bbc463..0f64a897b 100644 --- a/jdbc2/jtssrc/org/postgis/jts/JtsBinaryWriter.java +++ b/jdbc2/jtssrc/org/postgis/jts/JtsBinaryWriter.java @@ -38,7 +38,7 @@ import org.postgis.binary.ValueSetter; /** * Create binary representation of geometries. Currently, only text rep (hexed) - * implementation is tested. + * implementation is tested. Supports only 2 dimensional geometries. * * It should be easy to add char[] and CharSequence ByteGetter instances, * although the latter one is not compatible with older jdks. @@ -114,29 +114,29 @@ public class JtsBinaryWriter { /** Parse a geometry starting at offset. */ protected void writeGeometry(Geometry geom, ValueSetter dest) { - if (geom.getDimension() < 2 || geom.getDimension() > 4) { - throw new IllegalArgumentException("Unsupported geometry dimensionality: " - + geom.getDimension()); + final int dimension = getCoordDim(geom); + if (dimension < 2 || dimension > 4) { + throw new IllegalArgumentException("Unsupported geometry dimensionality: " + dimension); } // write endian flag dest.setByte(dest.endian); // write typeword - int plaintype = getWKBType(geom); + final int plaintype = getWKBType(geom); int typeword = plaintype; - if (geom.getDimension() == 3 || geom.getDimension() == 4) { - typeword &= 0x80000000; + if (dimension == 3 || dimension == 4) { + typeword |= 0x80000000; } - if (geom.getDimension() == 4) { - typeword &= 0x40000000; + if (dimension == 4) { + typeword |= 0x40000000; } - if (geom.getSRID() != -1) { - typeword &= 0x20000000; + if (checkSrid(geom)) { + typeword |= 0x20000000; } dest.setInt(typeword); - if (geom.getSRID() != -1) { + if (checkSrid(geom)) { dest.setInt(geom.getSRID()); } @@ -193,7 +193,7 @@ public class JtsBinaryWriter { * ordinates and measure. Used by writeGeometry. */ private void writePoint(Point geom, ValueSetter dest) { - writeCoordinates(geom.getCoordinateSequence(), geom.getDimension(), dest); + writeCoordinates(geom.getCoordinateSequence(), getCoordDim(geom), dest); } /** @@ -219,7 +219,8 @@ public class JtsBinaryWriter { } private void writeLineString(LineString geom, ValueSetter dest) { - writeCoordinates(geom.getCoordinateSequence(), geom.getDimension(), dest); + dest.setInt(geom.getNumPoints()); + writeCoordinates(geom.getCoordinateSequence(), getCoordDim(geom), dest); } private void writePolygon(Polygon geom, ValueSetter dest) { @@ -231,25 +232,24 @@ public class JtsBinaryWriter { } private void writeMultiLineString(MultiLineString geom, ValueSetter dest) { - dest.setInt(geom.getNumGeometries()); - for (int i = 0; i < geom.getNumGeometries(); i++) { - writeLineString((LineString) geom.getGeometryN(i), dest); - } + writeGeometryArray(geom, dest); } private void writeMultiPolygon(MultiPolygon geom, ValueSetter dest) { - dest.setInt(geom.getNumGeometries()); - for (int i = 0; i < geom.getNumGeometries(); i++) { - writePolygon((Polygon) geom.getGeometryN(i), dest); - } + writeGeometryArray(geom, dest); } private void writeCollection(GeometryCollection geom, ValueSetter dest) { + writeGeometryArray(geom, dest); + } + + private void writeGeometryArray(Geometry geom, ValueSetter dest) { dest.setInt(geom.getNumGeometries()); for (int i = 0; i < geom.getNumGeometries(); i++) { writeGeometry(geom.getGeometryN(i), dest); } } + /** Estimate how much bytes a geometry will need in WKB. */ protected int estimateBytes(Geometry geom) { @@ -261,7 +261,7 @@ public class JtsBinaryWriter { // write typeword result += 4; - if (geom.getSRID() != -1) { + if (checkSrid(geom)) { result += 4; } @@ -293,8 +293,15 @@ public class JtsBinaryWriter { return result; } + private boolean checkSrid(Geometry geom) { + final int srid = geom.getSRID(); + // SRID is default 0 with jts geometries + final boolean result = srid != -1 && srid != 0; + return result; + } + private int estimatePoint(Point geom) { - return 8 * geom.getDimension(); + return 8*getCoordDim(geom); } /** Write an Array of "full" Geometries */ @@ -338,9 +345,11 @@ public class JtsBinaryWriter { } private int estimateLineString(LineString geom) { - return estimatePointArray(geom.getNumGeometries(), (Point) (geom.getNumGeometries() > 0 - ? geom.getGeometryN(0) - : null)); + if (geom == null || geom.getNumGeometries() == 0) { + return 0; + } else { + return estimatePointArray(geom.getNumPoints(), geom.getStartPoint()); + } } private int estimatePolygon(Polygon geom) { @@ -367,4 +376,14 @@ public class JtsBinaryWriter { // 4-byte count + subgeometries return 4 + estimateGeometryArray(geom); } + + public static final int getCoordDim(Geometry geom) { + // TODO: Fix geometries with more dimensions + //geom.getFactory().getCoordinateSequenceFactory() + if (geom == null) { + return 0; + } else { + return 2; + } + } } diff --git a/jdbc2/jtssrc/org/postgis/jts/JtsGeometry.java b/jdbc2/jtssrc/org/postgis/jts/JtsGeometry.java index 5407be11d..fd068a567 100644 --- a/jdbc2/jtssrc/org/postgis/jts/JtsGeometry.java +++ b/jdbc2/jtssrc/org/postgis/jts/JtsGeometry.java @@ -33,7 +33,8 @@ import org.postgresql.util.PGobject; import java.sql.SQLException; /** - * JTS Geometry SQL wrapper + * JTS Geometry SQL wrapper. Supports PostGIS 1.x (lwgeom hexwkb) for writing + * and both PostGIS 0.x (EWKT) and 1.x (lwgeom hexwkb) for reading. * * @author Markus Schaber */ @@ -46,6 +47,7 @@ public class JtsGeometry extends PGobject { final static WKTReader reader = new WKTReader(); final static JtsBinaryParser bp = new JtsBinaryParser(); + final static JtsBinaryWriter bw = new JtsBinaryWriter(); /** Constructor called by JDBC drivers */ public JtsGeometry() { @@ -99,7 +101,7 @@ public class JtsGeometry extends PGobject { } public String getValue() { - return geom.toString(); + return bw.writeHexed(getGeometry()); } public Object clone() { diff --git a/jdbc2/jtssrc/org/postgis/jts/JtsGisWrapper.java b/jdbc2/jtssrc/org/postgis/jts/JtsGisWrapper.java index cfeaf6373..bee777489 100644 --- a/jdbc2/jtssrc/org/postgis/jts/JtsGisWrapper.java +++ b/jdbc2/jtssrc/org/postgis/jts/JtsGisWrapper.java @@ -40,7 +40,7 @@ import java.util.Properties; * This method currently works with J2EE DataSource implementations, and with * DriverManager framework. * - * Simply replace the "jdbc:postgresql:" with a "jdbc:postgresql_postGIS" in the + * Simply replace the "jdbc:postgresql:" with a "jdbc:postgresql_JTS" in the * jdbc URL. * * @author markus.schaber@logix-tt.com diff --git a/jdbc2/src/org/postgis/binary/ByteSetter.java b/jdbc2/src/org/postgis/binary/ByteSetter.java index a0b5320c9..e5d8d7707 100644 --- a/jdbc2/src/org/postgis/binary/ByteSetter.java +++ b/jdbc2/src/org/postgis/binary/ByteSetter.java @@ -46,6 +46,14 @@ public abstract class ByteSetter { public byte[] result() { return array; } + + public String toString() { + char[] arr = new char[array.length]; + for (int i=0; i