Render themes: symbols on lines, fix #495

This commit is contained in:
Emux 2018-01-30 14:02:00 +02:00
parent ea21d64822
commit e304c04f1c
No known key found for this signature in database
GPG Key ID: 89C6921D7AF2BDD0
7 changed files with 161 additions and 6 deletions

View File

@ -5,7 +5,8 @@
- S3DB layer [#475](https://github.com/mapsforge/vtm/pull/475)
- vtm-mvt module with MVT tile decoder [#481](https://github.com/mapsforge/vtm/pull/481)
- OpenMapTiles MVT vector tiles [#482](https://github.com/mapsforge/vtm/issues/482)
- Theme styles improvements [#479](https://github.com/mapsforge/vtm/pull/479)
- Render themes: symbols on lines [#495](https://github.com/mapsforge/vtm/issues/495)
- Render themes: styles improvements [#479](https://github.com/mapsforge/vtm/pull/479)
- Internal render themes improvements [#488](https://github.com/mapsforge/vtm/pull/488)
- Map view roll [#474](https://github.com/mapsforge/vtm/pull/474)
- Fling animation improvements [#489](https://github.com/mapsforge/vtm/pull/489)

View File

@ -234,6 +234,9 @@
<xs:attribute name="symbol-width" type="xs:positiveInteger" use="optional" />
<xs:attribute name="symbol-height" type="xs:positiveInteger" use="optional" />
<xs:attribute name="symbol-percent" type="xs:positiveInteger" use="optional" />
<xs:attribute name="repeat" default="false" type="xs:boolean" use="optional" />
<xs:attribute name="repeat-gap" default="200" type="xs:float" use="optional" />
<xs:attribute name="repeat-start" default="30" type="xs:float" use="optional" />
</xs:complexType>
<xs:complexType name="extrusion">

View File

@ -123,7 +123,16 @@ public class LabelTileLoaderHook implements TileLoaderThemeHook {
LabelTileData ld = get(tile);
if (element.type == LINE) {
// TODO
int offset = 0;
for (int i = 0, n = element.index.length; i < n; i++) {
int length = element.index[i];
if (length < 4)
break;
WayDecorator.renderSymbol(null, element.points, symbol,
offset, length, ld);
offset += length;
}
} else if (element.type == POLY) {
PointF centroid = element.labelPosition;
if (!Parameters.POLY_SYMBOL) {

View File

@ -1,6 +1,7 @@
/*
* Copyright 2010, 2011, 2012 mapsforge.org
* Copyright 2010, 2011, 2012, 2013 mapsforge.org
* Copyright 2013 Hannes Janetzek
* Copyright 2018 devemux86
*
* This file is part of the OpenScienceMap project (http://www.opensciencemap.org).
*
@ -18,13 +19,94 @@
package org.oscim.layers.tile.vector.labeling;
import org.oscim.core.Tile;
import org.oscim.renderer.bucket.SymbolItem;
import org.oscim.renderer.bucket.TextItem;
import org.oscim.theme.styles.SymbolStyle;
import org.oscim.theme.styles.TextStyle;
import org.oscim.utils.geom.GeometryUtils;
import org.oscim.utils.geom.LineClipper;
public final class WayDecorator {
/**
* Mapsforge implementation.
*/
public static void renderSymbol(LineClipper clipper, float[] coordinates, SymbolStyle symbol,
int pos, int len, LabelTileData ld) {
int skipPixels = (int) symbol.repeatStart;
// get the first way point coordinates
float previousX = coordinates[pos + 0];
float previousY = coordinates[pos + 1];
// draw the symbol on each way segment
float segmentLengthRemaining;
float segmentSkipPercentage;
float theta = 0;
for (int i = pos; i < pos + len - 2; i += 2) {
// get the current way point coordinates
float currentX = coordinates[i + 2];
float currentY = coordinates[i + 3];
// calculate the length of the current segment (Euclidean distance)
float diffX = currentX - previousX;
float diffY = currentY - previousY;
double segmentLengthInPixel = Math.sqrt(diffX * diffX + diffY * diffY);
segmentLengthRemaining = (float) segmentLengthInPixel;
while (segmentLengthRemaining - skipPixels > symbol.repeatStart) {
// calculate the percentage of the current segment to skip
segmentSkipPercentage = skipPixels / segmentLengthRemaining;
// move the previous point forward towards the current point
previousX += diffX * segmentSkipPercentage;
previousY += diffY * segmentSkipPercentage;
// TODO
/*if (rotate) {
// if we do not rotate theta will be 0, which is correct
theta = (float) Math.atan2(currentY - previousY, currentX - previousX);
}*/
float x = previousX;
float y = previousY;
if (x >= 0 && x <= Tile.SIZE && y >= 0 && y <= Tile.SIZE) {
SymbolItem s = SymbolItem.pool.get();
if (symbol.bitmap != null)
s.set(x, y, symbol.bitmap, 0, true);
else
s.set(x, y, symbol.texture, 0, true);
ld.symbols.push(s);
}
// check if the symbol should only be rendered once
if (!symbol.repeat) {
return;
}
// recalculate the distances
diffX = currentX - previousX;
diffY = currentY - previousY;
// recalculate the remaining length of the current segment
segmentLengthRemaining -= skipPixels;
// set the amount of pixels to skip before repeating the symbol
skipPixels = (int) symbol.repeatGap;
}
skipPixels -= segmentLengthRemaining;
if (skipPixels < symbol.repeatStart) {
skipPixels = (int) symbol.repeatStart;
}
// set the previous way point coordinates for the next loop
previousX = currentX;
previousY = currentY;
}
}
public static void renderText(LineClipper clipper, float[] coordinates, String label,
TextStyle text, int pos, int len, LabelTileData ld) {
//TextItem items = textItems;
@ -82,7 +164,7 @@ public final class WayDecorator {
int last = i;
// calculate the length of the current segment (Euclidian distance)
// calculate the length of the current segment (Euclidean distance)
float vx = prevX - curX;
float vy = prevY - curY;
if (vx == 0 && vy == 0)

View File

@ -1123,6 +1123,15 @@ public class XmlMapsforgeThemeBuilder extends DefaultHandler {
else if ("symbol-scaling".equals(name))
; // no-op
else if ("repeat".equals(name))
b.repeat(Boolean.parseBoolean(value));
else if ("repeat-start".equals(name))
b.repeatStart = Float.parseFloat(value) * mScale;
else if ("repeat-gap".equals(name))
b.repeatGap = Float.parseFloat(value) * mScale;
else
logUnknownAttribute(elementName, name, value, i);
}

View File

@ -1,7 +1,7 @@
/*
* Copyright 2010, 2011, 2012 mapsforge.org
* Copyright 2013 Hannes Janetzek
* Copyright 2016-2017 devemux86
* Copyright 2016-2018 devemux86
* Copyright 2016-2017 Longri
* Copyright 2016 Andrey Novikov
*
@ -1100,6 +1100,15 @@ public class XmlThemeBuilder extends DefaultHandler {
else if ("symbol-scaling".equals(name))
; // no-op
else if ("repeat".equals(name))
b.repeat(Boolean.parseBoolean(value));
else if ("repeat-start".equals(name))
b.repeatStart = Float.parseFloat(value) * mScale;
else if ("repeat-gap".equals(name))
b.repeatGap = Float.parseFloat(value) * mScale;
else
logUnknownAttribute(elementName, name, value, i);
}

View File

@ -1,7 +1,7 @@
/*
* Copyright 2010, 2011, 2012 mapsforge.org
* Copyright 2013 Hannes Janetzek
* Copyright 2016-2017 devemux86
* Copyright 2016-2018 devemux86
* Copyright 2017 Longri
*
* This file is part of the OpenScienceMap project (http://www.opensciencemap.org).
@ -27,6 +27,9 @@ import org.oscim.renderer.atlas.TextureRegion;
*/
public final class SymbolStyle extends RenderStyle<SymbolStyle> {
public static final float REPEAT_START_DEFAULT = 30f;
public static final float REPEAT_GAP_DEFAULT = 200f;
public final Bitmap bitmap;
public final TextureRegion texture;
public final int hash;
@ -35,6 +38,10 @@ public final class SymbolStyle extends RenderStyle<SymbolStyle> {
public final int symbolHeight;
public final int symbolPercent;
public final boolean repeat;
public final float repeatStart;
public final float repeatGap;
public SymbolStyle(Bitmap bitmap) {
this(bitmap, null, 0);
}
@ -55,6 +62,10 @@ public final class SymbolStyle extends RenderStyle<SymbolStyle> {
this.symbolWidth = 0;
this.symbolHeight = 0;
this.symbolPercent = 100;
this.repeat = false;
this.repeatStart = REPEAT_START_DEFAULT;
this.repeatGap = REPEAT_GAP_DEFAULT;
}
public SymbolStyle(SymbolBuilder<?> b) {
@ -67,6 +78,10 @@ public final class SymbolStyle extends RenderStyle<SymbolStyle> {
this.symbolWidth = b.symbolWidth;
this.symbolHeight = b.symbolHeight;
this.symbolPercent = b.symbolPercent;
this.repeat = b.repeat;
this.repeatStart = b.repeatStart;
this.repeatGap = b.repeatGap;
}
@Override
@ -100,6 +115,10 @@ public final class SymbolStyle extends RenderStyle<SymbolStyle> {
public int symbolHeight;
public int symbolPercent;
public boolean repeat;
public float repeatStart;
public float repeatGap;
public SymbolBuilder() {
}
@ -117,6 +136,10 @@ public final class SymbolStyle extends RenderStyle<SymbolStyle> {
this.symbolHeight = symbol.symbolHeight;
this.symbolPercent = symbol.symbolPercent;
this.repeat = symbol.repeat;
this.repeatStart = symbol.repeatStart;
this.repeatGap = symbol.repeatGap;
return self();
}
@ -150,6 +173,21 @@ public final class SymbolStyle extends RenderStyle<SymbolStyle> {
return self();
}
public T repeat(boolean repeat) {
this.repeat = repeat;
return self();
}
public T repeatStart(float repeatStart) {
this.repeatStart = repeatStart;
return self();
}
public T repeatGap(float repeatGap) {
this.repeatGap = repeatGap;
return self();
}
public T reset() {
cat = null;
@ -161,6 +199,10 @@ public final class SymbolStyle extends RenderStyle<SymbolStyle> {
symbolHeight = 0;
symbolPercent = 100;
repeat = false;
repeatStart = REPEAT_START_DEFAULT;
repeatGap = REPEAT_GAP_DEFAULT;
return self();
}