/*
* Copyright (c) 2016 Vivid Solutions.
*
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* and Eclipse Distribution License v. 1.0 which accompanies this distribution.
* The Eclipse Public License is available at http://www.eclipse.org/legal/epl-v10.html
* and the Eclipse Distribution License is available at
*
* http://www.eclipse.org/org/documents/edl-v10.php.
*/
package org.locationtech.jts.io;
import java.io.IOException;
import org.locationtech.jts.geom.Coordinate;
import org.locationtech.jts.geom.CoordinateFilter;
import org.locationtech.jts.geom.CoordinateSequenceComparator;
import org.locationtech.jts.geom.Geometry;
import org.locationtech.jts.geom.GeometryFactory;
import org.locationtech.jts.geom.impl.PackedCoordinateSequenceFactory;
import org.locationtech.jts.util.GeometricShapeFactory;
import junit.framework.TestCase;
import junit.textui.TestRunner;
/**
* Tests the {@link WKBReader} and {@link WKBWriter}.
* Tests all geometries with both 2 and 3 dimensions and both byte orderings.
*/
public class WKBTest
extends TestCase
{
public static void main(String args[]) {
TestRunner.run(WKBTest.class);
}
private GeometryFactory geomFactory = new GeometryFactory();
private WKTReader rdr = new WKTReader(geomFactory);
public WKBTest(String name)
{
super(name);
}
public void testFirst()
throws IOException, ParseException
{
runWKBTest("MULTIPOINT ((0 0), (1 4), (100 200))");
}
public void testPointPCS() throws IOException, ParseException {
runWKBTestPackedCoordinate("POINT (1 2)");
}
public void testPoint() throws IOException, ParseException {
runWKBTest("POINT (1 2)");
}
public void testLineString()
throws IOException, ParseException
{
runWKBTest("LINESTRING (1 2, 10 20, 100 200)");
}
public void testPolygon()
throws IOException, ParseException
{
runWKBTest("POLYGON ((0 0, 100 0, 100 100, 0 100, 0 0))");
}
public void testPolygonWithHole()
throws IOException, ParseException
{
runWKBTest("POLYGON ((0 0, 100 0, 100 100, 0 100, 0 0), (1 1, 1 10, 10 10, 10 1, 1 1) )");
}
public void testMultiPoint()
throws IOException, ParseException
{
runWKBTest("MULTIPOINT ((0 0), (1 4), (100 200))");
}
public void testMultiLineString()
throws IOException, ParseException
{
runWKBTest("MULTILINESTRING ((0 0, 1 10), (10 10, 20 30), (123 123, 456 789))");
}
public void testMultiPolygon()
throws IOException, ParseException
{
runWKBTest("MULTIPOLYGON ( ((0 0, 100 0, 100 100, 0 100, 0 0), (1 1, 1 10, 10 10, 10 1, 1 1) ), ((200 200, 200 250, 250 250, 250 200, 200 200)) )");
}
public void testGeometryCollection()
throws IOException, ParseException
{
runWKBTest("GEOMETRYCOLLECTION ( POINT ( 1 1), LINESTRING (0 0, 10 10), POLYGON ((0 0, 100 0, 100 100, 0 100, 0 0)) )");
}
public void testNestedGeometryCollection()
throws IOException, ParseException
{
runWKBTest("GEOMETRYCOLLECTION ( POINT (20 20), GEOMETRYCOLLECTION ( POINT ( 1 1), LINESTRING (0 0, 10 10), POLYGON ((0 0, 100 0, 100 100, 0 100, 0 0)) ) )");
}
public void testLineStringEmpty()
throws IOException, ParseException
{
runWKBTest("LINESTRING EMPTY");
}
public void testBigPolygon()
throws IOException, ParseException
{
GeometricShapeFactory shapeFactory = new GeometricShapeFactory(geomFactory);
shapeFactory.setBase(new Coordinate(0,0));
shapeFactory.setSize(1000);
shapeFactory.setNumPoints(1000);
Geometry geom = shapeFactory.createRectangle();
runWKBTest(geom, 2, false);
}
public void testPolygonEmpty()
throws IOException, ParseException
{
runWKBTest("POLYGON EMPTY");
}
public void testMultiPointEmpty()
throws IOException, ParseException
{
runWKBTest("MULTIPOINT EMPTY");
}
public void testMultiLineStringEmpty()
throws IOException, ParseException
{
runWKBTest("MULTILINESTRING EMPTY");
}
public void testMultiPolygonEmpty()
throws IOException, ParseException
{
runWKBTest("MULTIPOLYGON EMPTY");
}
public void testGeometryCollectionEmpty()
throws IOException, ParseException
{
runWKBTest("GEOMETRYCOLLECTION EMPTY");
}
private void runWKBTest(String wkt) throws IOException, ParseException
{
runWKBTestCoordinateArray(wkt);
runWKBTestPackedCoordinate(wkt);
}
private void runWKBTestPackedCoordinate(String wkt) throws IOException, ParseException {
GeometryFactory geomFactory = new GeometryFactory(
new PackedCoordinateSequenceFactory(PackedCoordinateSequenceFactory.DOUBLE, 2));
WKTReader rdr = new WKTReader(geomFactory);
Geometry g = rdr.read(wkt);
// Since we are using a PCS of dim=2, only check 2-dimensional storage
runWKBTest(g, 2, true);
runWKBTest(g, 2, false);
}
private void runWKBTestCoordinateArray(String wkt) throws IOException, ParseException {
GeometryFactory geomFactory = new GeometryFactory();
WKTReader rdr = new WKTReader(geomFactory);
Geometry g = rdr.read(wkt);
// CoordinateArrays support dimension 3, so test both dimensions
runWKBTest(g, 2, true);
runWKBTest(g, 2, false);
runWKBTest(g, 3, true);
runWKBTest(g, 3, false);
}
private void runWKBTest(Geometry g, int dimension, boolean toHex)
throws IOException, ParseException
{
setZ(g);
runWKBTest(g, dimension, ByteOrderValues.LITTLE_ENDIAN, toHex);
runWKBTest(g, dimension, ByteOrderValues.BIG_ENDIAN, toHex);
}
private void runWKBTest(Geometry g, int dimension, int byteOrder, boolean toHex)
throws IOException, ParseException
{
runGeometry(g, dimension, byteOrder, toHex, 100);
runGeometry(g, dimension, byteOrder, toHex, 0);
runGeometry(g, dimension, byteOrder, toHex, 101010);
runGeometry(g, dimension, byteOrder, toHex, -1);
}
private void setZ(Geometry g)
{
g.apply(new AverageZFilter());
}
//static Comparator comp2D = new Coordinate.DimensionalComparator();
//static Comparator comp3D = new Coordinate.DimensionalComparator(3);
static CoordinateSequenceComparator comp2 = new CoordinateSequenceComparator(2);
static CoordinateSequenceComparator comp3 = new CoordinateSequenceComparator(3);
/**
* Use single WKB reader, to ensure it can be used for multiple input geometries
*/
WKBReader wkbReader = new WKBReader(geomFactory);
void runGeometry(Geometry g, int dimension, int byteOrder, boolean toHex, int srid)
throws IOException, ParseException
{
boolean includeSRID = false;
if (srid >= 0) {
includeSRID = true;
g.setSRID(srid);
}
WKBWriter wkbWriter = new WKBWriter(dimension, byteOrder, includeSRID);
byte[] wkb = wkbWriter.write(g);
String wkbHex = null;
if (toHex)
wkbHex = WKBWriter.toHex(wkb);
if (toHex)
wkb = WKBReader.hexToBytes(wkbHex);
Geometry g2 = wkbReader.read(wkb);
CoordinateSequenceComparator comp = (dimension == 2) ? comp2 : comp3;
boolean isEqual = (g.compareTo(g2, comp) == 0);
assertTrue(isEqual);
if (includeSRID) {
boolean isSRIDEqual = g.getSRID() == g2.getSRID();
assertTrue(isSRIDEqual);
}
}
}
class AverageZFilter implements CoordinateFilter
{
public void filter(Coordinate coord)
{
coord.z = (coord.x + coord.y) / 2;
}
}