- add multi-linestrings / -polygons in one go

This commit is contained in:
Hannes Janetzek 2012-09-07 21:10:09 +02:00
parent 7c95930ba3
commit 18d10e744c
6 changed files with 491 additions and 464 deletions

View File

@ -37,7 +37,7 @@ class GLMapTile extends MapTile {
boolean newData;
// pointer in TileTree
// pointer to access relatives in TileTree
TreeTile rel;
GLMapTile(int tileX, int tileY, byte zoomLevel) {

View File

@ -23,9 +23,9 @@ import android.util.FloatMath;
class LineLayer {
private static final float COORD_SCALE = MapRenderer.COORD_MULTIPLIER;
// scale factor mapping direction vector to short values
// scale factor mapping extrusion vector to short values
private static final float DIR_SCALE = 2048;
// mask for packing last two bits of direction vector with texture coordinates
// mask for packing last two bits of extrusion vector with texture coordinates
private static final int DIR_MASK = 0xFFFFFFFC;
// next layer
@ -66,11 +66,14 @@ class LineLayer {
/*
* line extrusion is based on code from GLMap (https://github.com/olofsj/GLMap/) by olofsj
*/
void addLine(float[] points, int pos, int length) {
void addLine(float[] points, short[] index) {
float x, y, nextX, nextY, prevX, prevY;
float a, ux, uy, vx, vy, wx, wy;
int ipos = pos;
int tmax = Tile.TILE_SIZE + 10;
int tmin = -10;
boolean rounded = false;
boolean squared = false;
@ -79,6 +82,30 @@ class LineLayer {
else if (line.cap == Cap.SQUARE)
squared = true;
if (pool == null) {
pool = curItem = ShortPool.get();
}
ShortItem si = curItem;
short v[] = si.vertices;
int opos = si.used;
for (int i = 0, pos = 0, n = index.length; i < n; i++) {
int length = index[i];
if (length < 0)
break;
// save some vertices
if (rounded && i > 200)
rounded = false;
int ipos = pos;
// need at least two points
if (length < 4) {
pos += length;
continue;
}
// amount of vertices used
verticesCnt += length + (rounded ? 6 : 2);
@ -100,23 +127,10 @@ class LineLayer {
ux = -vy;
uy = vx;
int tmax = Tile.TILE_SIZE + 10;
int tmin = -10;
if (pool == null) {
pool = curItem = ShortPool.get();
}
ShortItem si = curItem;
short v[] = si.vertices;
int opos = si.used;
if (opos == ShortItem.SIZE) {
si.used = ShortItem.SIZE;
si.next = ShortPool.get();
si = si.next;
opos = 0;
si = si.next = ShortPool.get();
v = si.vertices;
opos = 0;
}
short ox, oy, dx, dy;
@ -127,6 +141,12 @@ class LineLayer {
boolean outside = (x < tmin || x > tmax || y < tmin || y > tmax);
if (opos == ShortItem.SIZE) {
si = si.next = ShortPool.get();
v = si.vertices;
opos = 0;
}
if (rounded && !outside) {
// add first vertex twice
ddx = (int) ((ux - vx) * DIR_SCALE);
@ -140,11 +160,9 @@ class LineLayer {
v[opos++] = dy;
if (opos == ShortItem.SIZE) {
si.used = ShortItem.SIZE;
si.next = ShortPool.get();
si = si.next;
opos = 0;
si = si.next = ShortPool.get();
v = si.vertices;
opos = 0;
}
v[opos++] = ox;
@ -153,11 +171,9 @@ class LineLayer {
v[opos++] = dy;
if (opos == ShortItem.SIZE) {
si.used = ShortItem.SIZE;
si.next = ShortPool.get();
si = si.next;
opos = 0;
si = si.next = ShortPool.get();
v = si.vertices;
opos = 0;
}
ddx = (int) (-(ux + vx) * DIR_SCALE);
@ -169,11 +185,9 @@ class LineLayer {
v[opos++] = (short) (2 | ddy & DIR_MASK);
if (opos == ShortItem.SIZE) {
si.used = ShortItem.SIZE;
si.next = ShortPool.get();
si = si.next;
opos = 0;
si = si.next = ShortPool.get();
v = si.vertices;
opos = 0;
}
// Start of line
@ -186,11 +200,9 @@ class LineLayer {
v[opos++] = (short) (1 | ddy & DIR_MASK);
if (opos == ShortItem.SIZE) {
si.used = ShortItem.SIZE;
si.next = ShortPool.get();
si = si.next;
opos = 0;
si = si.next = ShortPool.get();
v = si.vertices;
opos = 0;
}
v[opos++] = ox;
@ -226,11 +238,9 @@ class LineLayer {
v[opos++] = dy;
if (opos == ShortItem.SIZE) {
si.used = ShortItem.SIZE;
si.next = ShortPool.get();
si = si.next;
opos = 0;
si = si.next = ShortPool.get();
v = si.vertices;
opos = 0;
}
v[opos++] = ox;
@ -239,11 +249,9 @@ class LineLayer {
v[opos++] = dy;
if (opos == ShortItem.SIZE) {
si.used = ShortItem.SIZE;
si.next = ShortPool.get();
si = si.next;
opos = 0;
si = si.next = ShortPool.get();
v = si.vertices;
opos = 0;
}
ddx = (int) (-(ux + vx) * DIR_SCALE);
@ -295,7 +303,6 @@ class LineLayer {
uy = (uy / a);
// hack to avoid miter going to infinity
// note to myself: find my mathbook and do this properly!
if (ux > 2.0f || ux < -2.0f || uy > 2.0f || uy < -2.0f) {
ux = -wy;
uy = wx;
@ -303,11 +310,9 @@ class LineLayer {
}
if (opos == ShortItem.SIZE) {
si.used = ShortItem.SIZE;
si.next = ShortPool.get();
si = si.next;
opos = 0;
si = si.next = ShortPool.get();
v = si.vertices;
opos = 0;
}
ox = (short) (x * COORD_SCALE);
@ -322,11 +327,9 @@ class LineLayer {
v[opos++] = (short) (1 | ddy & DIR_MASK);
if (opos == ShortItem.SIZE) {
si.used = ShortItem.SIZE;
si.next = ShortPool.get();
si = si.next;
opos = 0;
si = si.next = ShortPool.get();
v = si.vertices;
opos = 0;
}
v[opos++] = ox;
@ -354,7 +357,6 @@ class LineLayer {
outside = (x < tmin || x > tmax || y < tmin || y > tmax);
if (opos == ShortItem.SIZE) {
si.used = ShortItem.SIZE;
si.next = ShortPool.get();
si = si.next;
opos = 0;
@ -374,11 +376,9 @@ class LineLayer {
v[opos++] = (short) (1 | ddy & DIR_MASK);
if (opos == ShortItem.SIZE) {
si.used = ShortItem.SIZE;
si.next = ShortPool.get();
si = si.next;
opos = 0;
si = si.next = ShortPool.get();
v = si.vertices;
opos = 0;
}
v[opos++] = ox;
@ -387,11 +387,9 @@ class LineLayer {
v[opos++] = (short) (1 | -ddy & DIR_MASK);
if (opos == ShortItem.SIZE) {
si.used = ShortItem.SIZE;
si.next = ShortPool.get();
si = si.next;
opos = 0;
si = si.next = ShortPool.get();
v = si.vertices;
opos = 0;
}
// For rounded line edges
@ -406,11 +404,9 @@ class LineLayer {
v[opos++] = dy;
if (opos == ShortItem.SIZE) {
si.used = ShortItem.SIZE;
si.next = ShortPool.get();
si = si.next;
opos = 0;
si = si.next = ShortPool.get();
v = si.vertices;
opos = 0;
}
// add last vertex twice
@ -425,11 +421,9 @@ class LineLayer {
v[opos++] = dy;
if (opos == ShortItem.SIZE) {
si.used = ShortItem.SIZE;
si.next = ShortPool.get();
si = si.next;
opos = 0;
si = si.next = ShortPool.get();
v = si.vertices;
opos = 0;
}
v[opos++] = ox;
@ -458,11 +452,9 @@ class LineLayer {
v[opos++] = (short) (1 | ddy & DIR_MASK);
if (opos == ShortItem.SIZE) {
si.used = ShortItem.SIZE;
si.next = ShortPool.get();
si = si.next;
opos = 0;
si = si.next = ShortPool.get();
v = si.vertices;
opos = 0;
}
// add last vertex twice
@ -477,11 +469,9 @@ class LineLayer {
v[opos++] = dy;
if (opos == ShortItem.SIZE) {
si.used = ShortItem.SIZE;
si.next = ShortPool.get();
si = si.next;
opos = 0;
si = si.next = ShortPool.get();
v = si.vertices;
opos = 0;
}
v[opos++] = ox;
@ -489,6 +479,8 @@ class LineLayer {
v[opos++] = dx;
v[opos++] = dy;
}
pos += length;
}
si.used = opos;
curItem = si;

View File

@ -191,7 +191,14 @@ class LineLayers {
continue;
for (ShortItem item = l.pool; item != null; item = item.next) {
if (item.next == null) {
sbuf.put(item.vertices, 0, item.used);
} else {
// item.used = ShortItem.SIZE;
sbuf.put(item.vertices);
}
last = item;
}

View File

@ -351,26 +351,7 @@ public class MapGenerator implements IMapGenerator, IRenderCallback, IMapDatabas
mCurLineLayer = lineLayer;
boolean round = line.round;
for (int i = 0, pos = 0, n = mWays.length; i < n; i++) {
int length = mWays[i];
if (length < 0)
break;
// save some vertices
if (round && i > 200) {
// Log.d(TAG, "WAY TOO MANY LINES!!!");
round = false;
}
// need at least two points
if (length >= 4) {
lineLayer.addLine(mWayNodes, pos, length);
countLines++;
countNodes += length;
}
pos += length;
}
lineLayer.addLine(mWayNodes, mWays);
}
@Override
@ -415,19 +396,7 @@ public class MapGenerator implements IMapGenerator, IRenderCallback, IMapDatabas
mCurPolyLayer = layer;
for (int i = 0, pos = 0, n = mWays.length; i < n; i++) {
int length = mWays[i];
if (length < 0)
break;
// need at least three points
if (length >= 6)
layer.addPolygon(mWayNodes, pos, length);
pos += length;
}
// if (area.line != null)
layer.addPolygon(mWayNodes, mWays);
}
@Override

View File

@ -24,8 +24,8 @@ class PolygonLayer {
Area area;
// private static final float MapRenderer.COORD_MULTIPLIER = 8.0f;
private boolean first = true;
private float originX;
private float originY;
private short originX;
private short originY;
ShortItem pool;
protected ShortItem curItem;
@ -41,69 +41,121 @@ class PolygonLayer {
pool = curItem;
}
short[] getNextItem() {
curItem.used = ShortItem.SIZE;
// short[] getNextItem() {
// curItem.used = ShortItem.SIZE;
// curItem.next = ShortPool.get();
// curItem = curItem.next;
//
// return curItem.vertices;
// }
//
// void addPolygon(float[] points, int pos, int length) {
//
// verticesCnt += length / 2 + 2;
//
// if (first) {
// first = false;
// originX = (short) ((Tile.TILE_SIZE >> 1) * S);
// originY = (short) ((Tile.TILE_SIZE >> 1) * S);
// }
//
// short[] curVertices = curItem.vertices;
// int outPos = curItem.used;
//
// if (outPos == ShortItem.SIZE) {
// curVertices = getNextItem();
// outPos = 0;
// }
//
// curVertices[outPos++] = originX;
// curVertices[outPos++] = originY;
//
// int MAX = ShortItem.SIZE;
// int remaining = length;
// int inPos = pos;
// while (remaining > 0) {
//
// if (outPos == MAX) {
// curVertices = getNextItem();
// outPos = 0;
// }
//
// int len = remaining;
// if (len > MAX - outPos)
// len = MAX - outPos;
//
// for (int i = 0; i < len; i++)
// curVertices[outPos++] = (short) (points[inPos++] * S);
//
// remaining -= len;
// }
//
// if (outPos == MAX) {
// curVertices = getNextItem();
// outPos = 0;
// }
//
// curVertices[outPos++] = (short) (points[pos + 0] * S);
// curVertices[outPos++] = (short) (points[pos + 1] * S);
//
// curItem.used = outPos;
// }
curItem.next = ShortPool.get();
curItem = curItem.next;
void addPolygon(float[] points, short[] index) {
short center = (short) ((Tile.TILE_SIZE >> 1) * S);
return curItem.vertices;
ShortItem si = curItem;
short[] v = si.vertices;
int outPos = si.used;
for (int i = 0, pos = 0, n = index.length; i < n; i++) {
int length = index[i];
if (length < 0)
break;
// need at least three points
if (length < 6) {
pos += length;
continue;
}
void addPolygon(float[] points, int pos, int length) {
verticesCnt += length / 2 + 2;
if (first) {
first = false;
originX = Tile.TILE_SIZE >> 1; // points[pos];
originY = Tile.TILE_SIZE >> 1; // points[pos + 1];
}
short[] curVertices = curItem.vertices;
int outPos = curItem.used;
int inPos = pos;
if (outPos == ShortItem.SIZE) {
curVertices = getNextItem();
si = si.next = ShortPool.get();
v = si.vertices;
outPos = 0;
}
curVertices[outPos++] = (short) (originX * S);
curVertices[outPos++] = (short) (originY * S);
v[outPos++] = center;
v[outPos++] = center;
int MAX = ShortItem.SIZE;
int remaining = length;
int inPos = pos;
while (remaining > 0) {
for (int j = 0; j < length; j += 2) {
if (outPos == ShortItem.SIZE) {
si = si.next = ShortPool.get();
v = si.vertices;
outPos = 0;
}
v[outPos++] = (short) (points[inPos++] * S);
v[outPos++] = (short) (points[inPos++] * S);
}
if (outPos == MAX) {
curVertices = getNextItem();
if (outPos == ShortItem.SIZE) {
si = si.next = ShortPool.get();
v = si.vertices;
outPos = 0;
}
int len = remaining;
if (len > MAX - outPos)
len = MAX - outPos;
v[outPos++] = (short) (points[pos + 0] * S);
v[outPos++] = (short) (points[pos + 1] * S);
for (int i = 0; i < len; i++)
curVertices[outPos++] = (short) (points[inPos++] * S);
// System.arraycopy(points, inPos, curVertices, outPos, len);
// outPos += len;
// inPos += len;
remaining -= len;
pos += length;
}
if (outPos == MAX) {
curVertices = getNextItem();
outPos = 0;
si.used = outPos;
curItem = si;
}
curVertices[outPos++] = (short) (points[pos + 0] * S);
curVertices[outPos++] = (short) (points[pos + 1] * S);
curItem.used = outPos;
}
}

View File

@ -260,7 +260,14 @@ class PolygonLayers {
for (PolygonLayer l = layers; l != null; l = l.next) {
for (ShortItem item = l.pool; item != null; item = item.next) {
if (item.next == null) {
sbuf.put(item.vertices, 0, item.used);
} else {
// item.used = ShortItem.SIZE;
sbuf.put(item.vertices);
}
last = item;
}