/*
* Copyright (c) 2005-2010 KOM – Multimedia Communications Lab
*
* This file is part of PeerfactSim.KOM.
*
* PeerfactSim.KOM 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
* any later version.
*
* PeerfactSim.KOM 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 PeerfactSim.KOM. If not, see .
*
*/
package de.tud.kom.p2psim.impl.util.geo.maps.osm;
import java.io.File;
import java.io.FileInputStream;
import java.io.InputStream;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Vector;
import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;
import org.apache.commons.compress.compressors.bzip2.BZip2CompressorInputStream;
import org.xml.sax.Attributes;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.DefaultHandler;
import de.tud.kom.p2psim.api.scenario.ConfigurationException;
import de.tud.kom.p2psim.api.util.geo.maps.Node;
import de.tud.kom.p2psim.api.util.geo.maps.Way;
import de.tud.kom.p2psim.impl.topology.util.PositionVector;
import de.tudarmstadt.maki.simonstrator.api.Monitor;
import de.tudarmstadt.maki.simonstrator.api.Monitor.Level;
public class OSMReader extends DefaultHandler {
private static HashMap loadedMaps = new HashMap();
private OSMMap map;
private STATE state = STATE.INITIAL;
private Vector idList = new Vector();
private String name;
private boolean boundsFound = false;
private boolean firstNode = true;
private HashMap options = new HashMap();
private Long nodeId;
public OSMReader() {
map = new OSMMap();
}
public OSMReader(OSMMap osmMap) {
this.map = osmMap;
}
public OSMMap getMap() {
return map;
}
public static void loadMap(String filename, OSMMap map) {
File osmFile = new File(filename);
if (!osmFile.exists())
throw new ConfigurationException("Couldn't find OSM file: " + filename);
try {
SAXParserFactory parserFactory = SAXParserFactory.newInstance();
SAXParser parser;
parser = parserFactory.newSAXParser();
OSMReader reader = new OSMReader(map);
File mapFile = new File(filename);
InputStream mapIn = new FileInputStream(mapFile);
if (filename.endsWith(".bz2")) {
mapIn = new BZip2CompressorInputStream(mapIn);
}
parser.parse(mapIn, reader);
reader.postProcessing();
} catch (Exception e) {
e.printStackTrace();
}
}
private void postProcessing() {
removeOutOfBoundNodes(map);
}
public void removeOutOfBoundNodes(OSMMap map) {
Iterator iter = map.getWays().iterator();
int size = map.getWays().size();
OSMWay way;
while (iter.hasNext()) {
way = (OSMWay)iter.next();
for (Node node : way.getNodes()) {
if (node == null || !checkBounds(map, node.getPosition())) {
iter.remove();
break;
}
}
}
Monitor.log(OSMReader.class, Level.INFO, "Removed "
+ (size - map.getWays().size()) + " of " + size + " ways.");
}
private boolean checkBounds(OSMMap map, PositionVector pos) {
if (pos.getX() > map.getMaxPosition().getX()) return false;
if (pos.getY() > map.getMaxPosition().getY()) return false;
if (pos.getX() < map.getMinPosition().getX()) return false;
if (pos.getY() < map.getMinPosition().getY()) return false;
return true;
}
private static enum STATE {
INITIAL,
NODES,
WAYS;
}
@Override
public void startElement(String uri, String localName, String qName, Attributes attrs) throws SAXException {
if (state.equals(STATE.WAYS)) {
if ("nd".equals(qName)) {
idList.add(Long.parseLong(attrs.getValue("ref")));
} else if ("tag".equals(qName)) {
if (attrs.getValue("k").equals("name")) {
name = attrs.getValue("v");
}
options.put(attrs.getValue("k"), attrs.getValue("v"));
}
} else if (state.equals(STATE.NODES)) {
if ("tag".equals(qName)) {
options.put(attrs.getValue("k"), attrs.getValue("v"));
}
} else {
if ("node".equals(qName)) {
UTM utmCoord = UTMConversion.latLon2UTM(Double.parseDouble(attrs.getValue("lat")),
Double.parseDouble(attrs.getValue("lon")));
PositionVector nodePosition = utmCoord.getPosition();
if (!boundsFound) {
PositionVector minLonLat = map.getMinPosition();
PositionVector maxLonLat = map.getMaxPosition();
if (firstNode) {
firstNode = false;
minLonLat.replace(nodePosition);
maxLonLat.replace(nodePosition);
} else {
if (nodePosition.getX() < minLonLat.getX()) minLonLat.setEntry(0, nodePosition.getX());
if (nodePosition.getY() < minLonLat.getY()) minLonLat.setEntry(1, nodePosition.getY());
if (nodePosition.getX() > maxLonLat.getX()) maxLonLat.setEntry(0, nodePosition.getX());
if (nodePosition.getY() > maxLonLat.getY()) maxLonLat.setEntry(1, nodePosition.getY());
map.setMinPosition(minLonLat);
map.setMaxPosition(maxLonLat);
}
}
nodeId = Long.parseLong(attrs.getValue("id"));
options = new HashMap();
map.addNode(nodeId, nodePosition);
state = STATE.NODES;
} else if ("way".equals(qName)) {
if (!boundsFound) {
// Assume that all nodes come in front of the way definitions and make
// the bounds final at this point to get a consistent map
boundsFound = true;
}
idList = new Vector();
options = new HashMap();
state = STATE.WAYS;
} else if ("bounds".equals(qName)) {
boundsFound = true;
//
UTM minUtmCoord = UTMConversion.latLon2UTM(Double.parseDouble(attrs.getValue("minlat")),
Double.parseDouble(attrs.getValue("minlon")));
UTM maxUtmCoord = UTMConversion.latLon2UTM(Double.parseDouble(attrs.getValue("maxlat")),
Double.parseDouble(attrs.getValue("maxlon")));
map.setMinPosition(minUtmCoord.getPosition());
map.setMaxPosition(maxUtmCoord.getPosition());
}
}
}
@Override
public void endElement(String uri, String localName, String qName) throws SAXException {
if ("way".equals(qName)) {
state = STATE.INITIAL;
map.addWay(name, idList, options);
} else if ("node".equals(qName)) {
state = STATE.INITIAL;
map.getNode(nodeId).setAttributes(options);
}
}
public static void main(String... args) {
OSMMap map = null;
File osmFile = new File(args[0]);
if (!osmFile.exists())
throw new ConfigurationException("Couldn't find OSM file: " + args[0]);
try {
SAXParserFactory parserFactory = SAXParserFactory.newInstance();
SAXParser parser;
parser = parserFactory.newSAXParser();
OSMReader reader = new OSMReader();
parser.parse(osmFile, reader);
reader.postProcessing();
map = reader.getMap();
System.out.println("Filename: " + args[0]);
System.out.println("maxlat: " + map.getMaxPosition().getY());
System.out.println("minlon: " + map.getMinPosition().getY());
System.out.println("maxlat: " + map.getMaxPosition().getX());
System.out.println("minlon: " + map.getMinPosition().getX());
} catch (Exception e) {
e.printStackTrace();
}
}
}