Render themes: symbols on lines, fix #495
This commit is contained in:
@@ -5,7 +5,8 @@
|
|||||||
- S3DB layer [#475](https://github.com/mapsforge/vtm/pull/475)
|
- 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)
|
- 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)
|
- 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)
|
- Internal render themes improvements [#488](https://github.com/mapsforge/vtm/pull/488)
|
||||||
- Map view roll [#474](https://github.com/mapsforge/vtm/pull/474)
|
- Map view roll [#474](https://github.com/mapsforge/vtm/pull/474)
|
||||||
- Fling animation improvements [#489](https://github.com/mapsforge/vtm/pull/489)
|
- 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-width" type="xs:positiveInteger" use="optional" />
|
||||||
<xs:attribute name="symbol-height" 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="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>
|
||||||
|
|
||||||
<xs:complexType name="extrusion">
|
<xs:complexType name="extrusion">
|
||||||
|
|||||||
@@ -123,7 +123,16 @@ public class LabelTileLoaderHook implements TileLoaderThemeHook {
|
|||||||
|
|
||||||
LabelTileData ld = get(tile);
|
LabelTileData ld = get(tile);
|
||||||
if (element.type == LINE) {
|
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) {
|
} else if (element.type == POLY) {
|
||||||
PointF centroid = element.labelPosition;
|
PointF centroid = element.labelPosition;
|
||||||
if (!Parameters.POLY_SYMBOL) {
|
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 2013 Hannes Janetzek
|
||||||
|
* Copyright 2018 devemux86
|
||||||
*
|
*
|
||||||
* This file is part of the OpenScienceMap project (http://www.opensciencemap.org).
|
* This file is part of the OpenScienceMap project (http://www.opensciencemap.org).
|
||||||
*
|
*
|
||||||
@@ -18,13 +19,94 @@
|
|||||||
package org.oscim.layers.tile.vector.labeling;
|
package org.oscim.layers.tile.vector.labeling;
|
||||||
|
|
||||||
import org.oscim.core.Tile;
|
import org.oscim.core.Tile;
|
||||||
|
import org.oscim.renderer.bucket.SymbolItem;
|
||||||
import org.oscim.renderer.bucket.TextItem;
|
import org.oscim.renderer.bucket.TextItem;
|
||||||
|
import org.oscim.theme.styles.SymbolStyle;
|
||||||
import org.oscim.theme.styles.TextStyle;
|
import org.oscim.theme.styles.TextStyle;
|
||||||
import org.oscim.utils.geom.GeometryUtils;
|
import org.oscim.utils.geom.GeometryUtils;
|
||||||
import org.oscim.utils.geom.LineClipper;
|
import org.oscim.utils.geom.LineClipper;
|
||||||
|
|
||||||
public final class WayDecorator {
|
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,
|
public static void renderText(LineClipper clipper, float[] coordinates, String label,
|
||||||
TextStyle text, int pos, int len, LabelTileData ld) {
|
TextStyle text, int pos, int len, LabelTileData ld) {
|
||||||
//TextItem items = textItems;
|
//TextItem items = textItems;
|
||||||
@@ -82,7 +164,7 @@ public final class WayDecorator {
|
|||||||
|
|
||||||
int last = i;
|
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 vx = prevX - curX;
|
||||||
float vy = prevY - curY;
|
float vy = prevY - curY;
|
||||||
if (vx == 0 && vy == 0)
|
if (vx == 0 && vy == 0)
|
||||||
|
|||||||
@@ -1123,6 +1123,15 @@ public class XmlMapsforgeThemeBuilder extends DefaultHandler {
|
|||||||
else if ("symbol-scaling".equals(name))
|
else if ("symbol-scaling".equals(name))
|
||||||
; // no-op
|
; // 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
|
else
|
||||||
logUnknownAttribute(elementName, name, value, i);
|
logUnknownAttribute(elementName, name, value, i);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2010, 2011, 2012 mapsforge.org
|
* Copyright 2010, 2011, 2012 mapsforge.org
|
||||||
* Copyright 2013 Hannes Janetzek
|
* Copyright 2013 Hannes Janetzek
|
||||||
* Copyright 2016-2017 devemux86
|
* Copyright 2016-2018 devemux86
|
||||||
* Copyright 2016-2017 Longri
|
* Copyright 2016-2017 Longri
|
||||||
* Copyright 2016 Andrey Novikov
|
* Copyright 2016 Andrey Novikov
|
||||||
*
|
*
|
||||||
@@ -1100,6 +1100,15 @@ public class XmlThemeBuilder extends DefaultHandler {
|
|||||||
else if ("symbol-scaling".equals(name))
|
else if ("symbol-scaling".equals(name))
|
||||||
; // no-op
|
; // 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
|
else
|
||||||
logUnknownAttribute(elementName, name, value, i);
|
logUnknownAttribute(elementName, name, value, i);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2010, 2011, 2012 mapsforge.org
|
* Copyright 2010, 2011, 2012 mapsforge.org
|
||||||
* Copyright 2013 Hannes Janetzek
|
* Copyright 2013 Hannes Janetzek
|
||||||
* Copyright 2016-2017 devemux86
|
* Copyright 2016-2018 devemux86
|
||||||
* Copyright 2017 Longri
|
* Copyright 2017 Longri
|
||||||
*
|
*
|
||||||
* This file is part of the OpenScienceMap project (http://www.opensciencemap.org).
|
* 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 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 Bitmap bitmap;
|
||||||
public final TextureRegion texture;
|
public final TextureRegion texture;
|
||||||
public final int hash;
|
public final int hash;
|
||||||
@@ -35,6 +38,10 @@ public final class SymbolStyle extends RenderStyle<SymbolStyle> {
|
|||||||
public final int symbolHeight;
|
public final int symbolHeight;
|
||||||
public final int symbolPercent;
|
public final int symbolPercent;
|
||||||
|
|
||||||
|
public final boolean repeat;
|
||||||
|
public final float repeatStart;
|
||||||
|
public final float repeatGap;
|
||||||
|
|
||||||
public SymbolStyle(Bitmap bitmap) {
|
public SymbolStyle(Bitmap bitmap) {
|
||||||
this(bitmap, null, 0);
|
this(bitmap, null, 0);
|
||||||
}
|
}
|
||||||
@@ -55,6 +62,10 @@ public final class SymbolStyle extends RenderStyle<SymbolStyle> {
|
|||||||
this.symbolWidth = 0;
|
this.symbolWidth = 0;
|
||||||
this.symbolHeight = 0;
|
this.symbolHeight = 0;
|
||||||
this.symbolPercent = 100;
|
this.symbolPercent = 100;
|
||||||
|
|
||||||
|
this.repeat = false;
|
||||||
|
this.repeatStart = REPEAT_START_DEFAULT;
|
||||||
|
this.repeatGap = REPEAT_GAP_DEFAULT;
|
||||||
}
|
}
|
||||||
|
|
||||||
public SymbolStyle(SymbolBuilder<?> b) {
|
public SymbolStyle(SymbolBuilder<?> b) {
|
||||||
@@ -67,6 +78,10 @@ public final class SymbolStyle extends RenderStyle<SymbolStyle> {
|
|||||||
this.symbolWidth = b.symbolWidth;
|
this.symbolWidth = b.symbolWidth;
|
||||||
this.symbolHeight = b.symbolHeight;
|
this.symbolHeight = b.symbolHeight;
|
||||||
this.symbolPercent = b.symbolPercent;
|
this.symbolPercent = b.symbolPercent;
|
||||||
|
|
||||||
|
this.repeat = b.repeat;
|
||||||
|
this.repeatStart = b.repeatStart;
|
||||||
|
this.repeatGap = b.repeatGap;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -100,6 +115,10 @@ public final class SymbolStyle extends RenderStyle<SymbolStyle> {
|
|||||||
public int symbolHeight;
|
public int symbolHeight;
|
||||||
public int symbolPercent;
|
public int symbolPercent;
|
||||||
|
|
||||||
|
public boolean repeat;
|
||||||
|
public float repeatStart;
|
||||||
|
public float repeatGap;
|
||||||
|
|
||||||
public SymbolBuilder() {
|
public SymbolBuilder() {
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -117,6 +136,10 @@ public final class SymbolStyle extends RenderStyle<SymbolStyle> {
|
|||||||
this.symbolHeight = symbol.symbolHeight;
|
this.symbolHeight = symbol.symbolHeight;
|
||||||
this.symbolPercent = symbol.symbolPercent;
|
this.symbolPercent = symbol.symbolPercent;
|
||||||
|
|
||||||
|
this.repeat = symbol.repeat;
|
||||||
|
this.repeatStart = symbol.repeatStart;
|
||||||
|
this.repeatGap = symbol.repeatGap;
|
||||||
|
|
||||||
return self();
|
return self();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -150,6 +173,21 @@ public final class SymbolStyle extends RenderStyle<SymbolStyle> {
|
|||||||
return self();
|
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() {
|
public T reset() {
|
||||||
cat = null;
|
cat = null;
|
||||||
|
|
||||||
@@ -161,6 +199,10 @@ public final class SymbolStyle extends RenderStyle<SymbolStyle> {
|
|||||||
symbolHeight = 0;
|
symbolHeight = 0;
|
||||||
symbolPercent = 100;
|
symbolPercent = 100;
|
||||||
|
|
||||||
|
repeat = false;
|
||||||
|
repeatStart = REPEAT_START_DEFAULT;
|
||||||
|
repeatGap = REPEAT_GAP_DEFAULT;
|
||||||
|
|
||||||
return self();
|
return self();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user