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