Render themes: tag transform (#587)
This commit is contained in:
@@ -301,11 +301,24 @@
|
|||||||
<xs:attribute name="id" type="xs:string" use="required" />
|
<xs:attribute name="id" type="xs:string" use="required" />
|
||||||
</xs:complexType>
|
</xs:complexType>
|
||||||
|
|
||||||
|
<!-- tag-transform element -->
|
||||||
|
<xs:complexType name="tag-transform">
|
||||||
|
<xs:attribute name="k" type="xs:string" use="required" />
|
||||||
|
<xs:attribute name="v" type="xs:string" use="optional" />
|
||||||
|
<xs:attribute name="k-match" type="xs:string" use="required" />
|
||||||
|
<xs:attribute name="v-match" type="xs:string" use="optional" />
|
||||||
|
</xs:complexType>
|
||||||
|
|
||||||
<!-- rendertheme element -->
|
<!-- rendertheme element -->
|
||||||
<xs:complexType name="rendertheme">
|
<xs:complexType name="rendertheme">
|
||||||
<xs:sequence maxOccurs="1" minOccurs="0">
|
<xs:sequence maxOccurs="1" minOccurs="0">
|
||||||
<xs:element name="stylemenu" maxOccurs="1" minOccurs="0" type="tns:stylemenu" />
|
<xs:element name="stylemenu" maxOccurs="1" minOccurs="0" type="tns:stylemenu" />
|
||||||
|
|
||||||
|
<!-- tag definitions -->
|
||||||
|
<xs:choice maxOccurs="unbounded" minOccurs="0">
|
||||||
|
<xs:element name="tag-transform" type="tns:tag-transform" />
|
||||||
|
</xs:choice>
|
||||||
|
|
||||||
<!-- style definitions -->
|
<!-- style definitions -->
|
||||||
<xs:sequence maxOccurs="256" minOccurs="0">
|
<xs:sequence maxOccurs="256" minOccurs="0">
|
||||||
<xs:choice maxOccurs="unbounded" minOccurs="0">
|
<xs:choice maxOccurs="unbounded" minOccurs="0">
|
||||||
|
|||||||
@@ -251,6 +251,20 @@ public class RenderTheme implements IRenderTheme {
|
|||||||
public void scaleTextSize(float scaleFactor) {
|
public void scaleTextSize(float scaleFactor) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String transformKey(String key) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Tag transformTag(Tag tag) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void updateStyles() {
|
||||||
|
}
|
||||||
|
|
||||||
public static void main(String[] args) {
|
public static void main(String[] args) {
|
||||||
RenderTheme t = new RenderTheme();
|
RenderTheme t = new RenderTheme();
|
||||||
|
|
||||||
@@ -261,11 +275,4 @@ public class RenderTheme implements IRenderTheme {
|
|||||||
t.matchElement(GeometryType.POLY, e.tags, 16);
|
t.matchElement(GeometryType.POLY, e.tags, 16);
|
||||||
t.matchElement(GeometryType.POLY, e.tags, 15);
|
t.matchElement(GeometryType.POLY, e.tags, 15);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public void updateStyles() {
|
|
||||||
// TODO Auto-generated method stub
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ package org.oscim.test;
|
|||||||
|
|
||||||
import org.oscim.backend.canvas.Color;
|
import org.oscim.backend.canvas.Color;
|
||||||
import org.oscim.core.GeometryBuffer.GeometryType;
|
import org.oscim.core.GeometryBuffer.GeometryType;
|
||||||
|
import org.oscim.core.Tag;
|
||||||
import org.oscim.core.TagSet;
|
import org.oscim.core.TagSet;
|
||||||
import org.oscim.theme.IRenderTheme;
|
import org.oscim.theme.IRenderTheme;
|
||||||
import org.oscim.theme.styles.AreaStyle;
|
import org.oscim.theme.styles.AreaStyle;
|
||||||
@@ -46,6 +47,16 @@ public class DebugTheme implements IRenderTheme {
|
|||||||
public void scaleTextSize(float scaleFactor) {
|
public void scaleTextSize(float scaleFactor) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String transformKey(String key) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Tag transformTag(Tag tag) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void updateStyles() {
|
public void updateStyles() {
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,6 +3,17 @@
|
|||||||
version="1" xmlns="http://opensciencemap.org/rendertheme"
|
version="1" xmlns="http://opensciencemap.org/rendertheme"
|
||||||
xsi:schemaLocation="http://opensciencemap.org/rendertheme https://raw.githubusercontent.com/mapsforge/vtm/master/resources/rendertheme.xsd">
|
xsi:schemaLocation="http://opensciencemap.org/rendertheme https://raw.githubusercontent.com/mapsforge/vtm/master/resources/rendertheme.xsd">
|
||||||
|
|
||||||
|
<!--<tag-transform k="kind" v="building" k-match="building" v-match="yes" />-->
|
||||||
|
<!--<tag-transform k="kind" v="building_part" k-match="building:part" v-match="yes" />-->
|
||||||
|
<tag-transform k="root_id" k-match="ref" />
|
||||||
|
|
||||||
|
<tag-transform k="roof_color" k-match="roof:colour" />
|
||||||
|
<tag-transform k="roof_direction" k-match="roof:direction" />
|
||||||
|
<tag-transform k="roof_height" k-match="roof:height" />
|
||||||
|
<tag-transform k="roof_material" k-match="roof:material" />
|
||||||
|
<tag-transform k="roof_orientation" k-match="roof:orientation" />
|
||||||
|
<tag-transform k="roof_shape" k-match="roof:shape" />
|
||||||
|
|
||||||
<!-- base style for fixed width lines -->
|
<!-- base style for fixed width lines -->
|
||||||
<style-line cap="butt" fix="true" id="fix" width="1.0" />
|
<style-line cap="butt" fix="true" id="fix" width="1.0" />
|
||||||
|
|
||||||
|
|||||||
@@ -3,6 +3,11 @@
|
|||||||
version="1" xmlns="http://opensciencemap.org/rendertheme"
|
version="1" xmlns="http://opensciencemap.org/rendertheme"
|
||||||
xsi:schemaLocation="http://opensciencemap.org/rendertheme https://raw.githubusercontent.com/mapsforge/vtm/master/resources/rendertheme.xsd">
|
xsi:schemaLocation="http://opensciencemap.org/rendertheme https://raw.githubusercontent.com/mapsforge/vtm/master/resources/rendertheme.xsd">
|
||||||
|
|
||||||
|
<tag-transform k="render_height" k-match="height" />
|
||||||
|
<tag-transform k="render_min_height" k-match="min_height" />
|
||||||
|
<!--<tag-transform k="layer" v="building" k-match="building" v-match="yes" />-->
|
||||||
|
<!--<tag-transform k="layer" v="building:part" k-match="building:part" v-match="yes" />-->
|
||||||
|
|
||||||
<!--###### TEXT styles ######-->
|
<!--###### TEXT styles ######-->
|
||||||
|
|
||||||
<!--default label-->
|
<!--default label-->
|
||||||
|
|||||||
@@ -19,6 +19,8 @@
|
|||||||
*/
|
*/
|
||||||
package org.oscim.core;
|
package org.oscim.core;
|
||||||
|
|
||||||
|
import org.oscim.theme.IRenderTheme;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The MapElement class is a reusable container for a geometry
|
* The MapElement class is a reusable container for a geometry
|
||||||
* with tags.
|
* with tags.
|
||||||
@@ -63,10 +65,9 @@ public class MapElement extends GeometryBuffer {
|
|||||||
/**
|
/**
|
||||||
* @return height in meters, if present
|
* @return height in meters, if present
|
||||||
*/
|
*/
|
||||||
public Float getHeight() {
|
public Float getHeight(IRenderTheme theme) {
|
||||||
String v = tags.getValue(Tag.KEY_HEIGHT);
|
String res = theme.transformKey(Tag.KEY_HEIGHT);
|
||||||
if (v == null)
|
String v = tags.getValue(res != null ? res : Tag.KEY_HEIGHT);
|
||||||
v = tags.getValue("render_height"); // OpenMapTiles
|
|
||||||
if (v != null)
|
if (v != null)
|
||||||
return Float.parseFloat(v);
|
return Float.parseFloat(v);
|
||||||
return null;
|
return null;
|
||||||
@@ -75,22 +76,21 @@ public class MapElement extends GeometryBuffer {
|
|||||||
/**
|
/**
|
||||||
* @return minimum height in meters, if present
|
* @return minimum height in meters, if present
|
||||||
*/
|
*/
|
||||||
public Float getMinHeight() {
|
public Float getMinHeight(IRenderTheme theme) {
|
||||||
String v = tags.getValue(Tag.KEY_MIN_HEIGHT);
|
String res = theme.transformKey(Tag.KEY_MIN_HEIGHT);
|
||||||
if (v == null)
|
String v = tags.getValue(res != null ? res : Tag.KEY_MIN_HEIGHT);
|
||||||
v = tags.getValue("render_min_height"); // OpenMapTiles
|
|
||||||
if (v != null)
|
if (v != null)
|
||||||
return Float.parseFloat(v);
|
return Float.parseFloat(v);
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isBuilding() {
|
public boolean isBuilding() { // TODO from themes (with overzoom ref)
|
||||||
return tags.containsKey(Tag.KEY_BUILDING)
|
return tags.containsKey(Tag.KEY_BUILDING)
|
||||||
|| "building".equals(tags.getValue("kind")) // Mapzen
|
|| "building".equals(tags.getValue("kind")) // Mapzen
|
||||||
|| "building".equals(tags.getValue("layer")); // OpenMapTiles
|
|| "building".equals(tags.getValue("layer")); // OpenMapTiles
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isBuildingPart() {
|
public boolean isBuildingPart() { // TODO from themes (with overzoom ref)
|
||||||
return tags.containsKey(Tag.KEY_BUILDING_PART)
|
return tags.containsKey(Tag.KEY_BUILDING_PART)
|
||||||
|| "building_part".equals(tags.getValue("kind")) // Mapzen
|
|| "building_part".equals(tags.getValue("kind")) // Mapzen
|
||||||
|| "building:part".equals(tags.getValue("layer")); // OpenMapTiles
|
|| "building:part".equals(tags.getValue("layer")); // OpenMapTiles
|
||||||
|
|||||||
@@ -65,9 +65,9 @@ public class Tag {
|
|||||||
public static final String KEY_BUILDING_MATERIAL = "building:material";
|
public static final String KEY_BUILDING_MATERIAL = "building:material";
|
||||||
public static final String KEY_BUILDING_MIN_LEVEL = "building:min_level";
|
public static final String KEY_BUILDING_MIN_LEVEL = "building:min_level";
|
||||||
public static final String KEY_BUILDING_PART = "building:part";
|
public static final String KEY_BUILDING_PART = "building:part";
|
||||||
public static final String KEY_COLOR = "colour";
|
//public static final String KEY_COLOR = "colour";
|
||||||
public static final String KEY_HEIGHT = "height";
|
public static final String KEY_HEIGHT = "height";
|
||||||
public static final String KEY_MATERIAL = "material";
|
//public static final String KEY_MATERIAL = "material";
|
||||||
public static final String KEY_MIN_HEIGHT = "min_height";
|
public static final String KEY_MIN_HEIGHT = "min_height";
|
||||||
public static final String KEY_ROOF = "roof";
|
public static final String KEY_ROOF = "roof";
|
||||||
public static final String KEY_ROOF_ANGLE = "roof:angle";
|
public static final String KEY_ROOF_ANGLE = "roof:angle";
|
||||||
|
|||||||
@@ -31,6 +31,7 @@ import org.oscim.renderer.OffscreenRenderer;
|
|||||||
import org.oscim.renderer.OffscreenRenderer.Mode;
|
import org.oscim.renderer.OffscreenRenderer.Mode;
|
||||||
import org.oscim.renderer.bucket.ExtrusionBuckets;
|
import org.oscim.renderer.bucket.ExtrusionBuckets;
|
||||||
import org.oscim.renderer.bucket.RenderBuckets;
|
import org.oscim.renderer.bucket.RenderBuckets;
|
||||||
|
import org.oscim.theme.IRenderTheme;
|
||||||
import org.oscim.theme.styles.ExtrusionStyle;
|
import org.oscim.theme.styles.ExtrusionStyle;
|
||||||
import org.oscim.theme.styles.RenderStyle;
|
import org.oscim.theme.styles.RenderStyle;
|
||||||
|
|
||||||
@@ -66,6 +67,8 @@ public class BuildingLayer extends Layer implements TileLoaderThemeHook, ZoomLim
|
|||||||
|
|
||||||
private final ZoomLimiter mZoomLimiter;
|
private final ZoomLimiter mZoomLimiter;
|
||||||
|
|
||||||
|
protected final IRenderTheme mRenderTheme;
|
||||||
|
|
||||||
class BuildingElement {
|
class BuildingElement {
|
||||||
MapElement element;
|
MapElement element;
|
||||||
ExtrusionStyle style;
|
ExtrusionStyle style;
|
||||||
@@ -103,6 +106,8 @@ public class BuildingLayer extends Layer implements TileLoaderThemeHook, ZoomLim
|
|||||||
mRenderer = new BuildingRenderer(tileLayer.tileRenderer(), mZoomLimiter, mesh, TRANSLUCENT);
|
mRenderer = new BuildingRenderer(tileLayer.tileRenderer(), mZoomLimiter, mesh, TRANSLUCENT);
|
||||||
if (POST_AA)
|
if (POST_AA)
|
||||||
mRenderer = new OffscreenRenderer(Mode.SSAO_FXAA, mRenderer);
|
mRenderer = new OffscreenRenderer(Mode.SSAO_FXAA, mRenderer);
|
||||||
|
|
||||||
|
mRenderTheme = tileLayer.getTheme();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -160,22 +165,22 @@ public class BuildingLayer extends Layer implements TileLoaderThemeHook, ZoomLim
|
|||||||
int height = 0; // cm
|
int height = 0; // cm
|
||||||
int minHeight = 0; // cm
|
int minHeight = 0; // cm
|
||||||
|
|
||||||
Float f = element.getHeight();
|
Float f = element.getHeight(mRenderTheme);
|
||||||
if (f != null)
|
if (f != null)
|
||||||
height = (int) (f * 100);
|
height = (int) (f * 100);
|
||||||
else {
|
else {
|
||||||
// #TagFromTheme: generalize level/height tags
|
// #TagFromTheme: generalize level/height tags
|
||||||
String v = element.tags.getValue(Tag.KEY_BUILDING_LEVELS);
|
String v = getValue(element, Tag.KEY_BUILDING_LEVELS);
|
||||||
if (v != null)
|
if (v != null)
|
||||||
height = (int) (Float.parseFloat(v) * BUILDING_LEVEL_HEIGHT);
|
height = (int) (Float.parseFloat(v) * BUILDING_LEVEL_HEIGHT);
|
||||||
}
|
}
|
||||||
|
|
||||||
f = element.getMinHeight();
|
f = element.getMinHeight(mRenderTheme);
|
||||||
if (f != null)
|
if (f != null)
|
||||||
minHeight = (int) (f * 100);
|
minHeight = (int) (f * 100);
|
||||||
else {
|
else {
|
||||||
// #TagFromTheme: level/height tags
|
// #TagFromTheme: level/height tags
|
||||||
String v = element.tags.getValue(Tag.KEY_BUILDING_MIN_LEVEL);
|
String v = getValue(element, Tag.KEY_BUILDING_MIN_LEVEL);
|
||||||
if (v != null)
|
if (v != null)
|
||||||
minHeight = (int) (Float.parseFloat(v) * BUILDING_LEVEL_HEIGHT);
|
minHeight = (int) (Float.parseFloat(v) * BUILDING_LEVEL_HEIGHT);
|
||||||
}
|
}
|
||||||
@@ -202,15 +207,14 @@ public class BuildingLayer extends Layer implements TileLoaderThemeHook, ZoomLim
|
|||||||
if (!partBuilding.element.isBuildingPart())
|
if (!partBuilding.element.isBuildingPart())
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
String refId = partBuilding.element.tags.getValue(Tag.KEY_REF); // #TagFromTheme
|
String refId = getValue(partBuilding.element, Tag.KEY_REF);
|
||||||
refId = refId == null ? partBuilding.element.tags.getValue("root_id") : refId; // Mapzen
|
|
||||||
if (refId == null)
|
if (refId == null)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
// Search buildings which inherit parts
|
// Search buildings which inherit parts
|
||||||
for (BuildingElement rootBuilding : tileBuildings) {
|
for (BuildingElement rootBuilding : tileBuildings) {
|
||||||
if (rootBuilding.element.isBuildingPart()
|
if (rootBuilding.element.isBuildingPart()
|
||||||
|| !(refId.equals(rootBuilding.element.tags.getValue(Tag.KEY_ID))))
|
|| !(refId.equals(getValue(rootBuilding.element, Tag.KEY_ID))))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
rootBuildings.add(rootBuilding);
|
rootBuildings.add(rootBuilding);
|
||||||
@@ -239,6 +243,15 @@ public class BuildingLayer extends Layer implements TileLoaderThemeHook, ZoomLim
|
|||||||
return ebs;
|
return ebs;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected String getKeyOrDefault(String key) {
|
||||||
|
String res = mRenderTheme.transformKey(key);
|
||||||
|
return res != null ? res : key;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected String getValue(MapElement element, String key) {
|
||||||
|
return element.tags.getValue(getKeyOrDefault(key));
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void complete(MapTile tile, boolean success) {
|
public void complete(MapTile tile, boolean success) {
|
||||||
if (success) {
|
if (success) {
|
||||||
|
|||||||
@@ -101,12 +101,12 @@ public class S3DBLayer extends BuildingLayer {
|
|||||||
int roofHeight = 0;
|
int roofHeight = 0;
|
||||||
|
|
||||||
// Get roof height
|
// Get roof height
|
||||||
String v = element.tags.getValue(Tag.KEY_ROOF_HEIGHT);
|
String v = getValue(element, Tag.KEY_ROOF_HEIGHT);
|
||||||
if (v != null) {
|
if (v != null) {
|
||||||
roofHeight = (int) (Float.parseFloat(v) * 100);
|
roofHeight = (int) (Float.parseFloat(v) * 100);
|
||||||
} else if ((v = element.tags.getValue(Tag.KEY_ROOF_LEVELS)) != null) {
|
} else if ((v = getValue(element, Tag.KEY_ROOF_LEVELS)) != null) {
|
||||||
roofHeight = (int) (Float.parseFloat(v) * BUILDING_LEVEL_HEIGHT);
|
roofHeight = (int) (Float.parseFloat(v) * BUILDING_LEVEL_HEIGHT);
|
||||||
} else if ((v = element.tags.getValue(Tag.KEY_ROOF_ANGLE)) != null) {
|
} else if ((v = getValue(element, Tag.KEY_ROOF_ANGLE)) != null) {
|
||||||
Box bb = null;
|
Box bb = null;
|
||||||
for (int k = 0; k < element.index[0]; k += 2) {
|
for (int k = 0; k < element.index[0]; k += 2) {
|
||||||
float p1 = element.points[k];
|
float p1 = element.points[k];
|
||||||
@@ -122,17 +122,17 @@ public class S3DBLayer extends BuildingLayer {
|
|||||||
// Angle is simplified, 40 is an estimated constant
|
// Angle is simplified, 40 is an estimated constant
|
||||||
roofHeight = (int) ((Float.parseFloat(v) / 45.f) * (minSize * 40));
|
roofHeight = (int) ((Float.parseFloat(v) / 45.f) * (minSize * 40));
|
||||||
}
|
}
|
||||||
} else if ((v = element.tags.getValue(Tag.KEY_ROOF_SHAPE)) != null && !v.equals(Tag.VALUE_FLAT)) {
|
} else if ((v = getValue(element, Tag.KEY_ROOF_SHAPE)) != null && !v.equals(Tag.VALUE_FLAT)) {
|
||||||
roofHeight = (2 * BUILDING_LEVEL_HEIGHT);
|
roofHeight = (2 * BUILDING_LEVEL_HEIGHT);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get building height
|
// Get building height
|
||||||
v = element.tags.getValue(Tag.KEY_HEIGHT);
|
v = getValue(element, Tag.KEY_HEIGHT);
|
||||||
if (v != null) {
|
if (v != null) {
|
||||||
maxHeight = (int) (Float.parseFloat(v) * 100);
|
maxHeight = (int) (Float.parseFloat(v) * 100);
|
||||||
} else {
|
} else {
|
||||||
// #TagFromTheme: generalize level/height tags
|
// #TagFromTheme: generalize level/height tags
|
||||||
if ((v = element.tags.getValue(Tag.KEY_BUILDING_LEVELS)) != null) {
|
if ((v = getValue(element, Tag.KEY_BUILDING_LEVELS)) != null) {
|
||||||
maxHeight = (int) (Float.parseFloat(v) * BUILDING_LEVEL_HEIGHT);
|
maxHeight = (int) (Float.parseFloat(v) * BUILDING_LEVEL_HEIGHT);
|
||||||
maxHeight += roofHeight;
|
maxHeight += roofHeight;
|
||||||
}
|
}
|
||||||
@@ -140,22 +140,22 @@ public class S3DBLayer extends BuildingLayer {
|
|||||||
if (maxHeight == 0)
|
if (maxHeight == 0)
|
||||||
maxHeight = extrusion.defaultHeight * 100;
|
maxHeight = extrusion.defaultHeight * 100;
|
||||||
|
|
||||||
v = element.tags.getValue(Tag.KEY_MIN_HEIGHT);
|
v = getValue(element, Tag.KEY_MIN_HEIGHT);
|
||||||
if (v != null)
|
if (v != null)
|
||||||
minHeight = (int) (Float.parseFloat(v) * 100);
|
minHeight = (int) (Float.parseFloat(v) * 100);
|
||||||
else {
|
else {
|
||||||
// #TagFromTheme: level/height tags
|
// #TagFromTheme: level/height tags
|
||||||
if ((v = element.tags.getValue(Tag.KEY_BUILDING_MIN_LEVEL)) != null)
|
if ((v = getValue(element, Tag.KEY_BUILDING_MIN_LEVEL)) != null)
|
||||||
minHeight = (int) (Float.parseFloat(v) * BUILDING_LEVEL_HEIGHT);
|
minHeight = (int) (Float.parseFloat(v) * BUILDING_LEVEL_HEIGHT);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get building color
|
// Get building color
|
||||||
Integer bColor = null;
|
Integer bColor = null;
|
||||||
if (mColored) {
|
if (mColored) {
|
||||||
if (element.tags.containsKey(Tag.KEY_BUILDING_COLOR)) {
|
if ((v = getValue(element, Tag.KEY_BUILDING_COLOR)) != null) {
|
||||||
bColor = S3DBUtils.getColor(element.tags.getValue(Tag.KEY_BUILDING_COLOR), false, false);
|
bColor = S3DBUtils.getColor(v, false, false);
|
||||||
} else if (element.tags.containsKey(Tag.KEY_BUILDING_MATERIAL)) {
|
} else if ((v = getValue(element, Tag.KEY_BUILDING_MATERIAL)) != null) {
|
||||||
bColor = S3DBUtils.getMaterialColor(element.tags.getValue(Tag.KEY_BUILDING_MATERIAL), false);
|
bColor = S3DBUtils.getMaterialColor(v, false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -190,25 +190,32 @@ public class S3DBLayer extends BuildingLayer {
|
|||||||
if (!partBuilding.element.isBuildingPart())
|
if (!partBuilding.element.isBuildingPart())
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
TagSet partTags = partBuilding.element.tags;
|
String refId = getValue(partBuilding.element, Tag.KEY_REF);
|
||||||
String refId = partTags.getValue(Tag.KEY_REF); // #TagFromTheme
|
|
||||||
refId = refId == null ? partTags.getValue("root_id") : refId; // Mapzen
|
|
||||||
if (refId == null)
|
if (refId == null)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
TagSet partTags = partBuilding.element.tags;
|
||||||
|
|
||||||
// Search buildings which inherit parts
|
// Search buildings which inherit parts
|
||||||
for (BuildingElement rootBuilding : tileBuildings) {
|
for (BuildingElement rootBuilding : tileBuildings) {
|
||||||
if (rootBuilding.element.isBuildingPart()
|
if (rootBuilding.element.isBuildingPart()
|
||||||
|| !(refId.equals(rootBuilding.element.tags.getValue(Tag.KEY_ID))))
|
|| !(refId.equals(rootBuilding.element.tags.getValue(Tag.KEY_ID))))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
if ((getValue(rootBuilding.element, Tag.KEY_ROOF_SHAPE) != null)
|
||||||
|
&& (getValue(partBuilding.element, Tag.KEY_ROOF_SHAPE) == null)) {
|
||||||
|
partBuilding.element.tags.add(rootBuilding.element.tags.get(getKeyOrDefault(Tag.KEY_ROOF_SHAPE)));
|
||||||
|
}
|
||||||
|
|
||||||
if (mColored) {
|
if (mColored) {
|
||||||
TagSet rootTags = rootBuilding.element.tags;
|
TagSet rootTags = rootBuilding.element.tags;
|
||||||
|
|
||||||
for (int i = 0; i < rootTags.size(); i++) {
|
for (int i = 0; i < rootTags.size(); i++) {
|
||||||
Tag rTag = rootTags.get(i);
|
Tag rTag = rootTags.get(i);
|
||||||
if ((rTag.key.equals(Tag.KEY_COLOR) && !partTags.containsKey(Tag.KEY_MATERIAL)
|
if ((rTag.key.equals(getKeyOrDefault(Tag.KEY_BUILDING_COLOR))
|
||||||
|| rTag.key.equals(Tag.KEY_ROOF_COLOR) && !partTags.containsKey(Tag.KEY_ROOF_MATERIAL)
|
&& !partTags.containsKey(getKeyOrDefault(Tag.KEY_BUILDING_MATERIAL))
|
||||||
|| rTag.key.equals(Tag.KEY_ROOF_SHAPE))
|
|| rTag.key.equals(getKeyOrDefault(Tag.KEY_ROOF_COLOR))
|
||||||
|
&& !partTags.containsKey(getKeyOrDefault(Tag.KEY_ROOF_MATERIAL)))
|
||||||
&& !partTags.containsKey(rTag.key)) {
|
&& !partTags.containsKey(rTag.key)) {
|
||||||
partTags.add(rTag);
|
partTags.add(rTag);
|
||||||
}
|
}
|
||||||
@@ -243,22 +250,22 @@ public class S3DBLayer extends BuildingLayer {
|
|||||||
String v;
|
String v;
|
||||||
|
|
||||||
if (mColored) {
|
if (mColored) {
|
||||||
v = element.tags.getValue(Tag.KEY_ROOF_COLOR);
|
v = getValue(element, Tag.KEY_ROOF_COLOR);
|
||||||
if (v != null)
|
if (v != null)
|
||||||
roofColor = S3DBUtils.getColor(v, true, false);
|
roofColor = S3DBUtils.getColor(v, true, false);
|
||||||
else if ((v = element.tags.getValue(Tag.KEY_ROOF_MATERIAL)) != null)
|
else if ((v = getValue(element, Tag.KEY_ROOF_MATERIAL)) != null)
|
||||||
roofColor = S3DBUtils.getMaterialColor(v, true);
|
roofColor = S3DBUtils.getMaterialColor(v, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
boolean roofOrientationAcross = false;
|
boolean roofOrientationAcross = false;
|
||||||
if ((v = element.tags.getValue(Tag.KEY_ROOF_ORIENTATION)) != null) {
|
if ((v = getValue(element, Tag.KEY_ROOF_ORIENTATION)) != null) {
|
||||||
if (v.equals(Tag.VALUE_ACROSS)) {
|
if (v.equals(Tag.VALUE_ACROSS)) {
|
||||||
roofOrientationAcross = true;
|
roofOrientationAcross = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Calc roof shape
|
// Calc roof shape
|
||||||
v = element.tags.getValue(Tag.KEY_ROOF_SHAPE);
|
v = getValue(element, Tag.KEY_ROOF_SHAPE);
|
||||||
if (v == null) {
|
if (v == null) {
|
||||||
v = Tag.VALUE_FLAT;
|
v = Tag.VALUE_FLAT;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,6 +2,7 @@
|
|||||||
* Copyright 2010, 2011, 2012 mapsforge.org
|
* Copyright 2010, 2011, 2012 mapsforge.org
|
||||||
* Copyright 2013 Hannes Janetzek
|
* Copyright 2013 Hannes Janetzek
|
||||||
* Copyright 2017 devemux86
|
* Copyright 2017 devemux86
|
||||||
|
* Copyright 2018 Gustl22
|
||||||
*
|
*
|
||||||
* This file is part of the OpenScienceMap project (http://www.opensciencemap.org).
|
* This file is part of the OpenScienceMap project (http://www.opensciencemap.org).
|
||||||
*
|
*
|
||||||
@@ -19,6 +20,7 @@
|
|||||||
package org.oscim.theme;
|
package org.oscim.theme;
|
||||||
|
|
||||||
import org.oscim.core.GeometryBuffer.GeometryType;
|
import org.oscim.core.GeometryBuffer.GeometryType;
|
||||||
|
import org.oscim.core.Tag;
|
||||||
import org.oscim.core.TagSet;
|
import org.oscim.core.TagSet;
|
||||||
import org.oscim.theme.styles.RenderStyle;
|
import org.oscim.theme.styles.RenderStyle;
|
||||||
|
|
||||||
@@ -63,6 +65,16 @@ public interface IRenderTheme {
|
|||||||
*/
|
*/
|
||||||
void scaleTextSize(float scaleFactor);
|
void scaleTextSize(float scaleFactor);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return the transformed tag key of this RenderTheme.
|
||||||
|
*/
|
||||||
|
String transformKey(String key);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return the transformed tag of this RenderTheme.
|
||||||
|
*/
|
||||||
|
Tag transformTag(Tag tag);
|
||||||
|
|
||||||
class ThemeException extends IllegalArgumentException {
|
class ThemeException extends IllegalArgumentException {
|
||||||
public ThemeException(String string) {
|
public ThemeException(String string) {
|
||||||
super(string);
|
super(string);
|
||||||
|
|||||||
@@ -2,6 +2,7 @@
|
|||||||
* Copyright 2014 Hannes Janetzek
|
* Copyright 2014 Hannes Janetzek
|
||||||
* Copyright 2017 Longri
|
* Copyright 2017 Longri
|
||||||
* Copyright 2017 devemux86
|
* Copyright 2017 devemux86
|
||||||
|
* Copyright 2018 Gustl22
|
||||||
*
|
*
|
||||||
* This file is part of the OpenScienceMap project (http://www.opensciencemap.org).
|
* This file is part of the OpenScienceMap project (http://www.opensciencemap.org).
|
||||||
*
|
*
|
||||||
@@ -19,6 +20,7 @@
|
|||||||
package org.oscim.theme;
|
package org.oscim.theme;
|
||||||
|
|
||||||
import org.oscim.core.GeometryBuffer.GeometryType;
|
import org.oscim.core.GeometryBuffer.GeometryType;
|
||||||
|
import org.oscim.core.Tag;
|
||||||
import org.oscim.core.TagSet;
|
import org.oscim.core.TagSet;
|
||||||
import org.oscim.theme.rule.Rule;
|
import org.oscim.theme.rule.Rule;
|
||||||
import org.oscim.theme.rule.Rule.Element;
|
import org.oscim.theme.rule.Rule.Element;
|
||||||
@@ -31,6 +33,7 @@ import org.slf4j.LoggerFactory;
|
|||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
public class RenderTheme implements IRenderTheme {
|
public class RenderTheme implements IRenderTheme {
|
||||||
static final Logger log = LoggerFactory.getLogger(RenderTheme.class);
|
static final Logger log = LoggerFactory.getLogger(RenderTheme.class);
|
||||||
@@ -44,6 +47,9 @@ public class RenderTheme implements IRenderTheme {
|
|||||||
private final Rule[] mRules;
|
private final Rule[] mRules;
|
||||||
private final boolean mMapsforgeTheme;
|
private final boolean mMapsforgeTheme;
|
||||||
|
|
||||||
|
private final Map<String, String> mTransformKeyMap;
|
||||||
|
private final Map<Tag, Tag> mTransformTagMap;
|
||||||
|
|
||||||
class RenderStyleCache {
|
class RenderStyleCache {
|
||||||
final int matchType;
|
final int matchType;
|
||||||
final LRUCache<MatchingCacheKey, RenderStyleItem> cache;
|
final LRUCache<MatchingCacheKey, RenderStyleItem> cache;
|
||||||
@@ -79,7 +85,17 @@ public class RenderTheme implements IRenderTheme {
|
|||||||
this(mapBackground, baseTextSize, rules, levels, false);
|
this(mapBackground, baseTextSize, rules, levels, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public RenderTheme(int mapBackground, float baseTextSize, Rule[] rules, int levels,
|
||||||
|
Map<String, String> transformKeyMap, Map<Tag, Tag> transformTagMap) {
|
||||||
|
this(mapBackground, baseTextSize, rules, levels, transformKeyMap, transformTagMap, false);
|
||||||
|
}
|
||||||
|
|
||||||
public RenderTheme(int mapBackground, float baseTextSize, Rule[] rules, int levels, boolean mapsforgeTheme) {
|
public RenderTheme(int mapBackground, float baseTextSize, Rule[] rules, int levels, boolean mapsforgeTheme) {
|
||||||
|
this(mapBackground, baseTextSize, rules, levels, null, null, mapsforgeTheme);
|
||||||
|
}
|
||||||
|
|
||||||
|
public RenderTheme(int mapBackground, float baseTextSize, Rule[] rules, int levels,
|
||||||
|
Map<String, String> transformKeyMap, Map<Tag, Tag> transformTagMap, boolean mapsforgeTheme) {
|
||||||
if (rules == null)
|
if (rules == null)
|
||||||
throw new IllegalArgumentException("rules missing");
|
throw new IllegalArgumentException("rules missing");
|
||||||
|
|
||||||
@@ -89,6 +105,9 @@ public class RenderTheme implements IRenderTheme {
|
|||||||
mRules = rules;
|
mRules = rules;
|
||||||
mMapsforgeTheme = mapsforgeTheme;
|
mMapsforgeTheme = mapsforgeTheme;
|
||||||
|
|
||||||
|
mTransformKeyMap = transformKeyMap;
|
||||||
|
mTransformTagMap = transformTagMap;
|
||||||
|
|
||||||
mStyleCache = new RenderStyleCache[3];
|
mStyleCache = new RenderStyleCache[3];
|
||||||
mStyleCache[0] = new RenderStyleCache(Element.NODE);
|
mStyleCache[0] = new RenderStyleCache(Element.NODE);
|
||||||
mStyleCache[1] = new RenderStyleCache(Element.LINE);
|
mStyleCache[1] = new RenderStyleCache(Element.LINE);
|
||||||
@@ -272,6 +291,20 @@ public class RenderTheme implements IRenderTheme {
|
|||||||
rule.scaleTextSize(scaleFactor * mBaseTextSize);
|
rule.scaleTextSize(scaleFactor * mBaseTextSize);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String transformKey(String key) {
|
||||||
|
if (mTransformKeyMap != null)
|
||||||
|
return mTransformKeyMap.get(key);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Tag transformTag(Tag tag) {
|
||||||
|
if (mTransformTagMap != null)
|
||||||
|
return mTransformTagMap.get(tag);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void updateStyles() {
|
public void updateStyles() {
|
||||||
for (Rule rule : mRules)
|
for (Rule rule : mRules)
|
||||||
|
|||||||
@@ -4,6 +4,7 @@
|
|||||||
* Copyright 2016-2018 devemux86
|
* Copyright 2016-2018 devemux86
|
||||||
* Copyright 2016-2017 Longri
|
* Copyright 2016-2017 Longri
|
||||||
* Copyright 2016 Andrey Novikov
|
* Copyright 2016 Andrey Novikov
|
||||||
|
* Copyright 2018 Gustl22
|
||||||
*
|
*
|
||||||
* This file is part of the OpenScienceMap project (http://www.opensciencemap.org).
|
* This file is part of the OpenScienceMap project (http://www.opensciencemap.org).
|
||||||
*
|
*
|
||||||
@@ -64,6 +65,7 @@ import java.io.IOException;
|
|||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.Locale;
|
import java.util.Locale;
|
||||||
|
import java.util.Map;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import java.util.Stack;
|
import java.util.Stack;
|
||||||
|
|
||||||
@@ -168,6 +170,9 @@ public class XmlThemeBuilder extends DefaultHandler {
|
|||||||
private XmlRenderThemeStyleLayer mCurrentLayer;
|
private XmlRenderThemeStyleLayer mCurrentLayer;
|
||||||
private XmlRenderThemeStyleMenu mRenderThemeStyleMenu;
|
private XmlRenderThemeStyleMenu mRenderThemeStyleMenu;
|
||||||
|
|
||||||
|
private Map<String, String> mTransformKeyMap = new HashMap<>();
|
||||||
|
private Map<Tag, Tag> mTransformTagMap = new HashMap<>();
|
||||||
|
|
||||||
public XmlThemeBuilder(ThemeFile theme) {
|
public XmlThemeBuilder(ThemeFile theme) {
|
||||||
this(theme, null);
|
this(theme, null);
|
||||||
}
|
}
|
||||||
@@ -202,7 +207,7 @@ public class XmlThemeBuilder extends DefaultHandler {
|
|||||||
}
|
}
|
||||||
|
|
||||||
RenderTheme createTheme(Rule[] rules) {
|
RenderTheme createTheme(Rule[] rules) {
|
||||||
return new RenderTheme(mMapBackground, mTextScale, rules, mLevels, mMapsforgeTheme);
|
return new RenderTheme(mMapBackground, mTextScale, rules, mLevels, mTransformKeyMap, mTransformTagMap, mMapsforgeTheme);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -369,6 +374,10 @@ public class XmlThemeBuilder extends DefaultHandler {
|
|||||||
mRenderThemeStyleMenu = new XmlRenderThemeStyleMenu(getStringAttribute(attributes, "id"),
|
mRenderThemeStyleMenu = new XmlRenderThemeStyleMenu(getStringAttribute(attributes, "id"),
|
||||||
getStringAttribute(attributes, "defaultlang"), getStringAttribute(attributes, "defaultvalue"));
|
getStringAttribute(attributes, "defaultlang"), getStringAttribute(attributes, "defaultvalue"));
|
||||||
|
|
||||||
|
} else if ("tag-transform".equals(localName)) {
|
||||||
|
checkState(qName, Element.RENDERING_STYLE);
|
||||||
|
tagTransform(localName, attributes);
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
log.error("unknown element: {}", localName);
|
log.error("unknown element: {}", localName);
|
||||||
throw new SAXException("unknown element: " + localName);
|
throw new SAXException("unknown element: " + localName);
|
||||||
@@ -1239,6 +1248,44 @@ public class XmlThemeBuilder extends DefaultHandler {
|
|||||||
return dashIntervals;
|
return dashIntervals;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void tagTransform(String localName, Attributes attributes) {
|
||||||
|
String k, v, matchKey, matchValue;
|
||||||
|
k = v = matchKey = matchValue = null;
|
||||||
|
|
||||||
|
for (int i = 0; i < attributes.getLength(); i++) {
|
||||||
|
String name = attributes.getLocalName(i);
|
||||||
|
String value = attributes.getValue(i);
|
||||||
|
|
||||||
|
switch (name) {
|
||||||
|
case "k":
|
||||||
|
k = value;
|
||||||
|
break;
|
||||||
|
case "v":
|
||||||
|
v = value;
|
||||||
|
break;
|
||||||
|
case "k-match":
|
||||||
|
matchKey = value;
|
||||||
|
break;
|
||||||
|
case "v-match":
|
||||||
|
matchValue = value;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
logUnknownAttribute(localName, name, value, i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (k == null || k.isEmpty() || matchKey == null || matchKey.isEmpty()) {
|
||||||
|
log.debug("empty key in element " + localName);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (v == null && matchValue == null) {
|
||||||
|
mTransformKeyMap.put(matchKey, k);
|
||||||
|
} else {
|
||||||
|
mTransformTagMap.put(new Tag(matchKey, matchValue), new Tag(k, v));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private static void validateNonNegative(String name, float value) {
|
private static void validateNonNegative(String name, float value) {
|
||||||
if (value < 0)
|
if (value < 0)
|
||||||
throw new ThemeException(name + " must not be negative: "
|
throw new ThemeException(name + " must not be negative: "
|
||||||
|
|||||||
Reference in New Issue
Block a user