fix WKBReader
This commit is contained in:
parent
1481f4b508
commit
a6994913be
@ -15,33 +15,46 @@
|
|||||||
package org.oscim.utils.wkb;
|
package org.oscim.utils.wkb;
|
||||||
|
|
||||||
import org.oscim.core.GeometryBuffer;
|
import org.oscim.core.GeometryBuffer;
|
||||||
|
import org.oscim.core.Tile;
|
||||||
|
|
||||||
public class WKBReader {
|
public class WKBReader {
|
||||||
interface Callback {
|
public interface Callback {
|
||||||
public void process(GeometryBuffer geom);
|
public void process(GeometryBuffer geom);
|
||||||
}
|
}
|
||||||
|
|
||||||
// taken from postgis-java
|
private final GeometryBuffer mGeom;
|
||||||
|
private final boolean mFlipY;
|
||||||
private GeometryBuffer mGeom;
|
|
||||||
private final double mScale = 1;
|
|
||||||
private final double mOffsetX = 0;
|
|
||||||
private final double mOffsetY = 0;
|
|
||||||
|
|
||||||
private WKBReader.Callback mCallback;
|
private WKBReader.Callback mCallback;
|
||||||
|
|
||||||
/**
|
public WKBReader(GeometryBuffer geom, boolean flipY) {
|
||||||
* Parse a binary encoded geometry.
|
mGeom = geom;
|
||||||
*
|
mFlipY = flipY;
|
||||||
* @param value
|
|
||||||
* ...
|
|
||||||
* @return ...
|
|
||||||
*/
|
|
||||||
boolean parse(byte[] value) {
|
|
||||||
return parseGeometry(valueGetterForEndian(value), 0);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean parseGeometry(ValueGetter data, int count) {
|
public void setCallback(WKBReader.Callback cb) {
|
||||||
|
mCallback = cb;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Parse a binary encoded geometry.
|
||||||
|
*/
|
||||||
|
public void parse(byte[] value) {
|
||||||
|
parseGeometry(valueGetterForEndian(value), 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Parse a hex encoded geometry.
|
||||||
|
*/
|
||||||
|
public void parse(String value) {
|
||||||
|
byte[] b = hexStringToByteArray(value);
|
||||||
|
if (b == null)
|
||||||
|
return;
|
||||||
|
|
||||||
|
parse(b);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void parseGeometry(ValueGetter data, int count) {
|
||||||
byte endian = data.getByte(); // skip and test endian flag
|
byte endian = data.getByte(); // skip and test endian flag
|
||||||
if (endian != data.endian) {
|
if (endian != data.endian) {
|
||||||
throw new IllegalArgumentException("Endian inconsistency!");
|
throw new IllegalArgumentException("Endian inconsistency!");
|
||||||
@ -55,59 +68,59 @@ public class WKBReader {
|
|||||||
boolean haveS = (typeword & 0x20000000) != 0;
|
boolean haveS = (typeword & 0x20000000) != 0;
|
||||||
|
|
||||||
// int srid = Geometry.UNKNOWN_SRID;
|
// int srid = Geometry.UNKNOWN_SRID;
|
||||||
boolean polygon = false;
|
|
||||||
if (haveS) {
|
if (haveS) {
|
||||||
// srid = Geometry.parseSRID(data.getInt());
|
// srid = Geometry.parseSRID(data.getInt());
|
||||||
data.getInt();
|
data.getInt();
|
||||||
}
|
}
|
||||||
switch (realtype) {
|
switch (realtype) {
|
||||||
case Geometry.POINT:
|
case Geometry.POINT:
|
||||||
mGeom.startPoints();
|
mGeom.startPoints();
|
||||||
parsePoint(data, haveZ, haveM);
|
parsePoint(data, haveZ, haveM);
|
||||||
break;
|
break;
|
||||||
case Geometry.LINESTRING:
|
case Geometry.LINESTRING:
|
||||||
mGeom.startLine();
|
mGeom.startLine();
|
||||||
parseLineString(data, haveZ, haveM);
|
parseLineString(data, haveZ, haveM);
|
||||||
break;
|
break;
|
||||||
case Geometry.POLYGON:
|
case Geometry.POLYGON:
|
||||||
mGeom.startPolygon();
|
mGeom.startPolygon();
|
||||||
parsePolygon(data, haveZ, haveM);
|
parsePolygon(data, haveZ, haveM);
|
||||||
polygon = true;
|
break;
|
||||||
break;
|
case Geometry.MULTIPOINT:
|
||||||
case Geometry.MULTIPOINT:
|
mGeom.startPoints();
|
||||||
mGeom.startPoints();
|
parseMultiPoint(data);
|
||||||
parseMultiPoint(data);
|
break;
|
||||||
break;
|
case Geometry.MULTILINESTRING:
|
||||||
case Geometry.MULTILINESTRING:
|
mGeom.startLine();
|
||||||
mGeom.startLine();
|
parseMultiLineString(data);
|
||||||
parseMultiLineString(data);
|
break;
|
||||||
break;
|
case Geometry.MULTIPOLYGON:
|
||||||
case Geometry.MULTIPOLYGON:
|
mGeom.startPolygon();
|
||||||
mGeom.startPolygon();
|
parseMultiPolygon(data);
|
||||||
parseMultiPolygon(data);
|
break;
|
||||||
polygon = true;
|
case Geometry.GEOMETRYCOLLECTION:
|
||||||
break;
|
parseCollection(data);
|
||||||
case Geometry.GEOMETRYCOLLECTION:
|
break;
|
||||||
parseCollection(data);
|
default:
|
||||||
break;
|
throw new IllegalArgumentException("Unknown Geometry Type: " + realtype);
|
||||||
default:
|
|
||||||
throw new IllegalArgumentException("Unknown Geometry Type: " + realtype);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (count == 0) {
|
if (count == 0) {
|
||||||
mCallback.process(mGeom);
|
mCallback.process(mGeom);
|
||||||
|
|
||||||
mGeom.clear();
|
mGeom.clear();
|
||||||
}
|
}
|
||||||
// if (srid != Geometry.UNKNOWN_SRID) {
|
// if (srid != Geometry.UNKNOWN_SRID) {
|
||||||
// result.setSrid(srid);
|
// result.setSrid(srid);
|
||||||
// }
|
// }
|
||||||
return polygon;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void parsePoint(ValueGetter data, boolean haveZ, boolean haveM) {
|
private void parsePoint(ValueGetter data, boolean haveZ, boolean haveM) {
|
||||||
|
|
||||||
float x = (float) ((data.getDouble() + mOffsetX) * mScale);
|
float x = (float) data.getDouble();
|
||||||
float y = (float) ((data.getDouble() + mOffsetY) * mScale);
|
float y = (float) data.getDouble();
|
||||||
|
if (mFlipY)
|
||||||
|
y = Tile.SIZE - y;
|
||||||
|
|
||||||
mGeom.addPoint(x, y);
|
mGeom.addPoint(x, y);
|
||||||
|
|
||||||
if (haveZ)
|
if (haveZ)
|
||||||
@ -125,12 +138,22 @@ public class WKBReader {
|
|||||||
* @param count
|
* @param count
|
||||||
* ...
|
* ...
|
||||||
*/
|
*/
|
||||||
private void parseGeometryArray(ValueGetter data, int count) {
|
private void parseGeometryArray(ValueGetter data, int count, int type) {
|
||||||
mGeom.clear();
|
mGeom.clear();
|
||||||
|
|
||||||
for (int i = 0; i < count; i++) {
|
for (int i = 0; i < count; i++) {
|
||||||
|
if (i > 0) {
|
||||||
|
if (type == Geometry.LINESTRING)
|
||||||
|
mGeom.startLine();
|
||||||
|
else if (type == Geometry.POLYGON)
|
||||||
|
mGeom.startPolygon();
|
||||||
|
else {
|
||||||
|
mCallback.process(mGeom);
|
||||||
|
mGeom.clear();
|
||||||
|
}
|
||||||
|
}
|
||||||
parseGeometry(data, count);
|
parseGeometry(data, count);
|
||||||
mGeom.index[mGeom.indexPos++] = 0;
|
// mGeom.index[++mGeom.indexPos] = -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
mCallback.process(mGeom);
|
mCallback.process(mGeom);
|
||||||
@ -138,7 +161,7 @@ public class WKBReader {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void parseMultiPoint(ValueGetter data) {
|
private void parseMultiPoint(ValueGetter data) {
|
||||||
parseGeometryArray(data, data.getInt());
|
parseGeometryArray(data, data.getInt(), Geometry.POINT);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void parseLineString(ValueGetter data, boolean haveZ, boolean haveM) {
|
private void parseLineString(ValueGetter data, boolean haveZ, boolean haveM) {
|
||||||
@ -146,8 +169,12 @@ public class WKBReader {
|
|||||||
int count = data.getInt();
|
int count = data.getInt();
|
||||||
|
|
||||||
for (int i = 0; i < count; i++) {
|
for (int i = 0; i < count; i++) {
|
||||||
float x = (float) ((data.getDouble() + mOffsetX) * mScale);
|
float x = (float) data.getDouble();
|
||||||
float y = (float) ((data.getDouble() + mOffsetY) * mScale);
|
float y = (float) data.getDouble();
|
||||||
|
|
||||||
|
if (mFlipY)
|
||||||
|
y = Tile.SIZE - y;
|
||||||
|
|
||||||
mGeom.addPoint(x, y);
|
mGeom.addPoint(x, y);
|
||||||
|
|
||||||
// ignore
|
// ignore
|
||||||
@ -166,7 +193,26 @@ public class WKBReader {
|
|||||||
if (i > 0)
|
if (i > 0)
|
||||||
mGeom.startHole();
|
mGeom.startHole();
|
||||||
|
|
||||||
parseLineString(data, haveZ, haveM);
|
|
||||||
|
int points = data.getInt();
|
||||||
|
|
||||||
|
for (int j = 0; j < points; j++) {
|
||||||
|
float x = (float) data.getDouble();
|
||||||
|
float y = (float) data.getDouble();
|
||||||
|
|
||||||
|
if (mFlipY)
|
||||||
|
y = Tile.SIZE - y;
|
||||||
|
|
||||||
|
// drop redundant closing point
|
||||||
|
if (j < points - 1)
|
||||||
|
mGeom.addPoint(x, y);
|
||||||
|
|
||||||
|
// ignore
|
||||||
|
if (haveZ)
|
||||||
|
data.getDouble();
|
||||||
|
if (haveM)
|
||||||
|
data.getDouble();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -176,7 +222,7 @@ public class WKBReader {
|
|||||||
if (count <= 0)
|
if (count <= 0)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
parseGeometryArray(data, count);
|
parseGeometryArray(data, count, Geometry.LINESTRING);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void parseMultiPolygon(ValueGetter data) {
|
private void parseMultiPolygon(ValueGetter data) {
|
||||||
@ -184,12 +230,13 @@ public class WKBReader {
|
|||||||
if (count <= 0)
|
if (count <= 0)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
parseGeometryArray(data, count);
|
parseGeometryArray(data, count, Geometry.POLYGON);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void parseCollection(ValueGetter data) {
|
private void parseCollection(ValueGetter data) {
|
||||||
int count = data.getInt();
|
int count = data.getInt();
|
||||||
parseGeometryArray(data, count);
|
|
||||||
|
parseGeometryArray(data, count, Geometry.GEOMETRYCOLLECTION);
|
||||||
|
|
||||||
mCallback.process(mGeom);
|
mCallback.process(mGeom);
|
||||||
mGeom.clear();
|
mGeom.clear();
|
||||||
@ -205,4 +252,24 @@ public class WKBReader {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Converting a string of hex character to bytes
|
||||||
|
*
|
||||||
|
* from http://stackoverflow.com/questions/140131/convert-a-string-
|
||||||
|
* representation-of-a-hex-dump-to-a-byte-array-using-java
|
||||||
|
*/
|
||||||
|
public static byte[] hexStringToByteArray(String s) {
|
||||||
|
|
||||||
|
int len = s.length();
|
||||||
|
if (len < 2)
|
||||||
|
return null;
|
||||||
|
|
||||||
|
byte[] data = new byte[len / 2];
|
||||||
|
for (int i = 0; i < len; i += 2) {
|
||||||
|
data[i / 2] = (byte) ((Character.digit(s.charAt(i), 16) << 4)
|
||||||
|
+ Character.digit(s.charAt(i + 1), 16));
|
||||||
|
}
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user