Rendering local names

As discussed on the mailing list, this thread is to collect information how to set up a map with local names i.e. Serbian cyrillic. Once successfull, it would be worth to summarise.

Basic setup:
PostgreSQL with PostGIS extension → Mapserver (renderer) → OpenLayers (Web Presentation)

So basically start with installing PostgeSQL, PostGIS, Mapserver. In case of Mapserver, I am not sure if all works with the new version 6.x. I have heart that it is not always downwardly compatible. For the beginning I would recommend Mapserver 5.6.x. There exist Debian packages for all.
You also need gdal and apache
So the following packages are required: mapserver-bin cgi-mapserver gdal-bin apache2 postgis postgresql

put a file called wms.wsgi in your apache root with the following


#!/usr/bin/python
# -*- coding: UTF-8 -*-
#
# Mapscript WMS server with default request parameters for josm
#
# to be used in conjunction with wsgi Interface
# 
# (c) 2009-2010 Sven Geggus <sven-osm@geggus.net>
#
# Released under the GNU GENERAL PUBLIC LICENSE
# http://www.gnu.org/copyleft/gpl.html
#
# $Id$
#

debug = 0
mapfile="/osm/mapserver/thomas.map"
tcopyright=" "

josmdefaults={'SERVICE': 'WMS', 'VERSION': '1.1.1', 'FORMAT':'image/png', 'REQUEST':'GetMap'}

import os,crypt,mapscript,sys,math,string,cgi
from time import *

# make our WMS also usable as TMS
def TileToMeters(tx, ty, zoom):
  initialResolution = 20037508.342789244 * 2.0 / 256.0
  originShift = 20037508.342789244
  tileSize = 256.0
  zoom2 = (2.0**zoom)
  res = initialResolution / zoom2
  mx = (res*tileSize*(tx+1))-originShift
  my = (res*tileSize*(zoom2-ty))-originShift
  return mx, my

# this will give the BBox Parameter from x,y,z
def TileToBBox(x,y,z):
  x1,y1=TileToMeters(x-1,y+1,z)
  x2,y2=TileToMeters(x,y,z) 
  return x1,y1,x2,y2

# generate a valid XML ServiceException message text
# from a simple textual error message
def SException(start_response,msg,code=""):
  xml = '<ServiceExceptionReport '
  xml += 'xmlns=\"http://www.opengis.net/ogc\" '
  xml += 'xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance" '
  xml += 'xsi:schemaLocation=\"http://www.opengis.net/ogc '
  xml += 'http://schemas.opengis.net/wms/1.1.1/OGC-exception.xsd\">\n'
  if code == "":
    xml += '  <ServiceException>\n  ' + msg
  else:
    xml += '  <ServiceException code=\"' + code +'\">\n  ' + msg
  xml += '\n  </ServiceException>\n</ServiceExceptionReport>\n'
  status = '200 OK'
  response_headers = [('Content-type', 'application/vnd.ogc.se_xml'),('Content-Length', str(len(xml)))]
  start_response(status, response_headers)
  return xml

# "main"
def application(env, start_response):
  
  global debug
  global tcopyright

  # read apaceh environment variables
  content_type = "text/plain"
  response_headers = dict([('Content-type', content_type)])

  url = "http://%s%s" % \
        (env['SERVER_NAME'],env['REQUEST_URI'])

  os.chdir(env['DOCUMENT_ROOT'])
  
  querystr = env['QUERY_STRING']
  try:
    uagent = env['HTTP_USER_AGENT']
  except:
    uagent = ''
  
  qupper=querystr.upper()
  
  # MAP=something in request is always an error  
  if "MAP=" in qupper:
    return SException(start_response,'Invalid argument "MAP=..." in request')

  # check for necessary queries
  if not "GETCAPABILITIES" in qupper and not ('LAYERS=' in qupper and (('BBOX=' in qupper and 'WIDTH=' in qupper and 'HEIGHT=' in qupper) or 'TILE=' in qupper)):
    return SException(start_response, 'Incomplete WMS request: Please specify "LAYERS", "BBOX", "WIDTH" & "HEIGHT" for WMS mode or "LAYERS" & "TILE=x,y,z" for TMS mode.')
  
  # if tile=something is given we are in TMS mode
    
  # parse QUERY_STRING
  query = cgi.parse_qsl(querystr)
  query = dict(query)
  
  msreq = mapscript.OWSRequest()

  query_layers=''
  tilemode=0
  # ad QUERY items into mapscript request object
  for key, value in query.items():
    key=key.upper()
    if (key == "DEBUG"):
      debug = 1
    if (key == "LAYERS"):
      query_layers=value
      if ("," in query_layers):
        return SException(start_response,'Multiple Layers are currently unsupported')
    if key != "TILE":
      msreq.setParameter(key,value)
    else:
      xyz=value.split(',')
      if (len(xyz) != 3):
        return SException(start_response,'Invalid argument "TILE=%s" in request, must be TILE=x,y,z' % value)
      try:
        x=int(xyz[0])
      except:
        return SException(start_response,'Invalid argument "TILE=%s" in request, must be TILE=x,y,z' % value)
      try:
        y=int(xyz[1])
      except:
        return SException(start_response,'Invalid argument "TILE=%s" in request, must be TILE=x,y,z' % value)
      try:
        z=int(xyz[2])
      except:
        return SException(start_response,'Invalid argument "TILE=%s" in request, must be TILE=x,y,z' % value)                                                                                                                                                      
      tilemode=1
  
  # we are in tilemode, lets add the required keys
  if (tilemode):
    msreq.setParameter("srs","EPSG:900913")
    msreq.setParameter("bbox","%f,%f,%f,%f" % TileToBBox(x,y,z))
    msreq.setParameter("width","256")
    msreq.setParameter("height","256")

  # add default QUERY items for use with JOSM
  # this will allow for easy to remember WMS Request-URLs
  if ("JOSM" in uagent) or (tilemode):
    for d in josmdefaults:
      if d not in qupper:
        msreq.setParameter(d,josmdefaults[d])

  map = mapscript.mapObj(mapfile)
  map.setMetaData("wms_onlineresource",url.split("?")[0])
  
  try:
    layer=map.getLayerByName(query_layers)
    cstring=layer.metadata.get('copyright')
  except:
    cstring=tcopyright
  
  clayer=map.getLayerByName("copyright")
  cclass=clayer.getClass(0)
  cclass.setText(cstring)
  
  # write a mapfile for debugging purposes
  if (debug):
    os.umask(022)
    map.save("/tmp/topomap.map")

  # write mapserver results to buffer
  mapscript.msIO_installStdoutToBuffer()
  try:
    res = map.OWSDispatch(msreq)
  except:
     return SException(start_response,str(sys.exc_info()[1]))

  # adjust content-type
  content_type = mapscript.msIO_stripStdoutBufferContentType()
    
  output=mapscript.msIO_getStdoutBufferBytes()
  
  # set Expire header to 100 days from now
  expire = strftime('%a, %d %b %Y %H:%M:%S %z',gmtime(time()+3600*24*100))   
  
  response_headers = [('Content-type', content_type),
                      ('Expires', expire),
                      ('Content-Length', str(len(output)))]
  status = '200 OK'
  start_response(status, response_headers)
  
  # write image data to stdout
  return output

Adjust path where you want to put the mapfile (where the rendering rules will be). Currently it points to mapfile=“/osm/mapserver/thomas.map”
try if it responds to …/wms?

How to import OSM data in database?

create a database as postgres user

createdb -E utf8 osm

Apply the Geospatial functions (check where the files are at you system) as user postgres
cat /usr/share/postgresql/9.0/contrib/postgis-1.5/postgis.sql | psql -d osm
cat /usr/share/postgresql/9.0/contrib/postgis-1.5/spatial_ref_sys.sql | psql -d osm

create a user in SQL as postgres user
psql -d osm
at the sql prompt run
create user “www-data” with password ‘www-data’;
logoff from sql with “\q”

get osm2pgsql
http://wiki.openstreetmap.org/wiki/Osm2pgsql

modify the osm2pgsql database shema
/usr/share/osm2pgsql/default.style
and add “node,way name:sr text linear”

get the data here
http://download.geofabrik.de/osm/

I suggest to start with Serbia first. Europe and World can take weeks on s slow machine.

import it with as postgres user
osm2pgsql -l -d osm -p osm -s -C 12000 /home/thomas/serbia.osm.bz2

with
-l importet in latlon
-d osm database name
-p osm database table name prefix
-s slim mode
-C 12000 use max 12G RAM (don’t use swap and let some RAM for other processes)

as user postgres try if everything works with for example
psql -d osm -c “SELECT extent(way) FROM osm_line”
psql -d osm -c “SELECT * FROM osm_line limit 10;”

check if you have a file with the projection definition /usr/share/proj/epsg and check that it has a definition for 900913
if not add
<900913> +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

What about software called Marble? Ir renders local names automatically…

Zanimljiv prevod
http://translate.google.com/?hl=en#auto|sr|render

To i jeste jedno od značenja: http://dictionary.reference.com/browse/render