LRS From Base Map: A Feasibility Study

Intro

IRI Image

The following images of an IRI layer are rendered completely from a list of objects containing the fields RouteID, BMP, and EMP we hand that to our map and it renders those objects representing the LRS to the map automatically no rest service needed!

Video Demo



Pretty exciting stuff if you ask me!

What is a base map?

A base map is the default map underneath everything that is rendered when you pan around. A base map usually made up of raster or image tiles. A tile is a x,y,z coordinate with z being the zoom of your map. So as you zoom in the map client will make the network requests for the handful of tiles or so you need to render whats on your screen at any given time.

What is a vector tile?

A vector tile is a vector representation of GIS data that is sent over the wire with a similar API as to the raster tiles. (same schema) However, instead of rendering an image, we parse that vector tile data into a structure graphics libraries desire, like WebGL. Who can then use it to render data extremely quickly. Many advantages come from using vector-tiles rather than raster but one of the main advantages I find is you can act with the data making up the basemap super easy.

If you recall our basemap is already built on your DOT's specific data and rendered that way. So your DOT's data already exists in the underlying base map: What would it take to be able to do LRS operations purely from the client side, using the base map data? This would make interfacing with the LRS inherit to the way we design.

How Much Error Will Our Vector Tiles Have?

Vector tiles our an estimation of GIS data, so typicallly a tile would only have 4096 pixels in each dimension. However, the nice thing about vector-tiles is you have the benefit of vector data eventually becoming less and less tangible the more zoomed in you are.

For example a zoom 14 tiles height or width is about 1.49 miles, but when you divide that by the 4096 pixels that exist 1.49 mi /4096 * 5280.0 ft /mi = 1.9 feet/pixel resolution! If we render any more tiles passed the zoom 14 our resolution can't go up.

For this reason vector-tiles really only need the max zoom of 14 saving significantly on how many tiles are needed to make a basemap

Process - Generate Output of Errors

LRS Operations

The three basic LRS operations we typically care about are listed below but in reality almost all of the what we care about can be derived from RouteID/Measure -> Point. We also have a clear method for getting error between the two send a measure (milepoint) in with the two different render methods and take the distance inbetween.

  • Point -> RouteID/Measure
  • RouteID/Measure -> Point
  • RouteID/BMP/EMP -> Line

To figure out how much error would exist in our vector-tile data based off of normal data I set up a little go program to do the following:

  1. read through each tile at a zoom
  2. Read in all the vector tile data for that tile
  3. Filter for only the road layer
  4. From each feature in the vector tile feature geojson road layer
  • Created a location object
  • This location object could generate a point from a measure if given a particular milepoint
    • Method 1 - On the vector tile data
    • Method 2 - On geobuf data (ground truth)
  • The location object could also generate a random point on the feature between its BMP and EMP then get the coordinate associated with both methods, finally returning the distance between the two in feet!
  1. Assembled each location object into a list of locations and wrapped it in a random point method that basically just randomly picked one from the list of locations than called it's RandomPoint() function
  2. Did 10,000 random point operations per tile and captured the following
  • average error in feet between the two
  • the number of errors thrown rendering both the geobuf and the vector-tile feature

Results

The results are listed below of the analysis ran are listed below and are pretty remarkable!

Zoom Number Tiles Average Accuracy (ft) % error buf % error vt
3 2 1104 0.02 0
4 1 625 0.01 0
5 2 350 0.01 0
6 2 200 0.03 0
7 5 114 0.05 0
8 10 64 0.08 0.01
9 30 34 0.06 0.01
10 97 18 0.06 0.01
11 331 10 0.07 0.02
12 1199 7 0.06 0.03
13 4503 4 0.06 0.03
14 16439 4 0.04 0.01

So tile data is typically messy but if structured correctly we can get remarkable coverage of an LRS system from base map vector-tiles. **Moreover it completely negates to rely on an API for a lot of typical LRS operations!**

How Were The Tiles Created?

Tiling is a messy operation that I have years of experience optimizing. One of the hardest things to pipe into a tile cutting operation is a geometry based properties along its geometry. How you carry it through the clipping operation properly is pivotal for if something like this will ever work. I ended up writing a custom branch of one my golang libraries to do this properly. Much work was put in just to get the backend engine to make the tiles correctly.

Size Implications

Carrying another large field through vector-tiles probably increases the size dramatically you'd guess right? While this is somewhat true I found it to be pretty manageable. A base map tile set for WV went from 117MB to 150MB which isn't terrible at all and well worth the trade off.

Get in touch

If you have any questions about NexusIO email me at bennett@nexuslrs.com or use the contact page.


Previous
Previous

Clipping the LRS About Polygon Data

Next
Next

NexusLRS iOS Beta