View Javadoc
1   package org.opentrafficsim.road.network.factory.osm.input;
2   
3   import java.io.IOException;
4   import java.io.Serializable;
5   import java.util.ArrayList;
6   import java.util.HashMap;
7   import java.util.Iterator;
8   import java.util.List;
9   import java.util.Map;
10  
11  import org.openstreetmap.osmosis.core.container.v0_6.EntityContainer;
12  import org.openstreetmap.osmosis.core.domain.v0_6.Entity;
13  import org.openstreetmap.osmosis.core.domain.v0_6.EntityType;
14  import org.openstreetmap.osmosis.core.domain.v0_6.Node;
15  import org.openstreetmap.osmosis.core.domain.v0_6.Relation;
16  import org.openstreetmap.osmosis.core.domain.v0_6.RelationMember;
17  import org.openstreetmap.osmosis.core.domain.v0_6.Tag;
18  import org.openstreetmap.osmosis.core.domain.v0_6.Way;
19  import org.openstreetmap.osmosis.core.domain.v0_6.WayNode;
20  import org.openstreetmap.osmosis.core.task.v0_6.Sink;
21  import org.opentrafficsim.road.network.factory.osm.OSMNetwork;
22  import org.opentrafficsim.road.network.factory.osm.OSMNode;
23  import org.opentrafficsim.road.network.factory.osm.OSMRelation;
24  import org.opentrafficsim.road.network.factory.osm.OSMTag;
25  import org.opentrafficsim.road.network.factory.osm.OSMWay;
26  import org.opentrafficsim.road.network.factory.osm.events.ProgressEvent;
27  import org.opentrafficsim.road.network.factory.osm.events.ProgressListener;
28  
29  /**
30   * Build a structure from the elements in an OSM file.
31   * <p>
32   * Copyright (c) 2013-2018 Delft University of Technology, PO Box 5, 2600 AA, Delft, the Netherlands. All rights reserved. <br>
33   * BSD-style license. See <a href="http://opentrafficsim.org/docs/license.html">OpenTrafficSim License</a>.
34   * <p>
35   * $LastChangedDate: 2015-07-26 01:01:13 +0200 (Sun, 26 Jul 2015) $, @version $Revision: 1155 $, by $Author: averbraeck $,
36   * initial version 31 dec. 2014 <br>
37   * @author <a href="http://www.tbm.tudelft.nl/mzhang">Mingxin Zhang </a>
38   * @author <a>Moritz Bergmann</a>
39   */
40  public class OSMParser implements Sink, Serializable
41  {
42      /** */
43      private static final long serialVersionUID = 20141231L;
44  
45      /** The OSMNetwork. */
46      private OSMNetwork net = new OSMNetwork("tempnet");
47  
48      /** The wanted Tags. If null, all Tags are wanted. */
49      private List<Tag> wantedTags;
50  
51      /** */
52      private List<String> filterKeys;
53  
54      /** ProgressListener. */
55      private ProgressListener progressListener;
56  
57      /**
58       * Construct a new OSMParser and set wantedTags and filteredKeys in one call.
59       * @param wantedTags List&lt;Tab&gt;; the list of wantedTags
60       * @param filteredKeys List&lt;String&gt;; the list of filtered keys
61       */
62      public OSMParser(final List<OSMTag> wantedTags, final List<String> filteredKeys)
63      {
64          setWantedTags(wantedTags);
65          this.filterKeys = filteredKeys;
66      }
67  
68      /** {@inheritDoc} */
69      @Override
70      public void initialize(final Map<String, Object> arg0)
71      {
72          // Nothing needs to be initialized in this Sink implementation
73      }
74  
75      /** {@inheritDoc} */
76      @Override
77      public final void process(final EntityContainer entityContainer)
78      {
79          Entity entity = entityContainer.getEntity();
80          if (entity instanceof Node)
81          {
82              Node node = (Node) entity;
83              OSMNode osmNode = new OSMNode(entity.getId(), node.getLongitude(), node.getLatitude());
84              Iterator<Tag> tagint = entity.getTags().iterator();
85              while (tagint.hasNext())
86              {
87                  Tag nodetag = tagint.next();
88                  if (this.filterKeys.contains(nodetag.getKey()) || this.filterKeys.isEmpty())
89                  {
90                      OSMTag tag = new OSMTag(nodetag.getKey(), nodetag.getValue());
91                      osmNode.addTag(tag);
92                  }
93              }
94              this.net.addNode(osmNode);
95          }
96          else if (entity instanceof Way)
97          {
98              boolean wanted = false;
99              checkTags: for (Tag wayTag : entity.getTags())
100             {
101                 for (Tag wantedTag : this.wantedTags)
102                 {
103                     if (wayTag.getKey().equals(wantedTag.getKey()) && wayTag.getValue().equals(wantedTag.getValue()))
104                     {
105                         wanted = true;
106                         break checkTags;
107                     }
108                 }
109             }
110             if (wanted)
111             {
112                 Iterator<Tag> tagint = entity.getTags().iterator();
113                 OSMWay osmWay = new OSMWay(entity.getId());
114                 while (tagint.hasNext())
115                 {
116                     Tag waytag = tagint.next();
117                     if (this.filterKeys.contains(waytag.getKey()) || this.filterKeys.isEmpty())
118                     {
119                         OSMTag tag = new OSMTag(waytag.getKey(), waytag.getValue());
120                         osmWay.addTag(tag);
121                     }
122                 }
123                 Iterator<WayNode> wayint1 = ((Way) entity).getWayNodes().iterator();
124                 while (wayint1.hasNext())
125                 {
126                     WayNode waynode1 = wayint1.next();
127                     osmWay.appendNode(waynode1.getNodeId());
128                 }
129                 this.net.addWay(osmWay);
130             }
131         }
132         else if (entity instanceof Relation)
133         { // A relation is a Set of Ways and Nodes
134             boolean wanted = false;
135             checkTags: for (Tag entityTag : entity.getTags())
136             {
137                 for (Tag wantedTag : this.wantedTags)
138                 {
139                     if (entityTag.getKey().equals(wantedTag.getKey()) && entityTag.getValue().equals(wantedTag.getValue()))
140                     {
141                         wanted = true;
142                         break checkTags;
143                     }
144                 }
145             }
146             if (wanted)
147             {
148                 Iterator<Tag> tagIterator = entity.getTags().iterator();
149                 OSMRelation osmRelation = new OSMRelation(entity.getId());
150                 while (tagIterator.hasNext())
151                 {
152                     Tag reltag = tagIterator.next();
153                     if (this.filterKeys.contains(reltag.getKey()) || this.filterKeys.isEmpty())
154                     {
155                         OSMTag tag = new OSMTag(reltag.getKey(), reltag.getValue());
156                         osmRelation.addTag(tag);
157                     }
158                 }
159                 Iterator<RelationMember> relIterator = ((Relation) entity).getMembers().iterator();
160                 while (relIterator.hasNext())
161                 {
162                     RelationMember relMember = relIterator.next();
163                     if (relMember.getMemberType().equals(EntityType.Node))
164                     {
165                         osmRelation.addNode(relMember.getMemberId());
166                     }
167                     if (relMember.getMemberType().equals(EntityType.Way))
168                     {
169                         osmRelation.addWay(relMember.getMemberId());
170                     }
171                 }
172                 this.net.addRelation(osmRelation);
173             }
174         }
175     }
176 
177     /** {@inheritDoc} */
178     @Override
179     public void close()
180     {
181         // Nothing needs to be done after the entire network has been parsed
182     }
183 
184     /** {@inheritDoc} */
185     @Override
186     public final void complete()
187     {
188         HashMap<Long, OSMNode> usedNodes = new HashMap<Long, OSMNode>();
189         double total = this.net.getWays().size() + this.net.getRelations().size();
190         double counter = 0;
191         double percentageStep = 20.0d;
192         double nextPercentage = percentageStep;
193         this.progressListener.progress(new ProgressEvent(this, "Removing unused nodes"));
194         for (Long wid : this.net.getWays().keySet())
195         {
196             try
197             {
198                 OSMWay w = this.net.getWay(wid);
199                 for (Long nid : w.getNodes())
200                 {
201                     if (this.net.getNodes().containsKey(nid) && !usedNodes.containsKey(nid))
202                     {
203                         usedNodes.put(nid, this.net.getNode(nid));
204                     }
205                 }
206             }
207             catch (IOException e)
208             {
209                 e.printStackTrace();
210             }
211             if (++counter / total * 100 >= nextPercentage)
212             {
213                 this.progressListener.progress(new ProgressEvent(this, "Removing unused nodes " + nextPercentage + "%"));
214                 nextPercentage += percentageStep;
215             }
216         }
217         for (OSMRelation r : this.net.getRelations().values())
218         {
219             try
220             {
221                 // OSMRelation r = this.net.getRelation(rid);
222                 for (Long nid : r.getNodes())
223                 {
224                     if (this.net.getNodes().containsKey(nid) && !usedNodes.containsKey(nid))
225                     {
226                         usedNodes.put(nid, this.net.getNode(nid));
227                     }
228                 }
229             }
230             catch (IOException e)
231             {
232                 e.printStackTrace();
233             }
234             if (++counter / total * 100 >= nextPercentage)
235             {
236                 this.progressListener.progress(new ProgressEvent(this, "Removing unused nodes " + nextPercentage + "%"));
237                 nextPercentage += percentageStep;
238             }
239         }
240         this.net.setNodes(usedNodes);
241         this.progressListener.progress(new ProgressEvent(this, "Cleanup complete."));
242     }
243 
244     /**
245      * @return the whole Network
246      */
247     public final OSMNetwork getNetwork()
248     {
249         return this.net;
250     }
251 
252     /**
253      * Set/replace the list of wanted tags.<br>
254      * This method makes a deep copy of the supplied list.
255      * @param tags List&lt;Tag&gt;; the list of wanted tags
256      */
257     public final void setWantedTags(final List<OSMTag> tags)
258     {
259         this.wantedTags = new ArrayList<Tag>();
260         for (OSMTag osmTag : tags)
261         {
262             this.wantedTags.add(new Tag(osmTag.getKey(), osmTag.getValue()));
263         }
264     }
265 
266     /**
267      * Set/replace the filter keys.<br>
268      * The provided list is <b>not copied</b>; the caller should not modify the list afterwards.
269      * @param keys List&lt;String&gt; list of filter keys
270      */
271     public final void setFilterKeys(final List<String> keys)
272     {
273         this.filterKeys = keys;
274     }
275 
276     /**
277      * @return progressListener.
278      */
279     public final ProgressListener getProgressListener()
280     {
281         return this.progressListener;
282     }
283 
284     /**
285      * @param progressListener set progressListener.
286      */
287     public final void setProgressListener(final ProgressListener progressListener)
288     {
289         this.progressListener = progressListener;
290     }
291 
292     /** {@inheritDoc} */
293     @Override
294     public String toString()
295     {
296         return "OSMParser [net=" + this.net + ", wantedTags=" + this.wantedTags + ", filterKeys=" + this.filterKeys + "]";
297     }
298 }