Render themes: symbols on lines, fix #495
This commit is contained in:
parent
ea21d64822
commit
e304c04f1c
@ -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)
|
||||
|
@ -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">
|
||||
|
@ -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) {
|
||||
|
@ -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)
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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();
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user