Paragon Corpoation PostGIS Spatial Database Engine OSGeo.org The Open Source Geospatial Foundation UMN Mapserver Boston Geographic Information Systems       PostGreSQL Object Relational Database Management System
Home   About Boston GIS   Consulting Services  Boston GIS Blog  Postgres OnLine Journal  Planet PostGIS  PostGIS Funding

Purpose of BostonGIS

BostonGIS is a testbed for GIS and Web Mapping solutions utilizing open source, freely available and/or open gis technologies. We will be using mostly Boston, Massachusetts data to provide mapping and spatial database examples.

If you have some thoughts or comments on what you would like to see covered on this site, drop us a line on our Feed Back page.


GIS Tutorials on Opensource and OpenGIS technologies Tutorials
GIS Article comments Article and Tutorial Comments
Boston GIS BLog Rss FeedBoston GIS blog

PDF HTML All BostonGIS tutorials packaged together in an E-Book.


Tutorial and Tip Sites
Desktop GIS
External Data
GIS Events and Groups
GIS SDKs and Frameworks
External Resources
Glossary
GIS Blogs Around Boston
External GIS Blogs
External Papers Articles
GIS Quick Guides and References
OpenStreetMap and OpenLayers Tutorials
Part 3: Using your own custom built OSM tiles in OpenLayers

Printer Friendly

In this third Part of our OpenStreetMap series we will demonstrate how to use the osm tiles we built in Part 2: Building Tiles with PostGIS OpenStreetMap data.

Creating your own Tile Layer Class

  1. This first part is optional: Note that when you built the tiles, as you got deeper and deeper levels, therw were a lot more tiles and even worse, a lot of those damn tiles were empty. I personally hate carrying around thousands of files of nothingness. It takes a long time to upload nothing. So what I do first is delete those nothing tiles which there seem to be more of than real tiles before I upload them to my server. If you are on Windows, the easiest way to do that is with a command line VBscript. Here is a little script to get rid of nothing. Before you do this, set aside one blank tile to use when you get a 404 request. This will only work on Windows. I haven't figured out the complimentary command for Linux yet. Simply save the contents of this code to a file called delete_osm_blank_tiles.vbs and edit the last line to point to your osm maptiles cache. Then run the script at a command line with cscript delete_osm_blank_tiles.vbs.

    Sub RecursiveDeleteBlankOSMImages(ByVal strDirectory)
      Dim objFolder, objSubFolder, objFile
      Dim strExt
      Dim strExtensionsToDelete
      Dim lngSize
      lngSize = 104 ' The threshold in bytes (this is 104bytes - anything less seems to be a blank image)
      strExtensionsToDelete = "png"
      Set objFolder = objFSO.GetFolder(strDirectory)
      For Each objFile in objFolder.Files   
        For Each strExt in Split(Ucase(strExtensionsToDelete),",")
          If Right(Ucase(objFile.Path), Len(strExt)+1) = "." & strExt AND objFile.Size < lngSize Then
              wscript.echo "Deleting:" & objFile.Path
              objFile.Delete
          End If
        Next
      Next 
      For Each objSubFolder in objFolder.SubFolders
        RecursiveDeleteBlankOSMImages objSubFolder.Path
      Next
    End Sub
    
    
    Dim objFSO
    Set objFSO = CreateObject("Scripting.FileSystemObject")
    RecursiveDeleteBlankOSMImages "C:\osm_matiles\" 
    
  2. Copy the tiles to your web server or one of those cloud storage web accessible file distributions like S3.
  3. Next create a new layer class and save it in it's own JS file. Replace http://localhost/osm_matiles, http://localhost/images/404.png with your own server details. NOTE: We have an array of 3 tile urls. For our case, this is pretty useless, but for load balancing purposes and to also get rid of javascripts limitations of calling a server x amount of times in any period, you may want to setup more than one tile server or mask your single tile server with multiple dns names (to fool javscript). So my OpenStreetMapLocal.js file looks something like below and I place it in the same folder as my mapping application:
    OpenLayers.Util.OSMLocal = {};
    
    /**
     * Constant: MISSING_TILE_URL
     * {String} URL of image to display for missing tiles
     */
    OpenLayers.Util.OSMLocal.MISSING_TILE_URL = "http://localhost/images/404.png";
    /**
     * Function: onImageLoadError
     */
    OpenLayers.Util.onImageLoadError = function() {
        this.src = OpenLayers.Util.OSMLocal.MISSING_TILE_URL;
    };
    
    /**
     * Class: OpenLayers.Layer.OSM.LocalMassachusettsMapnik
     *
     * Inherits from:
     *  - <OpenLayers.Layer.OSM>
     */
    OpenLayers.Layer.OSM.LocalMassachusettsMapnik = OpenLayers.Class(OpenLayers.Layer.OSM, {
        /**
         * Constructor: OpenLayers.Layer.OSM.LocalMassachuettsMapnik
         *
         * Parameters:
         * name - {String}
         * options - {Object} Hashtable of extra options to tag onto the layer
         */
        initialize: function(name, options) {
            var url = [
                "http://localhost/osm_matiles/${z}/${x}/${y}.png",
                "http://localhost/osm_matiles/${z}/${x}/${y}.png",
                "http://localhost/osm_matiles/${z}/${x}/${y}.png"
            ];
            options = OpenLayers.Util.extend({
                numZoomLevels: 19,
                buffer: 0,
                transitionEffect: "resize"
            }, options);
            var newArguments = [name, url, options];
            OpenLayers.Layer.OSM.prototype.initialize.apply(this, newArguments);
        },
    
        CLASS_NAME: "OpenLayers.Layer.OSM.LocalMassachusettsMapnik"
    });
    

Using your custom tile layer class

Now you link in this file as you would OpenStreetMap file and use this new class as you would any other OpenStreetMap OpenLayer layer class and you can even create ones with different themes if you want by creating a different set of tiles and theming them differently. That's it folks. Here is a complete version just containing Massachusetts and neighboring State tiles with a complimentary Town boundary layer dished out by our local MassGIS government agency.

<html><title>OpenStreetMap with Local Tile Cache</title>
<script src="http://www.openlayers.org/api/OpenLayers.js"></script>
<script src="js/OpenStreetMapLocal.js"></script>
<script>
    var lat= 42.06651;  //POINT(-71.7169041387889 42.0665181226572)
    var lon=-71.71690;
    var zoom=5;
    var map; //complex object of type OpenLayers.Map
    var ls = new OpenLayers.Control.LayerSwitcher();
    var mgisurls = ["http://giswebservices.massgis.state.ma.us/geoserver/wms"];
    var prjwgs84 = new OpenLayers.Projection("EPSG:4326");

    function init() {
        //var boundsms = new OpenLayers.Bounds(33869, 772032, 335919, 959719) //EPSG:26986
        var boundswm = new OpenLayers.Bounds(-8182919, 5035362.5,-7784059.5, 5304535) //EPSG:900913 Web Mercator (native projection of tiles)
        
        map = new OpenLayers.Map ("map", {
                controls:[ new OpenLayers.Control.Navigation({'mouseWheelOptions': {interval: 100}}),
                new OpenLayers.Control.PanZoomBar(),ls ,
                  new OpenLayers.Control.Attribution(), 
                  new OpenLayers.Control.MousePosition()
               ],
            maxExtent: boundswm,
            maxResolution: 700,
            numZoomLevels: 18,
            units: 'm',
            projection: new OpenLayers.Projection("EPSG:900913"),
            displayProjection: new OpenLayers.Projection("EPSG:4326")
        } );

        var lyrMapnik = new OpenLayers.Layer.OSM.LocalMassachusettsMapnik("OSM Mapnik Massachusetts", {'isBaseLayer': true});   
        var lyrTowns = new OpenLayers.Layer.WMS("Towns",  mgisurls, 
            { 'layers': "massgis:GISDATA.TOWNS_POLYM", 
                'styles': "",
                'transparent': "true", 'FORMAT': "image/png"}, 
                { 'isBaseLayer': false, 'attribution': '<br /><a href="http://www.mass.gov/mgis/">MASSGIS (MA ITD)</a>',
                'visibility': false, 'buffer': 1, 'singleTile':false, 'tileSize': new OpenLayers.Size(240,150) })
        map.addLayers([lyrMapnik, lyrTowns]);
        
        if( ! map.getCenter() ){
            var lonLat = new OpenLayers.LonLat(lon, lat).transform(new OpenLayers.Projection("EPSG:4326"), map.getProjectionObject());
            map.zoomToExtent(boundswm);
            ls.maximizeControl();
        }
    }
</script>
<body>
<div style="width:880; height:550" id="map"></div>
<script type="text/javascript" defer="true">
    init();
</script>
</body>
</html>

To see it in action go to http://www.bostongis.com/demos/OpenLayers/mapnik_localosm.htm





Post Comments About Part 3: Using your own custom built OSM tiles in OpenLayers
Part 2: Building Tiles with PostGIS OpenStreetMap data and Mapnik: Your Own OpenStreetMap more ...
Part 1: Loading OpenStreetMap data into PostGIS: An Almost Idiot's Guide more ...
Using OpenLayers: Part 2 more ...
Using OpenLayers: Part 1 more ... download
PostGIS, pgRouting, and PostgreSQL Tutorials
Part 1: Getting Started With PostGIS: An almost Idiot's Guide more ...
pgRouting: Loading OpenStreetMap with Osm2Po and route querying more ...
Part 1: Getting Started With PostGIS: An almost Idiot's Guide (PostGIS 2.0) more ...
OSCON 2009: Tips and Tricks for Writing PostGIS Spatial Queries more ...
PGCon2009: PostGIS 1.4, PostgreSQL 8.4 Spatial Analysis Queries, Building Geometries, Open Jump more ...
PLR Part 3: PL/R and Geospatial Data Abstraction Library (GDAL) RGDAL more ...
PostGIS Nearest Neighbor: A Generic Solution - Much Faster than Previous Solution more ...
Solving the Nearest Neighbor Problem in PostGIS more ...
PLR Part 2: PL/R and PostGIS more ...
PLR Part 1: Up and Running with PL/R (PLR) in PostgreSQL: An almost Idiot's Guide more ...
Part 3: PostGIS Loading Data from Non-Spatial Sources more ...
Part 2: Introduction to Spatial Queries and SFSQL with PostGIS more ...
Miscellaneous Tutorials/Cheatsheets/Examples
SpatiaLite Tutorials
Boston External Map Examples
SQL Server 2008 Tutorials
UMN Mapserver Tutorials
General Commentary
Boston GIS      Copyright 2024      Paragon Corporation