add more labels as they fit at current scale
This commit is contained in:
parent
5c36b204ce
commit
3c990b3289
@ -14,9 +14,9 @@
|
|||||||
*/
|
*/
|
||||||
package org.oscim.renderer;
|
package org.oscim.renderer;
|
||||||
|
|
||||||
|
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;
|
|
||||||
|
|
||||||
public final class WayDecorator {
|
public final class WayDecorator {
|
||||||
// /**
|
// /**
|
||||||
@ -27,7 +27,7 @@ public final class WayDecorator {
|
|||||||
// /**
|
// /**
|
||||||
// * Minimum distance in pixels before the way name is repeated.
|
// * Minimum distance in pixels before the way name is repeated.
|
||||||
// */
|
// */
|
||||||
// private static final int DISTANCE_BETWEEN_WAY_NAMES = 500;
|
private static final int DISTANCE_BETWEEN_WAY_NAMES = 100;
|
||||||
|
|
||||||
// /**
|
// /**
|
||||||
// * Distance in pixels to skip from both ends of a segment.
|
// * Distance in pixels to skip from both ends of a segment.
|
||||||
@ -104,95 +104,118 @@ public final class WayDecorator {
|
|||||||
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 = 100;
|
float minWidth = Tile.TILE_SIZE / 10;
|
||||||
int skipPixels = 0;
|
int skipPixels = 0;
|
||||||
|
|
||||||
// get the first way point coordinates
|
// get the first way point coordinates
|
||||||
int previousX = (int) coordinates[pos + 0];
|
int prevX = (int) coordinates[pos + 0];
|
||||||
int previousY = (int) coordinates[pos + 1];
|
int prevY = (int) coordinates[pos + 1];
|
||||||
|
if (string.equals("Filip Road")) {
|
||||||
|
System.out.println("blub");
|
||||||
|
}
|
||||||
// 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 + 2; i < pos + len; i += 2) {
|
||||||
// get the current way point coordinates
|
// get the current way point coordinates
|
||||||
int currentX = (int) coordinates[i];
|
int curX = (int) coordinates[i];
|
||||||
int currentY = (int) coordinates[i + 1];
|
int curY = (int) coordinates[i + 1];
|
||||||
|
|
||||||
// calculate the length of the current segment (Euclidian distance)
|
// calculate the length of the current segment (Euclidian distance)
|
||||||
float diffX = currentX - previousX;
|
float vx = prevX - curX;
|
||||||
float diffY = currentY - previousY;
|
float vy = prevY - curY;
|
||||||
|
float a = (float) Math.sqrt(vx * vx + vy * vy);
|
||||||
|
vx /= a;
|
||||||
|
vy /= a;
|
||||||
|
|
||||||
for (int j = i + 2; j < pos + len; j += 2) {
|
int last = i;
|
||||||
int nextX = (int) coordinates[j];
|
int nextX = 0, nextY = 0;
|
||||||
int nextY = (int) coordinates[j + 1];
|
|
||||||
|
|
||||||
if (diffY == 0) {
|
// add additional segments if possible
|
||||||
if ((currentY - nextY) != 0)
|
for (int j = last + 2; j < pos + len; j += 2) {
|
||||||
|
nextX = (int) coordinates[j];
|
||||||
|
nextY = (int) coordinates[j + 1];
|
||||||
|
|
||||||
|
float wx = curX - nextX;
|
||||||
|
float wy = curY - nextY;
|
||||||
|
|
||||||
|
a = (float) Math.sqrt(wx * wx + wy * wy);
|
||||||
|
wx /= a;
|
||||||
|
wy /= a;
|
||||||
|
|
||||||
|
float ux = vx + wx;
|
||||||
|
float uy = vy + wy;
|
||||||
|
|
||||||
|
float diff = wx * uy - wy * ux;
|
||||||
|
|
||||||
|
if (diff > 0.1 || diff < -0.1)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
currentX = nextX;
|
last = j;
|
||||||
currentY = nextY;
|
curX = nextX;
|
||||||
continue;
|
curY = nextY;
|
||||||
} else if ((currentY - nextY) == 0)
|
|
||||||
break;
|
|
||||||
|
|
||||||
float diff = diffX / diffY -
|
|
||||||
(float) (currentX - nextX) / (currentY - nextY);
|
|
||||||
|
|
||||||
// skip segments with corners
|
|
||||||
if (diff >= 0.1f || diff <= -0.1f)
|
|
||||||
break;
|
|
||||||
|
|
||||||
currentX = nextX;
|
|
||||||
currentY = nextY;
|
|
||||||
}
|
|
||||||
|
|
||||||
diffX = currentX - previousX;
|
|
||||||
diffY = currentY - previousY;
|
|
||||||
|
|
||||||
if (diffX < 0)
|
|
||||||
diffX = -diffX;
|
|
||||||
if (diffY < 0)
|
|
||||||
diffY = -diffY;
|
|
||||||
|
|
||||||
if (diffX + diffY < minWidth) {
|
|
||||||
previousX = currentX;
|
|
||||||
previousY = currentY;
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (wayNameWidth > 0 && diffX + diffY < wayNameWidth) {
|
vx = curX - prevX;
|
||||||
previousX = currentX;
|
vy = curY - prevY;
|
||||||
previousY = currentY;
|
|
||||||
|
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;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
double segmentLengthInPixel = Math.sqrt(diffX * diffX + diffY * diffY);
|
// 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;
|
||||||
|
}
|
||||||
|
|
||||||
|
double segmentLength = Math.sqrt(vx * vx + vy * vy);
|
||||||
|
|
||||||
if (skipPixels > 0) {
|
if (skipPixels > 0) {
|
||||||
skipPixels -= segmentLengthInPixel;
|
skipPixels -= segmentLength;
|
||||||
|
|
||||||
} else if (segmentLengthInPixel > minWidth) {
|
} else if (segmentLength < minWidth) {
|
||||||
|
// restart from next node
|
||||||
|
prevX = (int) coordinates[i];
|
||||||
|
prevY = (int) coordinates[i + 1];
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
if (wayNameWidth < 0) {
|
if (wayNameWidth < 0) {
|
||||||
wayNameWidth = text.paint.measureText(string);
|
wayNameWidth = text.paint.measureText(string);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (segmentLengthInPixel > wayNameWidth * 0.80) {
|
if (segmentLength < wayNameWidth * 0.50) {
|
||||||
|
// restart from next node
|
||||||
|
prevX = (int) coordinates[i];
|
||||||
|
prevY = (int) coordinates[i + 1];
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
float s = (wayNameWidth + 25) / (float) segmentLengthInPixel;
|
float s = wayNameWidth / (float) segmentLength;
|
||||||
int width, height;
|
int width, height;
|
||||||
int x1, y1, x2, y2;
|
int x1, y1, x2, y2;
|
||||||
|
|
||||||
if (previousX < currentX) {
|
if (prevX < curX) {
|
||||||
x1 = previousX;
|
x1 = prevX;
|
||||||
y1 = previousY;
|
y1 = prevY;
|
||||||
x2 = currentX;
|
x2 = curX;
|
||||||
y2 = currentY;
|
y2 = curY;
|
||||||
} else {
|
} else {
|
||||||
x1 = currentX;
|
x1 = curX;
|
||||||
y1 = currentY;
|
y1 = curY;
|
||||||
x2 = previousX;
|
x2 = prevX;
|
||||||
y2 = previousY;
|
y2 = prevY;
|
||||||
}
|
}
|
||||||
|
|
||||||
// estimate position of text on path
|
// estimate position of text on path
|
||||||
@ -204,47 +227,41 @@ public final class WayDecorator {
|
|||||||
y2 = y2 - (int) (height - s * height);
|
y2 = y2 - (int) (height - s * height);
|
||||||
y1 = y1 + (int) (height - s * height);
|
y1 = y1 + (int) (height - s * height);
|
||||||
|
|
||||||
short top = (short) (y1 < y2 ? y1 : y2);
|
// short top = (short) (y1 < y2 ? y1 : y2);
|
||||||
short bot = (short) (y1 < y2 ? y2 : y1);
|
// short bot = (short) (y1 < y2 ? y2 : y1);
|
||||||
|
// boolean intersects = false;
|
||||||
|
//
|
||||||
|
// for (TextItem t2 = items; t2 != null; t2 = t2.next) {
|
||||||
|
//
|
||||||
|
// // check crossings
|
||||||
|
// if (GeometryUtils.lineIntersect(x1, y1, x2, y2, t2.x1, t2.y1,
|
||||||
|
// t2.x2, t2.y2)) {
|
||||||
|
// intersects = true;
|
||||||
|
// break;
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// // check overlapping labels of road with more than one
|
||||||
|
// // way
|
||||||
|
// short top2 = t2.y1 < t2.y2 ? t2.y1 : t2.y2;
|
||||||
|
// short bot2 = t2.y1 < t2.y2 ? t2.y2 : t2.y1;
|
||||||
|
//
|
||||||
|
// if (x1 - 10 < t2.x2 && t2.x1 - 10 < x2 && top - 10 < bot2
|
||||||
|
// && top2 - 10 < bot) {
|
||||||
|
//
|
||||||
|
// if (t2.string.equals(string)) {
|
||||||
|
// intersects = true;
|
||||||
|
// break;
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// if (intersects) {
|
||||||
|
// previousX = (int) coordinates[pos + i];
|
||||||
|
// previousY = (int) coordinates[pos + i + 1];
|
||||||
|
// continue;
|
||||||
|
// }
|
||||||
|
|
||||||
boolean intersects = false;
|
|
||||||
|
|
||||||
for (TextItem t2 = items; t2 != null; t2 = t2.next) {
|
|
||||||
|
|
||||||
// check crossings
|
|
||||||
if (GeometryUtils.lineIntersect(x1, y1, x2, y2, t2.x1, t2.y1,
|
|
||||||
t2.x2, t2.y2)) {
|
|
||||||
intersects = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
// check overlapping labels of road with more than one
|
|
||||||
// way
|
|
||||||
short top2 = t2.y1 < t2.y2 ? t2.y1 : t2.y2;
|
|
||||||
short bot2 = t2.y1 < t2.y2 ? t2.y2 : t2.y1;
|
|
||||||
|
|
||||||
if (x1 - 10 < t2.x2 && t2.x1 - 10 < x2 && top - 10 < bot2
|
|
||||||
&& top2 - 10 < bot) {
|
|
||||||
|
|
||||||
if (t2.string.equals(string)) {
|
|
||||||
intersects = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (intersects) {
|
|
||||||
previousX = (int) coordinates[pos + i];
|
|
||||||
previousY = (int) coordinates[pos + i + 1];
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
// if (t == null)
|
|
||||||
t = TextItem.get();
|
t = TextItem.get();
|
||||||
// t = new TextItem(x1 + (x2 - x1) / 2, y1 + (y2 - y1) / 2,
|
|
||||||
// string,
|
|
||||||
// text, wayNameWidth);
|
|
||||||
|
|
||||||
t.x = x1 + (x2 - x1) / 2f;
|
t.x = x1 + (x2 - x1) / 2f;
|
||||||
t.y = y1 + (y2 - y1) / 2f;
|
t.y = y1 + (y2 - y1) / 2f;
|
||||||
t.string = string;
|
t.string = string;
|
||||||
@ -254,19 +271,18 @@ public final class WayDecorator {
|
|||||||
t.y1 = (short) y1;
|
t.y1 = (short) y1;
|
||||||
t.x2 = (short) x2;
|
t.x2 = (short) x2;
|
||||||
t.y2 = (short) y2;
|
t.y2 = (short) y2;
|
||||||
|
t.length = (short) segmentLength;
|
||||||
|
|
||||||
t.next = items;
|
t.next = items;
|
||||||
items = t;
|
items = t;
|
||||||
|
|
||||||
// skipPixels = DISTANCE_BETWEEN_WAY_NAMES;
|
skipPixels = DISTANCE_BETWEEN_WAY_NAMES;
|
||||||
|
|
||||||
return items;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
// skip to last
|
||||||
|
i = last;
|
||||||
// store the previous way point coordinates
|
// store the previous way point coordinates
|
||||||
previousX = currentX;
|
prevX = curX;
|
||||||
previousY = currentY;
|
prevY = curY;
|
||||||
}
|
}
|
||||||
return items;
|
return items;
|
||||||
}
|
}
|
||||||
|
@ -84,6 +84,6 @@ public class TextItem {
|
|||||||
public Text text;
|
public Text text;
|
||||||
public float width;
|
public float width;
|
||||||
public short x1, y1, x2, y2;
|
public short x1, y1, x2, y2;
|
||||||
|
public short length;
|
||||||
// public byte placement
|
// public byte placement
|
||||||
}
|
}
|
||||||
|
@ -138,14 +138,13 @@ public class TextOverlay extends RenderOverlay {
|
|||||||
|
|
||||||
for (TextItem ti = t.labels; ti != null; ti = ti.next) {
|
for (TextItem ti = t.labels; ti != null; ti = ti.next) {
|
||||||
|
|
||||||
if (ti2 == null)
|
|
||||||
ti2 = TextItem.get();
|
|
||||||
|
|
||||||
ti2.move(ti, dx, dy, scale);
|
|
||||||
|
|
||||||
boolean overlaps = false;
|
boolean overlaps = false;
|
||||||
|
|
||||||
if (ti.text.caption) {
|
if (ti.text.caption) {
|
||||||
|
if (ti2 == null)
|
||||||
|
ti2 = TextItem.get();
|
||||||
|
ti2.move(ti, dx, dy, scale);
|
||||||
|
|
||||||
int tx = (int) (ti2.x);
|
int tx = (int) (ti2.x);
|
||||||
int ty = (int) (ti2.y);
|
int ty = (int) (ti2.y);
|
||||||
int tw = (int) (ti2.width / 2);
|
int tw = (int) (ti2.width / 2);
|
||||||
@ -169,6 +168,13 @@ public class TextOverlay extends RenderOverlay {
|
|||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
|
if (ti.width > ti.length * scale) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (ti2 == null)
|
||||||
|
ti2 = TextItem.get();
|
||||||
|
ti2.move(ti, dx, dy, scale);
|
||||||
|
|
||||||
if (cos * (ti.x2 - ti.x1) - sin * (ti.y2 - ti.y1) < 0) {
|
if (cos * (ti.x2 - ti.x1) - sin * (ti.y2 - ti.y1) < 0) {
|
||||||
// flip label upside-down
|
// flip label upside-down
|
||||||
ti2.x1 = (short) ((ti.x2 * scale + dx));
|
ti2.x1 = (short) ((ti.x2 * scale + dx));
|
||||||
|
Loading…
x
Reference in New Issue
Block a user