Improve code / xml formatting, closes #54
This commit is contained in:
@@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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) {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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) {
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
//}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
@@ -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
@@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -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
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user