Improve code / xml formatting, closes #54

This commit is contained in:
Emux
2016-07-09 19:45:22 +03:00
parent 7919d0ab9c
commit e793e8851b
458 changed files with 58405 additions and 63062 deletions

View File

@@ -23,35 +23,35 @@ import java.util.Collection;
*/
public class OsmData {
private final Collection<Bound> bounds;
private final Collection<OsmNode> nodes;
private final Collection<OsmWay> ways;
private final Collection<OsmRelation> relations;
private final Collection<Bound> bounds;
private final Collection<OsmNode> nodes;
private final Collection<OsmWay> ways;
private final Collection<OsmRelation> relations;
public OsmData(Collection<Bound> bounds, Collection<OsmNode> nodes,
Collection<OsmWay> ways, Collection<OsmRelation> relations) {
public OsmData(Collection<Bound> bounds, Collection<OsmNode> nodes,
Collection<OsmWay> ways, Collection<OsmRelation> relations) {
this.bounds = bounds;
this.nodes = nodes;
this.ways = ways;
this.relations = relations;
this.bounds = bounds;
this.nodes = nodes;
this.ways = ways;
this.relations = relations;
}
}
public Collection<OsmNode> getNodes() {
return nodes;
}
public Collection<OsmNode> getNodes() {
return nodes;
}
public Collection<OsmWay> getWays() {
return ways;
}
public Collection<OsmWay> getWays() {
return ways;
}
public Collection<OsmRelation> getRelations() {
return relations;
}
public Collection<OsmRelation> getRelations() {
return relations;
}
public Collection<Bound> getBounds() {
return bounds;
}
public Collection<Bound> getBounds() {
return bounds;
}
}

View File

@@ -16,50 +16,50 @@
*/
package org.oscim.core.osm;
import org.oscim.core.TagSet;
import com.vividsolutions.jts.geom.Geometry;
import org.oscim.core.TagSet;
public abstract class OsmElement {
public final TagSet tags;
public final long id;
public final TagSet tags;
public final long id;
public OsmElement(TagSet tags, long id) {
assert tags != null;
this.tags = tags;
this.id = id;
}
public OsmElement(TagSet tags, long id) {
assert tags != null;
this.tags = tags;
this.id = id;
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + (int) (id ^ (id >>> 32));
return result;
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + (int) (id ^ (id >>> 32));
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
OsmElement other = (OsmElement) obj;
if (id != other.id)
return false;
return true;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
OsmElement other = (OsmElement) obj;
if (id != other.id)
return false;
return true;
}
/**
* returns the id, plus an one-letter prefix for the element type
*/
@Override
public String toString() {
return "?" + id;
}
/**
* returns the id, plus an one-letter prefix for the element type
*/
@Override
public String toString() {
return "?" + id;
}
public abstract Geometry toJts();
public abstract Geometry toJts();
}

View File

@@ -17,24 +17,24 @@
package org.oscim.core.osm;
public class OsmMember {
public enum MemberType {
NODE,
WAY,
RELATIOM
}
public enum MemberType {
NODE,
WAY,
RELATIOM
}
public final String role;
public final OsmElement member;
public final String role;
public final OsmElement member;
public OsmMember(String role, OsmElement member) {
assert role != null && member != null;
this.role = role;
this.member = member;
}
public OsmMember(String role, OsmElement member) {
assert role != null && member != null;
this.role = role;
this.member = member;
}
@Override
public String toString() {
return role + ":" + member;
}
@Override
public String toString() {
return role + ":" + member;
}
}

View File

@@ -16,28 +16,28 @@
*/
package org.oscim.core.osm;
import org.oscim.core.TagSet;
import com.vividsolutions.jts.geom.Geometry;
import org.oscim.core.TagSet;
public class OsmNode extends OsmElement {
public final double lat;
public final double lon;
public final double lat;
public final double lon;
public OsmNode(double lat, double lon, TagSet tags, long id) {
super(tags, id);
this.lat = lat;
this.lon = lon;
}
public OsmNode(double lat, double lon, TagSet tags, long id) {
super(tags, id);
this.lat = lat;
this.lon = lon;
}
@Override
public String toString() {
return "n" + id;
}
@Override
public String toString() {
return "n" + id;
}
@Override
public Geometry toJts() {
return null; //bnew Point(new Coordinate(lat, lon), null);
}
@Override
public Geometry toJts() {
return null; //bnew Point(new Coordinate(lat, lon), null);
}
}

View File

@@ -16,32 +16,32 @@
*/
package org.oscim.core.osm;
import java.util.ArrayList;
import java.util.List;
import com.vividsolutions.jts.geom.Geometry;
import org.oscim.core.TagSet;
import com.vividsolutions.jts.geom.Geometry;
import java.util.ArrayList;
import java.util.List;
public class OsmRelation extends OsmElement {
public final List<OsmMember> relationMembers;
public final List<OsmMember> relationMembers;
// content added after constructor call
// content added after constructor call
public OsmRelation(TagSet tags, long id, int initialMemberSize) {
super(tags, id);
this.relationMembers =
new ArrayList<OsmMember>(initialMemberSize);
}
public OsmRelation(TagSet tags, long id, int initialMemberSize) {
super(tags, id);
this.relationMembers =
new ArrayList<OsmMember>(initialMemberSize);
}
@Override
public String toString() {
return "r" + id;
}
@Override
public String toString() {
return "r" + id;
}
@Override
public Geometry toJts() {
return null;
}
@Override
public Geometry toJts() {
return null;
}
}

View File

@@ -16,43 +16,43 @@
*/
package org.oscim.core.osm;
import java.util.List;
import org.oscim.core.TagSet;
import com.vividsolutions.jts.geom.CoordinateSequence;
import com.vividsolutions.jts.geom.Geometry;
import com.vividsolutions.jts.geom.LineString;
import com.vividsolutions.jts.geom.impl.PackedCoordinateSequenceFactory;
import org.oscim.core.TagSet;
import java.util.List;
public class OsmWay extends OsmElement {
public final List<OsmNode> nodes;
public final List<OsmNode> nodes;
public OsmWay(TagSet tags, long id, List<OsmNode> nodes) {
super(tags, id);
this.nodes = nodes;
}
public OsmWay(TagSet tags, long id, List<OsmNode> nodes) {
super(tags, id);
this.nodes = nodes;
}
public boolean isClosed() {
return nodes.size() > 0 &&
nodes.get(0).equals(nodes.get(nodes.size() - 1));
}
public boolean isClosed() {
return nodes.size() > 0 &&
nodes.get(0).equals(nodes.get(nodes.size() - 1));
}
@Override
public String toString() {
return "w" + id;
}
@Override
public String toString() {
return "w" + id;
}
public Geometry toJts() {
double[] coords = new double[nodes.size() * 2];
int i = 0;
for (OsmNode n : nodes) {
coords[i++] = n.lon;
coords[i++] = n.lat;
}
public Geometry toJts() {
double[] coords = new double[nodes.size() * 2];
int i = 0;
for (OsmNode n : nodes) {
coords[i++] = n.lon;
coords[i++] = n.lat;
}
CoordinateSequence c = PackedCoordinateSequenceFactory.DOUBLE_FACTORY.create(coords, 2);
return new LineString(c, null);
}
CoordinateSequence c = PackedCoordinateSequenceFactory.DOUBLE_FACTORY.create(coords, 2);
return new LineString(c, null);
}
}

View File

@@ -7,13 +7,13 @@ import org.oscim.map.Map;
public class OsmVectorLayer extends AbstractVectorLayer<OsmElement> {
public OsmVectorLayer(Map map) {
super(map);
}
public OsmVectorLayer(Map map) {
super(map);
}
@Override
protected void processFeatures(Task t, Box b) {
@Override
protected void processFeatures(Task t, Box b) {
}
}
}

View File

@@ -16,6 +16,25 @@
*/
package org.oscim.tiling.source.geojson;
import com.fasterxml.jackson.core.JsonFactory;
import com.fasterxml.jackson.core.JsonParseException;
import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.core.JsonToken;
import org.oscim.core.GeometryBuffer.GeometryType;
import org.oscim.core.MapElement;
import org.oscim.core.Tile;
import org.oscim.tiling.ITileDataSink;
import org.oscim.tiling.source.ITileDecoder;
import org.oscim.utils.ArrayUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.LinkedHashMap;
import static com.fasterxml.jackson.core.JsonToken.END_ARRAY;
import static com.fasterxml.jackson.core.JsonToken.END_OBJECT;
import static com.fasterxml.jackson.core.JsonToken.FIELD_NAME;
@@ -27,324 +46,304 @@ import static com.fasterxml.jackson.core.JsonToken.VALUE_STRING;
import static org.oscim.core.MercatorProjection.latitudeToY;
import static org.oscim.core.MercatorProjection.longitudeToX;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.LinkedHashMap;
import org.oscim.core.GeometryBuffer.GeometryType;
import org.oscim.core.MapElement;
import org.oscim.core.Tile;
import org.oscim.tiling.ITileDataSink;
import org.oscim.tiling.source.ITileDecoder;
import org.oscim.utils.ArrayUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.fasterxml.jackson.core.JsonFactory;
import com.fasterxml.jackson.core.JsonParseException;
import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.core.JsonToken;
public class GeoJsonTileDecoder implements ITileDecoder {
static final Logger log = LoggerFactory.getLogger(GeoJsonTileDecoder.class);
static final Logger log = LoggerFactory.getLogger(GeoJsonTileDecoder.class);
private final MapElement mMapElement;
private final GeoJsonTileSource mTileSource;
private final LinkedHashMap<String, Object> mTagMap;
private final JsonFactory mJsonFactory;
private final MapElement mMapElement;
private final GeoJsonTileSource mTileSource;
private final LinkedHashMap<String, Object> mTagMap;
private final JsonFactory mJsonFactory;
private final static char[] FIELD_FEATURES = "features".toCharArray();
private final static char[] FIELD_GEOMETRY = "geometry".toCharArray();
private final static char[] FIELD_PROPERTIES = "properties".toCharArray();
private final static char[] FIELD_COORDINATES = "coordinates".toCharArray();
private final static char[] FIELD_TYPE = "type".toCharArray();
private final static char[] FIELD_FEATURES = "features".toCharArray();
private final static char[] FIELD_GEOMETRY = "geometry".toCharArray();
private final static char[] FIELD_PROPERTIES = "properties".toCharArray();
private final static char[] FIELD_COORDINATES = "coordinates".toCharArray();
private final static char[] FIELD_TYPE = "type".toCharArray();
private final static char[] LINETRING = "LineString".toCharArray();
private final static char[] POLYGON = "Polygon".toCharArray();
private final static char[] POINT = "Point".toCharArray();
private final static char[] MULTI_LINESTRING = "MultiLineString".toCharArray();
private final static char[] MULTI_POLYGON = "MultiPolygon".toCharArray();
private final static char[] MULTI_POINT = "MultiPoint".toCharArray();
private final static char[] LINETRING = "LineString".toCharArray();
private final static char[] POLYGON = "Polygon".toCharArray();
private final static char[] POINT = "Point".toCharArray();
private final static char[] MULTI_LINESTRING = "MultiLineString".toCharArray();
private final static char[] MULTI_POLYGON = "MultiPolygon".toCharArray();
private final static char[] MULTI_POINT = "MultiPoint".toCharArray();
private ITileDataSink mTileDataSink;
private ITileDataSink mTileDataSink;
private double mTileY, mTileX, mTileScale;
private double mTileY, mTileX, mTileScale;
public GeoJsonTileDecoder(GeoJsonTileSource tileSource) {
mTileSource = tileSource;
mTagMap = new LinkedHashMap<String, Object>();
mJsonFactory = new JsonFactory();
public GeoJsonTileDecoder(GeoJsonTileSource tileSource) {
mTileSource = tileSource;
mTagMap = new LinkedHashMap<String, Object>();
mJsonFactory = new JsonFactory();
mMapElement = new MapElement();
mMapElement.layer = 5;
}
mMapElement = new MapElement();
mMapElement.layer = 5;
}
@Override
public boolean decode(Tile tile, ITileDataSink sink, InputStream is) throws IOException {
mTileDataSink = sink;
mTileScale = 1 << tile.zoomLevel;
mTileX = tile.tileX / mTileScale;
mTileY = tile.tileY / mTileScale;
mTileScale *= Tile.SIZE;
@Override
public boolean decode(Tile tile, ITileDataSink sink, InputStream is) throws IOException {
mTileDataSink = sink;
mTileScale = 1 << tile.zoomLevel;
mTileX = tile.tileX / mTileScale;
mTileY = tile.tileY / mTileScale;
mTileScale *= Tile.SIZE;
JsonParser jp = mJsonFactory.createParser(new InputStreamReader(is));
JsonParser jp = mJsonFactory.createParser(new InputStreamReader(is));
for (JsonToken t; (t = jp.nextToken()) != null;) {
if (t == FIELD_NAME) {
if (match(jp, FIELD_FEATURES)) {
if (jp.nextToken() != START_ARRAY)
continue;
for (JsonToken t; (t = jp.nextToken()) != null; ) {
if (t == FIELD_NAME) {
if (match(jp, FIELD_FEATURES)) {
if (jp.nextToken() != START_ARRAY)
continue;
while ((t = jp.nextToken()) != null) {
if (t == START_OBJECT)
parseFeature(jp);
while ((t = jp.nextToken()) != null) {
if (t == START_OBJECT)
parseFeature(jp);
if (t == END_ARRAY)
break;
}
}
}
}
return true;
}
if (t == END_ARRAY)
break;
}
}
}
}
return true;
}
private void parseFeature(JsonParser jp)
throws JsonParseException, IOException {
private void parseFeature(JsonParser jp)
throws JsonParseException, IOException {
mMapElement.clear();
mMapElement.tags.clear();
mTagMap.clear();
mMapElement.clear();
mMapElement.tags.clear();
mTagMap.clear();
for (JsonToken t; (t = jp.nextToken()) != null;) {
if (t == FIELD_NAME) {
if (match(jp, FIELD_GEOMETRY)) {
if (jp.nextToken() == START_OBJECT)
parseGeometry(jp);
}
for (JsonToken t; (t = jp.nextToken()) != null; ) {
if (t == FIELD_NAME) {
if (match(jp, FIELD_GEOMETRY)) {
if (jp.nextToken() == START_OBJECT)
parseGeometry(jp);
}
if (match(jp, FIELD_PROPERTIES)) {
if (jp.nextToken() == START_OBJECT)
parseProperties(jp);
}
continue;
}
if (t == END_OBJECT)
break;
}
if (match(jp, FIELD_PROPERTIES)) {
if (jp.nextToken() == START_OBJECT)
parseProperties(jp);
}
continue;
}
if (t == END_OBJECT)
break;
}
//add tag information
mTileSource.decodeTags(mMapElement, mTagMap);
if (mMapElement.tags.numTags == 0)
return;
//add tag information
mTileSource.decodeTags(mMapElement, mTagMap);
if (mMapElement.tags.numTags == 0)
return;
mTileSource.postGeomHook(mMapElement);
mTileSource.postGeomHook(mMapElement);
if (mMapElement.type == GeometryType.NONE)
return;
if (mMapElement.type == GeometryType.NONE)
return;
//process this element
mTileDataSink.process(mMapElement);
}
//process this element
mTileDataSink.process(mMapElement);
}
private void parseProperties(JsonParser jp)
throws JsonParseException, IOException {
for (JsonToken t; (t = jp.nextToken()) != null;) {
if (t == FIELD_NAME) {
String text = jp.getCurrentName();
private void parseProperties(JsonParser jp)
throws JsonParseException, IOException {
for (JsonToken t; (t = jp.nextToken()) != null; ) {
if (t == FIELD_NAME) {
String text = jp.getCurrentName();
t = jp.nextToken();
if (t == VALUE_STRING) {
mTagMap.put(text, jp.getText());
} else if (t == VALUE_NUMBER_INT) {
mTagMap.put(text, jp.getNumberValue());
}
continue;
}
if (t == END_OBJECT)
break;
}
}
t = jp.nextToken();
if (t == VALUE_STRING) {
mTagMap.put(text, jp.getText());
} else if (t == VALUE_NUMBER_INT) {
mTagMap.put(text, jp.getNumberValue());
}
continue;
}
if (t == END_OBJECT)
break;
}
}
private void parseGeometry(JsonParser jp)
throws JsonParseException, IOException {
private void parseGeometry(JsonParser jp)
throws JsonParseException, IOException {
boolean multi = false;
GeometryType type = GeometryType.NONE;
boolean multi = false;
GeometryType type = GeometryType.NONE;
for (JsonToken t; (t = jp.nextToken()) != null;) {
if (t == FIELD_NAME) {
if (match(jp, FIELD_COORDINATES)) {
if (jp.nextToken() != START_ARRAY)
continue;
if (multi) {
parseMulti(jp, type);
} else {
if (type == GeometryType.POLY)
parsePolygon(jp);
for (JsonToken t; (t = jp.nextToken()) != null; ) {
if (t == FIELD_NAME) {
if (match(jp, FIELD_COORDINATES)) {
if (jp.nextToken() != START_ARRAY)
continue;
if (multi) {
parseMulti(jp, type);
} else {
if (type == GeometryType.POLY)
parsePolygon(jp);
if (type == GeometryType.LINE)
parseLineString(jp);
if (type == GeometryType.LINE)
parseLineString(jp);
if (type == GeometryType.POINT)
parseCoordinate(jp);
if (type == GeometryType.POINT)
parseCoordinate(jp);
}
} else if (match(jp, FIELD_TYPE)) {
multi = false;
}
} else if (match(jp, FIELD_TYPE)) {
multi = false;
jp.nextToken();
jp.nextToken();
if (match(jp, LINETRING))
type = GeometryType.LINE;
else if (match(jp, POLYGON))
type = GeometryType.POLY;
else if (match(jp, POINT))
type = GeometryType.POINT;
else if (match(jp, MULTI_LINESTRING)) {
type = GeometryType.LINE;
multi = true;
}
else if (match(jp, MULTI_POLYGON)) {
type = GeometryType.POLY;
multi = true;
}
else if (match(jp, MULTI_POINT)) {
type = GeometryType.POINT;
multi = true;
}
if (match(jp, LINETRING))
type = GeometryType.LINE;
else if (match(jp, POLYGON))
type = GeometryType.POLY;
else if (match(jp, POINT))
type = GeometryType.POINT;
else if (match(jp, MULTI_LINESTRING)) {
type = GeometryType.LINE;
multi = true;
} else if (match(jp, MULTI_POLYGON)) {
type = GeometryType.POLY;
multi = true;
} else if (match(jp, MULTI_POINT)) {
type = GeometryType.POINT;
multi = true;
}
if (type == GeometryType.POINT)
mMapElement.startPoints();
}
continue;
}
if (t == END_OBJECT)
break;
}
}
if (type == GeometryType.POINT)
mMapElement.startPoints();
}
continue;
}
if (t == END_OBJECT)
break;
}
}
private void parseMulti(JsonParser jp, GeometryType type)
throws JsonParseException, IOException {
private void parseMulti(JsonParser jp, GeometryType type)
throws JsonParseException, IOException {
for (JsonToken t; (t = jp.nextToken()) != null;) {
if (t == END_ARRAY)
break;
for (JsonToken t; (t = jp.nextToken()) != null; ) {
if (t == END_ARRAY)
break;
if (t == START_ARRAY) {
if (type == GeometryType.POLY)
parsePolygon(jp);
if (t == START_ARRAY) {
if (type == GeometryType.POLY)
parsePolygon(jp);
else if (type == GeometryType.LINE)
parseLineString(jp);
else if (type == GeometryType.LINE)
parseLineString(jp);
else if (type == GeometryType.POINT)
parseCoordinate(jp);;
else if (type == GeometryType.POINT)
parseCoordinate(jp);
;
} else {
//....
}
}
}
} else {
//....
}
}
}
private void parsePolygon(JsonParser jp)
throws JsonParseException, IOException {
int ring = 0;
private void parsePolygon(JsonParser jp)
throws JsonParseException, IOException {
int ring = 0;
for (JsonToken t; (t = jp.nextToken()) != null;) {
if (t == START_ARRAY) {
if (ring == 0)
mMapElement.startPolygon();
else
mMapElement.startHole();
for (JsonToken t; (t = jp.nextToken()) != null; ) {
if (t == START_ARRAY) {
if (ring == 0)
mMapElement.startPolygon();
else
mMapElement.startHole();
ring++;
parseCoordSequence(jp);
removeLastPoint();
continue;
}
ring++;
parseCoordSequence(jp);
removeLastPoint();
continue;
}
if (t == END_ARRAY)
break;
}
}
if (t == END_ARRAY)
break;
}
}
private void removeLastPoint() {
mMapElement.pointPos -= 2;
mMapElement.index[mMapElement.indexPos] -= 2;
}
private void removeLastPoint() {
mMapElement.pointPos -= 2;
mMapElement.index[mMapElement.indexPos] -= 2;
}
private void parseLineString(JsonParser jp)
throws JsonParseException, IOException {
mMapElement.startLine();
parseCoordSequence(jp);
}
private void parseLineString(JsonParser jp)
throws JsonParseException, IOException {
mMapElement.startLine();
parseCoordSequence(jp);
}
private void parseCoordSequence(JsonParser jp)
throws JsonParseException, IOException {
private void parseCoordSequence(JsonParser jp)
throws JsonParseException, IOException {
for (JsonToken t; (t = jp.nextToken()) != null;) {
for (JsonToken t; (t = jp.nextToken()) != null; ) {
if (t == START_ARRAY) {
parseCoordinate(jp);
continue;
}
if (t == START_ARRAY) {
parseCoordinate(jp);
continue;
}
if (t == END_ARRAY)
break;
if (t == END_ARRAY)
break;
}
}
}
}
private void parseCoordinate(JsonParser jp)
throws JsonParseException, IOException {
int pos = 0;
double x = 0, y = 0; //, z = 0;
private void parseCoordinate(JsonParser jp)
throws JsonParseException, IOException {
int pos = 0;
double x = 0, y = 0; //, z = 0;
for (JsonToken t; (t = jp.nextToken()) != null;) {
if (t == VALUE_NUMBER_FLOAT || t == VALUE_NUMBER_INT) {
for (JsonToken t; (t = jp.nextToken()) != null; ) {
if (t == VALUE_NUMBER_FLOAT || t == VALUE_NUMBER_INT) {
// avoid String allocation (by getDouble...)
char[] val = jp.getTextCharacters();
int offset = jp.getTextOffset();
int length = jp.getTextLength();
double c = ArrayUtils.parseNumber(val, offset, offset + length);
// avoid String allocation (by getDouble...)
char[] val = jp.getTextCharacters();
int offset = jp.getTextOffset();
int length = jp.getTextLength();
double c = ArrayUtils.parseNumber(val, offset, offset + length);
if (pos == 0)
x = c;
if (pos == 1)
y = c;
//if (pos == 2)
//z = c;
if (pos == 0)
x = c;
if (pos == 1)
y = c;
//if (pos == 2)
//z = c;
pos++;
continue;
}
pos++;
continue;
}
if (t == END_ARRAY)
break;
}
if (t == END_ARRAY)
break;
}
mMapElement.addPoint((float) ((longitudeToX(x) - mTileX) * mTileScale),
(float) ((latitudeToY(y) - mTileY) * mTileScale));
mMapElement.addPoint((float) ((longitudeToX(x) - mTileX) * mTileScale),
(float) ((latitudeToY(y) - mTileY) * mTileScale));
}
}
private final static boolean match(JsonParser jp, char[] fieldName)
throws JsonParseException, IOException {
private final static boolean match(JsonParser jp, char[] fieldName)
throws JsonParseException, IOException {
int length = jp.getTextLength();
if (length != fieldName.length)
return false;
int length = jp.getTextLength();
if (length != fieldName.length)
return false;
char[] val = jp.getTextCharacters();
int offset = jp.getTextOffset();
char[] val = jp.getTextCharacters();
int offset = jp.getTextOffset();
for (int i = 0; i < length; i++) {
if (fieldName[i] != val[i + offset])
return false;
}
for (int i = 0; i < length; i++) {
if (fieldName[i] != val[i + offset])
return false;
}
return true;
}
return true;
}
}

View File

@@ -16,56 +16,60 @@
*/
package org.oscim.tiling.source.geojson;
import java.util.HashMap;
import java.util.Map;
import org.oscim.core.MapElement;
import org.oscim.core.Tag;
import org.oscim.tiling.ITileDataSource;
import org.oscim.tiling.source.UrlTileDataSource;
import org.oscim.tiling.source.UrlTileSource;
import java.util.HashMap;
import java.util.Map;
public abstract class GeoJsonTileSource extends UrlTileSource {
public GeoJsonTileSource(String url) {
super(url, "/{Z}/{X}/{Y}.json");
Map<String, String> opt = new HashMap<String, String>();
opt.put("Accept-Encoding", "gzip");
setHttpRequestHeaders(opt);
}
public GeoJsonTileSource(String url) {
super(url, "/{Z}/{X}/{Y}.json");
Map<String, String> opt = new HashMap<String, String>();
opt.put("Accept-Encoding", "gzip");
setHttpRequestHeaders(opt);
}
public GeoJsonTileSource(String url, int zoomMin, int zoomMax) {
super(url, "/{Z}/{X}/{Y}.json", zoomMin, zoomMax);
Map<String, String> opt = new HashMap<String, String>();
opt.put("Accept-Encoding", "gzip");
setHttpRequestHeaders(opt);
}
public GeoJsonTileSource(String url, int zoomMin, int zoomMax) {
super(url, "/{Z}/{X}/{Y}.json", zoomMin, zoomMax);
Map<String, String> opt = new HashMap<String, String>();
opt.put("Accept-Encoding", "gzip");
setHttpRequestHeaders(opt);
}
@Override
public ITileDataSource getDataSource() {
@Override
public ITileDataSource getDataSource() {
return new UrlTileDataSource(this, new GeoJsonTileDecoder(this), getHttpEngine());
}
return new UrlTileDataSource(this, new GeoJsonTileDecoder(this), getHttpEngine());
}
public Tag getFeatureTag() {
return null;
}
public Tag getFeatureTag() {
return null;
}
/** allow overriding tag handling */
public abstract void decodeTags(MapElement mapElement, Map<String, Object> properties);
/**
* allow overriding tag handling
*/
public abstract void decodeTags(MapElement mapElement, Map<String, Object> properties);
public Tag rewriteTag(String key, Object value) {
public Tag rewriteTag(String key, Object value) {
if (value == null)
return null;
if (value == null)
return null;
String val = (value instanceof String) ? (String) value : String.valueOf(value);
String val = (value instanceof String) ? (String) value : String.valueOf(value);
return new Tag(key, val);
}
return new Tag(key, val);
}
/** modify mapElement before process() */
public void postGeomHook(MapElement mapElement) {
/**
* modify mapElement before process()
*/
public void postGeomHook(MapElement mapElement) {
}
}
}

View File

@@ -16,23 +16,23 @@
*/
package org.oscim.tiling.source.geojson;
import java.util.Map;
import org.oscim.core.MapElement;
import org.oscim.core.Tag;
import java.util.Map;
public class OsmBuildingJsonTileSource extends GeoJsonTileSource {
public OsmBuildingJsonTileSource() {
super("http://tile.openstreetmap.us/vectiles-buildings");
}
public OsmBuildingJsonTileSource() {
super("http://tile.openstreetmap.us/vectiles-buildings");
}
Tag mTagBuilding = new Tag("building", "yes");
Tag mTagBuilding = new Tag("building", "yes");
@Override
public void decodeTags(MapElement mapElement, Map<String, Object> properties) {
@Override
public void decodeTags(MapElement mapElement, Map<String, Object> properties) {
mapElement.tags.add(mTagBuilding);
mapElement.tags.add(mTagBuilding);
}
}
}

View File

@@ -16,112 +16,112 @@
*/
package org.oscim.tiling.source.geojson;
import java.util.LinkedHashMap;
import java.util.Map;
import org.oscim.core.GeometryBuffer.GeometryType;
import org.oscim.core.MapElement;
import org.oscim.core.Tag;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.LinkedHashMap;
import java.util.Map;
public class OsmLanduseJsonTileSource extends GeoJsonTileSource {
static final Logger log = LoggerFactory.getLogger(OsmLanduseJsonTileSource.class);
static final Logger log = LoggerFactory.getLogger(OsmLanduseJsonTileSource.class);
public OsmLanduseJsonTileSource() {
super("http://tile.openstreetmap.us/vectiles-land-usages");
}
public OsmLanduseJsonTileSource() {
super("http://tile.openstreetmap.us/vectiles-land-usages");
}
private static LinkedHashMap<String, Tag> mappings =
new LinkedHashMap<String, Tag>();
private static LinkedHashMap<String, Tag> mappings =
new LinkedHashMap<String, Tag>();
static void addMapping(String key, String val) {
mappings.put(val, new Tag(key, val));
}
static void addMapping(String key, String val) {
mappings.put(val, new Tag(key, val));
}
static {
addMapping("landuse", "residential");
addMapping("landuse", "commercial");
addMapping("landuse", "retail");
addMapping("landuse", "railway");
addMapping("landuse", "grass");
addMapping("landuse", "meadow");
addMapping("landuse", "forest");
addMapping("landuse", "farm");
addMapping("landuse", "allotments");
addMapping("landuse", "cemetery");
addMapping("landuse", "farmyard");
addMapping("landuse", "farmland");
addMapping("landuse", "quarry");
addMapping("landuse", "military");
addMapping("landuse", "industrial");
addMapping("landuse", "greenfield");
addMapping("landuse", "village_green");
addMapping("landuse", "recreation_ground");
addMapping("landuse", "conservation");
addMapping("landuse", "landfill");
addMapping("landuse", "construction");
static {
addMapping("landuse", "residential");
addMapping("landuse", "commercial");
addMapping("landuse", "retail");
addMapping("landuse", "railway");
addMapping("landuse", "grass");
addMapping("landuse", "meadow");
addMapping("landuse", "forest");
addMapping("landuse", "farm");
addMapping("landuse", "allotments");
addMapping("landuse", "cemetery");
addMapping("landuse", "farmyard");
addMapping("landuse", "farmland");
addMapping("landuse", "quarry");
addMapping("landuse", "military");
addMapping("landuse", "industrial");
addMapping("landuse", "greenfield");
addMapping("landuse", "village_green");
addMapping("landuse", "recreation_ground");
addMapping("landuse", "conservation");
addMapping("landuse", "landfill");
addMapping("landuse", "construction");
addMapping("leisure", "common");
addMapping("leisure", "park");
addMapping("leisure", "pitch");
addMapping("leisure", "garden");
addMapping("leisure", "sports_centre");
addMapping("leisure", "playground");
addMapping("leisure", "nature_reserve");
addMapping("leisure", "golf_course");
addMapping("leisure", "stadium");
addMapping("leisure", "common");
addMapping("leisure", "park");
addMapping("leisure", "pitch");
addMapping("leisure", "garden");
addMapping("leisure", "sports_centre");
addMapping("leisure", "playground");
addMapping("leisure", "nature_reserve");
addMapping("leisure", "golf_course");
addMapping("leisure", "stadium");
addMapping("amenity", "hospital");
addMapping("amenity", "cinema");
addMapping("amenity", "school");
addMapping("amenity", "college");
addMapping("amenity", "university");
addMapping("amenity", "theatre");
addMapping("amenity", "library");
addMapping("amenity", "parking");
addMapping("amenity", "place_of_worship");
addMapping("amenity", "hospital");
addMapping("amenity", "cinema");
addMapping("amenity", "school");
addMapping("amenity", "college");
addMapping("amenity", "university");
addMapping("amenity", "theatre");
addMapping("amenity", "library");
addMapping("amenity", "parking");
addMapping("amenity", "place_of_worship");
addMapping("highway", "pedestrian");
addMapping("highway", "footway");
addMapping("highway", "service");
addMapping("highway", "street");
addMapping("highway", "pedestrian");
addMapping("highway", "footway");
addMapping("highway", "service");
addMapping("highway", "street");
addMapping("natural", "scrub");
addMapping("natural", "wood");
addMapping("natural", "scrub");
addMapping("natural", "wood");
mappings.put("urban area", new Tag("landuse", "urban"));
mappings.put("park or protected land", new Tag("leisure", "park"));
}
mappings.put("urban area", new Tag("landuse", "urban"));
mappings.put("park or protected land", new Tag("leisure", "park"));
}
private final static Tag mTagArea = new Tag("area", "yes");
private final static Tag mTagArea = new Tag("area", "yes");
@Override
public void decodeTags(MapElement mapElement, Map<String, Object> properties) {
@Override
public void decodeTags(MapElement mapElement, Map<String, Object> properties) {
for (Map.Entry<String, Object> entry : properties.entrySet()) {
String key = entry.getKey();
for (Map.Entry<String, Object> entry : properties.entrySet()) {
String key = entry.getKey();
if (!"kind".equals(key))
continue;
if (!"kind".equals(key))
continue;
String value = (String) entry.getValue();
String value = (String) entry.getValue();
Tag tag = mappings.get(value);
if (tag == null) {
System.out.println("unmatched " + value);
} else {
mapElement.tags.add(tag);
}
break;
}
}
Tag tag = mappings.get(value);
if (tag == null) {
System.out.println("unmatched " + value);
} else {
mapElement.tags.add(tag);
}
break;
}
}
@Override
public void postGeomHook(MapElement mapElement) {
//if (mapElement.type != GeometryType.POLY) {
mapElement.type = GeometryType.POLY;
mapElement.tags.add(mTagArea);
//}
}
@Override
public void postGeomHook(MapElement mapElement) {
//if (mapElement.type != GeometryType.POLY) {
mapElement.type = GeometryType.POLY;
mapElement.tags.add(mTagArea);
//}
}
}

View File

@@ -25,35 +25,34 @@ import java.util.Map;
public class OsmRoadLabelJsonTileSource extends GeoJsonTileSource {
static final Logger log = LoggerFactory.getLogger(OsmRoadLabelJsonTileSource.class);
static final Logger log = LoggerFactory.getLogger(OsmRoadLabelJsonTileSource.class);
public OsmRoadLabelJsonTileSource() {
super("http://tile.openstreetmap.us/vectiles-skeletron");
}
public OsmRoadLabelJsonTileSource() {
super("http://tile.openstreetmap.us/vectiles-skeletron");
}
@Override
public void decodeTags(MapElement mapElement, Map<String, Object> properties) {
String highway = null;
@Override
public void decodeTags(MapElement mapElement, Map<String, Object> properties) {
String highway = null;
for (Map.Entry<String, Object> entry : properties.entrySet()) {
String key = entry.getKey();
Object value = entry.getValue();
//log.debug(key + " : " + String.valueOf(value));
for (Map.Entry<String, Object> entry : properties.entrySet()) {
String key = entry.getKey();
Object value = entry.getValue();
//log.debug(key + " : " + String.valueOf(value));
if (value == null)
continue;
if (value == null)
continue;
if ("highway".equals(key) && value instanceof String) {
highway = (String) entry.getValue();
}
else if ("name".equals(key) && value instanceof String) {
mapElement.tags.add(new Tag("name", (String) value));
}
}
if ("highway".equals(key) && value instanceof String) {
highway = (String) entry.getValue();
} else if ("name".equals(key) && value instanceof String) {
mapElement.tags.add(new Tag("name", (String) value));
}
}
if (highway == null)
return;
if (highway == null)
return;
mapElement.tags.add(new Tag("highway", highway));
}
mapElement.tags.add(new Tag("highway", highway));
}
}

View File

@@ -16,83 +16,78 @@
*/
package org.oscim.tiling.source.geojson;
import java.util.Map;
import org.oscim.core.MapElement;
import org.oscim.core.Tag;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.Map;
public class OsmRoadLineJsonTileSource extends GeoJsonTileSource {
static final Logger log = LoggerFactory.getLogger(OsmRoadLineJsonTileSource.class);
static final Logger log = LoggerFactory.getLogger(OsmRoadLineJsonTileSource.class);
Tag mTagTunnel = new Tag("tunnel", "yes");
Tag mTagBridge = new Tag("bridge", "yes");
Tag mTagTunnel = new Tag("tunnel", "yes");
Tag mTagBridge = new Tag("bridge", "yes");
public OsmRoadLineJsonTileSource() {
super("http://tile.openstreetmap.us/vectiles-highroad");
}
public OsmRoadLineJsonTileSource() {
super("http://tile.openstreetmap.us/vectiles-highroad");
}
@Override
public void decodeTags(MapElement mapElement, Map<String, Object> properties) {
String highway = null;
boolean isLink = false;
@Override
public void decodeTags(MapElement mapElement, Map<String, Object> properties) {
String highway = null;
boolean isLink = false;
mapElement.layer = 5;
mapElement.layer = 5;
for (Map.Entry<String, Object> entry : properties.entrySet()) {
String key = entry.getKey();
Object value = entry.getValue();
//log.debug(key + " : " + String.valueOf(value));
for (Map.Entry<String, Object> entry : properties.entrySet()) {
String key = entry.getKey();
Object value = entry.getValue();
//log.debug(key + " : " + String.valueOf(value));
if (value == null)
continue;
if (value == null)
continue;
if ("no".equals(value))
continue;
if ("no".equals(value))
continue;
if ("highway".equals(key) && value instanceof String) {
highway = (String) entry.getValue();
}
else if ("is_link".equals(key)) {
isLink = "yes".equals(value);
}
else if ("is_tunnel".equals(key)) {
mapElement.tags.add(mTagTunnel);
}
else if ("is_bridge".equals(key)) {
mapElement.tags.add(mTagBridge);
}
else if ("sort_key".equals(key)) {
if (value instanceof Integer)
mapElement.layer = 5 + (Integer) value;
}
else if ("railway".equals(key) && value instanceof String) {
mapElement.tags.add(new Tag("railway", (String) value));
}
}
if ("highway".equals(key) && value instanceof String) {
highway = (String) entry.getValue();
} else if ("is_link".equals(key)) {
isLink = "yes".equals(value);
} else if ("is_tunnel".equals(key)) {
mapElement.tags.add(mTagTunnel);
} else if ("is_bridge".equals(key)) {
mapElement.tags.add(mTagBridge);
} else if ("sort_key".equals(key)) {
if (value instanceof Integer)
mapElement.layer = 5 + (Integer) value;
} else if ("railway".equals(key) && value instanceof String) {
mapElement.tags.add(new Tag("railway", (String) value));
}
}
if (highway == null)
return;
if (highway == null)
return;
if (isLink)
highway += "_link";
if (isLink)
highway += "_link";
mapElement.tags.add(new Tag("highway", highway));
mapElement.tags.add(new Tag("highway", highway));
}
}
@Override
public Tag rewriteTag(String key, Object value) {
if ("kind".equals(key))
return null;
@Override
public Tag rewriteTag(String key, Object value) {
if ("kind".equals(key))
return null;
if (value == null)
return null;
if (value == null)
return null;
String val = (value instanceof String) ? (String) value : String.valueOf(value);
String val = (value instanceof String) ? (String) value : String.valueOf(value);
return new Tag(key, val);
}
return new Tag(key, val);
}
}

View File

@@ -16,23 +16,23 @@
*/
package org.oscim.tiling.source.geojson;
import java.util.Map;
import org.oscim.core.MapElement;
import org.oscim.core.Tag;
import java.util.Map;
public class OsmWaterJsonTileSource extends GeoJsonTileSource {
public OsmWaterJsonTileSource() {
super("http://tile.openstreetmap.us/vectiles-water-areas");
}
public OsmWaterJsonTileSource() {
super("http://tile.openstreetmap.us/vectiles-water-areas");
}
Tag mTagWater = new Tag("natural", "water");
Tag mTagWater = new Tag("natural", "water");
@Override
public void decodeTags(MapElement mapElement, Map<String, Object> properties) {
@Override
public void decodeTags(MapElement mapElement, Map<String, Object> properties) {
mapElement.tags.add(mTagWater);
mapElement.tags.add(mTagWater);
}
}
}

View File

@@ -1,22 +1,22 @@
package org.oscim.tiling.source.geojson;
import java.util.Map;
import org.oscim.core.MapElement;
import org.oscim.core.Tag;
import java.util.Map;
public class RiverJsonTileSource extends GeoJsonTileSource {
public RiverJsonTileSource() {
super("http://www.somebits.com:8001/rivers");
}
public RiverJsonTileSource() {
super("http://www.somebits.com:8001/rivers");
}
Tag mTagWater = new Tag("waterway", "river");
Tag mTagWater = new Tag("waterway", "river");
@Override
public void decodeTags(MapElement mapElement, Map<String, Object> properties) {
@Override
public void decodeTags(MapElement mapElement, Map<String, Object> properties) {
mapElement.tags.add(mTagWater);
mapElement.tags.add(mTagWater);
}
}
}

View File

@@ -23,36 +23,36 @@ import org.oscim.tiling.source.UrlTileSource;
public class MapnikVectorTileSource extends UrlTileSource {
public MapnikVectorTileSource() {
super("http://d1s11ojcu7opje.cloudfront.net/dev/764e0b8d", "");
setUrlFormatter(new TileUrlFormatter() {
@Override
public String formatTilePath(UrlTileSource tileSource, Tile tile) {
// url formatter for mapbox streets
byte[] hexTable = {
'0', '1', '2', '3',
'4', '5', '6', '7',
'8', '9', 'a', 'b',
'c', 'd', 'e', 'f'
};
StringBuilder sb = new StringBuilder();
sb.append('/');
sb.append(hexTable[(tile.tileX) % 16]);
sb.append(hexTable[(tile.tileY) % 16]);
sb.append('/');
sb.append(tile.zoomLevel);
sb.append('/');
sb.append(tile.tileX);
sb.append('/');
sb.append(tile.tileY);
public MapnikVectorTileSource() {
super("http://d1s11ojcu7opje.cloudfront.net/dev/764e0b8d", "");
setUrlFormatter(new TileUrlFormatter() {
@Override
public String formatTilePath(UrlTileSource tileSource, Tile tile) {
// url formatter for mapbox streets
byte[] hexTable = {
'0', '1', '2', '3',
'4', '5', '6', '7',
'8', '9', 'a', 'b',
'c', 'd', 'e', 'f'
};
StringBuilder sb = new StringBuilder();
sb.append('/');
sb.append(hexTable[(tile.tileX) % 16]);
sb.append(hexTable[(tile.tileY) % 16]);
sb.append('/');
sb.append(tile.zoomLevel);
sb.append('/');
sb.append(tile.tileX);
sb.append('/');
sb.append(tile.tileY);
return sb.toString();
}
});
}
return sb.toString();
}
});
}
@Override
public ITileDataSource getDataSource() {
return new UrlTileDataSource(this, new TileDecoder(), getHttpEngine());
}
@Override
public ITileDataSource getDataSource() {
return new UrlTileDataSource(this, new TileDecoder(), getHttpEngine());
}
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -22,16 +22,15 @@ import org.oscim.tiling.source.UrlTileSource;
/**
* Deprecated
*
*/
public class OSciMap1TileSource extends UrlTileSource {
public OSciMap1TileSource(String url) {
super(url, "/{Z}/{X}/{Y}.osmtile");
}
public OSciMap1TileSource(String url) {
super(url, "/{Z}/{X}/{Y}.osmtile");
}
@Override
public ITileDataSource getDataSource() {
return new UrlTileDataSource(this, new TileDecoder(), getHttpEngine());
}
@Override
public ITileDataSource getDataSource() {
return new UrlTileDataSource(this, new TileDecoder(), getHttpEngine());
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -16,12 +16,6 @@
*/
package org.oscim.tiling.source.oscimap;
import java.io.IOException;
import java.io.InputStream;
import java.util.Collections;
import java.util.LinkedHashMap;
import java.util.Map;
import org.oscim.core.GeometryBuffer.GeometryType;
import org.oscim.core.MapElement;
import org.oscim.core.Tag;
@@ -31,427 +25,433 @@ import org.oscim.tiling.source.PbfDecoder;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.IOException;
import java.io.InputStream;
import java.util.Collections;
import java.util.LinkedHashMap;
import java.util.Map;
public class TileDecoder extends PbfDecoder {
static final Logger log = LoggerFactory.getLogger(TileDecoder.class);
private final static float REF_TILE_SIZE = 4096.0f;
private static final int TAG_TILE_TAGS = 1;
private static final int TAG_TILE_WAYS = 2;
private static final int TAG_TILE_POLY = 3;
private static final int TAG_TILE_NODES = 4;
private static final int TAG_WAY_TAGS = 11;
private static final int TAG_WAY_INDEX = 12;
private static final int TAG_WAY_COORDS = 13;
private static final int TAG_WAY_LAYER = 21;
private static final int TAG_WAY_NUM_TAGS = 1;
private static final int TAG_WAY_NUM_INDICES = 2;
private static final int TAG_WAY_NUM_COORDS = 3;
private static final int TAG_NODE_TAGS = 11;
private static final int TAG_NODE_COORDS = 12;
private static final int TAG_NODE_LAYER = 21;
private static final int TAG_NODE_NUM_TAGS = 1;
private static final int TAG_NODE_NUM_COORDS = 2;
private int MAX_TILE_TAGS = 100;
private Tag[] curTags = new Tag[MAX_TILE_TAGS];
private int mCurTagCnt;
private ITileDataSink mSink;
private float mScale;
private Tile mTile;
private final MapElement mElem;
TileDecoder() {
mElem = new MapElement();
}
@Override
public boolean decode(Tile tile, ITileDataSink sink, InputStream is)
throws IOException {
setInputStream(is);
mTile = tile;
mSink = sink;
mScale = REF_TILE_SIZE / Tile.SIZE;
return decode();
}
private static final int MAX_TAGS_CACHE = 100;
private static Map<String, Tag> tagHash =
Collections.synchronizedMap(new LinkedHashMap<String, Tag>(MAX_TAGS_CACHE,
0.75f,
true) {
private static final long serialVersionUID = 1L;
//@Override
//protected boolean removeEldestEntry(Entry<String, Tag> e) {
//if (size() < MAX_TAGS_CACHE)
//return false;
//return true;
//}
});
private boolean decode() throws IOException {
int val;
mCurTagCnt = 0;
while (hasData() && (val = decodeVarint32()) > 0) {
// read tag and wire type
int tag = (val >> 3);
switch (tag) {
case TAG_TILE_TAGS:
decodeTileTags();
break;
case TAG_TILE_WAYS:
decodeTileWays(false);
break;
case TAG_TILE_POLY:
decodeTileWays(true);
break;
case TAG_TILE_NODES:
decodeTileNodes();
break;
default:
log.debug("invalid type for tile: " + tag);
return false;
}
}
return true;
}
private boolean decodeTileTags() throws IOException {
String tagString = decodeString();
if (tagString == null || tagString.length() == 0) {
curTags[mCurTagCnt++] = new Tag(Tag.KEY_NAME, "...");
return false;
}
Tag tag = tagHash.get(tagString);
if (tag == null) {
if (tagString.startsWith(Tag.KEY_NAME))
tag = new Tag(Tag.KEY_NAME, tagString.substring(5), false);
else
tag = Tag.parse(tagString);
if (tag != null)
tagHash.put(tagString, tag);
}
if (mCurTagCnt >= MAX_TILE_TAGS) {
MAX_TILE_TAGS = mCurTagCnt + 10;
Tag[] tmp = new Tag[MAX_TILE_TAGS];
System.arraycopy(curTags, 0, tmp, 0, mCurTagCnt);
curTags = tmp;
}
curTags[mCurTagCnt++] = tag;
return true;
}
private boolean decodeTileWays(boolean polygon) throws IOException {
int bytes = decodeVarint32();
int end = position() + bytes;
int indexCnt = 0;
int tagCnt = 0;
int coordCnt = 0;
int layer = 5;
boolean fail = false;
while (position() < end) {
// read tag and wire type
int val = decodeVarint32();
if (val == 0)
break;
int tag = (val >> 3);
switch (tag) {
case TAG_WAY_TAGS:
if (!decodeWayTags(tagCnt))
return false;
break;
case TAG_WAY_INDEX:
decodeWayIndices(indexCnt);
break;
case TAG_WAY_COORDS:
if (coordCnt == 0) {
log.debug(mTile + " no coordinates");
}
mElem.ensurePointSize(coordCnt, false);
int cnt = decodeInterleavedPoints(mElem.points, mScale);
if (cnt != coordCnt) {
log.debug(mTile + " wrong number of coordintes "
+ coordCnt + "/" + cnt);
fail = true;
}
break;
case TAG_WAY_LAYER:
layer = decodeVarint32();
break;
case TAG_WAY_NUM_TAGS:
tagCnt = decodeVarint32();
break;
case TAG_WAY_NUM_INDICES:
indexCnt = decodeVarint32();
break;
case TAG_WAY_NUM_COORDS:
coordCnt = decodeVarint32();
break;
default:
log.debug("X invalid type for way: " + tag);
}
}
if (fail || indexCnt == 0 || tagCnt == 0) {
log.debug("failed reading way: bytes:" + bytes + " index:"
//+ (tags != null ? tags.toString() : "...") + " "
+ indexCnt + " " + coordCnt + " " + tagCnt);
return false;
}
// FIXME, remove all tiles from cache then remove this below
//if (layer == 0)
// layer = 5;
mElem.type = polygon ? GeometryType.POLY : GeometryType.LINE;
mElem.setLayer(layer);
mSink.process(mElem);
return true;
}
private boolean decodeTileNodes() throws IOException {
int bytes = decodeVarint32();
int end = position() + bytes;
int tagCnt = 0;
int coordCnt = 0;
byte layer = 0;
while (position() < end) {
// read tag and wire type
int val = decodeVarint32();
if (val == 0)
break;
int tag = (val >> 3);
switch (tag) {
case TAG_NODE_TAGS:
if (!decodeWayTags(tagCnt))
return false;
break;
case TAG_NODE_COORDS:
int cnt = decodeNodeCoordinates(coordCnt, layer);
if (cnt != coordCnt) {
log.debug("X wrong number of coordintes");
return false;
}
break;
case TAG_NODE_LAYER:
layer = (byte) decodeVarint32();
break;
case TAG_NODE_NUM_TAGS:
tagCnt = decodeVarint32();
break;
case TAG_NODE_NUM_COORDS:
coordCnt = decodeVarint32();
break;
default:
log.debug("X invalid type for node: " + tag);
}
}
return true;
}
private int decodeNodeCoordinates(int numNodes, byte layer)
throws IOException {
int bytes = decodeVarint32();
fillBuffer(bytes);
int cnt = 0;
int end = position() + bytes;
// read repeated sint32
int lastX = 0;
int lastY = 0;
float[] coords = mElem.ensurePointSize(numNodes, false);
while (position() < end && cnt < numNodes) {
int lon = deZigZag(decodeVarint32());
int lat = deZigZag(decodeVarint32());
lastX = lon + lastX;
lastY = lat + lastY;
coords[cnt++] = lastX / mScale;
coords[cnt++] = Tile.SIZE - lastY / mScale;
}
mElem.index[0] = (short) numNodes;
mElem.type = GeometryType.POINT;
mElem.setLayer(layer);
mSink.process(mElem);
return cnt;
}
private boolean decodeWayTags(int tagCnt) throws IOException {
int bytes = decodeVarint32();
mElem.tags.clear();
int cnt = 0;
int end = position() + bytes;
int max = mCurTagCnt;
for (; position() < end; cnt++) {
int tagNum = decodeVarint32();
if (tagNum < 0 || cnt == tagCnt) {
log.debug("NULL TAG: " + mTile
+ " invalid tag:" + tagNum
+ " " + tagCnt + "/" + cnt);
continue;
}
if (tagNum < Tags.MAX) {
mElem.tags.add(Tags.tags[tagNum]);
continue;
}
tagNum -= Tags.LIMIT;
if (tagNum >= 0 && tagNum < max) {
mElem.tags.add(curTags[tagNum]);
} else {
log.debug("NULL TAG: " + mTile
+ " could find tag:"
+ tagNum + " " + tagCnt
+ "/" + cnt);
}
}
if (tagCnt != cnt) {
log.debug("NULL TAG: " + mTile);
return false;
}
return true;
}
private int decodeWayIndices(int indexCnt) throws IOException {
mElem.ensureIndexSize(indexCnt, false);
decodeVarintArray(indexCnt, mElem.index);
int[] index = mElem.index;
int coordCnt = 0;
for (int i = 0; i < indexCnt; i++) {
coordCnt += index[i];
index[i] *= 2;
}
// set end marker
if (indexCnt < index.length)
index[indexCnt] = -1;
return coordCnt;
}
//@Override
protected int decodeInterleavedPoints(float[] coords, float scale)
throws IOException {
int bytes = decodeVarint32();
fillBuffer(bytes);
int cnt = 0;
int lastX = 0;
int lastY = 0;
boolean even = true;
byte[] buf = buffer;
int pos = bufferPos;
int end = pos + bytes;
int val;
while (pos < end) {
if (buf[pos] >= 0) {
val = buf[pos++];
} else if (buf[pos + 1] >= 0) {
val = (buf[pos++] & 0x7f)
| buf[pos++] << 7;
} else if (buf[pos + 2] >= 0) {
val = (buf[pos++] & 0x7f)
| (buf[pos++] & 0x7f) << 7
| (buf[pos++]) << 14;
} else if (buf[pos + 3] >= 0) {
val = (buf[pos++] & 0x7f)
| (buf[pos++] & 0x7f) << 7
| (buf[pos++] & 0x7f) << 14
| (buf[pos++]) << 21;
} else {
val = (buf[pos++] & 0x7f)
| (buf[pos++] & 0x7f) << 7
| (buf[pos++] & 0x7f) << 14
| (buf[pos++] & 0x7f) << 21
| (buf[pos]) << 28;
if (buf[pos++] < 0)
throw INVALID_VARINT;
}
// zigzag decoding
int s = ((val >>> 1) ^ -(val & 1));
if (even) {
lastX = lastX + s;
coords[cnt++] = lastX / scale;
even = false;
} else {
lastY = lastY + s;
coords[cnt++] = Tile.SIZE - lastY / scale;
even = true;
}
}
if (pos != bufferPos + bytes)
throw INVALID_PACKED_SIZE;
bufferPos = pos;
// return number of points read
return cnt;
}
static final Logger log = LoggerFactory.getLogger(TileDecoder.class);
private final static float REF_TILE_SIZE = 4096.0f;
private static final int TAG_TILE_TAGS = 1;
private static final int TAG_TILE_WAYS = 2;
private static final int TAG_TILE_POLY = 3;
private static final int TAG_TILE_NODES = 4;
private static final int TAG_WAY_TAGS = 11;
private static final int TAG_WAY_INDEX = 12;
private static final int TAG_WAY_COORDS = 13;
private static final int TAG_WAY_LAYER = 21;
private static final int TAG_WAY_NUM_TAGS = 1;
private static final int TAG_WAY_NUM_INDICES = 2;
private static final int TAG_WAY_NUM_COORDS = 3;
private static final int TAG_NODE_TAGS = 11;
private static final int TAG_NODE_COORDS = 12;
private static final int TAG_NODE_LAYER = 21;
private static final int TAG_NODE_NUM_TAGS = 1;
private static final int TAG_NODE_NUM_COORDS = 2;
private int MAX_TILE_TAGS = 100;
private Tag[] curTags = new Tag[MAX_TILE_TAGS];
private int mCurTagCnt;
private ITileDataSink mSink;
private float mScale;
private Tile mTile;
private final MapElement mElem;
TileDecoder() {
mElem = new MapElement();
}
@Override
public boolean decode(Tile tile, ITileDataSink sink, InputStream is)
throws IOException {
setInputStream(is);
mTile = tile;
mSink = sink;
mScale = REF_TILE_SIZE / Tile.SIZE;
return decode();
}
private static final int MAX_TAGS_CACHE = 100;
private static Map<String, Tag> tagHash =
Collections.synchronizedMap(new LinkedHashMap<String, Tag>(MAX_TAGS_CACHE,
0.75f,
true) {
private static final long serialVersionUID = 1L;
//@Override
//protected boolean removeEldestEntry(Entry<String, Tag> e) {
//if (size() < MAX_TAGS_CACHE)
//return false;
//return true;
//}
});
private boolean decode() throws IOException {
int val;
mCurTagCnt = 0;
while (hasData() && (val = decodeVarint32()) > 0) {
// read tag and wire type
int tag = (val >> 3);
switch (tag) {
case TAG_TILE_TAGS:
decodeTileTags();
break;
case TAG_TILE_WAYS:
decodeTileWays(false);
break;
case TAG_TILE_POLY:
decodeTileWays(true);
break;
case TAG_TILE_NODES:
decodeTileNodes();
break;
default:
log.debug("invalid type for tile: " + tag);
return false;
}
}
return true;
}
private boolean decodeTileTags() throws IOException {
String tagString = decodeString();
if (tagString == null || tagString.length() == 0) {
curTags[mCurTagCnt++] = new Tag(Tag.KEY_NAME, "...");
return false;
}
Tag tag = tagHash.get(tagString);
if (tag == null) {
if (tagString.startsWith(Tag.KEY_NAME))
tag = new Tag(Tag.KEY_NAME, tagString.substring(5), false);
else
tag = Tag.parse(tagString);
if (tag != null)
tagHash.put(tagString, tag);
}
if (mCurTagCnt >= MAX_TILE_TAGS) {
MAX_TILE_TAGS = mCurTagCnt + 10;
Tag[] tmp = new Tag[MAX_TILE_TAGS];
System.arraycopy(curTags, 0, tmp, 0, mCurTagCnt);
curTags = tmp;
}
curTags[mCurTagCnt++] = tag;
return true;
}
private boolean decodeTileWays(boolean polygon) throws IOException {
int bytes = decodeVarint32();
int end = position() + bytes;
int indexCnt = 0;
int tagCnt = 0;
int coordCnt = 0;
int layer = 5;
boolean fail = false;
while (position() < end) {
// read tag and wire type
int val = decodeVarint32();
if (val == 0)
break;
int tag = (val >> 3);
switch (tag) {
case TAG_WAY_TAGS:
if (!decodeWayTags(tagCnt))
return false;
break;
case TAG_WAY_INDEX:
decodeWayIndices(indexCnt);
break;
case TAG_WAY_COORDS:
if (coordCnt == 0) {
log.debug(mTile + " no coordinates");
}
mElem.ensurePointSize(coordCnt, false);
int cnt = decodeInterleavedPoints(mElem.points, mScale);
if (cnt != coordCnt) {
log.debug(mTile + " wrong number of coordintes "
+ coordCnt + "/" + cnt);
fail = true;
}
break;
case TAG_WAY_LAYER:
layer = decodeVarint32();
break;
case TAG_WAY_NUM_TAGS:
tagCnt = decodeVarint32();
break;
case TAG_WAY_NUM_INDICES:
indexCnt = decodeVarint32();
break;
case TAG_WAY_NUM_COORDS:
coordCnt = decodeVarint32();
break;
default:
log.debug("X invalid type for way: " + tag);
}
}
if (fail || indexCnt == 0 || tagCnt == 0) {
log.debug("failed reading way: bytes:" + bytes + " index:"
//+ (tags != null ? tags.toString() : "...") + " "
+ indexCnt + " " + coordCnt + " " + tagCnt);
return false;
}
// FIXME, remove all tiles from cache then remove this below
//if (layer == 0)
// layer = 5;
mElem.type = polygon ? GeometryType.POLY : GeometryType.LINE;
mElem.setLayer(layer);
mSink.process(mElem);
return true;
}
private boolean decodeTileNodes() throws IOException {
int bytes = decodeVarint32();
int end = position() + bytes;
int tagCnt = 0;
int coordCnt = 0;
byte layer = 0;
while (position() < end) {
// read tag and wire type
int val = decodeVarint32();
if (val == 0)
break;
int tag = (val >> 3);
switch (tag) {
case TAG_NODE_TAGS:
if (!decodeWayTags(tagCnt))
return false;
break;
case TAG_NODE_COORDS:
int cnt = decodeNodeCoordinates(coordCnt, layer);
if (cnt != coordCnt) {
log.debug("X wrong number of coordintes");
return false;
}
break;
case TAG_NODE_LAYER:
layer = (byte) decodeVarint32();
break;
case TAG_NODE_NUM_TAGS:
tagCnt = decodeVarint32();
break;
case TAG_NODE_NUM_COORDS:
coordCnt = decodeVarint32();
break;
default:
log.debug("X invalid type for node: " + tag);
}
}
return true;
}
private int decodeNodeCoordinates(int numNodes, byte layer)
throws IOException {
int bytes = decodeVarint32();
fillBuffer(bytes);
int cnt = 0;
int end = position() + bytes;
// read repeated sint32
int lastX = 0;
int lastY = 0;
float[] coords = mElem.ensurePointSize(numNodes, false);
while (position() < end && cnt < numNodes) {
int lon = deZigZag(decodeVarint32());
int lat = deZigZag(decodeVarint32());
lastX = lon + lastX;
lastY = lat + lastY;
coords[cnt++] = lastX / mScale;
coords[cnt++] = Tile.SIZE - lastY / mScale;
}
mElem.index[0] = (short) numNodes;
mElem.type = GeometryType.POINT;
mElem.setLayer(layer);
mSink.process(mElem);
return cnt;
}
private boolean decodeWayTags(int tagCnt) throws IOException {
int bytes = decodeVarint32();
mElem.tags.clear();
int cnt = 0;
int end = position() + bytes;
int max = mCurTagCnt;
for (; position() < end; cnt++) {
int tagNum = decodeVarint32();
if (tagNum < 0 || cnt == tagCnt) {
log.debug("NULL TAG: " + mTile
+ " invalid tag:" + tagNum
+ " " + tagCnt + "/" + cnt);
continue;
}
if (tagNum < Tags.MAX) {
mElem.tags.add(Tags.tags[tagNum]);
continue;
}
tagNum -= Tags.LIMIT;
if (tagNum >= 0 && tagNum < max) {
mElem.tags.add(curTags[tagNum]);
} else {
log.debug("NULL TAG: " + mTile
+ " could find tag:"
+ tagNum + " " + tagCnt
+ "/" + cnt);
}
}
if (tagCnt != cnt) {
log.debug("NULL TAG: " + mTile);
return false;
}
return true;
}
private int decodeWayIndices(int indexCnt) throws IOException {
mElem.ensureIndexSize(indexCnt, false);
decodeVarintArray(indexCnt, mElem.index);
int[] index = mElem.index;
int coordCnt = 0;
for (int i = 0; i < indexCnt; i++) {
coordCnt += index[i];
index[i] *= 2;
}
// set end marker
if (indexCnt < index.length)
index[indexCnt] = -1;
return coordCnt;
}
//@Override
protected int decodeInterleavedPoints(float[] coords, float scale)
throws IOException {
int bytes = decodeVarint32();
fillBuffer(bytes);
int cnt = 0;
int lastX = 0;
int lastY = 0;
boolean even = true;
byte[] buf = buffer;
int pos = bufferPos;
int end = pos + bytes;
int val;
while (pos < end) {
if (buf[pos] >= 0) {
val = buf[pos++];
} else if (buf[pos + 1] >= 0) {
val = (buf[pos++] & 0x7f)
| buf[pos++] << 7;
} else if (buf[pos + 2] >= 0) {
val = (buf[pos++] & 0x7f)
| (buf[pos++] & 0x7f) << 7
| (buf[pos++]) << 14;
} else if (buf[pos + 3] >= 0) {
val = (buf[pos++] & 0x7f)
| (buf[pos++] & 0x7f) << 7
| (buf[pos++] & 0x7f) << 14
| (buf[pos++]) << 21;
} else {
val = (buf[pos++] & 0x7f)
| (buf[pos++] & 0x7f) << 7
| (buf[pos++] & 0x7f) << 14
| (buf[pos++] & 0x7f) << 21
| (buf[pos]) << 28;
if (buf[pos++] < 0)
throw INVALID_VARINT;
}
// zigzag decoding
int s = ((val >>> 1) ^ -(val & 1));
if (even) {
lastX = lastX + s;
coords[cnt++] = lastX / scale;
even = false;
} else {
lastY = lastY + s;
coords[cnt++] = Tile.SIZE - lastY / scale;
even = true;
}
}
if (pos != bufferPos + bytes)
throw INVALID_PACKED_SIZE;
bufferPos = pos;
// return number of points read
return cnt;
}
}

View File

@@ -16,10 +16,6 @@
*/
package org.oscim.tiling.source.oscimap2;
import java.io.IOException;
import java.io.InputStream;
import java.util.Arrays;
import org.oscim.core.GeometryBuffer.GeometryType;
import org.oscim.core.MapElement;
import org.oscim.core.Tag;
@@ -33,295 +29,299 @@ import org.oscim.tiling.source.UrlTileSource;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.IOException;
import java.io.InputStream;
import java.util.Arrays;
public class OSciMap2TileSource extends UrlTileSource {
public OSciMap2TileSource(String url) {
super(url, "/{Z}/{X}/{Y}.osmtile");
}
@Override
public ITileDataSource getDataSource() {
return new UrlTileDataSource(this, new TileDecoder(), getHttpEngine());
}
public OSciMap2TileSource(String url) {
super(url, "/{Z}/{X}/{Y}.osmtile");
}
@Override
public ITileDataSource getDataSource() {
return new UrlTileDataSource(this, new TileDecoder(), getHttpEngine());
}
static class TileDecoder extends PbfDecoder {
static final Logger log = LoggerFactory.getLogger(TileDecoder.class);
private static final int TAG_TILE_NUM_TAGS = 1;
private static final int TAG_TILE_TAG_KEYS = 2;
private static final int TAG_TILE_TAG_VALUES = 3;
static class TileDecoder extends PbfDecoder {
static final Logger log = LoggerFactory.getLogger(TileDecoder.class);
private static final int TAG_TILE_NUM_TAGS = 1;
private static final int TAG_TILE_TAG_KEYS = 2;
private static final int TAG_TILE_TAG_VALUES = 3;
private static final int TAG_TILE_LINE = 11;
private static final int TAG_TILE_POLY = 12;
private static final int TAG_TILE_POINT = 13;
// private static final int TAG_TILE_LABEL = 21;
// private static final int TAG_TILE_WATER = 31;
private static final int TAG_TILE_LINE = 11;
private static final int TAG_TILE_POLY = 12;
private static final int TAG_TILE_POINT = 13;
// private static final int TAG_TILE_LABEL = 21;
// private static final int TAG_TILE_WATER = 31;
private static final int TAG_ELEM_NUM_INDICES = 1;
private static final int TAG_ELEM_TAGS = 11;
private static final int TAG_ELEM_INDEX = 12;
private static final int TAG_ELEM_COORDS = 13;
private static final int TAG_ELEM_LAYER = 21;
private static final int TAG_ELEM_HEIGHT = 31;
private static final int TAG_ELEM_MIN_HEIGHT = 32;
private static final int TAG_ELEM_PRIORITY = 41;
private static final int TAG_ELEM_NUM_INDICES = 1;
private static final int TAG_ELEM_TAGS = 11;
private static final int TAG_ELEM_INDEX = 12;
private static final int TAG_ELEM_COORDS = 13;
private static final int TAG_ELEM_LAYER = 21;
private static final int TAG_ELEM_HEIGHT = 31;
private static final int TAG_ELEM_MIN_HEIGHT = 32;
private static final int TAG_ELEM_PRIORITY = 41;
private int[] mSArray;
private final TagSet mTileTags;
private final MapElement mElem;
private int[] mSArray;
private final TagSet mTileTags;
private final MapElement mElem;
private Tile mTile;
private ITileDataSink mMapDataSink;
// scale coordinates to tile size
private final static float REF_TILE_SIZE = 4096.0f;
private float mScale;
private Tile mTile;
private ITileDataSink mMapDataSink;
// scale coordinates to tile size
private final static float REF_TILE_SIZE = 4096.0f;
private float mScale;
TileDecoder() {
mElem = new MapElement();
mTileTags = new TagSet(20);
TileDecoder() {
mElem = new MapElement();
mTileTags = new TagSet(20);
// temp array for decoding shorts
mSArray = new int[100];
}
// temp array for decoding shorts
mSArray = new int[100];
}
@Override
public boolean decode(Tile tile, ITileDataSink sink, InputStream is)
throws IOException {
@Override
public boolean decode(Tile tile, ITileDataSink sink, InputStream is)
throws IOException {
readUnsignedInt(is, buffer);
readUnsignedInt(is, buffer);
setInputStream(is);
setInputStream(is);
mTile = tile;
mMapDataSink = sink;
mTile = tile;
mMapDataSink = sink;
mScale = REF_TILE_SIZE / Tile.SIZE;
mScale = REF_TILE_SIZE / Tile.SIZE;
mTileTags.clear();
mTileTags.clear();
int val;
int numTags = 0;
int val;
int numTags = 0;
while (hasData() && (val = decodeVarint32()) > 0) {
// read tag and wire type
int tag = (val >> 3);
while (hasData() && (val = decodeVarint32()) > 0) {
// read tag and wire type
int tag = (val >> 3);
switch (tag) {
case TAG_TILE_NUM_TAGS:
numTags = decodeVarint32();
break;
switch (tag) {
case TAG_TILE_NUM_TAGS:
numTags = decodeVarint32();
break;
case TAG_TILE_TAG_KEYS:
int len = numTags;
if (mSArray.length < len)
mSArray = new int[len];
case TAG_TILE_TAG_KEYS:
int len = numTags;
if (mSArray.length < len)
mSArray = new int[len];
decodeVarintArray(numTags, mSArray);
break;
decodeVarintArray(numTags, mSArray);
break;
case TAG_TILE_TAG_VALUES:
// this wastes one byte, as there is no packed string...
decodeTileTags();
break;
case TAG_TILE_TAG_VALUES:
// this wastes one byte, as there is no packed string...
decodeTileTags();
break;
case TAG_TILE_LINE:
case TAG_TILE_POLY:
case TAG_TILE_POINT:
decodeTileElement(tag);
break;
default:
log.debug(mTile + " invalid type for tile: " + tag);
return false;
}
}
return true;
}
case TAG_TILE_LINE:
case TAG_TILE_POLY:
case TAG_TILE_POINT:
decodeTileElement(tag);
break;
default:
log.debug(mTile + " invalid type for tile: " + tag);
return false;
}
}
return true;
}
private boolean decodeTileTags() throws IOException {
String tagString = decodeString();
private boolean decodeTileTags() throws IOException {
String tagString = decodeString();
int curTag = mTileTags.numTags;
int curTag = mTileTags.numTags;
String key = Tags.keys[mSArray[curTag]];
Tag tag;
String key = Tags.keys[mSArray[curTag]];
Tag tag;
if (key == Tag.KEY_NAME)
tag = new Tag(key, tagString, false);
else
tag = new Tag(key, tagString, true);
if (debug)
log.debug(mTile + " add tag: " + curTag + " " + tag);
if (key == Tag.KEY_NAME)
tag = new Tag(key, tagString, false);
else
tag = new Tag(key, tagString, true);
if (debug)
log.debug(mTile + " add tag: " + curTag + " " + tag);
mTileTags.add(tag);
mTileTags.add(tag);
return true;
}
return true;
}
private int decodeWayIndices(int indexCnt) throws IOException {
mElem.ensureIndexSize(indexCnt, false);
decodeVarintArray(indexCnt, mElem.index);
private int decodeWayIndices(int indexCnt) throws IOException {
mElem.ensureIndexSize(indexCnt, false);
decodeVarintArray(indexCnt, mElem.index);
int[] index = mElem.index;
int coordCnt = 0;
int[] index = mElem.index;
int coordCnt = 0;
for (int i = 0; i < indexCnt; i++) {
coordCnt += index[i];
index[i] *= 2;
}
// set end marker
if (indexCnt < index.length)
index[indexCnt] = -1;
return coordCnt;
}
private boolean decodeTileElement(int type) throws IOException {
int bytes = decodeVarint32();
short[] index = null;
int end = position() + bytes;
int indexCnt = 1;
boolean fail = false;
int coordCnt = 0;
if (type == TAG_TILE_POINT) {
coordCnt = 1;
mElem.index[0] = 2;
}
mElem.layer = 5;
//mElem.height = 0;
//mElem.minHeight = 0;
while (position() < end) {
// read tag and wire type
int val = decodeVarint32();
if (val == 0)
break;
int tag = (val >> 3);
switch (tag) {
case TAG_ELEM_TAGS:
if (!decodeElementTags())
return false;
break;
case TAG_ELEM_NUM_INDICES:
indexCnt = decodeVarint32();
break;
case TAG_ELEM_INDEX:
coordCnt = decodeWayIndices(indexCnt);
break;
case TAG_ELEM_COORDS:
if (coordCnt == 0) {
log.debug(mTile + " no coordinates");
}
mElem.ensurePointSize(coordCnt, false);
int cnt = decodeInterleavedPoints(mElem, mScale);
if (cnt != coordCnt) {
log.debug(mTile + " wrong number of coordintes");
fail = true;
}
break;
case TAG_ELEM_LAYER:
mElem.layer = decodeVarint32();
break;
case TAG_ELEM_HEIGHT:
//mElem.height =
decodeVarint32();
break;
case TAG_ELEM_MIN_HEIGHT:
//mElem.minHeight =
decodeVarint32();
break;
case TAG_ELEM_PRIORITY:
//mElem.priority =
decodeVarint32();
break;
default:
log.debug(mTile + " invalid type for way: " + tag);
}
}
if (fail || indexCnt == 0) {
log.debug(mTile + " failed reading way: bytes:" + bytes + " index:"
+ (Arrays.toString(index)) + " tag:"
+ (mElem.tags.numTags > 0 ? Arrays.deepToString(mElem.tags.tags) : "null")
+ " " + indexCnt + " " + coordCnt);
return false;
}
switch (type) {
case TAG_TILE_LINE:
mElem.type = GeometryType.LINE;
break;
case TAG_TILE_POLY:
mElem.type = GeometryType.POLY;
break;
case TAG_TILE_POINT:
mElem.type = GeometryType.POINT;
break;
}
mMapDataSink.process(mElem);
return true;
}
private boolean decodeElementTags() throws IOException {
int bytes = decodeVarint32();
mElem.tags.clear();
int cnt = 0;
int end = position() + bytes;
int max = mTileTags.numTags - 1;
for (; position() < end; cnt++) {
int tagNum = decodeVarint32();
if (tagNum < 0) {
log.debug("NULL TAG: " + mTile
+ " invalid tag:"
+ tagNum + " " + cnt);
return false;
}
if (tagNum < Tags.MAX) {
mElem.tags.add(Tags.tags[tagNum]);
continue;
}
tagNum -= Tags.LIMIT;
if (tagNum < 0 || tagNum > max) {
log.debug("NULL TAG: " + mTile
+ " could not find tag:"
+ tagNum + " " + cnt);
return false;
}
mElem.tags.add(mTileTags.tags[tagNum]);
}
if (cnt == 0) {
log.debug("got no TAG!");
return false;
}
return true;
}
}
for (int i = 0; i < indexCnt; i++) {
coordCnt += index[i];
index[i] *= 2;
}
// set end marker
if (indexCnt < index.length)
index[indexCnt] = -1;
return coordCnt;
}
private boolean decodeTileElement(int type) throws IOException {
int bytes = decodeVarint32();
short[] index = null;
int end = position() + bytes;
int indexCnt = 1;
boolean fail = false;
int coordCnt = 0;
if (type == TAG_TILE_POINT) {
coordCnt = 1;
mElem.index[0] = 2;
}
mElem.layer = 5;
//mElem.height = 0;
//mElem.minHeight = 0;
while (position() < end) {
// read tag and wire type
int val = decodeVarint32();
if (val == 0)
break;
int tag = (val >> 3);
switch (tag) {
case TAG_ELEM_TAGS:
if (!decodeElementTags())
return false;
break;
case TAG_ELEM_NUM_INDICES:
indexCnt = decodeVarint32();
break;
case TAG_ELEM_INDEX:
coordCnt = decodeWayIndices(indexCnt);
break;
case TAG_ELEM_COORDS:
if (coordCnt == 0) {
log.debug(mTile + " no coordinates");
}
mElem.ensurePointSize(coordCnt, false);
int cnt = decodeInterleavedPoints(mElem, mScale);
if (cnt != coordCnt) {
log.debug(mTile + " wrong number of coordintes");
fail = true;
}
break;
case TAG_ELEM_LAYER:
mElem.layer = decodeVarint32();
break;
case TAG_ELEM_HEIGHT:
//mElem.height =
decodeVarint32();
break;
case TAG_ELEM_MIN_HEIGHT:
//mElem.minHeight =
decodeVarint32();
break;
case TAG_ELEM_PRIORITY:
//mElem.priority =
decodeVarint32();
break;
default:
log.debug(mTile + " invalid type for way: " + tag);
}
}
if (fail || indexCnt == 0) {
log.debug(mTile + " failed reading way: bytes:" + bytes + " index:"
+ (Arrays.toString(index)) + " tag:"
+ (mElem.tags.numTags > 0 ? Arrays.deepToString(mElem.tags.tags) : "null")
+ " " + indexCnt + " " + coordCnt);
return false;
}
switch (type) {
case TAG_TILE_LINE:
mElem.type = GeometryType.LINE;
break;
case TAG_TILE_POLY:
mElem.type = GeometryType.POLY;
break;
case TAG_TILE_POINT:
mElem.type = GeometryType.POINT;
break;
}
mMapDataSink.process(mElem);
return true;
}
private boolean decodeElementTags() throws IOException {
int bytes = decodeVarint32();
mElem.tags.clear();
int cnt = 0;
int end = position() + bytes;
int max = mTileTags.numTags - 1;
for (; position() < end; cnt++) {
int tagNum = decodeVarint32();
if (tagNum < 0) {
log.debug("NULL TAG: " + mTile
+ " invalid tag:"
+ tagNum + " " + cnt);
return false;
}
if (tagNum < Tags.MAX) {
mElem.tags.add(Tags.tags[tagNum]);
continue;
}
tagNum -= Tags.LIMIT;
if (tagNum < 0 || tagNum > max) {
log.debug("NULL TAG: " + mTile
+ " could not find tag:"
+ tagNum + " " + cnt);
return false;
}
mElem.tags.add(mTileTags.tags[tagNum]);
}
if (cnt == 0) {
log.debug("got no TAG!");
return false;
}
return true;
}
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -5,362 +5,376 @@ import java.util.ArrayList;
/**
* Triangulates a polygon into triangles - duh. Doesn't handle
* holes in polys
*
*
* @author Public Source from FlipCode
*/
public class Triangulator {
/** The accepted error value */
private static final float EPSILON = 0.0000000001f;
/** The list of points to be triangulated */
private final PointList poly = new PointList();
/** The list of points describing the triangles */
private final PointList tris = new PointList();
/** True if we've tried to triangulate */
private boolean tried;
/**
* The accepted error value
*/
private static final float EPSILON = 0.0000000001f;
/**
* The list of points to be triangulated
*/
private final PointList poly = new PointList();
/**
* The list of points describing the triangles
*/
private final PointList tris = new PointList();
/**
* True if we've tried to triangulate
*/
private boolean tried;
/**
* Create a new triangulator
*/
public Triangulator() {
}
/**
* Create a new triangulator
*/
public Triangulator() {
}
/**
* Add a point describing the polygon to be triangulated
*
* @param x The x coordinate of the point
* @param y the y coordinate of the point
*/
public void addPolyPoint(float x, float y) {
poly.add(new Point(x, y));
}
/**
* Add a point describing the polygon to be triangulated
*
* @param x The x coordinate of the point
* @param y the y coordinate of the point
*/
public void addPolyPoint(float x, float y) {
poly.add(new Point(x, y));
}
/**
* Cause the triangulator to split the polygon
*
* @return True if we managed the task
*/
public boolean triangulate() {
tried = true;
/**
* Cause the triangulator to split the polygon
*
* @return True if we managed the task
*/
public boolean triangulate() {
tried = true;
boolean worked = process(poly, tris);
return worked;
}
boolean worked = process(poly, tris);
return worked;
}
/**
* Get a count of the number of triangles produced
*
* @return The number of triangles produced
*/
public int getTriangleCount() {
if (!tried) {
throw new RuntimeException("Call triangulate() before accessing triangles");
}
return tris.size() / 3;
}
/**
* Get a count of the number of triangles produced
*
* @return The number of triangles produced
*/
public int getTriangleCount() {
if (!tried) {
throw new RuntimeException("Call triangulate() before accessing triangles");
}
return tris.size() / 3;
}
/**
* Get a point on a specified generated triangle
*
* @param tri The index of the triangle to interegate
* @param i The index of the point within the triangle to retrieve
* (0 - 2)
* @return The x,y coordinate pair for the point
*/
public float[] getTrianglePoint(int tri, int i) {
if (!tried) {
throw new RuntimeException("Call triangulate() before accessing triangles");
}
return tris.get((tri * 3) + i).toArray();
}
/**
* Get a point on a specified generated triangle
*
* @param tri The index of the triangle to interegate
* @param i The index of the point within the triangle to retrieve
* (0 - 2)
* @return The x,y coordinate pair for the point
*/
public float[] getTrianglePoint(int tri, int i) {
if (!tried) {
throw new RuntimeException("Call triangulate() before accessing triangles");
}
return tris.get((tri * 3) + i).toArray();
}
/**
* Find the area of a polygon defined by the series of points
* in the list
*
* @param contour The list of points defined the contour of the polygon
* (Vector2f)
* @return The area of the polygon defined
*/
private static float area(PointList contour) {
int n = contour.size();
/**
* Find the area of a polygon defined by the series of points
* in the list
*
* @param contour The list of points defined the contour of the polygon
* (Vector2f)
* @return The area of the polygon defined
*/
private static float area(PointList contour) {
int n = contour.size();
float A = 0.0f;
float A = 0.0f;
for (int p = n - 1, q = 0; q < n; p = q++) {
Point contourP = contour.get(p);
Point contourQ = contour.get(q);
for (int p = n - 1, q = 0; q < n; p = q++) {
Point contourP = contour.get(p);
Point contourQ = contour.get(q);
A += contourP.getX() * contourQ.getY() - contourQ.getX()
* contourP.getY();
}
return A * 0.5f;
}
A += contourP.getX() * contourQ.getY() - contourQ.getX()
* contourP.getY();
}
return A * 0.5f;
}
/**
* Check if the point P is inside the triangle defined by
* the points A,B,C
*
* @param Ax Point A x-coordinate
* @param Ay Point A y-coordinate
* @param Bx Point B x-coordinate
* @param By Point B y-coordinate
* @param Cx Point C x-coordinate
* @param Cy Point C y-coordinate
* @param Px Point P x-coordinate
* @param Py Point P y-coordinate
* @return True if the point specified is within the triangle
*/
private static boolean insideTriangle(float Ax, float Ay, float Bx,
float By, float Cx, float Cy, float Px, float Py) {
float ax, ay, bx, by, cx, cy, apx, apy, bpx, bpy, cpx, cpy;
float cCROSSap, bCROSScp, aCROSSbp;
/**
* Check if the point P is inside the triangle defined by
* the points A,B,C
*
* @param Ax Point A x-coordinate
* @param Ay Point A y-coordinate
* @param Bx Point B x-coordinate
* @param By Point B y-coordinate
* @param Cx Point C x-coordinate
* @param Cy Point C y-coordinate
* @param Px Point P x-coordinate
* @param Py Point P y-coordinate
* @return True if the point specified is within the triangle
*/
private static boolean insideTriangle(float Ax, float Ay, float Bx,
float By, float Cx, float Cy, float Px, float Py) {
float ax, ay, bx, by, cx, cy, apx, apy, bpx, bpy, cpx, cpy;
float cCROSSap, bCROSScp, aCROSSbp;
ax = Cx - Bx;
ay = Cy - By;
bx = Ax - Cx;
by = Ay - Cy;
cx = Bx - Ax;
cy = By - Ay;
apx = Px - Ax;
apy = Py - Ay;
bpx = Px - Bx;
bpy = Py - By;
cpx = Px - Cx;
cpy = Py - Cy;
ax = Cx - Bx;
ay = Cy - By;
bx = Ax - Cx;
by = Ay - Cy;
cx = Bx - Ax;
cy = By - Ay;
apx = Px - Ax;
apy = Py - Ay;
bpx = Px - Bx;
bpy = Py - By;
cpx = Px - Cx;
cpy = Py - Cy;
aCROSSbp = ax * bpy - ay * bpx;
cCROSSap = cx * apy - cy * apx;
bCROSScp = bx * cpy - by * cpx;
aCROSSbp = ax * bpy - ay * bpx;
cCROSSap = cx * apy - cy * apx;
bCROSScp = bx * cpy - by * cpx;
return ((aCROSSbp >= 0.0f) && (bCROSScp >= 0.0f) && (cCROSSap >= 0.0f));
}
return ((aCROSSbp >= 0.0f) && (bCROSScp >= 0.0f) && (cCROSSap >= 0.0f));
}
/**
* Cut a the contour and add a triangle into V to describe the
* location of the cut
*
* @param contour The list of points defining the polygon
* @param u The index of the first point
* @param v The index of the second point
* @param w The index of the third point
* @param n ?
* @param V The array to populate with indicies of triangles
* @return True if a triangle was found
*/
private static boolean snip(PointList contour, int u, int v, int w, int n,
int[] V) {
int p;
float Ax, Ay, Bx, By, Cx, Cy, Px, Py;
/**
* Cut a the contour and add a triangle into V to describe the
* location of the cut
*
* @param contour The list of points defining the polygon
* @param u The index of the first point
* @param v The index of the second point
* @param w The index of the third point
* @param n ?
* @param V The array to populate with indicies of triangles
* @return True if a triangle was found
*/
private static boolean snip(PointList contour, int u, int v, int w, int n,
int[] V) {
int p;
float Ax, Ay, Bx, By, Cx, Cy, Px, Py;
Ax = contour.get(V[u]).getX();
Ay = contour.get(V[u]).getY();
Ax = contour.get(V[u]).getX();
Ay = contour.get(V[u]).getY();
Bx = contour.get(V[v]).getX();
By = contour.get(V[v]).getY();
Bx = contour.get(V[v]).getX();
By = contour.get(V[v]).getY();
Cx = contour.get(V[w]).getX();
Cy = contour.get(V[w]).getY();
Cx = contour.get(V[w]).getX();
Cy = contour.get(V[w]).getY();
if (EPSILON > (((Bx - Ax) * (Cy - Ay)) - ((By - Ay) * (Cx - Ax)))) {
return false;
}
if (EPSILON > (((Bx - Ax) * (Cy - Ay)) - ((By - Ay) * (Cx - Ax)))) {
return false;
}
for (p = 0; p < n; p++) {
if ((p == u) || (p == v) || (p == w)) {
continue;
}
for (p = 0; p < n; p++) {
if ((p == u) || (p == v) || (p == w)) {
continue;
}
Px = contour.get(V[p]).getX();
Py = contour.get(V[p]).getY();
Px = contour.get(V[p]).getX();
Py = contour.get(V[p]).getY();
if (insideTriangle(Ax, Ay, Bx, By, Cx, Cy, Px, Py)) {
return false;
}
}
if (insideTriangle(Ax, Ay, Bx, By, Cx, Cy, Px, Py)) {
return false;
}
}
return true;
}
return true;
}
/**
* Process a list of points defining a polygon
*
* @param contour The list of points describing the polygon
* @param result The list of points describing the triangles. Groups
* of 3 describe each triangle
* @return True if we succeeded in completing triangulation
*/
private static boolean process(PointList contour, PointList result) {
/* allocate and initialize list of Vertices in polygon */
/**
* Process a list of points defining a polygon
*
* @param contour The list of points describing the polygon
* @param result The list of points describing the triangles. Groups
* of 3 describe each triangle
* @return True if we succeeded in completing triangulation
*/
private static boolean process(PointList contour, PointList result) {
/* allocate and initialize list of Vertices in polygon */
int n = contour.size();
if (n < 3)
return false;
int n = contour.size();
if (n < 3)
return false;
int[] V = new int[n];
int[] V = new int[n];
/* we want a counter-clockwise polygon in V */
if (0.0f < area(contour)) {
for (int v = 0; v < n; v++)
V[v] = v;
} else {
for (int v = 0; v < n; v++)
V[v] = (n - 1) - v;
}
if (0.0f < area(contour)) {
for (int v = 0; v < n; v++)
V[v] = v;
} else {
for (int v = 0; v < n; v++)
V[v] = (n - 1) - v;
}
int nv = n;
int nv = n;
/* remove nv-2 Vertices, creating 1 triangle every time */
int count = 2 * nv; /* error detection */
int count = 2 * nv; /* error detection */
//for (int m = 0, v = nv - 1; nv > 2;) {
for (int v = nv - 1; nv > 2;) {
/* if we loop, it is probably a non-simple polygon */
if (0 >= (count--)) {
//** Triangulate: ERROR - probable bad polygon!
return false;
}
//for (int m = 0, v = nv - 1; nv > 2;) {
for (int v = nv - 1; nv > 2; ) {
/* if we loop, it is probably a non-simple polygon */
if (0 >= (count--)) {
//** Triangulate: ERROR - probable bad polygon!
return false;
}
/* three consecutive vertices in current polygon, <u,v,w> */
int u = v;
if (nv <= u)
u = 0; /* previous */
v = u + 1;
if (nv <= v)
v = 0; /* new v */
int w = v + 1;
if (nv <= w)
w = 0; /* next */
int u = v;
if (nv <= u)
u = 0; /* previous */
v = u + 1;
if (nv <= v)
v = 0; /* new v */
int w = v + 1;
if (nv <= w)
w = 0; /* next */
if (snip(contour, u, v, w, nv, V)) {
int a, b, c, s, t;
if (snip(contour, u, v, w, nv, V)) {
int a, b, c, s, t;
/* true names of the vertices */
a = V[u];
b = V[v];
c = V[w];
a = V[u];
b = V[v];
c = V[w];
/* output Triangle */
result.add(contour.get(a));
result.add(contour.get(b));
result.add(contour.get(c));
result.add(contour.get(a));
result.add(contour.get(b));
result.add(contour.get(c));
//m++;
//m++;
/* remove v from remaining polygon */
for (s = v, t = v + 1; t < nv; s++, t++) {
V[s] = V[t];
}
nv--;
for (s = v, t = v + 1; t < nv; s++, t++) {
V[s] = V[t];
}
nv--;
/* resest error detection counter */
count = 2 * nv;
}
}
count = 2 * nv;
}
}
return true;
}
return true;
}
/**
* A single point handled by the triangulator
*
* @author Kevin Glass
*/
private class Point {
/** The x coorindate of this point */
private final float x;
/** The y coorindate of this point */
private final float y;
/**
* A single point handled by the triangulator
*
* @author Kevin Glass
*/
private class Point {
/**
* The x coorindate of this point
*/
private final float x;
/**
* The y coorindate of this point
*/
private final float y;
/**
* Create a new point
*
* @param x The x coordindate of the point
* @param y The y coordindate of the point
*/
public Point(float x, float y) {
this.x = x;
this.y = y;
}
/**
* Create a new point
*
* @param x The x coordindate of the point
* @param y The y coordindate of the point
*/
public Point(float x, float y) {
this.x = x;
this.y = y;
}
/**
* Get the x coordinate of the point
*
* @return The x coordinate of the point
*/
public float getX() {
return x;
}
/**
* Get the x coordinate of the point
*
* @return The x coordinate of the point
*/
public float getX() {
return x;
}
/**
* Get the y coordinate of the point
*
* @return The y coordinate of the point
*/
public float getY() {
return y;
}
/**
* Get the y coordinate of the point
*
* @return The y coordinate of the point
*/
public float getY() {
return y;
}
/**
* Convert this point into a float array
*
* @return The contents of this point as a float array
*/
public float[] toArray() {
return new float[] { x, y };
}
}
/**
* Convert this point into a float array
*
* @return The contents of this point as a float array
*/
public float[] toArray() {
return new float[]{x, y};
}
}
/**
* A list of type <code>Point</code>
*
* @author Kevin Glass
*/
private class PointList {
/** The list of points */
private final ArrayList<Point> points = new ArrayList<Point>();
/**
* A list of type <code>Point</code>
*
* @author Kevin Glass
*/
private class PointList {
/**
* The list of points
*/
private final ArrayList<Point> points = new ArrayList<Point>();
/**
* Create a new empty list
*/
public PointList() {
}
/**
* Create a new empty list
*/
public PointList() {
}
/**
* Add a point to the list
*
* @param point The point to add
*/
public void add(Point point) {
points.add(point);
}
/**
* Add a point to the list
*
* @param point The point to add
*/
public void add(Point point) {
points.add(point);
}
///**
// * Remove a point from the list
// *
// * @param point The point to remove
// */
//public void remove(Point point) {
// points.remove(point);
//}
///**
// * Remove a point from the list
// *
// * @param point The point to remove
// */
//public void remove(Point point) {
// points.remove(point);
//}
/**
* Get the size of the list
*
* @return The size of the list
*/
public int size() {
return points.size();
}
/**
* Get the size of the list
*
* @return The size of the list
*/
public int size() {
return points.size();
}
/**
* Get a point a specific index in the list
*
* @param i The index of the point to retrieve
* @return The point
*/
public Point get(int i) {
return points.get(i);
}
}
/**
* Get a point a specific index in the list
*
* @param i The index of the point to retrieve
* @return The point
*/
public Point get(int i) {
return points.get(i);
}
}
}

View File

@@ -17,10 +17,6 @@
package org.oscim.utils.osmpbf;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import org.openstreetmap.osmosis.osmbinary.BinaryParser;
import org.openstreetmap.osmosis.osmbinary.Osmformat;
import org.oscim.core.Tag;
@@ -31,303 +27,309 @@ import org.oscim.core.osm.OsmNode;
import org.oscim.core.osm.OsmRelation;
import org.oscim.core.osm.OsmWay;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
/**
* Class that reads and parses binary files and sends the contained entities to
* the sink.
*/
public class OsmPbfParser extends BinaryParser {
@Override
public void complete() {
//sink.complete();
}
@Override
public void complete() {
//sink.complete();
}
// /** Get the osmosis object representing a the user in a given Info protobuf.
// * @param info The info protobuf.
// * @return The OsmUser object */
// OsmUser getUser(Osmformat.Info info) {
// // System.out.println(info);
// if (info.hasUid() && info.hasUserSid()) {
// if (info.getUid() < 0) {
// return OsmUser.NONE;
// }
// return new OsmUser(info.getUid(), getStringById(info.getUserSid()));
// } else {
// return OsmUser.NONE;
// }
// }
// /** Get the osmosis object representing a the user in a given Info protobuf.
// * @param info The info protobuf.
// * @return The OsmUser object */
// OsmUser getUser(Osmformat.Info info) {
// // System.out.println(info);
// if (info.hasUid() && info.hasUserSid()) {
// if (info.getUid() < 0) {
// return OsmUser.NONE;
// }
// return new OsmUser(info.getUid(), getStringById(info.getUserSid()));
// } else {
// return OsmUser.NONE;
// }
// }
/**
* The magic number used to indicate no version number metadata for this
* entity.
*/
static final int NOVERSION = -1;
/** The magic number used to indicate no changeset metadata for this entity. */
static final int NOCHANGESET = -1;
/**
* The magic number used to indicate no version number metadata for this
* entity.
*/
static final int NOVERSION = -1;
/**
* The magic number used to indicate no changeset metadata for this entity.
*/
static final int NOCHANGESET = -1;
HashMap<Long, OsmNode> mNodeMap = new HashMap<Long, OsmNode>();
HashMap<Long, OsmWay> mWayMap = new HashMap<Long, OsmWay>();
HashMap<Long, OsmNode> mNodeMap = new HashMap<Long, OsmNode>();
HashMap<Long, OsmWay> mWayMap = new HashMap<Long, OsmWay>();
@Override
protected void parseNodes(List<Osmformat.Node> nodes) {
for (Osmformat.Node i : nodes) {
int tagCnt = i.getKeysCount();
@Override
protected void parseNodes(List<Osmformat.Node> nodes) {
for (Osmformat.Node i : nodes) {
int tagCnt = i.getKeysCount();
TagSet tags = new TagSet(tagCnt);
TagSet tags = new TagSet(tagCnt);
// List<Tag> tags = new ArrayList<Tag>();
for (int j = 0; j < tagCnt; j++) {
tags.add(new Tag(getStringById(i.getKeys(j)), getStringById(i.getVals(j))));
}
// long id, int version, Date timestamp, OsmUser user,
// long changesetId, Collection<Tag> tags,
// double latitude, double longitude
OsmNode tmp;
long id = i.getId();
double latf = parseLat(i.getLat()), lonf = parseLon(i.getLon());
// List<Tag> tags = new ArrayList<Tag>();
for (int j = 0; j < tagCnt; j++) {
tags.add(new Tag(getStringById(i.getKeys(j)), getStringById(i.getVals(j))));
}
// long id, int version, Date timestamp, OsmUser user,
// long changesetId, Collection<Tag> tags,
// double latitude, double longitude
OsmNode tmp;
long id = i.getId();
double latf = parseLat(i.getLat()), lonf = parseLon(i.getLon());
// if (i.hasInfo()) {
// Osmformat.Info info = i.getInfo();
// tmp = new OsmNode(new CommonEntityData(id, info.getVersion(), getDate(info),
// getUser(info), info.getChangeset(), tags), latf, lonf);
// } else {
tmp = new OsmNode(latf, lonf, tags, id);
// tmp = new Node(new CommonEntityData(id, NOVERSION, NODATE, OsmUser.NONE,
// NOCHANGESET, tags), latf, lonf);
// }
//sink.process(new NodeContainer(tmp));
mNodeMap.put(Long.valueOf(id), tmp);
}
}
// if (i.hasInfo()) {
// Osmformat.Info info = i.getInfo();
// tmp = new OsmNode(new CommonEntityData(id, info.getVersion(), getDate(info),
// getUser(info), info.getChangeset(), tags), latf, lonf);
// } else {
tmp = new OsmNode(latf, lonf, tags, id);
// tmp = new Node(new CommonEntityData(id, NOVERSION, NODATE, OsmUser.NONE,
// NOCHANGESET, tags), latf, lonf);
// }
//sink.process(new NodeContainer(tmp));
mNodeMap.put(Long.valueOf(id), tmp);
}
}
@Override
protected void parseDense(Osmformat.DenseNodes nodes) {
long lastId = 0, lastLat = 0, lastLon = 0;
@Override
protected void parseDense(Osmformat.DenseNodes nodes) {
long lastId = 0, lastLat = 0, lastLon = 0;
int j = 0; // Index into the keysvals array.
int j = 0; // Index into the keysvals array.
// Stuff for dense info
// long lasttimestamp = 0, lastchangeset = 0;
// int lastuserSid = 0, lastuid = 0;
// DenseInfo di = null;
// if (nodes.hasDenseinfo()) {
// di = nodes.getDenseinfo();
// }
// Stuff for dense info
// long lasttimestamp = 0, lastchangeset = 0;
// int lastuserSid = 0, lastuid = 0;
// DenseInfo di = null;
// if (nodes.hasDenseinfo()) {
// di = nodes.getDenseinfo();
// }
for (int i = 0; i < nodes.getIdCount(); i++) {
OsmNode tmp;
TagSet tags = new TagSet(4);
long lat = nodes.getLat(i) + lastLat;
lastLat = lat;
long lon = nodes.getLon(i) + lastLon;
lastLon = lon;
long id = nodes.getId(i) + lastId;
lastId = id;
double latf = parseLat(lat), lonf = parseLon(lon);
// If empty, assume that nothing here has keys or vals.
if (nodes.getKeysValsCount() > 0) {
while (nodes.getKeysVals(j) != 0) {
int keyid = nodes.getKeysVals(j++);
int valid = nodes.getKeysVals(j++);
tags.add(new Tag(getStringById(keyid), getStringById(valid)));
}
j++; // Skip over the '0' delimiter.
}
// Handle dense info.
// if (di != null) {
// int uid = di.getUid(i) + lastuid; lastuid = uid;
// int userSid = di.getUserSid(i) + lastuserSid; lastuserSid = userSid;
// long timestamp = di.getTimestamp(i) + lasttimestamp; lasttimestamp = timestamp;
// int version = di.getVersion(i);
// long changeset = di.getChangeset(i) + lastchangeset; lastchangeset = changeset;
//
// Date date = new Date(date_granularity * timestamp);
for (int i = 0; i < nodes.getIdCount(); i++) {
OsmNode tmp;
TagSet tags = new TagSet(4);
long lat = nodes.getLat(i) + lastLat;
lastLat = lat;
long lon = nodes.getLon(i) + lastLon;
lastLon = lon;
long id = nodes.getId(i) + lastId;
lastId = id;
double latf = parseLat(lat), lonf = parseLon(lon);
// If empty, assume that nothing here has keys or vals.
if (nodes.getKeysValsCount() > 0) {
while (nodes.getKeysVals(j) != 0) {
int keyid = nodes.getKeysVals(j++);
int valid = nodes.getKeysVals(j++);
tags.add(new Tag(getStringById(keyid), getStringById(valid)));
}
j++; // Skip over the '0' delimiter.
}
// Handle dense info.
// if (di != null) {
// int uid = di.getUid(i) + lastuid; lastuid = uid;
// int userSid = di.getUserSid(i) + lastuserSid; lastuserSid = userSid;
// long timestamp = di.getTimestamp(i) + lasttimestamp; lasttimestamp = timestamp;
// int version = di.getVersion(i);
// long changeset = di.getChangeset(i) + lastchangeset; lastchangeset = changeset;
//
// Date date = new Date(date_granularity * timestamp);
//OsmUser user;
// if (uid < 0) {
// user = OsmUser.NONE;
// } else {
// user = new OsmUser(uid, getStringById(userSid));
// }
//
// tmp = new OsmNode(id, tags, latf, lonf);
// } else {
tmp = new OsmNode(latf, lonf, tags, id);
//OsmUser user;
// if (uid < 0) {
// user = OsmUser.NONE;
// } else {
// user = new OsmUser(uid, getStringById(userSid));
// }
//
// tmp = new OsmNode(id, tags, latf, lonf);
// } else {
tmp = new OsmNode(latf, lonf, tags, id);
mNodeMap.put(Long.valueOf(id), tmp);
mNodeMap.put(Long.valueOf(id), tmp);
// }
// }
//sink.process(new NodeContainer(tmp));
}
}
//sink.process(new NodeContainer(tmp));
}
}
@Override
protected void parseWays(List<Osmformat.Way> ways) {
for (Osmformat.Way i : ways) {
int tagCnt = i.getKeysCount();
TagSet tags = new TagSet(tagCnt);
@Override
protected void parseWays(List<Osmformat.Way> ways) {
for (Osmformat.Way i : ways) {
int tagCnt = i.getKeysCount();
TagSet tags = new TagSet(tagCnt);
// List<Tag> tags = new ArrayList<Tag>();
for (int j = 0; j < tagCnt; j++) {
tags.add(new Tag(getStringById(i.getKeys(j)), getStringById(i.getVals(j))));
}
// List<Tag> tags = new ArrayList<Tag>();
// for (int j = 0; j < ; j++) {
// tags.add(new Tag(getStringById(i.getKeys(j)), getStringById(i.getVals(j))));
// }
// List<Tag> tags = new ArrayList<Tag>();
for (int j = 0; j < tagCnt; j++) {
tags.add(new Tag(getStringById(i.getKeys(j)), getStringById(i.getVals(j))));
}
// List<Tag> tags = new ArrayList<Tag>();
// for (int j = 0; j < ; j++) {
// tags.add(new Tag(getStringById(i.getKeys(j)), getStringById(i.getVals(j))));
// }
long lastId = 0;
List<OsmNode> nodes = new ArrayList<OsmNode>();
for (long j : i.getRefsList()) {
OsmNode n = mNodeMap.get(Long.valueOf(j + lastId));
if (n == null)
n = new OsmNode(Double.NaN, Double.NaN, null, j + lastId);
long lastId = 0;
List<OsmNode> nodes = new ArrayList<OsmNode>();
for (long j : i.getRefsList()) {
OsmNode n = mNodeMap.get(Long.valueOf(j + lastId));
if (n == null)
n = new OsmNode(Double.NaN, Double.NaN, null, j + lastId);
nodes.add(n);
lastId = j + lastId;
}
nodes.add(n);
lastId = j + lastId;
}
long id = i.getId();
long id = i.getId();
// long id, int version, Date timestamp, OsmUser user,
// long changesetId, Collection<Tag> tags,
// List<WayNode> wayNodes
OsmWay tmp;
// if (i.hasInfo()) {
// Osmformat.Info info = i.getInfo();
// tmp = new Way(new CommonEntityData(id, info.getVersion(), getDate(info),
// getUser(info), info.getChangeset(), tags), nodes);
// } else {
tmp = new OsmWay(tags, id, nodes);
// }
// long id, int version, Date timestamp, OsmUser user,
// long changesetId, Collection<Tag> tags,
// List<WayNode> wayNodes
OsmWay tmp;
// if (i.hasInfo()) {
// Osmformat.Info info = i.getInfo();
// tmp = new Way(new CommonEntityData(id, info.getVersion(), getDate(info),
// getUser(info), info.getChangeset(), tags), nodes);
// } else {
tmp = new OsmWay(tags, id, nodes);
// }
mWayMap.put(Long.valueOf(id), tmp);
mWayMap.put(Long.valueOf(id), tmp);
//sink.process(new WayContainer(tmp));
}
}
//sink.process(new WayContainer(tmp));
}
}
@Override
protected void parseRelations(List<Osmformat.Relation> rels) {
for (Osmformat.Relation i : rels) {
int tagCnt = i.getKeysCount();
TagSet tags = new TagSet(tagCnt);
@Override
protected void parseRelations(List<Osmformat.Relation> rels) {
for (Osmformat.Relation i : rels) {
int tagCnt = i.getKeysCount();
TagSet tags = new TagSet(tagCnt);
for (int j = 0; j < tagCnt; j++)
tags.add(new Tag(getStringById(i.getKeys(j)), getStringById(i.getVals(j))));
for (int j = 0; j < tagCnt; j++)
tags.add(new Tag(getStringById(i.getKeys(j)), getStringById(i.getVals(j))));
long id = i.getId();
long id = i.getId();
long lastMid = 0;
List<OsmMember> nodes = new ArrayList<OsmMember>();
int memberCnt = i.getMemidsCount();
long lastMid = 0;
List<OsmMember> nodes = new ArrayList<OsmMember>();
int memberCnt = i.getMemidsCount();
// for (int j = 0; j < memberCnt; j++) {
// long mid = lastMid + i.getMemids(j);
// lastMid = mid;
// String role = getStringById(i.getRolesSid(j));
//
// Osmformat.Relation.MemberType t = i.getTypes(j);
//
// if (t == Osmformat.Relation.MemberType.NODE) {
// etype = EntityType.Node;
// } else if (t == Osmformat.Relation.MemberType.WAY) {
// etype = EntityType.Way;
// } else if (t == Osmformat.Relation.MemberType.RELATION) {
// etype = EntityType.Relation;
// } else {
// assert false; // TODO; Illegal file?
// }
//
// nodes.add(new OsmMember(mid, etype, role));
// }
// for (int j = 0; j < memberCnt; j++) {
// long mid = lastMid + i.getMemids(j);
// lastMid = mid;
// String role = getStringById(i.getRolesSid(j));
//
// Osmformat.Relation.MemberType t = i.getTypes(j);
//
// if (t == Osmformat.Relation.MemberType.NODE) {
// etype = EntityType.Node;
// } else if (t == Osmformat.Relation.MemberType.WAY) {
// etype = EntityType.Way;
// } else if (t == Osmformat.Relation.MemberType.RELATION) {
// etype = EntityType.Relation;
// } else {
// assert false; // TODO; Illegal file?
// }
//
// nodes.add(new OsmMember(mid, etype, role));
// }
// long id, int version, TimestampContainer timestampContainer,
// OsmUser user,
// long changesetId, Collection<Tag> tags,
// List<RelationMember> members
OsmRelation tmp = new OsmRelation(tags, id, memberCnt);
// long id, int version, TimestampContainer timestampContainer,
// OsmUser user,
// long changesetId, Collection<Tag> tags,
// List<RelationMember> members
OsmRelation tmp = new OsmRelation(tags, id, memberCnt);
// if (i.hasInfo()) {
// Osmformat.Info info = i.getInfo();
// tmp = new Relation(new CommonEntityData(id, info.getVersion(), getDate(info),
// getUser(info), info.getChangeset(), tags), nodes);
// } else {
// tmp = new Relation(new CommonEntityData(id, NOVERSION, NODATE, OsmUser.NONE,
// NOCHANGESET, tags), nodes);
// }
// sink.process(new RelationContainer(tmp));
}
}
// if (i.hasInfo()) {
// Osmformat.Info info = i.getInfo();
// tmp = new Relation(new CommonEntityData(id, info.getVersion(), getDate(info),
// getUser(info), info.getChangeset(), tags), nodes);
// } else {
// tmp = new Relation(new CommonEntityData(id, NOVERSION, NODATE, OsmUser.NONE,
// NOCHANGESET, tags), nodes);
// }
// sink.process(new RelationContainer(tmp));
}
}
@Override
public void parse(Osmformat.HeaderBlock block) {
for (String s : block.getRequiredFeaturesList()) {
if (s.equals("OsmSchema-V0.6")) {
continue; // We can parse this.
}
if (s.equals("DenseNodes")) {
continue; // We can parse this.
}
throw new RuntimeException("File requires unknown feature: " + s);
}
@Override
public void parse(Osmformat.HeaderBlock block) {
for (String s : block.getRequiredFeaturesList()) {
if (s.equals("OsmSchema-V0.6")) {
continue; // We can parse this.
}
if (s.equals("DenseNodes")) {
continue; // We can parse this.
}
throw new RuntimeException("File requires unknown feature: " + s);
}
// if (block.hasBbox()) {
// String source = OsmosisConstants.VERSION;
// if (block.hasSource()) {
// source = block.getSource();
// }
//
// double multiplier = .000000001;
// double rightf = block.getBbox().getRight() * multiplier;
// double leftf = block.getBbox().getLeft() * multiplier;
// double topf = block.getBbox().getTop() * multiplier;
// double bottomf = block.getBbox().getBottom() * multiplier;
//
// Bound bounds = new Bound(rightf, leftf, topf, bottomf, source);
// sink.process(new BoundContainer(bounds));
// }
}
// if (block.hasBbox()) {
// String source = OsmosisConstants.VERSION;
// if (block.hasSource()) {
// source = block.getSource();
// }
//
// double multiplier = .000000001;
// double rightf = block.getBbox().getRight() * multiplier;
// double leftf = block.getBbox().getLeft() * multiplier;
// double topf = block.getBbox().getTop() * multiplier;
// double bottomf = block.getBbox().getBottom() * multiplier;
//
// Bound bounds = new Bound(rightf, leftf, topf, bottomf, source);
// sink.process(new BoundContainer(bounds));
// }
}
public OsmData getData() {
public OsmData getData() {
// for (Entry<OsmRelation, List<TmpRelation>> entry : relationMembersForRelation
// .entrySet()) {
//
// OsmRelation relation = entry.getKey();
//
// for (TmpRelation member : entry.getValue()) {
//
// OsmElement memberObject = null;
//
// if ("node".equals(member)) {
// memberObject = nodesById.get(member.id);
// } else if ("way".equals(member)) {
// memberObject = waysById.get(member.id);
// } else if ("relation".equals(member)) {
// memberObject = relationsById.get(member.id);
// } else {
// // log("missing relation " + member.id);
// continue;
// }
//
// if (memberObject != null) {
// OsmMember ownMember = new OsmMember(member.role,
// memberObject);
//
// relation.relationMembers.add(ownMember);
// }
// }
// }
// for (Entry<OsmRelation, List<TmpRelation>> entry : relationMembersForRelation
// .entrySet()) {
//
// OsmRelation relation = entry.getKey();
//
// for (TmpRelation member : entry.getValue()) {
//
// OsmElement memberObject = null;
//
// if ("node".equals(member)) {
// memberObject = nodesById.get(member.id);
// } else if ("way".equals(member)) {
// memberObject = waysById.get(member.id);
// } else if ("relation".equals(member)) {
// memberObject = relationsById.get(member.id);
// } else {
// // log("missing relation " + member.id);
// continue;
// }
//
// if (memberObject != null) {
// OsmMember ownMember = new OsmMember(member.role,
// memberObject);
//
// relation.relationMembers.add(ownMember);
// }
// }
// }
// give up references to original collections
// give up references to original collections
ArrayList<OsmWay> ways = new ArrayList<OsmWay>(mWayMap.values());
ArrayList<OsmNode> nodes = new ArrayList<OsmNode>(mNodeMap.values());
ArrayList<OsmWay> ways = new ArrayList<OsmWay>(mWayMap.values());
ArrayList<OsmNode> nodes = new ArrayList<OsmNode>(mNodeMap.values());
//log.debug("nodes: " + nodes.size() + " ways: " + ways.size());
//log.debug("nodes: " + nodes.size() + " ways: " + ways.size());
return new OsmData(null, nodes, ways, null);
}
return new OsmData(null, nodes, ways, null);
}
}

View File

@@ -16,25 +16,25 @@
*/
package org.oscim.utils.osmpbf;
import java.io.IOException;
import java.io.InputStream;
import org.openstreetmap.osmosis.osmbinary.file.BlockInputStream;
import org.oscim.core.osm.OsmData;
import java.io.IOException;
import java.io.InputStream;
public class OsmPbfReader {
public static OsmData process(InputStream is) {
OsmPbfParser parser = new OsmPbfParser();
public static OsmData process(InputStream is) {
OsmPbfParser parser = new OsmPbfParser();
try {
(new BlockInputStream(is, parser)).process();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
return null;
}
try {
(new BlockInputStream(is, parser)).process();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
return null;
}
return parser.getData();
}
return parser.getData();
}
}

View File

@@ -17,6 +17,21 @@
package org.oscim.utils.overpass;
import com.fasterxml.jackson.core.JsonFactory;
import com.fasterxml.jackson.core.JsonParseException;
import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.core.JsonToken;
import org.oscim.core.Tag;
import org.oscim.core.TagSet;
import org.oscim.core.osm.Bound;
import org.oscim.core.osm.OsmData;
import org.oscim.core.osm.OsmElement;
import org.oscim.core.osm.OsmMember;
import org.oscim.core.osm.OsmNode;
import org.oscim.core.osm.OsmRelation;
import org.oscim.core.osm.OsmWay;
import java.io.IOException;
import java.io.InputStream;
import java.io.UnsupportedEncodingException;
@@ -33,381 +48,359 @@ import java.util.zip.GZIPInputStream;
import java.util.zip.Inflater;
import java.util.zip.InflaterInputStream;
import org.oscim.core.Tag;
import org.oscim.core.TagSet;
import org.oscim.core.osm.Bound;
import org.oscim.core.osm.OsmData;
import org.oscim.core.osm.OsmElement;
import org.oscim.core.osm.OsmMember;
import org.oscim.core.osm.OsmNode;
import org.oscim.core.osm.OsmRelation;
import org.oscim.core.osm.OsmWay;
import com.fasterxml.jackson.core.JsonFactory;
import com.fasterxml.jackson.core.JsonParseException;
import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.core.JsonToken;
public class OverpassAPIReader {
private static final String OVERPASS_API = "http://city.informatik.uni-bremen.de/oapi/interpreter";
private static final int RESPONSECODE_OK = 200;
/**
* The timeout we use for the HttpURLConnection.
*/
private static final int TIMEOUT = 15000;
/**
* The base url of the server. Defaults to.
* "http://www.openstreetmap.org/api/0.5".
*/
private final String myBaseUrl = OVERPASS_API;
/**
* The http connection used to retrieve data.
*/
private HttpURLConnection myActiveConnection;
/**
* The stream providing response data.
*/
private InputStream responseStream;
private final String query;
/**
* Creates a new instance with the specified geographical coordinates.
*
* @param left
* The longitude marking the left edge of the bounding box.
* @param right
* The longitude marking the right edge of the bounding box.
* @param top
* The latitude marking the top edge of the bounding box.
* @param bottom
* The latitude marking the bottom edge of the bounding box.
* @param baseUrl
* (optional) The base url of the server (eg.
* http://www.openstreetmap.org/api/0.5).
*/
public OverpassAPIReader(final double left, final double right,
final double top, final double bottom, final String baseUrl,
final String query) {
String bbox = "(" + Math.min(top, bottom) + "," + Math.min(left, right)
+ "," + Math.max(top, bottom) + "," + Math.max(left, right)
+ ")";
this.query = query.replaceAll("\\{\\{bbox\\}\\}", bbox);
}
/**
* Open a connection to the given url and return a reader on the input
* stream from that connection.
*
* @param pUrlStr
* The exact url to connect to.
* @return An reader reading the input stream (servers answer) or
* <code>null</code>.
* @throws IOException
* on io-errors
*/
private InputStream getInputStream(final String pUrlStr) throws IOException {
URL url;
int responseCode;
String encoding;
url = new URL(pUrlStr);
myActiveConnection = (HttpURLConnection) url.openConnection();
myActiveConnection.setRequestProperty("Accept-Encoding",
"gzip, deflate");
responseCode = myActiveConnection.getResponseCode();
if (responseCode != RESPONSECODE_OK) {
String message;
String apiErrorMessage;
apiErrorMessage = myActiveConnection.getHeaderField("Error");
if (apiErrorMessage != null) {
message = "Received API HTTP response code " + responseCode
+ " with message \"" + apiErrorMessage
+ "\" for URL \"" + pUrlStr + "\".";
} else {
message = "Received API HTTP response code " + responseCode
+ " for URL \"" + pUrlStr + "\".";
}
throw new IOException(message);
}
myActiveConnection.setConnectTimeout(TIMEOUT);
encoding = myActiveConnection.getContentEncoding();
responseStream = myActiveConnection.getInputStream();
if (encoding != null && encoding.equalsIgnoreCase("gzip")) {
responseStream = new GZIPInputStream(responseStream);
} else if (encoding != null && encoding.equalsIgnoreCase("deflate")) {
responseStream = new InflaterInputStream(responseStream,
new Inflater(true));
}
return responseStream;
}
class TmpRelation {
Long id;
String type;
String role;
}
private final List<Bound> bounds = new ArrayList<Bound>();
private Map<Long, OsmNode> nodesById = new HashMap<Long, OsmNode>();
private Map<Long, OsmWay> waysById = new HashMap<Long, OsmWay>();
private Map<Long, OsmRelation> relationsById = new HashMap<Long, OsmRelation>();
private Map<OsmRelation, List<TmpRelation>> relationMembersForRelation =
new HashMap<OsmRelation, List<TmpRelation>>();
private final Collection<OsmNode> ownNodes = new ArrayList<OsmNode>(10000);
private final Collection<OsmWay> ownWays = new ArrayList<OsmWay>(1000);
private final Collection<OsmRelation> ownRelations = new ArrayList<OsmRelation>(
100);
public void parse(InputStream in) throws IOException {
JsonFactory jsonFactory = new JsonFactory();
try {
JsonParser jp = jsonFactory.createJsonParser(in);
JsonToken t;
while ((t = jp.nextToken()) != null) {
if (t == JsonToken.START_OBJECT) {
jp.nextToken();
String name = jp.getCurrentName();
jp.nextToken();
if ("type".equals(name)) {
String type = jp.getText();
if ("node".equals(type))
parseNode(jp);
else if ("way".equals(type))
parseWay(jp);
else if ("relation".equals(type))
parseRelation(jp);
}
}
}
} catch (JsonParseException e) {
e.printStackTrace();
}
}
private void parseNode(JsonParser jp) throws JsonParseException,
IOException {
long id = 0;
double lat = 0, lon = 0;
TagSet tags = null;
private static final String OVERPASS_API = "http://city.informatik.uni-bremen.de/oapi/interpreter";
private static final int RESPONSECODE_OK = 200;
/**
* The timeout we use for the HttpURLConnection.
*/
private static final int TIMEOUT = 15000;
/**
* The base url of the server. Defaults to.
* "http://www.openstreetmap.org/api/0.5".
*/
private final String myBaseUrl = OVERPASS_API;
/**
* The http connection used to retrieve data.
*/
private HttpURLConnection myActiveConnection;
/**
* The stream providing response data.
*/
private InputStream responseStream;
private final String query;
/**
* Creates a new instance with the specified geographical coordinates.
*
* @param left The longitude marking the left edge of the bounding box.
* @param right The longitude marking the right edge of the bounding box.
* @param top The latitude marking the top edge of the bounding box.
* @param bottom The latitude marking the bottom edge of the bounding box.
* @param baseUrl (optional) The base url of the server (eg.
* http://www.openstreetmap.org/api/0.5).
*/
public OverpassAPIReader(final double left, final double right,
final double top, final double bottom, final String baseUrl,
final String query) {
String bbox = "(" + Math.min(top, bottom) + "," + Math.min(left, right)
+ "," + Math.max(top, bottom) + "," + Math.max(left, right)
+ ")";
this.query = query.replaceAll("\\{\\{bbox\\}\\}", bbox);
}
/**
* Open a connection to the given url and return a reader on the input
* stream from that connection.
*
* @param pUrlStr The exact url to connect to.
* @return An reader reading the input stream (servers answer) or
* <code>null</code>.
* @throws IOException on io-errors
*/
private InputStream getInputStream(final String pUrlStr) throws IOException {
URL url;
int responseCode;
String encoding;
url = new URL(pUrlStr);
myActiveConnection = (HttpURLConnection) url.openConnection();
myActiveConnection.setRequestProperty("Accept-Encoding",
"gzip, deflate");
responseCode = myActiveConnection.getResponseCode();
if (responseCode != RESPONSECODE_OK) {
String message;
String apiErrorMessage;
apiErrorMessage = myActiveConnection.getHeaderField("Error");
if (apiErrorMessage != null) {
message = "Received API HTTP response code " + responseCode
+ " with message \"" + apiErrorMessage
+ "\" for URL \"" + pUrlStr + "\".";
} else {
message = "Received API HTTP response code " + responseCode
+ " for URL \"" + pUrlStr + "\".";
}
throw new IOException(message);
}
myActiveConnection.setConnectTimeout(TIMEOUT);
encoding = myActiveConnection.getContentEncoding();
responseStream = myActiveConnection.getInputStream();
if (encoding != null && encoding.equalsIgnoreCase("gzip")) {
responseStream = new GZIPInputStream(responseStream);
} else if (encoding != null && encoding.equalsIgnoreCase("deflate")) {
responseStream = new InflaterInputStream(responseStream,
new Inflater(true));
}
return responseStream;
}
class TmpRelation {
Long id;
String type;
String role;
}
private final List<Bound> bounds = new ArrayList<Bound>();
private Map<Long, OsmNode> nodesById = new HashMap<Long, OsmNode>();
private Map<Long, OsmWay> waysById = new HashMap<Long, OsmWay>();
private Map<Long, OsmRelation> relationsById = new HashMap<Long, OsmRelation>();
private Map<OsmRelation, List<TmpRelation>> relationMembersForRelation =
new HashMap<OsmRelation, List<TmpRelation>>();
private final Collection<OsmNode> ownNodes = new ArrayList<OsmNode>(10000);
private final Collection<OsmWay> ownWays = new ArrayList<OsmWay>(1000);
private final Collection<OsmRelation> ownRelations = new ArrayList<OsmRelation>(
100);
public void parse(InputStream in) throws IOException {
JsonFactory jsonFactory = new JsonFactory();
try {
JsonParser jp = jsonFactory.createJsonParser(in);
JsonToken t;
while ((t = jp.nextToken()) != null) {
if (t == JsonToken.START_OBJECT) {
jp.nextToken();
String name = jp.getCurrentName();
jp.nextToken();
if ("type".equals(name)) {
String type = jp.getText();
if ("node".equals(type))
parseNode(jp);
while (jp.nextToken() != JsonToken.END_OBJECT) {
else if ("way".equals(type))
parseWay(jp);
String name = jp.getCurrentName();
jp.nextToken();
else if ("relation".equals(type))
parseRelation(jp);
}
}
}
} catch (JsonParseException e) {
e.printStackTrace();
}
}
private void parseNode(JsonParser jp) throws JsonParseException,
IOException {
long id = 0;
double lat = 0, lon = 0;
TagSet tags = null;
if ("id".equals(name))
id = jp.getLongValue();
while (jp.nextToken() != JsonToken.END_OBJECT) {
else if ("lat".equals(name))
lat = jp.getDoubleValue();
else if ("lon".equals(name))
lon = jp.getDoubleValue();
else if ("tags".equals(name))
tags = parseTags(jp);
}
String name = jp.getCurrentName();
jp.nextToken();
// log("node: "+id + " "+ lat + " " + lon);
OsmNode node = new OsmNode(lat, lon, tags, id);
ownNodes.add(node);
nodesById.put(Long.valueOf(id), node);
}
if ("id".equals(name))
id = jp.getLongValue();
private void parseWay(JsonParser jp) throws JsonParseException, IOException {
else if ("lat".equals(name))
lat = jp.getDoubleValue();
else if ("lon".equals(name))
lon = jp.getDoubleValue();
else if ("tags".equals(name))
tags = parseTags(jp);
}
long id = 0;
TagSet tags = null;
ArrayList<OsmNode> wayNodes = new ArrayList<OsmNode>();
// log("node: "+id + " "+ lat + " " + lon);
OsmNode node = new OsmNode(lat, lon, tags, id);
ownNodes.add(node);
nodesById.put(Long.valueOf(id), node);
}
while (jp.nextToken() != JsonToken.END_OBJECT) {
String name = jp.getCurrentName();
jp.nextToken();
if ("id".equals(name))
id = jp.getLongValue();
private void parseWay(JsonParser jp) throws JsonParseException, IOException {
else if ("nodes".equals(name)) {
while (jp.nextToken() != JsonToken.END_ARRAY) {
Long nodeId = Long.valueOf(jp.getLongValue());
long id = 0;
TagSet tags = null;
ArrayList<OsmNode> wayNodes = new ArrayList<OsmNode>();
OsmNode node = nodesById.get(nodeId);
if (node != null)
// log("missing node " + nodeId);
// else
wayNodes.add(node);
}
} else if ("tags".equals(name))
tags = parseTags(jp);
}
// log("way: "+ id + " " + wayNodes.size());
OsmWay way = new OsmWay(tags, id, wayNodes);
ownWays.add(way);
waysById.put(Long.valueOf(id), way);
}
while (jp.nextToken() != JsonToken.END_OBJECT) {
String name = jp.getCurrentName();
jp.nextToken();
if ("id".equals(name))
id = jp.getLongValue();
private void parseRelation(JsonParser jp) throws JsonParseException,
IOException {
else if ("nodes".equals(name)) {
while (jp.nextToken() != JsonToken.END_ARRAY) {
Long nodeId = Long.valueOf(jp.getLongValue());
long id = 0;
TagSet tags = null;
ArrayList<TmpRelation> members = new ArrayList<TmpRelation>();
OsmNode node = nodesById.get(nodeId);
if (node != null)
// log("missing node " + nodeId);
// else
wayNodes.add(node);
}
} else if ("tags".equals(name))
tags = parseTags(jp);
}
// log("way: "+ id + " " + wayNodes.size());
OsmWay way = new OsmWay(tags, id, wayNodes);
ownWays.add(way);
waysById.put(Long.valueOf(id), way);
}
while (jp.nextToken() != JsonToken.END_OBJECT) {
private void parseRelation(JsonParser jp) throws JsonParseException,
IOException {
String name = jp.getCurrentName();
jp.nextToken();
long id = 0;
TagSet tags = null;
ArrayList<TmpRelation> members = new ArrayList<TmpRelation>();
if ("id".equals(name))
id = jp.getLongValue();
while (jp.nextToken() != JsonToken.END_OBJECT) {
else if ("members".equals(name)) {
while (jp.nextToken() != JsonToken.END_ARRAY) {
TmpRelation member = new TmpRelation();
while (jp.nextToken() != JsonToken.END_OBJECT) {
name = jp.getCurrentName();
jp.nextToken();
if ("type".equals(name))
member.type = jp.getText();
else if ("ref".equals(name))
member.id = Long.valueOf(jp.getLongValue());
else if ("role".equals(name))
member.role = jp.getText();
}
members.add(member);
}
} else if ("tags".equals(name))
tags = parseTags(jp);
}
OsmRelation relation = new OsmRelation(tags, id, members.size());
ownRelations.add(relation);
relationsById.put(Long.valueOf(id), relation);
relationMembersForRelation.put(relation, members);
}
private static TagSet parseTags(JsonParser jp) throws JsonParseException,
IOException {
TagSet tags = null;
while (jp.nextToken() != JsonToken.END_OBJECT) {
String key = jp.getCurrentName();
jp.nextToken();
String val = jp.getText();
if (tags == null)
tags = new TagSet(4);
tags.add(new Tag(key, val, false));
}
return tags;
}
private static void log(String msg) {
System.out.println(msg);
}
public OsmData getData() {
String encoded;
try {
encoded = URLEncoder.encode(this.query, "utf-8");
} catch (UnsupportedEncodingException e1) {
e1.printStackTrace();
return null;
}
System.out.println(myBaseUrl + "?data=" + encoded);
InputStream inputStream = null;
try {
inputStream = getInputStream(myBaseUrl + "?data=[out:json];" + encoded);
parse(inputStream);
} catch (IOException e) {
e.printStackTrace();
} finally {
if (inputStream != null)
try {
inputStream.close();
} catch (IOException e) {
//...
}
inputStream = null;
}
for (Entry<OsmRelation, List<TmpRelation>> entry : relationMembersForRelation
.entrySet()) {
OsmRelation relation = entry.getKey();
for (TmpRelation member : entry.getValue()) {
OsmElement memberObject = null;
if ("node".equals(member)) {
memberObject = nodesById.get(member.id);
} else if ("way".equals(member)) {
memberObject = waysById.get(member.id);
} else if ("relation".equals(member)) {
memberObject = relationsById.get(member.id);
} else {
// log("missing relation " + member.id);
continue;
}
if (memberObject != null) {
OsmMember ownMember = new OsmMember(member.role,
memberObject);
relation.relationMembers.add(ownMember);
}
}
}
log("nodes: " + ownNodes.size() + " ways: " + ownWays.size()
+ " relations: " + ownRelations.size());
// give up references to original collections
nodesById = null;
waysById = null;
relationsById = null;
relationMembersForRelation = null;
return new OsmData(bounds, ownNodes, ownWays, ownRelations);
}
String name = jp.getCurrentName();
jp.nextToken();
if ("id".equals(name))
id = jp.getLongValue();
else if ("members".equals(name)) {
while (jp.nextToken() != JsonToken.END_ARRAY) {
TmpRelation member = new TmpRelation();
while (jp.nextToken() != JsonToken.END_OBJECT) {
name = jp.getCurrentName();
jp.nextToken();
if ("type".equals(name))
member.type = jp.getText();
else if ("ref".equals(name))
member.id = Long.valueOf(jp.getLongValue());
else if ("role".equals(name))
member.role = jp.getText();
}
members.add(member);
}
} else if ("tags".equals(name))
tags = parseTags(jp);
}
OsmRelation relation = new OsmRelation(tags, id, members.size());
ownRelations.add(relation);
relationsById.put(Long.valueOf(id), relation);
relationMembersForRelation.put(relation, members);
}
private static TagSet parseTags(JsonParser jp) throws JsonParseException,
IOException {
TagSet tags = null;
while (jp.nextToken() != JsonToken.END_OBJECT) {
String key = jp.getCurrentName();
jp.nextToken();
String val = jp.getText();
if (tags == null)
tags = new TagSet(4);
tags.add(new Tag(key, val, false));
}
return tags;
}
private static void log(String msg) {
System.out.println(msg);
}
public OsmData getData() {
String encoded;
try {
encoded = URLEncoder.encode(this.query, "utf-8");
} catch (UnsupportedEncodingException e1) {
e1.printStackTrace();
return null;
}
System.out.println(myBaseUrl + "?data=" + encoded);
InputStream inputStream = null;
try {
inputStream = getInputStream(myBaseUrl + "?data=[out:json];" + encoded);
parse(inputStream);
} catch (IOException e) {
e.printStackTrace();
} finally {
if (inputStream != null)
try {
inputStream.close();
} catch (IOException e) {
//...
}
inputStream = null;
}
for (Entry<OsmRelation, List<TmpRelation>> entry : relationMembersForRelation
.entrySet()) {
OsmRelation relation = entry.getKey();
for (TmpRelation member : entry.getValue()) {
OsmElement memberObject = null;
if ("node".equals(member)) {
memberObject = nodesById.get(member.id);
} else if ("way".equals(member)) {
memberObject = waysById.get(member.id);
} else if ("relation".equals(member)) {
memberObject = relationsById.get(member.id);
} else {
// log("missing relation " + member.id);
continue;
}
if (memberObject != null) {
OsmMember ownMember = new OsmMember(member.role,
memberObject);
relation.relationMembers.add(ownMember);
}
}
}
log("nodes: " + ownNodes.size() + " ways: " + ownWays.size()
+ " relations: " + ownRelations.size());
// give up references to original collections
nodesById = null;
waysById = null;
relationsById = null;
relationMembersForRelation = null;
return new OsmData(bounds, ownNodes, ownWays, ownRelations);
}
}

View File

@@ -28,357 +28,350 @@ package org.oscim.utils.wkb;
import java.io.Serializable;
/** The base class of all geometries */
/**
* The base class of all geometries
*/
abstract class Geometry implements Serializable {
/* JDK 1.5 Serialization */
private static final long serialVersionUID = 0x100;
/* JDK 1.5 Serialization */
private static final long serialVersionUID = 0x100;
// OpenGIS Geometry types as defined in the OGC WKB Spec
// (May we replace this with an ENUM as soon as JDK 1.5
// has gained widespread usage?)
// OpenGIS Geometry types as defined in the OGC WKB Spec
// (May we replace this with an ENUM as soon as JDK 1.5
// has gained widespread usage?)
/** Fake type for linear ring */
static final int LINEARRING = 0;
/**
* The OGIS geometry type number for points.
*/
static final int POINT = 1;
/**
* Fake type for linear ring
*/
static final int LINEARRING = 0;
/**
* The OGIS geometry type number for points.
*/
static final int POINT = 1;
/**
* The OGIS geometry type number for lines.
*/
static final int LINESTRING = 2;
/**
* The OGIS geometry type number for lines.
*/
static final int LINESTRING = 2;
/**
* The OGIS geometry type number for polygons.
*/
static final int POLYGON = 3;
/**
* The OGIS geometry type number for polygons.
*/
static final int POLYGON = 3;
/**
* The OGIS geometry type number for aggregate points.
*/
static final int MULTIPOINT = 4;
/**
* The OGIS geometry type number for aggregate points.
*/
static final int MULTIPOINT = 4;
/**
* The OGIS geometry type number for aggregate lines.
*/
static final int MULTILINESTRING = 5;
/**
* The OGIS geometry type number for aggregate lines.
*/
static final int MULTILINESTRING = 5;
/**
* The OGIS geometry type number for aggregate polygons.
*/
static final int MULTIPOLYGON = 6;
/**
* The OGIS geometry type number for aggregate polygons.
*/
static final int MULTIPOLYGON = 6;
/**
* The OGIS geometry type number for feature collections.
*/
static final int GEOMETRYCOLLECTION = 7;
/**
* The OGIS geometry type number for feature collections.
*/
static final int GEOMETRYCOLLECTION = 7;
static final String[] ALLTYPES = new String[] {
"", // internally used LinearRing does not have any text in front of
// it
"POINT", "LINESTRING", "POLYGON", "MULTIPOINT", "MULTILINESTRING",
"MULTIPOLYGON", "GEOMETRYCOLLECTION" };
static final String[] ALLTYPES = new String[]{
"", // internally used LinearRing does not have any text in front of
// it
"POINT", "LINESTRING", "POLYGON", "MULTIPOINT", "MULTILINESTRING",
"MULTIPOLYGON", "GEOMETRYCOLLECTION"};
/**
* The Text representations of the geometry types
*
* @param type
* ...
* @return ...
*/
static String getTypeString(int type) {
if (type >= 0 && type <= 7)
return ALLTYPES[type];
/**
* The Text representations of the geometry types
*
* @param type ...
* @return ...
*/
static String getTypeString(int type) {
if (type >= 0 && type <= 7)
return ALLTYPES[type];
throw new IllegalArgumentException("Unknown Geometry type" + type);
throw new IllegalArgumentException("Unknown Geometry type" + type);
}
}
// Properties common to all geometries
/**
* The dimensionality of this feature (2,3)
*/
int dimension;
// Properties common to all geometries
/**
* The dimensionality of this feature (2,3)
*/
int dimension;
/**
* Do we have a measure (4th dimension)
*/
boolean haveMeasure = false;
/**
* Do we have a measure (4th dimension)
*/
boolean haveMeasure = false;
/**
* The OGIS geometry type of this feature. this is final as it never
* changes, it is bound to the subclass of the
* instance.
*/
final int type;
/**
* The OGIS geometry type of this feature. this is final as it never
* changes, it is bound to the subclass of the
* instance.
*/
final int type;
/**
* Official UNKNOWN srid value
*/
final static int UNKNOWN_SRID = 0;
/**
* Official UNKNOWN srid value
*/
final static int UNKNOWN_SRID = 0;
/**
* The spacial reference system id of this geometry, default is no srid
*/
int srid = UNKNOWN_SRID;
/**
* The spacial reference system id of this geometry, default is no srid
*/
int srid = UNKNOWN_SRID;
/**
* Parse a SRID value, anything <= 0 is unknown
*
* @param srid
* ...
* @return ...
*/
static int parseSRID(int srid) {
if (srid < 0) {
/* TODO: raise a warning ? */
return 0;
}
return srid;
}
/**
* Parse a SRID value, anything <= 0 is unknown
*
* @param srid ...
* @return ...
*/
static int parseSRID(int srid) {
if (srid < 0) {
/* TODO: raise a warning ? */
return 0;
}
return srid;
}
/**
* Constructor for subclasses
*
* @param type
* has to be given by all subclasses.
*/
protected Geometry(int type) {
this.type = type;
}
/**
* Constructor for subclasses
*
* @param type has to be given by all subclasses.
*/
protected Geometry(int type) {
this.type = type;
}
/**
* java.lang.Object hashCode implementation
*/
@Override
public int hashCode() {
return dimension | (type * 4) | (srid * 32);
}
/**
* java.lang.Object hashCode implementation
*/
@Override
public int hashCode() {
return dimension | (type * 4) | (srid * 32);
}
/**
* java.lang.Object equals implementation
*/
@Override
public boolean equals(Object other) {
return (other != null) && (other instanceof Geometry)
&& equals((Geometry) other);
}
/**
* java.lang.Object equals implementation
*/
@Override
public boolean equals(Object other) {
return (other != null) && (other instanceof Geometry)
&& equals((Geometry) other);
}
/**
* geometry specific equals implementation - only defined for non-null
* values
*
* @param other
* ...
* @return ...
*/
public boolean equals(Geometry other) {
return (other != null) && (this.dimension == other.dimension)
&& (this.type == other.type) && (this.srid == other.srid)
&& (this.haveMeasure == other.haveMeasure)
&& other.getClass().equals(this.getClass())
&& this.equalsintern(other);
}
/**
* geometry specific equals implementation - only defined for non-null
* values
*
* @param other ...
* @return ...
*/
public boolean equals(Geometry other) {
return (other != null) && (this.dimension == other.dimension)
&& (this.type == other.type) && (this.srid == other.srid)
&& (this.haveMeasure == other.haveMeasure)
&& other.getClass().equals(this.getClass())
&& this.equalsintern(other);
}
/**
* Whether test coordinates for geometry - subclass specific code
* Implementors can assume that dimensin, type, srid
* and haveMeasure are equal, other != null and other is the same subclass.
*
* @param other
* ...
* @return ...
*/
protected abstract boolean equalsintern(Geometry other);
/**
* Whether test coordinates for geometry - subclass specific code
* Implementors can assume that dimensin, type, srid
* and haveMeasure are equal, other != null and other is the same subclass.
*
* @param other ...
* @return ...
*/
protected abstract boolean equalsintern(Geometry other);
/**
* Return the number of Points of the geometry
*
* @return ...
*/
abstract int numPoints();
/**
* Return the number of Points of the geometry
*
* @return ...
*/
abstract int numPoints();
/**
* Get the nth Point of the geometry
*
* @param n
* the index of the point, from 0 to numPoints()-1;
* @throws ArrayIndexOutOfBoundsException
* in case of an emtpy geometry or bad index.
*/
// abstract Point getPoint(int n);
/**
* Get the nth Point of the geometry
*
* @param n
* the index of the point, from 0 to numPoints()-1;
* @throws ArrayIndexOutOfBoundsException
* in case of an emtpy geometry or bad index.
*/
// abstract Point getPoint(int n);
//
// /**
// * Same as getPoint(0);
// */
// abstract Point getFirstPoint();
//
// /**
// * Same as getPoint(numPoints()-1);
// */
// abstract Point getLastPoint();
//
// /**
// * Same as getPoint(0);
// */
// abstract Point getFirstPoint();
//
// /**
// * Same as getPoint(numPoints()-1);
// */
// abstract Point getLastPoint();
/**
* The OGIS geometry type number of this geometry.
*
* @return ...
*/
int getType() {
return this.type;
}
/**
* The OGIS geometry type number of this geometry.
*
* @return ...
*/
int getType() {
return this.type;
}
/**
* Return the Type as String
*
* @return ...
*/
String getTypeString() {
return getTypeString(this.type);
}
/**
* Return the Type as String
*
* @return ...
*/
String getTypeString() {
return getTypeString(this.type);
}
/**
* Returns whether we have a measure
*
* @return ....
*/
boolean isMeasured() {
return haveMeasure;
}
/**
* Returns whether we have a measure
*
* @return ....
*/
boolean isMeasured() {
return haveMeasure;
}
/**
* Queries the number of geometric dimensions of this geometry. This does
* not include measures, as opposed to the
* server.
*
* @return The dimensionality (eg, 2D or 3D) of this geometry.
*/
int getDimension() {
return this.dimension;
}
/**
* Queries the number of geometric dimensions of this geometry. This does
* not include measures, as opposed to the
* server.
*
* @return The dimensionality (eg, 2D or 3D) of this geometry.
*/
int getDimension() {
return this.dimension;
}
/**
* The OGIS geometry type number of this geometry.
*
* @return ...
*/
int getSrid() {
return this.srid;
}
/**
* The OGIS geometry type number of this geometry.
*
* @return ...
*/
int getSrid() {
return this.srid;
}
/**
* Recursively sets the srid on this geometry and all contained
* subgeometries
*
* @param srid
* ...
*/
void setSrid(int srid) {
this.srid = srid;
}
/**
* Recursively sets the srid on this geometry and all contained
* subgeometries
*
* @param srid ...
*/
void setSrid(int srid) {
this.srid = srid;
}
@Override
public String toString() {
StringBuffer sb = new StringBuffer();
if (srid != UNKNOWN_SRID) {
sb.append("SRID=");
sb.append(srid);
sb.append(';');
}
outerWKT(sb, true);
return sb.toString();
}
@Override
public String toString() {
StringBuffer sb = new StringBuffer();
if (srid != UNKNOWN_SRID) {
sb.append("SRID=");
sb.append(srid);
sb.append(';');
}
outerWKT(sb, true);
return sb.toString();
}
/**
* Render the WKT version of this Geometry (without SRID) into the given
* StringBuffer.
*
* @param sb
* ...
* @param putM
* ...
*/
void outerWKT(StringBuffer sb, boolean putM) {
sb.append(getTypeString());
if (putM && haveMeasure && dimension == 2) {
sb.append('M');
}
mediumWKT(sb);
}
/**
* Render the WKT version of this Geometry (without SRID) into the given
* StringBuffer.
*
* @param sb ...
* @param putM ...
*/
void outerWKT(StringBuffer sb, boolean putM) {
sb.append(getTypeString());
if (putM && haveMeasure && dimension == 2) {
sb.append('M');
}
mediumWKT(sb);
}
final void outerWKT(StringBuffer sb) {
outerWKT(sb, true);
}
final void outerWKT(StringBuffer sb) {
outerWKT(sb, true);
}
/**
* Render the WKT without the type name, but including the brackets into the
* StringBuffer
*
* @param sb
* ...
*/
protected void mediumWKT(StringBuffer sb) {
sb.append('(');
innerWKT(sb);
sb.append(')');
}
/**
* Render the WKT without the type name, but including the brackets into the
* StringBuffer
*
* @param sb ...
*/
protected void mediumWKT(StringBuffer sb) {
sb.append('(');
innerWKT(sb);
sb.append(')');
}
/**
* Render the "inner" part of the WKT (inside the brackets) into the
* StringBuffer.
*
* @param SB
* ...
*/
protected abstract void innerWKT(StringBuffer SB);
/**
* Render the "inner" part of the WKT (inside the brackets) into the
* StringBuffer.
*
* @param SB ...
*/
protected abstract void innerWKT(StringBuffer SB);
/**
* backwards compatibility method
*
* @return ...
*/
String getValue() {
StringBuffer sb = new StringBuffer();
mediumWKT(sb);
return sb.toString();
}
/**
* backwards compatibility method
*
* @return ...
*/
String getValue() {
StringBuffer sb = new StringBuffer();
mediumWKT(sb);
return sb.toString();
}
/**
* Do some internal consistency checks on the geometry. Currently, all
* Geometries must have a valid dimension (2 or
* 3) and a valid type. 2-dimensional Points must have Z=0.0, as well as
* non-measured Points must have m=0.0.
* Composed geometries must have all equal SRID, dimensionality and
* measures, as well as that they do not contain
* NULL or inconsistent subgeometries. BinaryParser and WKTParser should
* only generate consistent geometries.
* BinaryWriter may produce invalid results on inconsistent geometries.
*
* @return true if all checks are passed.
*/
boolean checkConsistency() {
return (dimension >= 2 && dimension <= 3) && (type >= 0 && type <= 7);
}
/**
* Do some internal consistency checks on the geometry. Currently, all
* Geometries must have a valid dimension (2 or
* 3) and a valid type. 2-dimensional Points must have Z=0.0, as well as
* non-measured Points must have m=0.0.
* Composed geometries must have all equal SRID, dimensionality and
* measures, as well as that they do not contain
* NULL or inconsistent subgeometries. BinaryParser and WKTParser should
* only generate consistent geometries.
* BinaryWriter may produce invalid results on inconsistent geometries.
*
* @return true if all checks are passed.
*/
boolean checkConsistency() {
return (dimension >= 2 && dimension <= 3) && (type >= 0 && type <= 7);
}
/**
* Splits the SRID=4711; part of a EWKT rep if present and sets the srid.
*
* @param value
* ...
* @return value without the SRID=4711; part
*/
protected String initSRID(String value) {
String v = value.trim();
if (v.startsWith("SRID=")) {
int index = v.indexOf(';', 5); // sridprefix length is 5
if (index == -1) {
throw new IllegalArgumentException(
"Error parsing Geometry - SRID not delimited with ';' ");
}
this.srid = Integer.parseInt(v.substring(5, index));
return v.substring(index + 1).trim();
}
return v;
}
/**
* Splits the SRID=4711; part of a EWKT rep if present and sets the srid.
*
* @param value ...
* @return value without the SRID=4711; part
*/
protected String initSRID(String value) {
String v = value.trim();
if (v.startsWith("SRID=")) {
int index = v.indexOf(';', 5); // sridprefix length is 5
if (index == -1) {
throw new IllegalArgumentException(
"Error parsing Geometry - SRID not delimited with ';' ");
}
this.srid = Integer.parseInt(v.substring(5, index));
return v.substring(index + 1).trim();
}
return v;
}
}

View File

@@ -25,115 +25,113 @@
package org.oscim.utils.wkb;
abstract class ValueGetter {
byte[] data;
int position;
final byte endian;
byte[] data;
int position;
final byte endian;
ValueGetter(byte[] data, byte endian) {
this.data = data;
ValueGetter(byte[] data, byte endian) {
this.data = data;
this.endian = endian;
}
this.endian = endian;
}
/**
* Get a byte, should be equal for all endians
*
* @return ...
*/
byte getByte() {
return data[position++];
}
/**
* Get a byte, should be equal for all endians
*
* @return ...
*/
byte getByte() {
return data[position++];
}
int getInt() {
int res = getInt(position);
position += 4;
return res;
}
int getInt() {
int res = getInt(position);
position += 4;
return res;
}
long getLong() {
long res = getLong(position);
position += 8;
return res;
}
long getLong() {
long res = getLong(position);
position += 8;
return res;
}
/**
* Get a 32-Bit integer
*
* @param index
* ...
* @return ...
*/
protected abstract int getInt(int index);
/**
* Get a 32-Bit integer
*
* @param index ...
* @return ...
*/
protected abstract int getInt(int index);
/**
* Get a long value. This is not needed directly, but as a nice side-effect
* from GetDouble.
*
* @param index
* ...
* @return ...
*/
protected abstract long getLong(int index);
/**
* Get a long value. This is not needed directly, but as a nice side-effect
* from GetDouble.
*
* @param index ...
* @return ...
*/
protected abstract long getLong(int index);
/**
* Get a double.
*
* @return ...
*/
double getDouble() {
long bitrep = getLong();
return Double.longBitsToDouble(bitrep);
}
/**
* Get a double.
*
* @return ...
*/
double getDouble() {
long bitrep = getLong();
return Double.longBitsToDouble(bitrep);
}
static class XDR extends ValueGetter {
static final byte NUMBER = 0;
static class XDR extends ValueGetter {
static final byte NUMBER = 0;
XDR(byte[] data) {
super(data, NUMBER);
}
XDR(byte[] data) {
super(data, NUMBER);
}
@Override
protected int getInt(int index) {
return ((data[index] & 0xFF) << 24) + ((data[index + 1] & 0xFF) << 16)
+ ((data[index + 2] & 0xFF) << 8) + (data[index + 3] & 0xFF);
}
@Override
protected int getInt(int index) {
return ((data[index] & 0xFF) << 24) + ((data[index + 1] & 0xFF) << 16)
+ ((data[index + 2] & 0xFF) << 8) + (data[index + 3] & 0xFF);
}
@Override
protected long getLong(int index) {
@Override
protected long getLong(int index) {
return ((long) (data[index] & 0xFF) << 56) | ((long) (data[index + 1] & 0xFF) << 48)
| ((long) (data[index + 2] & 0xFF) << 40)
| ((long) (data[index + 3] & 0xFF) << 32)
| ((long) (data[index + 4] & 0xFF) << 24)
| ((long) (data[index + 5] & 0xFF) << 16)
| ((long) (data[index + 6] & 0xFF) << 8)
| ((long) (data[index + 7] & 0xFF) << 0);
}
}
return ((long) (data[index] & 0xFF) << 56) | ((long) (data[index + 1] & 0xFF) << 48)
| ((long) (data[index + 2] & 0xFF) << 40)
| ((long) (data[index + 3] & 0xFF) << 32)
| ((long) (data[index + 4] & 0xFF) << 24)
| ((long) (data[index + 5] & 0xFF) << 16)
| ((long) (data[index + 6] & 0xFF) << 8)
| ((long) (data[index + 7] & 0xFF) << 0);
}
}
static class NDR extends ValueGetter {
static final byte NUMBER = 1;
static class NDR extends ValueGetter {
static final byte NUMBER = 1;
NDR(byte[] data) {
super(data, NUMBER);
}
NDR(byte[] data) {
super(data, NUMBER);
}
@Override
protected int getInt(int index) {
return ((data[index + 3] & 0xFF) << 24) + ((data[index + 2] & 0xFF) << 16)
+ ((data[index + 1] & 0xFF) << 8) + (data[index] & 0xFF);
}
@Override
protected int getInt(int index) {
return ((data[index + 3] & 0xFF) << 24) + ((data[index + 2] & 0xFF) << 16)
+ ((data[index + 1] & 0xFF) << 8) + (data[index] & 0xFF);
}
@Override
protected long getLong(int index) {
return ((long) (data[index + 7] & 0xFF) << 56)
| ((long) (data[index + 6] & 0xFF) << 48)
| ((long) (data[index + 5] & 0xFF) << 40)
| ((long) (data[index + 4] & 0xFF) << 32)
| ((long) (data[index + 3] & 0xFF) << 24)
| ((long) (data[index + 2] & 0xFF) << 16)
| ((long) (data[index + 1] & 0xFF) << 8) | ((long) (data[index] & 0xFF) << 0);
@Override
protected long getLong(int index) {
return ((long) (data[index + 7] & 0xFF) << 56)
| ((long) (data[index + 6] & 0xFF) << 48)
| ((long) (data[index + 5] & 0xFF) << 40)
| ((long) (data[index + 4] & 0xFF) << 32)
| ((long) (data[index + 3] & 0xFF) << 24)
| ((long) (data[index + 2] & 0xFF) << 16)
| ((long) (data[index + 1] & 0xFF) << 8) | ((long) (data[index] & 0xFF) << 0);
}
}
}
}
}

View File

@@ -20,257 +20,255 @@ import org.oscim.core.GeometryBuffer;
import org.oscim.core.Tile;
public class WKBReader {
public interface Callback {
public void process(GeometryBuffer geom);
}
public interface Callback {
public void process(GeometryBuffer geom);
}
private final GeometryBuffer mGeom;
private final boolean mFlipY;
private final GeometryBuffer mGeom;
private final boolean mFlipY;
private WKBReader.Callback mCallback;
private WKBReader.Callback mCallback;
public WKBReader(GeometryBuffer geom, boolean flipY) {
mGeom = geom;
mFlipY = flipY;
}
public WKBReader(GeometryBuffer geom, boolean flipY) {
mGeom = geom;
mFlipY = flipY;
}
public void setCallback(WKBReader.Callback cb) {
mCallback = cb;
}
public void setCallback(WKBReader.Callback cb) {
mCallback = cb;
}
/**
* Parse a binary encoded geometry.
*/
public void parse(byte[] value) {
parseGeometry(valueGetterForEndian(value), 0);
}
/**
* 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 a hex encoded geometry.
*/
public void parse(String value) {
byte[] b = hexStringToByteArray(value);
if (b == null)
return;
parse(b);
}
parse(b);
}
private void parseGeometry(ValueGetter data, int count) {
byte endian = data.getByte(); // skip and test endian flag
if (endian != data.endian) {
throw new IllegalArgumentException("Endian inconsistency!");
}
int typeword = data.getInt();
private void parseGeometry(ValueGetter data, int count) {
byte endian = data.getByte(); // skip and test endian flag
if (endian != data.endian) {
throw new IllegalArgumentException("Endian inconsistency!");
}
int typeword = data.getInt();
int realtype = typeword & 0x1FFFFFFF; // cut off high flag bits
int realtype = typeword & 0x1FFFFFFF; // cut off high flag bits
boolean haveZ = (typeword & 0x80000000) != 0;
boolean haveM = (typeword & 0x40000000) != 0;
boolean haveS = (typeword & 0x20000000) != 0;
boolean haveZ = (typeword & 0x80000000) != 0;
boolean haveM = (typeword & 0x40000000) != 0;
boolean haveS = (typeword & 0x20000000) != 0;
// int srid = Geometry.UNKNOWN_SRID;
if (haveS) {
// srid = Geometry.parseSRID(data.getInt());
data.getInt();
}
switch (realtype) {
case Geometry.POINT:
mGeom.startPoints();
parsePoint(data, haveZ, haveM);
break;
case Geometry.LINESTRING:
mGeom.startLine();
parseLineString(data, haveZ, haveM);
break;
case Geometry.POLYGON:
mGeom.startPolygon();
parsePolygon(data, haveZ, haveM);
break;
case Geometry.MULTIPOINT:
mGeom.startPoints();
parseMultiPoint(data);
break;
case Geometry.MULTILINESTRING:
mGeom.startLine();
parseMultiLineString(data);
break;
case Geometry.MULTIPOLYGON:
mGeom.startPolygon();
parseMultiPolygon(data);
break;
case Geometry.GEOMETRYCOLLECTION:
parseCollection(data);
break;
default:
throw new IllegalArgumentException("Unknown Geometry Type: " + realtype);
}
// int srid = Geometry.UNKNOWN_SRID;
if (haveS) {
// srid = Geometry.parseSRID(data.getInt());
data.getInt();
}
switch (realtype) {
case Geometry.POINT:
mGeom.startPoints();
parsePoint(data, haveZ, haveM);
break;
case Geometry.LINESTRING:
mGeom.startLine();
parseLineString(data, haveZ, haveM);
break;
case Geometry.POLYGON:
mGeom.startPolygon();
parsePolygon(data, haveZ, haveM);
break;
case Geometry.MULTIPOINT:
mGeom.startPoints();
parseMultiPoint(data);
break;
case Geometry.MULTILINESTRING:
mGeom.startLine();
parseMultiLineString(data);
break;
case Geometry.MULTIPOLYGON:
mGeom.startPolygon();
parseMultiPolygon(data);
break;
case Geometry.GEOMETRYCOLLECTION:
parseCollection(data);
break;
default:
throw new IllegalArgumentException("Unknown Geometry Type: " + realtype);
}
if (count == 0) {
mCallback.process(mGeom);
if (count == 0) {
mCallback.process(mGeom);
mGeom.clear();
}
// if (srid != Geometry.UNKNOWN_SRID) {
// result.setSrid(srid);
// }
}
mGeom.clear();
}
// if (srid != Geometry.UNKNOWN_SRID) {
// result.setSrid(srid);
// }
}
private void parsePoint(ValueGetter data, boolean haveZ, boolean haveM) {
private void parsePoint(ValueGetter data, boolean haveZ, boolean haveM) {
float x = (float) data.getDouble();
float y = (float) data.getDouble();
if (mFlipY)
y = Tile.SIZE - y;
float x = (float) data.getDouble();
float y = (float) data.getDouble();
if (mFlipY)
y = Tile.SIZE - y;
mGeom.addPoint(x, y);
mGeom.addPoint(x, y);
if (haveZ)
data.getDouble();
if (haveZ)
data.getDouble();
if (haveM)
data.getDouble();
}
if (haveM)
data.getDouble();
}
/**
* Parse an Array of "full" Geometries
*
* @param data
* ...
* @param count
* ...
*/
private void parseGeometryArray(ValueGetter data, int count, int type) {
mGeom.clear();
/**
* Parse an Array of "full" Geometries
*
* @param data ...
* @param count ...
*/
private void parseGeometryArray(ValueGetter data, int count, int type) {
mGeom.clear();
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);
// mGeom.index[++mGeom.indexPos] = -1;
}
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);
// mGeom.index[++mGeom.indexPos] = -1;
}
mCallback.process(mGeom);
mGeom.clear();
}
mCallback.process(mGeom);
mGeom.clear();
}
private void parseMultiPoint(ValueGetter data) {
parseGeometryArray(data, data.getInt(), Geometry.POINT);
}
private void parseMultiPoint(ValueGetter data) {
parseGeometryArray(data, data.getInt(), Geometry.POINT);
}
private void parseLineString(ValueGetter data, boolean haveZ, boolean haveM) {
private void parseLineString(ValueGetter data, boolean haveZ, boolean haveM) {
int count = data.getInt();
int count = data.getInt();
for (int i = 0; i < count; i++) {
float x = (float) data.getDouble();
float y = (float) data.getDouble();
for (int i = 0; i < count; i++) {
float x = (float) data.getDouble();
float y = (float) data.getDouble();
if (mFlipY)
y = Tile.SIZE - y;
if (mFlipY)
y = Tile.SIZE - y;
mGeom.addPoint(x, y);
mGeom.addPoint(x, y);
// ignore
if (haveZ)
data.getDouble();
if (haveM)
data.getDouble();
}
}
// ignore
if (haveZ)
data.getDouble();
if (haveM)
data.getDouble();
}
}
private void parsePolygon(ValueGetter data, boolean haveZ, boolean haveM) {
int count = data.getInt();
private void parsePolygon(ValueGetter data, boolean haveZ, boolean haveM) {
int count = data.getInt();
for (int i = 0; i < count; i++) {
for (int i = 0; i < count; i++) {
if (i > 0)
mGeom.startHole();
if (i > 0)
mGeom.startHole();
int points = data.getInt();
int points = data.getInt();
for (int j = 0; j < points; j++) {
float x = (float) data.getDouble();
float y = (float) data.getDouble();
for (int j = 0; j < points; j++) {
float x = (float) data.getDouble();
float y = (float) data.getDouble();
if (mFlipY)
y = Tile.SIZE - y;
if (mFlipY)
y = Tile.SIZE - y;
// drop redundant closing point
if (j < points - 1)
mGeom.addPoint(x, y);
// drop redundant closing point
if (j < points - 1)
mGeom.addPoint(x, y);
// ignore
if (haveZ)
data.getDouble();
if (haveM)
data.getDouble();
}
}
}
// ignore
if (haveZ)
data.getDouble();
if (haveM)
data.getDouble();
}
}
}
private void parseMultiLineString(ValueGetter data) {
private void parseMultiLineString(ValueGetter data) {
int count = data.getInt();
if (count <= 0)
return;
int count = data.getInt();
if (count <= 0)
return;
parseGeometryArray(data, count, Geometry.LINESTRING);
}
parseGeometryArray(data, count, Geometry.LINESTRING);
}
private void parseMultiPolygon(ValueGetter data) {
int count = data.getInt();
if (count <= 0)
return;
private void parseMultiPolygon(ValueGetter data) {
int count = data.getInt();
if (count <= 0)
return;
parseGeometryArray(data, count, Geometry.POLYGON);
}
parseGeometryArray(data, count, Geometry.POLYGON);
}
private void parseCollection(ValueGetter data) {
int count = data.getInt();
private void parseCollection(ValueGetter data) {
int count = data.getInt();
parseGeometryArray(data, count, Geometry.GEOMETRYCOLLECTION);
parseGeometryArray(data, count, Geometry.GEOMETRYCOLLECTION);
mCallback.process(mGeom);
mGeom.clear();
}
mCallback.process(mGeom);
mGeom.clear();
}
private static ValueGetter valueGetterForEndian(byte[] bytes) {
if (bytes[0] == ValueGetter.XDR.NUMBER) { // XDR
return new ValueGetter.XDR(bytes);
} else if (bytes[0] == ValueGetter.NDR.NUMBER) {
return new ValueGetter.NDR(bytes);
} else {
throw new IllegalArgumentException("Unknown Endian type:" + bytes[0]);
}
}
private static ValueGetter valueGetterForEndian(byte[] bytes) {
if (bytes[0] == ValueGetter.XDR.NUMBER) { // XDR
return new ValueGetter.XDR(bytes);
} else if (bytes[0] == ValueGetter.NDR.NUMBER) {
return new ValueGetter.NDR(bytes);
} else {
throw new IllegalArgumentException("Unknown Endian type:" + bytes[0]);
}
}
/**
* 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) {
/**
* Converting a string of hex character to bytes
* <p/>
* 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;
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;
}
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;
}
}