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-2019 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;OSMTag&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 = this.wantedTags.size() == 0;
99              if (!wanted)
100             {
101                 checkTags: for (Tag wayTag : entity.getTags())
102                 {
103                     for (Tag wantedTag : this.wantedTags)
104                     {
105                         if (wayTag.getKey().equals(wantedTag.getKey()) && wayTag.getValue().equals(wantedTag.getValue()))
106                         {
107                             wanted = true;
108                             break checkTags;
109                         }
110                     }
111                 }
112             }
113             if (wanted)
114             {
115                 Iterator<Tag> tagint = entity.getTags().iterator();
116                 OSMWay osmWay = new OSMWay(entity.getId());
117                 while (tagint.hasNext())
118                 {
119                     Tag waytag = tagint.next();
120                     if (this.filterKeys.contains(waytag.getKey()) || this.filterKeys.isEmpty())
121                     {
122                         OSMTag tag = new OSMTag(waytag.getKey(), waytag.getValue());
123                         osmWay.addTag(tag);
124                     }
125                 }
126                 Iterator<WayNode> wayint1 = ((Way) entity).getWayNodes().iterator();
127                 while (wayint1.hasNext())
128                 {
129                     WayNode waynode1 = wayint1.next();
130                     osmWay.appendNode(waynode1.getNodeId());
131                 }
132                 this.net.addWay(osmWay);
133             }
134         }
135         else if (entity instanceof Relation)
136         { // A relation is a Set of Ways and Nodes
137             boolean wanted = false;
138             checkTags: for (Tag entityTag : entity.getTags())
139             {
140                 for (Tag wantedTag : this.wantedTags)
141                 {
142                     if (entityTag.getKey().equals(wantedTag.getKey()) && entityTag.getValue().equals(wantedTag.getValue()))
143                     {
144                         wanted = true;
145                         break checkTags;
146                     }
147                 }
148             }
149             if (wanted)
150             {
151                 Iterator<Tag> tagIterator = entity.getTags().iterator();
152                 OSMRelation osmRelation = new OSMRelation(entity.getId());
153                 while (tagIterator.hasNext())
154                 {
155                     Tag reltag = tagIterator.next();
156                     if (this.filterKeys.contains(reltag.getKey()) || this.filterKeys.isEmpty())
157                     {
158                         OSMTag tag = new OSMTag(reltag.getKey(), reltag.getValue());
159                         osmRelation.addTag(tag);
160                     }
161                 }
162                 Iterator<RelationMember> relIterator = ((Relation) entity).getMembers().iterator();
163                 while (relIterator.hasNext())
164                 {
165                     RelationMember relMember = relIterator.next();
166                     if (relMember.getMemberType().equals(EntityType.Node))
167                     {
168                         osmRelation.addNode(relMember.getMemberId());
169                     }
170                     if (relMember.getMemberType().equals(EntityType.Way))
171                     {
172                         osmRelation.addWay(relMember.getMemberId());
173                     }
174                 }
175                 this.net.addRelation(osmRelation);
176             }
177         }
178     }
179 
180     /** {@inheritDoc} */
181     @Override
182     public void close()
183     {
184         // Nothing needs to be done after the entire network has been parsed
185     }
186 
187     /** {@inheritDoc} */
188     @Override
189     public final void complete()
190     {
191         HashMap<Long, OSMNode> usedNodes = new HashMap<Long, OSMNode>();
192         double total = this.net.getWays().size() + this.net.getRelations().size();
193         double counter = 0;
194         double percentageStep = 20.0d;
195         double nextPercentage = percentageStep;
196         this.progressListener.progress(new ProgressEvent(this, "Removing unused nodes"));
197         for (Long wid : this.net.getWays().keySet())
198         {
199             try
200             {
201                 OSMWay w = this.net.getWay(wid);
202                 for (Long nid : w.getNodes())
203                 {
204                     if (this.net.getNodes().containsKey(nid) && !usedNodes.containsKey(nid))
205                     {
206                         usedNodes.put(nid, this.net.getNode(nid));
207                     }
208                 }
209             }
210             catch (IOException e)
211             {
212                 e.printStackTrace();
213             }
214             if (++counter / total * 100 >= nextPercentage)
215             {
216                 this.progressListener.progress(new ProgressEvent(this, "Removing unused nodes " + nextPercentage + "%"));
217                 nextPercentage += percentageStep;
218             }
219         }
220         for (OSMRelation r : this.net.getRelations().values())
221         {
222             try
223             {
224                 // OSMRelation r = this.net.getRelation(rid);
225                 for (Long nid : r.getNodes())
226                 {
227                     if (this.net.getNodes().containsKey(nid) && !usedNodes.containsKey(nid))
228                     {
229                         usedNodes.put(nid, this.net.getNode(nid));
230                     }
231                 }
232             }
233             catch (IOException e)
234             {
235                 e.printStackTrace();
236             }
237             if (++counter / total * 100 >= nextPercentage)
238             {
239                 this.progressListener.progress(new ProgressEvent(this, "Removing unused nodes " + nextPercentage + "%"));
240                 nextPercentage += percentageStep;
241             }
242         }
243         this.net.setNodes(usedNodes);
244         this.progressListener.progress(new ProgressEvent(this, "Cleanup complete."));
245     }
246 
247     /**
248      * @return the whole Network
249      */
250     public final OSMNetwork getNetwork()
251     {
252         return this.net;
253     }
254 
255     /**
256      * Set/replace the list of wanted tags.<br>
257      * This method makes a deep copy of the supplied list.
258      * @param tags List&lt;OSMTag&gt;; the list of wanted tags
259      */
260     public final void setWantedTags(final List<OSMTag> tags)
261     {
262         this.wantedTags = new ArrayList<Tag>();
263         for (OSMTag osmTag : tags)
264         {
265             this.wantedTags.add(new Tag(osmTag.getKey(), osmTag.getValue()));
266         }
267     }
268 
269     /**
270      * Set/replace the filter keys.<br>
271      * The provided list is <b>not copied</b>; the caller should not modify the list afterwards.
272      * @param keys List&lt;String&gt;; List&lt;String&gt; list of filter keys
273      */
274     public final void setFilterKeys(final List<String> keys)
275     {
276         this.filterKeys = keys;
277     }
278 
279     /**
280      * @return progressListener.
281      */
282     public final ProgressListener getProgressListener()
283     {
284         return this.progressListener;
285     }
286 
287     /**
288      * @param progressListener ProgressListener; set progressListener.
289      */
290     public final void setProgressListener(final ProgressListener progressListener)
291     {
292         this.progressListener = progressListener;
293     }
294 
295     /** {@inheritDoc} */
296     @Override
297     public String toString()
298     {
299         return "OSMParser [net=" + this.net + ", wantedTags=" + this.wantedTags + ", filterKeys=" + this.filterKeys + "]";
300     }
301 }