OSGeoLive-Notebooks/mapnik-py/mapnik_draw_example.ipynb

479 lines
17 KiB
Plaintext

{
"cells": [
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"#!/usr/bin/env python\n",
"# -*- coding: utf-8 -*-\n",
"#\n",
"#\n",
"#\n",
"# This file is part of Mapnik (c++ mapping toolkit)\n",
"# Copyright (C) 2005 Jean-Francois Doyon\n",
"#\n",
"from __future__ import print_function\n",
"import sys\n",
"from os import path\n",
"import mapnik\n",
"\n",
"# Instanciate a map, giving it a width and height. Remember: the word \"map\" is\n",
"# reserved in Python! :)\n",
"\n",
"#root = path.dirname(__file__)\n",
"root = '/home/user/jupyter/notebook_gallery/mapnik-py/'\n",
"\n",
"m = mapnik.Map(800,600,\"+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\")\n",
"\n",
"# Set its background colour. More on colours later ...\n",
"\n",
"m.background = mapnik.Color('white')\n",
"\n",
"# Now we can start adding layers, in stacking order (i.e. bottom layer first)\n",
"\n",
"# Canadian Provinces (Polygons)\n",
"\n",
"# Instanciate a layer. The parameters depend on the type of data:\n",
"# shape:\n",
"# type='shape'\n",
"# file='/path/to/shape'\n",
"# raster:\n",
"# type='raster'\n",
"# file='/path/to/raster'\n",
"# postgis:\n",
"# type='postgis'\n",
"# host='127.0.0.1'\n",
"# dbname='mydatabase'\n",
"# user='myusername'\n",
"# password='mypassword'\n",
"# table= TODO\n",
"\n",
"provpoly_lyr = mapnik.Layer('Provinces')\n",
"provpoly_lyr.srs = \"+proj=lcc +ellps=GRS80 +lat_0=49 +lon_0=-95 +lat+1=49 +lat_2=77 +datum=NAD83 +units=m +no_defs\"\n",
"provpoly_lyr.datasource = mapnik.Shapefile(file=path.join(root,'data/boundaries.shp'), encoding='latin1')\n",
"\n",
"# We then define a style for the layer. A layer can have one or many styles.\n",
"# Styles are named, so they can be shared across different layers.\n",
"# Multiple styles per layer behaves functionally like multiple layers. The\n",
"# data is completely re-scanned for each style within one layer, and a style\n",
"# will be drawn entirely \"above\" the previous one. Performance wise using\n",
"# multiple styles in one layer is the same has having multiple layers.\n",
"# The paradigm is useful mostly as a convenience.\n",
"\n",
"provpoly_style = mapnik.Style()\n",
"\n",
"# A Style needs one or more rules. A rule will normally consist of a filter\n",
"# for feature selection, and one or more symbolizers.\n",
"\n",
"provpoly_rule_on = mapnik.Rule()\n",
"\n",
"# A Expression() allows the selection of features to which the symbology will\n",
"# be applied. More on Mapnik expressions can be found in Tutorial #2.\n",
"# A given feature can only match one filter per rule per style.\n",
"\n",
"provpoly_rule_on.filter = mapnik.Expression(\"[NAME_EN] = 'Ontario'\")\n",
"\n",
"# Here a symbolizer is defined. Available are:\n",
"# - LineSymbolizer(Color(),<width>)\n",
"# - LineSymbolizer(Stroke())\n",
"# - PolygonSymbolizer(Color())\n",
"# - PointSymbolizer(<file>,<type>,<width>,<height>)\n",
"\n",
"# Some of them can accept a Color() instance, which can be created with:\n",
"# - Color(<red>, <green>, <blue>)\n",
"# - Color(<red>, <green>, <blue>, <alpha>)\n",
"# - Color(<string>) where <string> will be something like '#00FF00'\n",
"# or '#0f0' or 'green'\n",
"\n",
"sym = mapnik.PolygonSymbolizer()\n",
"sym.fill = mapnik.Color(250, 190, 183);\n",
"provpoly_rule_on.symbols.append(sym)\n",
"provpoly_style.rules.append(provpoly_rule_on)\n",
"\n",
"provpoly_rule_qc = mapnik.Rule()\n",
"provpoly_rule_qc.filter = mapnik.Expression(\"[NOM_FR] = 'Québec'\")\n",
"sym = mapnik.PolygonSymbolizer()\n",
"sym.fill = mapnik.Color(217, 235, 203)\n",
"provpoly_rule_qc.symbols.append(sym)\n",
"provpoly_style.rules.append(provpoly_rule_qc)\n",
"\n",
"# Add the style to the map, giving it a name. This is the name that will be\n",
"# used to refer to it from here on. Having named styles allows them to be\n",
"# re-used throughout the map.\n",
"\n",
"m.append_style('provinces', provpoly_style)\n",
"\n",
"# Then associate the style to the layer itself.\n",
"\n",
"provpoly_lyr.styles.append('provinces')\n",
"\n",
"# Then add the layer to the map. In reality, it's the order in which you\n",
"# append them to the map that will determine the drawing order, though by\n",
"# convention it is recommended to define them in drawing order as well.\n",
"\n",
"m.layers.append(provpoly_lyr)\n",
"\n",
"# Drainage\n",
"\n",
"# A simple example ...\n",
"\n",
"qcdrain_lyr = mapnik.Layer('Quebec Hydrography')\n",
"qcdrain_lyr.srs = \"+proj=lcc +ellps=GRS80 +lat_0=49 +lon_0=-95 +lat+1=49 +lat_2=77 +datum=NAD83 +units=m +no_defs\"\n",
"qcdrain_lyr.datasource = mapnik.Shapefile(file=path.join(root,'data/qcdrainage'))\n",
"\n",
"qcdrain_style = mapnik.Style()\n",
"qcdrain_rule = mapnik.Rule()\n",
"qcdrain_rule.filter = mapnik.Expression('[HYC] = 8')\n",
"sym = mapnik.PolygonSymbolizer()\n",
"sym.fill = mapnik.Color(153, 204, 255)\n",
"sym.smooth = 1.0 # very smooth\n",
"qcdrain_rule.symbols.append(sym)\n",
"qcdrain_style.rules.append(qcdrain_rule)\n",
"\n",
"m.append_style('drainage', qcdrain_style)\n",
"qcdrain_lyr.styles.append('drainage')\n",
"m.layers.append(qcdrain_lyr)\n",
"\n",
"# In this case, we have 2 data sets with similar schemas (same filtering\n",
"# attributes, and same desired style), so we're going to\n",
"# re-use the style defined in the above layer for the next one.\n",
"\n",
"ondrain_lyr = mapnik.Layer('Ontario Hydrography')\n",
"ondrain_lyr.srs = \"+proj=lcc +ellps=GRS80 +lat_0=49 +lon_0=-95 +lat+1=49 +lat_2=77 +datum=NAD83 +units=m +no_defs\"\n",
"ondrain_lyr.datasource = mapnik.Shapefile(file=path.join(root,'data/ontdrainage'))\n",
"\n",
"ondrain_lyr.styles.append('drainage')\n",
"m.layers.append(ondrain_lyr)\n",
"\n",
"# Provincial boundaries\n",
"\n",
"provlines_lyr = mapnik.Layer('Provincial borders')\n",
"provlines_lyr.srs = \"+proj=lcc +ellps=GRS80 +lat_0=49 +lon_0=-95 +lat+1=49 +lat_2=77 +datum=NAD83 +units=m +no_defs\"\n",
"provlines_lyr.datasource = mapnik.Shapefile(file=path.join(root,'data/boundaries_l'))\n",
"\n",
"# Here we define a \"dash dot dot dash\" pattern for the provincial boundaries.\n",
"\n",
"provlines_style = mapnik.Style()\n",
"provlines_rule = mapnik.Rule()\n",
"sym = mapnik.LineSymbolizer()\n",
"# FIXME - currently adding dash arrays is broken\n",
"# https://github.com/mapnik/mapnik/issues/2324\n",
"sym.stroke = mapnik.Color('black')\n",
"sym.stroke_width = 1\n",
"provlines_rule.symbols.append(sym)\n",
"provlines_style.rules.append(provlines_rule)\n",
"\n",
"m.append_style('provlines', provlines_style)\n",
"provlines_lyr.styles.append('provlines')\n",
"m.layers.append(provlines_lyr)\n",
"\n",
"# Roads 3 and 4 (The \"grey\" roads)\n",
"\n",
"roads34_lyr = mapnik.Layer('Roads')\n",
"roads34_lyr.srs = \"+proj=lcc +ellps=GRS80 +lat_0=49 +lon_0=-95 +lat+1=49 +lat_2=77 +datum=NAD83 +units=m +no_defs\"\n",
"# create roads datasource (we're going to re-use it later)\n",
"\n",
"roads34_lyr.datasource = mapnik.Shapefile(file=path.join(root,'data/roads'))\n",
"\n",
"roads34_style = mapnik.Style()\n",
"roads34_rule = mapnik.Rule()\n",
"roads34_rule.filter = mapnik.Expression('([CLASS] = 3) or ([CLASS] = 4)')\n",
"\n",
"# With lines of a certain width, you can control how the ends\n",
"# are closed off using line_cap as below.\n",
"\n",
"# Available options are:\n",
"# line_cap: BUTT_CAP, SQUARE_CAP, ROUND_CAP\n",
"# line_join: MITER_JOIN, MITER_REVERT_JOIN, ROUND_JOIN, BEVEL_JOIN\n",
"\n",
"# And one last Stroke() attribute not used here is \"opacity\", which\n",
"# can be set to a numerical value.\n",
"\n",
"sym = mapnik.LineSymbolizer()\n",
"sym.stroke = mapnik.Color(171,158,137)\n",
"sym.stroke_width = 2\n",
"sym.stroke_linecap = mapnik.stroke_linecap.ROUND_CAP\n",
"\n",
"roads34_rule.symbols.append(sym)\n",
"roads34_style.rules.append(roads34_rule)\n",
"\n",
"m.append_style('smallroads', roads34_style)\n",
"roads34_lyr.styles.append('smallroads')\n",
"m.layers.append(roads34_lyr)\n",
"\n",
"# Roads 2 (The thin yellow ones)\n",
"\n",
"roads2_lyr = mapnik.Layer('Roads')\n",
"roads2_lyr.srs = \"+proj=lcc +ellps=GRS80 +lat_0=49 +lon_0=-95 +lat+1=49 +lat_2=77 +datum=NAD83 +units=m +no_defs\"\n",
"# Just get a copy from roads34_lyr\n",
"roads2_lyr.datasource = roads34_lyr.datasource\n",
"\n",
"roads2_style_1 = mapnik.Style()\n",
"roads2_rule_1 = mapnik.Rule()\n",
"roads2_rule_1.filter = mapnik.Expression('[CLASS] = 2')\n",
"\n",
"sym = mapnik.LineSymbolizer()\n",
"sym.stroke = mapnik.Color(171,158,137)\n",
"sym.stroke_width = 4\n",
"sym.stroke_linecap = mapnik.stroke_linecap.ROUND_CAP\n",
"roads2_rule_1.symbols.append(sym)\n",
"roads2_style_1.rules.append(roads2_rule_1)\n",
"\n",
"m.append_style('road-border', roads2_style_1)\n",
"\n",
"roads2_style_2 = mapnik.Style()\n",
"roads2_rule_2 = mapnik.Rule()\n",
"roads2_rule_2.filter = mapnik.Expression('[CLASS] = 2')\n",
"sym = mapnik.LineSymbolizer()\n",
"sym.stroke = mapnik.Color(255,250,115)\n",
"sym.stroke_linecap = mapnik.stroke_linecap.ROUND_CAP\n",
"sym.stroke_width = 2\n",
"roads2_rule_2.symbols.append(sym)\n",
"roads2_style_2.rules.append(roads2_rule_2)\n",
"\n",
"m.append_style('road-fill', roads2_style_2)\n",
"\n",
"roads2_lyr.styles.append('road-border')\n",
"roads2_lyr.styles.append('road-fill')\n",
"\n",
"m.layers.append(roads2_lyr)\n",
"\n",
"# Roads 1 (The big orange ones, the highways)\n",
"\n",
"roads1_lyr = mapnik.Layer('Roads')\n",
"roads1_lyr.srs = \"+proj=lcc +ellps=GRS80 +lat_0=49 +lon_0=-95 +lat+1=49 +lat_2=77 +datum=NAD83 +units=m +no_defs\"\n",
"roads1_lyr.datasource = roads34_lyr.datasource\n",
"\n",
"roads1_style_1 = mapnik.Style()\n",
"roads1_rule_1 = mapnik.Rule()\n",
"roads1_rule_1.filter = mapnik.Expression('[CLASS] = 1')\n",
"sym = mapnik.LineSymbolizer()\n",
"sym.stroke = mapnik.Color(188,149,28)\n",
"sym.stroke_linecap = mapnik.stroke_linecap.ROUND_CAP\n",
"sym.stroke_width = 7\n",
"roads1_rule_1.symbols.append(sym)\n",
"roads1_style_1.rules.append(roads1_rule_1)\n",
"m.append_style('highway-border', roads1_style_1)\n",
"\n",
"roads1_style_2 = mapnik.Style()\n",
"roads1_rule_2 = mapnik.Rule()\n",
"roads1_rule_2.filter = mapnik.Expression('[CLASS] = 1')\n",
"sym.stroke = mapnik.Color(242,191,36)\n",
"sym.stroke_linecap = mapnik.stroke_linecap.ROUND_CAP\n",
"sym.stroke_width = 5\n",
"roads1_rule_2.symbols.append(sym)\n",
"roads1_style_2.rules.append(roads1_rule_2)\n",
"\n",
"m.append_style('highway-fill', roads1_style_2)\n",
"\n",
"roads1_lyr.styles.append('highway-border')\n",
"roads1_lyr.styles.append('highway-fill')\n",
"\n",
"m.layers.append(roads1_lyr)\n",
"\n",
"# Populated Places\n",
"\n",
"popplaces_lyr = mapnik.Layer('Populated Places')\n",
"popplaces_lyr.srs = \"+proj=lcc +ellps=GRS80 +lat_0=49 +lon_0=-95 +lat+1=49 +lat_2=77 +datum=NAD83 +units=m +no_defs\"\n",
"popplaces_lyr.datasource = mapnik.Shapefile(file=path.join(root,'data/popplaces'),encoding='latin1')\n",
"\n",
"popplaces_style = mapnik.Style()\n",
"popplaces_rule = mapnik.Rule()\n",
"\n",
"# And here we have a TextSymbolizer, used for labeling.\n",
"# The first parameter is the name of the attribute to use as the source of the\n",
"# text to label with. Then there is font size in points (I think?), and colour.\n",
"\n",
"# TODO - currently broken: https://github.com/mapnik/mapnik/issues/2324\n",
"#popplaces_text_symbolizer = mapnik.TextSymbolizer(mapnik.Expression(\"[GEONAME]\"),\n",
"# 'DejaVu Sans Book',\n",
"# 10, mapnik.Color('black'))\n",
"\n",
"# We set a \"halo\" around the text, which looks like an outline if thin enough,\n",
"# or an outright background if large enough.\n",
"#popplaces_text_symbolizer.label_placement= mapnik.label_placement.POINT_PLACEMENT\n",
"#popplaces_text_symbolizer.halo_fill = mapnik.Color(255,255,200)\n",
"#popplaces_text_symbolizer.halo_radius = 1\n",
"#popplaces_text_symbolizer.avoid_edges = True\n",
"#popplaces_text_symbolizer.minimum_padding = 30\n",
"#popplaces_rule.symbols.append(popplaces_text_symbolizer)\n",
"\n",
"popplaces_style.rules.append(popplaces_rule)\n",
"\n",
"m.append_style('popplaces', popplaces_style)\n",
"popplaces_lyr.styles.append('popplaces')\n",
"m.layers.append(popplaces_lyr)\n",
"\n",
"# Draw map\n",
"\n",
"# Set the initial extent of the map in 'master' spherical Mercator projection\n",
"m.zoom_to_box(mapnik.Box2d(-8024477.28459,5445190.38849,-7381388.20071,5662941.44855))\n",
"\n",
"# Render map\n",
"im = mapnik.Image(m.width,m.height)\n",
"mapnik.render(m, im)\n",
"\n",
"# Save image to files\n",
"images_ = []\n",
"if mapnik.has_png():\n",
" im.save('demo.png', 'png') # true-colour RGBA\n",
" images_.append('demo.png')\n",
"\n",
" # old behavior, now can do 'png8:c=256'\n",
" im.save('demo256.png', 'png256') # save to palette based (max 256 colours) png\n",
" images_.append('demo256.png')\n",
"\n",
" im.save('demo64_binary_transparency.png', 'png8:c=64:t=1')\n",
" images_.append('demo64_binary_transparency.png')\n",
"\n",
" im.save('demo128_colors_hextree_no_alpha.png', 'png8:c=100:m=h:t=0')\n",
" images_.append('demo128_colors_hextree_no_alpha.png')\n",
"\n",
"if mapnik.has_jpeg():\n",
" im.save('demo_high.jpg', 'jpeg100')\n",
" images_.append('demo_high.jpg')\n",
"\n",
" im.save('demo_low.jpg', 'jpeg50')\n",
" images_.append('demo_low.jpg')\n",
"\n",
"if mapnik.has_tiff():\n",
" im.save('demo.tif', 'tiff')\n",
" images_.append('demo.tif')\n",
"\n",
"if mapnik.has_webp():\n",
" im.save('demo.webp', 'webp') # default quality is 90\n",
" images_.append('demo.webp')\n",
"\n",
" im.save('demo_highest.webp', 'webp:quality=100')\n",
" images_.append('demo_med.webp')\n",
"\n",
" im.save('demo_low.webp', 'webp:quality=50')\n",
" images_.append('demo_low.webp')\n",
"\n",
"\n",
"# Render cairo examples\n",
"if mapnik.has_cairo():\n",
" mapnik.render_to_file(m,'demo.pdf')\n",
" images_.append('demo.pdf')\n",
" mapnik.render_to_file(m,'demo.ps')\n",
" images_.append('demo.ps')\n",
" mapnik.render_to_file(m,'demo.svg')\n",
" images_.append('demo.svg')\n",
" mapnik.render_to_file(m,'demo_cairo_rgb24.png','RGB24')\n",
" images_.append('demo_cairo_rgb.png')\n",
" mapnik.render_to_file(m,'demo_cairo_argb32.png','ARGB32')\n",
" images_.append('demo_cairo_argb.png')\n",
"\n",
"print (\"\\n\\n\", len(images_), \"maps have been rendered in the current directory:\")\n",
"\n",
"for im_ in images_:\n",
" print (\"-\", im_)\n",
"\n",
"print (\"\\n\\nHave a look!\\n\\n\")\n",
"\n",
"mapnik.save_map(m,\"map.xml\")"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"!ls "
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"from IPython.display import Image"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"Image('demo.png')"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"from IPython.display import SVG"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"SVG('demo.svg')"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"mapnik.has_cairo()"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"%whos"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": []
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": []
}
],
"metadata": {
"kernelspec": {
"display_name": "Python 3",
"language": "python",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.8.5"
}
},
"nbformat": 4,
"nbformat_minor": 4
}