labeling testing
This commit is contained in:
parent
d25d967332
commit
34bffcc15f
@ -35,6 +35,7 @@ import org.oscim.theme.renderinstruction.Area;
|
||||
import org.oscim.theme.renderinstruction.Line;
|
||||
import org.oscim.theme.renderinstruction.RenderInstruction;
|
||||
import org.oscim.theme.renderinstruction.Text;
|
||||
import org.oscim.utils.LineClipper;
|
||||
import org.oscim.view.DebugSettings;
|
||||
import org.oscim.view.MapView;
|
||||
|
||||
@ -114,6 +115,8 @@ public class TileGenerator implements IRenderCallback, IMapDatabaseCallback {
|
||||
private boolean mDebugDrawPolygons;
|
||||
boolean mDebugDrawUnmatched;
|
||||
|
||||
private final LineClipper mClipper;
|
||||
|
||||
public static void setRenderTheme(RenderTheme theme) {
|
||||
renderTheme = theme;
|
||||
renderLevels = theme.getLevels();
|
||||
@ -129,6 +132,7 @@ public class TileGenerator implements IRenderCallback, IMapDatabaseCallback {
|
||||
*/
|
||||
public TileGenerator(MapView mapView) {
|
||||
// mMapView = mapView;
|
||||
mClipper = new LineClipper(0,0,Tile.TILE_SIZE, Tile.TILE_SIZE, true);
|
||||
}
|
||||
|
||||
public void cleanup() {
|
||||
@ -172,10 +176,10 @@ public class TileGenerator implements IRenderCallback, IMapDatabaseCallback {
|
||||
}
|
||||
|
||||
if (debug.drawTileFrames) {
|
||||
//mTagName = new Tag("name", tile.toString(), false);
|
||||
//mPoiX = Tile.TILE_SIZE >> 1;
|
||||
//mPoiY = 10;
|
||||
//TileGenerator.renderTheme.matchNode(this, debugTagWay, (byte) 0);
|
||||
mTagName = new Tag("name", tile.toString(), false);
|
||||
mPoiX = Tile.TILE_SIZE >> 1;
|
||||
mPoiY = 10;
|
||||
TileGenerator.renderTheme.matchNode(this, debugTagWay, (byte) 0);
|
||||
|
||||
mIndices = debugBoxIndex;
|
||||
if (MapView.enableClosePolygons)
|
||||
@ -476,7 +480,7 @@ public class TileGenerator implements IRenderCallback, IMapDatabaseCallback {
|
||||
int length = mIndices[i];
|
||||
if (length < 4)
|
||||
break;
|
||||
mLabels = WayDecorator.renderText(mCoords, mTagName.value, text,
|
||||
mLabels = WayDecorator.renderText(mClipper,mCoords, mTagName.value, text,
|
||||
offset, length, mLabels);
|
||||
offset += length;
|
||||
}
|
||||
|
@ -18,123 +18,170 @@ package org.oscim.generator;
|
||||
import org.oscim.core.Tile;
|
||||
import org.oscim.renderer.layer.TextItem;
|
||||
import org.oscim.theme.renderinstruction.Text;
|
||||
import org.oscim.utils.GeometryUtils;
|
||||
import org.oscim.utils.LineClipper;
|
||||
|
||||
public final class WayDecorator {
|
||||
|
||||
public static TextItem renderText(float[] coordinates, String string, Text text,
|
||||
public static TextItem renderText(LineClipper clipper, float[] coordinates, String string,
|
||||
Text text,
|
||||
int pos, int len, TextItem textItems) {
|
||||
TextItem items = textItems;
|
||||
TextItem t = null;
|
||||
|
||||
// calculate the way name length plus some margin of safety
|
||||
float wayNameWidth = -1;
|
||||
float minWidth = Tile.TILE_SIZE / 10;
|
||||
//int skipPixels = 0;
|
||||
|
||||
// get the first way point coordinates
|
||||
int prevX = (int) coordinates[pos + 0];
|
||||
int prevY = (int) coordinates[pos + 1];
|
||||
final int min = 0;
|
||||
final int max = Tile.TILE_SIZE;
|
||||
|
||||
// find way segments long enough to draw the way name on them
|
||||
for (int i = pos + 2; i < pos + len; i += 2) {
|
||||
for (int i = pos; i < pos + len - 2; i += 2) {
|
||||
// get the first way point coordinates
|
||||
int prevX = (int) coordinates[i + 0];
|
||||
int prevY = (int) coordinates[i + 1];
|
||||
|
||||
byte edge = 0;
|
||||
|
||||
clipper.clipStart(prevX, prevY);
|
||||
|
||||
// get the current way point coordinates
|
||||
int curX = (int) coordinates[i];
|
||||
int curY = (int) coordinates[i + 1];
|
||||
int curX = (int) coordinates[i + 2];
|
||||
int curY = (int) coordinates[i + 3];
|
||||
|
||||
int clip;
|
||||
if ((clip = clipper.clipNext(curX, curY)) != 0) {
|
||||
if (clip < 0) {
|
||||
prevX = clipper.out[0];
|
||||
prevY = clipper.out[1];
|
||||
curX = clipper.out[2];
|
||||
curY = clipper.out[3];
|
||||
|
||||
if (prevX == min)
|
||||
edge |= 1 << 0;
|
||||
else if (prevX == max)
|
||||
edge |= 1 << 1;
|
||||
|
||||
if (prevY == min)
|
||||
edge |= 1 << 2;
|
||||
else if (prevY == max)
|
||||
edge |= 1 << 3;
|
||||
|
||||
if (curX == min)
|
||||
edge |= 1 << 4;
|
||||
else if (curX == max)
|
||||
edge |= 1 << 5;
|
||||
|
||||
if (curY == min)
|
||||
edge |= 1 << 5;
|
||||
else if (curY == max)
|
||||
edge |= 1 << 6;
|
||||
}
|
||||
}
|
||||
|
||||
int last = i;
|
||||
|
||||
// calculate the length of the current segment (Euclidian distance)
|
||||
float vx = prevX - curX;
|
||||
float vy = prevY - curY;
|
||||
if (vx == 0 && vy == 0)
|
||||
continue;
|
||||
|
||||
float a = (float) Math.sqrt(vx * vx + vy * vy);
|
||||
vx /= a;
|
||||
vy /= a;
|
||||
|
||||
int last = i;
|
||||
int nextX = 0, nextY = 0;
|
||||
// only if not cur segment crosses edge
|
||||
if (edge < (1 << 4)) {
|
||||
vx /= a;
|
||||
vy /= a;
|
||||
|
||||
// add additional segments if possible
|
||||
for (int j = last + 2; j < pos + len; j += 2) {
|
||||
nextX = (int) coordinates[j];
|
||||
nextY = (int) coordinates[j + 1];
|
||||
// add additional segments if possible
|
||||
for (int j = i + 4; j < pos + len; j += 2) {
|
||||
int nextX = (int) coordinates[j + 0];
|
||||
int nextY = (int) coordinates[j + 1];
|
||||
|
||||
float wx = curX - nextX;
|
||||
float wy = curY - nextY;
|
||||
if ((clip = clipper.clipNext(nextX, nextY)) != 0) {
|
||||
if (clip < 0) {
|
||||
curX = clipper.out[0];
|
||||
curY = clipper.out[1];
|
||||
// TODO break when cur has changed
|
||||
nextX = clipper.out[2];
|
||||
nextY = clipper.out[3];
|
||||
}
|
||||
}
|
||||
|
||||
a = (float) Math.sqrt(wx * wx + wy * wy);
|
||||
wx /= a;
|
||||
wy /= a;
|
||||
float wx = nextX - curX;
|
||||
float wy = nextY - curY;
|
||||
if (wx == 0 && wy == 0)
|
||||
continue;
|
||||
|
||||
float ux = vx + wx;
|
||||
float uy = vy + wy;
|
||||
float area = GeometryUtils.area(prevX, prevY, curX, curY, nextX, nextY);
|
||||
|
||||
float diff = wx * uy - wy * ux;
|
||||
if (area > 1000) {
|
||||
//Log.d(">>>", "b: " + string + " " + area );
|
||||
break;
|
||||
}
|
||||
|
||||
if (diff > 0.1 || diff < -0.1)
|
||||
break;
|
||||
a = (float) Math.sqrt(wx * wx + wy * wy);
|
||||
wx /= a;
|
||||
wy /= a;
|
||||
|
||||
last = j;
|
||||
curX = nextX;
|
||||
curY = nextY;
|
||||
continue;
|
||||
// avoid adding short segments that add much area
|
||||
if (area / 2 > a * a) {
|
||||
//Log.d(">>>", "a: " +string + " " + area + " " + a*a);
|
||||
break;
|
||||
}
|
||||
|
||||
float ux = vx + wx;
|
||||
float uy = vy + wy;
|
||||
float diff = wx * uy - wy * ux;
|
||||
|
||||
// maximum angle between segments
|
||||
if (diff > 0.1 || diff < -0.1) {
|
||||
//Log.d(">>>", "c: " + string + " " + area );
|
||||
break;
|
||||
}
|
||||
curX = nextX;
|
||||
curY = nextY;
|
||||
last = j - 2;
|
||||
|
||||
if (clip < 0) {
|
||||
if (nextX == min)
|
||||
edge |= 1 << 4;
|
||||
else if (nextX == max)
|
||||
edge |= 1 << 5;
|
||||
|
||||
if (nextY == min)
|
||||
edge |= 1 << 6;
|
||||
else if (nextY == max)
|
||||
edge |= 1 << 7;
|
||||
}
|
||||
}
|
||||
|
||||
vx = curX - prevX;
|
||||
vy = curY - prevY;
|
||||
a = (float) Math.sqrt(vx * vx + vy * vy);
|
||||
}
|
||||
|
||||
vx = curX - prevX;
|
||||
vy = curY - prevY;
|
||||
float segmentLength = a;
|
||||
|
||||
if (vx < 0)
|
||||
vx = -vx;
|
||||
if (vy < 0)
|
||||
vy = -vy;
|
||||
if (edge == 0) {
|
||||
if (segmentLength < minWidth) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// minimum segment to label
|
||||
if (vx + vy < minWidth) {
|
||||
// restart from next node
|
||||
prevX = (int) coordinates[i];
|
||||
prevY = (int) coordinates[i + 1];
|
||||
continue;
|
||||
}
|
||||
if (wayNameWidth < 0) {
|
||||
wayNameWidth = text.paint.measureText(string);
|
||||
}
|
||||
|
||||
// compare against max segment length
|
||||
if (wayNameWidth > 0 && vx + vy < wayNameWidth) {
|
||||
// restart from next node
|
||||
prevX = (int) coordinates[i];
|
||||
prevY = (int) coordinates[i + 1];
|
||||
continue;
|
||||
}
|
||||
|
||||
float segmentLength = (float) Math.sqrt(vx * vx + vy * vy);
|
||||
|
||||
//if (skipPixels > 0) {
|
||||
// skipPixels -= segmentLength;
|
||||
//
|
||||
//} else
|
||||
|
||||
if (segmentLength < minWidth) {
|
||||
// restart from next node
|
||||
prevX = (int) coordinates[i];
|
||||
prevY = (int) coordinates[i + 1];
|
||||
continue;
|
||||
}
|
||||
|
||||
if (wayNameWidth < 0) {
|
||||
if (segmentLength < wayNameWidth * 0.50) {
|
||||
continue;
|
||||
}
|
||||
} else if (wayNameWidth < 0) {
|
||||
wayNameWidth = text.paint.measureText(string);
|
||||
}
|
||||
|
||||
if (segmentLength < wayNameWidth * 0.50) {
|
||||
// restart from next node
|
||||
prevX = (int) coordinates[i];
|
||||
prevY = (int) coordinates[i + 1];
|
||||
continue;
|
||||
}
|
||||
|
||||
//float s = (wayNameWidth + 20) / segmentLength;
|
||||
//float s;
|
||||
//if (wayNameWidth < segmentLength)
|
||||
// s = (segmentLength - 10) / segmentLength;
|
||||
//else
|
||||
//s = (wayNameWidth + 20) / segmentLength;
|
||||
//float width, height;
|
||||
|
||||
float x1, y1, x2, y2;
|
||||
|
||||
if (prevX < curX) {
|
||||
x1 = prevX;
|
||||
y1 = prevY;
|
||||
@ -147,17 +194,6 @@ public final class WayDecorator {
|
||||
y2 = prevY;
|
||||
}
|
||||
|
||||
//// estimate position of text on path
|
||||
//width = (x2 - x1) / 2f;
|
||||
////width += 4 * (width / wayNameWidth);
|
||||
//x2 = x2 - (width - s * width);
|
||||
//x1 = x1 + (width - s * width);
|
||||
//
|
||||
//height = (y2 - y1) / 2f;
|
||||
////height += 4 * (height / wayNameWidth);
|
||||
//y2 = y2 - (height - s * height);
|
||||
//y1 = y1 + (height - s * height);
|
||||
|
||||
TextItem n = TextItem.get();
|
||||
|
||||
// link items together
|
||||
@ -177,15 +213,11 @@ public final class WayDecorator {
|
||||
t.x2 = x2;
|
||||
t.y2 = y2;
|
||||
t.length = (short) segmentLength;
|
||||
|
||||
t.edges = edge;
|
||||
t.next = items;
|
||||
items = t;
|
||||
|
||||
// skip to last
|
||||
i = last;
|
||||
// store the previous way point coordinates
|
||||
prevX = curX;
|
||||
prevY = curY;
|
||||
}
|
||||
return items;
|
||||
}
|
||||
|
@ -544,7 +544,7 @@ public class GLRenderer implements GLSurfaceView.Renderer {
|
||||
td.cnt = 0;
|
||||
for (int i = 0; i < cnt; i++) {
|
||||
MapTile t = newTiles[i];
|
||||
if (t.isVisible) {
|
||||
if (t.isVisible && t.state == STATE_READY) {
|
||||
t.lock();
|
||||
td.tiles[td.cnt++] = t;
|
||||
}
|
||||
|
@ -91,6 +91,8 @@ public class TextureObject {
|
||||
* @param to the TextureObjet to compile and upload
|
||||
*/
|
||||
public static synchronized void uploadTexture(TextureObject to) {
|
||||
// FIXME what needs synchronized ?
|
||||
|
||||
if (TextureRenderer.debug)
|
||||
Log.d(TAG, "upload texture " + to.id);
|
||||
|
||||
|
@ -158,11 +158,12 @@ public final class TextureRenderer {
|
||||
+ "const float coord_scale = 0.125;"
|
||||
+ "void main() {"
|
||||
+ " vec4 pos;"
|
||||
+ " vec2 dir = vertex.zw;"
|
||||
+ " if (mod(vertex.x, 2.0) == 0.0){"
|
||||
+ " pos = u_proj * (u_mv * vec4(vertex.xy + vertex.zw * u_scale, 0.0, 1.0));"
|
||||
+ " pos = u_proj * (u_mv * vec4(vertex.xy + dir * u_scale, 0.0, 1.0));"
|
||||
+ " } else {" // place as billboard
|
||||
+ " vec4 dir = u_mv * vec4(vertex.xy, 0.0, 1.0);"
|
||||
+ " pos = u_proj * (dir + vec4(vertex.zw * (coord_scale * u_swidth), 0.1, 0.0));"
|
||||
+ " vec4 center = u_mv * vec4(vertex.xy, 0.0, 1.0);"
|
||||
+ " pos = u_proj * (center + vec4(dir * (coord_scale * u_swidth), 0.1, 0.0));"
|
||||
+ " }"
|
||||
+ " gl_Position = pos;"
|
||||
+ " tex_c = tex_coord * div;"
|
||||
|
@ -290,7 +290,7 @@ public class ExtrusionLayer extends Layer {
|
||||
}
|
||||
|
||||
/* check if face is within tile */
|
||||
if (!mClipper.clipNext((int) nx, (int) ny)) {
|
||||
if (mClipper.clipNext((int) nx, (int) ny) == 0) {
|
||||
even = (even == 0 ? 1 : 0);
|
||||
continue;
|
||||
}
|
||||
|
@ -15,7 +15,6 @@
|
||||
package org.oscim.renderer.layer;
|
||||
|
||||
import org.oscim.theme.renderinstruction.Text;
|
||||
import org.oscim.utils.OBB2D;
|
||||
|
||||
import android.util.Log;
|
||||
|
||||
@ -40,7 +39,33 @@ public class TextItem {
|
||||
pool = pool.next;
|
||||
|
||||
ti.next = null;
|
||||
ti.active = 0;
|
||||
//ti.active = 0;
|
||||
return ti;
|
||||
}
|
||||
}
|
||||
|
||||
public static TextItem copy(TextItem orig) {
|
||||
synchronized (lock) {
|
||||
TextItem ti = pool;
|
||||
|
||||
if (ti == null) {
|
||||
count++;
|
||||
ti = new TextItem();
|
||||
} else {
|
||||
inPool--;
|
||||
pool = pool.next;
|
||||
}
|
||||
|
||||
ti.next = null;
|
||||
|
||||
ti.x = orig.x;
|
||||
ti.y = orig.y;
|
||||
|
||||
ti.x1 = orig.x1;
|
||||
ti.y1 = orig.y1;
|
||||
ti.x2 = orig.x2;
|
||||
ti.y2 = orig.y2;
|
||||
|
||||
return ti;
|
||||
}
|
||||
}
|
||||
@ -115,28 +140,24 @@ public class TextItem {
|
||||
public TextItem move(TextItem ti, float dx, float dy) {
|
||||
this.x = dx + ti.x;
|
||||
this.y = dy + ti.y;
|
||||
this.string = ti.string;
|
||||
this.text = ti.text;
|
||||
this.width = ti.width;
|
||||
this.length = ti.length;
|
||||
return this;
|
||||
|
||||
}
|
||||
|
||||
/* copy properties from 'ti' and add offset
|
||||
*
|
||||
* */
|
||||
public TextItem move(TextItem ti, float dx, float dy, float scale) {
|
||||
this.x = dx + (ti.x * scale);
|
||||
this.y = dy + (ti.y * scale);
|
||||
this.x = (dx + ti.x) * scale;
|
||||
this.y = (dy + ti.y) * scale;
|
||||
return this;
|
||||
}
|
||||
|
||||
public void clone(TextItem ti){
|
||||
this.string = ti.string;
|
||||
this.text = ti.text;
|
||||
this.width = ti.width;
|
||||
this.length = ti.length;
|
||||
return this;
|
||||
}
|
||||
|
||||
public void setAxisAlignedBBox(){
|
||||
public void setAxisAlignedBBox() {
|
||||
this.x1 = x - width / 2;
|
||||
this.y1 = y - text.fontHeight / 2;
|
||||
this.x2 = x + width / 2;
|
||||
@ -197,8 +218,10 @@ public class TextItem {
|
||||
public TextItem n1;
|
||||
public TextItem n2;
|
||||
|
||||
public byte origin;
|
||||
public byte edges;
|
||||
|
||||
public int active;
|
||||
public OBB2D bbox;
|
||||
@Override
|
||||
public String toString() {
|
||||
return x + " " + y + " " + string;
|
||||
}
|
||||
}
|
||||
|
@ -34,7 +34,6 @@ public final class TextLayer extends TextureLayer {
|
||||
|
||||
public TextItem labels;
|
||||
private final Canvas mCanvas;
|
||||
private float mScale;
|
||||
|
||||
public TextItem getLabels() {
|
||||
return labels;
|
||||
@ -44,11 +43,6 @@ public final class TextLayer extends TextureLayer {
|
||||
type = Layer.SYMBOL;
|
||||
mCanvas = new Canvas();
|
||||
fixed = true;
|
||||
mScale = 1;
|
||||
}
|
||||
|
||||
public void setScale(float scale) {
|
||||
mScale = scale;
|
||||
}
|
||||
|
||||
public boolean removeText(TextItem item) {
|
||||
@ -132,7 +126,7 @@ public final class TextLayer extends TextureLayer {
|
||||
for (TextItem it = labels; it != null;) {
|
||||
|
||||
float width = it.width + 2 * mFontPadX;
|
||||
float height = (int) (it.text.fontHeight) + 2 * mFontPadY + 0.5f;
|
||||
float height = (int) (it.text.fontHeight) + 0.5f;
|
||||
|
||||
if (height > advanceY)
|
||||
advanceY = (int) height;
|
||||
@ -158,7 +152,8 @@ public final class TextLayer extends TextureLayer {
|
||||
}
|
||||
}
|
||||
|
||||
yy = y + (height - 1) - it.text.fontDescent - mFontPadY;
|
||||
//yy = y + (height - 1) - it.text.fontDescent - mFontPadY;
|
||||
yy = y + height - it.text.fontDescent; // - mFontPadY;
|
||||
|
||||
if (it.text.stroke != null)
|
||||
mCanvas.drawText(it.string, x + it.width / 2, yy, it.text.stroke);
|
||||
@ -174,11 +169,10 @@ public final class TextLayer extends TextureLayer {
|
||||
|
||||
float hh2 = 0;
|
||||
if (!it.text.caption) {
|
||||
hw /= mScale;
|
||||
hh2 = hh + it.text.fontDescent / 2;
|
||||
hh -= it.text.fontDescent / 2;
|
||||
hh /= mScale;
|
||||
hh2 /= mScale;
|
||||
// displace by baseline
|
||||
float desc = it.text.fontDescent / 2;
|
||||
hh2 = hh + desc;
|
||||
hh = hh - desc;
|
||||
}
|
||||
|
||||
// texture coordinates
|
||||
@ -192,17 +186,17 @@ public final class TextLayer extends TextureLayer {
|
||||
short x1, x2, x3, x4, y1, y3, y2, y4;
|
||||
|
||||
if (it.text.caption) {
|
||||
if (it.origin == 0) {
|
||||
x1 = x3 = (short) (SCALE * -hw);
|
||||
x2 = x4 = (short) (SCALE * hw);
|
||||
y1 = y2 = (short) (SCALE * hh);
|
||||
y3 = y4 = (short) (SCALE * -hh);
|
||||
} else {
|
||||
x1 = x3 = (short) (SCALE * 0);
|
||||
x2 = x4 = (short) (SCALE * width);
|
||||
y1 = y2 = (short) (SCALE * 0);
|
||||
y3 = y4 = (short) (SCALE * -height);
|
||||
}
|
||||
//if (it.origin == 0) {
|
||||
x1 = x3 = (short) (SCALE * -hw);
|
||||
x2 = x4 = (short) (SCALE * hw);
|
||||
y1 = y2 = (short) (SCALE * hh);
|
||||
y3 = y4 = (short) (SCALE * -hh);
|
||||
//} else {
|
||||
// x1 = x3 = (short) (SCALE * 0);
|
||||
// x2 = x4 = (short) (SCALE * width);
|
||||
// y1 = y2 = (short) (SCALE * 0);
|
||||
// y3 = y4 = (short) (SCALE * -height);
|
||||
//}
|
||||
} else {
|
||||
float vx = it.x1 - it.x2;
|
||||
float vy = it.y1 - it.y2;
|
||||
@ -219,12 +213,16 @@ public final class TextLayer extends TextureLayer {
|
||||
vx *= hw;
|
||||
vy *= hw;
|
||||
|
||||
// top-left
|
||||
x1 = (short) (SCALE * (vx - ux));
|
||||
y1 = (short) (SCALE * (vy - uy));
|
||||
// top-right
|
||||
x2 = (short) (SCALE * (-vx - ux));
|
||||
y2 = (short) (SCALE * (-vy - uy));
|
||||
// bot-right
|
||||
x4 = (short) (SCALE * (-vx + ux2));
|
||||
y4 = (short) (SCALE * (-vy + uy2));
|
||||
// bot-left
|
||||
x3 = (short) (SCALE * (vx + ux2));
|
||||
y3 = (short) (SCALE * (vy + uy2));
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2012 Hannes Janetzek
|
||||
* Copyright 2012, 2013 OpenScienceMap
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify it under the
|
||||
* terms of the GNU Lesser General Public License as published by the Free Software
|
||||
@ -17,12 +17,15 @@ package org.oscim.renderer.layer;
|
||||
import java.nio.ShortBuffer;
|
||||
|
||||
import org.oscim.renderer.TextureObject;
|
||||
import org.oscim.renderer.TextureRenderer;
|
||||
|
||||
import android.util.Log;
|
||||
|
||||
/**
|
||||
* @author Hannes Janetzek
|
||||
*/
|
||||
public abstract class TextureLayer extends Layer {
|
||||
// holds textures and offset in vbo
|
||||
public TextureObject textures;
|
||||
|
||||
// scale mode
|
||||
public boolean fixed;
|
||||
|
||||
/**
|
||||
@ -30,12 +33,11 @@ public abstract class TextureLayer extends Layer {
|
||||
* buffer to add vertices
|
||||
*/
|
||||
void compile(ShortBuffer sbuf) {
|
||||
if (TextureRenderer.debug)
|
||||
Log.d("...", "compile");
|
||||
|
||||
for (TextureObject to = textures; to != null; to = to.next)
|
||||
TextureObject.uploadTexture(to);
|
||||
|
||||
// add vertices to vbo
|
||||
Layers.addPoolItems(this, sbuf);
|
||||
}
|
||||
|
||||
|
@ -363,7 +363,6 @@ public class TextOverlay extends BasicOverlay {
|
||||
}
|
||||
|
||||
// draw text to bitmaps and create vertices
|
||||
tl.setScale(scale);
|
||||
tl.prepare();
|
||||
|
||||
// everything synchronized?
|
||||
|
@ -30,7 +30,6 @@ import java.util.HashMap;
|
||||
|
||||
import org.oscim.core.MapPosition;
|
||||
import org.oscim.core.Tile;
|
||||
import org.oscim.generator.JobTile;
|
||||
import org.oscim.renderer.BufferObject;
|
||||
import org.oscim.renderer.GLRenderer;
|
||||
import org.oscim.renderer.GLRenderer.Matrices;
|
||||
@ -82,7 +81,7 @@ public class TextOverlayExp extends BasicOverlay {
|
||||
|
||||
@Override
|
||||
protected void doWork() {
|
||||
SystemClock.sleep(300);
|
||||
SystemClock.sleep(150);
|
||||
if (!mRun)
|
||||
return;
|
||||
|
||||
@ -106,35 +105,45 @@ public class TextOverlayExp extends BasicOverlay {
|
||||
}
|
||||
}
|
||||
|
||||
private float mSquareRadius;
|
||||
private int mRelabelCnt;
|
||||
|
||||
public TextOverlayExp(MapView mapView) {
|
||||
super(mapView);
|
||||
mMapViewPosition = mapView.getMapViewPosition();
|
||||
|
||||
layers.textureLayers = new TextLayer();
|
||||
mTmpLayer = new TextLayer();
|
||||
|
||||
mActiveTiles = new HashMap<MapTile, Link>();
|
||||
mTmpPos = new MapPosition();
|
||||
mThread = new LabelThread();
|
||||
mThread.start();
|
||||
|
||||
mRelabelCnt = 0;
|
||||
}
|
||||
|
||||
private HashMap<MapTile, PlacementItem> mItemMap;
|
||||
private HashMap<MapTile, Label> mItemMap;
|
||||
|
||||
class PlacementItem extends TextItem {
|
||||
int tileX;
|
||||
int tileY;
|
||||
class Label extends TextItem {
|
||||
TextItem item;
|
||||
|
||||
boolean isTileNeighbour(PlacementItem other) {
|
||||
int dx = other.tileX - tileX;
|
||||
if (dx > 1 || dx < -1)
|
||||
return false;
|
||||
Link blocking;
|
||||
Link blockedBy;
|
||||
|
||||
int dy = other.tileY - tileY;
|
||||
if (dy > 1 || dy < -1)
|
||||
return false;
|
||||
// shared list of all label for a tile
|
||||
Link siblings;
|
||||
|
||||
return true;
|
||||
}
|
||||
MapTile tile;
|
||||
|
||||
public byte origin;
|
||||
public int active;
|
||||
public OBB2D bbox;
|
||||
}
|
||||
|
||||
class Link {
|
||||
Link next;
|
||||
Link prev;
|
||||
Label it;
|
||||
}
|
||||
|
||||
//private static void setOBB(TextItem ti){
|
||||
@ -147,35 +156,35 @@ public class TextOverlayExp extends BasicOverlay {
|
||||
//}
|
||||
|
||||
// local pool, avoids synchronized TextItem.get()/release()
|
||||
private TextItem mPool;
|
||||
private Label mPool;
|
||||
|
||||
private byte checkOverlap(TextLayer tl, TextItem ti) {
|
||||
private Label mNewLabels;
|
||||
private Label mPrevLabels;
|
||||
private final HashMap<MapTile, Link> mActiveTiles;
|
||||
|
||||
for (TextItem lp = tl.labels; lp != null;) {
|
||||
private byte checkOverlap(TextLayer tl, Label ti) {
|
||||
|
||||
for (Label lp = (Label) tl.labels; lp != null;) {
|
||||
|
||||
// check bounding box
|
||||
if (!TextItem.bboxOverlaps(ti, lp, 100)) {
|
||||
lp = lp.next;
|
||||
if (!TextItem.bboxOverlaps(ti, lp, 150)) {
|
||||
lp = (Label) lp.next;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (lp.text == ti.text && (lp.string == ti.string || lp.string.equals(ti.string))) {
|
||||
|
||||
if (lp.active <= ti.active)
|
||||
return 1;
|
||||
|
||||
// make strings unique
|
||||
ti.string = lp.string;
|
||||
|
||||
//p.active < ti.active ||
|
||||
|
||||
//Log.d(TAG, "overlap, same label in bbox " + lp.string
|
||||
// + " at " + ti.x + ":" + ti.y + ", " + lp.x + ":"
|
||||
//+ lp.y + " " + ti.length + "/" + lp.length);
|
||||
|
||||
if (lp.length < ti.length) {
|
||||
Label tmp = lp;
|
||||
lp = (Label) lp.next;
|
||||
|
||||
//if (lp.length > ti.length) {
|
||||
//Log.d(TAG, "drop " + lp.string);
|
||||
TextItem tmp = lp;
|
||||
lp = lp.next;
|
||||
|
||||
TextItem.release(tmp.item);
|
||||
tl.removeText(tmp);
|
||||
|
||||
tmp.next = mPool;
|
||||
@ -199,19 +208,20 @@ public class TextOverlayExp extends BasicOverlay {
|
||||
|
||||
boolean intersect = ti.bbox.overlaps(lp.bbox);
|
||||
|
||||
// byte intersect = GeometryUtils.linesIntersect(
|
||||
// ti.x1, ti.y1, ti.x2, ti.y2,
|
||||
// lp.x1, lp.y1, lp.x2, lp.y2);
|
||||
|
||||
if (intersect) {
|
||||
|
||||
if (lp.active <= ti.active)
|
||||
return 1;
|
||||
|
||||
//Log.d(TAG, "intersection " + lp.string + " <> " + ti.string
|
||||
// + " at " + ti.x + ":" + ti.y);
|
||||
|
||||
if (!lp.text.caption
|
||||
&& (lp.text.priority > ti.text.priority || lp.length < ti.length)) {
|
||||
TextItem tmp = lp;
|
||||
lp = lp.next;
|
||||
Label tmp = lp;
|
||||
lp = (Label) lp.next;
|
||||
|
||||
TextItem.release(tmp.item);
|
||||
tl.removeText(tmp);
|
||||
|
||||
tmp.next = mPool;
|
||||
@ -221,42 +231,66 @@ public class TextOverlayExp extends BasicOverlay {
|
||||
}
|
||||
|
||||
return 1;
|
||||
|
||||
// if ((lp.n1 != null && lp.n1 == ti.n2) ||
|
||||
// (lp.n2 != null && lp.n2 == ti.n1)) {
|
||||
// Log.d(TAG, "overlap with adjacent label " + lp.string
|
||||
// + " at " + ti.x + ":" + ti.y + ", " + lp.x + ":" + lp.y);
|
||||
//
|
||||
// return intersect;
|
||||
// }
|
||||
//
|
||||
// if ((ti.n1 != null || ti.n2 != null) && (lp.n1 == null && lp.n2 == null)) {
|
||||
// Log.d(TAG, "overlap, other is unique " + lp.string + " " + ti.string
|
||||
// + " at " + ti.x + ":" + ti.y + ", " + lp.x + ":" + lp.y);
|
||||
// return intersect;
|
||||
// }
|
||||
//
|
||||
// return intersect;
|
||||
}
|
||||
|
||||
lp = lp.next;
|
||||
lp = (Label) lp.next;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
private int mMinX;
|
||||
private int mMinY;
|
||||
private int mMaxX;
|
||||
private int mMaxY;
|
||||
|
||||
private boolean isVisible(TextItem ti) {
|
||||
private boolean nodeIsVisible(TextItem ti) {
|
||||
// rough filter
|
||||
float dist = ti.x * ti.x + ti.y * ti.y;
|
||||
if (dist > mSquareRadius)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private boolean wayIsVisible(TextItem ti) {
|
||||
// rough filter
|
||||
float dist = ti.x * ti.x + ti.y * ti.y;
|
||||
if (dist < mSquareRadius)
|
||||
return true;
|
||||
|
||||
dist = ti.x1 * ti.x1 + ti.y1 * ti.y1;
|
||||
if (dist < mSquareRadius)
|
||||
return true;
|
||||
|
||||
dist = ti.x2 * ti.x2 + ti.y2 * ti.y2;
|
||||
if (dist < mSquareRadius)
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
private Layers mDebugLayer;
|
||||
private final float[] mMVP = new float[16];
|
||||
|
||||
void addTile(MapTile t) {
|
||||
|
||||
}
|
||||
private static void addDebugLayers(Layers dbg){
|
||||
dbg.clear();
|
||||
LineLayer ll = (LineLayer) dbg.getLayer(0, Layer.LINE);
|
||||
ll.line = new Line((Color.BLUE & 0xaaffffff), 1, Cap.BUTT);
|
||||
ll.width = 2;
|
||||
ll = (LineLayer) dbg.getLayer(3, Layer.LINE);
|
||||
ll.line = new Line((Color.YELLOW & 0xaaffffff), 1, Cap.BUTT);
|
||||
ll.width = 2;
|
||||
ll = (LineLayer) dbg.getLayer(1, Layer.LINE);
|
||||
ll.line = new Line((Color.RED & 0xaaffffff), 1, Cap.BUTT);
|
||||
ll.width = 2;
|
||||
ll = (LineLayer) dbg.getLayer(2, Layer.LINE);
|
||||
ll.line = new Line((Color.GREEN & 0xaaffffff), 1, Cap.BUTT);
|
||||
ll.width = 2;
|
||||
ll = (LineLayer) dbg.getLayer(4, Layer.LINE);
|
||||
ll.line = new Line((Color.CYAN & 0xaaffffff), 1, Cap.BUTT);
|
||||
ll.width = 2;
|
||||
ll = (LineLayer) dbg.getLayer(5, Layer.LINE);
|
||||
ll.line = new Line((Color.MAGENTA & 0xaaffffff), 1, Cap.BUTT);
|
||||
ll.width = 2;
|
||||
}
|
||||
|
||||
boolean updateLabels() {
|
||||
if (mTmpLayer == null)
|
||||
return false;
|
||||
@ -271,106 +305,133 @@ public class TextOverlayExp extends BasicOverlay {
|
||||
TextLayer tl = mTmpLayer;
|
||||
mTmpLayer = null;
|
||||
|
||||
mNewLabels = null;
|
||||
|
||||
Layers dbg = null; //new Layers();
|
||||
|
||||
float[] coords = mTmpCoords;
|
||||
MapPosition pos = mTmpPos;
|
||||
|
||||
synchronized (mMapViewPosition) {
|
||||
mMapViewPosition.getMapPosition(mTmpPos);
|
||||
mMapViewPosition.getMapPosition(pos);
|
||||
mMapViewPosition.getMapViewProjection(coords);
|
||||
mMapViewPosition.getMatrix(null, null, mMVP);
|
||||
}
|
||||
int mw = (mMapView.getWidth() + Tile.TILE_SIZE) / 2;
|
||||
int mh = (mMapView.getHeight() + Tile.TILE_SIZE) / 2;
|
||||
mSquareRadius = mw * mw + mh * mh;
|
||||
|
||||
// mTiles might be from another zoomlevel than the current:
|
||||
// this scales MapPosition to the zoomlevel of mTiles...
|
||||
// TODO create a helper function in MapPosition
|
||||
MapTile[] tiles = mTileSet.tiles;
|
||||
int diff = tiles[0].zoomLevel - mTmpPos.zoomLevel;
|
||||
int diff = tiles[0].zoomLevel - pos.zoomLevel;
|
||||
float div = FastMath.pow(diff);
|
||||
float scale = mTmpPos.scale * div;
|
||||
float scale = pos.scale * div;
|
||||
|
||||
double angle = Math.toRadians(mTmpPos.angle);
|
||||
double angle = Math.toRadians(pos.angle);
|
||||
float cos = (float) Math.cos(angle);
|
||||
float sin = (float) Math.sin(angle);
|
||||
|
||||
int maxx = Tile.TILE_SIZE << (mTmpPos.zoomLevel - 1);
|
||||
int maxx = Tile.TILE_SIZE << (pos.zoomLevel - 1);
|
||||
|
||||
TextItem ti2 = null;
|
||||
Label l = null;
|
||||
|
||||
if (dbg != null) {
|
||||
dbg.clear();
|
||||
LineLayer ll = (LineLayer) dbg.getLayer(0, Layer.LINE);
|
||||
ll.line = new Line((Color.BLUE & 0xaaffffff), 1, Cap.BUTT);
|
||||
ll.width = 2;
|
||||
ll = (LineLayer) dbg.getLayer(3, Layer.LINE);
|
||||
ll.line = new Line((Color.YELLOW & 0xaaffffff), 1, Cap.BUTT);
|
||||
ll.width = 2;
|
||||
ll = (LineLayer) dbg.getLayer(1, Layer.LINE);
|
||||
ll.line = new Line((Color.RED & 0xaaffffff), 1, Cap.BUTT);
|
||||
ll.width = 2;
|
||||
ll = (LineLayer) dbg.getLayer(2, Layer.LINE);
|
||||
ll.line = new Line((Color.GREEN & 0xaaffffff), 1, Cap.BUTT);
|
||||
ll.width = 2;
|
||||
}
|
||||
if (dbg != null)
|
||||
addDebugLayers(dbg);
|
||||
|
||||
for (int i = 0, n = mTileSet.cnt; i < n; i++) {
|
||||
mRelabelCnt++;
|
||||
|
||||
MapTile t = tiles[i];
|
||||
for (Label lp = mPrevLabels; lp != null; ) {
|
||||
//l.active = mRelabelCnt;
|
||||
|
||||
if (t.state == JobTile.STATE_NONE || t.state == JobTile.STATE_LOADING)
|
||||
// transform screen coordinates to tile coordinates
|
||||
float s = FastMath.pow(lp.tile.zoomLevel - pos.zoomLevel);
|
||||
float sscale = pos.scale / s;
|
||||
|
||||
if (lp.width > lp.length * sscale){
|
||||
Log.d(TAG, "- scale " + lp + " " + s + " " + sscale + " " + lp.length + " " + lp.width);
|
||||
TextItem.release(lp.item);
|
||||
lp = (Label) lp.next;
|
||||
continue;
|
||||
}
|
||||
|
||||
float dx = (float) (t.pixelX - mTmpPos.x);
|
||||
float dy = (float) (t.pixelY - mTmpPos.y);
|
||||
float dx = (float) (lp.tile.pixelX - pos.x * s);
|
||||
float dy = (float) (lp.tile.pixelY - pos.y * s);
|
||||
|
||||
// flip around date-line
|
||||
if (dx > maxx) {
|
||||
if (dx > maxx)
|
||||
dx = dx - maxx * 2;
|
||||
} else if (dx < -maxx) {
|
||||
else if (dx < -maxx)
|
||||
dx = dx + maxx * 2;
|
||||
}
|
||||
dx *= scale;
|
||||
dy *= scale;
|
||||
|
||||
for (TextItem ti = t.labels; ti != null; ti = ti.next) {
|
||||
lp.move(lp.item, dx, dy, sscale);
|
||||
|
||||
// acquire a TextItem to add to TextLayer
|
||||
if (ti2 == null) {
|
||||
if (mPool == null)
|
||||
ti2 = TextItem.get();
|
||||
else {
|
||||
ti2 = mPool;
|
||||
mPool = mPool.next;
|
||||
ti2.next = null;
|
||||
}
|
||||
}
|
||||
if (!lp.text.caption) {
|
||||
// set line endpoints relative to view to be able to
|
||||
// check intersections with label from other tiles
|
||||
float width = (lp.x2 - lp.x1) / 2f;
|
||||
float height = (lp.y2 - lp.y1) / 2f;
|
||||
|
||||
if (!ti.text.caption)
|
||||
lp.x2 = (lp.x + width);
|
||||
lp.x1 = (lp.x - width);
|
||||
lp.y2 = (lp.y + height);
|
||||
lp.y1 = (lp.y - height);
|
||||
|
||||
if (!wayIsVisible(lp)){
|
||||
Log.d(TAG, "- visible " + lp);
|
||||
TextItem.release(lp.item);
|
||||
lp = (Label) lp.next;
|
||||
continue;
|
||||
}
|
||||
|
||||
ti2.move(ti, dx, dy, scale);
|
||||
ti2.setAxisAlignedBBox();
|
||||
byte overlaps = -1;
|
||||
if (lp.bbox != null)
|
||||
lp.bbox.set(lp.x, lp.y, lp.x1, lp.y1,
|
||||
lp.width + 5, lp.text.fontHeight + 5);
|
||||
else lp.bbox= new OBB2D(lp.x, lp.y, lp.x1, lp.y1,
|
||||
lp.width + 5, lp.text.fontHeight + 5);
|
||||
|
||||
ti2.bbox = new OBB2D(ti2.x, ti2.y, cos, -sin, ti2.width + 6,
|
||||
ti2.text.fontHeight + 6, true);
|
||||
if (dbg != null) {
|
||||
|
||||
boolean overlaps = false;
|
||||
for (TextItem lp = tl.labels; lp != null; lp = lp.next) {
|
||||
if (!lp.text.caption)
|
||||
continue;
|
||||
LineLayer ll;
|
||||
if (overlaps == 1)
|
||||
ll = (LineLayer) dbg.getLayer(4, Layer.LINE);
|
||||
else
|
||||
ll = (LineLayer) dbg.getLayer(5, Layer.LINE);
|
||||
|
||||
if (ti2.bbox.overlaps(lp.bbox)) {
|
||||
Log.d(TAG, "overlap > " + ti2.string + " " + lp.string);
|
||||
//if (TextItem.bboxOverlaps(ti2, lp, 4)) {
|
||||
overlaps = true;
|
||||
break;
|
||||
{
|
||||
float[] points = new float[4];
|
||||
short[] indices = { 4 };
|
||||
points[0] = (lp.x - width * sscale);
|
||||
points[1] = (lp.y - height * sscale);
|
||||
points[2] = (lp.x + width * sscale);
|
||||
points[3] = (lp.y + height * sscale);
|
||||
ll.addLine(points, indices, false);
|
||||
}
|
||||
if (lp.bbox != null) {
|
||||
short[] indices = { 8 };
|
||||
ll.addLine(lp.bbox.corner, indices, true);
|
||||
}
|
||||
}
|
||||
if (!overlaps) {
|
||||
tl.addText(ti2);
|
||||
ti2 = null;
|
||||
}
|
||||
|
||||
overlaps = checkOverlap(tl, lp);
|
||||
|
||||
if (overlaps == 0) {
|
||||
if (s != 1)
|
||||
Log.d(TAG, s + "add prev label " + lp);
|
||||
|
||||
Label tmp = lp;
|
||||
lp = (Label) lp.next;
|
||||
|
||||
tmp.next = null;
|
||||
tl.addText(tmp);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
TextItem.release(lp.item);
|
||||
lp = (Label) lp.next;
|
||||
}
|
||||
|
||||
/* add way labels */
|
||||
@ -378,20 +439,14 @@ public class TextOverlayExp extends BasicOverlay {
|
||||
|
||||
MapTile t = tiles[i];
|
||||
|
||||
if (t.state == JobTile.STATE_NONE || t.state == JobTile.STATE_LOADING)
|
||||
continue;
|
||||
|
||||
float dx = (float) (t.pixelX - mTmpPos.x);
|
||||
float dy = (float) (t.pixelY - mTmpPos.y);
|
||||
float dx = (float) (t.pixelX - pos.x);
|
||||
float dy = (float) (t.pixelY - pos.y);
|
||||
|
||||
// flip around date-line
|
||||
if (dx > maxx) {
|
||||
if (dx > maxx)
|
||||
dx = dx - maxx * 2;
|
||||
} else if (dx < -maxx) {
|
||||
else if (dx < -maxx)
|
||||
dx = dx + maxx * 2;
|
||||
}
|
||||
dx *= scale;
|
||||
dy *= scale;
|
||||
|
||||
for (TextItem ti = t.labels; ti != null; ti = ti.next) {
|
||||
|
||||
@ -399,36 +454,41 @@ public class TextOverlayExp extends BasicOverlay {
|
||||
continue;
|
||||
|
||||
// acquire a TextItem to add to TextLayer
|
||||
if (ti2 == null) {
|
||||
if (l == null) {
|
||||
if (mPool == null)
|
||||
ti2 = TextItem.get();
|
||||
l = new Label();
|
||||
else {
|
||||
ti2 = mPool;
|
||||
mPool = mPool.next;
|
||||
ti2.next = null;
|
||||
l = mPool;
|
||||
mPool = (Label) mPool.next;
|
||||
l.next = null;
|
||||
}
|
||||
l.active = Integer.MAX_VALUE;
|
||||
}
|
||||
|
||||
// check if path at current scale is long enough for text
|
||||
if (dbg == null && ti.width > ti.length * scale)
|
||||
continue;
|
||||
|
||||
l.clone(ti);
|
||||
l.move(ti, dx, dy, scale);
|
||||
|
||||
// set line endpoints relative to view to be able to
|
||||
// check intersections with label from other tiles
|
||||
float width = (ti.x2 - ti.x1) / 2f;
|
||||
float height = (ti.y2 - ti.y1) / 2f;
|
||||
ti2.bbox = null;
|
||||
l.bbox = null;
|
||||
l.x2 = (l.x + width);
|
||||
l.x1 = (l.x - width);
|
||||
l.y2 = (l.y + height);
|
||||
l.y1 = (l.y - height);
|
||||
|
||||
ti2.move(ti, dx, dy, scale);
|
||||
ti2.x2 = (ti2.x + width);
|
||||
ti2.x1 = (ti2.x - width);
|
||||
ti2.y2 = (ti2.y + height);
|
||||
ti2.y1 = (ti2.y - height);
|
||||
if (!wayIsVisible(l))
|
||||
continue;
|
||||
|
||||
byte overlaps = -1;
|
||||
|
||||
if (dbg == null || ti.width < ti.length * scale)
|
||||
overlaps = checkOverlap(tl, ti2);
|
||||
overlaps = checkOverlap(tl, l);
|
||||
|
||||
if (dbg != null) {
|
||||
|
||||
@ -451,35 +511,93 @@ public class TextOverlayExp extends BasicOverlay {
|
||||
{
|
||||
float[] points = new float[4];
|
||||
short[] indices = { 4 };
|
||||
points[0] = (ti2.x - width * scale) / scale;
|
||||
points[1] = (ti2.y - height * scale) / scale;
|
||||
points[2] = (ti2.x + width * scale) / scale;
|
||||
points[3] = (ti2.y + height * scale) / scale;
|
||||
points[0] = (l.x - width * scale);
|
||||
points[1] = (l.y - height * scale);
|
||||
points[2] = (l.x + width * scale);
|
||||
points[3] = (l.y + height * scale);
|
||||
ll.addLine(points, indices, false);
|
||||
}
|
||||
if (ti2.bbox != null) {
|
||||
if (l.bbox != null) {
|
||||
short[] indices = { 8 };
|
||||
float[] points = new float[8];
|
||||
for (int p = 0; p < 8; p++)
|
||||
points[p] = ti2.bbox.corner[p] / scale;
|
||||
|
||||
ll.addLine(points, indices, true);
|
||||
ll.addLine(l.bbox.corner, indices, true);
|
||||
}
|
||||
}
|
||||
if (overlaps == 0) {
|
||||
ti.active++;
|
||||
|
||||
tl.addText(ti2);
|
||||
ti2.active = ti.active;
|
||||
ti2 = null;
|
||||
tl.addText(l);
|
||||
l.item = TextItem.copy(ti);
|
||||
l.tile = t;
|
||||
l.active = mRelabelCnt;
|
||||
l = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (TextItem ti = tl.labels; ti != null; ti = ti.next) {
|
||||
// scale back to fixed zoom-level. could be done in setMatrix
|
||||
ti.x /= scale;
|
||||
ti.y /= scale;
|
||||
for (int i = 0, n = mTileSet.cnt; i < n; i++) {
|
||||
|
||||
MapTile t = tiles[i];
|
||||
|
||||
float dx = (float) (t.pixelX - pos.x);
|
||||
float dy = (float) (t.pixelY - pos.y);
|
||||
|
||||
// flip around date-line
|
||||
if (dx > maxx)
|
||||
dx = dx - maxx * 2;
|
||||
else if (dx < -maxx)
|
||||
dx = dx + maxx * 2;
|
||||
|
||||
for (TextItem ti = t.labels; ti != null; ti = ti.next) {
|
||||
if (!ti.text.caption)
|
||||
continue;
|
||||
|
||||
// acquire a TextItem to add to TextLayer
|
||||
if (l == null) {
|
||||
if (mPool == null)
|
||||
l = new Label();
|
||||
else {
|
||||
l = mPool;
|
||||
mPool = (Label) mPool.next;
|
||||
l.next = null;
|
||||
}
|
||||
l.active = Integer.MAX_VALUE;
|
||||
}
|
||||
|
||||
l.clone(ti);
|
||||
l.move(ti, dx, dy, scale);
|
||||
if (!nodeIsVisible(l))
|
||||
continue;
|
||||
|
||||
l.setAxisAlignedBBox();
|
||||
|
||||
l.bbox = new OBB2D(l.x, l.y, cos, -sin, l.width + 6,
|
||||
l.text.fontHeight + 6, true);
|
||||
|
||||
boolean overlaps = false;
|
||||
for (Label lp = (Label) tl.labels; lp != null; lp = (Label) lp.next) {
|
||||
//if (!lp.text.caption)
|
||||
// continue;
|
||||
if (lp.bbox == null) {
|
||||
lp.bbox = new OBB2D(lp.x, lp.y, lp.x1, lp.y1,
|
||||
lp.width + 5, lp.text.fontHeight + 5);
|
||||
}
|
||||
|
||||
if (l.bbox.overlaps(lp.bbox)) {
|
||||
//Log.d(TAG, "overlap > " + ti2.string + " " + lp.string);
|
||||
//if (TextItem.bboxOverlaps(ti2, lp, 4)) {
|
||||
overlaps = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!overlaps) {
|
||||
tl.addText(l);
|
||||
l.item = TextItem.copy(ti);
|
||||
l.tile = t;
|
||||
l.active = mRelabelCnt;
|
||||
l = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (Label ti = (Label)tl.labels; ti != null; ti = (Label)ti.next) {
|
||||
|
||||
if (ti.text.caption)
|
||||
continue;
|
||||
@ -497,19 +615,18 @@ public class TextOverlayExp extends BasicOverlay {
|
||||
}
|
||||
|
||||
// release temporarily used TextItems
|
||||
if (ti2 != null) {
|
||||
ti2.next = mPool;
|
||||
mPool = ti2;
|
||||
}
|
||||
if (mPool != null) {
|
||||
TextItem.release(mPool);
|
||||
mPool = null;
|
||||
if (l != null) {
|
||||
l.next = mPool;
|
||||
mPool = l;
|
||||
}
|
||||
|
||||
// draw text to bitmaps and create vertices
|
||||
tl.setScale(scale);
|
||||
tl.prepare();
|
||||
|
||||
// after 'prepare' TextLayer does not need TextItems any longer
|
||||
mPrevLabels = (Label) tl.labels;
|
||||
tl.labels = null;
|
||||
|
||||
// remove tile locks
|
||||
GLRenderer.releaseTiles(mTileSet);
|
||||
|
||||
@ -530,6 +647,7 @@ public class TextOverlayExp extends BasicOverlay {
|
||||
mTmpLayer = (TextLayer) layers.textureLayers;
|
||||
|
||||
// clear textures and text items from previous layer
|
||||
layers.textureLayers = null;
|
||||
layers.clear();
|
||||
|
||||
if (mDebugLayer != null) {
|
||||
@ -589,13 +707,15 @@ public class TextOverlayExp extends BasicOverlay {
|
||||
GLState.test(false, false);
|
||||
|
||||
if (layers.layers != null) {
|
||||
setMatrix(pos, m);
|
||||
Matrix.multiplyMM(m.mvp, 0, m.proj, 0, m.mvp,0);
|
||||
setMatrix(pos, m, true);
|
||||
|
||||
//Matrix.multiplyMM(m.mvp, 0, m.proj, 0, m.mvp,0);
|
||||
for (Layer l = layers.layers; l != null;) {
|
||||
if (l.type == Layer.POLYGON) {
|
||||
l = PolygonRenderer.draw(pos, l, m.mvp, true, false);
|
||||
} else {
|
||||
l = LineRenderer.draw(pos, l, m.mvp, div, 0, layers.lineOffset);
|
||||
float scale = pos.scale * div;
|
||||
l = LineRenderer.draw(pos, l, m.mvp, scale, 0, layers.lineOffset);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -603,6 +723,7 @@ public class TextOverlayExp extends BasicOverlay {
|
||||
setMatrix(pos, m);
|
||||
for (Layer l = layers.textureLayers; l != null;) {
|
||||
float scale = (mMapPosition.scale / pos.scale) * div;
|
||||
|
||||
l = TextureRenderer.draw(l, scale, m.proj, m.mvp);
|
||||
}
|
||||
|
||||
@ -616,9 +737,9 @@ public class TextOverlayExp extends BasicOverlay {
|
||||
float x = (float) (oPos.x - curPos.x * div);
|
||||
float y = (float) (oPos.y - curPos.y * div);
|
||||
|
||||
float scale = curPos.scale / div;
|
||||
|
||||
GlUtils.setMatrix(m.mvp, x * scale, y * scale,
|
||||
float scale = (curPos.scale / mMapPosition.scale) / div;
|
||||
float s = curPos.scale / div;
|
||||
GlUtils.setMatrix(m.mvp, x * s, y * s,
|
||||
scale / GLRenderer.COORD_MULTIPLIER);
|
||||
|
||||
Matrix.multiplyMM(m.mvp, 0, m.view, 0, m.mvp, 0);
|
||||
|
@ -167,7 +167,8 @@ public final class Text extends RenderInstruction {
|
||||
|
||||
FontMetrics fm = paint.getFontMetrics();
|
||||
fontHeight = (float) Math.ceil(Math.abs(fm.bottom) + Math.abs(fm.top));
|
||||
fontDescent = (float) Math.ceil(Math.abs(fm.descent));
|
||||
//fontDescent = (float) Math.ceil(Math.abs(fm.descent));
|
||||
fontDescent = Math.abs(fm.bottom);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -991,14 +991,22 @@
|
||||
|
||||
<!-- place -->
|
||||
<rule e="node" k="place" v="*">
|
||||
<rule e="node" k="*" v="suburb|town|village">
|
||||
<caption k="name" font-size="17" fill="#2020bb"
|
||||
<rule e="node" k="*" v="suburb" zoom-max="14">
|
||||
<caption k="name" font-size="17" fill="#bb2020"
|
||||
stroke="#ffffff" stroke-width="2.0" />
|
||||
</rule>
|
||||
<rule e="node" k="*" v="village" zoom-max="14">
|
||||
<caption k="name" font-size="17" fill="#2020cc"
|
||||
stroke="#ffffff" stroke-width="2.0" />
|
||||
</rule>
|
||||
<rule e="node" k="*" v="island" zoom-min="10">
|
||||
<caption k="name" font-style="bold" font-size="20" fill="#000000"
|
||||
stroke="#ffffff" stroke-width="2.0" />
|
||||
</rule>
|
||||
<rule e="node" k="*" v="town">
|
||||
<caption k="name" font-size="19" fill="#000000"
|
||||
stroke="#ffffff" stroke-width="2.0" />
|
||||
</rule>
|
||||
<rule e="node" k="*" v="city">
|
||||
<caption k="name" font-size="20" fill="#000000"
|
||||
stroke="#ffffff" stroke-width="2.0" />
|
||||
|
@ -329,5 +329,37 @@ public final class GeometryUtils {
|
||||
return inside;
|
||||
}
|
||||
|
||||
public static float areaSigned(Point p1, Point p2, Point p3) {
|
||||
return ((p1.x - p3.x) * (p2.y - p3.y) - (p2.x - p3.x) * (p1.y - p3.y))*0.5f;
|
||||
}
|
||||
|
||||
public static float areaSigned(float ax, float ay, float bx, float by, float cx, float cy) {
|
||||
return ((ax - cx) * (by - cy) - (bx - cx) * (ay - cy)) * 0.5f;
|
||||
}
|
||||
|
||||
public static float area(float ax, float ay, float bx, float by, float cx, float cy) {
|
||||
float area = ((ax - cx) * (by - cy) - (bx - cx) * (ay - cy)) * 0.5f;
|
||||
return area < 0 ? -area : area;
|
||||
}
|
||||
|
||||
public static boolean pointInTri(Point pt, Point p1, Point p2, Point p3) {
|
||||
boolean inside = false;
|
||||
boolean p1s = p1.y > pt.y;
|
||||
boolean p2s = p2.y > pt.y;
|
||||
boolean p3s = p3.y > pt.y;
|
||||
|
||||
if ((p1s != p3s)
|
||||
&& (pt.x < (p3.x - p1.x) * (pt.y - p1.y) / (p3.y - p1.y) + p1.x))
|
||||
inside = !inside;
|
||||
|
||||
if ((p2s != p1s)
|
||||
&& (pt.x < (p1.x - p2.x) * (pt.y - p2.y) / (p1.y - p2.y) + p2.x))
|
||||
inside = !inside;
|
||||
|
||||
if ((p3s != p2s)
|
||||
&& (pt.x < (p2.x - p3.x) * (pt.y - p3.y) / (p2.y - p3.y) + p3.x))
|
||||
inside = !inside;
|
||||
|
||||
return inside;
|
||||
}
|
||||
}
|
||||
|
@ -15,9 +15,10 @@
|
||||
package org.oscim.utils;
|
||||
|
||||
/**
|
||||
* @author Hannes Janetzek
|
||||
* taken from http://en.wikipedia.org/wiki/Cohen%E2%80%93
|
||||
* Sutherland_algorithm
|
||||
* from http://en.wikipedia.org/wiki/Cohen%E2%80%93
|
||||
* Sutherland_algorithm
|
||||
*
|
||||
* @adapted by Hannes Janetzek
|
||||
*/
|
||||
|
||||
public class LineClipper {
|
||||
@ -28,19 +29,35 @@ public class LineClipper {
|
||||
private static final int BOTTOM = 4; // 0100
|
||||
private static final int TOP = 8; // 1000
|
||||
|
||||
private int xmin, xmax, ymin, ymax;
|
||||
private final int xmin, xmax, ymin, ymax;
|
||||
public final int[] out;
|
||||
|
||||
public LineClipper(int minx, int miny, int maxx, int maxy) {
|
||||
this.xmin = minx;
|
||||
this.ymin = miny;
|
||||
this.xmax = maxx;
|
||||
this.ymax = maxy;
|
||||
this.out = null;
|
||||
}
|
||||
|
||||
public LineClipper(int minx, int miny, int maxx, int maxy, boolean keepResult) {
|
||||
this.xmin = minx;
|
||||
this.ymin = miny;
|
||||
this.xmax = maxx;
|
||||
this.ymax = maxy;
|
||||
if (keepResult)
|
||||
this.out = new int[4];
|
||||
else
|
||||
this.out = null;
|
||||
}
|
||||
|
||||
private int mPrevOutcode;
|
||||
private int mPrevX;
|
||||
private int mPrevY;
|
||||
|
||||
public int outX;
|
||||
public int outY;
|
||||
|
||||
public void clipStart(int x0, int y0) {
|
||||
mPrevX = x0;
|
||||
mPrevY = y0;
|
||||
@ -58,8 +75,13 @@ public class LineClipper {
|
||||
mPrevOutcode = outcode;
|
||||
}
|
||||
|
||||
public boolean clipNext(int x1, int y1) {
|
||||
boolean accept;
|
||||
/**
|
||||
* @param x1 ...
|
||||
* @param y1 ...
|
||||
* @return 0 if not intersection, 1 fully within, -1 clipped (and 'out' set to new points)
|
||||
*/
|
||||
public int clipNext(int x1, int y1) {
|
||||
int accept;
|
||||
|
||||
int outcode = INSIDE;
|
||||
if (x1 < xmin)
|
||||
@ -73,12 +95,13 @@ public class LineClipper {
|
||||
|
||||
if ((mPrevOutcode | outcode) == 0) {
|
||||
// Bitwise OR is 0. Trivially accept
|
||||
accept = true;
|
||||
accept = 1;
|
||||
} else if ((mPrevOutcode & outcode) != 0) {
|
||||
// Bitwise AND is not 0. Trivially reject
|
||||
accept = false;
|
||||
accept = 0;
|
||||
} else {
|
||||
accept = clip(mPrevX, mPrevY, x1, y1, xmin, ymin, xmax, ymax, mPrevOutcode, outcode);
|
||||
accept = clip(mPrevX, mPrevY, x1, y1, xmin, ymin, xmax, ymax, mPrevOutcode, outcode,
|
||||
this.out) ? -1 : 0;
|
||||
}
|
||||
mPrevOutcode = outcode;
|
||||
mPrevX = x1;
|
||||
@ -91,7 +114,7 @@ public class LineClipper {
|
||||
// P0 = (x0, y0) to P1 = (x1, y1) against a rectangle with
|
||||
// diagonal from (xmin, ymin) to (xmax, ymax).
|
||||
private static boolean clip(int x0, int y0, int x1, int y1,
|
||||
int xmin, int ymin, int xmax, int ymax, int outcode0, int outcode1) {
|
||||
int xmin, int ymin, int xmax, int ymax, int outcode0, int outcode1, int[] out) {
|
||||
|
||||
boolean accept = false;
|
||||
|
||||
@ -154,9 +177,12 @@ public class LineClipper {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// TODO could do sth with the result x0...
|
||||
if (accept && out != null) {
|
||||
out[0] = x0;
|
||||
out[1] = y0;
|
||||
out[2] = x1;
|
||||
out[3] = y1;
|
||||
}
|
||||
return accept;
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -158,6 +158,37 @@ public class OBB2D {
|
||||
computeAxes();
|
||||
}
|
||||
|
||||
public void set(float cx, float cy, float dx, float dy, float width, float height){
|
||||
float vx = cx - dx;
|
||||
float vy = cy - dy;
|
||||
|
||||
float a = (float) Math.sqrt(vx * vx + vy * vy);
|
||||
vx /= a;
|
||||
vy /= a;
|
||||
|
||||
float hw = width / 2;
|
||||
float hh = height / 2;
|
||||
|
||||
float ux = vy * hh;
|
||||
float uy = -vx * hh;
|
||||
|
||||
vx *= hw;
|
||||
vy *= hw;
|
||||
|
||||
corner[0] = cx - vx - ux;
|
||||
corner[1] = cy - vy - uy;
|
||||
|
||||
corner[2] = cx + vx - ux;
|
||||
corner[3] = cy + vy - uy;
|
||||
|
||||
corner[4] = cx + vx + ux;
|
||||
corner[5] = cy + vy + uy;
|
||||
|
||||
corner[6] = cx - vx + ux;
|
||||
corner[7] = cy - vy + uy;
|
||||
|
||||
computeAxes();
|
||||
}
|
||||
public OBB2D(float cx, float cy, float dx, float dy, float width, float height) {
|
||||
|
||||
float vx = cx - dx;
|
||||
|
Loading…
x
Reference in New Issue
Block a user