Serving Tiles in EPSG:4326

3,397 views
Skip to first unread message

pwi...@ix.netcom.com

unread,
Jan 22, 2013, 7:55:06 PM1/22/13
to map...@googlegroups.com

I need to serve tiles for maps in Platte Carre CRS. The data sources are in EPSG:4326, and the mapfile specifies this CRS properly.

But the maps have extra rows of tiles were I don't need them, and missing rows of tiles where I do. (See attached samples.)  I can see why this is happening, but not how to get around this.

I'm slowly coming to the realization that no matter what I specify, the OpenLayers / mod_tile / Mapnik stack expects the x and y coordinates of tiles in Google Spherical Mercator (900913) projection, and that while specifying EPSG:4326 in OpenLayers changes aspect ratio of the map, the tile server still expects the "extra" rows of tiles that 900913 uses.

renderd finds the crs I specify in the map file, but neither generate_tiles.py nor render_list will store tiles in the rows and columns that I'd need for a map that was half as tall as its width.

Leaflet also allows me to use EPSG:4326, but expects more rows than a Platte Carre map should have.

I'm weighing options, now.

A WMS layer works properly, at least in Leaflet. But when I went to compile mod_mapnik_wms, it complained about the version of Mapnik I'm using (2.2.1-pre).  Something about:

  wms.cpp:63:44: error: 'class mapnik::Map' has no member named 'setAspectFixMode'
  wms.cpp: At global scope:
  wms.cpp:361:36: error: variable or field 'reduce_8' declared void
  wms.cpp:361:16: error: 'ImageData32' is not a member of 'mapnik'
  wms.cpp:361:47: error: 'ImageData8' is not a member of 'mapnik'
  wms.cpp:361:67: error: 'out' was not declared in this scope


Before I consider making changes to generate_tiles.py or leaflet-src.js, am I missing something obvious?

  • Would 256px x 128px tiles avoid  a complete x, y tile index overhaul?
  • Is there a solution that already works with EPSG:4326 with renderd, mod_tile, javascript, et al?

I was about to try Tirex, but there appears to be a patch needed for it to work with the current release of Mapnik. I'd apply that patch in a second, if I had any sense that it Tirex could count rows in the 2:1 aspect ratio of EPSG:4326.

TileMill and friends look elegant, but the documentation is clear that any self-respecting map should be square, to match its pixels.

It hasn't escaped me that trying to avoid Spherical Mercator is like trying to avoid oxygen, but Platte Carre was specified in the requirements that I accepted.

Has anyone succeeded in serving tiles from a local host in EPSG:4326?


Thoughts?




Dane Springmeyer

unread,
Jan 22, 2013, 8:35:57 PM1/22/13
to map...@googlegroups.com
For supporting tiles in EPSG:4326 take a look at mapproxy. It has a notion of "grids" which provide the necessary info to build up a tiling scheme that should work with any projection that is generally "square", EPSG:4326 is one of them along with UTM or Mercator. It apears MapProxy calls the EPSG:4326 grid 'GLOBAL_GEODETIC'.

I've not personally used MapProxy for this but a quick peek at the docs suggests you should be well taken care of. There is a Mapnik backend that should allow rendering directly by using the Mapnik python bindings (and skipping the overhead of a WMS endpoint).

Dane

pwi...@ix.netcom.com

unread,
Jan 22, 2013, 8:42:27 PM1/22/13
to map...@googlegroups.com
Thank you, Dane!

I'll report on my progress, as soon as I get MapProxy up and running.

pwi...@ix.netcom.com

unread,
Jan 23, 2013, 4:51:06 PM1/23/13
to map...@googlegroups.com

Huge Success / Quick Win

MapProxy does what I need it to do, in areas where other solutions won't, and seems to harbour significant Mapnik-love.

There are a couple of snags that people are likely to run into, but nothing insurmountable.

First, MapProxy documentation suggests that it be installed in a Python virtual environment. This may be prudent, but unless you also install virtualenvwrapper and use "toggleglobalsitepackages", you probably won't be able to import mapnik (assuming Mapnik was already installed before instantiating your virtual environment). I chose to start-over and install MapProxy without a virtual environment. People on shared servers may not have this luxury, so look at virtualenvwrapper.

Second, you must assign a value of true or false to a configuration variable: "use_mapnik2". It appears to work well with 2.2.1 given use_mapnik2: true.

From that point forward, it all moves very quickly.

When you add a mapnik source, cache, and any layer(s) to the mapproxy.yaml file, a link appears in the demo HTML / Javascript that gets created for you.

MapProxy's tile indexing works without having to fiddle with arrays of resolution at each zoom level, adopting odd tile sizes, or hacking the Javascript library, regardless of whether your map is in Mercator or Global Geodetic projections.

(The reason tile indexing changes with projection is that the aspect ratio of the map can change. At zoom level 0, a map in Mercator / 900913 is made up of 4 tiles - two rows of tiles in two columns; At the same zoom level, a map in Platte Carre / Global Geodetic / EPSG:4326 is made of two tiles in one row. This basic difference in geometry is reflected in every zoom level.)

Install MapProxy, then try this:

Create a generic configuration, to validate the platform, before making any adjustments:

mapproxy-util create -t base-config mymapproxy

Fire-up the server:

cd [/path/leading/to/]mymapproxy
mapproxy-util serve-develop mapproxy.yaml

Point a browser at http://localhost:8080 and navigate to the demo maps.

Edit mapproxy.yaml to add your Mapnik configuration (see my example, below), then refresh the browser.

Caveats:

I haven't bothered to determine whether you'll need to restart the MapProxy server to see changes to the yaml file, but that'll become apparent soon enough.

All this assumes you've already got the Mapnik rendering daemon (renderd) running.

Sample Config:

Here are some tested configuration values, taken from my mapproxy.yaml file (changes in red):

layers:
  - name: osm
    title: Omniscale OSM WMS - osm.omniscale.net
    sources: [osm_cache]
  - name: world
    title: local Mapnik boundary data
    sources: [mapnik_cache]

  # - name: osm_full_example
  #   title: Omniscale OSM WMS - osm.omniscale.net
  #   sources: [osm_cache_full_example]

caches:
  osm_cache:
    grids: [GLOBAL_MERCATOR, global_geodetic_sqrt2]
    sources: [osm_wms]
  mapnik_cache:
    grids: [global_geodetic_sqrt2]
    sources: [xyz_mapnik]
    format: image/png


  # osm_cache_full_example:
  #   meta_buffer: 20
  #   meta_size: [5, 5]
  #   format: image/png
  #   request_format: image/tiff
  #   link_single_color_images: true
  #   use_direct_from_level: 5
  #   grids: [grid_full_example]
  #   sources: [osm_wms, overlay_full_example]

sources:
  osm_wms:
    type: wms
    req:
      url: http://osm.omniscale.net/proxy/service?
      layers: osm
  xyz_mapnik:
    type: mapnik
    mapfile: /home/paul/src/mapnik-stylesheets/osm.xml
    layers: world
    use_mapnik2: true


For even more control, (although I found it unnecessary / redundant), you can define your own grid:

grids:
  global_geodetic_sqrt2:
    base: GLOBAL_GEODETIC
    res_factor: 'sqrt2'

  platte_carre:
    srs: 'EPSG:4326'
    tile_size: [512, 512]
    bbox: [-180, -90, 180, 90]
    bbox_srs: 'EPSG:4326'
    res: [0.000171661376953, 0.000343322753906, 0.000686645507812, 0.00137329101562, 0.00274658203125, 0.0054931640625, 0.010986328125, 0.02197265625, 0.0439453125, 0.087890625, 0.17578125, 0.3515625, 0.703125]

  # grid_full_example:
  #   tile_size: [512, 512]
  #   srs: 'EPSG:900913'
  #   bbox: [5, 45, 15, 55]
  #   bbox_srs: 'EPSG:4326'
  #   min_res: 2000 #m/px
  #   max_res: 50 #m/px
  #   align_resolutions_with: GLOBAL_MERCATOR
  # another_grid_full_example:
  #   srs: 'EPSG:900913'
  #   bbox: [5, 45, 15, 55]
  #   bbox_srs: 'EPSG:4326'
  #   res_factor: 1.5
  #   num_levels: 25


Summary:

TileMill and friends deliver beautiful Mercator maps from all the usual sources. That's great, but I'm constrained from using Mercator projection.

Leaflet presents EPSG:4326 maps from WMS sources, cleanly and elegantly, and will do the same with mod_tile as soon as _getWrapTileNum() is refactored. Mapnik 1.7 (or thereabouts) can be set up as a WMS service for Leaflet to work with, but as of January 2013, mod_mapnik_wms appears to need a little nip and tuck, before it'll get along with Mapnik 2.2.1 and beyond.

But MapProxy already does everything necessary to break out of the Google Map box and serve tiles in global geodetic projection, using the Mapnik rendering tool chain.

The documentation hints at a wide range of adjustments that can be made to the configuration, addressing everything from fine control of the resolution at which vector data sources are rendered, to merging separate sources into a single layer.

I'm grateful to have been introduced to MapProxy. It might be prudent to draw-up a prenuptial agreement, but at first blush it looks like we're going to be very happy together.

 

On Tuesday, January 22, 2013 5:35:57 PM UTC-8, Dane Springmeyer wrote:

Dane Springmeyer

unread,
Jan 23, 2013, 5:22:36 PM1/23/13
to map...@googlegroups.com
Nice writeup!

Couple quick thoughts:

 - mod_tile's `renderd` should not need to running or involved at all, mapproxy should be hitting mapnik directly, unless you are having MapProxy reproject the tiles (which I did not see mentioned but I think is feasible with MapProxy)
 - Not using virtual env makes sense and I think the right call. Mapnik python bindings being normally installed globally makes using virtual env a hassle. This is what https://github.com/mapnik/mapnik/pull/1455 is somewhat about
 - Lame that mapproxy requires `use_mapnik2`, it really should be able to handle both versions seamlessly now that `import mapnik` is used no matter version
 - Yes, mod_mapnik_wms has not been updated in a while. If WMS + > Mapnik 2.x is ever needed (which hopefully it will not since tiles are better) you can also use either OGCServer[1] or landspeed.js[2] with Mapnik 2 and above.

Dane

pwi...@ix.netcom.com

unread,
Jan 23, 2013, 7:34:33 PM1/23/13
to map...@googlegroups.com
Ah, yes: I just stopped renderd, without affecting MapProxy.

I'm lucky enough to have control of entire hosts, usually, so I'm going to leave the virtual environment details to others, for the moment.

The MapProxy config loader.py code for handling Mapnik version looks like this:

if self.conf.get('use_mapnik2', False):
    from mapproxy.source.mapnik import Mapnik2Source as MapnikSource, mapnik2 as mapnik_api
else:
    from mapproxy.source.mapnik import MapnikSource, mapnik as mapnik_api
if mapnik_api is None:
    raise ConfigurationError('Could not import Mapnik, please verify it is installed!')
return MapnikSource(mapfile, layers=layers, image_opts=image_opts,
    coverage=coverage, res_range=res_range, lock=lock)


There must be a try - catch somewhere that I haven't found, because I just set use_mapnik2 to false, (that's actually the default, so I just removed the assignment) and everything still works. So, I whatever problem I had, that led me set use_mapnik2 this morning, was coincidental. BTW, I found a problematic try - catch for "mapnik2" in Leaflet, which I simply reversed, so that it tried "import mapnik" first. Maybe I'll mention that to the Leaflet team.

The notion of creating a WMS, then consuming locally, was a bit of a hack, based on Leaflet's ability to do what I wanted, using a WMS data source, but not with my tiles. MapProxy obviates any of that, (so I won't be calling for anyone to update mod_mapnik_wms any time soon).

Summary:
  • No real need to set 'use_mapnik2', unless you're using that interim Mapnik version (1.8?) that demanded we "import mapnik2".
  • No reason to have renderd running; Mapnik is imported by the MapProxy code, and calls its methods directly.
Thanks,


-Paul

Jukka Rahkonen

unread,
Jan 24, 2013, 7:43:17 PM1/24/13
to map...@googlegroups.com
Dane Springmeyer wrote:

> - Yes, mod_mapnik_wms has not been updated in a while. If WMS + > Mapnik
> 2.x is ever needed (which hopefully it will not since tiles are better)
> you can also use either OGCServer[1] or landspeed.js[2] with Mapnik 2 and
> above.

There is still use for WMS. I counted that the largest WMS service we have
has 66 layers, users want to have them all and only two of them are used
so much that it pays to tile them. And we support three coordinate systems
for all layers, and users can themself adjust the rendering styles for
about 10 of the layers with SLD and about 20 layers support
GetFeatureInfo. But naturally Mapnik does not need to be WMS. It may shine
with tiles and WMS can be handled with other tools.

-Jukka Rahkonen-

Peter Antypas

unread,
Jan 28, 2013, 11:51:12 AM1/28/13
to map...@googlegroups.com
After successfully prototyping with MapProxy (which is nowhere near production quality -- too many 500s with latest mapnik and PostGIS), I decided to generate pre-rendered geographic tiles according to the TMS spec. I wrote this script and the results rendered correctly as an imagery provider for Cesium (http://cesium.agi.com/).

You and everyone else are welcome to use this and modify it as you see fit. I hereby release it in the public domain. It's a re-write of generate_tiles.py.

Peter
generate_geographic_tiles.py

pwi...@ix.netcom.com

unread,
Jan 29, 2013, 2:10:53 PM1/29/13
to map...@googlegroups.com
n = 1e9
HUGE = int(n)
person = mapnik.PersonSymbolizer()
person.grateful = True
person.multiplicity = HUGE

if (person.grateful):
  msg = "Thanks Peter"
if (person.multiplicity >= 'HUGE'):
  msg += '!!!\n'
  msg += "I have to imagine that this is going to help a lot of people."
print msg


I'm testing your script, now. Everything seems to work as advertised.

The only contribution I can offer at the moment is to have the local environment determine which Python 2.x to use, by changing the first line of generate_geographic_tiles.py to:

#!/usr/bin/env python

In any case, I vote for its inclusion in openstreetmap/mapnik-stylesheets.

BTW:

The problem of MapProxy timing out while waiting for a tile to render seems like something that should / could be adjustable, and a seeded cache seems like the logical first step in solving that.

I'm also watching MapProxy emit deprecation warnings that it's getting from Mapnik. That should be simple to address. If I get time I'll see about contributing a patch to MapProxy.

-Paul

pwi...@ix.netcom.com

unread,
Jan 30, 2013, 5:37:15 PM1/30/13
to map...@googlegroups.com
If I understand your question correctly, you want to know whether you can use the OSM layer defined in www.openstreetmap.org/openlayers/OpenStreetMap.js, which uses a WMS source.

You'd have to use OpenLayers' transform() method to re-project that data into EPSG:4326, if I'm not mistaken. I recall doing this, a couple of weeks ago, but what I'm doing now is importing OSM data into my own PostGIS database, using osm2pgsql with the --latlong parameter, to preserve the geodetic CRS, then creating tiles from this source, and finally creating my own layer using the new tiles as a data source. While this avoids having to re-project, it's also the reason I'm using MapProxy: to create a cache of tiles with the correct number of rows and columns for a map that's twice as wide as it is tall.

I'm including snoppets of the osm.xml that you wanted. Rather than creating this with create_xml.py, I used OSM's mapnik stylesheet, here: https://github.com/openstreetmap/mapnik-stylesheets (or git clone git://github.com/openstreetmap/mapnik-stylesheets.git). That's why I've also included some xml.inc files, because this osm.xml file uses HTML entities and includes.

Note that you may or may not need to create a PostGIS user called ww-data, and you shouldn't need to specify a password in the datasource.settings.xml.inc file, assuming that you're behind a firewall and are using trust authentication for local users in your pg_hba.conf file.

Here's the Javascipt for implementing  OpenLayers:

<script src="static/OpenLayers.js"></script>
<script type="text/javascript">
    var map;
    function init(){
        OpenLayers.Util.onImageLoadErrorColor = "transparent";

        map = new OpenLayers.Map('map', {
          maxResolution: 1.40625,
          maxExtent: new OpenLayers.Bounds(-180.0, -90.0, 180.0, 90.0),
          projection: new OpenLayers.Projection("EPSG:4326")
        });
        var layer = new OpenLayers.Layer.WMS( "WMS world",
            "../service?",
            {layers: "world", format: "image/png", srs:"EPSG:4326",
             exceptions: "application/vnd.ogc.se_inimage", transparent: true},
            {singleTile: true, ratio: 1, isBaseLayer: true} );

        map.addLayer(layer);
        map.zoomToMaxExtent();
    }
</script>

mapnik-stylesheets/osm.xml:

<!DOCTYPE Map [
<!ENTITY % entities SYSTEM "inc/entities.xml.inc">
<!ENTITY % settings SYSTEM "settings.xml.inc">
<!-- Settings for symbols, the spatial reference of your postgis tables, coastline shapefiles directory, and their prefix names.  -->
<!-- use 'symbols' unless you have moved the symbols directory -->
<!ENTITY symbols "symbols">
<!-- use the '&srs900913;' entity if you have called osm2pgsql without special flags (or with -m); use '&srs4326;' if you have used -l -->
<!ENTITY osm2pgsql_projection "+init=epsg:4326">
<!-- used for 'node in way' ST_DWithin spatial operations -->
<!-- Use 0.1 (meters) when your database is in 900913     -->
<!-- Use 0.000001 (degrees) when your database is in 4326 -->
<!ENTITY dwithin_900913 "0.1">
<!ENTITY dwithin_4326 "0.00001">
<!ENTITY dwithin_node_way "&dwithin_4326;">
<!-- use 'world_boundaries', which is the usual naming for the local folder the coastline shapefiles are unzipped into -->
<!ENTITY world_boundaries "/usr/share/mapnik-osm-data/world_boundaries">
<!-- use 'planet_osm' unless you have customized your database table prefix using the osm2pgsql 'prefix' flag -->
<!ENTITY prefix "planet_osm">
<!ENTITY datasource-settings SYSTEM "datasource-settings.xml.inc">
<!ENTITY fontset-settings SYSTEM "fontset-settings.xml.inc">
<!ENTITY srs900913 "+proj=merc +a=6378137 +b=6378137 +lat_ts=0.0 +lon_0=0.0 +x_0=0.0 +y_0=0 +k=1.0 +units=m +nadgrids=@null +no_defs +over">
<!ENTITY srsmercator "+proj=merc +datum=WGS84 +over">
<!ENTITY srs4326 "+init=epsg:4326">

mapnik-stylesheets/inc/datasource-settings.xml.inc:

<Parameter name="type">postgis</Parameter>
<Parameter name="password"></Parameter>
<Parameter name="host"></Parameter>
<Parameter name="port"></Parameter>
<Parameter name="user"></Parameter>
<Parameter name="dbname">osm</Parameter>
<!-- this should be 'false' if you are manually providing the 'extent' -->
<Parameter name="estimate_extent">false</Parameter>
<!-- manually provided extent in epsg 900913 for whole globe -->
<!-- providing this speeds up Mapnik database queries -->
<Parameter name="extent">-179, -89, 179, 89</Parameter>

mapnik-stylesheets/inc/settings.xml.inc:

<!ENTITY symbols "symbols">

<!-- use the '&srs900913;' entity if you have called osm2pgsql without special flags (or with -m); use '&srs4326;' if you have used -l -->
<!ENTITY osm2pgsql_projection "&srs4326;">

<!-- used for 'node in way' ST_DWithin spatial operations -->
<!-- Use 0.1 (meters) when your database is in 900913     -->
<!-- Use 0.000001 (degrees) when your database is in 4326 -->
<!ENTITY dwithin_900913 "0.1">
<!ENTITY dwithin_4326 "0.00001">
<!ENTITY dwithin_node_way "&dwithin_4326;">

<!-- use 'world_boundaries', which is the usual naming for the local folder the coastline shapefiles are unzipped into -->
<!ENTITY world_boundaries "/home/paul/world_boundaries">

<!-- use 'planet_osm' unless you have customized your database table prefix using the osm2pgsql 'prefix' flag -->
<!ENTITY prefix "planet_osm">

mapnik-stylesheets/inc/entities.xml.inc:

!ENTITY % settings SYSTEM "settings.xml.inc">
%settings;
<!ENTITY datasource-settings SYSTEM "datasource-settings.xml.inc">
<!ENTITY fontset-settings SYSTEM "fontset-settings.xml.inc">
<!ENTITY srs900913 "+proj=merc +a=6378137 +b=6378137 +lat_ts=0.0 +lon_0=0.0 +x_0=0.0 +y_0=0 +k=1.0 +units=m +nadgrids=@null +no_defs +over">
<!ENTITY srsmercator "+proj=merc +datum=WGS84 +over">
<!ENTITY srs4326 "+init=epsg:4326">
<!ENTITY % layers SYSTEM "layers.xml.inc">
%layers;
<!ENTITY maxscale_zoom0 "<MaxScaleDenominator>250000000000</MaxScaleDenominator>">
<!ENTITY maxscale_zoom1 "<MaxScaleDenominator>500000000</MaxScaleDenominator>">
<!ENTITY minscale_zoom1 "<MinScaleDenominator>200000000</MinScaleDenominator>">
<!ENTITY maxscale_zoom2 "<MaxScaleDenominator>200000000</MaxScaleDenominator>">
<!ENTITY minscale_zoom2 "<MinScaleDenominator>100000000</MinScaleDenominator>">
<!ENTITY maxscale_zoom3 "<MaxScaleDenominator>100000000</MaxScaleDenominator>">
<!ENTITY minscale_zoom3 "<MinScaleDenominator>50000000</MinScaleDenominator>">
<!ENTITY maxscale_zoom4 "<MaxScaleDenominator>50000000</MaxScaleDenominator>">
<!ENTITY minscale_zoom4 "<MinScaleDenominator>25000000</MinScaleDenominator>">
<!ENTITY maxscale_zoom5 "<MaxScaleDenominator>25000000</MaxScaleDenominator>">
<!ENTITY minscale_zoom5 "<MinScaleDenominator>12500000</MinScaleDenominator>">
<!ENTITY maxscale_zoom6 "<MaxScaleDenominator>12500000</MaxScaleDenominator>">
<!ENTITY minscale_zoom6 "<MinScaleDenominator>6500000</MinScaleDenominator>">
<!ENTITY maxscale_zoom7 "<MaxScaleDenominator>6500000</MaxScaleDenominator>">
<!ENTITY minscale_zoom7 "<MinScaleDenominator>3000000</MinScaleDenominator>">
<!ENTITY maxscale_zoom8 "<MaxScaleDenominator>3000000</MaxScaleDenominator>">
<!ENTITY minscale_zoom8 "<MinScaleDenominator>1500000</MinScaleDenominator>">
<!ENTITY maxscale_zoom9 "<MaxScaleDenominator>1500000</MaxScaleDenominator>">
<!ENTITY minscale_zoom9 "<MinScaleDenominator>750000</MinScaleDenominator>">
<!ENTITY maxscale_zoom10 "<MaxScaleDenominator>750000</MaxScaleDenominator>">
<!ENTITY minscale_zoom10 "<MinScaleDenominator>400000</MinScaleDenominator>">
<!ENTITY maxscale_zoom11 "<MaxScaleDenominator>400000</MaxScaleDenominator>">
<!ENTITY minscale_zoom11 "<MinScaleDenominator>200000</MinScaleDenominator>">
<!ENTITY maxscale_zoom12 "<MaxScaleDenominator>200000</MaxScaleDenominator>">
<!ENTITY minscale_zoom12 "<MinScaleDenominator>100000</MinScaleDenominator>">
<!ENTITY maxscale_zoom13 "<MaxScaleDenominator>100000</MaxScaleDenominator>">
<!ENTITY minscale_zoom13 "<MinScaleDenominator>50000</MinScaleDenominator>">
<!ENTITY maxscale_zoom14 "<MaxScaleDenominator>50000</MaxScaleDenominator>">
<!ENTITY minscale_zoom14 "<MinScaleDenominator>25000</MinScaleDenominator>">
<!ENTITY maxscale_zoom15 "<MaxScaleDenominator>25000</MaxScaleDenominator>">
<!ENTITY minscale_zoom15 "<MinScaleDenominator>12500</MinScaleDenominator>">
<!ENTITY maxscale_zoom16 "<MaxScaleDenominator>12500</MaxScaleDenominator>">
<!ENTITY minscale_zoom16 "<MinScaleDenominator>5000</MinScaleDenominator>">
<!ENTITY maxscale_zoom17 "<MaxScaleDenominator>5000</MaxScaleDenominator>">
<!ENTITY minscale_zoom17 "<MinScaleDenominator>2500</MinScaleDenominator>">
<!ENTITY maxscale_zoom18 "<MaxScaleDenominator>2500</MaxScaleDenominator>">
<!ENTITY minscale_zoom18 "">


I hope this helps.


On Wednesday, January 30, 2013 10:10:43 AM UTC-8, Hoang Dam wrote:
HUGE thanks for all who have contributed to this, this is what I'm looking for - the ability to render OSM map tiles in 4326.  I would like to replicate this success on my system, and wonder if you can share your map file (osm.xml).  After that, I will try to generate the world data set for zoom level 0-8, any pointer on how to do this effectively is much appreciated.

Paul,
Can you use OpenLayer's OSM layer to display the generated map tiles or you need to use a different algo to select the tile?

Thanks,
...-H

Hoang Dam

unread,
Jan 31, 2013, 11:45:33 AM1/31/13
to map...@googlegroups.com
Great, thanks for your quick and detail responses.

So, it looks like that you use wms on the client side, I originally thought that you would use TMS (EPSG:4326) similar to what's been done on MapProxy's demo.  That's why I asked how you did it using openslayer's script since I don't understand how they can do that (don't see that in the mapproxy.yaml configuration).  I will read more about mapproxy.

Again, many thanks.

...-H

pwi...@ix.netcom.com

unread,
Jan 31, 2013, 12:32:59 PM1/31/13
to map...@googlegroups.com
Well, TMS is really what I'm using locally. I was toying with WMS because it would allow me to use Leaflet. But using a WMS, locally, just so I could get around a bug in Leaflet is a bit more of a hack that I'm prepared to deploy. I'll have another look at leaflet in the spring.

PostGIS, GDAL, Mapnik, MapProxy's TMS, and OpenLayers are really the appropriate components for what I'm trying to accomplish, at the moment.

The Javascript for the MapProxy TMS looks like this:

<script src="static/OpenLayers.js"></script>
<script type="text/javascript">
var map;
function init(){
    var mapOptions = {
    projection: new OpenLayers.Projection('EPSG:4326'),
    maxResolution: 0.703125,
    units: 'degree',
    numZoomLevels: 19,
    maxExtent: new OpenLayers.Bounds(-180.0, -90.0, 180.0, 90.0)
    };

    map = new OpenLayers.Map('map', mapOptions);

    var layer = new OpenLayers.Layer.TMS('TMS world', '../tms/',
        {layername: 'world_EPSG4326', type: 'png',
         tileSize: new OpenLayers.Size(256, 256)
    });

    map.addLayer(layer)
    map.zoomToExtent(new OpenLayers.Bounds(-180.00, -90.00, 180.00, 90.00));
}
</script>

...and the YAML:

services:
  demo:
  kml:
  tms:
    # needs no arguments
  wmts:
  wms:
    # srs: ['EPSG:4326', 'EPSG:900913']
    # image_formats: ['image/jpeg', 'image/png']
    md:
      # metadata used in capabilities documents
      title: MapProxy WMS Proxy
      abstract: This is the fantastic MapProxy.
      online_resource: http://mapproxy.org/
      contact:
        person: Your Name Here
        position: Technical Director
        organization:
        address: Fakestreet 123
        city: Somewhere
        postcode: 12345
        country: Germany
        phone: +49(0)000-000000-0
        fax: +49(0)000-000000-0
        email: some-e-mail-address
      access_constraints:
        This service is intended for private and evaluation use only.
        The data is licensed as Creative Commons Attribution-Share Alike 2.0
        (http://creativecommons.org/licenses/by-sa/2.0/)
      fees: 'None'
layers:
  - name: root
    title: Root Layer
    layers:
      - name: iai_outage
        title: Service Area Outages
        layers:

          - name: world
            title: local Mapnik boundary data
            sources: [iai_cache]
          - name: coast-poly
            title: Coastline
            sources: [iai_cache]
          - name: builtup
            title: Urban Areas
            sources: [iai_cache]
          - name: necountries
            title: Countries
            sources: [iai_cache]
          - name: nepopulated
            title: Places
            sources: [iai_cache]
          - name: landcover
            title: Landcover
            sources: [iai_cache]
          - name: landcover_line
            title: Landcover Lines
            sources: [iai_cache]
          - name: water-lines-casing
            title: Waterline Casings
            sources: [iai_cache]
          - name: water_areas
            title: Water Areas
            sources: [iai_cache]
          - name: water-areas-overlay
            title: Water Areas Overlay
            sources: [iai_cache]
          - name: water-lines-low-zoom
            title: Water Areas Low-zoom
            sources: [iai_cache]
   
caches:
  iai_cache:
    grids: [global_geodetic_sqrt2]
    sources: [iai_tms]
    format: image/png
 
sources:
  iai_tms:
    type: mapnik
    mapfile: /home/paul/src/mapnik-stylesheets/osm.xml
    layers: [world,coast-poly,builtup,necountries,nepopulated,landcover,landcover_line,water-lines-casing,water_areas,water-areas-overlay,water-lines-low-zoom]
    use_mapnik2: false

 
grids:
  global_geodetic_sqrt2:
    base: GLOBAL_GEODETIC
    res_factor: 'sqrt2'
  platte_carre:
    srs: 'EPSG:4326'
    tile_size: [256, 256]

    bbox: [-180, -90, 180, 90]
    bbox_srs: 'EPSG:4326'
    #res: [0.000171661376953, 0.000343322753906, 0.000686645507812, 0.00137329101562, 0.00274658203125, 0.0054931640625, 0.010986328125, 0.02197265625, 0.0439453125, 0.087890625, 0.17578125, 0.3515625, 0.703125]

globals:
  cache:
    base_dir: './cache_data'
    lock_dir: './cache_data/locks'

  image:
      resampling_method: nearest
      # resampling_method: bilinear
      # resampling_method: bicubic


Note that the platte_carre grid that I started to write is not needed, since global_geodedic_sqrt2 is already provided with MapProxy.

Is the closer to what you need?

Hoang Dam

unread,
Jan 31, 2013, 2:04:39 PM1/31/13
to map...@googlegroups.com
Wonderful, now I understand the interconnect between Mapnik, Mapproxy's TMS and OpenLayers.  I'll try what you suggested but using a different client (openscales - a port of OpenLayers for flash) to see if it works.  I'll also try to see if Mapproxy supports static images (via file:// instead of http://).

Many, many thanks,
...-H

Hoang Dam

unread,
Jan 31, 2013, 5:08:46 PM1/31/13
to map...@googlegroups.com
Hi,

I tried both (openscales client and static files) and they're all working.  It would be a simple changes in the configuration (refer to Paul's wonderful post of the detail yalm file), following is what you can do for static osm or google tiles....

layers:
  - name: test
    title: Test Static Tile
    sources: [test_cache]

caches:
  test_cache:
    grids: [tile_grid_osm]
    sources: []
    cache:
      type: file
      directory_layout: tms                 <use "tc" or don't need to specify this if you follow tilecache's directory structure>
      directory:<your tile directory>

grids:
  tile_grid_osm:
    base: GLOBAL_MERCATOR
    origin: nw
Reply all
Reply to author
Forward
0 new messages