package net.osmand.osm;
import gnu.trove.map.TIntByteMap;
import gnu.trove.map.hash.TIntByteHashMap;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.Collection;
import java.util.LinkedHashMap;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;
import net.osmand.data.AmenityType;
import net.osmand.osm.OSMSettings.OSMTagKey;
import net.osmand.LogUtil;
import org.apache.commons.logging.Log;
import org.xml.sax.Attributes;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.DefaultHandler;
/**
* SOURCE : http://wiki.openstreetmap.org/wiki/Map_Features
*
* Describing types of polygons :
* 1. Last 2 bits define type of element : polygon, polyline, point
*/
public class MapRenderingTypes {
private static final Log log = LogUtil.getLog(MapRenderingTypes.class);
// TODO Internet access bits for point, polygon
/** standard schema :
polygon : ll aaaaa ttttt 11 : 14 bits
multi : ll aaaaa ttttt 00 : 14 bits
t - object type, a - area subtype,l - layer
polyline : ll ppppp ttttt 10 : 14 bits
t - object type, p - polyline object type, l - layer
point : ssss ssss ttttt 10 : 15 bits
t - object type, s - subtype
*/
public final static int MULTY_POLYGON_TYPE = 0;
public final static int POLYGON_TYPE = 3;
public final static int POLYLINE_TYPE = 2;
public final static int POINT_TYPE = 1;
public final static int PG_SUBTYPE_MASK_LEN = 5;
public final static int PG_SUBTYPE_MASK = (1 << PG_SUBTYPE_MASK_LEN) -1;
public final static int PO_SUBTYPE_MASK_LEN = 8;
public final static int PO_SUBTYPE_MASK = (1 << PO_SUBTYPE_MASK_LEN) -1;
public final static int PL_SUBTYPE_MASK_LEN = 5;
public final static int PL_SUBTYPE_MASK = (1 << PL_SUBTYPE_MASK_LEN) -1;
// TYPES :
public final static int OBJ_TYPE_MASK_LEN = 5;
public final static int OBJ_TYPE_MASK = (1 << OBJ_TYPE_MASK_LEN) -1;
public final static int MASK_13 = (1 << 13) - 1;
public final static int MASK_12 = (1 << 12) - 1;
public final static int MASK_4 = (1 << 4) - 1;
public final static int MASK_5 = (1 << 5) - 1;
public final static int MASK_10 = (1 << 10) - 1;
public final static char REF_CHAR = ((char)0x0019);
public final static char DELIM_CHAR = ((char)0x0018);
public final static byte RESTRICTION_NO_RIGHT_TURN = 1;
public final static byte RESTRICTION_NO_LEFT_TURN = 2;
public final static byte RESTRICTION_NO_U_TURN = 3;
public final static byte RESTRICTION_NO_STRAIGHT_ON = 4;
public final static byte RESTRICTION_ONLY_RIGHT_TURN = 5;
public final static byte RESTRICTION_ONLY_LEFT_TURN = 6;
public final static byte RESTRICTION_ONLY_STRAIGHT_ON = 7;
// two bytes pass!
public static int getMainObjectType(int type){
return (type >> 2) & OBJ_TYPE_MASK;
}
// two bytes pass!
public static int getObjectSubType(int type){
if((type & 3) == 1){
return (type >> 7) & PO_SUBTYPE_MASK;
} else {
return (type >> 7) & PG_SUBTYPE_MASK;
}
}
private String resourceName = null;
// stored information to convert from osm tags to int type
private Map<String, MapRulType> types = null;
private TIntByteMap objectsToMinZoom = null;
private static Map<String, AmenityType> amenityTagValToType = null;
private static Map<String, String> amenityTagValToPrefix = null;
private static String TAG_DELIMETER = "&&"; //$NON-NLS-1$
private Map<AmenityType, Map<String, String>> amenityTypeNameToTagVal = null;
private Map<String, AmenityType> amenityNameToType = null;
public MapRenderingTypes(String fileName){
this.resourceName = fileName;
}
private static MapRenderingTypes DEFAULT_INSTANCE = null;
public static MapRenderingTypes getDefault() {
if(DEFAULT_INSTANCE == null){
DEFAULT_INSTANCE = new MapRenderingTypes(null);
}
return DEFAULT_INSTANCE;
}
private final static int POLYGON_WITH_CENTER_TYPE = 9;
// special type means that ways will transform in area with the same point subtype = as area subtype
// instead of zero point subtype (only for ways!)
private final static int DEFAULT_POLYGON_BUILDING = 10;
public static class MapRulType {
private String tag;
// val could be null means others for that tag
private Integer nullRule;
private Map<String, Integer> rules = new LinkedHashMap<String, Integer>();
private String nameNullTag;
public MapRulType(String tag, String nameNullTag){
this.tag = tag;
}
public String getTag() {
return tag;
}
public String getNameNullTag() {
return nameNullTag;
}
public Collection<String> getValuesSet(){
return rules.keySet();
}
public void registerType(int minZoom, String val, int pointRule, int polylineRule, int polygonRule, int type, int subtype){
int r = encodeRule(minZoom, pointRule, polylineRule, polygonRule, type, subtype);
if(val != null){
rules.put(val, r);
} else {
nullRule = r;
}
}
public boolean registered(String val){
return rules.containsKey(val);
}
public boolean registeredAsNull(){
return nullRule != null && nullRule > 0;
}
private int encodeRule(int minZoom, int pointRule, int polylineRule, int polygonRule, int type, int subtype){
int rule = (((((minZoom << 4) | polygonRule) << 4) | polylineRule) << 4) | pointRule; // 17 bit
rule = (((rule << 8) | subtype) << 5) | type; // + 13 bits
return rule;
}
public int getPointRule(String val){
Integer i = val == null ? nullRule : rules.get(val);
if(i == null){
return 0;
}
return (i >> 13) & MASK_4;
}
public int getPolylineRule(String val){
Integer i = val == null ? nullRule : rules.get(val);
if(i == null){
return 0;
}
return (i >> 17) & MASK_4;
}
public int getPolygonRule(String val){
Integer i = val == null ? nullRule : rules.get(val);
if(i == null){
return 0;
}
return (i >> 21) & MASK_4;
}
public int getMinZoom(String val){
Integer i = val == null ? nullRule : rules.get(val);
if(i == null){
return 0;
}
return (i >> 25);
}
public int getType(String val) {
Integer i = val == null ? nullRule : rules.get(val);
if (i == null) {
return 0;
}
return i & MASK_5;
}
public int getSubType(String val) {
Integer i = val == null ? nullRule : rules.get(val);
if (i == null) {
return 0;
}
return (i & MASK_13) >> 5;
}
public int getType(String val, int mask){
Integer i = val == null ? nullRule : rules.get(val);
if(i == null){
return 0;
}
return i & mask;
}
}
public Map<String, MapRulType> getEncodingRuleTypes(){
if (types == null) {
types = new LinkedHashMap<String, MapRulType>();
init(INIT_RULE_TYPES);
}
return types;
}
// if type equals 0 no need to save that point
public int encodeEntityWithType(Entity e, int zoom, boolean multipolygon, List<Integer> additionalTypes) {
if (types == null) {
types = new LinkedHashMap<String, MapRulType>();
init(INIT_RULE_TYPES);
}
additionalTypes.clear();
if("coastline".equals(e.getTag(OSMTagKey.NATURAL))){ //$NON-NLS-1$
multipolygon = true;
}
boolean point = e instanceof Node;
boolean polygon = multipolygon;
if (!point && !polygon) {
// determining area or path
boolean area = "yes".equals(e.getTag("area")); //$NON-NLS-1$ //$NON-NLS-2$
boolean highway = e.getTag("highway") != null; //$NON-NLS-1$
if(highway && !area){
// skip the check for first and last point
} else {
List<Long> ids = ((Way) e).getNodeIds();
if (ids.size() > 1) {
polygon = ((long) ids.get(0) == (long) ids.get(ids.size() - 1));
}
}
}
Collection<String> tagKeySet = e.getTagKeySet();
// 1. sort tags : important tags (type) will be rendered first
if(tagKeySet.size() > 1 && tagKeySet.contains("building")){ //$NON-NLS-1$
// first of all process building tag (in order to distinguish area and buildings)
LinkedHashSet<String> set = new LinkedHashSet<String>();
set.add("building"); //$NON-NLS-1$
set.addAll(tagKeySet);
tagKeySet = set;
}
int pointType = 0;
int polylineType = 0;
int polygonType = 0;
// 2. 2 iterations first for exact tag=value match, second for any tag match
for (int i = 0; i < 2; i++) {
if (i == 1 && !additionalTypes.isEmpty()) {
break;
}
for (String tag : tagKeySet) {
if (types.containsKey(tag)) {
MapRulType rType = types.get(tag);
String val = i == 1 ? null : e.getTag(tag);
if(rType.getMinZoom(val) > zoom){
continue;
}
int pr = point ? rType.getPointRule(val) : (polygon ? rType.getPolygonRule(val) : rType.getPolylineRule(val));
int typeVal = rType.getType(val, MASK_13) << 2;
if (pr == POINT_TYPE && pointType == 0) {
pointType = POINT_TYPE | typeVal;
additionalTypes.add(pointType);
} else if (!point && pr == POLYLINE_TYPE) {
int attr = getLayerAttributes(e) << 12;
boolean prevPoint = (polylineType == 0 && polygonType == 0);
polylineType = POLYLINE_TYPE | (typeVal & MASK_12) | attr;
if (tag.equals("highway") || prevPoint){ //$NON-NLS-1$
additionalTypes.add(0, polylineType);
} else {
additionalTypes.add(polylineType);
}
} else if (polygon && (pr == POLYGON_WITH_CENTER_TYPE || pr == POLYGON_TYPE)) {
boolean prevPoint = (polylineType == 0 && polygonType == 0);
int attr = getLayerAttributes(e) << 12;
polygonType = (multipolygon ? MULTY_POLYGON_TYPE : POLYGON_TYPE) | (typeVal & MASK_12) | attr;
if (prevPoint){
additionalTypes.add(0, polygonType);
} else {
additionalTypes.add(polygonType);
}
if (pr == POLYGON_WITH_CENTER_TYPE) {
pointType = POINT_TYPE | typeVal;
additionalTypes.add(pointType);
}
} else if (polygon && (pr == DEFAULT_POLYGON_BUILDING)) {
// TODO get polygon type
int MAN_MADE = 8;
int SUBTYPE_BUILDING = 1;
if(polygonType == 0 && polylineType == 0){
int attr = getLayerAttributes(e) << 12;
polygonType = (multipolygon ? MULTY_POLYGON_TYPE : POLYGON_TYPE) | (((SUBTYPE_BUILDING << 5) | MAN_MADE) << 2) | attr;
additionalTypes.add(0, polygonType);
}
pointType = POINT_TYPE | typeVal;
additionalTypes.add(pointType);
}
}
}
}
int type = 0;
if(!additionalTypes.isEmpty()){
type = additionalTypes.get(0);
additionalTypes.remove(0);
}
return type;
}
public static boolean isOneWayWay(int highwayAttributes){
return (highwayAttributes & 1) > 0;
}
public static boolean isRoundabout(int highwayAttributes){
return ((highwayAttributes >> 2) & 1) > 0;
}
// 0 - normal, 1 - under, 2 - bridge,over
public static int getWayLayer(int type){
return (3 & (type >> 12));
}
// 0 - normal, -1 - under, 1 - bridge,over
public static int getNegativeWayLayer(int type) {
int i = (3 & (type >> 12));
if (i == 1) {
return -1;
} else if (i == 2) {
return 1;
}
return 0;
}
// return 0 if not defined
public static int getMaxSpeedIfDefined(int highwayAttributes){
switch((highwayAttributes >> 4) & 7) {
case 0:
return 20;
case 1:
return 40;
case 2:
// for old format it should return 0;
// TODO it should be uncommented because now it is fixed
// return 60;
return 0;
case 3:
return 80;
case 4:
return 100;
case 5:
return 120;
case 6:
return 140;
case 7:
return 0;
}
return 0;
}
// HIGHWAY special attributes :
// o/oneway 1 bit
// f/free toll 1 bit
// r/roundabout 2 bit (+ 1 bit direction)
// s/max speed 3 bit [0 - 30km/h, 1 - 50km/h, 2 - 70km/h, 3 - 90km/h, 4 - 110km/h, 5 - 130 km/h, 6 >, 7 - 0/not specified]
// a/vehicle access 4 bit (height, weight?) - one bit bicycle
// p/parking 1 bit
// c/cycle oneway 1 bit
// TODO
// ci/inside city 1 bit
// ENCODING : ci|c|p|aaaa|sss|rr|f|o - 14 bit
public static int getHighwayAttributes(Entity e){
int attr = 0;
// cycle oneway
attr <<= 1;
String c = e.getTag("cycleway"); //$NON-NLS-1$
if(c != null && ("opposite_lane".equals(c) || "opposite_track".equals(c) || "opposite".equals(c))){ //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
attr |= 1;
}
// parking
attr <<= 1;
String park = e.getTag("service"); //$NON-NLS-1$
if("parking_aisle".equals(park)){ //$NON-NLS-1$
attr |= 1;
}
// ACCESS not complete (should be redesigned)
// vehicle access (not implement yet)
attr <<= 3;
boolean hgv = "yes".equals(e.getTag("hgv")); //$NON-NLS-1$ //$NON-NLS-2$
if(hgv){
attr |= 3;
} else {
boolean goods = "yes".equals(e.getTag("goods")); //$NON-NLS-1$ //$NON-NLS-2$
if(goods){
attr |= 2;
} else {
attr |= 1;
}
}
// bicycle access
attr <<= 1;
// speed
// very simple algorithm doesn't consider city rules (country rules) and miles per hour
attr <<= 3;
String maxspeed = e.getTag("maxspeed"); //$NON-NLS-1$
if(maxspeed != null){
int kmh = 0;
try {
kmh = Integer.parseInt(maxspeed);
} catch (NumberFormatException es) {
}
if(kmh <= 0){
attr |= 7;
} else if(kmh <= 30){
attr |= 0;
} else if(kmh <= 50){
attr |= 1;
} else if(kmh <= 70){
attr |= 2;
} else if(kmh <= 90){
attr |= 3;
} else if(kmh <= 110){
attr |= 4;
} else if(kmh <= 130){
attr |= 5;
} else {
attr |= 6;
}
} else {
attr |= 7;
}
// roundabout
attr <<= 2;
String jun = e.getTag(OSMTagKey.JUNCTION);
if(jun != null){
if("roundabout".equals(jun)){ //$NON-NLS-1$
attr |= 1;
if("clockwise".equals(e.getTag("direction"))){ //$NON-NLS-1$ //$NON-NLS-2$
attr |= 2;
}
}
}
// toll
String toll = e.getTag(OSMTagKey.TOLL);
attr <<= 1;
if(toll != null){
if("yes".equals(toll)){ //$NON-NLS-1$
attr |= 1;
}
}
// oneway
String one = e.getTag(OSMTagKey.ONEWAY);
attr <<= 1;
if(one != null && (one.equals("yes") || one.equals("1") || one.equals("-1"))){ //$NON-NLS-1$ //$NON-NLS-2$//$NON-NLS-3$
attr |= 1;
}
return attr;
}
private static int getLayerAttributes(Entity e){
// layer
String l = e.getTag(OSMTagKey.LAYER);
if(l != null){
if(l.startsWith("+")){ //$NON-NLS-1$
l = l.substring(1);
}
int la = 0;
try {
la = Integer.parseInt(l);
} catch (NumberFormatException es) {
}
if(la < 0){
return 1;
} else if(la > 0){
return 2;
}
} else if(e.getTag(OSMTagKey.BRIDGE) != null){
return 2;
} else if(e.getTag(OSMTagKey.TUNNEL) != null){
return 1;
}
return 0;
}
public static boolean isLayerUnder(int attr){
return (attr & 3) == 1;
}
public String getEntityName(Entity e) {
if (e.getTag(OSMTagKey.REF) != null && e.getTag(OSMTagKey.HIGHWAY) != null) {
String ref = e.getTag(OSMTagKey.REF);
if (ref.length() > 5 && ref.indexOf('_') != -1) {
ref = ref.substring(0, ref.indexOf('_'));
}
String name = e.getTag(OSMTagKey.NAME);
if(name != null && !name.equals(ref)){
return REF_CHAR + ref + REF_CHAR + name;
} else {
return REF_CHAR + ref;
}
}
String name = e.getTag(OSMTagKey.NAME);
if (name == null) {
name = e.getTag(OSMTagKey.ADDR_HOUSE_NUMBER);
}
if (name == null) {
Collection<String> tagKeySet = e.getTagKeySet();
Map<String, MapRulType> types = getEncodingRuleTypes();
for (int i = 0; i < 2 && name == null; i++) {
for (String tag : tagKeySet) {
if (types.containsKey(tag)) {
MapRulType rType = types.get(tag);
if (rType.getNameNullTag() != null) {
name = e.getTag(rType.getNameNullTag());
if (name != null) {
break;
}
}
}
}
}
}
return name;
}
private void initAmenityMap(){
if (amenityTypeNameToTagVal == null) {
amenityTypeNameToTagVal = new LinkedHashMap<AmenityType, Map<String, String>>();
init(INIT_AMENITY_MAP);
}
}
/**
*
* @return <type, minzoom> map
* only when minzoom < 15
*/
public TIntByteMap getObjectTypeMinZoom(){
if(objectsToMinZoom == null){
objectsToMinZoom = new TIntByteHashMap();
init(INIT_TYPE_ZOOM);
}
return objectsToMinZoom;
}
public Map<AmenityType, Map<String, String>> getAmenityTypeNameToTagVal() {
initAmenityMap();
return amenityTypeNameToTagVal;
}
public Map<String, AmenityType> getAmenityNameToType(){
initAmenityMap();
if(amenityNameToType == null){
amenityNameToType = new LinkedHashMap<String, AmenityType>();
for(AmenityType s : amenityTypeNameToTagVal.keySet()){
Map<String, String> map = amenityTypeNameToTagVal.get(s);
for(String t : map.keySet()){
// if(amenityNameToType.containsKey(t)){
// System.err.println("Conflict " + t + " " + amenityNameToType.get(t) + " <> " + s);
// }
amenityNameToType.put(t, s);
}
}
}
return amenityNameToType;
}
private void registerAmenity(String tag, String val, int type, int subtype){
AmenityType t = getAmenityType(tag, val);
if (t != null) {
if (val != null) {
if (!amenityTypeNameToTagVal.containsKey(t)) {
amenityTypeNameToTagVal.put(t, new LinkedHashMap<String, String>());
}
String name = val;
String prefix = getAmenitySubtypePrefix(tag, val);
if (prefix != null) {
name = prefix + name;
}
Map<String, String> map = amenityTypeNameToTagVal.get(t);
if (map.containsKey(val)) {
if (type == 17 && subtype == 23) {
// natural wood
} else if (type == 2 && subtype == 21) {
// barrier gate
} else {
// debug purpose
// System.err.println("Duplicate entry " + tag + " " + val + " for " + t);
}
} else {
if (prefix != null) {
map.put(name, tag + " " + val); //$NON-NLS-1$
} else {
map.put(name, tag);
}
}
}
}else {
// debug purpose
// System.out.println("NOT ACCEPTED " + tag + " " + val);
}
}
private final static int INIT_RULE_TYPES = 0;
private final static int INIT_AMENITY_MAP = 1;
private final static int INIT_TYPE_ZOOM = 2;
private void init(final int st){
InputStream is;
try {
if(resourceName == null){
is = MapRenderingTypes.class.getResourceAsStream("rendering_types.xml"); //$NON-NLS-1$
} else {
is = new FileInputStream(resourceName);
}
long time = System.currentTimeMillis();
final SAXParser parser = SAXParserFactory.newInstance().newSAXParser();
parser.parse(is, new DefaultHandler(){
int currentType = 1;
@Override
public void startElement(String uri, String localName, String name, Attributes attributes) throws SAXException {
name = parser.isNamespaceAware() ? localName : name;
if(name.equals("type")){ //$NON-NLS-1$
currentType = Integer.parseInt(attributes.getValue("id")); //$NON-NLS-1$
} else if (name.equals("subtype")) { //$NON-NLS-1$
String val = attributes.getValue("minzoom"); //$NON-NLS-1$
int maxzoom = 15;
if (val != null) {
maxzoom = Integer.parseInt(val);
}
String nameNullTag = attributes.getValue("nameNullTag"); //$NON-NLS-1$
String tag = attributes.getValue("tag"); //$NON-NLS-1$
val = attributes.getValue("value"); //$NON-NLS-1$
if (val != null && (val.equalsIgnoreCase("null") || val.length() == 0)) { //$NON-NLS-1$
val = null;
}
int subtype = Integer.parseInt(attributes.getValue("id")); //$NON-NLS-1$
boolean building = Boolean.parseBoolean(attributes.getValue("building")); //$NON-NLS-1$
boolean polygon = Boolean.parseBoolean(attributes.getValue("polygon")); //$NON-NLS-1$
boolean polyline = Boolean.parseBoolean(attributes.getValue("polyline")); //$NON-NLS-1$
boolean point = Boolean.parseBoolean(attributes.getValue("point")); //$NON-NLS-1$
boolean polygon_center = Boolean.parseBoolean(attributes.getValue("polygon_center")); //$NON-NLS-1$
int polygonRule = 0;
int pointRule = 0;
int polylineRule = 0;
if(building || point || polygon_center){
pointRule = POINT_TYPE;
}
if(!polyline && polygon) {
pointRule = POINT_TYPE;
}
if(polyline){
polylineRule = POLYLINE_TYPE;
} else if(point){
polylineRule = POINT_TYPE;
}
if(building){
polygonRule = DEFAULT_POLYGON_BUILDING;
} else if(polygon_center){
polygonRule = POLYGON_WITH_CENTER_TYPE;
} else if(polygon){
polygonRule = POLYGON_TYPE;
}else if(polyline){
polygonRule = POLYLINE_TYPE;
} else if(point){
polygonRule = POINT_TYPE;
}
stepSubtype(st, maxzoom, tag, val, currentType, subtype, polygonRule, polylineRule, pointRule, nameNullTag);
}
}
});
log.info("Time to init " + (System.currentTimeMillis() - time)); //$NON-NLS-1$
is.close();
} catch (IOException e) {
log.error("Unexpected error", e); //$NON-NLS-1$
e.printStackTrace();
throw new RuntimeException(e);
} catch (RuntimeException e) {
log.error("Unexpected error", e); //$NON-NLS-1$
e.printStackTrace();
throw e;
} catch (ParserConfigurationException e) {
log.error("Unexpected error", e); //$NON-NLS-1$
e.printStackTrace();
throw new RuntimeException(e);
} catch (SAXException e) {
log.error("Unexpected error", e); //$NON-NLS-1$
e.printStackTrace();
throw new RuntimeException(e);
}
}
private void stepSubtype(int st, int minZoom, String tag, String val, int type, int subtype, int polygonRule, int polylineRule,
int pointRule, String nameNullTag) {
if(st == INIT_RULE_TYPES){
MapRulType rtype = types.get(tag);
if(rtype == null){
rtype = new MapRulType(tag, nameNullTag);
types.put(tag, rtype);
}
rtype.registerType(minZoom, val, pointRule, polylineRule, polygonRule, type, subtype);
} else if(st == INIT_AMENITY_MAP){
if(pointRule == POINT_TYPE || polygonRule == POLYGON_WITH_CENTER_TYPE || polygonRule == POLYGON_TYPE){
registerAmenity(tag, val, type, subtype);
}
} else if(st == INIT_TYPE_ZOOM){
if(minZoom < 15){
int value = (((subtype) << 5) | type) << 2;
if(!objectsToMinZoom.containsKey(value)){
// add only first
objectsToMinZoom.put(value, (byte) minZoom);
}
}
}
}
public static String getAmenitySubtype(String tag, String val){
String prefix = getAmenitySubtypePrefix(tag, val);
if(prefix != null){
return prefix + val;
}
return val;
}
public static String getAmenitySubtypePrefix(String tag, String val){
if(amenityTagValToPrefix == null){
amenityTagValToPrefix = new LinkedHashMap<String, String>();
amenityTagValToPrefix.put("traffic_calming", "traffic_calming_"); //$NON-NLS-1$ //$NON-NLS-2$
amenityTagValToPrefix.put("power", "power_"); //$NON-NLS-1$//$NON-NLS-2$
amenityTagValToPrefix.put("waterway", "water_"); //$NON-NLS-1$ //$NON-NLS-2$
amenityTagValToPrefix.put("waterway"+TAG_DELIMETER+"riverbank", null); //$NON-NLS-1$ //$NON-NLS-2$
amenityTagValToPrefix.put("railway", "railway_"); //$NON-NLS-1$ //$NON-NLS-2$
amenityTagValToPrefix.put("railway"+TAG_DELIMETER+"subway_entrance", null); //$NON-NLS-1$ //$NON-NLS-2$
amenityTagValToPrefix.put("aeroway", "aeroway_"); //$NON-NLS-1$ //$NON-NLS-2$
amenityTagValToPrefix.put("aerialway", "aerialway_"); //$NON-NLS-1$ //$NON-NLS-2$
}
if(val != null && amenityTagValToPrefix.containsKey(tag+TAG_DELIMETER+val)){
return amenityTagValToPrefix.get(tag+TAG_DELIMETER+val);
}
return amenityTagValToPrefix.get(tag);
}
public static AmenityType getAmenityType(String tag, String val){
// register amenity types
if(amenityTagValToType == null){
initAmenityTagValToType();
}
if(amenityTagValToType.containsKey(tag+TAG_DELIMETER+val)){
return amenityTagValToType.get(tag+TAG_DELIMETER+val);
}
return amenityTagValToType.get(tag);
}
private static void initAmenityTagValToType() {
amenityTagValToType = new LinkedHashMap<String, AmenityType>();
amenityTagValToType.put("highway"+TAG_DELIMETER+"bus_stop", AmenityType.TRANSPORTATION); //$NON-NLS-1$ //$NON-NLS-2$
amenityTagValToType.put("highway"+TAG_DELIMETER+"platform", AmenityType.TRANSPORTATION); //$NON-NLS-1$ //$NON-NLS-2$
amenityTagValToType.put("highway"+TAG_DELIMETER+"turning_circle", AmenityType.TRANSPORTATION); //$NON-NLS-1$ //$NON-NLS-2$
amenityTagValToType.put("highway"+TAG_DELIMETER+"emergency_access_point", AmenityType.TRANSPORTATION); //$NON-NLS-1$ //$NON-NLS-2$
amenityTagValToType.put("highway"+TAG_DELIMETER+"speed_camera", AmenityType.TRANSPORTATION); //$NON-NLS-1$ //$NON-NLS-2$
amenityTagValToType.put("traffic_calming", AmenityType.BARRIER); //$NON-NLS-1$
amenityTagValToType.put("barrier", AmenityType.BARRIER); //$NON-NLS-1$
amenityTagValToType.put("natural"+TAG_DELIMETER+"hedge", AmenityType.BARRIER); //$NON-NLS-1$//$NON-NLS-2$
amenityTagValToType.put("historic"+TAG_DELIMETER+"city_walls", AmenityType.BARRIER); //$NON-NLS-1$ //$NON-NLS-2$
amenityTagValToType.put("highway"+TAG_DELIMETER+"gate", AmenityType.BARRIER); //$NON-NLS-1$ //$NON-NLS-2$
amenityTagValToType.put("waterway"+TAG_DELIMETER+"stream", AmenityType.NATURAL); //$NON-NLS-1$//$NON-NLS-2$
amenityTagValToType.put("waterway"+TAG_DELIMETER+"riverbank", AmenityType.NATURAL); //$NON-NLS-1$//$NON-NLS-2$
amenityTagValToType.put("waterway"+TAG_DELIMETER+"river", AmenityType.NATURAL); //$NON-NLS-1$//$NON-NLS-2$
amenityTagValToType.put("waterway"+TAG_DELIMETER+"canal", AmenityType.NATURAL); //$NON-NLS-1$//$NON-NLS-2$
amenityTagValToType.put("waterway"+TAG_DELIMETER+"ditch", AmenityType.NATURAL); //$NON-NLS-1$//$NON-NLS-2$
amenityTagValToType.put("waterway"+TAG_DELIMETER+"drain", AmenityType.NATURAL); //$NON-NLS-1$//$NON-NLS-2$
amenityTagValToType.put("waterway", AmenityType.MAN_MADE); //$NON-NLS-1$
amenityTagValToType.put("railway", AmenityType.TRANSPORTATION); //$NON-NLS-1$
amenityTagValToType.put("aeroway", AmenityType.TRANSPORTATION); //$NON-NLS-1$
amenityTagValToType.put("aerialway", AmenityType.TRANSPORTATION); //$NON-NLS-1$
amenityTagValToType.put("aerialway"+TAG_DELIMETER+"pylon", null); //$NON-NLS-1$//$NON-NLS-2$
// do not add power tower to index
amenityTagValToType.put("power"+TAG_DELIMETER+"station", AmenityType.MAN_MADE); //$NON-NLS-1$//$NON-NLS-2$
amenityTagValToType.put("power"+TAG_DELIMETER+"sub_station", AmenityType.MAN_MADE); //$NON-NLS-1$//$NON-NLS-2$
amenityTagValToType.put("power"+TAG_DELIMETER+"generator", AmenityType.MAN_MADE); //$NON-NLS-1$//$NON-NLS-2$
amenityTagValToType.put("power"+TAG_DELIMETER+"cable_distribution_cabinet", AmenityType.MAN_MADE); //$NON-NLS-1$//$NON-NLS-2$
amenityTagValToType.put("building", null); //$NON-NLS-1$
amenityTagValToType.put("man_made"+TAG_DELIMETER+"wastewater_plant", null); //$NON-NLS-1$//$NON-NLS-2$
amenityTagValToType.put("man_made"+TAG_DELIMETER+"water_works", null); //$NON-NLS-1$//$NON-NLS-2$
amenityTagValToType.put("man_made"+TAG_DELIMETER+"works", null); //$NON-NLS-1$//$NON-NLS-2$
amenityTagValToType.put("man_made", AmenityType.MAN_MADE); //$NON-NLS-1$
amenityTagValToType.put("leisure", AmenityType.LEISURE); //$NON-NLS-1$
amenityTagValToType.put("natural"+TAG_DELIMETER+"park", AmenityType.LEISURE); //$NON-NLS-1$//$NON-NLS-2$
amenityTagValToType.put("office", AmenityType.OFFICE); //$NON-NLS-1$
amenityTagValToType.put("amenity"+TAG_DELIMETER+"architect_office", AmenityType.OFFICE); //$NON-NLS-1$//$NON-NLS-2$
amenityTagValToType.put("shop", AmenityType.SHOP); //$NON-NLS-1$
amenityTagValToType.put("emergency", AmenityType.EMERGENCY); //$NON-NLS-1$
amenityTagValToType.put("amenity"+TAG_DELIMETER+"fire_station", AmenityType.EMERGENCY); //$NON-NLS-1$//$NON-NLS-2$
amenityTagValToType.put("tourism", AmenityType.TOURISM); //$NON-NLS-1$
amenityTagValToType.put("historic", AmenityType.HISTORIC); //$NON-NLS-1$
amenityTagValToType.put("landuse"+TAG_DELIMETER+"basin", AmenityType.LANDUSE); //$NON-NLS-1$//$NON-NLS-2$
amenityTagValToType.put("landuse"+TAG_DELIMETER+"grave_yard", AmenityType.LANDUSE); //$NON-NLS-1$//$NON-NLS-2$
amenityTagValToType.put("landuse"+TAG_DELIMETER+"cemetery", AmenityType.LANDUSE); //$NON-NLS-1$//$NON-NLS-2$
amenityTagValToType.put("landuse"+TAG_DELIMETER+"forest", AmenityType.LANDUSE); //$NON-NLS-1$//$NON-NLS-2$
amenityTagValToType.put("landuse"+TAG_DELIMETER+"meadow", AmenityType.LANDUSE); //$NON-NLS-1$//$NON-NLS-2$
amenityTagValToType.put("landuse"+TAG_DELIMETER+"military", AmenityType.LANDUSE); //$NON-NLS-1$//$NON-NLS-2$
amenityTagValToType.put("landuse"+TAG_DELIMETER+"orchard", AmenityType.LANDUSE); //$NON-NLS-1$//$NON-NLS-2$
amenityTagValToType.put("landuse"+TAG_DELIMETER+"recreation_ground", AmenityType.LANDUSE); //$NON-NLS-1$//$NON-NLS-2$
amenityTagValToType.put("landuse"+TAG_DELIMETER+"conservation", AmenityType.LANDUSE); //$NON-NLS-1$//$NON-NLS-2$
amenityTagValToType.put("landuse"+TAG_DELIMETER+"village_green", AmenityType.LANDUSE); //$NON-NLS-1$//$NON-NLS-2$
amenityTagValToType.put("landuse"+TAG_DELIMETER+"reservoir", AmenityType.LANDUSE); //$NON-NLS-1$//$NON-NLS-2$
amenityTagValToType.put("landuse"+TAG_DELIMETER+"water", AmenityType.LANDUSE); //$NON-NLS-1$//$NON-NLS-2$
amenityTagValToType.put("landuse"+TAG_DELIMETER+"salt_pond", AmenityType.LANDUSE); //$NON-NLS-1$//$NON-NLS-2$
amenityTagValToType.put("landuse"+TAG_DELIMETER+"quarry", AmenityType.LANDUSE); //$NON-NLS-1$//$NON-NLS-2$
amenityTagValToType.put("landuse"+TAG_DELIMETER+"vineyard", AmenityType.LANDUSE); //$NON-NLS-1$//$NON-NLS-2$
amenityTagValToType.put("landuse"+TAG_DELIMETER+"wood", AmenityType.NATURAL); //$NON-NLS-1$//$NON-NLS-2$
amenityTagValToType.put("military", AmenityType.MILITARY); //$NON-NLS-1$
amenityTagValToType.put("natural", AmenityType.NATURAL); //$NON-NLS-1$
amenityTagValToType.put("natural"+TAG_DELIMETER+"field", null); //$NON-NLS-1$ //$NON-NLS-2$
amenityTagValToType.put("amenity"+TAG_DELIMETER+"restaurant", AmenityType.SUSTENANCE); //$NON-NLS-1$//$NON-NLS-2$
amenityTagValToType.put("amenity"+TAG_DELIMETER+"cafe", AmenityType.SUSTENANCE); //$NON-NLS-1$//$NON-NLS-2$
amenityTagValToType.put("amenity"+TAG_DELIMETER+"food_court", AmenityType.SUSTENANCE); //$NON-NLS-1$//$NON-NLS-2$
amenityTagValToType.put("amenity"+TAG_DELIMETER+"fast_food", AmenityType.SUSTENANCE); //$NON-NLS-1$//$NON-NLS-2$
amenityTagValToType.put("amenity"+TAG_DELIMETER+"pub", AmenityType.SUSTENANCE); //$NON-NLS-1$//$NON-NLS-2$
amenityTagValToType.put("amenity"+TAG_DELIMETER+"bar", AmenityType.SUSTENANCE); //$NON-NLS-1$//$NON-NLS-2$
amenityTagValToType.put("amenity"+TAG_DELIMETER+"biergarten", AmenityType.SUSTENANCE); //$NON-NLS-1$//$NON-NLS-2$
amenityTagValToType.put("amenity"+TAG_DELIMETER+"drinking_water", AmenityType.SUSTENANCE); //$NON-NLS-1$//$NON-NLS-2$
amenityTagValToType.put("amenity"+TAG_DELIMETER+"bbq", AmenityType.SUSTENANCE); //$NON-NLS-1$//$NON-NLS-2$
amenityTagValToType.put("amenity"+TAG_DELIMETER+"kindergarten", AmenityType.EDUCATION); //$NON-NLS-1$//$NON-NLS-2$
amenityTagValToType.put("amenity"+TAG_DELIMETER+"school", AmenityType.EDUCATION); //$NON-NLS-1$//$NON-NLS-2$
amenityTagValToType.put("amenity"+TAG_DELIMETER+"college", AmenityType.EDUCATION); //$NON-NLS-1$//$NON-NLS-2$
amenityTagValToType.put("amenity"+TAG_DELIMETER+"library", AmenityType.EDUCATION); //$NON-NLS-1$//$NON-NLS-2$
amenityTagValToType.put("amenity"+TAG_DELIMETER+"university", AmenityType.EDUCATION); //$NON-NLS-1$//$NON-NLS-2$
amenityTagValToType.put("amenity"+TAG_DELIMETER+"kindergarten", AmenityType.EDUCATION); //$NON-NLS-1$//$NON-NLS-2$
amenityTagValToType.put("amenity"+TAG_DELIMETER+"parking", AmenityType.TRANSPORTATION); //$NON-NLS-1$//$NON-NLS-2$
amenityTagValToType.put("amenity"+TAG_DELIMETER+"bicycle_parking", AmenityType.TRANSPORTATION); //$NON-NLS-1$//$NON-NLS-2$
amenityTagValToType.put("amenity"+TAG_DELIMETER+"ferry_terminal", AmenityType.TRANSPORTATION); //$NON-NLS-1$//$NON-NLS-2$
amenityTagValToType.put("amenity"+TAG_DELIMETER+"fuel", AmenityType.TRANSPORTATION); //$NON-NLS-1$//$NON-NLS-2$
amenityTagValToType.put("amenity"+TAG_DELIMETER+"taxi", AmenityType.TRANSPORTATION); //$NON-NLS-1$//$NON-NLS-2$
amenityTagValToType.put("amenity"+TAG_DELIMETER+"bicycle_rental", AmenityType.TRANSPORTATION); //$NON-NLS-1$//$NON-NLS-2$
amenityTagValToType.put("amenity"+TAG_DELIMETER+"bus_station", AmenityType.TRANSPORTATION); //$NON-NLS-1$//$NON-NLS-2$
amenityTagValToType.put("amenity"+TAG_DELIMETER+"car_rental", AmenityType.TRANSPORTATION); //$NON-NLS-1$//$NON-NLS-2$
amenityTagValToType.put("amenity"+TAG_DELIMETER+"car_sharing", AmenityType.TRANSPORTATION); //$NON-NLS-1$//$NON-NLS-2$
amenityTagValToType.put("amenity"+TAG_DELIMETER+"car_wash", AmenityType.TRANSPORTATION); //$NON-NLS-1$//$NON-NLS-2$
amenityTagValToType.put("amenity"+TAG_DELIMETER+"grit_bin", AmenityType.TRANSPORTATION); //$NON-NLS-1$//$NON-NLS-2$
amenityTagValToType.put("amenity"+TAG_DELIMETER+"atm", AmenityType.FINANCE); //$NON-NLS-1$//$NON-NLS-2$
amenityTagValToType.put("amenity"+TAG_DELIMETER+"bank", AmenityType.FINANCE); //$NON-NLS-1$//$NON-NLS-2$
amenityTagValToType.put("amenity"+TAG_DELIMETER+"bureau_de_change", AmenityType.FINANCE); //$NON-NLS-1$//$NON-NLS-2$
amenityTagValToType.put("amenity"+TAG_DELIMETER+"pharmacy", AmenityType.HEALTHCARE); //$NON-NLS-1$//$NON-NLS-2$
amenityTagValToType.put("amenity"+TAG_DELIMETER+"hospital", AmenityType.HEALTHCARE); //$NON-NLS-1$//$NON-NLS-2$
amenityTagValToType.put("amenity"+TAG_DELIMETER+"baby_hatch", AmenityType.HEALTHCARE); //$NON-NLS-1$//$NON-NLS-2$
amenityTagValToType.put("amenity"+TAG_DELIMETER+"dentist", AmenityType.HEALTHCARE); //$NON-NLS-1$//$NON-NLS-2$
amenityTagValToType.put("amenity"+TAG_DELIMETER+"doctors", AmenityType.HEALTHCARE); //$NON-NLS-1$//$NON-NLS-2$
amenityTagValToType.put("amenity"+TAG_DELIMETER+"veterinary", AmenityType.HEALTHCARE); //$NON-NLS-1$//$NON-NLS-2$
amenityTagValToType.put("amenity"+TAG_DELIMETER+"first_aid", AmenityType.HEALTHCARE); //$NON-NLS-1$//$NON-NLS-2$
amenityTagValToType.put("amenity"+TAG_DELIMETER+"arts_centre", AmenityType.ENTERTAINMENT); //$NON-NLS-1$//$NON-NLS-2$
amenityTagValToType.put("amenity"+TAG_DELIMETER+"cinema", AmenityType.ENTERTAINMENT); //$NON-NLS-1$//$NON-NLS-2$
amenityTagValToType.put("amenity"+TAG_DELIMETER+"community_centre", AmenityType.ENTERTAINMENT); //$NON-NLS-1$//$NON-NLS-2$
amenityTagValToType.put("amenity"+TAG_DELIMETER+"social_centre", AmenityType.ENTERTAINMENT); //$NON-NLS-1$//$NON-NLS-2$
amenityTagValToType.put("amenity"+TAG_DELIMETER+"nightclub", AmenityType.ENTERTAINMENT); //$NON-NLS-1$//$NON-NLS-2$
amenityTagValToType.put("amenity"+TAG_DELIMETER+"stripclub", AmenityType.ENTERTAINMENT); //$NON-NLS-1$//$NON-NLS-2$
amenityTagValToType.put("amenity"+TAG_DELIMETER+"studio", AmenityType.ENTERTAINMENT); //$NON-NLS-1$//$NON-NLS-2$
amenityTagValToType.put("amenity"+TAG_DELIMETER+"theatre", AmenityType.ENTERTAINMENT); //$NON-NLS-1$//$NON-NLS-2$
amenityTagValToType.put("amenity"+TAG_DELIMETER+"sauna", AmenityType.ENTERTAINMENT); //$NON-NLS-1$//$NON-NLS-2$
amenityTagValToType.put("amenity"+TAG_DELIMETER+"brothel", AmenityType.ENTERTAINMENT); //$NON-NLS-1$//$NON-NLS-2$
amenityTagValToType.put("geocache", AmenityType.GEOCACHE); //$NON-NLS-1$
amenityTagValToType.put("amenity", AmenityType.OTHER); //$NON-NLS-1$
amenityTagValToType.put("place", AmenityType.ADMINISTRATIVE); //$NON-NLS-1$
amenityTagValToType.put("sport", AmenityType.SPORT); //$NON-NLS-1$
}
public static void main(String[] args) {
// Map<String, Map<String, AmenityType>> amenityMap = getAmenityTagValToTypeMap();
// for(String s : amenityMap.keySet()){
// System.out.println(s + " - " + amenityMap.get(s));
// }
// Map<AmenityType, Map<String, String>> amenityType = getAmenityTypeNameToTagVal();
// for(AmenityType s : amenityType.keySet()){
// Map<String, String> map = amenityType.get(s);
// for(String t : map.keySet()){
// System.out.println(s + " - " + t + " " + map.get(t));
// }
// }
// System.out.println(getAmenityNameToType());
// long ts = System.currentTimeMillis();
System.out.println(MapUtils.getTileNumberX(13, 23.95)+ " " + MapUtils.getTileNumberY(13, 52.136));
MapRenderingTypes def = MapRenderingTypes.getDefault();
def.initAmenityMap();
System.out.println(def.amenityTypeNameToTagVal);
System.out.println(def.getAmenityNameToType());
}
}