- 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; boolean newData;
// pointer in TileTree // pointer to access relatives in TileTree
TreeTile rel; TreeTile rel;
GLMapTile(int tileX, int tileY, byte zoomLevel) { GLMapTile(int tileX, int tileY, byte zoomLevel) {

View File

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

View File

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

View File

@ -351,26 +351,7 @@ public class MapGenerator implements IMapGenerator, IRenderCallback, IMapDatabas
mCurLineLayer = lineLayer; mCurLineLayer = lineLayer;
boolean round = line.round; lineLayer.addLine(mWayNodes, mWays);
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;
}
} }
@Override @Override
@ -415,19 +396,7 @@ public class MapGenerator implements IMapGenerator, IRenderCallback, IMapDatabas
mCurPolyLayer = layer; mCurPolyLayer = layer;
for (int i = 0, pos = 0, n = mWays.length; i < n; i++) { layer.addPolygon(mWayNodes, mWays);
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)
} }
@Override @Override

View File

@ -24,8 +24,8 @@ class PolygonLayer {
Area area; Area area;
// private static final float MapRenderer.COORD_MULTIPLIER = 8.0f; // private static final float MapRenderer.COORD_MULTIPLIER = 8.0f;
private boolean first = true; private boolean first = true;
private float originX; private short originX;
private float originY; private short originY;
ShortItem pool; ShortItem pool;
protected ShortItem curItem; protected ShortItem curItem;
@ -41,69 +41,121 @@ class PolygonLayer {
pool = curItem; pool = curItem;
} }
short[] getNextItem() { // short[] getNextItem() {
curItem.used = ShortItem.SIZE; // 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(); void addPolygon(float[] points, short[] index) {
curItem = curItem.next; 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; verticesCnt += length / 2 + 2;
if (first) { int inPos = pos;
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;
if (outPos == ShortItem.SIZE) { if (outPos == ShortItem.SIZE) {
curVertices = getNextItem(); si = si.next = ShortPool.get();
v = si.vertices;
outPos = 0; outPos = 0;
} }
curVertices[outPos++] = (short) (originX * S); v[outPos++] = center;
curVertices[outPos++] = (short) (originY * S); v[outPos++] = center;
int MAX = ShortItem.SIZE; for (int j = 0; j < length; j += 2) {
int remaining = length; if (outPos == ShortItem.SIZE) {
int inPos = pos; si = si.next = ShortPool.get();
while (remaining > 0) { v = si.vertices;
outPos = 0;
}
v[outPos++] = (short) (points[inPos++] * S);
v[outPos++] = (short) (points[inPos++] * S);
}
if (outPos == MAX) { if (outPos == ShortItem.SIZE) {
curVertices = getNextItem(); si = si.next = ShortPool.get();
v = si.vertices;
outPos = 0; outPos = 0;
} }
int len = remaining; v[outPos++] = (short) (points[pos + 0] * S);
if (len > MAX - outPos) v[outPos++] = (short) (points[pos + 1] * S);
len = MAX - outPos;
for (int i = 0; i < len; i++) pos += length;
curVertices[outPos++] = (short) (points[inPos++] * S);
// System.arraycopy(points, inPos, curVertices, outPos, len);
// outPos += len;
// inPos += len;
remaining -= len;
} }
if (outPos == MAX) { si.used = outPos;
curVertices = getNextItem(); curItem = si;
outPos = 0;
} }
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 (PolygonLayer l = layers; l != null; l = l.next) {
for (ShortItem item = l.pool; item != null; item = item.next) { for (ShortItem item = l.pool; item != null; item = item.next) {
if (item.next == null) {
sbuf.put(item.vertices, 0, item.used); sbuf.put(item.vertices, 0, item.used);
} else {
// item.used = ShortItem.SIZE;
sbuf.put(item.vertices);
}
last = item; last = item;
} }