Konfigurationsprobleme Mapnik/PostgreSQL (Linux)

Ich versuche seit einigen Tagen Mapnik auf meinem ArchLinux zum Kachelrendern zu bringen - bisher leider relativ erfolglos.
Inzwischen habe ich es soweit geschaft, dass mir aus einer OSM-Datei (Geofabrik-Extract “Regierungsbezirk Karlsruhe”) alle railway=*-Ways gezeichnet werden, aber auch dabei passt irgendwas noch nicht:

Die schwarzen Linien meiner Tiles sollten identisch mit denen der Gravitystorm Transport Map sein. Der Python-Code den ich dazu genutzt habe ist folgender:

#!/usr/bin/env python2


# BASF:
left   = 8.4046
bottom = 49.5254
right  = 8.426
top    = 49.546

minzoom= 15
maxzoom= 16

mapfile = 'style.xml'


from mapnik import *
from time import gmtime, strftime
import os
import math
def latlon2tilenum(lat_deg, lon_deg, zoom):
	lat_rad = math.radians(lat_deg)
	n = 2.0 ** zoom
	xtile = int((lon_deg + 180.0) / 360.0 * n)
	ytile = int((1.0 - math.log(math.tan(lat_rad) + (1 / math.cos(lat_rad))) / math.pi) / 2.0 * n)
	return (xtile, ytile)
def tilenum2latlon(xtile, ytile, zoom):
	n = 2.0 ** zoom
	lon_deg = xtile / n * 360.0 - 180.0
	lat_rad = math.atan(math.sinh(math.pi * (1 - 2 * ytile / n)))
	lat_deg = math.degrees(lat_rad)
	return (lat_deg, lon_deg)


	
for Z in range(minzoom, maxzoom): 
	mintile = latlon2tilenum(top,    left,  Z)
	maxtile = latlon2tilenum(bottom, right, Z)
	
	for  X  in  range(mintile[0], maxtile[0]):
		for Y in range(mintile[1], maxtile[1]):
			if not os.path.exists('tiles/' + str(Z) + '/' + str(X)):
				os.makedirs('tiles/' + str(Z) + '/' + str(X))
			map_output = 'tiles/' + str(Z) + '/' + str(X) + '/' + str(Y) + '.png'
			m = Map(256,256)
			load_map(m,mapfile)
			bbox=(Envelope(
					tilenum2latlon(X,Y,Z)[1],
					tilenum2latlon(X+1,Y+1,Z)[0],
					tilenum2latlon(X+1,Y+1,Z)[1],
					tilenum2latlon(X,Y,Z)[0] ))
			m.zoom_to_box(bbox)
			render_to_file(m,map_output)
			print strftime("%Y-%m-%d %H:%M:%S", gmtime()),": Kachel fertig: ",Z,",",X,",",Y



print "Kacheln fertig erstellt. Scale: ", m.scale()

Style.xml (Ausschnitt):

<?xml version="1.0" encoding="utf-8"?>
<!--<Map background-color="#f2efe9" srs="+proj=latlong +datum=WGS84">-->
<Map srs="+proj=latlong +datum=WGS84">
	<FontSet name="book-fonts">
		<Font face-name="DejaVu Sans Book" />
	</FontSet>
	<Style name="highways">
		<Rule>
			<Filter>[railway] > ''</Filter>
			<LineSymbolizer stroke="#f00" stroke-width="1"/>
		</Rule>
		<Rule>
			<Filter>[railway] = 'rail'</Filter>
			<LineSymbolizer stroke="#000" stroke-width="2" stroke-linejoin="round" stroke-linecap="round"/>
		</Rule>
	</Style>
	<Layer name="highways" status="on" srs="+proj=latlong +datum=WGS84">
		<StyleName>highways</StyleName>
		<Datasource>
			<Parameter name="type">osm</Parameter>
			<Parameter name="file">render.osm</Parameter>
		</Datasource>
	</Layer>
</Map>

Da die Gerüchte über einen Geschwindigkeitsvorteil bei Nutzung einer Datenbank wahrscheinlich stimmen möchte ich die Daten eigentlich in einer solchen speichern. Ich habe daher folgendes versucht:

  • PostGIS (und damit auch PostgreSQL) wurde bereits als Abhängigkeit von Mapnik installiert

  • osm2pgsql aus dem AUR installiert

  • sudo su postgres

  • initdb -D /usr/local/pgsql/data

  • pg_ctl start -D /usr/local/pgsql/data

  • createuser ray

Wenn ich dann (wieder als normaler Benutzer) versuche, die OSM-Daten zu importieren erhalte ich folgendes:
[ray@systemname ~]$ osm2pgsql render.osm
osm2pgsql SVN version 0.81.0 (64bit id space)

Using projection SRS 900913 (Spherical Mercator)
Setting up table: planet_osm_point
HINWEIS:  Tabelle »planet_osm_point« existiert nicht, wird übersprungen
HINWEIS:  Tabelle »planet_osm_point_tmp« existiert nicht, wird übersprungen
SELECT AddGeometryColumn('planet_osm_point', 'way', 900913, 'POINT', 2 );
 failed: FEHLER:  Funktion addgeometrycolumn(unknown, unknown, integer, unknown, integer) existiert nicht
LINE 1: SELECT AddGeometryColumn('planet_osm_point', 'way', 900913, ...
               ^
HINT:  Keine Funktion stimmt mit dem angegebenen Namen und den Argumenttypen überein. Sie müssen möglicherweise ausdrückliche Typumwandlungen hinzufügen.

Error occurred, cleaning up

Was mache ich falsch?

mfg~ray

mal so auf die Schnelle geraten: PostGIS doch irgendwie nicht installiert oder falsche Version davon?

Was gibt denn “select postgis_full_version();” aus? Da müsste das Postgres seine postgis-Version sagen…

Grüße, Max

Mal so ‘ne ganz blöde Gegenfrage: Wo müsste ich das eingeben (Ich hab’ von PostgreSQL (noch) keine Ahnung)?

Laut pacman (Paketverwaltung) sind es postgresql-9.2.2-2 und postgis-2.0.1-1 (Wobei das natürlich nicht heisst, dass die auch voneinander wissen)

Nachtrag: Ich glaub’ ich hab’s gefunden: psql und das Semikolon nicht überlesen?

Ich vermute postgis ist noch nicht richtig installiert/konfiguriert. Hat jemand einen Tipp, wie man das korrigieren könnte?

mfg~ray

Im Postgres:

:~# su - postgres
postgres@srv101:~$ psql gis
psql (8.4.13)
Type "help" for help.

osm=# select postgis_full_version();
                                         postgis_full_version                                          
-------------------------------------------------------------------------------------------------------
 POSTGIS="1.5.1" GEOS="3.2.0-CAPI-1.6.0" PROJ="Rel. 4.7.1, 23 September 2009" LIBXML="2.7.7" USE_STATS
(1 row)

Da wo “psql gis” steht muss bei dir evtl was anderes stehen. “gis” ist der default-Datenbankname von osm2pgsql.

Ich hab leider nur Postgres 8.4 und Postgis 1.5 da. Laut der Doku ist AddGeometryColumn ab Postgis 2.0 veraltet. Da müsste ein osm2pgsql oder Postgis-Kundigerer sagen, ob das zu diesem Fehler führt…

Falls es nicht an der Version liegt, hilft evtl auch das da weiter: http://help.openstreetmap.org/questions/7255/how-to-setup-gis-server-on-debian (diese Lösung ist aber auch auf Postgres 8.4 und Postgis 1.5 bezogen)

Grüße, Max

Da war ich mit meinem Nachtrag wohl etwas zu langsam, trotzdem danke für deine Hilfe.

Bei dem hier beschriebenen Test erhalte ich folgendes:

Die dadrüber genannten *.sql- und *.control-Dateien befinden sich in /usr/share/postgresql/extension.

Nach der auf der verlinkten Seite vorgeschlagenen Eingabe von “CREATE EXTENSION postgis;” erhalte ich auch folgende Ausgabe auf die Anfrage “SELECT postgis_full_version();”:

Ein Importversuch mit osm2pgsql schlägt leider weiterhin mit der selben Fehlermeldung fehl.

suche mal legacy.sql und starte es in psql

psql
\i legacy.sql
\q

bei mir steht das unter /usr/share/postgresql/9.1/contrib/postgis-2.0/legacy.sql - der pfad ist linux aber zumindest contrib\postgis-2.0\legacy.sql solltest du bei dir finden.

Gruss
walter

Das half zumindest etwas weiter. Jetzt erhalte ich folgende Meldung, dass auf “Relation spatial_ref_sys” nicht zugreifen dürfte:

Was genau ist es und wie erlaube ich es mir?

Nachtrag: Manchmal glaube ich echt ich kann nicht lesen: “ALTER TABLE geometry_columns OWNER TO ray; ALTER TABLE spatial_ref_sys OWNER TO ray;” half…

Ich schaffe es jetzt leider nicht, den Parameter “table” im Style-File so anzupassen, dass ich die Daten die ich möchte (railway=*) aus der Datenbank erhalte.

Gibt es irgendwo soetwas wie http://dev.openlayers.org/releases/OpenLayers-2.12/doc/apidocs/files/OpenLayers-js.html für Mapnik?

Inzwischen verstehe ich, dass einige finden, dass das zu aufwändig sei. Ich will doch “nur” Route-Relationen und Abstände zwischen Objekten visualisieren…

Also beim mir sieht die Kommandofolge unter Arch wie folgt aus:

sudo -u postgres -i
createuser mapnik
createdb -E UTF8 -O mapnik osm
createlang plpgsql osm
psql -d osm -f /usr/share/postgresql/contrib/postgis-2.0/postgis.sql
psql -d osm -f /usr/share/postgresql/contrib/postgis-2.0/spatial_ref_sys.sql

psql -d osm -f /usr/share/osm2pgsql/900913.sql
psql -d osm -f /usr/share/postgresql/contrib/postgis-2.0/legacy.sql
echo "ALTER TABLE geometry_columns OWNER TO mapnik; ALTER TABLE spatial_ref_sys OWNER TO mapnik;"  | psql -d osm
exit

osm2pgsql -m -U mapnik -d osm -S default.style bla.osm

wobei ich den default.style aus /usr/share/osm2pgsql kopiert habe und nach meinen Bedürfnissen anpasse. Danach müsste eigentlich alles funktionieren. Wenn pgsql geupdatet wird funktioinert normalerweise die DB nicht mehr und du musst das Prozedere wie im Arch-Wiki beschrieben durchziehen, oder du importierst bei jedem Update neu. Die einfachste Alternative ist aber ein IgnorePkg = postgresql in der /etc/pacman.conf.

Eine richtige Beschreibung der API gibt es nicht, aber die XML-Referenz hilft schon einmal weiter.

Danke für die Zusammenstellung. Ich finde es im OSM-Wiki etwas durcheinander, wodurch ich einige Zeilen überlesen hatte.

Ich habe aus dem OSM-Style-File einen der Datasource-Bereiche (irgendwas mit “railway=‘tram’”) in mein bisheriges Style-File übernommen und so anzupassen versucht, dass railway=tram und =rail ausgelesen werden, woraufhin ich eine Fehlermeldung erhielt. Ich versuche es nachher nochmal mit einem unveränderten Style-File. Hat da jemand einen Tipp für ein möglichst Einfaches?

Danke für die Warnung. Ein Neu-Import erscheint mir annehmbar solange ich noch keine Diffs nutze.

Super Ausgangsbedingungen um was nachzuschlagen, dann muss ich wohl hier noch ein paar Mal fragen…

Evlt. wäre das eine passende Vorlage:
http://wiki.openstreetmap.org/wiki/User:Ajoessen/myMapnik

Bevor Du Dich aber zu sehr mit dem Mapnik XML beschäftigst, wäre evtl. auch ein Blick auf CartoCSS interessant, siehe auch:
https://github.com/gravitystorm/openstreetmap-carto

Gruß,
Norbert

Ich weiß jetzt nicht welches Style-File du meinst. Das default.style File gibt ja nur an, welche Tags du in der Datenbank haben willst, wobei alle möglichen values importiert werden. In der osm.xml änderst du dann letzendlich das Aussehen der Karte.

Ich würde aber für das Kartenstylen eher auf Tilemill zurückgreifen. Das verwendet das von ikonor angesprochene Carto.

Wenn du Tilemill selber bauen willst, musst du vorher dein python-binary umbiegen. Also in etwa so:


cd /usr/bin
sudo ln -s -f python2 python

Nach dem Bauen unbedingt dran denken wieder alles zurückzubiegen:


cd /usr/bin
sudo ln -s -f python3 python

(Ich glaube python war auf python3 gelinkt, kannst du aber, bevor du mit allem anfängst, mit ls -l /usr/bin/python abklären)
Und als Abschluß noch mein PKGBUILD:

pkgname=tilemill
pkgver=20130106
pkgrel=1
pkgdesc="a tool for easy map creation"
arch=('i686' 'x86_64')
url="http://tilemill.com/index.html"
license="GPL"
depends=('mapnik' 'curl' 'nodejs' 'sqlite3' 'gtk2' 'libwebkit')
makedepends=('git')
source=('tilemill.desktop' 'tilemill.svg')
# source=(https://github.com/mapbox/tilemill/zipball/$pkgver/mapbox-$pkgname-$pkgver-0-gfa0d12d.zip)
sha256sums=('5157751e9ee94b8933dd7085dc186315f4125fe465fd6b85faaea5560e3ee137'
	    '0c48f063a3cd563828159bea02c8a32bc9c0a9c16d0d5d40a68ce67a033c5a45')

_gitroot='https://github.com/mapbox/tilemill.git'
_gitname='tilemill'

build() {
  msg "Connecting to https://github.com/ GIT server...."

  if [ -d ${_gitname} ] ; then
    cd ${_gitname} && git pull origin
    msg "The local files are updated."
  else
    git clone ${_gitroot} ${_gitname}
  fi
  msg "GIT checkout done. Preparing sources..."

#   rm -rf "${srcdir}/${_gitname}-build"
#   cp -r "${srcdir}/${_gitname}" "${srcdir}/${_gitname}-build"


  mkdir -p ${pkgdir}/usr/bin/
  mkdir -p ${pkgdir}/usr/share/${pkgname}/
  mkdir -p ${pkgdir}/usr/share/icons/hicolor/scalable/apps/
  mkdir -p ${pkgdir}/usr/share/applications/
  cd "${srcdir}/${_gitname}"

  npm install

  cp -r * ${pkgdir}/usr/share/${pkgname}
  ln -sf /usr/share/${pkgname}/index.js ${pkgdir}/usr/bin/${pkgname}
  install -D -m644 $srcdir/${pkgname}.svg ${pkgdir}/usr/share/icons/hicolor/scalable/apps/${pkgname}.svg || return 1
  install -D -m644 $srcdir/${pkgname}.desktop ${pkgdir}/usr/share/applications/${pkgname}.desktop || return 1
}

und das tilemill.desktop file:

[Desktop Entry]
Name=TileMill
Comment=TileMill Map Design Studio
Exec=tilemill
Icon=/usr/share/icons/hicolor/scalable/apps/tilemill.svg
Terminal=false
Type=Application
Encoding=UTF-8
Categories=Graphics;Application;Geography;
StartupNotify=false

Die tilemill.svg gibt es unter https://github.com/mapbox/tilemill/blob/master/assets/images/tilemill.svg.

Ja, das habe ich inzwischen auch festgestellt (ich war als ich das Posting verfasst habe nicht am PC). Ich meinte osm.xml. Danke für die Erklärung, jetzt weiss ich auch, warum public_transport=* Probleme machte.

Da die von mir gewünsten Styles beim “nur mal kurz ausprobieren” schon einigermassen aussahen werde ich es wohl damit versuchen. Wie ich an Relationen rankomme habe ich auch inzwischen rausgefunden, aber kann ich dabei z.B. die Relations-Mitglieder mit einer bestimmten Rolle abwählen?
Kann ich die zu nutzende Farbe aus color=* nutzen?
Kann ich die hier grün markierte Fläche zwischen zwei Linien (also bis zu einem Bestimmten Abstand in Metern wenn an dem gemeinsamen Node ein bestimmtes Tag ist) einfärben?

Und wenn ja, wie jeweils (im Prinzip egal welche Style-Sprache)?

Vielen Dank für die ausführliche Erklärung. Ich lasse Tilemill zur Zeit unter Windows laufen, werde es aber bald auch unter Linux mal versuchen :wink:

mfg~ray

Ich glaube das ist nicht mit dem Datenbankschema von osm2pgsql möglich. Aber es gäbe ja auch noch andere Importer für die Postgre-SQL Datenbank. Also zum Beispiel Imposm, Osm2postgresql, oder Osmosis. Dann muss man aber auf jeden Fall den kompletten Style ändern.

Es gab, meine ich, mal ein Feature-Request bei Mapnik, der erlauben sollte, Werte aus der Datenbank als Farben zu nutzen. Aber ich finde irgendwie das Ticket nicht mehr. :roll_eyes:

Du müsstes die Geodaten vorher über einen Preprocessor laufen lassen. Dieser könnte dann das Dreieck temporär Mapnik übergeben, welcher es rendert. Oder man schriebt das Dreieck gleich in die Datenbank zurück. Der Preprocessor sollte dann aber so intelligent sein, das Dreieck nicht mehrfach anzulegen. Maxbe hatte Preprocessing schon gemacht.

Falls es das hier war ist es noch offen.

Danke auch für die beiden anderen Hinweise, ich werde es mir genauer ansehen, wenn ich daran weiterbastle - Ich habe jetzt aber erstmal keine Lust mehr dazu…

thx~ray

Ich habe noch keine Antwort dazu zu gelesen, daher meine.

In der …spatial… sind etliche Geokoordinatensysteme mit deren Parametern enthalten. Wenn von einem zu einem anderen Koordinatensystem konvertiert werden muß, wird auf diese Tabelle zugegriffen.

Die fehlende Zugriffsmöglichkeit war auch bei mir der Fall wg. eines zusätzclichen Accounts, daher mußt Du in psql in der zuständigen Datenbank (angemeldet mit postgres oder dem DB-Eigentümer Account) folgenden Befehl abgeben

grant select on table spatial_ref_sys to public;

Viele Grüße

Dietmar aka okilimu

Ich hatte mir selbst im Nachtrag desselben Postings geantwortet :wink:
Trotzdem Danke für die weiteren Erläuterungen - was “es” ist war mir bis eben noch nicht ganz klar.

mfg~ray