View Javadoc
1   package nl.tudelft.simulation.dsol.animation.gis.osm;
2   
3   import java.io.IOException;
4   import java.io.InputStream;
5   import java.net.URL;
6   import java.util.List;
7   
8   import org.openstreetmap.osmosis.core.task.v0_6.RunnableSource;
9   import org.openstreetmap.osmosis.xml.common.CompressionMethod;
10  
11  import crosby.binary.osmosis.OsmosisReader;
12  import nl.tudelft.simulation.dsol.animation.gis.DataSourceInterface;
13  import nl.tudelft.simulation.dsol.animation.gis.FeatureInterface;
14  import nl.tudelft.simulation.dsol.animation.gis.transform.CoordinateTransform;
15  
16  /**
17   * OsmFileReader reads one layer from an OpenStreetMap file based on the given specifications. The supported formats are pbf,
18   * osm, osm.gz, and osm.bz2.
19   * <p>
20   * Copyright (c) 2021-2023 Delft University of Technology, Jaffalaan 5, 2628 BX Delft, the Netherlands. All rights reserved. See
21   * for project information <a href="https://simulation.tudelft.nl/dsol/manual/" target="_blank">DSOL Manual</a>. The DSOL
22   * project is distributed under a three-clause BSD-style license, which can be found at
23   * <a href="https://https://simulation.tudelft.nl/dsol/docs/latest/license.html" target="_blank">DSOL License</a>.
24   * </p>
25   * @author <a href="https://www.tudelft.nl/averbraeck">Alexander Verbraeck</a>
26   */
27  public class OsmFileReader implements DataSourceInterface
28  {
29      /** */
30      private static final long serialVersionUID = 20220130L;
31  
32      /** the URL for the osm file to be read. */
33      private URL osmURL = null;
34  
35      /** an optional transformation of the lat/lon (or other) coordinates. */
36      private final CoordinateTransform coordinateTransform;
37  
38      /** the features to read by this OpenStreeetMap reader. */
39      private final List<FeatureInterface> featuresToRead;
40  
41      /**
42       * Constructs a new reader for a layer in an OSM shape file.
43       * @param osmURL URL; URL can have several valid extensions: .pbf, .osm, .osm.gz, and .osm.bz2
44       * @param coordinateTransform CoordinateTransform; the transformation of (x, y) coordinates to (x', y') coordinates.
45       * @param featuresToRead the features to read
46       * @throws IOException throws an IOException if the url is not accessible
47       */
48      public OsmFileReader(final URL osmURL, final CoordinateTransform coordinateTransform,
49              final List<FeatureInterface> featuresToRead) throws IOException
50      {
51          this.osmURL = osmURL;
52          this.coordinateTransform = coordinateTransform;
53          this.featuresToRead = featuresToRead;
54      }
55      
56      /** {@inheritDoc} */
57      @Override
58      public List<FeatureInterface> getFeatures()
59      {
60          return this.featuresToRead;
61      }
62  
63      /** {@inheritDoc} */
64      @Override
65      public void populateShapes() throws IOException
66      {
67          InputStream fis = this.osmURL.openStream();
68          String filename = this.osmURL.toString().toLowerCase();
69  
70          OsmLayerSink sinkImplementation = new OsmLayerSink(this.featuresToRead, this.coordinateTransform);
71          CompressionMethod compression = CompressionMethod.None;
72          boolean pbf = false;
73          RunnableSource reader = null;
74  
75          if (filename.endsWith(".pbf"))
76          {
77              pbf = true;
78          }
79          else if (filename.endsWith(".gz"))
80          {
81              compression = CompressionMethod.GZip;
82          }
83          else if (filename.endsWith(".bz2"))
84          {
85              compression = CompressionMethod.BZip2;
86          }
87  
88          if (pbf)
89          {
90              try
91              {
92                  reader = new OsmosisReader(fis);
93                  System.out.println("osm pbf map to read: " + filename);
94              }
95              catch (Exception exception)
96              {
97                  sinkImplementation.close();
98                  fis.close();
99                  throw new IOException("Error during reading of OSM file " + filename, exception);
100             }
101         }
102         else
103         {
104             reader = new XmlStreamReader(fis, false, compression);
105             System.out.println("osm xml map to read: " + filename);
106         }
107 
108         reader.setSink(sinkImplementation);
109         Thread readerThread = new Thread(reader);
110         readerThread.start();
111 
112         while (readerThread.isAlive())
113         {
114             try
115             {
116                 readerThread.join();
117             }
118             catch (InterruptedException e)
119             {
120                 System.err.println("The map reader thread got a problem!");
121                 throw new IOException(e);
122             }
123         }
124 
125         System.out.println("OSM layer has been read");
126     }
127 
128     /** {@inheritDoc} */
129     @Override
130     public URL getURL()
131     {
132         return this.osmURL;
133     }
134 
135     /** {@inheritDoc} */
136     @Override
137     public boolean isDynamic()
138     {
139         return false; // OSM data is static
140     }
141 
142 }