Author: mdavis Date: 2012-05-15 14:21:56 -0700 (Tue, 15 May 2012) New Revision: 38733 Added: trunk/modules/library/main/src/test/java/org/geotools/geometry/jts/coordinatesequence/ trunk/modules/library/main/src/test/java/org/geotools/geometry/jts/coordinatesequence/CoordinateSequencesTest.java Modified: trunk/modules/extension/xsd/xsd-gml3/src/main/java/org/geotools/gml3/bindings/AbstractGeometryTypeBinding.java trunk/modules/extension/xsd/xsd-gml3/src/main/java/org/geotools/gml3/bindings/DirectPositionListTypeBinding.java trunk/modules/extension/xsd/xsd-gml3/src/main/java/org/geotools/gml3/bindings/DirectPositionTypeBinding.java trunk/modules/extension/xsd/xsd-gml3/src/main/java/org/geotools/gml3/bindings/EnvelopeTypeBinding.java trunk/modules/extension/xsd/xsd-gml3/src/main/java/org/geotools/gml3/bindings/GML3EncodingUtils.java trunk/modules/extension/xsd/xsd-gml3/src/main/java/org/geotools/gml3/bindings/PointTypeBinding.java trunk/modules/extension/xsd/xsd-gml3/src/test/java/org/geotools/gml3/GML3TestSupport.java trunk/modules/extension/xsd/xsd-gml3/src/test/java/org/geotools/gml3/bindings/DirectPositionListTypeBindingTest.java trunk/modules/extension/xsd/xsd-gml3/src/test/java/org/geotools/gml3/bindings/DirectPositionTypeBindingTest.java trunk/modules/extension/xsd/xsd-gml3/src/test/java/org/geotools/gml3/bindings/GML3MockData.java trunk/modules/extension/xsd/xsd-gml3/src/test/java/org/geotools/gml3/bindings/LineStringTypeBindingTest.java trunk/modules/extension/xsd/xsd-gml3/src/test/java/org/geotools/gml3/bindings/MultiLineStringTypeBindingTest.java trunk/modules/extension/xsd/xsd-gml3/src/test/java/org/geotools/gml3/bindings/PointTypeBindingTest.java trunk/modules/extension/xsd/xsd-gml3/src/test/java/org/geotools/gml3/bindings/PolygonTypeBindingTest.java trunk/modules/library/main/src/main/java/org/geotools/geometry/jts/coordinatesequence/CoordinateSequences.java trunk/modules/library/xml/src/test/java/org/geotools/GMLTest.java Log: GEOT-4136, handling 3D data in gml3 encoding Modified: trunk/modules/extension/xsd/xsd-gml3/src/main/java/org/geotools/gml3/bindings/AbstractGeometryTypeBinding.java =================================================================== --- trunk/modules/extension/xsd/xsd-gml3/src/main/java/org/geotools/gml3/bindings/AbstractGeometryTypeBinding.java 2012-05-15 21:21:38 UTC (rev 38732) +++ trunk/modules/extension/xsd/xsd-gml3/src/main/java/org/geotools/gml3/bindings/AbstractGeometryTypeBinding.java 2012-05-15 21:21:56 UTC (rev 38733) @@ -18,6 +18,7 @@ import javax.xml.namespace.QName; +import org.geotools.geometry.jts.coordinatesequence.CoordinateSequences; import org.geotools.gml3.GML; import org.geotools.xml.AbstractComplexBinding; import org.geotools.xml.ElementInstance; @@ -116,10 +117,12 @@ } if ("srsDimension".equals(name.getLocalPart())) { - CoordinateReferenceSystem crs = GML3EncodingUtils.getCRS(geometry); - if (crs != null) { - return crs.getCoordinateSystem().getDimension(); - } + /** + * For the dimension, use the actual dimension of the geometry. Using + * the dimension of the CRS is not sufficient, since currently CRSes + * don't support 3D. + */ + return CoordinateSequences.coordinateDimension(geometry); } // FIXME: should be gml:id, but which GML? Modified: trunk/modules/extension/xsd/xsd-gml3/src/main/java/org/geotools/gml3/bindings/DirectPositionListTypeBinding.java =================================================================== --- trunk/modules/extension/xsd/xsd-gml3/src/main/java/org/geotools/gml3/bindings/DirectPositionListTypeBinding.java 2012-05-15 21:21:38 UTC (rev 38732) +++ trunk/modules/extension/xsd/xsd-gml3/src/main/java/org/geotools/gml3/bindings/DirectPositionListTypeBinding.java 2012-05-15 21:21:56 UTC (rev 38733) @@ -22,6 +22,7 @@ import org.geotools.geometry.DirectPosition1D; import org.geotools.geometry.DirectPosition2D; +import org.geotools.geometry.jts.coordinatesequence.CoordinateSequences; import org.geotools.gml3.GML; import org.geotools.xml.AbstractComplexBinding; import org.geotools.xml.ElementInstance; @@ -31,6 +32,8 @@ import org.w3c.dom.Document; import org.w3c.dom.Element; +import com.vividsolutions.jts.geom.CoordinateSequence; + /** * Binding object for the type * http://www.opengis.net/gml:DirectPositionListType. @@ -86,7 +89,7 @@ * @generated modifiable */ public Class getType() { - return DirectPosition[].class; + return CoordinateSequence.class; } /** @@ -144,21 +147,36 @@ return dps; } + /** + * + * @param object a CoordinateSequence + * + * @see org.geotools.xml.AbstractComplexBinding#encode(java.lang.Object, org.w3c.dom.Document, org.w3c.dom.Element) + */ public Element encode(Object object, Document document, Element value) throws Exception { // TODO: remove this when the parser can do lists - DirectPosition[] dps = (DirectPosition[]) object; + CoordinateSequence cs = (CoordinateSequence) object; StringBuffer sb = new StringBuffer(); - for (int i = 0; i < dps.length; i++) { - sb.append(dps[i].getOrdinate(0) + " " + dps[i].getOrdinate(1)); + int dim = CoordinateSequences.coordinateDimension(cs); + int size = cs.size(); + int nOrdWithSpace = size * dim - 1; + int count = 0; + for (int i = 0; i < size; i++) { + for (int d = 0; d < dim; d++) { + sb.append(cs.getOrdinate(i, d)); + + if (count < nOrdWithSpace) { + sb.append(" "); + } + count++; - if (i < (dps.length - 1)) { - sb.append(" "); - } + } } value.appendChild(document.createTextNode(sb.toString())); return value; } + } Modified: trunk/modules/extension/xsd/xsd-gml3/src/main/java/org/geotools/gml3/bindings/DirectPositionTypeBinding.java =================================================================== --- trunk/modules/extension/xsd/xsd-gml3/src/main/java/org/geotools/gml3/bindings/DirectPositionTypeBinding.java 2012-05-15 21:21:38 UTC (rev 38732) +++ trunk/modules/extension/xsd/xsd-gml3/src/main/java/org/geotools/gml3/bindings/DirectPositionTypeBinding.java 2012-05-15 21:21:56 UTC (rev 38733) @@ -29,6 +29,7 @@ import org.w3c.dom.Document; import org.w3c.dom.Element; +import com.vividsolutions.jts.geom.CoordinateSequence; import com.vividsolutions.jts.geom.GeometryFactory; @@ -87,7 +88,7 @@ * @generated modifiable */ public Class getType() { - return DirectPosition2D.class; + return CoordinateSequence.class; } /** @@ -118,21 +119,27 @@ public Element encode(Object object, Document document, Element value) throws Exception { - DirectPosition dp = (DirectPosition) object; + CoordinateSequence cs = (CoordinateSequence) object; - double[] coordinates = dp.getCoordinate(); - StringBuffer sb = new StringBuffer(); - for (int i = 0; i < coordinates.length; i++) { - sb.append(String.valueOf(coordinates[i])); + // assume either zero or one coordinate + if (cs.size() >= 1) { + int dim = cs.getDimension(); + for (int d = 0; d < dim; d++) { + double v = cs.getOrdinate(0, d); + if (Double.isNaN(v) && d > 1) { + continue; + } - if (i != (coordinates.length - 1)) { - sb.append(" "); + // separator char is a blank + sb.append(String.valueOf(v)).append(" "); } + if (dim > 0) { + sb.setLength(sb.length()-1); + } } - //Element pos = document.createElementNS(GML.pos.getNamespaceURI(), GML.pos.getLocalPart()); value.appendChild(document.createTextNode(sb.toString())); return value; Modified: trunk/modules/extension/xsd/xsd-gml3/src/main/java/org/geotools/gml3/bindings/EnvelopeTypeBinding.java =================================================================== --- trunk/modules/extension/xsd/xsd-gml3/src/main/java/org/geotools/gml3/bindings/EnvelopeTypeBinding.java 2012-05-15 21:21:38 UTC (rev 38732) +++ trunk/modules/extension/xsd/xsd-gml3/src/main/java/org/geotools/gml3/bindings/EnvelopeTypeBinding.java 2012-05-15 21:21:56 UTC (rev 38733) @@ -20,7 +20,7 @@ import javax.xml.namespace.QName; -import org.geotools.geometry.DirectPosition2D; +import org.geotools.geometry.jts.LiteCoordinateSequence; import org.geotools.geometry.jts.ReferencedEnvelope; import org.geotools.gml3.GML; import org.geotools.xml.AbstractComplexBinding; @@ -166,11 +166,11 @@ } if (name.getLocalPart().equals("lowerCorner")) { - return new DirectPosition2D(envelope.getMinX(), envelope.getMinY()); + return new LiteCoordinateSequence(new double[] { envelope.getMinX(), envelope.getMinY() }, 2); } if (name.getLocalPart().equals("upperCorner")) { - return new DirectPosition2D(envelope.getMaxX(), envelope.getMaxY()); + return new LiteCoordinateSequence(new double[] { envelope.getMaxX(), envelope.getMaxY() }, 2); } if (envelope instanceof ReferencedEnvelope) { Modified: trunk/modules/extension/xsd/xsd-gml3/src/main/java/org/geotools/gml3/bindings/GML3EncodingUtils.java =================================================================== --- trunk/modules/extension/xsd/xsd-gml3/src/main/java/org/geotools/gml3/bindings/GML3EncodingUtils.java 2012-05-15 21:21:38 UTC (rev 38732) +++ trunk/modules/extension/xsd/xsd-gml3/src/main/java/org/geotools/gml3/bindings/GML3EncodingUtils.java 2012-05-15 21:21:56 UTC (rev 38733) @@ -28,7 +28,6 @@ import org.eclipse.xsd.XSDElementDeclaration; import org.geotools.feature.NameImpl; -import org.geotools.geometry.DirectPosition2D; import org.geotools.gml2.bindings.GML2EncodingUtils; import org.geotools.gml2.bindings.GMLEncodingUtils; import org.geotools.gml3.GML; @@ -45,7 +44,6 @@ import org.opengis.feature.simple.SimpleFeature; import org.opengis.feature.type.Name; import org.opengis.filter.identity.FeatureId; -import org.opengis.geometry.DirectPosition; import org.opengis.referencing.crs.CoordinateReferenceSystem; import org.w3c.dom.Document; import org.w3c.dom.Element; @@ -85,20 +83,8 @@ e = new GMLEncodingUtils(gml); } - static DirectPosition[] positions(LineString line) { - CoordinateSequence coordinates = line.getCoordinateSequence(); - DirectPosition[] dps = new DirectPosition[coordinates.size()]; - - double x; - double y; - - for (int i = 0; i < dps.length; i++) { - x = coordinates.getOrdinate(i, 0); - y = coordinates.getOrdinate(i, 1); - dps[i] = new DirectPosition2D(x, y); - } - - return dps; + static CoordinateSequence positions(LineString line) { + return line.getCoordinateSequence(); } static URI toURI(CoordinateReferenceSystem crs) { Modified: trunk/modules/extension/xsd/xsd-gml3/src/main/java/org/geotools/gml3/bindings/PointTypeBinding.java =================================================================== --- trunk/modules/extension/xsd/xsd-gml3/src/main/java/org/geotools/gml3/bindings/PointTypeBinding.java 2012-05-15 21:21:38 UTC (rev 38732) +++ trunk/modules/extension/xsd/xsd-gml3/src/main/java/org/geotools/gml3/bindings/PointTypeBinding.java 2012-05-15 21:21:56 UTC (rev 38733) @@ -143,12 +143,7 @@ if ("pos".equals(name.getLocalPart())) { Point point = (Point) object; - - DirectPosition2D dp = new DirectPosition2D(); - dp.setOrdinate(0, point.getX()); - dp.setOrdinate(1, point.getY()); - - return dp; + return point.getCoordinateSequence(); } return null; Modified: trunk/modules/extension/xsd/xsd-gml3/src/test/java/org/geotools/gml3/GML3TestSupport.java =================================================================== --- trunk/modules/extension/xsd/xsd-gml3/src/test/java/org/geotools/gml3/GML3TestSupport.java 2012-05-15 21:21:38 UTC (rev 38732) +++ trunk/modules/extension/xsd/xsd-gml3/src/test/java/org/geotools/gml3/GML3TestSupport.java 2012-05-15 21:21:56 UTC (rev 38733) @@ -18,8 +18,11 @@ import org.geotools.xml.Configuration; import org.geotools.xml.test.XMLTestSupport; +import org.w3c.dom.Document; import org.w3c.dom.Element; +import org.w3c.dom.NamedNodeMap; import org.w3c.dom.Node; +import org.w3c.dom.NodeList; /* * Test bindings by extending this class with test cases that follow this pattern: @@ -80,7 +83,53 @@ protected Configuration createConfiguration() { return new GMLConfiguration(enableExtendedArcSurfaceSupport()); } + + protected void checkPosOrdinates(Document doc, int expectedNumOrdinates) + { + checkOrdinates(doc, GML.pos.getLocalPart(), expectedNumOrdinates); + } + protected void checkPosListOrdinates(Document doc, int expectedNumOrdinates) + { + checkOrdinates(doc, GML.posList.getLocalPart(), expectedNumOrdinates); + } + + + /** + * Checks that a posList exists, has a string as content, + * and the string encodes nOrdinates ordinates correctly + * (i.e. blank-separated). + * + * @param doc + * @param expectedNumOrdinates + */ + private void checkOrdinates(Document doc, String ordTag, int expectedNumOrdinates) { + NodeList nl = doc.getElementsByTagNameNS(GML.NAMESPACE, ordTag); + Node posListNode = nl.item(0); + assertEquals(1, posListNode.getChildNodes().getLength()); + String content = posListNode.getChildNodes().item(0).getNodeValue(); + String[] ord = content.split("\\s+"); + assertEquals(expectedNumOrdinates, ord.length); + } + + /** + * Checks that a given geometry element has an srsDimension attribute with an expected value + * + * @param doc + * @param tag + * @param expectedDim + */ + protected void checkDimension(Document doc, String tag, int expectedDim) { + NodeList lsNL = doc.getElementsByTagNameNS(GML.NAMESPACE, tag); + Node geomNode = lsNL.item(0); + NamedNodeMap attrMap = geomNode.getAttributes(); + Node dimNode = attrMap.getNamedItem("srsDimension"); + assertNotNull(dimNode); + String dimStr = dimNode.getChildNodes().item(0).getNodeValue(); + int dim = Integer.parseInt(dimStr); + assertEquals(dim, expectedDim); + } + /* * To be overriden by subclasses that require the extended arc/surface bindings * enabled. Modified: trunk/modules/extension/xsd/xsd-gml3/src/test/java/org/geotools/gml3/bindings/DirectPositionListTypeBindingTest.java =================================================================== --- trunk/modules/extension/xsd/xsd-gml3/src/test/java/org/geotools/gml3/bindings/DirectPositionListTypeBindingTest.java 2012-05-15 21:21:38 UTC (rev 38732) +++ trunk/modules/extension/xsd/xsd-gml3/src/test/java/org/geotools/gml3/bindings/DirectPositionListTypeBindingTest.java 2012-05-15 21:21:56 UTC (rev 38733) @@ -21,8 +21,12 @@ import org.geotools.gml3.GML; import org.geotools.gml3.GML3TestSupport; import org.opengis.geometry.DirectPosition; +import org.w3c.dom.Document; +import com.vividsolutions.jts.geom.CoordinateSequence; +import com.vividsolutions.jts.geom.LineString; + /** * * @@ -80,4 +84,18 @@ assertEquals(3d, dps[1].getOrdinate(0), 0d); assertEquals(4d, dps[1].getOrdinate(1), 0d); } + + public void testEncode2D() throws Exception { + LineString line = GML3MockData.lineStringLite2D(); + CoordinateSequence seq = line.getCoordinateSequence(); + Document doc = encode(seq, GML.posList); + checkPosListOrdinates(doc, 2 * line.getNumPoints()); + } + + public void testEncode3D() throws Exception { + LineString line = GML3MockData.lineStringLite3D(); + CoordinateSequence seq = line.getCoordinateSequence(); + Document doc = encode(seq, GML.posList); + checkPosListOrdinates(doc, 3 * line.getNumPoints()); + } } Modified: trunk/modules/extension/xsd/xsd-gml3/src/test/java/org/geotools/gml3/bindings/DirectPositionTypeBindingTest.java =================================================================== --- trunk/modules/extension/xsd/xsd-gml3/src/test/java/org/geotools/gml3/bindings/DirectPositionTypeBindingTest.java 2012-05-15 21:21:38 UTC (rev 38732) +++ trunk/modules/extension/xsd/xsd-gml3/src/test/java/org/geotools/gml3/bindings/DirectPositionTypeBindingTest.java 2012-05-15 21:21:56 UTC (rev 38733) @@ -21,8 +21,13 @@ import org.geotools.gml3.GML; import org.geotools.gml3.GML3TestSupport; import org.opengis.geometry.DirectPosition; +import org.w3c.dom.Document; +import com.vividsolutions.jts.geom.CoordinateSequence; +import com.vividsolutions.jts.geom.LineString; +import com.vividsolutions.jts.geom.Point; + /** * * @@ -53,4 +58,20 @@ assertEquals(pos.getOrdinate(0), 1.0, 0); assertEquals(pos.getOrdinate(1), 2.0, 0); } + + public void testEncode2D() throws Exception { + Point point = GML3MockData.pointLite2D(); + CoordinateSequence seq = point.getCoordinateSequence(); + Document doc = encode(seq, GML.pos); + checkPosOrdinates(doc, 2); + } + + public void testEncode3D() throws Exception { + Point point = GML3MockData.pointLite3D(); + CoordinateSequence seq = point.getCoordinateSequence(); + Document doc = encode(seq, GML.pos); + checkPosOrdinates(doc, 3); + } + + } Modified: trunk/modules/extension/xsd/xsd-gml3/src/test/java/org/geotools/gml3/bindings/GML3MockData.java =================================================================== --- trunk/modules/extension/xsd/xsd-gml3/src/test/java/org/geotools/gml3/bindings/GML3MockData.java 2012-05-15 21:21:38 UTC (rev 38732) +++ trunk/modules/extension/xsd/xsd-gml3/src/test/java/org/geotools/gml3/bindings/GML3MockData.java 2012-05-15 21:21:56 UTC (rev 38733) @@ -22,6 +22,8 @@ import org.geotools.feature.simple.SimpleFeatureBuilder; import org.geotools.feature.simple.SimpleFeatureTypeBuilder; +import org.geotools.geometry.jts.LiteCoordinateSequence; +import org.geotools.geometry.jts.LiteCoordinateSequenceFactory; import org.geotools.geometry.jts.ReferencedEnvelope; import org.geotools.gml3.GML; import org.geotools.referencing.CRS; @@ -34,6 +36,7 @@ import org.w3c.dom.Node; 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.GeometryCollection; @@ -59,6 +62,10 @@ */ public class GML3MockData { static GeometryFactory gf = new GeometryFactory(); + + static LiteCoordinateSequenceFactory liteCSF = new LiteCoordinateSequenceFactory(); + static GeometryFactory liteGF = new GeometryFactory(liteCSF); + static XSD gml = GML.getInstance(); public static void setGML(XSD gml) { @@ -97,10 +104,64 @@ return p; } + /** + * Creates a Point using a LiteCoordinateSequence + * with a 2D coordinate. + * + * @return a 2D Point + */ + public static Point pointLite2D() { + return liteGF.createPoint(new LiteCoordinateSequence(new double[] { 1, 2}, 2)); + } + + /** + * Creates a Point using a LiteCoordinateSequence + * with a 2D coordinate. + * + * @return a 2D Point + */ + public static Point pointLite3D() { + return liteGF.createPoint(new LiteCoordinateSequence(new double[] { 1, 2, 100}, 3)); + } + public static LineString lineString() { return gf.createLineString(new Coordinate[] { new Coordinate(1, 2), new Coordinate(3, 4) }); } + /** + * Creates a LineString using a LiteCoordinateSequence + * with 2 2D coordinates. + * + * @return a 2D LineString + */ + public static LineString lineStringLite2D() { + return liteGF.createLineString(new Coordinate[] { new Coordinate(1, 2), new Coordinate(3, 4) }); + } + + /** + * Creates a LineString using a LiteCoordinateSequence + * with 2 2D coordinates. + * + * @return a 2D LineString + */ + public static LineString lineStringLite2D(int size) { + Coordinate[] coords = new Coordinate[size]; + for (int i = 0; i < size; i++) { + coords[i] = new Coordinate(i, i+1); + } + return liteGF.createLineString(coords); + } + + /** + * Creates a LineString using a LiteCoordinateSequence + * with 2 3D coordinates. + * + * @return a 3D LineString + */ + public static LineString lineStringLite3D() { + return liteGF.createLineString(liteCSF.create(new double[] { 1, 2, 100, 3, 4, 200}, 3)); + } + public static Element lineString(Document document, Node parent) { return lineStringWithPos(document, parent); } @@ -193,6 +254,32 @@ return gf.createPolygon(linearRing(), null); } + /** + * Creates a Polygon using a LiteCoordinateSequence + * with 2D coordinates. + * + * @return a 2D Polygon + */ + public static Polygon polygonLite2D() { + return liteGF.createPolygon( + liteGF.createLinearRing(liteCSF.create( + new double[] { 1,1, 2,1, 2,2, 1,2, 1,1 }, 2 )), + null); + } + + /** + * Creates a Polygon using a LiteCoordinateSequence + * with 3D coordinates. + * + * @return a 3D Polygon + */ + public static Polygon polygonLite3D() { + return liteGF.createPolygon( + liteGF.createLinearRing(liteCSF.create( + new double[] { 1,1,100, 2,1,99, 2,2,98, 1,2,97, 1,1,100}, 3)), + null); + } + public static Element polygon(Document document, Node parent) { return polygon(document,parent,qName("Polygon"),false); } Modified: trunk/modules/extension/xsd/xsd-gml3/src/test/java/org/geotools/gml3/bindings/LineStringTypeBindingTest.java =================================================================== --- trunk/modules/extension/xsd/xsd-gml3/src/test/java/org/geotools/gml3/bindings/LineStringTypeBindingTest.java 2012-05-15 21:21:38 UTC (rev 38732) +++ trunk/modules/extension/xsd/xsd-gml3/src/test/java/org/geotools/gml3/bindings/LineStringTypeBindingTest.java 2012-05-15 21:21:56 UTC (rev 38733) @@ -16,7 +16,9 @@ */ package org.geotools.gml3.bindings; +import org.geotools.gml3.GML; import org.geotools.gml3.GML3TestSupport; +import org.w3c.dom.Document; import com.vividsolutions.jts.geom.Coordinate; import com.vividsolutions.jts.geom.LineString; @@ -47,4 +49,48 @@ assertEquals(new Coordinate(1d, 2d), line.getPointN(0).getCoordinate()); assertEquals(new Coordinate(3d, 4d), line.getPointN(1).getCoordinate()); } + + /** + * Tests encoding using a CoordinateArraySequence + * (which requires special logic to get the dimension correct) + * @throws Exception + */ + public void testEncodeLineString() throws Exception { + LineString line = GML3MockData.lineString(); + Document doc = encode(line, GML.LineString); + + checkDimension(doc, GML.LineString.getLocalPart(), 2); + checkPosListOrdinates(doc, 2 * line.getNumPoints()); + } + + public void testEncodeLite2D() throws Exception { + LineString line = GML3MockData.lineStringLite2D(); + Document doc = encode(line, GML.LineString); + + checkDimension(doc, GML.LineString.getLocalPart(), 2); + checkPosListOrdinates(doc, 2 * line.getNumPoints()); + } + + public void testEncodeLite3D() throws Exception { + LineString line = GML3MockData.lineStringLite3D(); + Document doc = encode(line, GML.LineString); + + checkDimension(doc, GML.LineString.getLocalPart(), 3); + checkPosListOrdinates(doc, 3 * line.getNumPoints()); + } + + /** + * Test a long LineString to catch problems that only show up with large numbers of ordinates + * + * @throws Exception + */ + public void testEncode2DLong() throws Exception { + LineString line = GML3MockData.lineStringLite2D(10); + Document doc = encode(line, GML.LineString); + + checkDimension(doc, GML.LineString.getLocalPart(), 2); + checkPosListOrdinates(doc, 2 * line.getNumPoints()); + } + + } Modified: trunk/modules/extension/xsd/xsd-gml3/src/test/java/org/geotools/gml3/bindings/MultiLineStringTypeBindingTest.java =================================================================== --- trunk/modules/extension/xsd/xsd-gml3/src/test/java/org/geotools/gml3/bindings/MultiLineStringTypeBindingTest.java 2012-05-15 21:21:38 UTC (rev 38732) +++ trunk/modules/extension/xsd/xsd-gml3/src/test/java/org/geotools/gml3/bindings/MultiLineStringTypeBindingTest.java 2012-05-15 21:21:56 UTC (rev 38733) @@ -51,6 +51,9 @@ assertEquals(2, children.getLength()); assertEquals("geometry.1", getID(children.item(0))); assertEquals("geometry.2", getID(children.item(1))); + + checkDimension(dom, GML.MultiLineString.getLocalPart(), 2); + checkDimension(dom, GML.LineString.getLocalPart(), 2); + checkPosListOrdinates(dom, 2 * geometry.getGeometryN(0).getNumPoints()); } - } Modified: trunk/modules/extension/xsd/xsd-gml3/src/test/java/org/geotools/gml3/bindings/PointTypeBindingTest.java =================================================================== --- trunk/modules/extension/xsd/xsd-gml3/src/test/java/org/geotools/gml3/bindings/PointTypeBindingTest.java 2012-05-15 21:21:38 UTC (rev 38732) +++ trunk/modules/extension/xsd/xsd-gml3/src/test/java/org/geotools/gml3/bindings/PointTypeBindingTest.java 2012-05-15 21:21:56 UTC (rev 38733) @@ -22,6 +22,7 @@ import org.w3c.dom.Document; import com.vividsolutions.jts.geom.Coordinate; +import com.vividsolutions.jts.geom.LineString; import com.vividsolutions.jts.geom.Point; @@ -50,4 +51,21 @@ //assertEquals("urn:x-ogc:def:crs:EPSG:6.11.2:4326", assertEquals("urn:x-ogc:def:crs:EPSG:4326", dom.getDocumentElement().getAttribute("srsName")); } + + public void testEncode2D() throws Exception { + Point point = GML3MockData.pointLite2D(); + Document doc = encode(point, GML.Point); + + checkDimension(doc, GML.Point.getLocalPart(), 2); + checkPosOrdinates(doc, 2); + } + + public void testEncode3D() throws Exception { + Point point = GML3MockData.pointLite3D(); + Document doc = encode(point, GML.Point); + + checkDimension(doc, GML.Point.getLocalPart(), 3); + checkPosOrdinates(doc, 3); + } + } Modified: trunk/modules/extension/xsd/xsd-gml3/src/test/java/org/geotools/gml3/bindings/PolygonTypeBindingTest.java =================================================================== --- trunk/modules/extension/xsd/xsd-gml3/src/test/java/org/geotools/gml3/bindings/PolygonTypeBindingTest.java 2012-05-15 21:21:38 UTC (rev 38732) +++ trunk/modules/extension/xsd/xsd-gml3/src/test/java/org/geotools/gml3/bindings/PolygonTypeBindingTest.java 2012-05-15 21:21:56 UTC (rev 38733) @@ -16,8 +16,11 @@ */ package org.geotools.gml3.bindings; +import org.geotools.gml3.GML; import org.geotools.gml3.GML3TestSupport; +import org.w3c.dom.Document; +import com.vividsolutions.jts.geom.LineString; import com.vividsolutions.jts.geom.Polygon; @@ -33,4 +36,22 @@ Polygon polygon = (Polygon) parse(); assertNotNull(polygon); } + + public void testEncode3D() throws Exception { + Polygon poly = GML3MockData.polygonLite3D(); + Document doc = encode(poly, GML.Polygon); + + checkDimension(doc, GML.Polygon.getLocalPart(), 3); + checkPosListOrdinates(doc, 3 * poly.getNumPoints()); + } + + public void testEncode2D() throws Exception { + Polygon poly = GML3MockData.polygonLite2D(); + Document doc = encode(poly, GML.Polygon); + + checkDimension(doc, GML.Polygon.getLocalPart(), 2); + checkPosListOrdinates(doc, 2 * poly.getNumPoints()); + } + + } Modified: trunk/modules/library/main/src/main/java/org/geotools/geometry/jts/coordinatesequence/CoordinateSequences.java =================================================================== --- trunk/modules/library/main/src/main/java/org/geotools/geometry/jts/coordinatesequence/CoordinateSequences.java 2012-05-15 21:21:38 UTC (rev 38732) +++ trunk/modules/library/main/src/main/java/org/geotools/geometry/jts/coordinatesequence/CoordinateSequences.java 2012-05-15 21:21:56 UTC (rev 38733) @@ -21,10 +21,17 @@ import com.vividsolutions.jts.algorithm.RobustDeterminant; import com.vividsolutions.jts.geom.Coordinate; import com.vividsolutions.jts.geom.CoordinateSequence; +import com.vividsolutions.jts.geom.CoordinateSequenceFilter; +import com.vividsolutions.jts.geom.Geometry; +import com.vividsolutions.jts.geom.LineString; +import com.vividsolutions.jts.geom.Point; +import com.vividsolutions.jts.geom.Polygon; +import com.vividsolutions.jts.geom.impl.CoordinateArraySequence; /** * Utility functions for coordinate sequences (extends the same named JTS class) * @author Andrea Aime - OpenGeo + * @author Martin Davis - OpenGeo * * * @source $URL$ @@ -125,4 +132,90 @@ return RobustDeterminant.signOfDet2x2(dx1, dy1, dx2, dy2); } + + /** + * Gets the dimension of the coordinates in a {@link Geometry}, + * by reading it from a component {@link CoordinateSequence}. + * This will be usually either 2 or 3. + * + * @param g a Geometry + * @return the dimension of the coordinates in the Geometry + */ + public static int coordinateDimension(Geometry g) + { + // common fast cases + if (g instanceof Point) + return coordinateDimension(((Point) g).getCoordinateSequence()); + if (g instanceof LineString) + return coordinateDimension(((LineString) g).getCoordinateSequence()); + if (g instanceof Polygon) + return coordinateDimension(((Polygon) g).getExteriorRing() + .getCoordinateSequence()); + + // dig down to find a CS + CoordinateSequence cs = CoordinateSequenceFinder.find(g); + return coordinateDimension(cs); + } + + /** + * Gets the effective dimension of a CoordinateSequence. + * This is a workaround for the issue that CoordinateArraySequence + * does not keep an accurate dimension - it always + * reports dim=3, even if there is no Z ordinate (ie they are NaN). + * This method checks for that case and reports dim=2. + * Only the first coordinate is checked. + * <p> + * There is one small hole: if a CoordinateArraySequence is empty, + * the dimension will be reported as 3. + * + * @param seq a CoordinateSequence + * @return the effective dimension of the coordinate sequence + */ + public static int coordinateDimension(CoordinateSequence seq) + { + int dim = seq.getDimension(); + if (dim != 3) + return dim; + + // hack to handle issue that CoordinateArraySequence always reports + // dimension = 3 + // check if a Z value is NaN - if so, assume dim is 2 + if (seq instanceof CoordinateArraySequence) { + if (seq.size() > 0) { + if (Double.isNaN(seq.getOrdinate(0, CoordinateSequence.Z))) + return 2; + } + } + return 3; + } + + private static class CoordinateSequenceFinder implements CoordinateSequenceFilter { + + public static CoordinateSequence find(Geometry g) { + CoordinateSequenceFinder finder = new CoordinateSequenceFinder(); + g.apply(finder); + return finder.getSeq(); + } + + private CoordinateSequence firstSeqFound = null; + + public CoordinateSequence getSeq() { + return firstSeqFound; + } + + public void filter(CoordinateSequence seq, int i) { + if (firstSeqFound == null) + firstSeqFound = seq; + + } + + public boolean isDone() { + return firstSeqFound != null; + } + + public boolean isGeometryChanged() { + return false; + } + + } } Added: trunk/modules/library/main/src/test/java/org/geotools/geometry/jts/coordinatesequence/CoordinateSequencesTest.java =================================================================== --- trunk/modules/library/main/src/test/java/org/geotools/geometry/jts/coordinatesequence/CoordinateSequencesTest.java (rev 0) +++ trunk/modules/library/main/src/test/java/org/geotools/geometry/jts/coordinatesequence/CoordinateSequencesTest.java 2012-05-15 21:21:56 UTC (rev 38733) @@ -0,0 +1,63 @@ +package org.geotools.geometry.jts.coordinatesequence; + +import static org.junit.Assert.assertEquals; + +import org.geotools.geometry.jts.LiteCoordinateSequence; +import org.geotools.geometry.jts.LiteCoordinateSequenceFactory; +import org.junit.Test; + +import com.vividsolutions.jts.geom.Coordinate; +import com.vividsolutions.jts.geom.Geometry; +import com.vividsolutions.jts.geom.GeometryFactory; + +public class CoordinateSequencesTest { + + static GeometryFactory gf = new GeometryFactory(); + + static LiteCoordinateSequenceFactory liteCSF = new LiteCoordinateSequenceFactory(); + static GeometryFactory liteGF = new GeometryFactory(liteCSF); + + + @Test + public void testCoordinateDimensionPointLite2D() + { + Geometry geom = liteGF.createPoint(new LiteCoordinateSequence(new double[] { 1, 2}, 2)); + assertEquals(2, CoordinateSequences.coordinateDimension(geom)); + } + @Test + public void testCoordinateDimensionPointLite3D() + { + Geometry geom = liteGF.createPoint(new LiteCoordinateSequence(new double[] { 1, 2, 99}, 3)); + assertEquals(3, CoordinateSequences.coordinateDimension(geom)); + } + @Test + public void testCoordinateDimensionLineString2D() + { + Geometry geom = gf.createLineString(new Coordinate[] { new Coordinate(1, 2), new Coordinate(3, 4) }); + assertEquals(2, CoordinateSequences.coordinateDimension(geom)); + } + @Test + public void testCoordinateDimensionLineStringLite3D() + { + Geometry geom = liteGF.createLineString(liteCSF.create(new double[] { 1, 2, 100, 3, 4, 200}, 3)); + assertEquals(3, CoordinateSequences.coordinateDimension(geom)); + } + @Test + public void testCoordinateDimensionPolygonLite2D() + { + Geometry geom = liteGF.createPolygon( + liteGF.createLinearRing(liteCSF.create( + new double[] { 1,1, 2,1, 2,2, 1,2, 1,1 }, 2 )), + null); + assertEquals(2, CoordinateSequences.coordinateDimension(geom)); + } + @Test + public void testCoordinateDimensionPolygonLite3D() + { + Geometry geom = liteGF.createPolygon( + liteGF.createLinearRing(liteCSF.create( + new double[] { 1,1,100, 2,1,99, 2,2,98, 1,2,97, 1,1,100}, 3)), + null); + assertEquals(3, CoordinateSequences.coordinateDimension(geom)); + } +} Modified: trunk/modules/library/xml/src/test/java/org/geotools/GMLTest.java =================================================================== --- trunk/modules/library/xml/src/test/java/org/geotools/GMLTest.java 2012-05-15 21:21:38 UTC (rev 38732) +++ trunk/modules/library/xml/src/test/java/org/geotools/GMLTest.java 2012-05-15 21:21:56 UTC (rev 38733) @@ -191,7 +191,7 @@ out.close(); String gml = out.toString(); - assertTrue(gml.indexOf("<gml:Point>") != -1); + assertTrue(gml.indexOf("<gml:Point") != -1); } // |