TileData.java :  » Tools » mapsforge » org » mapsforge » preprocessing » map » osmosis » Android Open Source

Android Open Source » Tools » mapsforge 
mapsforge » org » mapsforge » preprocessing » map » osmosis » TileData.java
/*
 * Copyright 2010, 2011 mapsforge.org
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
package org.mapsforge.preprocessing.map.osmosis;

import gnu.trove.list.array.TShortArrayList;
import gnu.trove.set.TShortSet;
import gnu.trove.set.hash.TShortHashSet;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.logging.Logger;

import org.mapsforge.core.GeoCoordinate;
import org.openstreetmap.osmosis.core.domain.v0_6.Node;
import org.openstreetmap.osmosis.core.domain.v0_6.Tag;
import org.openstreetmap.osmosis.core.domain.v0_6.Way;
import org.openstreetmap.osmosis.core.domain.v0_6.WayNode;

class TileData {

  static final Logger LOGGER =
      Logger.getLogger(TileData.class.getName());

  private Set<TDNode> pois;
  private Set<TDWay> ways;

  TileData() {
    this.pois = new HashSet<TDNode>();
    this.ways = new HashSet<TDWay>();
  }

  void addPOI(TDNode poi) {
    pois.add(poi);
  }

  void addWay(TDWay way) {
    ways.add(way);
  }

  void removeWay(TDWay way) {
    ways.remove(way);
  }

  Map<Byte, List<TDNode>> poisByZoomlevel(byte minValidZoomlevel,
      byte maxValidZoomlevel) {
    HashMap<Byte, List<TDNode>> poisByZoomlevel = new HashMap<Byte, List<TDNode>>();
    for (TDNode poi : pois) {
      byte zoomlevel = poi.getMinimumZoomLevel();
      if (zoomlevel > maxValidZoomlevel)
        continue;
      if (zoomlevel < minValidZoomlevel)
        zoomlevel = minValidZoomlevel;
      List<TDNode> group = poisByZoomlevel.get(zoomlevel);
      if (group == null)
        group = new ArrayList<TDNode>();
      group.add(poi);
      poisByZoomlevel.put(zoomlevel, group);
    }

    return poisByZoomlevel;
  }

  Map<Byte, List<TDWay>> waysByZoomlevel(byte minValidZoomlevel, byte maxValidZoomlevel) {
    HashMap<Byte, List<TDWay>> waysByZoomlevel = new HashMap<Byte, List<TDWay>>();
    for (TDWay way : ways) {
      byte zoomlevel = way.getMinimumZoomLevel();
      if (zoomlevel > maxValidZoomlevel)
        continue;
      if (zoomlevel < minValidZoomlevel)
        zoomlevel = minValidZoomlevel;
      List<TDWay> group = waysByZoomlevel.get(zoomlevel);
      if (group == null)
        group = new ArrayList<TDWay>();
      group.add(way);
      waysByZoomlevel.put(zoomlevel, group);
    }

    return waysByZoomlevel;
  }

  static class TDNode {

    private static final int MAX_ELEVATION = 9000;
    private static final byte ZOOM_HOUSENUMBER = (byte) 17;
    private static final byte ZOOM_NAME = (byte) 16;

    private final long id;
    private final int latitude;
    private final int longitude;

    private final short elevation;
    private final String houseNumber;
    private final byte layer;
    private final String name;
    private short[] tags;

    static TDNode fromNode(Node node) {
      // special tags
      short elevation = 0;
      byte layer = 5;
      String name = null;
      String housenumber = null;

      OSMTag currentTag = null;
      TShortArrayList currentTags = new TShortArrayList();

      // Process Tags
      for (Tag tag : node.getTags()) {
        // test for special tags
        if (tag.getKey().equalsIgnoreCase("ele")) {
          try {
            elevation = (short) Double.parseDouble(tag.getValue());
            if (elevation > MAX_ELEVATION) {
              LOGGER.finer("invalid elevation " + elevation + " for node "
                  + node.getId());
              elevation = 0;
            }

          } catch (NumberFormatException e) {
            // nothing to do here as elevation is initialized with 0
          }
        } else if (tag.getKey().equalsIgnoreCase("addr:housenumber")) {
          housenumber = tag.getValue();
        } else if (tag.getKey().equalsIgnoreCase("name")) {
          name = tag.getValue();
        } else if (tag.getKey().equalsIgnoreCase("layer")) {
          try {
            layer = Byte.parseByte(tag.getValue());
            if (layer >= -5 && layer <= 5)
              layer += 5;
          } catch (NumberFormatException e) {
            // nothing to do here as layer is initialized with 5
          }
        } else if ((currentTag = MapFileWriterTask.TAG_MAPPING.getPoiTag(tag.getKey(),
            tag.getValue())) != null) {
          currentTags.add(currentTag.getId());
        }
      }
      return new TDNode(node.getId(),
          GeoCoordinate.doubleToInt(node.getLatitude()),
          GeoCoordinate.doubleToInt(node.getLongitude()), elevation,
          layer, housenumber, name, currentTags.toArray());
    }

    TDNode(long id, int latitude, int longitude, short elevation, byte layer,
        String houseNumber, String name) {
      this.id = id;
      this.latitude = latitude;
      this.longitude = longitude;
      this.elevation = elevation;
      this.houseNumber = houseNumber;
      this.layer = layer;
      this.name = name;
    }

    TDNode(long id, int latitude, int longitude, short elevation, byte layer,
        String houseNumber, String name, short[] tags) {
      this.id = id;
      this.latitude = latitude;
      this.longitude = longitude;
      this.elevation = elevation;
      this.houseNumber = houseNumber;
      this.layer = layer;
      this.name = name;
      this.tags = tags;
    }

    boolean isPOI() {
      return houseNumber != null || elevation != 0 || name != null || tags.length > 0;
    }

    byte getMinimumZoomLevel() {
      byte min = Byte.MAX_VALUE;
      if (houseNumber != null)
        min = (byte) Math.min(min, ZOOM_HOUSENUMBER);
      if (name != null)
        min = (byte) Math.min(min, ZOOM_NAME);
      if (tags == null)
        return min;
      OSMTag tag;
      for (short tagID : tags) {
        tag = MapFileWriterTask.TAG_MAPPING.getPoiTag(tagID);
        if (tag.isRenderable())
          min = (byte) Math.min(min, tag.getZoomAppear());
      }

      return min;
    }

    short[] getTags() {
      return tags;
    }

    void setTags(short[] tags) {
      this.tags = tags;
    }

    long getId() {
      return id;
    }

    int getLatitude() {
      return latitude;
    }

    int getLongitude() {
      return longitude;
    }

    short getElevation() {
      return elevation;
    }

    String getHouseNumber() {
      return houseNumber;
    }

    byte getLayer() {
      return layer;
    }

    String getName() {
      return name;
    }

    @Override
    public int hashCode() {
      final int prime = 31;
      int result = 1;
      result = prime * result + (int) (id ^ (id >>> 32));
      return result;
    }

    @Override
    public boolean equals(Object obj) {
      if (this == obj)
        return true;
      if (obj == null)
        return false;
      if (getClass() != obj.getClass())
        return false;
      TDNode other = (TDNode) obj;
      if (id != other.id)
        return false;
      return true;
    }

    @Override
    public String toString() {
      return "TDNode [id=" + id + ", latitude=" + latitude + ", longitude=" + longitude
          + ", name=" + name + ", tags=" + tags + "]";
    }

  }

  static class TDWay {
    static final byte LINE = 0x0;
    static final byte SIMPLE_POLYGON = 0x1;
    static final byte MULTI_POLYGON = 0x2;

    private final long id;
    private final byte layer;
    private final String name;
    private final String ref;
    private short[] tags;
    private byte shape;
    private final TDNode[] wayNodes;

    static TDWay fromWay(Way way, EntityResolver<TDNode> er) {
      if (way == null)
        return null;

      // special tags
      byte layer = 5;
      String name = null;
      String ref = null;

      TShortArrayList currentTags = new TShortArrayList();
      OSMTag currentTag = null;

      // Process Tags
      for (Tag tag : way.getTags()) {
        // test for special tags
        if (tag.getKey().equalsIgnoreCase("name")) {
          name = tag.getValue();
        } else if (tag.getKey().equalsIgnoreCase("layer")) {
          try {
            layer = Byte.parseByte(tag.getValue());
            if (layer >= -5 && layer <= 5)
              layer += 5;
          } catch (NumberFormatException e) {
            // nothing to do here as layer is initialized with 5
          }
        } else if (tag.getKey().equalsIgnoreCase("ref")) {
          ref = tag.getValue();
        } else if ((currentTag = MapFileWriterTask.TAG_MAPPING.getWayTag(tag.getKey(),
            tag.getValue())) != null) {
          currentTags.add(currentTag.getId());
        }
      }

      // only ways with at least 2 way nodes are valid ways
      if (way.getWayNodes().size() >= 2) {

        boolean validWay = true;
        // retrieve way nodes from data store
        TDNode[] waynodes = new TDNode[way.getWayNodes().size()];
        int i = 0;
        for (WayNode waynode : way.getWayNodes()) {
          // TODO adjust interface to support a method getWayNodes()
          waynodes[i] = er.getEntity(waynode.getNodeId());
          if (waynodes[i] == null) {
            validWay = false;
            LOGGER.finer("unknown way node: " + waynode.getNodeId()
                + " in way " + way.getId());
          }
          i++;
        }

        // for a valid way all way nodes must be existent in the input data
        if (validWay) {

          // mark the way as polygon if the first and the last way node are the same
          // and if the way has at least 4 way nodes
          byte shape = LINE;
          if (waynodes[0].getId() == waynodes[waynodes.length - 1].getId()) {
            if (waynodes.length >= GeoUtils.MIN_NODES_POLYGON) {
              shape = SIMPLE_POLYGON;
            } else {
              LOGGER.finer("Found closed polygon with fewer than 4 way nodes. Way-id: "
                  + way.getId());
              return null;
            }
          }

          return new TDWay(way.getId(), layer, name,
              ref, currentTags.toArray(), shape, waynodes);
        }
      }

      return null;
    }

    TDWay(long id, byte layer, String name, String ref, TDNode[] wayNodes) {
      this.id = id;
      this.layer = layer;
      this.name = name;
      this.ref = ref;
      this.wayNodes = wayNodes;
    }

    TDWay(long id, byte layer, String name, String ref, short[] tags,
        byte shape, TDNode[] wayNodes) {
      this.id = id;
      this.layer = layer;
      this.name = name;
      this.ref = ref;
      this.tags = tags;
      this.shape = shape;
      this.wayNodes = wayNodes;
    }

    double[] wayNodesAsArray() {
      if (wayNodes == null)
        return null;
      double[] ret = new double[wayNodes.length * 2];
      int i = 0;
      for (TDNode waynode : wayNodes) {
        ret[i++] = GeoCoordinate.intToDouble(waynode.getLongitude());
        ret[i++] = GeoCoordinate.intToDouble(waynode.getLatitude());
      }

      return ret;
    }

    List<GeoCoordinate> wayNodesAsCoordinateList() {
      List<GeoCoordinate> waynodeCoordinates = new ArrayList<GeoCoordinate>();
      for (TDNode waynode : wayNodes) {
        waynodeCoordinates.add(new GeoCoordinate(waynode.getLatitude(),
            waynode.getLongitude()));
      }

      return waynodeCoordinates;
    }

    byte getMinimumZoomLevel() {
      byte min = Byte.MAX_VALUE;
      if (tags == null)
        return min;

      OSMTag tag = null;
      for (short tagID : tags) {
        tag = MapFileWriterTask.TAG_MAPPING.getWayTag(tagID);
        if (tag.isRenderable())
          min = (byte) Math.min(min, tag.getZoomAppear());

      }

      return min;
    }

    long getId() {
      return id;
    }

    byte getLayer() {
      return layer;
    }

    String getName() {
      return name;
    }

    String getRef() {
      return ref;
    }

    short[] getTags() {
      return tags;
    }

    public byte getShape() {
      return shape;
    }

    public void setShape(byte shape) {
      this.shape = shape;
    }

    void setTags(short[] tags) {
      this.tags = tags;
    }

    void addTags(short[] addendum) {
      if (tags == null)
        tags = addendum;
      else {
        TShortSet tags2 = new TShortHashSet();
        tags2.addAll(tags);
        tags2.addAll(addendum);
        tags = tags2.toArray();
      }

    }

    void removeTags(short[] substract) {
      TShortSet tags2 = new TShortHashSet();
      tags2.addAll(tags);
      tags2.removeAll(substract);
      tags = tags2.toArray();
    }

    boolean isPolygon() {
      return shape == SIMPLE_POLYGON || shape == MULTI_POLYGON;
    }

    boolean isCoastline() {
      if (tags == null)
        return false;
      OSMTag tag;
      for (short tagID : tags) {
        tag = MapFileWriterTask.TAG_MAPPING.getWayTag(tagID);
        if (tag.isCoastline())
          return true;
      }

      return false;
    }

    TDNode[] getWayNodes() {
      return wayNodes;
    }

    @Override
    public int hashCode() {
      final int prime = 31;
      int result = 1;
      result = prime * result + (int) (id ^ (id >>> 32));
      return result;
    }

    @Override
    public boolean equals(Object obj) {
      if (this == obj)
        return true;
      if (obj == null)
        return false;
      if (getClass() != obj.getClass())
        return false;
      TDWay other = (TDWay) obj;
      if (id != other.id)
        return false;
      return true;
    }

    @Override
    public String toString() {
      return "TDWay [id=" + id + ", name=" + name + ", tags=" + tags + ", polygon="
          + shape + "]";
    }

  }
}
java2s.com  | Contact Us | Privacy Policy
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.