Mapnik - eigenen Text rendern

Hallo zusammen,

mal ne Frage an die Mapnik-Profis…

Ist es eigentlich möglich, mit Mapnik eigenen, freien Text zu rendern.

Will sagen, ich möchte zum Beispiel an einem Wanderweg nicht den hinterlegten Namen über

<TextSymbolizer ... >[name]</TextSymbolizer>

darstellen, sondern da soll dann “Highway to Hell” oder sowas stehen.

Geht das?

Wenn ja, wie?

Gruß
Andreas

Es gibt bestimmt verschiedene Wege - diesen würde ich gehen, da SQL kein Geheimnis für mich ist:

Mapnik besorgt sich die Daten per SQL-Query aus der Datenbank. Dort brauchst du “nur” die Abfrage so anzupassen, dass für bestimmte Objekte die von dir gewünschten Texte rauskommen.
Machbar wäre das durch die case-Klausel in der Sql-Abfrage. Macht aber nur Sinn für wenige Objekte (<10 ?)

Gruss
walter

oder noch einfacher: Nach dem Import (osm2pgsql ?) Texte in DB ändern (kleiner Script mit sql-update-Befehlen). danach ganz normal weitermachen.

Hallo Walter,

puh, die sql-Thematik ist so gar nicht meins…

Vielleicht kannst du mir konkret bei folgendem Beispiel mal helfen?

Ich habe mir eine eigene xml-Datei erstellt, um die verschiedenen Schwierigkeitsgrade von Wanderwegen über verschiedene Farben darzustellen.
An diesen Wege soll nun der Schwierigkeitsgrad (sac_scale) als Text dargestellt werden, allerdings als T1 - T6 und nicht als hiking, mountain_hiking, alpine_hiking etc.

Der Style-Abschnitt für T1 sieht bei mir z.B. so aus

<Style name="sac-scale">   
    <!-- T1 -->
    <Rule>
	    <Filter>([highway] = 'footway' or [highway] = 'path' or [highway] = 'bridleway' or [highway] = 'track') 
		    and [sac_scale]='hiking' 
		    and (not [trail_visibility]='intermediate' 
		    and not [trail_visibility]='horrible' 
		    and not [trail_visibility]='bad' 
		    and not [trail_visibility]='no')
	    </Filter>
	    &maxscale_zoom13;
	    <LineSymbolizer stroke-linejoin="round" stroke-opacity="1" stroke="yellow" stroke-linecap="round" stroke-width="2"/>
            <TextSymbolizer fontset-name="book-fonts" size="9" fill="gray" placement="line" spacing="300">[sac_scale]</TextSymbolizer>
    </Rule>

Wie sähe denn dazu dann deine angesprochene sql-Abfrage im Layer-Abschnitt aus, damit an diesen Wegen T1 steht?

<Layer name="sac-scale" status="on" srs="&osm2pgsql_projection;">
    <StyleName>sac-scale</StyleName>
    <Datasource>
      <Parameter name="table">
      (select way,highway,sac_scale ???
      ...

Gruß
Andreas

obige Zeile in sowas ändern:


(select way,highway,case when sac_scale='hiking' then 'T1'
                         when sac_scale='mountain' then 'T2'
                         when ... 
                    end
    ....)

wenn das noch unklar sein sollte, mach mal diesen Block etwas länger, damit ich die Umgebung sehe.

Syntax siehe http://www.postgresql.org/docs/9.2/static/functions-conditional.html

Gruss
walter

Hallo Walter,

habe deinen Vorschlag mal probiert. Leider ohne Erfolg…

Der layer-Eintrag sieht jetzt bei mir so aus:

<Layer name="sac-scale" status="on" srs="&osm2pgsql_projection;">
    <StyleName>sac-scale</StyleName>
    <Datasource>
      <Parameter name="table">
      (select way,highway,
      case when sac_scale='hiking' then 'T1' end
      from &prefix;_line
          where highway is not null
          order by z_order) as roads
      </Parameter>
      &datasource-settings;
    </Datasource>
  </Layer>

Das Ganze führt dann hierzu:

render_tiles( (10.0, 47.23, 10.4, 47.45) sac-scale.xml tiles/sac/ 14 15 sac_scale)
Exception in thread Thread-3:
Traceback (most recent call last):
  File "/usr/lib/python2.7/threading.py", line 551, in __bootstrap_inner
    self.run()
  File "/usr/lib/python2.7/threading.py", line 504, in run
    self.__target(*self.__args, **self.__kwargs)
  File "./sac_scale.py", line 116, in loop
    self.render_tile(tile_uri, x, y, z)
  File "./sac_scale.py", line 98, in render_tile
    mapnik.render(self.m, im)
RuntimeError: Postgis Plugin: PSQL error:
ERROR:  column "sac_scale" does not exist
LINE 1: SELECT ST_AsBinary("way") AS geom,"highway","sac_scale","tra...
                                                    ^
Full sql was: 'SELECT ST_AsBinary("way") AS geom,"highway","sac_scale","trail_visibility","tunnel" FROM (select way,highway,
      case when sac_scale='hiking' then 'T1' end
      from planet_line
          where highway is not null
          order by z_order) as roads WHERE "way" && ST_SetSRID('BOX3D(1112923.131832166 6012230.896798821,1115369.116737292 6014676.881703949)'::box3d, 900913)'


Exception in thread Thread-4:
Traceback (most recent call last):
  File "/usr/lib/python2.7/threading.py", line 551, in __bootstrap_inner
    self.run()
  File "/usr/lib/python2.7/threading.py", line 504, in run
    self.__target(*self.__args, **self.__kwargs)
  File "./sac_scale.py", line 116, in loop
    self.render_tile(tile_uri, x, y, z)
  File "./sac_scale.py", line 98, in render_tile
    mapnik.render(self.m, im)
RuntimeError: Postgis Plugin: PSQL error:
ERROR:  column "sac_scale" does not exist
LINE 1: SELECT ST_AsBinary("way") AS geom,"highway","sac_scale","tra...
                                                    ^
Full sql was: 'SELECT ST_AsBinary("way") AS geom,"highway","sac_scale","trail_visibility","tunnel" FROM (select way,highway,
      case when sac_scale='hiking' then 'T1' end
      from planet_line
          where highway is not null
          order by z_order) as roads WHERE "way" && ST_SetSRID('BOX3D(1112923.131832166 6007338.926988571,1115369.116737292 6009784.911893697)'::box3d, 900913)'


Exception in thread Thread-1:
Traceback (most recent call last):
  File "/usr/lib/python2.7/threading.py", line 551, in __bootstrap_inner
    self.run()
  File "/usr/lib/python2.7/threading.py", line 504, in run
    self.__target(*self.__args, **self.__kwargs)
  File "./sac_scale.py", line 116, in loop
    self.render_tile(tile_uri, x, y, z)
  File "./sac_scale.py", line 98, in render_tile
    mapnik.render(self.m, im)
RuntimeError: Postgis Plugin: PSQL error:
ERROR:  column "sac_scale" does not exist
LINE 1: SELECT ST_AsBinary("way") AS geom,"highway","sac_scale","tra...
                                                    ^
Full sql was: 'SELECT ST_AsBinary("way") AS geom,"highway","sac_scale","trail_visibility","tunnel" FROM (select way,highway,
      case when sac_scale='hiking' then 'T1' end
      from planet_line
          where highway is not null
          order by z_order) as roads WHERE "way" && ST_SetSRID('BOX3D(1112923.131832166 6009784.911893696,1115369.116737292 6012230.896798821)'::box3d, 900913)'


Exception in thread Thread-2:
Traceback (most recent call last):
  File "/usr/lib/python2.7/threading.py", line 551, in __bootstrap_inner
    self.run()
  File "/usr/lib/python2.7/threading.py", line 504, in run
    self.__target(*self.__args, **self.__kwargs)
  File "./sac_scale.py", line 116, in loop
    self.render_tile(tile_uri, x, y, z)
  File "./sac_scale.py", line 98, in render_tile
    mapnik.render(self.m, im)
RuntimeError: Postgis Plugin: PSQL error:
ERROR:  column "sac_scale" does not exist
LINE 1: SELECT ST_AsBinary("way") AS geom,"highway","sac_scale","tra...
                                                    ^
Full sql was: 'SELECT ST_AsBinary("way") AS geom,"highway","sac_scale","trail_visibility","tunnel" FROM (select way,highway,
      case when sac_scale='hiking' then 'T1' end
      from planet_line
          where highway is not null
          order by z_order) as roads WHERE "way" && ST_SetSRID('BOX3D(1112923.131832166 6014676.881703947,1115369.116737292 6017122.866609074)'::box3d, 900913)'


Das Terminal bleibt hängen und das wars…

Dass die Wanderwege zumindest farbig dargestellt werden, funktioniert mit folgender layer-Angabe:

<Layer name="sac-scale" status="on" srs="&osm2pgsql_projection;">
    <StyleName>sac-scale</StyleName>
    <Datasource>
      <Parameter name="table">
      (select way,highway,sac_scale,trail_visibility,
       case when tunnel in ('yes','true','1') then 'yes'::text else tunnel end as tunnel,
       case when bridge in ('yes','true','1') then 'yes'::text else bridge end as bridge
      from &prefix;_line
          where highway is not null
          order by z_order) as roads
      </Parameter>
      &datasource-settings;
    </Datasource>
  </Layer>

Hänge ich deine case-Abfrage noch zusätzlich dort hinein, wird zwar gerendert, aber es steht weiterhin hiking, mountain_hiking, alpine_hiking etc. an den Wegen.

Irgendwelche Ideen?

Gruß
Andreas

versuch es mal mit
case when sac_scale=‘hiking’ then ‘T1’ else sac_scale end as “sac_scale”

das sollte hiking in T1 umwandeln und den Rest so lassen. Wenn die Syntax stimmt, musst du natürlich die anderen when auch noch reinhängen.

ansonsten muß ich passen, da ich derzeit nicht rendere und das nicht testen kann.

Hallo Walter,

mit deinem neuen Vorschlag hat es zunächst auch nicht geklappt.

Bin dann den Umweg gegangen und habe einen neuen Style für den Text erstellt

<Style name="sac-text">   
    <Rule>
      <Filter>([highway] = 'footway' or [highway] = 'path' or [highway] = 'bridleway' or [highway] = 'track') </Filter>
      &maxscale_zoom13;
      <TextSymbolizer minimum-padding="10" fontset-name="book-fonts" size="9" fill="black" halo-radius="2" placement="line" spacing="300">[sac_scale]</TextSymbolizer>
    </Rule>
</Style>

und diesen dann in einem eigenen, neuen layer gerendert

<Layer name="sac-text" status="on" srs="&osm2pgsql_projection;">
    <StyleName>sac-text</StyleName>
    <Datasource>
      <Parameter name="table">
      (select way,highway,
       case when sac_scale='hiking' then 'T1' else sac_scale end as sac_scale
       ... usw. bis T6 ...
      from &prefix;_line) as "sac_scale"
      </Parameter>
      &datasource-settings;
    </Datasource>
  </Layer>

Und siehe da, es klappt.
Warum es nicht über einen einzigen layer geht, weiß ich nicht…

Danke nochmal für deine Hilfe!

Gruß
Andreas