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. * references to any arrays after callback function returns.
*/ */
public interface IMapDatabaseCallback { 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). * Renders a single point of interest node (POI).
* *
@ -32,10 +61,6 @@ public interface IMapDatabaseCallback {
* the layer of the node. * the layer of the node.
* @param tags * @param tags
* the tags of the node. * 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); void renderPOI(byte layer, Tag[] tags, GeometryBuffer geom);
@ -45,23 +70,10 @@ public interface IMapDatabaseCallback {
void renderWaterBackground(); 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, void renderWay(WayData way);
boolean closed, int prio);
// /** // /**
// * TBD: check if way will be rendered before decoding - MUST be called before renderWay! // * 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]; && mGeom.points[1] == mGeom.points[l - 1];
projectToTile(mGeom.points, mGeom.index); 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.core.Tile;
import org.oscim.database.IMapDatabase; import org.oscim.database.IMapDatabase;
import org.oscim.database.IMapDatabaseCallback; import org.oscim.database.IMapDatabaseCallback;
import org.oscim.database.IMapDatabaseCallback.WayData;
import org.oscim.database.MapInfo; import org.oscim.database.MapInfo;
import org.oscim.database.MapOptions; import org.oscim.database.MapOptions;
import org.oscim.database.OpenResult; import org.oscim.database.OpenResult;
@ -74,6 +75,8 @@ public class MapDatabase implements IMapDatabase {
private final boolean debug = false; private final boolean debug = false;
private LwHttp lwHttp; private LwHttp lwHttp;
private final WayData mWay = new WayData();
@Override @Override
public QueryResult executeQuery(JobTile tile, IMapDatabaseCallback mapDatabaseCallback) { public QueryResult executeQuery(JobTile tile, IMapDatabaseCallback mapDatabaseCallback) {
QueryResult result = QueryResult.SUCCESS; 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_INDEX = 12;
private static final int TAG_ELEM_COORDS = 13; private static final int TAG_ELEM_COORDS = 13;
private static final int TAG_ELEM_LAYER = 21; 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 short[] mTmpKeys = new short[100];
private final Tag[] mTmpTags = new Tag[20]; private final Tag[] mTmpTags = new Tag[20];
@ -335,8 +340,7 @@ public class MapDatabase implements IMapDatabase {
int end = mBytesProcessed + bytes; int end = mBytesProcessed + bytes;
int indexCnt = 1; int indexCnt = 1;
int layer = 5; //int layer = 5;
int prio = 0;
boolean skip = false; boolean skip = false;
boolean fail = false; boolean fail = false;
@ -347,6 +351,11 @@ public class MapDatabase implements IMapDatabase {
mGeom.index[0] = 2; mGeom.index[0] = 2;
} }
mWay.layer = 5;
mWay.priority = 0;
mWay.height = 0;
mWay.minHeight = 0;
while (mBytesProcessed < end) { while (mBytesProcessed < end) {
// read tag and wire type // read tag and wire type
int val = decodeVarint32(); int val = decodeVarint32();
@ -382,11 +391,19 @@ public class MapDatabase implements IMapDatabase {
break; break;
case TAG_ELEM_LAYER: 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; break;
case TAG_ELEM_PRIORITY: case TAG_ELEM_PRIORITY:
prio = decodeVarint32(); mWay.priority = decodeVarint32();
break; break;
default: default:
@ -402,15 +419,20 @@ public class MapDatabase implements IMapDatabase {
return false; return false;
} }
mWay.geom = mGeom;
mWay.tags = tags;
switch (type) { switch (type) {
case TAG_TILE_LINE: case TAG_TILE_LINE:
mMapGenerator.renderWay((byte) layer, tags, mGeom, false, prio); mWay.closed = false;
mMapGenerator.renderWay(mWay);
break; break;
case TAG_TILE_POLY: case TAG_TILE_POLY:
mMapGenerator.renderWay((byte) layer, tags, mGeom, true, prio); mWay.closed = true;
mMapGenerator.renderWay(mWay);
break; break;
case TAG_TILE_POINT: case TAG_TILE_POINT:
mMapGenerator.renderPOI((byte) layer, tags, mGeom); mMapGenerator.renderPOI((byte) mWay.layer, tags, mGeom);
break; break;
} }

View File

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

View File

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

View File

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

View File

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