/** * This file is part of OSM2ShareNav * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as published by * the Free Software Foundation. * See COPYING. * * Copyright (C) 2007 Harald Mueller */ package net.sharenav.osmToShareNav.model; import net.sharenav.osmToShareNav.Configuration; import net.sharenav.osmToShareNav.Constants; import net.sharenav.osmToShareNav.LegendParser; public class Node extends Entity { public long id; /** * The position in the target array of nodes. */ public int renumberdId; /** * Latitude (in degrees) of this node. */ public float lat; /** * Longitude (in degrees) of this node. */ public float lon; /** * Type of this Node */ // polish.api.bigstyles private short type = -1; //public byte noConfType = -1; public boolean used = false; private byte connectedLineCount = 0; // private Set<Way> connectedWays = new HashSet<Way>(); public RouteNode routeNode; public boolean fid = false; // the upper flags of connectedLineCount are used to indicate special informations about the node public static final int CLC_MASK_CONNECTEDLINECOUNT = 31; public static final int CLC_NEVER_TRAFFICSIGNALS_ROUTENODE = 128; public static final int CLC_FLAG_TRAFFICSIGNALS = 64; public static final int CLC_FLAG_TRAFFICSIGNALS_ROUTENODE = 32; public Node() { } public Node(float node_lat, float node_lon, long id) { lat = node_lat; lon = node_lon; this.id = id; } public Node(Node old) { lat = old.lat; lon = old.lon; this.id = old.id; } /** * @return Latitude (in degrees) of this node */ public float getLat() { return lat; } /** * @return Longitude (in degrees) of this node */ public float getLon() { return lon; } /** * @return Node in the middle of this node and another node */ public Node midNode(Node old, long newID) { return new Node((lat + old.lat) / 2, (lon + old.lon) / 2, newID); } /** * @return Longitude (in map units) of this node for isClockWise() */ public long getLongLon() { return toMapUnit(lon); } /** * @return Longitude (in map units) of this node for isClockWise() */ public long getLongLat() { return toMapUnit(lat); } /* from mkgmap by Steve Ratcliffe */ /** * A map unit is an integer value that is 1/(2^24) degrees of latitude or * longitude. * * @param l The lat or long as decimal degrees. * @return An integer value in map units. */ private static int toMapUnit(float l) { double DELTA = 360.0D / (1 << 24) / 2; //Correct rounding if (l > 0) return (int) ((l + DELTA) * (1 << 24)/360); else return (int) ((l - DELTA) * (1 << 24)/360); } @Override public String getName() { if (type != -1) { POIdescription desc = Configuration.getConfiguration().getpoiDesc(type); if (desc != null) { String name = getAttribute(desc.nameKey); String nameFallback = null; if (desc.nameFallbackKey!= null && desc.nameFallbackKey.equals("*") ) { nameFallback = getAttribute(desc.key); } else { nameFallback = getAttribute(desc.nameFallbackKey); } if (name != null && nameFallback != null && (!desc.nameFallbackKey.equals("*") || !desc.key.equals(desc.nameKey))) { name += " (" + nameFallback + ")"; } else if ((name == null) && (nameFallback != null)) { name = nameFallback; } //System.out.println("New style name: " + name); return (name != null ? name.trim() : ""); } } return null; } public String getPlace() { String place = (getAttribute("place")); // System.out.println("Read place for id=" + id + " as=" + place); if (place != null) { return place.trim(); } return null; } public boolean isPlace() { if (type != -1) { POIdescription desc = Configuration.getConfiguration().getpoiDesc(type); if (desc.key.equalsIgnoreCase("place")) { return true; } } return false; } public void resetType(Configuration c) { type = -1; } // polish.api.bigstyles public short getType(Configuration c) { if (type != -1) { return type; } else { type = calcType(c); } return type; } public byte getConnectedLineCount() { return (byte)(connectedLineCount & CLC_MASK_CONNECTEDLINECOUNT); } private void setConnectedLineCount(byte count) { connectedLineCount &= ~CLC_MASK_CONNECTEDLINECOUNT; connectedLineCount |= count; } public void resetConnectedLineCount() { connectedLineCount &= ~CLC_MASK_CONNECTEDLINECOUNT; } public void incConnectedLineCount() { setConnectedLineCount((byte) (getConnectedLineCount() + 1)); } public void decConnectedLineCount() { setConnectedLineCount((byte) (getConnectedLineCount() -1)); } public void markAsTrafficSignals() { connectedLineCount |= CLC_FLAG_TRAFFICSIGNALS; } public boolean isTrafficSignals() { return ((connectedLineCount & CLC_FLAG_TRAFFICSIGNALS) > 0); } public void markAsTrafficSignalsRouteNode() { connectedLineCount |= CLC_FLAG_TRAFFICSIGNALS_ROUTENODE; } public void unMarkAsTrafficSignalsRouteNode() { connectedLineCount &= ~CLC_FLAG_TRAFFICSIGNALS_ROUTENODE; } public boolean isTrafficSignalsRouteNode() { return ((connectedLineCount & CLC_FLAG_TRAFFICSIGNALS_ROUTENODE) > 0); } public void markAsNeverTrafficSignalsRouteNode() { connectedLineCount |= CLC_NEVER_TRAFFICSIGNALS_ROUTENODE; } public boolean isNeverTrafficSignalsRouteNode() { return ((connectedLineCount & CLC_NEVER_TRAFFICSIGNALS_ROUTENODE) > 0); } // FIXME should not be hard-coded but taken from style-file public boolean hasHouseNumberTag() { return (containsKey("addr:housenumber")); } // FIXME should not be hard-coded but taken from style-file public boolean isBarrier() { return (containsKey("barrier")); } // polish.api.bigstyles private short calcType(Configuration c) { if (type != -1) { return type; } if (c == null) { return -1; } EntityDescription poi = super.calcType(c.getPOIlegend()); if (poi == null) { type = -1; } else { type = poi.typeNum; } return type; } public byte getZoomlevel(Configuration c) { if (type == -1) { //System.out.println("unknown type for node " + toString()); return 3; } int maxScale = c.getpoiDesc(type).minEntityScale; if (maxScale < LegendParser.tileScaleLevel[3]) { // 45000 in 0.5.0 return 3; } else if (maxScale < LegendParser.tileScaleLevel[2]) { // 180000 in 0.5.0 return 2; } else if (maxScale < LegendParser.tileScaleLevel[1]) { // 900000 in 0.5.0 return 1; } return 0; } @Override public String toString() { return "id=" + id + " (" + lat + "|" + lon + ") " + ((getPlace() != null) ? ("(" + getPlace() + ") ") : "") + "name=" + getName() + ((nearBy == null) ? "" : (" near " + nearBy.getName())); } /** * @return String with the URL to inspect this node on the OSM website */ public String toUrl() { return "http://www.openstreetmap.org/browse/node/" + id; } /** * @return */ public byte getNameType() { String t = getPlace(); if (t != null) { if ("suburb".equals(t)) { return (Constants.NAME_SUBURB); } else { return (Constants.NAME_CITY); } } return Constants.NAME_AMENITY; } /** * wayToPOItransfer is used to transfer properties of a way * onto a Node. This is used to represent area POIs. * @param w The way from which to transfer the properties * @param poi The type of POI to which it gets transfered. * @return if it was successful */ public boolean wayToPOItransfer(Way w, POIdescription poi) { if (type != -1) { System.out.println("WARNING: Node already has a type, can't assign way-poi type"); System.out.println(" " + toString()); return false; } type = poi.typeNum; //String value = w.getAttribute(poi.nameKey); //if (value != null) { // setAttribute(poi.nameKey, value); //} //value = w.getAttribute(poi.nameFallbackKey); //if (value != null) { // setAttribute(poi.nameFallbackKey, value); //} // FIXME could save some memory by copying only needed tags (namekey, fallback, addr:street) for (String t : w.getTags()) { if (w.containsKey(t)) { setAttribute(t, w.getAttribute(t)); } } return true; } }