cutting-room-floor / tilestream

A high-performance map tile server powered by MBTiles files
BSD 3-Clause "New" or "Revised" License
745 stars 106 forks source link

Serving Up SQLite Database like MapBox? #118

Closed jlpoolen closed 10 years ago

jlpoolen commented 10 years ago

I successfully installed tilestream and have it running against a SQlite database: John_test2.mbtiles.

The database: John_test2.mbtiles (32 MB) was created using TileMill's Export-mbtiles function. The underlying map consists of two shapefiles: parcels and roads. I set the center at -122.2982,38.2978,13; and I used a boundary which basically encompasses about a third of the City of Napa with the values: -122.3194,38.2874,-122.2701,38.3160. I set the zoom levels 16-19; the export took about 12 minutes on a 24GB (consumed only 6 GBs) Intel i7 (Taskmanager shows 12 processors, 98% CPU utilization on all twelve).

The server: Here's my start command:

themis tilestream # pwd
/usr/local/src/mapbox/tilestream
themis tilestream # ./index.js start --tiles=. --host 192.168.1.25

I can successfully access the map from Firefox with the URL: http://192.168.1.25:8888/map/John_test2 and I can move about within the boundary I specified. It looks great.

The problem: I'm stuck in trying to alter the Mapbox.js examples to point to my own tilestream server and display. I've also been trying to modify a Leafjs example, but with no success. Perhaps I'm missing a basic concepts here, but I thought if I had my SQLite database served up under tilestream, it would be just the same (subject to the limitations of what's in my database) as if I were referencing a map created on Mapbox or CloudMade. Apparently the Mapbox URL contains other items set that I'm failing to address. The sample file I've been trying to modify is from mapbox's examples: auto.html. I've searched for some documentation on how to basically serve up one's own SQLite database (using mapboxes JavaScript, of course) in a Mapbox kind of way and have not been successful.

Here's Mapbox's code (examples/auto.html):

<!DOCTYPE html>
<html>
<head>
    <meta charset='UTF-8'/>
    <link rel="stylesheet" href="../dist/mapbox.css"/>
    <meta name='viewport' content='initial-scale=1.0 maximum-scale=1.0'>
    <!--[if lte IE 8]>
    <link rel="stylesheet" href="../dist/mapbox/mapbox.ie.css"/>
    <![endif]-->
    <link rel="stylesheet" href="embed.css"/>
    <script src="../dist/mapbox.js"></script>
</head>
<body>
<div id='map'></div>
<script type='text/javascript'>
    L.mapbox.map('map', 'examples.map-zr0njcqy');
</script>
</body>
</html>

Can I take my SQLite database and serve it with the appropraite JavaScript so I'm doing the same as MapBox or CloudMade?

springmeyer commented 10 years ago

First, this request is better directed to support.mapbox.com where we provide help with MapBox.js.

But, while we are here... the issue is that L.mapbox.map is designed to work only against tile sets hosted at mapbox.com. For mbtiles you host yourself you'll need to direct your javascript mapping library to the fully tile web address. And example of doing this with MapBox.js is here: http://www.mapbox.com/mapbox.js/example/v1.0.0/external-layers/

jlpoolen commented 10 years ago

Thank you. I had seen, several times, the page you cited, http://www.mapbox.com/mapbox.js/example/v1.0.0/external-layers/, and the critical code line is:

 map.addLayer(L.tileLayer('http://{s}.tile.stamen.com/toner/{z}/{x}/{y}.png'));

The API for "L.tileLayer" is at http://leafletjs.com/reference.html#tilelayer. Moreover, the key issue appears to be what is the correct syntax for the URL, http://leafletjs.com/reference.html#url-template. Since I'm trying to access an SQLite database and harness the power of the JavaScript library mapbox.js, it seems appropriate that this server project, tilestream, have some sort of example showing how to integrate the SQLite database it serves up into something that could be used in conjunction with the mapbox library.

I'll post an inquiry at support.mapbox.com about my failed attempt to modify the external-layers.html to work against my SQLite database being served up through tilestream. In the meantime, can we keep this issue open and I'll report back here when I have succeeded in accomplishing this goal stated at the outset of this issue.

jlpoolen commented 10 years ago

I filed a support request at: http://support.mapbox.com/discussions/mapboxjs/1875-deploying-sqlite-database-via-tilestream

Therein, Tom MacWright of the Mapbox project suggested a work-around of basically clicked over a tile to determine what the correct URL is. It appears the server reformulates the URL, possibly depending upon how many mbtiles are in the directly. I don't think this URL change is documented, so the work-around is to look at the generic instances, e.g. : http://192.168.1.25:8888/map/John_test2 to see what the URL root path is for a sample PNG. In my case, I had two mbtiles in the directory, and the URL for a PNG was, for example: http://themis:8888/v2/John_test2/17/21010/50421.png. Consequently, there are two issues here: 1) one must use the addLayers mechanism to import maps not served by mapbox.com, 2) the URLs are programmatically changed and for now (I could not find any documentation on the matter), the work-around is to access the mbtiles file directly and determine what the URL construct is by right clicking an image and viewing its particular URL.

Here's my HTML that used to successfully render within a mapbox.map object:

<!DOCTYPE html>
<html>
<head>
    <meta charset='UTF-8'/>
    <link rel="stylesheet" href="../dist/mapbox.css"/>
    <!--[if lte IE 8]>
    <link rel="stylesheet" href="../dist/mapbox/mapbox.ie.css"/>
    <![endif]-->
    <link rel="stylesheet" href="embed.css"/>
    <script src="../dist/mapbox.js"></script>
</head>
<body>
<div id='map'></div>
<script type='text/javascript'>
    var map = L.mapbox.map('map');
    //map.addLayer(L.tileLayer('http://{s}.tile.stamen.com/toner/{z}/{x}/{y}.png'));  // original
    //
    //map.addLayer(L.tileLayer('http://192.168.1.25:8888/map/John_test2/{z}/{x}/{y}.png'));   // fails

    // per suggestion
    // http://support.mapbox.com/discussions/mapboxjs/1875-deploying-sqlite-database-via-tilestream
    map.addLayer(L.tileLayer('http://themis:8888/v2/John_test2/{z}/{x}/{y}.png'));

    //map.setView([0, 0], 5);  //original
    map.setView([38.297619, -122.296316 ], 17);
</script>
</body>
</html>

Note: I changed my server host name from an IP to "themis", hence the difference there is a result of my changing the initialization of the tilestream server.