|
From: <svn...@os...> - 2012-05-17 17:33:27
|
Author: jdeolive
Date: 2012-05-17 10:33:16 -0700 (Thu, 17 May 2012)
New Revision: 38743
Modified:
branches/2.7.x/modules/library/jdbc/src/test/java/org/geotools/jdbc/JDBC3DTest.java
branches/2.7.x/modules/library/main/src/main/java/org/geotools/geometry/jts/LiteCoordinateSequenceFactory.java
branches/2.7.x/modules/plugin/jdbc/jdbc-oracle/src/main/java/org/geotools/data/oracle/sdo/Coordinates.java
branches/2.7.x/modules/plugin/jdbc/jdbc-oracle/src/test/java/org/geotools/data/oracle/Oracle3DTest.java
branches/2.7.x/modules/plugin/jdbc/jdbc-oracle/src/test/java/org/geotools/data/oracle/OracleTestSetup.java
Log:
GEOT-4140, Fix for Oracle not handling read/write of 3D Polygons correctly
Modified: branches/2.7.x/modules/library/jdbc/src/test/java/org/geotools/jdbc/JDBC3DTest.java
===================================================================
--- branches/2.7.x/modules/library/jdbc/src/test/java/org/geotools/jdbc/JDBC3DTest.java 2012-05-17 17:01:52 UTC (rev 38742)
+++ branches/2.7.x/modules/library/jdbc/src/test/java/org/geotools/jdbc/JDBC3DTest.java 2012-05-17 17:33:16 UTC (rev 38743)
@@ -16,13 +16,17 @@
*/
package org.geotools.jdbc;
+import java.util.Arrays;
+import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
+import java.util.Map;
import org.geotools.data.DataUtilities;
import org.geotools.data.DefaultQuery;
import org.geotools.data.FeatureReader;
import org.geotools.data.FeatureWriter;
+import org.geotools.data.Query;
import org.geotools.data.Transaction;
import org.geotools.data.simple.SimpleFeatureCollection;
import org.geotools.data.simple.SimpleFeatureIterator;
@@ -32,6 +36,7 @@
import org.geotools.factory.Hints;
import org.geotools.feature.FeatureCollection;
import org.geotools.feature.simple.SimpleFeatureBuilder;
+import org.geotools.geometry.jts.LiteCoordinateSequence;
import org.geotools.geometry.jts.LiteCoordinateSequenceFactory;
import org.geotools.geometry.jts.ReferencedEnvelope;
import org.geotools.referencing.CRS;
@@ -43,6 +48,7 @@
import org.opengis.referencing.crs.CoordinateReferenceSystem;
import com.vividsolutions.jts.geom.Coordinate;
+import com.vividsolutions.jts.geom.CoordinateSequenceFactory;
import com.vividsolutions.jts.geom.Envelope;
import com.vividsolutions.jts.geom.Geometry;
import com.vividsolutions.jts.geom.GeometryFactory;
@@ -55,12 +61,12 @@
* Tests the ability of the datastore to cope with 3D data
*
* @author Andrea Aime - OpenGeo
+ * @author Martin Davis - OpenGeo
*
- *
* @source $URL$
*/
public abstract class JDBC3DTest extends JDBCTestSupport {
-
+
protected static final String LINE3D = "line3d";
protected static final String POLY3D = "poly3d";
@@ -78,12 +84,10 @@
protected SimpleFeatureType poly3DType;
protected SimpleFeatureType line3DType;
-
+
protected CoordinateReferenceSystem epsg4326;
protected abstract JDBC3DTestSetup createTestSetup();
-
-
@Override
protected void connect() throws Exception {
@@ -96,22 +100,21 @@
poly3DType = DataUtilities.createType(dataStore.getNamespaceURI() + "." + tname(POLY3D),
aname(ID) + ":0," + aname(GEOM) + ":Polygon:srid=4326," + aname(NAME) + ":String");
poly3DType.getGeometryDescriptor().getUserData().put(Hints.COORDINATE_DIMENSION, 3);
-
+
epsg4326 = CRS.decode("EPSG:4326");
}
-
protected Integer getNativeSRID() {
return new Integer(4326);
}
-
+
public void testSchema() throws Exception {
SimpleFeatureType schema = dataStore.getSchema(tname(LINE3D));
CoordinateReferenceSystem crs = schema.getGeometryDescriptor()
.getCoordinateReferenceSystem();
assertEquals(new Integer(4326), CRS.lookupEpsgCode(crs, false));
- assertEquals(getNativeSRID(), schema.getGeometryDescriptor().getUserData().get(
- JDBCDataStore.JDBC_NATIVE_SRID));
+ assertEquals(getNativeSRID(),
+ schema.getGeometryDescriptor().getUserData().get(JDBCDataStore.JDBC_NATIVE_SRID));
}
public void testReadPoint() throws Exception {
@@ -124,7 +127,7 @@
}
public void testReadLine() throws Exception {
- SimpleFeatureCollection fc = dataStore.getFeatureSource(tname(LINE3D)).getFeatures();
+ SimpleFeatureCollection fc = dataStore.getFeatureSource(tname(LINE3D)).getFeatures();
SimpleFeatureIterator fr = fc.features();
assertTrue(fr.hasNext());
LineString ls = (LineString) fr.next().getDefaultGeometry();
@@ -148,40 +151,82 @@
"l3" }, null);
// insert it
- SimpleFeatureStore fs = (SimpleFeatureStore) dataStore
- .getFeatureSource(tname(LINE3D), Transaction.AUTO_COMMIT);
+ SimpleFeatureStore fs = (SimpleFeatureStore) dataStore.getFeatureSource(tname(LINE3D),
+ Transaction.AUTO_COMMIT);
List<FeatureId> fids = fs.addFeatures(DataUtilities.collection(newFeature));
// retrieve it back
- SimpleFeatureIterator fi = fs.getFeatures(FF.id(new HashSet<FeatureId>(fids)))
- .features();
+ SimpleFeatureIterator fi = fs.getFeatures(FF.id(new HashSet<FeatureId>(fids))).features();
assertTrue(fi.hasNext());
SimpleFeature f = fi.next();
assertTrue(ls.equals((Geometry) f.getDefaultGeometry()));
fi.close();
}
+ public void testCreateSchemaAndInsertPolyTriangle() throws Exception {
+ LiteCoordinateSequenceFactory csf = new LiteCoordinateSequenceFactory();
+ GeometryFactory gf = new GeometryFactory(csf);
+
+ LinearRing shell = gf.createLinearRing(csf.create(new double[] { 0, 0, 99, 1, 0, 33, 1, 1,
+ 66, 0, 0, 99 }, 3));
+ Polygon poly = gf.createPolygon(shell, null);
+
+ checkCreateSchemaAndInsert(poly);
+ }
+
+ public void testCreateSchemaAndInsertPolyRectangle() throws Exception {
+ LiteCoordinateSequenceFactory csf = new LiteCoordinateSequenceFactory();
+ GeometryFactory gf = new GeometryFactory(csf);
+
+ LinearRing shell = gf.createLinearRing(csf.create(new double[] { 0, 0, 99, 1, 0, 33, 1, 1,
+ 66, 0, 1, 33, 0, 0, 99 }, 3));
+ Polygon poly = gf.createPolygon(shell, null);
+
+ checkCreateSchemaAndInsert(poly);
+ }
+
+ public void testCreateSchemaAndInsertPolyRectangleWithHole() throws Exception {
+ LiteCoordinateSequenceFactory csf = new LiteCoordinateSequenceFactory();
+ GeometryFactory gf = new GeometryFactory(csf);
+
+ LinearRing shell = gf.createLinearRing(csf.create(new double[] { 0, 0, 99, 10, 0, 33, 10,
+ 10, 66, 0, 10, 66, 0, 0, 99 }, 3));
+ LinearRing hole = gf.createLinearRing(csf.create(new double[] { 2, 2, 99, 3, 2, 44, 3, 3,
+ 99, 2, 3, 99, 2, 2, 99 }, 3));
+ Polygon poly = gf.createPolygon(shell, new LinearRing[] { hole });
+
+ checkCreateSchemaAndInsert(poly);
+ }
+
+ public void testCreateSchemaAndInsertPolyWithHoleCW() throws Exception {
+ LiteCoordinateSequenceFactory csf = new LiteCoordinateSequenceFactory();
+ GeometryFactory gf = new GeometryFactory(csf);
+
+ LinearRing shell = gf.createLinearRing(csf.create(new double[] { 1, 1, 99, 10, 1, 33,
+ 10, 10, 66, 1, 10, 66, 1, 1, 99 }, 3));
+ LinearRing hole = gf.createLinearRing(csf.create(new double[] { 2, 2, 99, 8, 2, 44, 8, 8,
+ 99, 2, 8, 99, 2, 2, 99 }, 3));
+ Polygon poly = gf.createPolygon(shell, new LinearRing[] { hole });
+
+ checkCreateSchemaAndInsert(poly);
+ }
+
/**
- * Creates the polygon schema and then inserts a 3D geometry into the
- * datastore and retrieves it back to make sure 3d data is really handled as
- * such
+ * Creates the polygon schema, inserts a 3D geometry into the datastore,
+ * and retrieves it back to make sure 3d data is preserved.
*
* @throws Exception
*/
- public void testCreateSchemaAndInsert() throws Exception {
+ private void checkCreateSchemaAndInsert(Geometry poly) throws Exception {
dataStore.createSchema(poly3DType);
SimpleFeatureType actualSchema = dataStore.getSchema(tname(POLY3D));
assertFeatureTypesEqual(poly3DType, actualSchema);
- assertEquals(getNativeSRID(), actualSchema.getGeometryDescriptor().getUserData().get(
- JDBCDataStore.JDBC_NATIVE_SRID));
+ assertEquals(
+ getNativeSRID(),
+ actualSchema.getGeometryDescriptor().getUserData()
+ .get(JDBCDataStore.JDBC_NATIVE_SRID));
- // build a 3d polygon (ordinates in ccw order)
- GeometryFactory gf = new GeometryFactory();
- LinearRing shell = gf.createLinearRing(new Coordinate[] { new Coordinate(0, 0, 0),
- new Coordinate(1, 1, 1), new Coordinate(1, 0, 1), new Coordinate(0, 0, 0) });
- Polygon poly = gf.createPolygon(shell, null);
-
- // insert it
+ // insert the feature
FeatureWriter<SimpleFeatureType, SimpleFeature> fw = dataStore.getFeatureWriterAppend(
tname(POLY3D), Transaction.AUTO_COMMIT);
SimpleFeature f = fw.next();
@@ -191,20 +236,62 @@
fw.write();
fw.close();
- // read id back and compare
+ // read feature back
+
+ /**
+ * Use a LiteCoordinateSequence, since this mimics GeoServer behaviour better,
+ * and it exposes bugs in CoordinateSequence handling.
+ */
+ final Hints hints = new Hints();
+ hints.put(Hints.JTS_COORDINATE_SEQUENCE_FACTORY, new LiteCoordinateSequenceFactory());
+ Query query = new DefaultQuery(tname(POLY3D));
+ query.setHints(hints);
+
FeatureReader<SimpleFeatureType, SimpleFeature> fr = dataStore.getFeatureReader(
- new DefaultQuery(tname(POLY3D)), Transaction.AUTO_COMMIT);
+ query, Transaction.AUTO_COMMIT);
assertTrue(fr.hasNext());
f = fr.next();
- // this unfortunately checks only the first 2d, but at the same time
- // a coordinate by coordinate check is not possible since the ring orientation
- // can be modified by the store
- assertTrue(poly.equals((Geometry) f.getDefaultGeometry()));
-
+
+ /**
+ * Check the geometries are topologically equal.
+ * Check that the Z values are preserved
+ */
+ Geometry fgeom = (Geometry) f.getDefaultGeometry();
+ assertTrue("2D topology does not match", poly.equals(fgeom));
+ assertTrue("Z values do not match", hasMatchingZValues(poly, fgeom));
fr.close();
}
/**
+ * Tests whether two geometries have the same Z values for coordinates with identical 2D locations. Requires that each geometry is internally
+ * location-consistent in Z; that is, if two coordinates are identical in location, then the Z values are equal. This should always be the case
+ * for valid data.
+ *
+ * @param g1
+ * @param g2
+ * @return true if the geometries are location-equal in Z
+ */
+ private static boolean hasMatchingZValues(Geometry g1, Geometry g2) {
+ Coordinate[] pt1 = g1.getCoordinates();
+ Map<Coordinate, Double> coordZMap = new HashMap<Coordinate, Double>();
+ for (int i = 0; i < pt1.length; i++) {
+ coordZMap.put(pt1[i], pt1[i].z);
+ }
+
+ Coordinate[] pt2 = g2.getCoordinates();
+
+ for (int i2 = 0; i2 < pt2.length; i2++) {
+ Coordinate p2 = pt2[i2];
+ double z = coordZMap.get(p2);
+ boolean isEqualZ = p2.z == z || (Double.isNaN(p2.z) && Double.isNaN(z));
+ if (!isEqualZ)
+ return false;
+ }
+
+ return true;
+ }
+
+ /**
* Make sure we can properly retrieve the bounds of 3d layers
*
* @throws Exception
@@ -232,11 +319,11 @@
new LiteCoordinateSequenceFactory());
q.setHints(hints);
- // check the srs you get is the expected one
- FeatureCollection fc = fs.getFeatures(q);
- FeatureType fcSchema = fc.getSchema();
+ // check the srs you get is the expected one
+ FeatureCollection fc = fs.getFeatures(q);
+ FeatureType fcSchema = fc.getSchema();
assertEquals(epsg4326, fcSchema.getCoordinateReferenceSystem());
- assertEquals(epsg4326, fcSchema.getGeometryDescriptor().getCoordinateReferenceSystem());
+ assertEquals(epsg4326, fcSchema.getGeometryDescriptor().getCoordinateReferenceSystem());
// build up the reference 2d line, the 3d one is (1 1 0, 2 2 0, 4 2 1, 5
// 1 1)
@@ -245,7 +332,8 @@
new Coordinate(5, 1) });
// check feature reader and the schema
- FeatureReader<SimpleFeatureType, SimpleFeature> fr = dataStore.getFeatureReader(q, Transaction.AUTO_COMMIT);
+ FeatureReader<SimpleFeatureType, SimpleFeature> fr = dataStore.getFeatureReader(q,
+ Transaction.AUTO_COMMIT);
assertEquals(epsg4326, fr.getFeatureType().getCoordinateReferenceSystem());
assertEquals(epsg4326, fr.getFeatureType().getGeometryDescriptor()
.getCoordinateReferenceSystem());
Modified: branches/2.7.x/modules/library/main/src/main/java/org/geotools/geometry/jts/LiteCoordinateSequenceFactory.java
===================================================================
--- branches/2.7.x/modules/library/main/src/main/java/org/geotools/geometry/jts/LiteCoordinateSequenceFactory.java 2012-05-17 17:01:52 UTC (rev 38742)
+++ branches/2.7.x/modules/library/main/src/main/java/org/geotools/geometry/jts/LiteCoordinateSequenceFactory.java 2012-05-17 17:33:16 UTC (rev 38743)
@@ -41,6 +41,12 @@
* @see com.vividsolutions.jts.geom.CoordinateSequenceFactory#create(com.vividsolutions.jts.geom.CoordinateSequence)
*/
public CoordinateSequence create(CoordinateSequence coordSeq) {
+ /**
+ * If copying a LiteCoordinateSequence, use the copy constructor
+ * to preserve dimensionality information.
+ */
+ if (coordSeq instanceof LiteCoordinateSequence)
+ return new LiteCoordinateSequence((LiteCoordinateSequence) coordSeq);
return new LiteCoordinateSequence(coordSeq.toCoordinateArray());
}
Modified: branches/2.7.x/modules/plugin/jdbc/jdbc-oracle/src/main/java/org/geotools/data/oracle/sdo/Coordinates.java
===================================================================
--- branches/2.7.x/modules/plugin/jdbc/jdbc-oracle/src/main/java/org/geotools/data/oracle/sdo/Coordinates.java 2012-05-17 17:01:52 UTC (rev 38742)
+++ branches/2.7.x/modules/plugin/jdbc/jdbc-oracle/src/main/java/org/geotools/data/oracle/sdo/Coordinates.java 2012-05-17 17:33:16 UTC (rev 38743)
@@ -26,6 +26,7 @@
import com.vividsolutions.jts.geom.CoordinateList;
import com.vividsolutions.jts.geom.CoordinateSequence;
import com.vividsolutions.jts.geom.CoordinateSequenceFactory;
+import com.vividsolutions.jts.geom.CoordinateSequences;
import com.vividsolutions.jts.geom.PrecisionModel;
@@ -172,15 +173,13 @@
return c;
}
- Coordinate[] array = new Coordinate[toIndex - fromIndex];
- int index = 0;
- for(int i = fromIndex; i < toIndex; i++, index++) {
- array[index] = sequence.getCoordinate(i);
- }
+ // handle coordinate sequence dimension correctly
+ int size = toIndex - fromIndex;
+ CoordinateSequence newSeq = factory.create(size, sequence.getDimension());
+ CoordinateSequences.copy(sequence, fromIndex, newSeq, 0, size);
+ return newSeq;
+ }
- return factory.create(array);
- }
-
/**
* DOCUMENT ME!
*
@@ -213,11 +212,11 @@
return c;
} else // else CoordinateSequence
- {
- CoordinateList list = new CoordinateList(sequence.toCoordinateArray());
- Collections.reverse(list);
-
- return factory.create(list.toCoordinateArray());
+ {
+ // handle coordinate sequence dimension correctly
+ CoordinateSequence revSeq = factory.create(sequence);
+ CoordinateSequences.reverse(revSeq);
+ return revSeq;
}
}
Modified: branches/2.7.x/modules/plugin/jdbc/jdbc-oracle/src/test/java/org/geotools/data/oracle/Oracle3DTest.java
===================================================================
--- branches/2.7.x/modules/plugin/jdbc/jdbc-oracle/src/test/java/org/geotools/data/oracle/Oracle3DTest.java 2012-05-17 17:01:52 UTC (rev 38742)
+++ branches/2.7.x/modules/plugin/jdbc/jdbc-oracle/src/test/java/org/geotools/data/oracle/Oracle3DTest.java 2012-05-17 17:33:16 UTC (rev 38743)
@@ -26,5 +26,13 @@
return new Oracle3DTestSetup();
}
+ /**
+ * This test is overriden to disable it, since it is a known issue.
+ * The issue is that the Oracle driver writes Rectangles as Oracle SDO Rectangle structures, which don't preserve 3D
+ * See GEOT-4133
+ */
+ @Override
+ public void testCreateSchemaAndInsertPolyRectangle() throws Exception {
+ }
}
Modified: branches/2.7.x/modules/plugin/jdbc/jdbc-oracle/src/test/java/org/geotools/data/oracle/OracleTestSetup.java
===================================================================
--- branches/2.7.x/modules/plugin/jdbc/jdbc-oracle/src/test/java/org/geotools/data/oracle/OracleTestSetup.java 2012-05-17 17:01:52 UTC (rev 38742)
+++ branches/2.7.x/modules/plugin/jdbc/jdbc-oracle/src/test/java/org/geotools/data/oracle/OracleTestSetup.java 2012-05-17 17:33:16 UTC (rev 38743)
@@ -54,7 +54,8 @@
fixture.put("host", "192.168.1.200");
fixture.put("port", "1521");
fixture.put("database", "xe");
- fixture.put("username", "geoserver");
+ fixture.put("usernamegit ", "geoserver");
+ fixture.put("user", "geoserver");
fixture.put("password", "postgis");
fixture.put("dbtype", "Oracle" );
return fixture;
|