use WayData container to pass geometry and tags to TileGenerator

This commit is contained in:
Hannes Janetzek 2013-04-02 11:21:13 +02:00
parent bef8e125fb
commit b7ca00ae8f
8 changed files with 152 additions and 85 deletions

View File

@ -25,6 +25,35 @@ import org.oscim.database.mapfile.MapDatabase;
* references to any arrays after callback function returns.
*/
public interface IMapDatabaseCallback {
public class WayData{
public WayData(){
}
public WayData(GeometryBuffer geom, Tag[] tags) {
this.geom = geom;
this.tags = tags;
}
public GeometryBuffer geom;
// closed == geometry is polygon
public boolean closed;
// osm layer of the way.
public int layer;
// osm tags of the way.
public Tag[] tags;
// building tags
public int height;
public int minHeight;
// unused
public int priority;
}
/**
* Renders a single point of interest node (POI).
*
@ -32,10 +61,6 @@ public interface IMapDatabaseCallback {
* the layer of the node.
* @param tags
* the tags of the node.
* @param latitude
* the latitude of the node.
* @param longitude
* the longitude of the node.
*/
void renderPOI(byte layer, Tag[] tags, GeometryBuffer geom);
@ -45,23 +70,10 @@ public interface IMapDatabaseCallback {
void renderWaterBackground();
/**
* Renders a single way or area (closed way).
* Renders a single way or area.
*
* @param layer
* the osm layer of the way.
* @param tags
* the tags of the way.
* @param wayNodes
* the geographical coordinates of the way nodes in the order
* longitude/latitude or x/y depending on the projection.
* @param wayLength
* length of way data in wayNodes
* @param closed
* wheter the way is an polygon.
* @param prio TODO
*/
void renderWay(byte layer, Tag[] tags, GeometryBuffer geom,
boolean closed, int prio);
void renderWay(WayData way);
// /**
// * TBD: check if way will be rendered before decoding - MUST be called before renderWay!

View File

@ -979,7 +979,7 @@ public class MapDatabase implements IMapDatabase {
&& mGeom.points[1] == mGeom.points[l - 1];
projectToTile(mGeom.points, mGeom.index);
mapDatabaseCallback.renderWay(layer, curTags, mGeom, closed, 0);
/// FIXME mapDatabaseCallback.renderWay(layer, curTags, mGeom, closed, 0);
}
}

View File

@ -28,6 +28,7 @@ import org.oscim.core.Tag;
import org.oscim.core.Tile;
import org.oscim.database.IMapDatabase;
import org.oscim.database.IMapDatabaseCallback;
import org.oscim.database.IMapDatabaseCallback.WayData;
import org.oscim.database.MapInfo;
import org.oscim.database.MapOptions;
import org.oscim.database.OpenResult;
@ -74,6 +75,8 @@ public class MapDatabase implements IMapDatabase {
private final boolean debug = false;
private LwHttp lwHttp;
private final WayData mWay = new WayData();
@Override
public QueryResult executeQuery(JobTile tile, IMapDatabaseCallback mapDatabaseCallback) {
QueryResult result = QueryResult.SUCCESS;
@ -228,7 +231,9 @@ public class MapDatabase implements IMapDatabase {
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_PRIORITY = 31;
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 short[] mTmpKeys = new short[100];
private final Tag[] mTmpTags = new Tag[20];
@ -335,8 +340,7 @@ public class MapDatabase implements IMapDatabase {
int end = mBytesProcessed + bytes;
int indexCnt = 1;
int layer = 5;
int prio = 0;
//int layer = 5;
boolean skip = false;
boolean fail = false;
@ -347,6 +351,11 @@ public class MapDatabase implements IMapDatabase {
mGeom.index[0] = 2;
}
mWay.layer = 5;
mWay.priority = 0;
mWay.height = 0;
mWay.minHeight = 0;
while (mBytesProcessed < end) {
// read tag and wire type
int val = decodeVarint32();
@ -382,11 +391,19 @@ public class MapDatabase implements IMapDatabase {
break;
case TAG_ELEM_LAYER:
layer = decodeVarint32();
mWay.layer = decodeVarint32();
break;
case TAG_ELEM_HEIGHT:
mWay.height= decodeVarint32();
break;
case TAG_ELEM_MIN_HEIGHT:
mWay.minHeight = decodeVarint32();
break;
case TAG_ELEM_PRIORITY:
prio = decodeVarint32();
mWay.priority = decodeVarint32();
break;
default:
@ -402,15 +419,20 @@ public class MapDatabase implements IMapDatabase {
return false;
}
mWay.geom = mGeom;
mWay.tags = tags;
switch (type) {
case TAG_TILE_LINE:
mMapGenerator.renderWay((byte) layer, tags, mGeom, false, prio);
mWay.closed = false;
mMapGenerator.renderWay(mWay);
break;
case TAG_TILE_POLY:
mMapGenerator.renderWay((byte) layer, tags, mGeom, true, prio);
mWay.closed = true;
mMapGenerator.renderWay(mWay);
break;
case TAG_TILE_POINT:
mMapGenerator.renderPOI((byte) layer, tags, mGeom);
mMapGenerator.renderPOI((byte) mWay.layer, tags, mGeom);
break;
}

View File

@ -41,6 +41,7 @@ import org.oscim.core.Tag;
import org.oscim.core.Tile;
import org.oscim.database.IMapDatabase;
import org.oscim.database.IMapDatabaseCallback;
import org.oscim.database.IMapDatabaseCallback.WayData;
import org.oscim.database.MapInfo;
import org.oscim.database.MapOptions;
import org.oscim.database.OpenResult;
@ -102,6 +103,8 @@ public class MapDatabase implements IMapDatabase {
private static final int MAX_TAGS_CACHE = 100;
private final WayData mWay = new WayData();
private static Map<String, Tag> tagHash = Collections
.synchronizedMap(new LinkedHashMap<String, Tag>(
MAX_TAGS_CACHE, 0.75f, true) {
@ -451,7 +454,12 @@ public class MapDatabase implements IMapDatabase {
if (layer == 0)
layer = 5;
mMapGenerator.renderWay((byte) layer, tags, mGeom, polygon, 0);
mWay.geom = mGeom;
mWay.tags = tags;
mWay.layer = layer;
mWay.closed = polygon;
mMapGenerator.renderWay(mWay);
return true;
}

View File

@ -30,6 +30,7 @@ import org.oscim.core.Tag;
import org.oscim.core.WebMercator;
import org.oscim.database.IMapDatabase;
import org.oscim.database.IMapDatabaseCallback;
import org.oscim.database.IMapDatabaseCallback.WayData;
import org.oscim.database.MapInfo;
import org.oscim.database.MapOptions;
import org.oscim.database.OpenResult;
@ -71,6 +72,9 @@ public class MapDatabase implements IMapDatabase {
new HashMap<Entry<String, String>, Tag>(100);
private PreparedStatement prepQuery = null;
private final WayData mWay = new WayData();
private boolean connect() {
Connection conn = null;
String dburl = "jdbc:postgresql://city.informatik.uni-bremen.de:5432/gis-2.0";
@ -187,7 +191,12 @@ public class MapDatabase implements IMapDatabase {
if (mGeom.index.length > mGeom.indexPos)
mGeom.index[mGeom.indexPos] = -1;
mapDatabaseCallback.renderWay((byte) 0, mTags, mGeom, polygon, 0);
mWay.geom = mGeom;
mWay.tags = mTags;
mWay.layer = 0;
mWay.closed = polygon;
mapDatabaseCallback.renderWay(mWay);
}
}
} catch (SQLException e) {

View File

@ -20,6 +20,7 @@ import org.oscim.core.Tag;
import org.oscim.core.Tile;
import org.oscim.database.IMapDatabase;
import org.oscim.database.IMapDatabaseCallback;
import org.oscim.database.IMapDatabaseCallback.WayData;
import org.oscim.database.MapInfo;
import org.oscim.database.MapOptions;
import org.oscim.database.OpenResult;
@ -51,6 +52,7 @@ public class MapDatabase implements IMapDatabase {
null);
private boolean mOpenFile = false;
private final WayData mWay = new WayData();
@Override
public QueryResult executeQuery(JobTile tile, IMapDatabaseCallback mapDatabaseCallback) {
@ -105,7 +107,12 @@ public class MapDatabase implements IMapDatabase {
index[2] = 10;
index[3] = 0;
mapDatabaseCallback.renderWay((byte) 0, mTags, mGeom, true, 0);
mWay.geom = mGeom;
mWay.tags = mTags;
mWay.layer = (byte)0;
mWay.closed = true;
mapDatabaseCallback.renderWay(mWay);
index[0] = 4;
index[1] = -1;
@ -115,43 +122,43 @@ public class MapDatabase implements IMapDatabase {
points[1] = size / 2;
points[2] = size;
points[3] = size / 2;
mapDatabaseCallback.renderWay((byte) 0, mTagsWay, mGeom, false, 0);
mapDatabaseCallback.renderWay(mWay);
// center up
points[0] = size / 2;
points[1] = -size / 2;
points[2] = size / 2;
points[3] = size / 2;
mapDatabaseCallback.renderWay((byte) 0, mTagsWay, mGeom,
false, 0);
mapDatabaseCallback.renderWay(mWay);
// center down
points[0] = size / 2;
points[1] = size / 2;
points[2] = size / 2;
points[3] = size / 2 + size;
mapDatabaseCallback.renderWay((byte) 0, mTagsWay, mGeom, false, 0);
mapDatabaseCallback.renderWay(mWay);
mWay.layer = (byte)1;
// left-top to center
points[0] = size / 2;
points[1] = size / 2;
points[2] = 10;
points[3] = 10;
mapDatabaseCallback.renderWay((byte) 1, mTagsWay, mGeom, false, 0);
mapDatabaseCallback.renderWay(mWay);
// middle horizontal
points[0] = 0;
points[1] = 10;
points[2] = size;
points[3] = 10;
mapDatabaseCallback.renderWay((byte) 1, mTagsWay, mGeom, false, 0);
mapDatabaseCallback.renderWay(mWay);
// middle horizontal
points[0] = 10;
points[1] = 0;
points[2] = 10;
points[3] = size;
mapDatabaseCallback.renderWay((byte) 1, mTagsWay, mGeom, false, 0);
mapDatabaseCallback.renderWay(mWay);
// lon1 = size / 2;
// lat1 = size / 2;

View File

@ -67,7 +67,7 @@ public class TileGenerator implements IRenderCallback, IMapDatabaseCallback {
public static final byte STROKE_MIN_ZOOM_LEVEL = 12;
public static final byte STROKE_MAX_ZOOM_LEVEL = 17;
private static final Tag[] debugTagBox = { new Tag("debug", "box") };
//private static final Tag[] debugTagBox = ;
private static final Tag[] debugTagWay = { new Tag("debug", "way") };
private static final Tag[] debugTagArea = { new Tag("debug", "area") };
@ -75,10 +75,14 @@ public class TileGenerator implements IRenderCallback, IMapDatabaseCallback {
new float[] { Tile.TILE_SIZE >> 1, 10 },
new short[] { 2 });
private final GeometryBuffer mDebugBox = new GeometryBuffer(
new float[] { 0, 0, 0, Tile.TILE_SIZE, Tile.TILE_SIZE,
Tile.TILE_SIZE, Tile.TILE_SIZE, 0, 0, 0 },
new short[] { 10 });
private final WayData mDebugWay = new WayData(
new GeometryBuffer(
new float[] { 0, 0, 0, Tile.TILE_SIZE,
Tile.TILE_SIZE, Tile.TILE_SIZE,
Tile.TILE_SIZE, 0, 0, 0 },
new short[1]),
new Tag[] { new Tag("debug", "box") }
);
private static RenderTheme renderTheme;
private static int renderLevels;
@ -92,9 +96,8 @@ public class TileGenerator implements IRenderCallback, IMapDatabaseCallback {
// currently processed geometry
private GeometryBuffer mGeom;
private boolean mClosed;
private int mPriority;
private WayData mWay;
// current line layer, will be added to outline layers
private LineLayer mCurLineLayer;
@ -174,12 +177,13 @@ public class TileGenerator implements IRenderCallback, IMapDatabaseCallback {
RenderInstruction[] ri;
ri = renderTheme.matchNode(debugTagWay, (byte) 0);
renderNode(ri, debugTagWay);
// draw tile box
mGeom = mDebugBox;
mGeom.index[0] = (short) (MapView.enableClosePolygons ? 8 : 10);
mDrawingLayer = 10 * renderLevels;
ri = renderTheme.matchWay(debugTagBox, (byte) 0, false);
renderWay(ri, debugTagBox);
mWay = mDebugWay;
mWay.geom.index[0] = (short) (MapView.enableClosePolygons ? 8 : 10);
mDrawingLayer = 100 * renderLevels;
ri = renderTheme.matchWay(mDebugWay.tags, (byte) 0, false);
renderWay(ri, mDebugWay.tags);
}
mTile = null;
@ -188,7 +192,7 @@ public class TileGenerator implements IRenderCallback, IMapDatabaseCallback {
Tag[] mFilterTags = new Tag[1];
private static byte getValidLayer(byte layer) {
private static int getValidLayer(int layer) {
if (layer < 0) {
return 0;
} else if (layer >= LAYERS) {
@ -216,7 +220,6 @@ public class TileGenerator implements IRenderCallback, IMapDatabaseCallback {
mMapDatabase.close();
mMapDatabase = mapDatabase;
//mMapProjection = mMapDatabase.getMapProjection();
}
public IMapDatabase getMapDatabase() {
@ -259,7 +262,6 @@ public class TileGenerator implements IRenderCallback, IMapDatabaseCallback {
@Override
public void renderPOI(byte layer, Tag[] tags, GeometryBuffer geom) {
clearState();
// remove tags that should not be cached in Rendertheme
@ -276,30 +278,28 @@ public class TileGenerator implements IRenderCallback, IMapDatabaseCallback {
}
@Override
public void renderWay(byte layer, Tag[] tags, GeometryBuffer geom,
boolean closed, int prio) {
public void renderWay(WayData way) {
mWay = way;
clearState();
// replace tags that should not be cached in Rendertheme (e.g. name)
if (!filterTags(tags))
if (!filterTags(way.tags))
return;
mDrawingLayer = getValidLayer(layer) * renderLevels;
mDrawingLayer = getValidLayer(way.layer) * renderLevels;
// get render instructions
RenderInstruction[] ri = renderTheme.matchWay(tags,
(byte) (mTile.zoomLevel + 0), closed);
RenderInstruction[] ri = renderTheme.matchWay(way.tags,
(byte) (mTile.zoomLevel + 0), way.closed);
mPriority = prio;
mClosed = closed;
mGeom = geom;
renderWay(ri, tags);
renderWay(ri, way.tags);
if (debug.debugTheme && ri == null)
debugUnmatched(closed, tags);
debugUnmatched(way.closed, way.tags);
mCurLineLayer = null;
mWay = null;
}
private void debugUnmatched(boolean closed, Tag[] tags) {
@ -375,7 +375,7 @@ public class TileGenerator implements IRenderCallback, IMapDatabaseCallback {
return;
}
lineLayer.addLine(mGeom.points, mGeom.index, mClosed);
lineLayer.addLine(mWay.geom.points, mWay.geom.index, mWay.closed);
// keep reference for outline layer
mCurLineLayer = lineLayer;
@ -398,7 +398,7 @@ public class TileGenerator implements IRenderCallback, IMapDatabaseCallback {
lineLayer.width = w;
}
lineLayer.addLine(mGeom.points, mGeom.index);
lineLayer.addLine(mWay.geom.points, mWay.geom.index);
}
}
@ -411,8 +411,7 @@ public class TileGenerator implements IRenderCallback, IMapDatabaseCallback {
if (mTile.layers.extrusionLayers == null)
mTile.layers.extrusionLayers = new ExtrusionLayer(0);
((ExtrusionLayer) mTile.layers.extrusionLayers)
.addBuildings(mGeom.points, mGeom.index, mPriority);
((ExtrusionLayer) mTile.layers.extrusionLayers).addBuildings(mWay);
return;
}
@ -429,7 +428,7 @@ public class TileGenerator implements IRenderCallback, IMapDatabaseCallback {
if (layer.area == null)
layer.area = area;
layer.addPolygon(mGeom.points, mGeom.index);
layer.addPolygon(mWay.geom.points, mWay.geom.index);
}
private String textValueForKey(Text text) {
@ -453,8 +452,8 @@ public class TileGenerator implements IRenderCallback, IMapDatabaseCallback {
if (value == null)
return;
float x = mGeom.points[0];
float y = mGeom.points[1];
float x = mWay.geom.points[0];
float y = mWay.geom.points[1];
mTile.addLabel(TextItem.get().set(x, y, value, text));
}
@ -479,12 +478,12 @@ public class TileGenerator implements IRenderCallback, IMapDatabaseCallback {
return;
int offset = 0;
for (int i = 0, n = mGeom.index.length; i < n; i++) {
int length = mGeom.index[i];
for (int i = 0, n = mWay.geom.index.length; i < n; i++) {
int length = mWay.geom.index[i];
if (length < 4)
break;
WayDecorator.renderText(mClipper, mGeom.points, value, text,
WayDecorator.renderText(mClipper, mWay.geom.points, value, text,
offset, length, mTile);
offset += length;
}

View File

@ -19,6 +19,7 @@ import java.nio.ByteOrder;
import java.nio.ShortBuffer;
import org.oscim.core.Tile;
import org.oscim.database.IMapDatabaseCallback.WayData;
import org.oscim.renderer.BufferObject;
import org.oscim.renderer.GLRenderer;
import org.oscim.utils.LineClipper;
@ -74,7 +75,8 @@ public class ExtrusionLayer extends Layer {
mClipper = new LineClipper(0, 0, Tile.TILE_SIZE, Tile.TILE_SIZE);
}
public void addBuildings(float[] points, short[] index, int height) {
public void addBuildings(WayData way) {
//
// start outer ring
int outer = 0;
@ -82,14 +84,21 @@ public class ExtrusionLayer extends Layer {
boolean simple = true;
int startVertex = mNumVertices;
float height = way.height;
float minHeight = way.minHeight;
// just a guessing to make it look ok
if (height == 0)
height = 10;
height = (int) (height * -Math.log(height / 100000f) * 3.6f);
height = (int) (height * -Math.log(height / 100000f) * 2.0f);
if (minHeight != 0)
minHeight = (int) (minHeight * -Math.log(minHeight / 100000f) * 2.0f);
int length = 0;
for (int ipos = 0, ppos = 0, n = index.length; ipos < n; ipos++, ppos += length) {
length = index[ipos];
for (int ipos = 0, ppos = 0, n = way.geom.index.length; ipos < n; ipos++, ppos += length) {
length = way.geom.index[ipos];
// end marker
if (length < 0)
@ -107,8 +116,8 @@ public class ExtrusionLayer extends Layer {
int len = length;
if (!MapView.enableClosePolygons) {
len -= 2;
} else if (points[ppos] == points[ppos + len - 2]
&& points[ppos + 1] == points[ppos + len - 1]) {
} else if (way.geom.points[ppos] == way.geom.points[ppos + len - 2]
&& way.geom.points[ppos + 1] == way.geom.points[ppos + len - 1]) {
// vector-tile-map does not produce implicty closed
// polygons (yet)
len -= 2;
@ -119,15 +128,15 @@ public class ExtrusionLayer extends Layer {
continue;
// check if polygon contains inner rings
if (simple && (ipos < n - 1) && (index[ipos + 1] > 0))
if (simple && (ipos < n - 1) && (way.geom.index[ipos + 1] > 0))
simple = false;
boolean convex = addOutline(points, ppos, len, height, simple);
boolean convex = addOutline(way.geom.points, ppos, len, minHeight, height, simple);
if (simple && (convex || len <= 8))
addRoofSimple(startVertex, len);
else if (ipos == outer) { // add roof only once
addRoof(startVertex, index, ipos, points, ppos);
addRoof(startVertex, way.geom.index, ipos, way.geom.points, ppos);
}
}
}
@ -183,7 +192,7 @@ public class ExtrusionLayer extends Layer {
}
}
private boolean addOutline(float[] points, int pos, int len, float height,
private boolean addOutline(float[] points, int pos, int len, float minHeight, float height,
boolean convex) {
// add two vertices for last face to make zigzag indices work
@ -191,6 +200,7 @@ public class ExtrusionLayer extends Layer {
int vertexCnt = len + (addFace ? 2 : 0);
short h = (short) height;
short mh = (short) minHeight;
float cx = points[pos + len - 2];
float cy = points[pos + len - 1];
@ -241,7 +251,7 @@ public class ExtrusionLayer extends Layer {
vertices[v + 1] = vertices[v + 5] = (short) (cy * S);
// set height
vertices[v + 2] = 0;
vertices[v + 2] = mh;
vertices[v + 6] = h;
// get direction to next point