<div dir="ltr"><div><div>Hi Mike,<br><br></div>I admit that the convenience of just using firebase (up to 1GB data) was a main motivation to look into tiled json elevation format. Json is convenient because it can be easily digested on a web page. <br><br></div>But it would not be very useful if the format would be tied to firebase. So I was glad to see that json is well supported by the nosql databases:<br><div><div><div><div><br><a href="https://en.wikipedia.org/wiki/Document-oriented_database">https://en.wikipedia.org/wiki/Document-oriented_database</a><br><br></div><div>most of which are opensource. I did not try any but it could be pretty straightforward to set up one such as mongodb. I would not be surprised if there are some free cloud offerings as well to try out, sort of similar to firebase but without the  broadcasting.<br><br></div><div>After learning how to produce and digest the 36x36 tiles, I found that they tend to be too small, and require too many connections to firebase to cover a reasonable area. This may not be a problem if you run your own server. Also, the jumps between zoom levels may be too large but I am not sure about that.<br><br></div><div>So I did fall back to the  256x256 tiles used for slippy maps, with the same spherical mercator based power of two hierarchy, this time base64 encoded. It took me while to figure out how to use gdal to generate the tiles but I did. However, 65536 points take up a lot of memory on a web page. GPUs can handle it, even mobile, but javascript is inefficient and the size of the json itself at  and data store is problematic, perhaps only on mobile. I tried some things with typed arrays which helps but in the end I do want to get into fiddling for performance too much.<br><br></div><div>I can put scripts and workflows on github for both the 36x36 tiles and the 256x256 tiles.<br><br></div><div>Andreas<br></div><div><br><br></div><div><br></div><div><br><br></div><div><br></div></div></div></div></div><div class="gmail_extra"><br><div class="gmail_quote">On Mon, Jun 6, 2016 at 12:04 PM, Mike McCann <span dir="ltr"><<a href="mailto:mccann@mbari.org" target="_blank">mccann@mbari.org</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div style="word-wrap:break-word">Hello Andreas,<div><br></div><div>This indexing scheme appears to be a nice design; using base 36 is clever.</div><div> </div><div>I'm currently working with a 5 cm grid of ocean bathymetry, so an 11 cm resolution tiling solution is "close enough" for this use case.</div><div><br></div><div>I tried examining your example at <a href="https://heights-database.firebaseio.com/" target="_blank">https://heights-database.firebaseio.com/</a> but am getting an "error completing the request" message.</div><div><br></div><div>Are there suitable locally-hosted open source json database solutions?</div><div><br></div><div>-Mike</div><div><br><div>
<span style="border-collapse:separate;border-spacing:0px">--<br>Mike McCann<br>Software Engineer<br>Monterey Bay Aquarium Research Institute<br>7700 Sandholdt Road<br>Moss Landing, CA 95039-9644<br>Voice: <a href="tel:831.775.1769" value="+18317751769" target="_blank">831.775.1769</a>  Fax: <a href="tel:831.775.1736" value="+18317751736" target="_blank">831.775.1736</a> <a href="http://www.mbari.org" target="_blank">http://www.mbari.org</a></span>

</div>
<br><div><div>On May 26, 2016, at 11:39 AM, Andreas Plesch <<a href="mailto:andreasplesch@gmail.com" target="_blank">andreasplesch@gmail.com</a>> wrote:</div><br><blockquote type="cite"><div dir="ltr"><div><div><div>I think I settled on a json structure for a tiled elevation grid which came out quite a bit different than originally anticipated.<br><br></div>Since json is text based, I am using base 36 for numbering to compress a bit. So in addition to numerical digits, the letters a-z are also used. JS has builtin functions to convert from and to base 36. The fundamental unit is micro-degrees which corresponds to about 110km/1000000 = 0.11m. Combined, this means a 6 digit coordinate can resolve down to 11 cm.<br><br></div>Tiles are 36 by 36 cells. A tile can be sparse, eg. not all cell values need to be specified. However, in order to make it easy for a tile consumer to fill in gaps, at least one value in a tile needs to (should) be provided.<br><br></div><div>The size of a tile depends on the zoom level. Zoom level 5 tiles are 36 microdegrees long on each side. Zoom level 4 tiles are 36x36 zoom level 5 tiles large, eg. each side is 36x36 = 1296 microdegrees long, eg. about 140m. Zoom level 3 tiles are about 5 km long on each side.<br><br></div><div>Here is a table of tile sizes:<br><br></div><div><font face="monospace,monospace">z | edge | in meters<br></font></div><div><font face="monospace,monospace">5 | 36   | 4<br>4 | 1296 | 143<br>3 | 46 656| 5132<br></font></div><div><font face="monospace,monospace">2 |1 679 616|185km<br></font></div><div><font face="monospace,monospace">1 |60 466 176| 6651km  <br></font></div><div><br></div><div>The size of each cell in a tile is 1/36 of the tile size (or the size the tile of the next higher zoom level).<br></div><div><br></div><div>The json structure is<br><br></div><div><font face="monospace,monospace">/z/lon/lat/cell_lon/cell_lat<br><br></font></div><div><font face="monospace,monospace">z is the zoom factor<br></font></div><div><font face="monospace,monospace">lon/lat is the location of the tile shortened to z digits<br></font></div><div><font face="monospace,monospace">cell_lon/cell_lat is the position of an elevation within the tile<br><br></font></div><div><font face="monospace,monospace"><font face="arial,helvetica,sans-serif">A level 2 tile would be<br>/2/23/2<br><br></font></font></div><div><font face="monospace,monospace"><font face="arial,helvetica,sans-serif">Its location is from 230000,20000 to 23z000,2z000 in microdegrees. This comes out to be<br></font></font></div><div><font face="monospace,monospace"><font face="arial,helvetica,sans-serif">parseInt(230000,36)/1000000 = 125.9712 degrees E, 3.359232 N to<br></font></font></div><div><font face="monospace,monospace"><font face="arial,helvetica,sans-serif">127.60416 E, 4.992192 N<br><br></font></font></div><div><font face="monospace,monospace"><font face="arial,helvetica,sans-serif">A query or lookup like heights[2][32][2] returns all populated cells in the 36x36 tile. The consumer then can easily reconstruct the position of each reported cell.<br><br></font></font></div><div><font face="monospace,monospace"><font face="arial,helvetica,sans-serif">A path like<br></font></font></div><div><font face="monospace,monospace"><font face="arial,helvetica,sans-serif">/2/23/2/8/7 returns a single datum. It looks up the elevation at<br></font></font></div><div><font face="monospace,monospace"><font face="arial,helvetica,sans-serif">238000, 27000 in microdegrees.<br><br></font></font></div><div><font face="monospace,monospace"><font face="arial,helvetica,sans-serif">Reversely, the procedure to extract an elevation at a given location (144.5678, 44.1245) is:<br><br></font></font></div><div><font face="monospace,monospace"><font face="arial,helvetica,sans-serif">1) decide on resolution(zoom level), depends on json data base, say 3 (143m cell resolution).<br></font></font></div><div><font face="monospace,monospace"><font face="arial,helvetica,sans-serif">2) convert to microdegrees<br></font></font></div><div><font face="monospace,monospace"><font face="arial,helvetica,sans-serif">lon =longitude * 1e6<br></font></font></div><div><font face="monospace,monospace"><font face="arial,helvetica,sans-serif">3) truncate to zoomlevel-1 and convert to base 36<br></font></font></div><div><font face="monospace,monospace"><font face="arial,helvetica,sans-serif">lon = Math.round(lon/Math.pow(36,z-1))*Math.pow(36,z-1).toString(36) (2e2l00, q9r00)<br></font></font></div><div><font face="monospace,monospace"><font face="arial,helvetica,sans-serif">3) determine tile to use according to zoom level:<br></font></font></div><div><font face="monospace,monospace"><font face="arial,helvetica,sans-serif">/3/2e2/q9/<br></font></font></div><div><font face="monospace,monospace"><font face="arial,helvetica,sans-serif">4) lookup elevation in tile <br></font></font></div><div><font face="monospace,monospace"><font face="arial,helvetica,sans-serif">/3/2e2/q9/l/r<br></font></font></div><div><font face="monospace,monospace"><font face="arial,helvetica,sans-serif">5) if successful done, if not get whole tile /3/2e2/q9<br></font></font></div><div><font face="monospace,monospace"><font face="arial,helvetica,sans-serif">and traverse for nearest neighbour or inverse distance weighted average<br></font></font></div><div><font face="monospace,monospace"><font face="arial,helvetica,sans-serif">possibly get surrounding tiles as well for more sophisticated interpolation.<br></font></font></div><div><font face="monospace,monospace"><font face="arial,helvetica,sans-serif">The advantage of a tiled grid would be to first get the whole tile to avoid connecting twice.<br></font></font></div><div><font face="monospace,monospace"><font face="arial,helvetica,sans-serif">Or to get the whole tile set by just /3/ <br><br></font></font></div><div><font face="monospace,monospace"><font face="arial,helvetica,sans-serif">It would be nice to attach meta information to tile sets and perhaps single tiles.<br><br></font></font></div><div><font face="monospace,monospace"><font face="arial,helvetica,sans-serif">I uploaded such a tiled elevation json database of California with zoom levels up to 3 (but only 1km resolution, eg. 3 tiles are sparse) to <br></font></font><br><font face="monospace,monospace"><font face="arial,helvetica,sans-serif">
<a href="https://heights-database.firebaseio.com/" target="_blank">https://heights-database.firebaseio.com/</a>
<br></font></font></div><div><font face="monospace,monospace"><font face="arial,helvetica,sans-serif"><br></font></font></div><div><font face="monospace,monospace"><font face="arial,helvetica,sans-serif">with public read access for experimentation.<br><br></font></font></div><div><font face="monospace,monospace"><font face="arial,helvetica,sans-serif">-Andreas<br></font></font></div><div><font face="monospace,monospace"><font face="arial,helvetica,sans-serif"><br><br></font></font></div><div><font face="monospace,monospace"><font face="arial,helvetica,sans-serif"><br></font></font></div><div><font face="monospace,monospace"><font face="arial,helvetica,sans-serif"><br><br><br><br><br></font></font></div><div><font face="monospace,monospace"><font face="arial,helvetica,sans-serif"><br><br></font></font></div><div><font face="monospace,monospace"><font face="arial,helvetica,sans-serif"><br></font></font></div><div><font face="monospace,monospace"><font face="arial,helvetica,sans-serif"><br><br></font></font></div><div><font face="monospace,monospace"><font face="arial,helvetica,sans-serif"><br></font></font></div><div><font face="monospace,monospace"><br><br><br></font></div><div><font face="monospace,monospace"><br></font></div><div><br><br></div><div><br><br><br><br><br><br><br><br><br><br><br><br></div><div><br><br><br><div><br><br><div><br><br><br></div></div></div></div><div class="gmail_extra"><br><div class="gmail_quote">On Wed, May 25, 2016 at 4:33 PM, Andreas Plesch <<a href="mailto:andreasplesch@gmail.com" target="_blank">andreasplesch@gmail.com</a>> wrote:<br><blockquote class="gmail_quote"><div dir="ltr"><div>Hi,<br><br></div>given the json x3d activity and availability of firebase as performant, easy to use, online json database engine, I started to think about a json structure for tiled elevation grid data.<br><div><div><br></div><div>As an example dataset I am using a global 1km (30 arcsecond) resolution dataset, cut down to the continental U.S. or California.<br><br></div><div>The simplest structure is an untiled, flat list like this:<br></div><div>{ "lon1:lat1" : elev1,<br>  "lon2:lat2" : elev2,<br> ... }<br></div><div>I transformed the dataset to this structure, and uploaded the json to firebase. It works as expected, eg. you can query the database but you need to know the exact keys, or array of keys for an area. It is actually pretty fast.<br></div><div><br></div><div>This where tiling comes in. My favorite idea sofar is to use the digits of lon.,lat. as hierarchical keys, with an addtional key "h" for the actual data. For a three by three digit, one degree grid, It would look like this:<br><br></div><div>{"0:0" : {"h": h00_ave,<br></div><div>          "0:0" : { "h": h00_ave,<br></div><div>                    "0:0" : { h: elev },<br>                    "0:1" : { h: elev }, ...<br>                    "9:9" : { h: elev }<br>                  },<br><div>          "0:1" : { "h": h01_ave,<br>                    "0:0" : { h: elev },<br>                    "0:1" : { h: elev }, ...<br>                    "9:9" : { h: elev }<br>                  }, ...<br><div>          "9:9" : { "h": h99_ave,<br>                    "0:0" : { h: elev },<br>                    "0:1" : { h: elev }, ...<br>                    "9:9" : { h: elev }<br>                  }<br>  "0:1" : {"h": h01_ave, //100N does not actually exist <br>          "0:0" : { ... }, ...<br>          "9:9" : { ... }<br>         }, ...<br> "9:9" : { ... }<br>}<br></div><div> <br></div>The elev. data are actual elevation, the h??_ave value are representative (average) elevation for a complete tile.<br><br>A json path to an elevation at 123E longitude and 40N latitude looks like this:<br>/1:0/2:4/3:0/h<br><div>A json path to all elevations in the area between 120 and 129E longitude and 40 and 49N latitude is:<br>/1:0/2:4/<br></div>This path refers to an object:<br>{ "h": 356, //average elevation in this area<br><div>  "0:0" : {"h": 344 }, // ...<br></div><div>  "9:9" : {"h": 377 }<br>}<br><br></div>which has all grid point elevations in this 10x10 degree tile.<br>So 129E,049N has an elevation of 377.<br><br>Hm, there is an issue. A json path<br>/2:0/<br><div>would refer to an area between 200E,000N to 299E,099N and would require loading all of the subtree although we are only interested in the h??_ave values.<br></div><div><font face="arial,helvetica,sans-serif"><br></font></div><div><font face="arial,helvetica,sans-serif">-Andreas<br></font></div><div><font face="arial,helvetica,sans-serif"><br>Thinking out loud: This probably means putting the tile level first in the hierarchy like in slippy maps. The tile level would be the number of significant digits.<br></font></div><div><font face="arial,helvetica,sans-serif">/3/0:0  //average for 000:000 to 099:099<br></font></div><div><font face="arial,helvetica,sans-serif">/2/0:0  //average for 000:000 to 009:009<br></font></div><div><font face="arial,helvetica,sans-serif">/2/1:0  //average for 010:000 to 019:009<br></font></div><div><font face="arial,helvetica,sans-serif">/2/ // all averages in 10x10 cells<br></font></div><div><font face="arial,helvetica,sans-serif">/1/222:89 // data in 222:89<br></font></div><div><font face="arial,helvetica,sans-serif">/1/ // all data in 1x1 cells<br></font></div><div><font face="arial,helvetica,sans-serif">looks better ...<font color="#888888"><br><br><br></font></font></div><font color="#888888"><div><font face="arial,helvetica,sans-serif"><br></font></div><div><br></div><div><br></div><div><br><br></div></font></div><font color="#888888">                                        <br>                            <br></font></div><font color="#888888"><div><br></div><div><br><br></div><div><br><br clear="all"><span class="HOEnZb"><font color="#888888"><br>-- <br><div>Andreas Plesch<br>39 Barbara Rd.<br>Waltham, MA 02453</div>
</font></span></div></font></div></div><span class="HOEnZb"><font color="#888888">
</font></span></blockquote></div><span class="HOEnZb"><font color="#888888"><br><br clear="all"><br>-- <br><div>Andreas Plesch<br>39 Barbara Rd.<br>Waltham, MA 02453</div>
</font></span></div><span class="HOEnZb"><font color="#888888">
_______________________________________________<br>geospatial mailing list<br><a href="mailto:geospatial@web3d.org" target="_blank">geospatial@web3d.org</a><br><a href="http://web3d.org/mailman/listinfo/geospatial_web3d.org" target="_blank">http://web3d.org/mailman/listinfo/geospatial_web3d.org</a><br></font></span></blockquote></div><br></div></div></blockquote></div><br><br clear="all"><br>-- <br><div class="gmail_signature" data-smartmail="gmail_signature">Andreas Plesch<br>39 Barbara Rd.<br>Waltham, MA 02453</div>
</div>