OSMParser.java
package org.opentrafficsim.road.network.factory.osm.input;
import java.io.IOException;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import org.openstreetmap.osmosis.core.container.v0_6.EntityContainer;
import org.openstreetmap.osmosis.core.domain.v0_6.Entity;
import org.openstreetmap.osmosis.core.domain.v0_6.EntityType;
import org.openstreetmap.osmosis.core.domain.v0_6.Node;
import org.openstreetmap.osmosis.core.domain.v0_6.Relation;
import org.openstreetmap.osmosis.core.domain.v0_6.RelationMember;
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;
import org.openstreetmap.osmosis.core.task.v0_6.Sink;
import org.opentrafficsim.road.network.factory.osm.OSMNetwork;
import org.opentrafficsim.road.network.factory.osm.OSMNode;
import org.opentrafficsim.road.network.factory.osm.OSMRelation;
import org.opentrafficsim.road.network.factory.osm.OSMTag;
import org.opentrafficsim.road.network.factory.osm.OSMWay;
import org.opentrafficsim.road.network.factory.osm.events.ProgressEvent;
import org.opentrafficsim.road.network.factory.osm.events.ProgressListener;
/**
* Build a structure from the elements in an OSM file.
* <p>
* Copyright (c) 2013-2015 Delft University of Technology, PO Box 5, 2600 AA, Delft, the Netherlands. All rights reserved. <br>
* BSD-style license. See <a href="http://opentrafficsim.org/docs/license.html">OpenTrafficSim License</a>.
* <p>
* $LastChangedDate: 2015-07-26 01:01:13 +0200 (Sun, 26 Jul 2015) $, @version $Revision: 1155 $, by $Author: averbraeck $,
* initial version 31 dec. 2014 <br>
* @author <a href="http://www.tbm.tudelft.nl/mzhang">Mingxin Zhang </a>
* @author <a>Moritz Bergmann</a>
*/
public class OSMParser implements Sink, Serializable
{
/** */
private static final long serialVersionUID = 20141231L;
/** The OSMNetwork. */
private OSMNetwork net = new OSMNetwork("tempnet");
/** The wanted Tags. If null, all Tags are wanted. */
private List<Tag> wantedTags;
/** */
private List<String> filterKeys;
/** ProgressListener. */
private ProgressListener progressListener;
/**
* Construct a new OSMParser and set wantedTags and filteredKeys in one call.
* @param wantedTags List<Tab>; the list of wantedTags
* @param filteredKeys List<String>; the list of filtered keys
*/
public OSMParser(final List<OSMTag> wantedTags, final List<String> filteredKeys)
{
setWantedTags(wantedTags);
this.filterKeys = filteredKeys;
}
/** {@inheritDoc} */
@Override
public void initialize(final Map<String, Object> arg0)
{
// Nothing needs to be initialized in this Sink implementation
}
/** {@inheritDoc} */
@Override
public final void process(final EntityContainer entityContainer)
{
Entity entity = entityContainer.getEntity();
if (entity instanceof Node)
{
Node node = (Node) entity;
OSMNode osmNode = new OSMNode(entity.getId(), node.getLongitude(), node.getLatitude());
Iterator<Tag> tagint = entity.getTags().iterator();
while (tagint.hasNext())
{
Tag nodetag = tagint.next();
if (this.filterKeys.contains(nodetag.getKey()) || this.filterKeys.isEmpty())
{
OSMTag tag = new OSMTag(nodetag.getKey(), nodetag.getValue());
osmNode.addTag(tag);
}
}
this.net.addNode(osmNode);
}
else if (entity instanceof Way)
{
boolean wanted = false;
checkTags: for (Tag wayTag : entity.getTags())
{
for (Tag wantedTag : this.wantedTags)
{
if (wayTag.getKey().equals(wantedTag.getKey()) && wayTag.getValue().equals(wantedTag.getValue()))
{
wanted = true;
break checkTags;
}
}
}
if (wanted)
{
Iterator<Tag> tagint = entity.getTags().iterator();
OSMWay osmWay = new OSMWay(entity.getId());
while (tagint.hasNext())
{
Tag waytag = tagint.next();
if (this.filterKeys.contains(waytag.getKey()) || this.filterKeys.isEmpty())
{
OSMTag tag = new OSMTag(waytag.getKey(), waytag.getValue());
osmWay.addTag(tag);
}
}
Iterator<WayNode> wayint1 = ((Way) entity).getWayNodes().iterator();
while (wayint1.hasNext())
{
WayNode waynode1 = wayint1.next();
osmWay.appendNode(waynode1.getNodeId());
}
this.net.addWay(osmWay);
}
}
else if (entity instanceof Relation)
{ // A relation is a Set of Ways and Nodes
boolean wanted = false;
checkTags: for (Tag entityTag : entity.getTags())
{
for (Tag wantedTag : this.wantedTags)
{
if (entityTag.getKey().equals(wantedTag.getKey())
&& entityTag.getValue().equals(wantedTag.getValue()))
{
wanted = true;
break checkTags;
}
}
}
if (wanted)
{
Iterator<Tag> tagIterator = entity.getTags().iterator();
OSMRelation osmRelation = new OSMRelation(entity.getId());
while (tagIterator.hasNext())
{
Tag reltag = tagIterator.next();
if (this.filterKeys.contains(reltag.getKey()) || this.filterKeys.isEmpty())
{
OSMTag tag = new OSMTag(reltag.getKey(), reltag.getValue());
osmRelation.addTag(tag);
}
}
Iterator<RelationMember> relIterator = ((Relation) entity).getMembers().iterator();
while (relIterator.hasNext())
{
RelationMember relMember = relIterator.next();
if (relMember.getMemberType().equals(EntityType.Node))
{
osmRelation.addNode(relMember.getMemberId());
}
if (relMember.getMemberType().equals(EntityType.Way))
{
osmRelation.addWay(relMember.getMemberId());
}
}
this.net.addRelation(osmRelation);
}
}
}
/** {@inheritDoc} */
@Override
public void release()
{
// Nothing needs to be done after the entire network has been parsed
}
/** {@inheritDoc} */
@Override
public final void complete()
{
HashMap<Long, OSMNode> usedNodes = new HashMap<Long, OSMNode>();
double total = this.net.getWays().size() + this.net.getRelations().size();
double counter = 0;
double percentageStep = 20.0d;
double nextPercentage = percentageStep;
this.progressListener.progress(new ProgressEvent(this, "Removing unused nodes"));
for (Long wid : this.net.getWays().keySet())
{
try
{
OSMWay w = this.net.getWay(wid);
for (Long nid : w.getNodes())
{
if (this.net.getNodes().containsKey(nid) && !usedNodes.containsKey(nid))
{
usedNodes.put(nid, this.net.getNode(nid));
}
}
}
catch (IOException e)
{
e.printStackTrace();
}
if (++counter / total * 100 >= nextPercentage)
{
this.progressListener
.progress(new ProgressEvent(this, "Removing unused nodes " + nextPercentage + "%"));
nextPercentage += percentageStep;
}
}
for (OSMRelation r : this.net.getRelations().values())
{
try
{
// OSMRelation r = this.net.getRelation(rid);
for (Long nid : r.getNodes())
{
if (this.net.getNodes().containsKey(nid) && !usedNodes.containsKey(nid))
{
usedNodes.put(nid, this.net.getNode(nid));
}
}
}
catch (IOException e)
{
e.printStackTrace();
}
if (++counter / total * 100 >= nextPercentage)
{
this.progressListener
.progress(new ProgressEvent(this, "Removing unused nodes " + nextPercentage + "%"));
nextPercentage += percentageStep;
}
}
this.net.setNodes(usedNodes);
this.progressListener.progress(new ProgressEvent(this, "Cleanup complete."));
}
/**
* @return the whole Network
*/
public final OSMNetwork getNetwork()
{
return this.net;
}
/**
* Set/replace the list of wanted tags.<br>
* This method makes a deep copy of the supplied list.
* @param tags List<Tag>; the list of wanted tags
*/
public final void setWantedTags(final List<OSMTag> tags)
{
this.wantedTags = new ArrayList<Tag>();
for (OSMTag osmTag : tags)
{
this.wantedTags.add(new Tag(osmTag.getKey(), osmTag.getValue()));
}
}
/**
* Set/replace the filter keys.<br>
* The provided list is <b>not copied</b>; the caller should not modify the list afterwards.
* @param keys List<String> list of filter keys
*/
public final void setFilterKeys(final List<String> keys)
{
this.filterKeys = keys;
}
/**
* @return progressListener.
*/
public final ProgressListener getProgressListener()
{
return this.progressListener;
}
/**
* @param progressListener set progressListener.
*/
public final void setProgressListener(final ProgressListener progressListener)
{
this.progressListener = progressListener;
}
/** {@inheritDoc} */
@Override
public String toString()
{
return "OSMParser [net=" + this.net + ", wantedTags=" + this.wantedTags + ", filterKeys=" + this.filterKeys + "]";
}
}