Skip to content
Browse files

Merge remote-tracking branch 'upstream/master' into getfeature_viewpa…

…rams_support
  • Loading branch information...
2 parents ff46c81 + 9d7f87d commit bf060cf2620034a02ca3492c6e4f5fe2271497cc Geoff Williams committed Apr 8, 2013
Showing with 1,189 additions and 177 deletions.
  1. +22 −2 build/maven/javadoc/pom.xml
  2. +1 −1 docs/user/build/install/mvn.rst
  3. +2 −16 modules/extension/xsd/xsd-gml3/src/main/java/org/geotools/gml3/bindings/ArcStringTypeBinding.java
  4. +0 −10 modules/extension/xsd/xsd-wfs/src/main/java/org/geotools/wfs/bindings/PropertyTypeBinding.java
  5. +88 −0 ...les/extension/xsd/xsd-wfs/src/test/java/org/geotools/wfs/bindings/TransactionTypeBindingTest.java
  6. +26 −0 ...xsd/xsd-wfs/src/test/resources/org/geotools/wfs/bindings/test-data/TransactionTypeBindingTest.xml
  7. +14 −1 modules/library/main/src/main/java/org/geotools/filter/visitor/SimplifyingFilterVisitor.java
  8. +1 −1 modules/library/main/src/main/java/org/geotools/styling/SLDParser.java
  9. +31 −1 modules/library/main/src/test/java/org/geotools/styling/SLDParserTest.java
  10. +28 −10 ...ibrary/referencing/src/main/java/org/geotools/referencing/operation/projection/MapProjection.java
  11. +5 −0 ...y/referencing/src/main/java/org/geotools/referencing/operation/projection/TransverseMercator.java
  12. +130 −0 ...ry/referencing/src/test/java/org/geotools/referencing/operation/projection/MapProjectionTest.java
  13. +24 −11 modules/library/render/src/main/java/org/geotools/renderer/lite/StyledShapePainter.java
  14. +1 −1 modules/library/render/src/test/java/org/geotools/renderer/lite/RenderingTransformationTest.java
  15. +20 −0 modules/library/render/src/test/java/org/geotools/renderer/lite/StyledShapePainterTest.java
  16. +1 −1 modules/plugin/arcsde/datastore/src/main/java/org/geotools/arcsde/ArcSDERasterFormatFactory.java
  17. +3 −1 modules/plugin/jdbc/jdbc-postgis/src/main/java/org/geotools/data/postgis/PostGISDialect.java
  18. +1 −1 modules/plugin/jdbc/jdbc-postgis/src/test/java/org/geotools/data/postgis/PostgisUDTTestSetup.java
  19. +21 −4 ...ugin/jdbc/jdbc-sqlserver/src/main/java/org/geotools/data/sqlserver/SQLServerDataStoreFactory.java
  20. +48 −33 modules/plugin/jdbc/jdbc-sqlserver/src/main/java/org/geotools/data/sqlserver/SQLServerDialect.java
  21. +2 −0 .../jdbc/jdbc-sqlserver/src/main/java/org/geotools/data/sqlserver/SQLServerJNDIDataStoreFactory.java
  22. +25 −0 modules/plugin/jdbc/jdbc-sqlserver/src/main/java/org/geotools/data/sqlserver/reader/Figure.java
  23. +31 −0 modules/plugin/jdbc/jdbc-sqlserver/src/main/java/org/geotools/data/sqlserver/reader/Shape.java
  24. +103 −0 .../plugin/jdbc/jdbc-sqlserver/src/main/java/org/geotools/data/sqlserver/reader/SqlServerBinary.java
  25. +15 −0 ...dbc-sqlserver/src/main/java/org/geotools/data/sqlserver/reader/SqlServerBinaryParseException.java
  26. +268 −0 ...n/jdbc/jdbc-sqlserver/src/main/java/org/geotools/data/sqlserver/reader/SqlServerBinaryReader.java
  27. +36 −0 modules/plugin/jdbc/jdbc-sqlserver/src/main/java/org/geotools/data/sqlserver/reader/Type.java
  28. +2 −2 ...gin/jdbc/jdbc-sqlserver/src/test/java/org/geotools/data/sqlserver/SQLServerFeatureSourceTest.java
  29. +20 −0 ...bc-sqlserver/src/test/java/org/geotools/data/sqlserver/SqlServerNativeSerializationTestSetup.java
  30. +120 −0 ...bc/jdbc-sqlserver/src/test/java/org/geotools/data/sqlserver/reader/SQLServerBinaryReaderTest.java
  31. +35 −41 modules/plugin/shapefile/src/main/java/org/geotools/data/shapefile/shp/ShapefileReader.java
  32. +16 −0 modules/plugin/shapefile/src/test/java/org/geotools/data/shapefile/ShapefileTest.java
  33. BIN modules/plugin/shapefile/src/test/resources/org/geotools/data/shapefile/test-data/sparse/sparse.dbf
  34. BIN modules/plugin/shapefile/src/test/resources/org/geotools/data/shapefile/test-data/sparse/sparse.shp
  35. BIN modules/plugin/shapefile/src/test/resources/org/geotools/data/shapefile/test-data/sparse/sparse.shx
  36. +34 −40 ...es/unsupported/shapefile-ng/src/main/java/org/geotools/data/shapefile/ng/shp/ShapefileReader.java
  37. +15 −0 modules/unsupported/shapefile-ng/src/test/java/org/geotools/data/shapefile/ng/ShapefileTest.java
  38. BIN ...ported/shapefile-ng/src/test/resources/org/geotools/data/shapefile/ng/test-data/sparse/sparse.dbf
  39. BIN ...ported/shapefile-ng/src/test/resources/org/geotools/data/shapefile/ng/test-data/sparse/sparse.shp
  40. BIN ...ported/shapefile-ng/src/test/resources/org/geotools/data/shapefile/ng/test-data/sparse/sparse.shx
View
24 build/maven/javadoc/pom.xml
@@ -160,7 +160,27 @@
</dependency>
</dependencies>
</profile>
- </profiles>
-
+ <!-- =========================================================== -->
+ <!-- Google' tools dependency -->
+ <!-- =========================================================== -->
+ <profile>
+ <id>google-jdk-default-tools.jar</id>
+ <activation>
+ <property>
+ <name>java.vendor</name>
+ <value>Google Inc.</value>
+ </property>
+ </activation>
+ <dependencies>
+ <dependency>
+ <groupId>com.sun</groupId>
+ <artifactId>tools</artifactId>
+ <version>1.5</version>
+ <scope>system</scope>
+ <systemPath>${java.home}/../lib/tools.jar</systemPath>
+ </dependency>
+ </dependencies>
+ </profile>
+ </profiles>
</project>
View
2 docs/user/build/install/mvn.rst
@@ -7,7 +7,7 @@ configuration. Actual build instructions will happen later.
Reference:
* http://maven.apache.org/
-* http://maven.apache.org/start/install.html
+* http://maven.apache.org/download.html
Download and Install Maven
^^^^^^^^^^^^^^^^^^^^^^^^^^
View
18 ...extension/xsd/xsd-gml3/src/main/java/org/geotools/gml3/bindings/ArcStringTypeBinding.java
@@ -8,6 +8,7 @@
import org.geotools.gml3.GML;
import org.geotools.xml.*;
+import com.vividsolutions.jts.algorithm.CGAlgorithms;
import com.vividsolutions.jts.geom.Coordinate;
import com.vividsolutions.jts.geom.CoordinateSequenceFactory;
import com.vividsolutions.jts.geom.GeometryFactory;
@@ -163,22 +164,7 @@ public Object parse(ElementInstance instance, Node node, Object value)
* @return true if input coordinates are laid out clockwise on their corresponding circle. false otherwise.
*/
protected boolean laidOutClockwise(Coordinate c1, Coordinate c2, Coordinate c3) {
- double x1 = c1.x;
- double y1 = c1.y;
- double x2 = c2.x;
- double y2 = c2.y;
- double x3 = c3.x;
- double y3 = c3.y;
-
- double midY = y1 - (y1 - y3) / 2;
-
- return (x1 < x3 && midY < y2) ||
- (x1 > x3 && midY > y2) ||
- (Double.compare(x1, x3) == 0 && (
- (y1 < y3 && x1 > x2) || // x1 == x3 == midX in this case and the case below
- (y1 > y3 && x1 < x2)
- // Double.compare(y1, y3) == 0 degenerate case omitted
- ));
+ return CGAlgorithms.computeOrientation(c1, c2, c3) == CGAlgorithms.CLOCKWISE;
}
}
View
10 ...es/extension/xsd/xsd-wfs/src/main/java/org/geotools/wfs/bindings/PropertyTypeBinding.java
@@ -81,16 +81,6 @@ public QName getTarget() {
*
* @generated modifiable
*/
- public Class getType() {
- return null;
- }
-
- /**
- * <!-- begin-user-doc -->
- * <!-- end-user-doc -->
- *
- * @generated modifiable
- */
public Object parse(ElementInstance instance, Node node, Object value)
throws Exception {
//TODO: implement and remove call to super
View
88 ...nsion/xsd/xsd-wfs/src/test/java/org/geotools/wfs/bindings/TransactionTypeBindingTest.java
@@ -0,0 +1,88 @@
+/*
+ * GeoTools - The Open Source Java GIS Toolkit
+ * http://geotools.org
+ *
+ * (C) 2002-2008, Open Source Geospatial Foundation (OSGeo)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ */
+package org.geotools.wfs.bindings;
+
+import java.math.BigInteger;
+import java.net.URL;
+import java.util.List;
+
+import net.opengis.wfs.GetFeatureType;
+import net.opengis.wfs.PropertyType;
+import net.opengis.wfs.TransactionType;
+import net.opengis.wfs.UpdateElementType;
+
+import org.geotools.filter.FidFilter;
+import org.geotools.test.TestData;
+import org.geotools.wfs.WFS;
+import org.geotools.wfs.WFSTestSupport;
+import org.geotools.xml.Binding;
+import org.w3c.dom.Document;
+
+/**
+ * Unit test suite for {@link TransactionTypeBinding}
+ *
+ * @author Daniel Leib
+ */
+public class TransactionTypeBindingTest extends WFSTestSupport
+{
+ public TransactionTypeBindingTest()
+ {
+ super(WFS.TransactionType, TransactionType.class, Binding.OVERRIDE);
+ }
+
+ @SuppressWarnings("unchecked")
+ public void testEncode() throws Exception
+ {
+ GetFeatureType getFeature = factory.createGetFeatureType();
+ getFeature.setHandle("handle");
+ getFeature.setMaxFeatures(BigInteger.valueOf(10));
+ getFeature.getQuery().add(factory.createQueryType());
+ getFeature.getQuery().add(factory.createQueryType());
+
+ Document dom = encode(getFeature, WFS.GetFeature);
+ assertEquals("handle", dom.getDocumentElement().getAttribute("handle"));
+ assertEquals("10", dom.getDocumentElement().getAttribute("maxFeatures"));
+ assertEquals(2, getElementsByQName(dom, WFS.Query).getLength());
+ }
+
+ public void testParse() throws Exception
+ {
+ final URL resource = TestData.getResource(this, "TransactionTypeBindingTest.xml");
+ buildDocument(resource);
+
+ Object parsed = parse(WFS.Transaction);
+ assertTrue(parsed instanceof TransactionType);
+ TransactionType req = (TransactionType) parsed;
+ assertEquals("WFS", req.getService());
+ assertEquals("1.1.0", req.getVersion());
+ assertEquals("fooHandle", req.getHandle());
+
+ List updates = req.getUpdate();
+ assertEquals(2, updates.size());
+ assertTrue(updates.get(0) instanceof UpdateElementType);
+ assertTrue(updates.get(1) instanceof UpdateElementType);
+
+ UpdateElementType update1 = (UpdateElementType)updates.get(0);
+ List properties = update1.getProperty();
+ assertTrue(update1.getFilter() instanceof FidFilter);
+ assertEquals(1, properties.size());
+ assertTrue(properties.get(0) instanceof PropertyType);
+ PropertyType property = (PropertyType) properties.get(0);
+ assertEquals("prop1", property.getName().getLocalPart());
+ assertEquals("val1", property.getValue());
+ }
+}
View
26 ...wfs/src/test/resources/org/geotools/wfs/bindings/test-data/TransactionTypeBindingTest.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<Transaction version="1.1.0" service="WFS" handle="fooHandle"
+ xmlns="http://www.opengis.net/wfs" xmlns:ogc="http://www.opengis.net/ogc"
+ xmlns:topp="http://www.openplans.org/topp" xmlns:gt="http://www.geotools.org/test"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://www.opengis.net/wfs http://schemas.opengis.net/wfs/1.1.0/wfs.xsd">
+
+ <Update typeName="topp:TestType" xmlns:feature="http://www.fnt.de/traymgmt">
+ <Property>
+ <Name>prop1</Name>
+ <Value>val1</Value>
+ </Property>
+ <ogc:Filter>
+ <ogc:FeatureId fid="fid1" />
+ </ogc:Filter>
+ </Update>
+ <Update typeName="topp:TestType" xmlns:feature="http://www.fnt.de/traymgmt">
+ <Property>
+ <Name>prop2</Name>
+ <Value>val2</Value>
+ </Property>
+ <ogc:Filter>
+ <ogc:FeatureId fid="fid2" />
+ </ogc:Filter>
+ </Update>
+</Transaction>
View
15 modules/library/main/src/main/java/org/geotools/filter/visitor/SimplifyingFilterVisitor.java
@@ -264,6 +264,19 @@ public Object visit(org.opengis.filter.expression.Function function, Object extr
}
}
-
+ /**
+ * Tries to simplify the filter if it's not already a simple one
+ * @param filter
+ * @return
+ */
+ public static Filter simplify(Filter filter) {
+ // if already as simple as possible, or cannot be simplified anyways
+ if(filter == Filter.INCLUDE || filter == Filter.EXCLUDE || filter == null) {
+ return filter;
+ }
+ // other filters might involve non volatile functions, so we need to look into them
+ SimplifyingFilterVisitor visitor = new SimplifyingFilterVisitor();
+ return (Filter) filter.accept(visitor, null);
+ }
}
View
2 modules/library/main/src/main/java/org/geotools/styling/SLDParser.java
@@ -1876,7 +1876,7 @@ protected Stroke parseStroke(Node root) {
// process the css entry
//
if (res.equalsIgnoreCase(strokeString)) {
- Expression color = parseCssParameter(child, false);
+ Expression color = parseCssParameter(child, true);
stroke.setColor(color);
} else if (res.equalsIgnoreCase("width") || res.equalsIgnoreCase("stroke-width")) {
Expression width = parseCssParameter(child, false);
View
32 modules/library/main/src/test/java/org/geotools/styling/SLDParserTest.java
@@ -20,15 +20,20 @@
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
+import java.awt.Color;
import java.io.ByteArrayInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.io.StringReader;
+import java.io.StringBufferInputStream;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.List;
+import javax.xml.parsers.DocumentBuilder;
+import javax.xml.parsers.DocumentBuilderFactory;
+
import junit.framework.Assert;
import org.geotools.factory.CommonFactoryFinder;
@@ -197,6 +202,20 @@
" </FeatureTypeStyle>\n" +
" </UserStyle>\n" +
"</StyledLayerDescriptor>";
+
+ static String color = "00AA00";
+
+ static String formattedCssStrokeParameter = "<Stroke>" +
+ "\n\t<CssParameter name=\"stroke\">#" +
+ "\n\t\t<ogc:Function name=\"env\">" +
+ "\n\t\t\t<ogc:Literal>stroke_color</ogc:Literal>" +
+ "\n\t\t\t<ogc:Literal>" +
+ color +
+ "</ogc:Literal>" +
+ "\n\t\t</ogc:Function>" +
+ "\n\t</CssParameter>" +
+ "</Stroke>";
+
static StyleFactory styleFactory = CommonFactoryFinder.getStyleFactory(null);
@@ -270,7 +289,7 @@ public URL locateResource(String uri) {
ExternalGraphic graphic = (ExternalGraphic) graphicalSymbols.get(0);
assertEquals(getClass().getResource("test-data/blob.gif"), graphic.getLocation());
}
-
+
@Test
public void testExternalEntitiesDisabled() {
// this SLD file references as external entity a file on the local filesystem
@@ -319,6 +338,17 @@ public InputSource resolveEntity(String publicId, String systemId) throws SAXExc
parser.readXML();
}
+ @Test
+ public void testStrokeColorWithEnv() throws Exception {
+ DocumentBuilder builder = DocumentBuilderFactory.newInstance().newDocumentBuilder();
+ org.w3c.dom.Document node = builder.parse(new StringBufferInputStream(
+ formattedCssStrokeParameter));
+ SLDParser parser = new SLDParser(styleFactory);
+ Stroke stroke = parser.parseStroke(node.getDocumentElement());
+ // <strConcat([#], [env([stroke_color], [" + color + "])])>";
+ Assert.assertEquals("#"+color,stroke.getColor().evaluate(Color.decode("#"+color)));
+ }
+
void assertStyles(Style[] styles) {
assertEquals(1, styles.length);
assertEquals("style", styles[0].getName());
View
38 ...eferencing/src/main/java/org/geotools/referencing/operation/projection/MapProjection.java
@@ -614,14 +614,32 @@ public final int getTargetDimensions() {
* Returns the orthodromic distance between the two specified points using a spherical
* approximation. This is used for assertions only.
*/
- private double orthodromicDistance(final Point2D source, final Point2D target) {
- final double y1 = toRadians(source.getY());
- final double y2 = toRadians(target.getY());
- final double dx = toRadians(abs(target.getX() - source.getX()) % 360);
- double rho = sin(y1)*sin(y2) + cos(y1)*cos(y2)*cos(dx);
- if (rho > +1) {assert rho <= +(1+EPSILON) : rho; rho = +1;}
- if (rho < -1) {assert rho >= -(1+EPSILON) : rho; rho = -1;}
- return acos(rho) * semiMajor;
+ protected double orthodromicDistance(final Point2D source, final Point2D target) {
+ // The orthodromic distance calculation here does not work well over short
+ // distances, so we only use it if we believe the distance is significant.
+ if (source.distanceSq(target) > 1.0) {
+ final double y1 = toRadians(source.getY());
+ final double y2 = toRadians(target.getY());
+ final double dx = toRadians(abs(target.getX() - source.getX()) % 360);
+ double rho = sin(y1)*sin(y2) + cos(y1)*cos(y2)*cos(dx);
+ if (rho > +1) {assert rho <= +(1+EPSILON) : rho; rho = +1;}
+ if (rho < -1) {assert rho >= -(1+EPSILON) : rho; rho = -1;}
+ return acos(rho) * semiMajor;
+ } else {
+ // Otherwise we approximate using alternate means. This is based
+ // on the Haversine formula to compute the arc angle between the
+ // point (derived from S2LatLng.getDistance()) which is stable for
+ // small distances.
+ double lat1 = toRadians(source.getY());
+ double lat2 = toRadians(target.getY());
+ double lng1 = toRadians(source.getX());
+ double lng2 = toRadians(target.getX());
+ double dlat = Math.sin(0.5 * (lat2 - lat1));
+ double dlng = Math.sin(0.5 * (lng2 - lng1));
+ double x = dlat * dlat + dlng * dlng * Math.cos(lat1) * Math.cos(lat2);
+ double arcRadians = 2 * Math.atan2(Math.sqrt(x), Math.sqrt(Math.max(0.0, 1.0 - x)));
+ return arcRadians * semiMajor;
+ }
}
/**
@@ -647,7 +665,7 @@ public CheckPoint(final Point2D point) {
* @param inverse {@code true} for an inverse transform instead of a direct one.
* @return {@code true} if the two points are close enough.
*/
- private boolean checkReciprocal(Point2D point, final Point2D target, final boolean inverse)
+ protected boolean checkReciprocal(Point2D point, final Point2D target, final boolean inverse)
throws ProjectionException
{
if (!(point instanceof CheckPoint)) try {
@@ -1183,7 +1201,7 @@ protected double getToleranceForAssertions(final double longitude, final double
return 1;
}
// Be less strict when the point is near an edge.
- return (abs(longitude) > 179) || (abs(latitude) > 89) ? 1E-1 : 1E-5;
+ return (abs(longitude) > 179) || (abs(latitude) > 89) ? 1E-1 : 3E-3;
}
/**
View
5 ...ncing/src/main/java/org/geotools/referencing/operation/projection/TransverseMercator.java
@@ -260,7 +260,12 @@ protected double getToleranceForAssertions(final double longitude, final double
return 1.0;
} else if (abs(longitude - centralMeridian) > 0.17) { // 10 degrees
return 0.5;
+ } else if(abs(latitude - latitudeOfOrigin) < 0.00001) {
+ // Strangely, very near the latitude of origin the cos() becomes lossy
+ // and errors are in excess of a millimeter.
+ return 0.01;
}
+
// a normal tolerance
return 1E-6;
}
View
130 ...encing/src/test/java/org/geotools/referencing/operation/projection/MapProjectionTest.java
@@ -0,0 +1,130 @@
+/*
+ * GeoTools - The Open Source Java GIS Toolkit
+ * http://geotools.org
+ *
+ * (C) 2005-2013, Open Source Geospatial Foundation (OSGeo)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ */
+package org.geotools.referencing.operation.projection;
+
+import static org.geotools.referencing.operation.projection.MapProjection.AbstractProvider.SEMI_MAJOR;
+import static org.geotools.referencing.operation.projection.MapProjection.AbstractProvider.SEMI_MINOR;
+import static org.junit.Assert.assertEquals;
+
+import java.awt.geom.Point2D;
+
+import org.geotools.referencing.ReferencingFactoryFinder;
+import org.junit.Test;
+import org.opengis.parameter.ParameterValueGroup;
+import org.opengis.referencing.FactoryException;
+import org.opengis.referencing.operation.MathTransformFactory;
+import org.opengis.referencing.operation.TransformException;
+
+
+/**
+ * Tests the {@link MapProjection} implementation.
+ *
+ * @source $URL$
+ * @version $Id$
+ * @author Frank Warmerdam
+ */
+public final class MapProjectionTest {
+
+ /**
+ * Make a simple spherical Mercator (Google Mercator) CRS. We just use this as
+ * a simple example of a MapProjection since that class is abstract.
+ */
+ private static MapProjection createGoogleMercator() throws FactoryException {
+ MathTransformFactory mtFactory = ReferencingFactoryFinder.getMathTransformFactory(null);
+ final ParameterValueGroup parameters = mtFactory.getDefaultParameters("Mercator_1SP");
+ parameters.parameter(SEMI_MAJOR.getName().getCode()).setValue(6378137.0);
+ parameters.parameter(SEMI_MINOR.getName().getCode()).setValue(6378137.0);
+ return (MapProjection) mtFactory.createParameterizedTransform(parameters);
+ }
+
+ /**
+ * Sets of geographic coordinates to project.
+ */
+ private static final double[] GEOGRAPHIC = {
+ 47.0, -14.0,
+ 48.38824840214492, -14.967538330290973,
+ };
+
+ /**
+ * Set of projected coordinates.
+ */
+ private static final double[] PROJECTED = {
+ 5232016.067283858, -1574216.548161465,
+ 5386555.1725052055, -1685459.3322153771,
+ };
+
+ /**
+ * Test we can round trip well behaved points, and that checkReciprocal() works properly.
+ */
+ @Test
+ public void testCheckReciprocal() throws TransformException, FactoryException {
+ final double[] dst = new double[PROJECTED.length];
+ MapProjection mt = createGoogleMercator();
+ mt.transform(GEOGRAPHIC, 0, dst, 0, PROJECTED.length/2);
+
+ for (int i=0; i<PROJECTED.length; i++) {
+ assertEquals(PROJECTED[i], dst[i], 0.1); // 10 cm precision
+ }
+
+ for (int i=0; i < PROJECTED.length/2; i++) {
+ Point2D src = new Point2D.Double(GEOGRAPHIC[i*2+0], GEOGRAPHIC[i*2+1]);
+ Point2D target = new Point2D.Double(PROJECTED[i*2+0], PROJECTED[i*2+1]);
+ assertEquals(true, mt.checkReciprocal(src, target, false));
+ assertEquals(true, mt.checkReciprocal(target, src, true));
+ }
+
+ mt.inverse().transform(PROJECTED, 0, dst, 0, PROJECTED.length/2);
+ for (int i=0; i<GEOGRAPHIC.length; i++) {
+ assertEquals(GEOGRAPHIC[i], dst[i], 0.0001); // About 10 m precision
+ }
+ }
+
+ /**
+ * Test that orthodromicDistance() works well for small and large distances.
+ */
+ @Test
+ public void testOrthodromicDistance() throws FactoryException {
+ MapProjection mt = createGoogleMercator();
+
+ // Test some large distances
+ assertEquals(111319.49079,
+ mt.orthodromicDistance(new Point2D.Double(0.0, 0.0),
+ new Point2D.Double(0.0, 1.0)), 0.001);
+ assertEquals(111319.49079,
+ mt.orthodromicDistance(new Point2D.Double(0.0, 0.0),
+ new Point2D.Double(1.0, 0.0)), 0.001);
+ assertEquals(111319.49079,
+ mt.orthodromicDistance(new Point2D.Double(0.0, 89.0),
+ new Point2D.Double(0.0, 90.0)), 0.001);
+ assertEquals(1942.76834,
+ mt.orthodromicDistance(new Point2D.Double(0.0, 89.0),
+ new Point2D.Double(1.0, 89.0)), 0.001);
+ assertEquals(10018754.17139,
+ mt.orthodromicDistance(new Point2D.Double(0.0, 0.0),
+ new Point2D.Double(0.0, 90.0)), 0.001);
+
+ // Test some small distances.
+ Point2D src = new Point2D.Double(48.38824840214492, -14.967538330290973);
+ assertEquals(0.0, mt.orthodromicDistance(src, src), 0.000000001);
+
+ Point2D target = new Point2D.Double(src.getX(), src.getY()+0.0000001);
+ assertEquals(0.011131948840096939, mt.orthodromicDistance(src, target), 1E-12);
+
+ Point2D target2 = new Point2D.Double(src.getX(), src.getY()+0.000000000001);
+ assertEquals(1.1117412E-7, mt.orthodromicDistance(src, target2), 1E-12);
+ }
+}
View
35 modules/library/render/src/main/java/org/geotools/renderer/lite/StyledShapePainter.java
@@ -322,10 +322,11 @@ public void paint(final Graphics2D graphics, final LiteShape2 shape,
* The shape to draw.
* @param legend
* The legend to apply.
- * @param scale
- * The scale denominator for the current zoom level
+ * @param symbolScale
+ * The scale of the symbol, if the legend graphic has to be rescaled
*/
- public void paint(final Graphics2D graphics, final LiteShape2 shape, final GraphicLegend legend, final double scale, boolean isLabelObstacle) {
+ public void paint(final Graphics2D graphics, final LiteShape2 shape, final GraphicLegend legend,
+ final double symbolScale, boolean isLabelObstacle) {
if (legend == null) {
// TODO: what's going on? Should not be reached...
throw new NullPointerException("ShapePainter has been asked to paint a null legend!!");
@@ -349,14 +350,26 @@ public void paint(final Graphics2D graphics, final LiteShape2 shape, final Graph
while (!(iter.isDone())) {
iter.currentSegment(coords);
try {
- renderImage(graphics, coords[0], coords[1],
- // Doesn't seem to work with SVGs
- // Looking at the SLDStyleFactory, they get the icon from an
- // ExternalGraphicFactory.
- ImageIO.read(graphic.getOnlineResource().getLinkage().toURL()),
- rotation,
- opacity,
- isLabelObstacle);
+ BufferedImage image = ImageIO.read(graphic.getOnlineResource().getLinkage().toURL());
+ if (symbolScale != 1.0){
+ int w = (int) (image.getWidth() / symbolScale);
+ int h = (int) (image.getHeight() / symbolScale);
+ int imageType = image.getType() == 0 ? BufferedImage.TYPE_4BYTE_ABGR : image.getType();
+ BufferedImage rescaled = new BufferedImage(w, h, imageType);
+ Graphics2D g = rescaled.createGraphics();
+ g.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BILINEAR);
+ g.drawImage(image, 0, 0, w, h, 0, 0, image.getWidth(), image.getHeight(), null);
+ g.dispose();
+ image = rescaled;
+ }
+ renderImage(graphics, coords[0], coords[1],
+ // Doesn't seem to work with SVGs
+ // Looking at the SLDStyleFactory, they get the icon from an
+ // ExternalGraphicFactory.
+ image,
+ rotation,
+ opacity,
+ isLabelObstacle);
} catch (IOException ex) {
Logger.getLogger(StyledShapePainter.class.getName()).log(Level.SEVERE, null, ex);
}
View
2 .../library/render/src/test/java/org/geotools/renderer/lite/RenderingTransformationTest.java
@@ -166,7 +166,7 @@ public void testTransformReproject() throws Exception {
// prepare a bbox in UTM-32N
ReferencedEnvelope reWgs84 = new ReferencedEnvelope(0, 12, 0, 12, CRS.decode("EPSG:4326"));
- ReferencedEnvelope reUTM32N = reWgs84.transform(CRS.decode("EPSG:32632"), true);
+ ReferencedEnvelope reUTM32N = reWgs84.transform(CRS.decode("EPSG:3857"), true);
// render it
MapContent mc = new MapContent();
View
20 modules/library/render/src/test/java/org/geotools/renderer/lite/StyledShapePainterTest.java
@@ -19,8 +19,11 @@
import java.awt.Graphics2D;
import java.awt.geom.AffineTransform;
import java.awt.image.BufferedImage;
+import java.io.File;
import java.net.URL;
+import javax.imageio.ImageIO;
+
import junit.framework.TestCase;
import org.geotools.factory.CommonFactoryFinder;
@@ -88,6 +91,23 @@ public void testGraphicLegend() throws Exception {
assertEquals(0, image.getRaster().getSample(90, 30, 0));
assertEquals(0, image.getRaster().getSample(90, 30, 1));
assertEquals(0, image.getRaster().getSample(90, 30, 2));
+
+ //check with a scaling factor
+ image = new BufferedImage(100, 100, BufferedImage.TYPE_INT_ARGB);
+ g2 = (Graphics2D) image.getGraphics();
+ painter.paint(g2, pointShape, legend, 2, false);
+ assertEquals(255, image.getRaster().getSample(0, 0, 0));
+ assertEquals(255, image.getRaster().getSample(0, 0, 1));
+ assertEquals(192, image.getRaster().getSample(0, 0, 2));
+
+ assertEquals(0, image.getRaster().getSample(30, 30, 0));
+ assertEquals(0, image.getRaster().getSample(30, 30, 1));
+ assertEquals(0, image.getRaster().getSample(30, 30, 2));
+
+ assertEquals(0, image.getRaster().getSample(90, 30, 0));
+ assertEquals(0, image.getRaster().getSample(90, 30, 1));
+ assertEquals(0, image.getRaster().getSample(90, 30, 2));
+
}
View
2 .../plugin/arcsde/datastore/src/main/java/org/geotools/arcsde/ArcSDERasterFormatFactory.java
@@ -58,7 +58,7 @@ public boolean isAvailable() {
LOGGER.fine(SeConnection.class.getName() + " is in place.");
LOGGER.fine(PeCoordinateSystem.class.getName() + " is in place.");
} catch (Throwable t) {
- LOGGER.log(Level.WARNING, "ArcSDE Java API seems to not be on your classpath. Please"
+ LOGGER.log(Level.FINE, "ArcSDE Java API seems to not be on your classpath. Please"
+ " verify that all needed jars are. ArcSDE data stores"
+ " will not be available.", t);
return false;
View
4 modules/plugin/jdbc/jdbc-postgis/src/main/java/org/geotools/data/postgis/PostGISDialect.java
@@ -110,6 +110,8 @@
static final Version V_2_0_0 = new Version("2.0.0");
static final Version PGSQL_V_9_0 = new Version("9.0");
+
+ static final Version PGSQL_V_9_1 = new Version("9.1");
public PostGISDialect(JDBCDataStore dataStore) {
super(dataStore);
@@ -836,7 +838,7 @@ public void encodeValue(Object value, Class type, StringBuffer sql) {
if(byte[].class.equals(type)) {
byte[] input = (byte[]) value;
//check postgres version, if > 9 default encoding is hex
- if (pgsqlVersion.compareTo(PGSQL_V_9_0) >= 0) {
+ if (pgsqlVersion.compareTo(PGSQL_V_9_1) >= 0) {
encodeByteArrayAsHex(input, sql);
}
else {
View
2 ...plugin/jdbc/jdbc-postgis/src/test/java/org/geotools/data/postgis/PostgisUDTTestSetup.java
@@ -39,7 +39,7 @@ public PostGISTestSetup getDelegate() {
@Override
protected void createUdtTable() throws Exception {
- if (getDelegate().isPgsqlVersionGreaterThanEqualTo(PostGISDialect.PGSQL_V_9_0)) {
+ if (getDelegate().isPgsqlVersionGreaterThanEqualTo(PostGISDialect.PGSQL_V_9_1)) {
run("CREATE DOMAIN foo AS text CHECK (VALUE ~ '\\d{2}\\D{2}');");
}
else {
View
25 ...c/jdbc-sqlserver/src/main/java/org/geotools/data/sqlserver/SQLServerDataStoreFactory.java
@@ -19,7 +19,6 @@
import java.io.IOException;
import java.util.Map;
-import org.geotools.data.DataAccessFactory.Param;
import org.geotools.jdbc.JDBCDataStore;
import org.geotools.jdbc.JDBCDataStoreFactory;
import org.geotools.jdbc.SQLDialect;
@@ -40,11 +39,17 @@
/** parameter for using integrated security, only works on windows, ignores the user and password parameters, the current windows user account is used for login*/
public static final Param INTSEC = new Param("Integrated Security", Boolean.class, "Login as current windows user account. Works only in windows. Ignores user and password settings.", false, new Boolean(false));
-
+
+ /** parameter for using Native Paging */
+ public static final Param NATIVE_PAGING = new Param("Use Native Paging", Boolean.class, "Use native paging for sql queries. For some sets of data, native paging can have a performance impact.", false, Boolean.TRUE);
+
/** Metadata table providing information about primary keys **/
public static final Param GEOMETRY_METADATA_TABLE = new Param("Geometry metadata table", String.class,
"The optional table containing geometry metadata (geometry type and srid). Can be expressed as 'schema.name' or just 'name'", false);
-
+
+ /** parameter for using WKB or Sql server binary directly. Setting to true will use WKB */
+ public static final Param NATIVE_SERIALIZATION = new Param("Use native geometry serialization", Boolean.class,
+ "Use native SQL Server serialization, or WKB serialization.", false, Boolean.FALSE);
@Override
protected SQLDialect createSQLDialect(JDBCDataStore dataStore) {
@@ -76,6 +81,8 @@ protected void setupParameters(Map parameters) {
super.setupParameters(parameters);
parameters.put(DBTYPE.key, DBTYPE);
parameters.put(INTSEC.key, INTSEC);
+ parameters.put(NATIVE_PAGING.key, NATIVE_PAGING);
+ parameters.put(NATIVE_SERIALIZATION.key, NATIVE_SERIALIZATION);
parameters.put(GEOMETRY_METADATA_TABLE.key, GEOMETRY_METADATA_TABLE);
}
@@ -107,7 +114,17 @@ protected JDBCDataStore createDataStoreInternal(JDBCDataStore dataStore, Map par
// check the geometry metadata table
String metadataTable = (String) GEOMETRY_METADATA_TABLE.lookUp(params);
dialect.setGeometryMetadataTable(metadataTable);
-
+
+ // check native paging
+ Boolean useNativePaging = (Boolean) NATIVE_PAGING.lookUp(params);
+ dialect.setUseOffSetLimit(useNativePaging == null || Boolean.TRUE.equals(useNativePaging));
+
+ // check serialization format
+ Boolean useNativeSerialization = (Boolean) NATIVE_SERIALIZATION.lookUp(params);
+ if (useNativeSerialization != null) {
+ dialect.setUseNativeSerialization(useNativeSerialization);
+ }
+
return dataStore;
}
View
81 ...lugin/jdbc/jdbc-sqlserver/src/main/java/org/geotools/data/sqlserver/SQLServerDialect.java
@@ -16,20 +16,12 @@
*/
package org.geotools.data.sqlserver;
-import java.io.IOException;
-import java.sql.Connection;
-import java.sql.Date;
-import java.sql.ResultSet;
-import java.sql.SQLException;
-import java.sql.Statement;
-import java.sql.Time;
-import java.sql.Types;
-import java.util.HashMap;
-import java.util.Map;
-import java.util.UUID;
-import java.util.logging.Level;
-
+import com.vividsolutions.jts.geom.*;
+import com.vividsolutions.jts.io.ParseException;
+import com.vividsolutions.jts.io.WKBReader;
+import com.vividsolutions.jts.io.WKTReader;
import org.geotools.data.jdbc.FilterToSQL;
+import org.geotools.data.sqlserver.reader.SqlServerBinaryReader;
import org.geotools.factory.Hints;
import org.geotools.geometry.jts.ReferencedEnvelope;
import org.geotools.jdbc.BasicSQLDialect;
@@ -42,19 +34,12 @@
import org.opengis.referencing.cs.CoordinateSystem;
import org.opengis.referencing.cs.CoordinateSystemAxis;
-import com.vividsolutions.jts.geom.Envelope;
-import com.vividsolutions.jts.geom.Geometry;
-import com.vividsolutions.jts.geom.GeometryCollection;
-import com.vividsolutions.jts.geom.GeometryFactory;
-import com.vividsolutions.jts.geom.LineString;
-import com.vividsolutions.jts.geom.MultiLineString;
-import com.vividsolutions.jts.geom.MultiPoint;
-import com.vividsolutions.jts.geom.MultiPolygon;
-import com.vividsolutions.jts.geom.Point;
-import com.vividsolutions.jts.geom.Polygon;
-import com.vividsolutions.jts.io.ParseException;
-import com.vividsolutions.jts.io.WKBReader;
-import com.vividsolutions.jts.io.WKTReader;
+import java.io.IOException;
+import java.sql.*;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.UUID;
+import java.util.logging.Level;
/**
* Dialect implementation for Microsoft SQL Server.
@@ -76,6 +61,10 @@
* @param dataStore
*/
private String geometryMetadataTable;
+
+ private Boolean useOffsetLimit = false;
+
+ private Boolean useNativeSerialization = false;
final static Map<String, Class> TYPE_TO_CLASS_MAP = new HashMap<String, Class>() {
{
@@ -411,7 +400,9 @@ public Integer getGeometrySRID(String schemaName, String tableName,
public void encodeGeometryColumn(GeometryDescriptor gatt, String prefix,
int srid, Hints hints, StringBuffer sql) {
encodeColumnName( prefix, gatt.getLocalName(), sql );
- sql.append( ".STAsBinary()");
+ if (!useNativeSerialization) {
+ sql.append( ".STAsBinary()");
+ }
}
@Override
@@ -434,11 +425,19 @@ public Geometry decodeGeometryValue(GeometryDescriptor descriptor,
if(bytes == null) {
return null;
}
- try {
- return new WKBReader(factory).read(bytes);
- } catch ( ParseException e ) {
- throw (IOException) new IOException().initCause( e );
- }
+ if (useNativeSerialization) {
+ try {
+ return new SqlServerBinaryReader(factory).read(bytes);
+ } catch ( IOException e ) {
+ throw (IOException) new IOException().initCause( e );
+ }
+ } else {
+ try {
+ return new WKBReader(factory).read(bytes);
+ } catch ( ParseException e ) {
+ throw (IOException) new IOException().initCause( e );
+ }
+ }
}
Geometry decodeGeometry( String s, GeometryFactory factory ) throws IOException {
@@ -556,7 +555,7 @@ protected void encodeTableName(String schemaName, String tableName, StringBuffer
@Override
public boolean isLimitOffsetSupported() {
- return true;
+ return useOffsetLimit;
}
@Override
@@ -626,4 +625,20 @@ public void setGeometryMetadataTable(String geometryMetadataTable) {
this.geometryMetadataTable = geometryMetadataTable;
}
+ /**
+ * Sets whether to use offset limit or not
+ * @param useOffsetLimit
+ */
+ public void setUseOffSetLimit(Boolean useOffsetLimit) {
+ this.useOffsetLimit = useOffsetLimit;
+ }
+
+ /**
+ * Sets whether to use native SQL Server binary serialization or WKB serialization
+ * @param useNativeSerialization
+ */
+ public void setUseNativeSerialization(Boolean useNativeSerialization) {
+ this.useNativeSerialization = useNativeSerialization;
+ }
+
}
View
2 ...bc-sqlserver/src/main/java/org/geotools/data/sqlserver/SQLServerJNDIDataStoreFactory.java
@@ -43,6 +43,8 @@ public SQLServerJNDIDataStoreFactory() {
protected void setupParameters(Map parameters) {
super.setupParameters(parameters);
parameters.put(INTSEC.key, INTSEC);
+ parameters.put(NATIVE_PAGING.key, NATIVE_PAGING);
+ parameters.put(NATIVE_SERIALIZATION.key, NATIVE_SERIALIZATION);
parameters.put(GEOMETRY_METADATA_TABLE.key, GEOMETRY_METADATA_TABLE);
}
}
View
25 ...s/plugin/jdbc/jdbc-sqlserver/src/main/java/org/geotools/data/sqlserver/reader/Figure.java
@@ -0,0 +1,25 @@
+package org.geotools.data.sqlserver.reader;
+
+/**
+ * @author Anders Bakkevold, Bouvet
+ *
+ * @source $URL$
+ */
+public class Figure {
+
+ private int attribute;
+ private int pointOffset;
+
+ public Figure(int attribute, int pointOffset) {
+ this.attribute = attribute;
+ this.pointOffset = pointOffset;
+ }
+
+ public int getAttribute() {
+ return attribute;
+ }
+
+ public int getPointOffset() {
+ return pointOffset;
+ }
+}
View
31 ...es/plugin/jdbc/jdbc-sqlserver/src/main/java/org/geotools/data/sqlserver/reader/Shape.java
@@ -0,0 +1,31 @@
+package org.geotools.data.sqlserver.reader;
+
+/**
+ * @author Anders Bakkevold, Bouvet
+ *
+ * @source $URL$
+ */
+public class Shape {
+
+ private int parentOffset;
+ private int figureOffset;
+ private Type type;
+
+ public Shape(int parentOffset, int figureOffset, int type) {
+ this.parentOffset = parentOffset;
+ this.figureOffset = figureOffset;
+ this.type = Type.findType(type);
+ }
+
+ public int getParentOffset() {
+ return parentOffset;
+ }
+
+ public int getFigureOffset() {
+ return figureOffset;
+ }
+
+ public Type getType() {
+ return type;
+ }
+}
View
103 ...jdbc/jdbc-sqlserver/src/main/java/org/geotools/data/sqlserver/reader/SqlServerBinary.java
@@ -0,0 +1,103 @@
+package org.geotools.data.sqlserver.reader;
+
+import com.vividsolutions.jts.geom.Coordinate;
+import com.vividsolutions.jts.geom.CoordinateSequence;
+
+/**
+ * Represents the information from a binary sqlserver geometry
+ *
+ * @author Anders Bakkevold, Bouvet
+ *
+ * @source $URL$
+ */
+class SqlServerBinary {
+
+ private int srid;
+ private int numberOfPoints;
+ private Coordinate[] coordinates;
+ private Shape[] shapes;
+ private Figure[] figures;
+ private CoordinateSequence[] sequences;
+
+ public int getSrid() {
+ return srid;
+ }
+
+ public void setSrid(int srid) {
+ this.srid = srid;
+ }
+
+ public void setSerializationProperties(byte serializationProperties) {
+ this.serializationProperties = serializationProperties;
+ }
+
+ public boolean hasZ() {
+ return (serializationProperties & 1) == 1;
+ }
+
+ public boolean hasM() {
+ return (serializationProperties & 2) == 2;
+ }
+
+ public boolean isValid(){
+ return (serializationProperties & 4) == 4;
+ }
+
+ public boolean isSinglePoint() {
+ return (serializationProperties & 8) == 8;
+ }
+
+ public boolean hasSingleLineSegment() {
+ return (serializationProperties & 16) == 16;
+ }
+
+ private byte serializationProperties;
+
+ public int getNumberOfPoints() {
+ return numberOfPoints;
+ }
+
+ public void setNumberOfPoints(int numberOfPoints) {
+ this.numberOfPoints = numberOfPoints;
+ }
+
+ public Coordinate[] getCoordinates() {
+ return coordinates;
+ }
+
+ public void setCoordinates(Coordinate[] coordinates) {
+ this.coordinates = coordinates;
+ }
+
+ public void setShapes(Shape[] shapes) {
+ this.shapes = shapes;
+ }
+
+ public void setFigures(Figure[] figures) {
+ this.figures = figures;
+ }
+
+ public Figure[] getFigures() {
+ return figures;
+ }
+
+ public void setSequences(CoordinateSequence[] sequences) {
+ this.sequences = sequences;
+ }
+
+ public Shape[] getShapes() {
+ return shapes;
+ }
+
+ public Shape getShape(int index) {
+ return shapes[index];
+ }
+
+ public Figure getFigure(int index) {
+ return figures[index];
+ }
+
+ public CoordinateSequence getSequence(int index) {
+ return sequences[index];
+ }
+}
View
15 ...erver/src/main/java/org/geotools/data/sqlserver/reader/SqlServerBinaryParseException.java
@@ -0,0 +1,15 @@
+package org.geotools.data.sqlserver.reader;
+
+import java.io.IOException;
+
+/**
+ * @author Anders Bakkevold, Bouvet
+ *
+ * @source $URL$
+ */
+public class SqlServerBinaryParseException extends IOException {
+
+ public SqlServerBinaryParseException(String message) {
+ super(message);
+ }
+}
View
268 ...dbc-sqlserver/src/main/java/org/geotools/data/sqlserver/reader/SqlServerBinaryReader.java
@@ -0,0 +1,268 @@
+package org.geotools.data.sqlserver.reader;
+
+import com.vividsolutions.jts.geom.*;
+import com.vividsolutions.jts.io.ByteArrayInStream;
+import com.vividsolutions.jts.io.ByteOrderDataInStream;
+import com.vividsolutions.jts.io.ByteOrderValues;
+import com.vividsolutions.jts.io.InStream;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.List;
+
+/**
+ * Decode Sql Server binary format to JTS
+ *
+ * @author Anders Bakkevold, Bouvet
+ *
+ * @source $URL$
+ */
+public class SqlServerBinaryReader {
+
+ private ByteOrderDataInStream dis = new ByteOrderDataInStream();
+ private GeometryFactory gf = new GeometryFactory();
+ private SqlServerBinary binary;
+
+ public SqlServerBinaryReader() {
+ this.gf = new GeometryFactory();
+ }
+
+ public SqlServerBinaryReader(GeometryFactory gf) {
+ this.gf = gf;
+ }
+
+ public Geometry read(byte[] bytes) throws IOException {
+ this.binary = new SqlServerBinary();
+ return read(new ByteArrayInStream(bytes));
+ }
+
+ public Geometry read(InStream is) throws IOException {
+ parse(is);
+ readCoordinateSequences();
+ Type type = getTypeFromBinary();
+ Geometry geometry = decode(0, type);
+ geometry.setSRID(binary.getSrid());
+ return geometry;
+ }
+
+ private Geometry decode(int shapeIndex, Type type) throws SqlServerBinaryParseException {
+ switch (type) {
+ case GEOMETRYCOLLECTION:
+ return decodeGeometryCollection(shapeIndex);
+ case POINT:
+ return decodePoint(shapeIndex);
+ case LINESTRING:
+ return decodeLinestring(shapeIndex);
+ case POLYGON:
+ return decodePolygon(shapeIndex);
+ case MULTILINESTRING:
+ return decodeMultiLinestring(shapeIndex);
+ case MULTIPOINT:
+ return decodeMultiPoint(shapeIndex);
+ case MULTIPOLYGON:
+ return decodeMultiPolygon(shapeIndex);
+ default:
+ throw new SqlServerBinaryParseException("Geometry type unsupported " + type);
+ }
+ }
+
+ private Geometry decodeMultiPolygon( int shapeIndex) {
+ Collection<Geometry> polygons = new ArrayList<Geometry>();
+ for (int i = shapeIndex; i < binary.getShapes().length; i++) {
+ if (binary.getShape(i).getParentOffset() == shapeIndex) {
+ polygons.add(gf.createPolygon(binary.getSequence(binary.getShape(i).getFigureOffset())));
+ }
+ }
+ return gf.createMultiPolygon(polygons.toArray(new Polygon[polygons.size()])); }
+
+ private Geometry decodeMultiPoint(int shapeIndex) {
+ Collection<Geometry> points = new ArrayList<Geometry>();
+ for (int i = shapeIndex; i < binary.getShapes().length; i++) {
+ if (binary.getShape(i).getParentOffset() == shapeIndex) {
+ points.add(gf.createPoint(binary.getSequence(binary.getShape(i).getFigureOffset())));
+ }
+ }
+ return gf.createMultiPoint(points.toArray(new Point[points.size()]));
+ }
+
+ private Geometry decodeMultiLinestring(int shapeIndex) {
+ Collection<Geometry> linestrings = new ArrayList<Geometry>();
+ for (int i = shapeIndex; i < binary.getShapes().length; i++) {
+ if (binary.getShape(i).getParentOffset() == shapeIndex) {
+ linestrings.add(gf.createLineString(binary.getSequence(binary.getShape(i).getFigureOffset())));
+ }
+ }
+ return gf.createMultiLineString(linestrings.toArray(new LineString[linestrings.size()]));
+ }
+
+ private Geometry decodePolygon(int shapeIndex) {
+ Shape shape = binary.getShape(shapeIndex);
+ int figureOffset = shape.getFigureOffset();
+ int figureStopIndex = binary.getFigures().length-1;
+ if (shapeIndex +1 < binary.getShapes().length) {
+ Shape nextShape = binary.getShape(shapeIndex + 1);
+ figureStopIndex = nextShape.getFigureOffset()-1;
+ }
+ List<LinearRing> linearRings = new ArrayList<LinearRing>();
+ if (figureOffset <= -1) {
+ return gf.createPolygon(new Coordinate[0]);
+ }
+ for (int i = figureOffset; i <= figureStopIndex; i++) {
+ CoordinateSequence sequence = binary.getSequence(i);
+ linearRings.add(gf.createLinearRing(sequence));
+ }
+ LinearRing outerShell = linearRings.remove(0);
+ LinearRing[] holes = linearRings.toArray(new LinearRing[linearRings.size()]);
+ return gf.createPolygon(outerShell, holes);
+ }
+
+ private Geometry decodeLinestring(int shapeIndex) {
+ Shape shape = binary.getShape(shapeIndex);
+ CoordinateSequence sequence = binary.getSequence(shape.getFigureOffset());
+ return gf.createLineString(sequence);
+ }
+
+ private Geometry decodePoint(int shapeIndex) {
+ Shape shape = binary.getShapes()[shapeIndex];
+ Coordinate coordinate;
+ if (binary.isSinglePoint()) {
+ coordinate = binary.getCoordinates()[0];
+ } else if (shape.getParentOffset() != -1) {
+ Figure figure = binary.getFigure(shape.getFigureOffset());
+ coordinate = binary.getCoordinates()[figure.getPointOffset()];
+ } else {
+ coordinate = null;
+ }
+ return gf.createPoint(coordinate);
+ }
+
+ private Geometry decodeGeometryCollection(int shapeIndex) throws SqlServerBinaryParseException {
+ Collection<Geometry> geometries = new ArrayList<Geometry>();
+ for (int i = shapeIndex +1; i < binary.getShapes().length; i++) {
+ Shape subShape = binary.getShapes()[i];
+ if (subShape.getParentOffset() == shapeIndex) {
+ geometries.add(decode(i, subShape.getType()));
+ }
+ }
+ return gf.buildGeometry(geometries);
+ }
+
+ private Type getTypeFromBinary() {
+ if (binary.isSinglePoint()) {
+ return Type.POINT;
+ }
+ if (binary.hasSingleLineSegment()) {
+ return Type.LINESTRING;
+ }
+ return binary.getShapes()[0].getType();
+ }
+
+ private void readCoordinateSequences() {
+ Figure[] figures = binary.getFigures();
+ CoordinateSequence[] sequences = new CoordinateSequence[figures.length];
+ for (int i = 0; i < figures.length; i++) {
+ int figurePointOffset = figures[i].getPointOffset();
+ int nextPointOffset = figures.length >= i+2 ? figures[i+1].getPointOffset() : binary.getCoordinates().length;
+ Coordinate[] coordinates = Arrays.copyOfRange(binary.getCoordinates(), figurePointOffset, nextPointOffset);
+ int attribute = figures[i].getAttribute();
+ if ((attribute == 0 || attribute == 2) && !coordinates[0].equals(coordinates[coordinates.length-1]) ) {
+ coordinates = Arrays.copyOf(coordinates, coordinates.length + 1);
+ coordinates[coordinates.length-1] = coordinates[0];
+ }
+ sequences[i] = gf.getCoordinateSequenceFactory().create(coordinates);
+ }
+ binary.setSequences(sequences);
+ }
+
+ private void parse(InStream is) throws IOException {
+ dis.setInStream(is);
+ dis.setOrder(ByteOrderValues.LITTLE_ENDIAN);
+ binary.setSrid(dis.readInt());
+ byte version = dis.readByte();
+ if (version != 1) {
+ throw new SqlServerBinaryParseException("Unsupported version (only supports version 1): " + version);
+ }
+ binary.setSerializationProperties(dis.readByte());
+
+ readNumberOfPoints();
+ readCoordinates();
+ readZValues();
+ readMValues();
+
+ if (binary.isSinglePoint()) {
+ binary.setFigures(new Figure[] { new Figure(1,0) });
+ binary.setShapes(new Shape[] { new Shape(-1,0,2)});
+ } else if (binary.hasSingleLineSegment()) {
+ binary.setFigures(new Figure[] { new Figure(1,0) });
+ binary.setShapes(new Shape[] { new Shape(-1,0,1)});
+ } else {
+ readFigures();
+ readShapes();
+ }
+ }
+
+ private void readNumberOfPoints() throws IOException {
+ if (binary.isSinglePoint()) {
+ binary.setNumberOfPoints(1);
+ } else if (binary.hasSingleLineSegment()) {
+ binary.setNumberOfPoints(2);
+ } else {
+ binary.setNumberOfPoints(dis.readInt());
+ }
+ }
+
+ private void readCoordinates() throws IOException {
+ Coordinate[] coordinates = new Coordinate[binary.getNumberOfPoints()];
+ for(int i = 0; i<binary.getNumberOfPoints(); i++) {
+ coordinates[i] = readCoordinate();
+ }
+ binary.setCoordinates(coordinates);
+ }
+
+ private void readShapes() throws IOException {
+ int numberOfShapes;Shape[] shapesMetadata;
+ numberOfShapes = dis.readInt();
+ shapesMetadata = new Shape[numberOfShapes];
+ for (int i = 0; i < numberOfShapes; i++) {
+ int parentOffset = dis.readInt();
+ int figureOffset = dis.readInt();
+ int shapeType = dis.readByte();
+ shapesMetadata[i] = new Shape(parentOffset, figureOffset, shapeType);
+ }
+ binary.setShapes(shapesMetadata);
+ }
+
+ private void readFigures() throws IOException {
+ int numberOfFigures;Figure[] figuresMetadata;
+ numberOfFigures = dis.readInt();
+ figuresMetadata = new Figure[numberOfFigures];
+ for (int i = 0; i < numberOfFigures; i++) {
+ byte figureAttribute = dis.readByte();
+ int figurePointOffset = dis.readInt();
+ figuresMetadata[i] = new Figure(figureAttribute,figurePointOffset);
+ }
+ binary.setFigures(figuresMetadata);
+ }
+
+ private void readMValues() throws IOException {
+ //measure values are currently discarded, as they cannot be represented in a JTS Geometry
+ if (binary.hasM()) {
+ for (int i = 0; i < binary.getNumberOfPoints(); i++) {
+ dis.readDouble();
+ }
+ }
+ }
+
+ private void readZValues() throws IOException {
+ if (binary.hasZ()) {
+ for (int i = 0; i < binary.getNumberOfPoints(); i++) {
+ binary.getCoordinates()[i].z = dis.readDouble();
+ }
+ }
+ }
+
+ private Coordinate readCoordinate() throws IOException {
+ return new Coordinate(dis.readDouble(), dis.readDouble());
+ }
+}
View
36 ...les/plugin/jdbc/jdbc-sqlserver/src/main/java/org/geotools/data/sqlserver/reader/Type.java
@@ -0,0 +1,36 @@
+package org.geotools.data.sqlserver.reader;
+
+/**
+ * @author Anders Bakkevold, Bouvet
+ *
+ * @source $URL$
+ */
+public enum Type {
+
+ POINT (1),
+ LINESTRING(2),
+ POLYGON(3),
+ MULTIPOINT(4),
+ MULTILINESTRING(5),
+ MULTIPOLYGON(6),
+ GEOMETRYCOLLECTION(7),
+ CIRCULARSTRING(8),
+ COMPOUNDCURVE(9),
+ CURVEPOLYGON(10),
+ FULLGLOBE(11);
+
+ private int value;
+
+ private Type(int value) {
+ this.value = value;
+ }
+
+ public static Type findType(int value) {
+ for (Type type : Type.values()) {
+ if (type.value == value) {
+ return type;
+ }
+ }
+ throw new IllegalArgumentException();
+ }
+}
View
4 .../jdbc-sqlserver/src/test/java/org/geotools/data/sqlserver/SQLServerFeatureSourceTest.java
@@ -20,15 +20,15 @@
import org.geotools.jdbc.JDBCTestSetup;
/**
- *
+ *
*
* @source $URL$
*/
public class SQLServerFeatureSourceTest extends JDBCFeatureSourceTest {
@Override
protected JDBCTestSetup createTestSetup() {
- return new SQLServerTestSetup();
+ return new SqlServerNativeSerializationTestSetup();
}
}
View
20 ...rver/src/test/java/org/geotools/data/sqlserver/SqlServerNativeSerializationTestSetup.java
@@ -0,0 +1,20 @@
+package org.geotools.data.sqlserver;
+
+import org.apache.commons.dbcp.BasicDataSource;
+import org.geotools.jdbc.JDBCDataStore;
+
+import java.util.Properties;
+
+/**
+ *
+ *
+ * @source $URL$
+ */
+public class SqlServerNativeSerializationTestSetup extends SQLServerTestSetup {
+
+ protected void setUpDataStore(JDBCDataStore dataStore) {
+ SQLServerDialect dialect = (SQLServerDialect) dataStore.getSQLDialect();
+ dialect.setUseNativeSerialization(Boolean.TRUE);
+ super.setUpDataStore(dataStore);
+ }
+}
View
120 ...sqlserver/src/test/java/org/geotools/data/sqlserver/reader/SQLServerBinaryReaderTest.java
@@ -0,0 +1,120 @@
+package org.geotools.data.sqlserver.reader;
+
+import com.vividsolutions.jts.geom.Geometry;
+import com.vividsolutions.jts.geom.GeometryFactory;
+import com.vividsolutions.jts.geom.PrecisionModel;
+import com.vividsolutions.jts.io.ParseException;
+import com.vividsolutions.jts.io.WKBReader;
+import com.vividsolutions.jts.io.WKTReader;
+import junit.framework.TestCase;
+
+import java.io.IOException;
+
+/**
+ * Binary test data have been produced by executing this query in SQL Server, and then removing the prefix '0x':
+ * select geometry::STGeomFromText('wktstring',srid);
+ *
+ * @source $URL$
+ */
+public class SQLServerBinaryReaderTest extends TestCase {
+
+ public void testPoint() throws Exception {
+ String geometryPointWKT = "POINT (5 10)";
+ String geometryPointBinary = "E6100000010C00000000000014400000000000002440";
+ testGeometry(geometryPointBinary, geometryPointWKT, 4326);
+ }
+
+ public void testEmptyPointGeometry() throws Exception {
+ String geometryEmptyWKT = "POINT EMPTY";
+ String geometryEmptyBinary = "000000000104000000000000000001000000FFFFFFFFFFFFFFFF01";
+ testGeometry(geometryEmptyBinary, geometryEmptyWKT);
+ }
+
+ public void testEmptyPolygonGeometry() throws Exception {
+ String geometryEmptyWKT = "POLYGON EMPTY";
+ String geometryEmptyBinary = "000000000104000000000000000001000000FFFFFFFFFFFFFFFF03";
+ testGeometry(geometryEmptyBinary, geometryEmptyWKT);
+ }
+
+ public void testEmptyGeometryCollection() throws Exception {
+ String geometryEmptyWKT = "GEOMETRYCOLLECTION EMPTY";
+ String geometryEmptyBinary = "000000000104000000000000000001000000FFFFFFFFFFFFFFFF07";
+ testGeometry(geometryEmptyBinary, geometryEmptyWKT);
+ }
+
+ public void testPolygon() throws Exception {
+ String geometryPolygonWkt = "POLYGON ((-680000 6100000, -670000 6100000, -670000 6090000, -680000 6090000, -680000 6100000))"; //32633
+ String geometryPolygonBinary = "797F00000104050000000000000080C024C1000000000845574100000000607224C1000000000845574100000000607224C100000000443B57410000000080C024C100000000443B57410000000080C024C1000000000845574101000000020000000001000000FFFFFFFF0000000003";
+ testGeometry(geometryPolygonBinary, geometryPolygonWkt, 32633);
+ }
+
+ public void testLineStringWithZ() throws Exception {
+ String geometryLineStringWithZWKT = "LINESTRING (0 1 1, 3 2 2, 4 5 NaN)";
+ String geometryLineStringWithZBinary = "E61000000105030000000000000000000000000000000000F03F0000000000000840000000000000004000000000000010400000000000001440000000000000F03F0000000000000040000000000000F8FF01000000010000000001000000FFFFFFFF0000000002";
+ Geometry geometry = testGeometry(geometryLineStringWithZBinary, geometryLineStringWithZWKT, 4326);
+ assertEquals(1.0, geometry.getCoordinates()[0].z, 0);
+ assertEquals(2.0, geometry.getCoordinates()[1].z, 0);
+ assertEquals(Double.NaN, geometry.getCoordinates()[2].z, 0);
+ }
+
+ public void testGeometryCollection() throws Exception {
+ String geometryCollectionWKT = "GEOMETRYCOLLECTION (POINT (4 0), LINESTRING (4 2, 5 3), POLYGON ((0 0, 3 0, 3 3, 0 3, 0 0),(1 1, 1 2, 2 2, 2 1, 1 1)))";
+ String geometryCollectionBinary = "0000000001040D0000000000000000001040000000000000000000000000000010400000000000000040000000000000144000000000000008400000000000000000000000000000000000000000000008400000000000000000000000000000084000000000000008400000000000000000000000000000084000000000000000000000000000000000000000000000F03F000000000000F03F000000000000F03F0000000000000040000000000000004000000000000000400000000000000040000000000000F03F000000000000F03F000000000000F03F04000000010000000001010000000203000000000800000004000000FFFFFFFF0000000007000000000000000001000000000100000002000000000200000003";
+ testGeometry(geometryCollectionBinary, geometryCollectionWKT,0);
+
+ String wkt2 = "GEOMETRYCOLLECTION (POINT (4.2585 0), MULTILINESTRING ((10 10, 20 20, 10 40.999), (40 40, 30 30, 40 20, 30 10)), POLYGON ((0 0, 3 0, 3 3, 0 3, 0 0),(1 1, 1 2, 2 2, 2 1, 1 1)))";
+ String binary2 = "0000000001041200000062105839B40811400000000000000000000000000000244000000000000024400000000000003440000000000000344000000000000024401D5A643BDF7F4440000000000000444000000000000044400000000000003E400000000000003E40000000000000444000000000000034400000000000003E4000000000000024400000000000000000000000000000000000000000000008400000000000000000000000000000084000000000000008400000000000000000000000000000084000000000000000000000000000000000000000000000F03F000000000000F03F000000000000F03F0000000000000040000000000000004000000000000000400000000000000040000000000000F03F000000000000F03F000000000000F03F050000000100000000010100000001040000000208000000000D00000006000000FFFFFFFF0000000007000000000000000001000000000100000005020000000100000002020000000200000002000000000300000003";
+ testGeometry(binary2, wkt2, 0);
+ }
+
+ public void testMultiLinestring() throws Exception {
+ String wkt = "MULTILINESTRING ((10 10, 20 20, 10 40), (40 40, 30 30, 40 20, 30 10)) "; //4326
+ String binary = "00000000010407000000000000000000244000000000000024400000000000003440000000000000344000000000000024400000000000004440000000000000444000000000000044400000000000003E400000000000003E40000000000000444000000000000034400000000000003E400000000000002440020000000100000000010300000003000000FFFFFFFF0000000005000000000000000002000000000100000002";
+ testGeometry(binary, wkt, 0);
+ }
+
+ public void testMultiPoint() throws Exception {
+ String wkt = "MULTIPOINT ((10 40), (40 30), (20 20), (30 10))";
+ String binary = "000000000104040000000000000000002440000000000000444000000000000044400000000000003E40000000000000344000000000000034400000000000003E40000000000000244004000000010000000001010000000102000000010300000005000000FFFFFFFF0000000004000000000000000001000000000100000001000000000200000001000000000300000001";
+ testGeometry(binary, wkt, 0);
+ }
+
+ public void testMultiPolygon() throws Exception {
+ String wkt = "MULTIPOLYGON (((30 20, 10 40, 45 40, 30 20)),((15 5, 40 10, 10 20, 5 10, 15 5)))";
+ String binary = "000000000104090000000000000000003E40000000000000344000000000000024400000000000004440000000000080464000000000000044400000000000003E4000000000000034400000000000002E4000000000000014400000000000004440000000000000244000000000000024400000000000003440000000000000144000000000000024400000000000002E400000000000001440020000000200000000020400000003000000FFFFFFFF0000000006000000000000000003000000000100000003";
+ testGeometry(binary, wkt, 0);
+ }
+
+ public void testSingleLineSegment() throws Exception {
+ String geometryPointWKT = "LINESTRING (5 10, 10 10)";
+ String geometryPointBinary = "0000000001140000000000001440000000000000244000000000000024400000000000002440";
+ testGeometry(geometryPointBinary, geometryPointWKT, 0);
+ }
+
+ public void testGeographyExtremeValues() throws Exception {
+ String wkt = "LINESTRING (-90 -15069, 90 15069)";
+ String binary = "E6100000011400000000008056C000000000806ECDC0000000000080564000000000806ECD40";
+ testGeometry(binary,wkt,4326);
+ }
+
+ private Geometry testGeometry(String geometryBinary, String geometryWKT) throws Exception {
+ WKTReader readerWkt = new WKTReader((new GeometryFactory(new PrecisionModel(), 0)));
+ return testGeometry(geometryBinary, geometryWKT, readerWkt);
+ }
+
+ private Geometry testGeometry(String geometryBinary, String geometryWKT, WKTReader wktReader) throws ParseException, IOException {
+ byte[] bytes = WKBReader.hexToBytes(geometryBinary);
+ Geometry geometryFromWkt = wktReader.read(geometryWKT);
+ SqlServerBinaryReader reader = new SqlServerBinaryReader();
+ Geometry geometryFromBinary = reader.read(bytes);
+ assertEquals(geometryFromWkt, geometryFromBinary);
+ return geometryFromBinary;
+ }
+
+ private Geometry testGeometry(String geometryBinary, String geometryWKT, int srid) throws Exception {
+ WKTReader readerWkt = new WKTReader((new GeometryFactory(new PrecisionModel(), srid)));
+ Geometry geometry = testGeometry(geometryBinary, geometryWKT, readerWkt);
+ assertEquals(srid, geometry.getSRID());
+ return geometry;
+ }
+}
View
76 modules/plugin/shapefile/src/main/java/org/geotools/data/shapefile/shp/ShapefileReader.java
@@ -237,18 +237,7 @@ public ShapefileReader(ShpFiles shapefileFiles, boolean strict,
*/
public ShapefileReader(ShpFiles shapefileFiles, boolean strict,
boolean useMemoryMapped, GeometryFactory gf) throws IOException, ShapefileException {
- this.channel = shapefileFiles.getReadChannel(ShpFileType.SHP, this);
- this.useMemoryMappedBuffer = useMemoryMapped;
- streamLogger.open();
- randomAccessEnabled = channel instanceof FileChannel;
- try {
- shxReader = new IndexFile(shapefileFiles, this.useMemoryMappedBuffer);
- } catch(Exception e) {
- LOGGER.log(Level.WARNING, "Could not open the .shx file, continuing " +
- "assuming the .shp file is not sparse", e);
- currentShape = UNKNOWN;
- }
- init(strict, gf);
+ this(shapefileFiles, strict, useMemoryMapped, gf, false);
}
/**
@@ -438,16 +427,17 @@ private boolean hasNext(boolean checkRecno) throws IOException {
// represents the current position)
if(currentShape > UNKNOWN && currentShape > shxReader.getRecordCount() - 1)
return false;
-
- // mark current position
- int position = buffer.position();
// ensure the proper position, regardless of read or handler behavior
- buffer.position(getNextOffset());
+ positionBufferForOffset(buffer, getNextOffset());
// no more data left
- if (buffer.remaining() < 8)
+ if (buffer.remaining() < 8) {
return false;
+ }
+
+ // mark current position
+ int position = buffer.position();
// looks good
boolean hasNext = true;
@@ -463,12 +453,12 @@ private boolean hasNext(boolean checkRecno) throws IOException {
return hasNext;
}
-
+
private int getNextOffset() throws IOException {
if(currentShape >= 0) {
- return this.toBufferOffset(shxReader.getOffsetInBytes(currentShape));
+ return shxReader.getOffsetInBytes(currentShape);
} else {
- return this.toBufferOffset(record.end);
+ return record.end;
}
}
@@ -524,6 +514,29 @@ public int transferTo(ShapefileWriter writer, int recordNum, double[] bounds)
return len;
}
+ private void positionBufferForOffset(ByteBuffer buffer, int offset) throws IOException {
+ if (useMemoryMappedBuffer) {
+ buffer.position(offset);
+ return;
+ }
+
+ // Check to see if requested offset is already loaded; ensure that record header is in the buffer
+ if (currentOffset <= offset && currentOffset + buffer.limit() >= offset + 8) {
+ buffer.position(toBufferOffset(offset));
+ } else {
+ if (!randomAccessEnabled) {
+ throw new UnsupportedOperationException("Random Access not enabled");
+ }
+ FileChannel fc = (FileChannel) this.channel;
+ fc.position(offset);
+ currentOffset = offset;
+ buffer.position(0);
+ buffer.limit(buffer.capacity());
+ fill(buffer, fc);
+ buffer.flip();
+ }
+ }
+
/**
* Fetch the next record information.
*
@@ -533,7 +546,7 @@ public int transferTo(ShapefileWriter writer, int recordNum, double[] bounds)
public Record nextRecord() throws IOException {
// need to update position
- buffer.position(getNextOffset());
+ positionBufferForOffset(buffer, getNextOffset());
if(currentShape != UNKNOWN)
currentShape++;
@@ -632,26 +645,7 @@ public void goTo(int offset) throws IOException,
UnsupportedOperationException {
disableShxUsage();
if (randomAccessEnabled) {
- if (this.useMemoryMappedBuffer) {
- buffer.position(offset);
- } else {
- /*
- * Check to see if requested offset is already loaded; ensure
- * that record header is in the buffer
- */
- if (this.currentOffset <= offset
- && this.currentOffset + buffer.limit() >= offset + 8) {
- buffer.position(this.toBufferOffset(offset));
- } else {
- FileChannel fc = (FileChannel) this.channel;
- fc.position(offset);
- this.currentOffset = offset;
- buffer.position(0);
- buffer.limit(buffer.capacity());
- fill(buffer, fc);
- buffer.position(0);
- }
- }
+ positionBufferForOffset(buffer, offset);
int oldRecordOffset = record.end;
record.end = offset;
View
16 modules/plugin/shapefile/src/test/java/org/geotools/data/shapefile/ShapefileTest.java
@@ -17,6 +17,7 @@
package org.geotools.data.shapefile;
import java.io.File;
+import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.Serializable;
import java.net.URL;
@@ -259,6 +260,21 @@ public void testNullGeometries() throws Exception {
}
}
+ public void testReadingSparse() throws IOException {
+ File file = TestData.file(TestCaseSupport.class, "sparse/sparse.shp");
+ ShapefileReader reader = new ShapefileReader(new ShpFiles(file), false, false, new GeometryFactory());
+ int cnt = 0;
+ try {
+ while (reader.hasNext()) {
+ reader.nextRecord().shape();
+ cnt++;
+ }
+ } finally {
+ reader.close();
+ }
+ assertEquals("Did not read all Geometries from sparse file.", 31, cnt);
+ }
+
protected void loadShapes(String resource, int expected) throws Exception {
final URL url = TestData.url(resource);
ShapefileReader reader = new ShapefileReader(new ShpFiles(url), false,
View
BIN ...ugin/shapefile/src/test/resources/org/geotools/data/shapefile/test-data/sparse/sparse.dbf
Binary file not shown.
View
BIN ...ugin/shapefile/src/test/resources/org/geotools/data/shapefile/test-data/sparse/sparse.shp
Binary file not shown.
View
BIN ...ugin/shapefile/src/test/resources/org/geotools/data/shapefile/test-data/sparse/sparse.shx
Binary file not shown.
View
74 ...ported/shapefile-ng/src/main/java/org/geotools/data/shapefile/ng/shp/ShapefileReader.java
@@ -228,18 +228,7 @@ public Object getSimplifiedShape(ScreenMap sm) {
*/
public ShapefileReader(ShpFiles shapefileFiles, boolean strict,
boolean useMemoryMapped, GeometryFactory gf) throws IOException, ShapefileException {
- this.channel = shapefileFiles.getReadChannel(ShpFileType.SHP, this);
- this.useMemoryMappedBuffer = useMemoryMapped;
- streamLogger.open();
- randomAccessEnabled = channel instanceof FileChannel;
- try {
- shxReader = new IndexFile(shapefileFiles, this.useMemoryMappedBuffer);
- } catch(Exception e) {
- LOGGER.log(Level.WARNING, "Could not open the .shx file, continuing " +
- "assuming the .shp file is not sparse", e);
- currentShape = UNKNOWN;
- }
- init(strict, gf);
+ this(shapefileFiles, strict, useMemoryMapped, gf, false);
}
/**
@@ -430,15 +419,16 @@ private boolean hasNext(boolean checkRecno) throws IOException {
if(currentShape > UNKNOWN && currentShape > shxReader.getRecordCount() - 1)
return false;
- // mark current position
- int position = buffer.position();
-
// ensure the proper position, regardless of read or handler behavior
- buffer.position(getNextOffset());
+ positionBufferForOffset(buffer, getNextOffset());
// no more data left
- if (buffer.remaining() < 8)
+ if (buffer.remaining() < 8) {
return false;
+ }
+
+ // mark current position
+ int position = buffer.position();
// looks good
boolean hasNext = true;
@@ -457,9 +447,9 @@ private boolean hasNext(boolean checkRecno) throws IOException {
private int getNextOffset() throws IOException {
if(currentShape >= 0) {
- return this.toBufferOffset(shxReader.getOffsetInBytes(currentShape));
+ return shxReader.getOffsetInBytes(currentShape);
} else {
- return this.toBufferOffset(record.end);
+ return record.end;
}
}
@@ -515,6 +505,29 @@ public int transferTo(ShapefileWriter writer, int recordNum, double[] bounds)
return len;
}
+ private void positionBufferForOffset(ByteBuffer buffer, int offset) throws IOException {
+ if (useMemoryMappedBuffer) {
+ buffer.position(offset);
+ return;
+ }
+
+ // Check to see if requested offset is already loaded; ensure that record header is in the buffer
+ if (currentOffset <= offset && currentOffset + buffer.limit() >= offset + 8) {
+ buffer.position(toBufferOffset(offset));
+ } else {
+ if (!randomAccessEnabled) {
+ throw new UnsupportedOperationException("Random Access not enabled");
+ }
+ FileChannel fc = (FileChannel) this.channel;
+ fc.position(offset);
+ currentOffset = offset;
+ buffer.position(0);
+ buffer.limit(buffer.capacity());
+ fill(buffer, fc);
+ buffer.flip();
+ }
+ }
+
/**
* Fetch the next record information.
*
@@ -524,7 +537,7 @@ public int transferTo(ShapefileWriter writer, int recordNum, double[] bounds)
public Record nextRecord() throws IOException {
// need to update position
- buffer.position(getNextOffset());
+ positionBufferForOffset(buffer, getNextOffset());
if(currentShape != UNKNOWN)
currentShape++;
@@ -623,26 +636,7 @@ public void goTo(int offset) throws IOException,
UnsupportedOperationException {
disableShxUsage();
if (randomAccessEnabled) {
- if (this.useMemoryMappedBuffer) {
- buffer.position(offset);
- } else {
- /*
- * Check to see if requested offset is already loaded; ensure
- * that record header is in the buffer
- */
- if (this.currentOffset <= offset
- && this.currentOffset + buffer.limit() >= offset + 8) {
- buffer.position(this.toBufferOffset(offset));
- } else {
- FileChannel fc = (FileChannel) this.channel;
- fc.position(offset);
- this.currentOffset = offset;
- buffer.position(0);
- buffer.limit(buffer.capacity());
- fill(buffer, fc);
- buffer.position(0);
- }
- }
+ positionBufferForOffset(buffer, offset);
int oldRecordOffset = record.end;
record.end = offset;
View
15 .../unsupported/shapefile-ng/src/test/java/org/geotools/data/shapefile/ng/ShapefileTest.java
@@ -275,6 +275,21 @@ protected void loadShapes(String resource, int expected) throws Exception {
expected, cnt);
}
+ public void testReadingSparse() throws IOException {
+ File file = TestData.file(TestCaseSupport.class, "sparse/sparse.shp");
+ ShapefileReader reader = new ShapefileReader(new ShpFiles(file), false, false, new GeometryFactory());
+ int cnt = 0;
+ try {
+ while (reader.hasNext()) {
+ reader.nextRecord().shape();
+ cnt++;
+ }
+ } finally {
+ reader.close();
+ }
+ assertEquals("Did not read all Geometries from sparse file.", 31, cnt);
+ }
+
protected void loadMemoryMapped(String resource, int expected)
throws Exception {
final URL url = TestData.url(resource);
View
BIN ...hapefile-ng/src/test/resources/org/geotools/data/shapefile/ng/test-data/sparse/sparse.dbf
Binary file not shown.
View
BIN ...hapefile-ng/src/test/resources/org/geotools/data/shapefile/ng/test-data/sparse/sparse.shp
Binary file not shown.
View
BIN ...hapefile-ng/src/test/resources/org/geotools/data/shapefile/ng/test-data/sparse/sparse.shx
Binary file not shown.

0 comments on commit bf060cf

Please sign in to comment.
Something went wrong with that request. Please try again.