[Thuban-commits] r2865 - in branches/WIP-pyshapelib-Unicode/thuban: . Doc/technotes Examples/simple_extensions Extensions Extensions/bboxdump Extensions/export_shapefile Extensions/gMapTiles Extensions/gMapTiles/sample Extensions/gMapTiles/test Extensions/gns2shp Extensions/gns2shp/test Extensions/importAPR Extensions/importMP Extensions/importMP/test Extensions/mouseposition Extensions/ogr Extensions/ogr/test Extensions/svgexport Extensions/svgexport/test Extensions/umn_mapserver Extensions/umn_mapserver/test Extensions/wms Resources/XML Thuban Thuban/Lib Thuban/Model Thuban/UI libraries/pyshapelib test

scm-commit@wald.intevation.org scm-commit at wald.intevation.org
Fri Sep 5 21:46:02 CEST 2008


Author: bramz
Date: 2008-09-05 21:45:58 +0200 (Fri, 05 Sep 2008)
New Revision: 2865

Added:
   branches/WIP-pyshapelib-Unicode/thuban/Extensions/gMapTiles/
   branches/WIP-pyshapelib-Unicode/thuban/Extensions/gMapTiles/README.txt
   branches/WIP-pyshapelib-Unicode/thuban/Extensions/gMapTiles/__init__.py
   branches/WIP-pyshapelib-Unicode/thuban/Extensions/gMapTiles/exportGMapTiles.py
   branches/WIP-pyshapelib-Unicode/thuban/Extensions/gMapTiles/exporter.py
   branches/WIP-pyshapelib-Unicode/thuban/Extensions/gMapTiles/sample/
   branches/WIP-pyshapelib-Unicode/thuban/Extensions/gMapTiles/sample/README.txt
   branches/WIP-pyshapelib-Unicode/thuban/Extensions/gMapTiles/sample/sample.html
   branches/WIP-pyshapelib-Unicode/thuban/Extensions/gMapTiles/sample/tile.py
   branches/WIP-pyshapelib-Unicode/thuban/Extensions/gMapTiles/test/
   branches/WIP-pyshapelib-Unicode/thuban/Extensions/gMapTiles/test/test_gMapTileExport.py
   branches/WIP-pyshapelib-Unicode/thuban/Extensions/gns2shp/README
   branches/WIP-pyshapelib-Unicode/thuban/Extensions/importMP/
   branches/WIP-pyshapelib-Unicode/thuban/Extensions/importMP/README
   branches/WIP-pyshapelib-Unicode/thuban/Extensions/importMP/__init__.py
   branches/WIP-pyshapelib-Unicode/thuban/Extensions/importMP/importMP.py
   branches/WIP-pyshapelib-Unicode/thuban/Extensions/importMP/pfm.py
   branches/WIP-pyshapelib-Unicode/thuban/Extensions/importMP/test/
   branches/WIP-pyshapelib-Unicode/thuban/Extensions/importMP/test/snippets.py
   branches/WIP-pyshapelib-Unicode/thuban/Extensions/importMP/test/test_pfm.py
   branches/WIP-pyshapelib-Unicode/thuban/test/test_mapservpostgis.py
Modified:
   branches/WIP-pyshapelib-Unicode/thuban/
   branches/WIP-pyshapelib-Unicode/thuban/ChangeLog
   branches/WIP-pyshapelib-Unicode/thuban/Doc/technotes/release_process.txt
   branches/WIP-pyshapelib-Unicode/thuban/Examples/simple_extensions/
   branches/WIP-pyshapelib-Unicode/thuban/Extensions/
   branches/WIP-pyshapelib-Unicode/thuban/Extensions/bboxdump/
   branches/WIP-pyshapelib-Unicode/thuban/Extensions/export_shapefile/
   branches/WIP-pyshapelib-Unicode/thuban/Extensions/gns2shp/
   branches/WIP-pyshapelib-Unicode/thuban/Extensions/gns2shp/gns2shp.py
   branches/WIP-pyshapelib-Unicode/thuban/Extensions/gns2shp/test/README
   branches/WIP-pyshapelib-Unicode/thuban/Extensions/gns2shp/test/ls.txt
   branches/WIP-pyshapelib-Unicode/thuban/Extensions/gns2shp/test/test_gns2shp.py
   branches/WIP-pyshapelib-Unicode/thuban/Extensions/importAPR/
   branches/WIP-pyshapelib-Unicode/thuban/Extensions/mouseposition/
   branches/WIP-pyshapelib-Unicode/thuban/Extensions/ogr/
   branches/WIP-pyshapelib-Unicode/thuban/Extensions/ogr/test/
   branches/WIP-pyshapelib-Unicode/thuban/Extensions/svgexport/
   branches/WIP-pyshapelib-Unicode/thuban/Extensions/svgexport/test/
   branches/WIP-pyshapelib-Unicode/thuban/Extensions/umn_mapserver/
   branches/WIP-pyshapelib-Unicode/thuban/Extensions/umn_mapserver/mapfile.py
   branches/WIP-pyshapelib-Unicode/thuban/Extensions/umn_mapserver/mf_export.py
   branches/WIP-pyshapelib-Unicode/thuban/Extensions/umn_mapserver/mf_handle.py
   branches/WIP-pyshapelib-Unicode/thuban/Extensions/umn_mapserver/mf_import.py
   branches/WIP-pyshapelib-Unicode/thuban/Extensions/umn_mapserver/test/test_mapserver.py
   branches/WIP-pyshapelib-Unicode/thuban/Extensions/wms/
   branches/WIP-pyshapelib-Unicode/thuban/Extensions/wms/__init__.py
   branches/WIP-pyshapelib-Unicode/thuban/Extensions/wms/layer.py
   branches/WIP-pyshapelib-Unicode/thuban/Extensions/wms/wms.py
   branches/WIP-pyshapelib-Unicode/thuban/NEWS
   branches/WIP-pyshapelib-Unicode/thuban/README
   branches/WIP-pyshapelib-Unicode/thuban/Resources/XML/thuban-1.1.dtd
   branches/WIP-pyshapelib-Unicode/thuban/Resources/XML/thuban-1.2.1.dtd
   branches/WIP-pyshapelib-Unicode/thuban/Thuban/
   branches/WIP-pyshapelib-Unicode/thuban/Thuban/Lib/
   branches/WIP-pyshapelib-Unicode/thuban/Thuban/Model/
   branches/WIP-pyshapelib-Unicode/thuban/Thuban/Model/load.py
   branches/WIP-pyshapelib-Unicode/thuban/Thuban/UI/
   branches/WIP-pyshapelib-Unicode/thuban/Thuban/UI/legend.py
   branches/WIP-pyshapelib-Unicode/thuban/Thuban/thuban_cfg.py
   branches/WIP-pyshapelib-Unicode/thuban/libraries/pyshapelib/shptreemodule.c
   branches/WIP-pyshapelib-Unicode/thuban/setup.py
   branches/WIP-pyshapelib-Unicode/thuban/test/
   branches/WIP-pyshapelib-Unicode/thuban/test/postgissupport.py
   branches/WIP-pyshapelib-Unicode/thuban/test/test_baserenderer.py
   branches/WIP-pyshapelib-Unicode/thuban/test/test_layer.py
   branches/WIP-pyshapelib-Unicode/thuban/test/test_save.py
Log:
Forward porting trunk rev (2834:2864] to WIP-pyshapelib-Unicode branch.


Property changes on: branches/WIP-pyshapelib-Unicode/thuban
___________________________________________________________________
Name: svn:ignore
   + *.pyc
*~



Modified: branches/WIP-pyshapelib-Unicode/thuban/ChangeLog
===================================================================
--- branches/WIP-pyshapelib-Unicode/thuban/ChangeLog	2008-08-08 23:39:11 UTC (rev 2864)
+++ branches/WIP-pyshapelib-Unicode/thuban/ChangeLog	2008-09-05 19:45:58 UTC (rev 2865)
@@ -1,3 +1,48 @@
+2008-007-24 Bernhard Reiter <bernhard at intevation.de>
+	
+	* NEWS: Added summary of changes since the 1.2.1 release. Fixed some
+	  typos.
+
+2008-007-24 Bernhard Reiter <bernhard at intevation.de>
+	
+	* Thuban/thuban_cfg.py: Enabled wms extension. 
+	*  Extensions/wms/__init__.py: Minor comment fix.
+
+2008-06-23  Didrik Pinte <dpinte at dipole-consulting.com>
+	* Extension/wms/__init__.py, wms.py, layer.py : copyright left to
+	Intevation.
+
+2008-06-19  Didrik Pinte <dpinte at dipole-consulting.com>
+	* Extension/wms/__init__.py, wms.py, layer.py : wms extension has been
+	update to use owslib 0.3. Extension is not stable but usable.
+
+2008-06-03  Bernhard Reiter <bernhard at intevation.de>
+
+	* test/test_baserenderer.py, testtest_layer.py: Give the
+	gdal_support_status if there is no gdal support. Gives a better hint
+	about why this is missing (e.g. no gdalwarp.so). Thanks to 
+	Anthony Lenton.
+
+2008-06-02  Bernhard Herzog  <bh at intevation.de>
+
+	* Resources/XML/thuban-1.2.1.dtd, Resources/XML/thuban-1.1.dtd:
+	Declare the attributes field and field_type of the element
+	classification as optional in the syntactically correct way.
+
+2008-05-23 Bernhard Reiter <bernhard at intevation.de>
+
+	* README: Added a hint that the requirements need to be installed
+	for building. Also added a section for installing, renaming the
+	former section to building.
+
+2008-04-18 Didrik Pinte <dpinte at dipole-consulting.com>
+
+	* Thuban/UI/legend.py : changed the use of wx.MemoryDC to 
+	wx.ScreenDC in order to allow compilation under Mac and wx 2.8
+
+	* libraries/pyshapelib/shptreemodule.c : bugfix coming from Debian
+	see http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=469007
+
 2008-02-14  Bernhard Reiter <bernhard at intevation.de>
 	
 	* Thuban/Model/table.py: Using internal_from_unicode() when reading
@@ -10,6 +55,15 @@
 	Given that the new dbflib should deal with unicode objects,
 	call dbf.add_field with an unicode object.
 
+2008-02-13 Bernhard Reiter <bernhard at intevation.de>
+
+	* test/test_save.py, Thuban/Model/load.py, setup.py: 
+	Mixed tabs and spaces indentation is bad, thus removed the tabs
+	from these inconsistant files.
+
+	* Doc/technotes/release_process.txt: Better use thuban-announce@
+	to announce. ;)
+
 2008-02-04	Bram de Greve <bram.degreve at bramz.net>
 
 	* Forward porting trunk (2819:2834] to WIP-pyshapelib-Unicode branch.

Modified: branches/WIP-pyshapelib-Unicode/thuban/Doc/technotes/release_process.txt
===================================================================
--- branches/WIP-pyshapelib-Unicode/thuban/Doc/technotes/release_process.txt	2008-08-08 23:39:11 UTC (rev 2864)
+++ branches/WIP-pyshapelib-Unicode/thuban/Doc/technotes/release_process.txt	2008-09-05 19:45:58 UTC (rev 2865)
@@ -91,7 +91,7 @@
     - Write announcement including all major improvements.
 
 Old:    - Send announcement to following mailing lists:
-      thuban-list at intevation.de
+      thuban-announce at intevation.de
       freegis-list at intevation.de
 
     - Have a beer and thank all contributors :-)


Property changes on: branches/WIP-pyshapelib-Unicode/thuban/Examples/simple_extensions
___________________________________________________________________
Name: svn:ignore
   + *.pyc
*~




Property changes on: branches/WIP-pyshapelib-Unicode/thuban/Extensions
___________________________________________________________________
Name: svn:ignore
   + *.pyc
*~




Property changes on: branches/WIP-pyshapelib-Unicode/thuban/Extensions/bboxdump
___________________________________________________________________
Name: svn:ignore
   + *.pyc
*~




Property changes on: branches/WIP-pyshapelib-Unicode/thuban/Extensions/export_shapefile
___________________________________________________________________
Name: svn:ignore
   + *.pyc
*~




Property changes on: branches/WIP-pyshapelib-Unicode/thuban/Extensions/gMapTiles
___________________________________________________________________
Name: svn:ignore
   + *.pyc
*~



Added: branches/WIP-pyshapelib-Unicode/thuban/Extensions/gMapTiles/README.txt
===================================================================
--- branches/WIP-pyshapelib-Unicode/thuban/Extensions/gMapTiles/README.txt	2008-08-08 23:39:11 UTC (rev 2864)
+++ branches/WIP-pyshapelib-Unicode/thuban/Extensions/gMapTiles/README.txt	2008-09-05 19:45:58 UTC (rev 2865)
@@ -0,0 +1,10 @@
+This extension generates 256x256px png tiles out of Thuban maps, to be able to
+overlay the data on Google Maps.
+
+The extension reprojects and chops the tiles accordingly so that the data
+matches Google's imagery.
+
+For now the extension only generates the tiles, you'll need to write your
+own javascript to use them.  Check the "sample/" subdirectory for a very simple
+way of viewing the data you generate.
+

Added: branches/WIP-pyshapelib-Unicode/thuban/Extensions/gMapTiles/__init__.py
===================================================================
--- branches/WIP-pyshapelib-Unicode/thuban/Extensions/gMapTiles/__init__.py	2008-08-08 23:39:11 UTC (rev 2864)
+++ branches/WIP-pyshapelib-Unicode/thuban/Extensions/gMapTiles/__init__.py	2008-09-05 19:45:58 UTC (rev 2865)
@@ -0,0 +1,22 @@
+# Copyright (c) 2008 by Intevation GmbH
+# Authors:
+# Anthony Lenton <anthony at except.com.ar>
+#
+# This program is free software under the GPL (>=v2)
+# Read the file COPYING coming with Thuban for details.
+
+# import the actual module
+import exportGMapTiles
+
+# perform the registration of the extension
+from Thuban import _
+from Thuban.UI.extensionregistry import ExtensionDesc, ext_registry
+
+ext_registry.add(ExtensionDesc(
+    name = 'exportGMapTiles',
+    version = '0.1.1',
+    authors= [ 'Anthony Lenton' ],
+    copyright = '2008 by Intevation GmbH',
+    desc = _("Export PNG tiles to be loaded with Google Maps\n" \
+             "as a GTileLayerOverlay.")))
+

Added: branches/WIP-pyshapelib-Unicode/thuban/Extensions/gMapTiles/exportGMapTiles.py
===================================================================
--- branches/WIP-pyshapelib-Unicode/thuban/Extensions/gMapTiles/exportGMapTiles.py	2008-08-08 23:39:11 UTC (rev 2864)
+++ branches/WIP-pyshapelib-Unicode/thuban/Extensions/gMapTiles/exportGMapTiles.py	2008-09-05 19:45:58 UTC (rev 2865)
@@ -0,0 +1,134 @@
+# Copyright (c) 2008 by Intevation GmbH
+# Authors:
+# Anthony Lenton <anthony at except.com.ar>
+#
+# This program is free software under the GPL (>=v2)
+# Read the file COPYING coming with Thuban for details.
+
+""" This module allows you to save your data as png files to be served as a
+    Google Maps layer overlay. """
+
+import os
+import wx
+
+if __name__ != '__main__':
+    from Thuban.UI.command import registry, Command
+    from Thuban import _
+    from Thuban.UI.mainwindow import main_menu
+    from Thuban.UI import internal_from_wxstring
+
+from exporter import export
+
+DEFAULT_DESTINATION_FOLDER = os.path.join (os.getcwd(), "tiles")
+
+class exportGMapTilesDialog(wx.Dialog):
+    def __init__(self, parent, ID, title,
+                 pos=wx.DefaultPosition, size=wx.DefaultSize,
+                 style=wx.DEFAULT_DIALOG_STYLE):
+                     
+        # initialize the Dialog
+        wx.Dialog.__init__(self, parent, ID, title, pos, size, style)
+
+        # Destination folder
+        box_folder = wx.BoxSizer(wx.HORIZONTAL)
+        box_folder.Add(wx.StaticText(self, -1, _("Destination folder:")), 1,
+                     wx.ALL|wx.ALIGN_LEFT|wx.ALIGN_CENTER_VERTICAL, 4)
+        self.text_folder = wx.TextCtrl(self, -1, DEFAULT_DESTINATION_FOLDER)
+        box_folder.Add(self.text_folder, 2, wx.ALL|wx.ALIGN_CENTER_VERTICAL, 4)
+        self.button_folder = wx.Button (self, -1, _("Choose folder"))
+        self.button_folder.Bind (wx.EVT_BUTTON, self.OnChooseFolder)
+        box_folder.Add(self.button_folder, 1,wx.ALL|wx.ALIGN_CENTER_VERTICAL, 4)
+
+        # Zoom levels
+        box_zoom = wx.BoxSizer (wx.HORIZONTAL)
+        box_zoom.Add (wx.StaticText (self, -1, _("Minimum Zoom:")), 0,
+                      wx.ALL|wx.ALIGN_LEFT|wx.ALIGN_CENTER_VERTICAL, 4)
+        self.minZoomSpin = wx.SpinCtrl (self, size=(60, -1), min=1, max=17)
+        self.Bind(wx.EVT_SPINCTRL, self.OnMinZoomChanged, self.minZoomSpin)
+        box_zoom.Add (self.minZoomSpin, 0, wx.ALL|wx.ALIGN_CENTER_VERTICAL, 4)
+        box_zoom.Add (wx.StaticText (self, -1, _("Maximum Zoom:")), 0,
+                      wx.ALL|wx.ALIGN_LEFT|wx.ALIGN_CENTER_VERTICAL, 4)
+        self.maxZoomSpin = wx.SpinCtrl (self, size=(60, -1), min=1, max=17)
+        self.Bind(wx.EVT_SPINCTRL, self.OnMaxZoomChanged, self.maxZoomSpin)
+        box_zoom.Add (self.maxZoomSpin, 0, wx.ALL|wx.ALIGN_CENTER_VERTICAL, 4)
+
+        #buttons
+        box_buttons = wx.BoxSizer(wx.HORIZONTAL)
+        button = wx.Button(self, wx.ID_OK, _("OK"))
+        box_buttons.Add(button, 0, wx.ALL, 5)
+        button = wx.Button(self, wx.ID_CANCEL, _("Cancel"))
+        box_buttons.Add(button, 0, wx.ALL, 5)
+        #set the button funcitons
+        self.Bind(wx.EVT_BUTTON, self.OnOK, id=wx.ID_OK)
+        self.Bind(wx.EVT_BUTTON, self.OnCancel, id=wx.ID_CANCEL)
+      
+        # compose the final dialog
+        top = wx.BoxSizer(wx.VERTICAL)
+        top.Add(box_folder, 0, wx.EXPAND |wx.ALL, 5)
+        top.Add(box_zoom, 0, wx.EXPAND |wx.ALL, 5)
+        top.Add(box_buttons, 0, wx.ALIGN_RIGHT)
+        
+        # final layout settings
+        self.SetSizer(top)
+        top.Fit(self)
+
+    def OnMinZoomChanged (self, event):
+        if self.maxZoomSpin.GetValue() < self.minZoomSpin.GetValue():
+            self.maxZoomSpin.SetValue(self.minZoomSpin.GetValue())
+
+    def OnMaxZoomChanged(self, event):
+        if self.minZoomSpin.GetValue() > self.maxZoomSpin.GetValue():
+            self.minZoomSpin.SetValue(self.maxZoomSpin.GetValue())
+
+    def OnChooseFolder (self, event):
+        dlg = wx.DirDialog(self, _("Select a folder to save the tiles in"), ".")
+        if dlg.ShowModal() == wx.ID_OK:
+            pfm_filename = internal_from_wxstring(dlg.GetPath())
+            self.text_folder.ChangeValue (pfm_filename)
+        dlg.Destroy()
+
+    def RunDialog(self):
+        self.ShowModal()
+        self.Destroy()
+
+    def endDialog(self, result):
+        self.result = result
+        if self.result is not None:
+            self.EndModal(wx.ID_OK)
+        else:
+            self.EndModal(wx.ID_CANCEL)
+        self.Show(False)
+
+    def OnOK(self, event):
+        self.result = "OK"
+        self.dataFolder = self.text_folder.GetValue()
+        self.minZoom = self.minZoomSpin.GetValue()
+        self.maxZoom = self.maxZoomSpin.GetValue()
+        self.endDialog(self.result)
+
+    def OnCancel(self, event):
+        self.endDialog(None)
+
+
+def export_gmap_dialog(context):
+    """ Select the destination folder and zoom levels needed.
+
+    context -- The Thuban context.
+    """
+    dlg = exportGMapTilesDialog(context.mainwindow, -1,
+                       _("Export Google Maps tiles"))
+    dlg.RunDialog()
+    if dlg.result == "OK":
+        export (context, dlg.minZoom, dlg.maxZoom, dlg.dataFolder)
+
+# register the new command
+registry.Add(Command('export-gmaptiles', _("(experimental) ") + _('Export GMap Tiles'),
+                     export_gmap_dialog, helptext=_('Export as Google Map tiles')))
+
+# find the extension menu (create it anew if not found)
+extensions_menu = main_menu.FindOrInsertMenu('extensions',
+                                               _('E&xtensions'))
+
+# finally add the new entry to the menu
+extensions_menu.InsertItem('export-gmaptiles')
+

Added: branches/WIP-pyshapelib-Unicode/thuban/Extensions/gMapTiles/exporter.py
===================================================================
--- branches/WIP-pyshapelib-Unicode/thuban/Extensions/gMapTiles/exporter.py	2008-08-08 23:39:11 UTC (rev 2864)
+++ branches/WIP-pyshapelib-Unicode/thuban/Extensions/gMapTiles/exporter.py	2008-09-05 19:45:58 UTC (rev 2865)
@@ -0,0 +1,162 @@
+import os
+import math
+import mapscript
+from Extensions.umn_mapserver.mf_export import thuban_to_map, add_circle_symbol
+from Extensions.umn_mapserver.mapfile import MF_Map
+from Thuban.Model.proj import Projection
+try:
+    from PythonMagick import Image
+    pythonMagick = True
+except:
+    print "Coultn't import PythonMagick.  gMapTile will call convert instead."
+    pythonMagick = False
+
+cmd = 'convert -crop 256x256+%d+%d %s/%d/model.png %s/%d/%d.%d.png'
+
+T = 2048 # Big Tile size
+
+# Port to Python of Google Map's javascript GMercatorClass
+class Mercator (object):
+    def __init__(self, zoom):
+        self.tileSize = 256
+        self.zoom = zoom
+        self.tiles = 2 ** zoom
+        self.circumference = self.tileSize * self.tiles
+        self.semi = self.circumference / 2
+        self.radius = self.circumference / (2 * math.pi)
+        self.fE = -1.0 * self.circumference / 2.0
+        self.fN = self.circumference / 2.0 
+
+    def longToX (self, degrees):
+        longitude = math.radians(degrees + 180)
+        return (self.radius * longitude)
+
+    def latToY (self, degrees):
+        latitude = math.radians(degrees)
+        y = self.radius/2.0 * math.log((1.0 + math.sin(latitude)) /
+                                           (1.0 - math.sin(latitude)))
+        return self.fN - y
+
+    def xToLong (self, x):
+        longRadians = x/self.radius
+        longDegrees = math.degrees(longRadians) - 180
+        rotations = math.floor((longDegrees + 180)/360)
+        longitude = longDegrees - (rotations * 360)
+        return longitude
+
+    def yToLat (self, y):
+        y = self.fN - y
+        latitude = ((math.pi / 2) -
+                    (2 * math.atan(math.exp(-1.0 * y / self.radius))))
+        return math.degrees(latitude)
+
+def generate (mf, pixtents, zoom, folder):
+    """ Generate an image of the map, and then
+        Chop up in to 256x256px tiles.  'mf' is the mapObj object completely
+        configured except for its size and extents.
+        'pixtents' is the extents to be shown, in projected (pixel)
+        coordinates.
+        'zoom' is the zoom level for the image.
+        'folder' is the folder to save the tiles. """
+    c = Mercator(zoom)
+    extents = [pixtents[0] - c.semi, c.semi - pixtents[1],
+               pixtents[2] - c.semi, c.semi - pixtents[3]]
+    mf.set_size (pixtents[2] - pixtents[0], pixtents[1] - pixtents[3])
+    mf.set_extent (extents)
+    img = mf._mf_map.draw()
+    png = img.save(folder+'/%d/model.png' % (zoom,))
+    xTile = pixtents[0] // 256
+    yTile = pixtents[3] // 256
+    width = pixtents[2] - pixtents[0]
+    height = pixtents[1] - pixtents[3]
+    i = xTile
+    x = 0
+    if pythonMagick:
+        img = Image(str(folder+"/%d/model.png" % (zoom,)))
+    while x < width:
+        y = 0
+        j = yTile
+        while y < height:
+            if pythonMagick:
+                img2 = Image(img)
+                img2.crop ('256x256+%d+%d' % (x, y))
+                img2.write (str(folder+"/%d/%d.%d.png" % (zoom, i, j)))
+            else:
+                c = cmd % (x, y, folder, zoom, folder, zoom, i, j)
+                os.system(c)
+            y += 256
+            j += 1
+        x += 256
+        i += 1
+
+def export (context, minZoom, maxZoom, dataFolder, filename=None):
+    """ Use the Thuban context to render the current map to gMapTiles.
+        All zoom levels between 'minZoom' and 'maxZoom' will be generated.
+        Tiles will be saved to 'dataFolder'.
+        If 'filename' is not None, the map will be generated from this mapfile,
+        instead of using 'context' (for testing only). """
+    if filename is None:
+        mf = MF_Map(mapscript.mapObj(""))
+        mf.set_size (60, 50) # Set some size for thuban_to_map not to fail
+        add_circle_symbol (mf)
+        thuban_to_map (context, mf)
+    else:
+        mf = MF_Map(mapscript.mapObj(filename))
+    # We need all layers to have a projection, assume that they're
+    # using un-projected (lat/long) coordinates.  Probably an exception
+    # should be raised instead
+    for lindex in range(mf._mf_map.numlayers):
+        l = mf._mf_map.getLayer(lindex)
+        if l.getProjection() == '':
+            l.setProjection("+proj=longlat +ellps=WGS84 +datum=WGS84 +no_defs")
+    mf.set_imagetype ('png')
+    mf._mf_map.imagecolor.setRGB(234, 234, 234)
+    mf._mf_map.transparent = 1
+    of = mapscript.outputFormatObj("GD/png")
+    of.transparent = 1
+    mf._mf_map.setOutputFormat (of)
+
+    if filename is None:
+        extents = context.mainwindow.canvas.map.BoundingBox() # Unprojected
+    else:
+        extents = mf.get_extent().get_rect()
+    if extents is None:
+        return
+    minx, miny, maxx, maxy = extents
+    for zoom in range(minZoom, maxZoom + 1):
+        try:
+            os.makedirs (os.path.join(dataFolder, str(zoom)))
+        except OSError:
+            pass # Lets assume that the directory already exists
+        coord = Mercator(zoom)
+        gMercator = ["proj=merc", "a=%f"%coord.radius, "b=%f"%coord.radius]
+        mf.set_projection (Projection(gMercator))
+        mminx = ((int(coord.longToX(minx))) // 256) * 256 # Projected (pixels)
+        mmaxx = ((int(coord.longToX(maxx)) + 255)// 256) * 256 - 1
+        mmaxy = ((int(coord.latToY(maxy))) // 256) * 256
+        mminy = ((int(coord.latToY(miny)) + 255)// 256) * 256 - 1
+        width = mmaxx - mminx
+        height = mminy - mmaxy
+        width = max (width, 1)
+        height = max (height, 1)
+        if width <= T and height < T:
+            pixtents = [mminx, mminy, mmaxx, mmaxy]
+            generate (mf, pixtents, zoom, dataFolder)
+        else:
+            x = mminx
+            while x < mmaxx:
+                y = mmaxy
+                while y < mminy:
+                    pixtents = [x, min(y + T - 1, mminy), min(x + T - 1, mmaxx), y]
+                    generate (mf, pixtents, zoom, dataFolder)
+                    y += T
+                x += T
+
+if __name__ == '__main__':
+    import sys
+    if len(sys.argv) <= 1:
+        print "-----\nUsage: python exporter.py <mapfile.map>"
+    else:
+        # Say, let's export only for zoom level seven.  I like seven.
+        export (None, 7, 7, 'tiles', sys.argv[-1])
+

Added: branches/WIP-pyshapelib-Unicode/thuban/Extensions/gMapTiles/sample/README.txt
===================================================================
--- branches/WIP-pyshapelib-Unicode/thuban/Extensions/gMapTiles/sample/README.txt	2008-08-08 23:39:11 UTC (rev 2864)
+++ branches/WIP-pyshapelib-Unicode/thuban/Extensions/gMapTiles/sample/README.txt	2008-09-05 19:45:58 UTC (rev 2865)
@@ -0,0 +1,20 @@
+This is a sample application of the gMapTiles extension.  To test this sample
+you need to:
+
+ * Use thuban to generate tiles for some data.
+
+ * Make tile.py accessible via web on your web server, and make sure that it has
+   execution permissions.  Let's say that the URL to tile.py is now
+   http://yourserver/tile.py.  If you open this URL in a web browser you should
+   see the message "Missing input arguments"
+
+ * Edit tile.py and replace the PATH_TO_TILES string constant for the absolute
+   path where you saved the tiles.
+
+ * Make sample.html accessible via web on your web server.  Edit sample.html
+   to use your own Google Maps API Key, and replace the URL_TO_TILE_PY string
+   constant with tile.py's absolute URL. (make sure your key is valid for the
+   sample's URL, more info, http://code.google.com/apis/maps/documentation/ )
+
+Enjoy!
+

Added: branches/WIP-pyshapelib-Unicode/thuban/Extensions/gMapTiles/sample/sample.html
===================================================================
--- branches/WIP-pyshapelib-Unicode/thuban/Extensions/gMapTiles/sample/sample.html	2008-08-08 23:39:11 UTC (rev 2864)
+++ branches/WIP-pyshapelib-Unicode/thuban/Extensions/gMapTiles/sample/sample.html	2008-09-05 19:45:58 UTC (rev 2865)
@@ -0,0 +1,48 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml" xmlns:v="urn:schemas-microsoft-com:vml">
+<head>
+  <meta http-equiv="content-type" content="text/html; charset=utf-8"/>
+  <title>Google Map Tiles Proof of concept</title>
+  <script src="http://maps.google.com/maps?file=api&amp;v=2.x&amp;key=[Insert your Google Maps API Key here]"
+          type="text/javascript">
+  </script>
+  <script type="text/javascript">
+
+var URL_TO_TILE_PY = "http://yourserver/tile.py";
+
+var map;
+
+function load() {
+	// Set up the initial map state.
+	if(document.implementation.hasFeature(
+	  "http://www.w3.org/TR/SVG11/feature#SVG","1.1")){ 
+		_mSvgEnabled = true;
+		_mSvgForced  = true;
+	}
+	map = new GMap2(document.getElementById("map"));
+	map.addControl(new GLargeMapControl());
+	map.addControl(new GMapTypeControl());
+	var omc = new GOverviewMapControl();
+	map.addControl(omc);
+	map.setCenter(new GLatLng(-42.423457,-60.292969),4);
+
+    var tilelayer = new GTileLayer(new GCopyrightCollection(), 0, 17);
+    tilelayer.getTileUrl = function(tile, zoom) {
+        var url = URL_TO_TILE_PY + "?x="+tile.x+"&y="+tile.y+"&z="+zoom;
+        //alert ("Called getTileUrl ("+tile.x+"/"+tile.y+", "+zoom+")\nReturning: " + url);
+        return url;
+    };
+    tilelayer.getOpacity = function() {return 0.6;}
+    map.addOverlay(new GTileLayerOverlay(tilelayer));
+
+}
+
+  </script>
+</head>
+<body onload="load()" onunload="GUnload()">
+<h2>The Map</h2>
+<div id="map" style="width: 800px; height: 500px"></div>
+</body>
+</html>
+

Added: branches/WIP-pyshapelib-Unicode/thuban/Extensions/gMapTiles/sample/tile.py
===================================================================
--- branches/WIP-pyshapelib-Unicode/thuban/Extensions/gMapTiles/sample/tile.py	2008-08-08 23:39:11 UTC (rev 2864)
+++ branches/WIP-pyshapelib-Unicode/thuban/Extensions/gMapTiles/sample/tile.py	2008-09-05 19:45:58 UTC (rev 2865)
@@ -0,0 +1,32 @@
+#!/usr/bin/python
+import cgi
+import cgitb
+cgitb.enable()
+import cStringIO
+
+PATH_TO_TILES = "/path/to/tiles"
+
+size = 256 #image width and height
+
+def getTile(x, y, z):
+    z = int(z)
+    y = int(y)
+    x = int(x)
+    
+    try:
+        f = open('%s/%d/%d.%d.png' % (PATH_TO_TILES, z, x, y))
+    except IOError:
+        print "Content-type: text/plain\n\nNothing"
+        return
+
+    print "Content-type: image/png\n"
+    print f.read()
+
+if __name__ == "__main__":
+    form = cgi.FieldStorage()
+    if "x" in form and "y" in form and "z" in form:
+        getTile(form["x"].value, form["y"].value, form["z"].value)
+    else:
+        print "Content-type: text/html\n"
+        print """<html><body>Missing input arguments</body></html>"""
+

Added: branches/WIP-pyshapelib-Unicode/thuban/Extensions/gMapTiles/test/test_gMapTileExport.py
===================================================================
--- branches/WIP-pyshapelib-Unicode/thuban/Extensions/gMapTiles/test/test_gMapTileExport.py	2008-08-08 23:39:11 UTC (rev 2864)
+++ branches/WIP-pyshapelib-Unicode/thuban/Extensions/gMapTiles/test/test_gMapTileExport.py	2008-09-05 19:45:58 UTC (rev 2865)
@@ -0,0 +1,59 @@
+import unittest
+import os, sys
+from Thuban.Model.layer import Layer
+from Thuban.Model.map import Map
+from Thuban.Model.session import Session
+from Thuban.UI.context import Context
+from Thuban.Lib.connector import ConnectorError
+
+mapscriptAvailable=True
+try:
+    import mapscript
+    from Extensions.gMapTiles.exporter import export
+except ImportError:
+    mapscriptAvailable=False
+
+def rm_rf(d):
+    for path in (os.path.join(d,f) for f in os.listdir(d)):
+        if os.path.isdir(path):
+            rm_rf(path)
+        else:
+            os.unlink(path)
+    os.rmdir(d)
+
+class DummyMainWindow(object):
+    def __init__(self, canvas):
+        self.canvas = canvas
+
+class DummyCanvas(object):
+    def __init__(self, map):
+        self.map = map
+    def Map(self):
+        return self.map
+    def VisibleExtent (self):
+        return self.map.BoundingBox()
+
+class TestGMapTileExport(unittest.TestCase):
+    def setUp(self):
+        self.session = Session("A Session")
+        self.map = Map("A Map")
+        self.session.AddMap(self.map)
+        shapefile = "../../../Data/iceland/political.shp"
+        self.store = self.session.OpenShapefile(shapefile)
+        layer = Layer("A Layer", self.store)
+        self.map.AddLayer(layer)
+
+    def testExport(self):
+        tileDir = 'temp'
+        if not mapscriptAvailable:
+            #Skip test...
+            return
+        mainwindow = DummyMainWindow(DummyCanvas(self.map))
+        context = Context(None, self.session, mainwindow)
+        export (context, 7, 7, tileDir)
+        self.session.Destroy()
+        rm_rf(tileDir)
+
+if __name__ == "__main__":
+    unittest.main()
+


Property changes on: branches/WIP-pyshapelib-Unicode/thuban/Extensions/gns2shp
___________________________________________________________________
Name: svn:ignore
   + *.pyc
*~



Added: branches/WIP-pyshapelib-Unicode/thuban/Extensions/gns2shp/README
===================================================================
--- branches/WIP-pyshapelib-Unicode/thuban/Extensions/gns2shp/README	2008-08-08 23:39:11 UTC (rev 2864)
+++ branches/WIP-pyshapelib-Unicode/thuban/Extensions/gns2shp/README	2008-09-05 19:45:58 UTC (rev 2865)
@@ -0,0 +1,8 @@
+This extension converts Files of Geographic Names for Geopolitical Areas
+from GNS to Shapefile format.
+
+These files can be downloaded from
+http://earth-info.nga.mil/gns/html/cntry_files.html
+They are simple tab-separated value files.  A description of the meaning
+of each field can be found at
+http://earth-info.nga.mil/gns/html/gis_countryfiles.htm

Modified: branches/WIP-pyshapelib-Unicode/thuban/Extensions/gns2shp/gns2shp.py
===================================================================
--- branches/WIP-pyshapelib-Unicode/thuban/Extensions/gns2shp/gns2shp.py	2008-08-08 23:39:11 UTC (rev 2864)
+++ branches/WIP-pyshapelib-Unicode/thuban/Extensions/gns2shp/gns2shp.py	2008-09-05 19:45:58 UTC (rev 2865)
@@ -58,10 +58,11 @@
 
     shp = shapelib.create(shp_filename, shapelib.SHPT_POINT)
     dbf = dbflib.create(dbf_filename)
+
     dbf.add_field('RC', dbflib.FTInteger, 1, 0)
     dbf.add_field('UFI', dbflib.FTInteger, 10, 0)
     dbf.add_field('UNI', dbflib.FTInteger, 10, 0)
-    dbf.add_field('UTM', dbflib.FTString, 4, 0)
+    dbf.add_field('MGRS', dbflib.FTString, 15, 0)
     dbf.add_field('JOG', dbflib.FTString, 7, 0)
     dbf.add_field('FC', dbflib.FTString, 1, 0)
     dbf.add_field('DSG', dbflib.FTString, 5, 0)
@@ -69,10 +70,11 @@
     dbf.add_field('CC1', dbflib.FTString, 2, 0)
     dbf.add_field('ADM1', dbflib.FTString, 2, 0)
     dbf.add_field('ADM2', dbflib.FTString, 200, 0)
-    dbf.add_field('DIM', dbflib.FTInteger, 10, 0)
+    dbf.add_field('POP', dbflib.FTInteger, 10, 0)
+    dbf.add_field('ELEV', dbflib.FTInteger, 10, 0)
     dbf.add_field('CC2', dbflib.FTString, 2, 0)
-    dbf.add_field('NT', dbflib.FTString, 1, 0)
-    dbf.add_field('LC', dbflib.FTString, 2, 0)
+    dbf.add_field('NT', dbflib.FTString, 2, 0)
+    dbf.add_field('LC', dbflib.FTString, 3, 0)
     dbf.add_field('SHORT_FORM', dbflib.FTString, 128, 0)
     dbf.add_field('GENERIC', dbflib.FTString, 128, 0)
     dbf.add_field('SORT_NAME', dbflib.FTString, 200, 0)
@@ -87,30 +89,32 @@
     i = 0
     for line in gns:
         if line[0] == '#': continue
-        RC, UFI, UNI, DD_LAT, DD_LONG, DMS_LAT, DMS_LONG, UTM, \
-            JOG, FC, DSG, PC, CC1, ADM1, ADM2, DIM, CC2, NT, LC, \
-            SHORT_FORM, GENERIC, SORT_NAME, FULL_NAME, FULL_NAME_ND, \
-            MODIFY_DATE  = line.split('\t')
-        RC = int(RC)
+        RC, UFI, UNI, LAT, LONG, DMS_LAT, DMS_LONG, MGRS, JOG, FC, DSG, PC, \
+            CC1, ADM1, ADM2, POP, ELEV, CC2, NT, LC, SHORT_FORM, GENERIC, \
+            SORT_NAME, FULL_NAME, FULL_NAME_ND, MODIFY_DATE = line.split('\t')
+        try: RC = int(RC)
+        except ValueError: RC = None
         UFI = int(UFI)
         UNI = int(UNI)
-        DD_LAT = float(DD_LAT)
-        DD_LONG = float(DD_LONG)
+        LAT = float(LAT)
+        LONG = float(LONG)
         try: PC = int(PC)
-        except: PC = None
-        try: DIM = int(DIM)
-        except: DIM = None
+        except ValueError: PC = None
+        try: POP = int(POP)
+        except ValueError: POP = None
+        try: ELEV = int(ELEV)
+        except ValueError: ELEV = None
         MODIFY_DATE = MODIFY_DATE[0:10] # kill trailing "\n" or "\r\n"
-        obj = shapelib.SHPObject(shapelib.SHPT_POINT, i, [[(DD_LONG, DD_LAT)]])
+        obj = shapelib.SHPObject(shapelib.SHPT_POINT, i, [[(LONG, LAT)]])
         shp.write_object(-1, obj)
-        dbf.write_record(i, { 'RC': RC, 'UFI': UFI, 'UNI': UNI, 'UTM': UTM,
-                              'JOG': JOG, 'FC': FC, 'DSG': DSG, 'PC': PC,
-                              'CC1': CC1, 'ADM1': ADM1, 'ADM2': ADM2,
-                              'DIM': DIM, 'CC2': CC2, 'NT': NT, 'LC': LC,
-                              'SHORT_FORM': SHORT_FORM, 'GENERIC': GENERIC,
-                              'SORT_NAME': SORT_NAME, 'FULL_NAME': FULL_NAME,
-                              'FULL_ND': FULL_NAME_ND,
-                              'MODIFY_DAT': MODIFY_DATE})
+
+        vals = {'RC': RC, 'UFI': UFI, 'UNI': UNI, 'MGRS':MGRS, 'JOG': JOG,
+                'FC': FC, 'DSG': DSG, 'PC': PC, 'CC1': CC1, 'ADM1': ADM1,
+                'ADM2': ADM2, 'POP': POP, 'ELEV': ELEV, 'CC2': CC2, 'NT': NT,
+                'LC': LC, 'SHORT_FORM': SHORT_FORM, 'GENERIC': GENERIC,
+                'SORT_NAME': SORT_NAME, 'FULL_NAME': FULL_NAME,
+                'FULL_ND': FULL_NAME_ND, 'MODIFY_DAT': MODIFY_DATE}
+        dbf.write_record(i, vals)
         i += 1
 
     del shp

Modified: branches/WIP-pyshapelib-Unicode/thuban/Extensions/gns2shp/test/README
===================================================================
--- branches/WIP-pyshapelib-Unicode/thuban/Extensions/gns2shp/test/README	2008-08-08 23:39:11 UTC (rev 2864)
+++ branches/WIP-pyshapelib-Unicode/thuban/Extensions/gns2shp/test/README	2008-09-05 19:45:58 UTC (rev 2865)
@@ -1,4 +1,4 @@
-This directory contains tests of the gns2shl extension.
+This directory contains tests of the gns2shp extension.
 
 About file "ls.txt":
 

Modified: branches/WIP-pyshapelib-Unicode/thuban/Extensions/gns2shp/test/ls.txt
===================================================================
--- branches/WIP-pyshapelib-Unicode/thuban/Extensions/gns2shp/test/ls.txt	2008-08-08 23:39:11 UTC (rev 2864)
+++ branches/WIP-pyshapelib-Unicode/thuban/Extensions/gns2shp/test/ls.txt	2008-09-05 19:45:58 UTC (rev 2865)
@@ -1,89 +1,110 @@
-RC	UFI	UNI	DD_LAT	DD_LONG	DMS_LAT	DMS_LONG	UTM	JOG	FC	DSG	PC	CC1	ADM1	ADM2	DIM	CC2	NT	LC	SHORT_FORM	GENERIC	SORT_NAME	FULL_NAME	FULL_NAME_ND	MODIFY_DATE
-1	-1187145	-1749126	47.0666667	9.5000000	470400	93000	NT31	NL32-02	A	ADM1 		LS	00				N				BALZERS	Balzers	Balzers	1993-12-22
-1	-1187146	-1749127	47.0666667	9.5000000	470400	93000	NT31	NL32-02	P	PPL		LS	00				N				BALZERS	Balzers	Balzers	1993-12-22
-1	-1187147	-1749128	47.2166667	9.5000000	471300	93000	NT32	NL32-02	P	PPL		LS	00				N				BENDERN	Bendern	Bendern	1993-12-22
-1	-1187148	-1749129	47.0666667	9.6166667	470400	93700	NT41	NL32-02	T	PASS 		LS	00				N				BETTLERJOCH	Bettlerjoch	Bettlerjoch	1993-12-22
-1	-1187170	-1749130	47.1833333	9.5333333	471100	93200	NT42	NL32-02	P	PPL		LS	00				V				BLANKEN	Blanken	Blanken	1993-12-22
-1	-1187149	-1749131	47.1666667	9.5500000	471000	93300	NT42	NL32-02	T	MTS		LS	00				N				DREISCHWESTERN	Drei Schwestern	Drei Schwestern	1993-12-22
-1	-1187149	-1749132	47.1666667	9.5500000	471000	93300	NT42	NL32-02	T	MTS		LS	00				V				DREYSCHWESTERN	Drey Schwestern	Drey Schwestern	1993-12-22
-1	419575	535546	47.1500000	9.5166667	470900	93100	NT32	NL32-02	P	PPL		LS	00				V				EBAHOLZ	Ebaholz	Ebaholz	1999-01-26
-1	419575	535575	47.1500000	9.5166667	470900	93100	NT32	NL32-02	P	PPL		LS	00				N				EBENHOLZ	Ebenholz	Ebenholz	1999-01-26
-1	-1187152	-1749133	47.0500000	9.5666667	470300	93400	NT41	NL32-02	T	MT		LS	00				V				ENDERLINHORN	Enderlin Horn	Enderlin Horn	1993-12-22
-1	-1187150	-1749134	47.2166667	9.5166667	471300	93100	NT32	NL32-02	A	ADM1 		LS	00				N				ESCHEN	Eschen	Eschen	1993-12-22
-1	-1187151	-1749135	47.2166667	9.5166667	471300	93100	NT32	NL32-02	P	PPL		LS	00				N				ESCHEN	Eschen	Eschen	1993-12-22
-1	-1187150	-1749136	47.2166667	9.5166667	471300	93100	NT32	NL32-02	A	ADM1 		LS	00				V				ESCHENNEDELN	Eschen-Nedeln	Eschen-Nedeln	1993-12-22
-1	-1187152	-1749137	47.0500000	9.5666667	470300	93400	NT41	NL32-02	T	MT		LS	00				N				FALKNIS	Falknis	Falknis	1993-12-22
-1	-1187152	-1749138	47.0500000	9.5666667	470300	93400	NT41	NL32-02	T	MT		LS	00				V				FALKNISHORN	Falknis Horn	Falknis Horn	1993-12-22
-1	-1187153	-1749139	47.2000000	9.5833333	471200	93500	NT42	NL32-02	T	MT		LS	00				N				FRASTANZERSAND	Frastanzer Sand	Frastanzer Sand	1993-12-22
-1	-1187154	-1749140	47.1333333	9.5500000	470800	93300	NT42	NL32-02	T	MT		LS	00				N				FURSTENSTEIG	Fürstensteig	Furstensteig	1993-12-22
-1	419573	535544	47.1333333	9.5333333	470800	93200	NT42	NL32-02	P	PPL		LS	00				N				GAFLEI	Gaflei	Gaflei	1999-01-26
-1	-1187155	-1749141	47.1500000	9.6166667	470900	93700	NT42	NL32-02	T	MT		LS	00				N				GALLINAKOPF	Gallinakopf	Gallinakopf	1993-12-22
-1	-1187157	-1749142	47.2166667	9.5000000	471300	93000	NT32	NL32-02	P	PPL		LS	00				V				GAMBRIN	Gambrin	Gambrin	1993-12-22
-1	-1187156	-1749143	47.2166667	9.5000000	471300	93000	NT32	NL32-02	A	ADM1 		LS	00				N				GAMPRIN	Gamprin	Gamprin	1993-12-22
-1	-1187157	-1749144	47.2166667	9.5000000	471300	93000	NT32	NL32-02	P	PPL		LS	00				N				GAMPRIN	Gamprin	Gamprin	1993-12-22
-1	-1187156	-1749145	47.2166667	9.5000000	471300	93000	NT32	NL32-02	A	ADM1 		LS	00				V				GAMPRINBENDERN	Gamprin-Bendern	Gamprin-Bendern	1993-12-22
-1	-1187158	-1749146	47.1666667	9.5666667	471000	93400	NT42	NL32-02	T	MT		LS	00				N				GARSELLAKOPF	Garsellakopf	Garsellakopf	1993-12-22
-1	-1187160	-1749147	47.0500000	9.5833333	470300	93500	NT41	NL32-02	T	PK		LS	00				V				GRAUSPITZ	Grauspitz	Grauspitz	1993-12-22
-1	-1187192	-1749148	47.0500000	9.5833333	470300	93500	NT41	NL32-02	T	PK		LS	00				V				GRAUSPITZ	Grauspitz	Grauspitz	1993-12-22
-1	-1187159	-1749149	47.2333333	9.5333333	471400	93200	NT43	NL32-02	P	PPLX 		LS	00				N				HINTERERSCHELLENBERG	Hinterer Schellenberg	Hinterer Schellenberg	1993-12-22
-1	-1187160	-1749150	47.0500000	9.5833333	470300	93500	NT41	NL32-02	T	PK		LS	00				N				HINTERGRAUSPITZ	Hinter-Grauspitz	Hinter-Grauspitz	1993-12-22
-1	419566	535536	47.0500000	9.5500000	470300	93300	NT41	NL32-02	T	VAL		LS	00				N				LAWENA	Lawena	Lawena	1999-01-26
-1	-1187161	-1749151	47.1666667	9.5333333	471000	93200	NT42	NL32-02	A	PCLI 		LS	00				V				LICHTENSTEIN	Lichtenstein	Lichtenstein	1996-11-29
-1	-1187161	-1749152	47.1666667	9.5333333	471000	93200	NT42	NL32-02	A	PCLI 		LS	00				V				LIECHTENSTEIN	Liechtenstein	Liechtenstein	1996-11-29
-1	-1187161	-1749154	47.1666667	9.5333333	471000	93200	NT42	NL32-02	A	PCLI 		LS	00				N	GM	Liechtenstein	Fürstentum	LIECHTENSTEIN FURSTENTUM	Fürstentum Liechtenstein	Furstentum Liechtenstein	1996-11-29
-1	-1187161	-1749153	47.1666667	9.5333333	471000	93200	NT42	NL32-02	A	PCLI 		LS	00				C		Liechtenstein		LIECHTENSTEIN PRINCIPALITYOF	Principality of Liechtenstein	Principality of Liechtenstein	1996-11-29
-1	419565	535533	47.0500000	9.5000000	470300	93000	NT31	NL32-02	P	PPL		LS	00				N				MALS	Mäls	Mals	1999-01-26
-1	419572	535543	47.1333333	9.5333333	470800	93200	NT42	NL32-02	P	PPL		LS	00				N				MASESCHA	Masescha	Masescha	1999-01-26
-1	-1187162	-1749155	47.1333333	9.6166667	470800	93700	NT42	NL32-02	T	PASS 		LS	00				V				MATLAJOCH	Matla Joch	Matla Joch	1994-04-28
-1	-1187162	-1749159	47.1333333	9.6166667	470800	93700	NT42	NL32-02	T	PASS 		LS	00			AU	N				MATLERJOCH	Matlerjoch	Matlerjoch	1994-04-28
-1	-1187181	-1749157	47.1333333	9.6333333	470800	93800	NT42	NL32-02	T	MT		LS	00				V				MATLERKOPF	Matler Kopf	Matler Kopf	1993-12-22
-1	-1187162	-1749158	47.1333333	9.6166667	470800	93700	NT42	NL32-02	T	PASS 		LS	00			LS	N				MATTAJOCH	Mattajoch	Mattajoch	1994-04-28
-1	-1187164	-1749160	47.2166667	9.5333333	471300	93200	NT42	NL32-02	P	PPL		LS	00				V				MAUERN	Mauern	Mauern	1993-12-22
-1	-1187163	-1749161	47.2166667	9.5333333	471300	93200	NT42	NL32-02	A	ADM1 		LS	00				N				MAUREN	Mauren	Mauren	1993-12-22
-1	-1187164	-1749162	47.2166667	9.5333333	471300	93200	NT42	NL32-02	P	PPL		LS	00				N				MAUREN	Mauren	Mauren	1993-12-22
-1	-1187163	-1749163	47.2166667	9.5333333	471300	93200	NT42	NL32-02	A	ADM1 		LS	00				V				MAURENSCHAANWALD	Mauren-Schaanwald	Mauren-Schaanwald	1993-12-22
-1	-1187165	-1749164	47.2333333	9.5333333	471400	93200	NT43	NL32-02	P	PPLX 		LS	00				N				MITTLERERSCHELLENBERG	Mittlerer Schellenberg	Mittlerer Schellenberg	1993-12-22
-1	419574	535545	47.1500000	9.5000000	470900	93000	NT32	NL32-02	P	PPL		LS	00				V				MOLIHOLZ	Möliholz	Moliholz	1999-01-26
-1	419574	535574	47.1500000	9.5000000	470900	93000	NT32	NL32-02	P	PPL		LS	00				N				MUHLEHOLZ	Mühleholz	Muhleholz	1999-01-26
-1	-1187166	-1749165	47.0500000	9.6000000	470300	93600	NT41	NL32-02	T	MT		LS	00				N				NAAFKOPF	Naafkopf	Naafkopf	1993-12-22
-1	-1187166	-1749166	47.0500000	9.6000000	470300	93600	NT41	NL32-02	T	MT		LS	00				V				NAUFKOPF	Nauf Kopf	Nauf Kopf	1993-12-22
-1	-1187167	-1749167	47.2000000	9.5500000	471200	93300	NT42	NL32-02	P	PPL		LS	00				N				NENDELN	Nendeln	Nendeln	1993-12-22
-1	-1187168	-1749168	47.1166667	9.6333333	470700	93800	NT41	NL32-02	T	MT		LS	00				V				OCHSENBERG	Ochsenberg	Ochsenberg	1993-12-22
-1	-1187168	-1749169	47.1166667	9.6333333	470700	93800	NT41	NL32-02	T	MT		LS	00				N				OCHSENKOPF	Ochsenkopf	Ochsenkopf	1993-12-22
-1	-1187169	-1749170	47.1833333	9.5333333	471100	93200	NT42	NL32-02	A	ADM1 		LS	00				N				PLANKEN	Planken	Planken	1993-12-22
-1	-1187170	-1749171	47.1833333	9.5333333	471100	93200	NT42	NL32-02	P	PPL		LS	00				N				PLANKEN	Planken	Planken	1993-12-22
-1	-1187171	-1749172	47.0500000	9.7500000	470300	94500	NT51	NL32-02	T	MTS		LS	00				V				RATIKON	Rätikon	Ratikon	1993-12-22
-1	-1187171	-1749174	47.0500000	9.7500000	470300	94500	NT51	NL32-02	T	MTS		LS	00				V				RHAETIKON	Rhaetikon	Rhaetikon	1993-12-22
-1	-1187171	-1749175	47.0500000	9.7500000	470300	94500	NT51	NL32-02	T	MTS		LS	00				N				RHATIKON	Rhätikon	Rhatikon	1993-12-22
-1	-1187171	-1749176	47.0500000	9.7500000	470300	94500	NT51	NL32-02	T	MTS		LS	00				V				RHATIKONMOUNTAINS	Rhätikon Mountains	Rhatikon Mountains	1993-12-22
-1	419569	535539	47.1166667	9.5500000	470700	93300	NT41	NL32-02	P	PPL		LS	00				V				ROTABODA	Rotaboda	Rotaboda	1999-01-26
-1	419569	535573	47.1166667	9.5500000	470700	93300	NT41	NL32-02	P	PPL		LS	00				N				ROTENBODEN	Rotenboden	Rotenboden	1999-01-26
-1	-1187174	-1749189	47.2333333	9.5166667	471400	93100	NT33	NL32-02	P	PPL		LS	00				V				RUGELL	Rugell	Rugell	1993-12-22
-1	-1187173	-1749190	47.2333333	9.5166667	471400	93100	NT33	NL32-02	A	ADM1 		LS	00				N				RUGGELL	Ruggell	Ruggell	1993-12-22
-1	-1187174	-1749191	47.2333333	9.5166667	471400	93100	NT33	NL32-02	P	PPL		LS	00				N				RUGGELL	Ruggell	Ruggell	1993-12-22
-1	-1187175	-1749192	47.2333333	9.6333333	471400	93800	NT43	NL32-02	H	STM		LS	00				N				SAMINA	Samina	Samina	1993-12-22
-1	-1187176	-1749193	47.1666667	9.5833333	471000	93500	NT42	NL32-02	T	VAL		LS	00				N				SAMINATAL	Saminatal	Saminatal	1993-12-22
-1	-1187176	-1749194	47.1666667	9.5833333	471000	93500	NT42	NL32-02	T	VAL		LS	00				V				SAMINATHAL	Samina Thal	Samina Thal	1993-12-22
-1	-1187177	-1749195	47.1000000	9.6333333	470600	93800	NT41	NL32-02	T	PASS 		LS	00				N				SAREISERJOCH	Sareiser Joch	Sareiser Joch	1993-12-22
-1	-1187178	-1749196	47.1666667	9.5000000	471000	93000	NT32	NL32-02	A	ADM1 		LS	00				N				SCHAAN	Schaan	Schaan	1993-12-22
-1	-1187179	-1749197	47.1666667	9.5000000	471000	93000	NT32	NL32-02	P	PPL		LS	00				N				SCHAAN	Schaan	Schaan	1993-12-22
-1	-1187180	-1749198	47.2166667	9.5666667	471300	93400	NT42	NL32-02	P	PPL		LS	00				N				SCHAANWALD	Schaanwald	Schaanwald	1993-12-22
-1	-1187179	-1749199	47.1666667	9.5000000	471000	93000	NT32	NL32-02	P	PPL		LS	00				V				SCHAN	Schan	Schan	1993-12-22
-1	-1187181	-1749200	47.1333333	9.6333333	470800	93800	NT42	NL32-02	T	MT		LS	00				N				SCHEIENKOPF	Scheienkopf	Scheienkopf	1993-12-22
-1	-1187182	-1749201	47.2333333	9.5333333	471400	93200	NT43	NL32-02	A	ADM1 		LS	00				N				SCHELLENBERG	Schellenberg	Schellenberg	1993-12-22
-1	-1187183	-1749202	47.2333333	9.5333333	471400	93200	NT43	NL32-02	P	PPL		LS	00				N				SCHELLENBERG	Schellenberg	Schellenberg	1993-12-22
-1	-1187181	-1749203	47.1333333	9.6333333	470800	93800	NT42	NL32-02	T	MT		LS	00				V				SCHEUENKOPF	Scheuenkopf	Scheuenkopf	1993-12-22
-1	419570	535541	47.1333333	9.5500000	470800	93300	NT42	NL32-02	P	PPL		LS	00				N				SILUM	Silum	Silum	1999-01-26
-1	419568	535538	47.1166667	9.5666667	470700	93400	NT41	NL32-02	P	PPL		LS	00				N				SUCKA	Sücka	Sucka	1999-01-26
-1	-1187184	-1749204	47.1000000	9.5333333	470600	93200	NT41	NL32-02	A	ADM1 		LS	00				N				TRIESEN	Triesen	Triesen	1993-12-22
-1	-1187185	-1749205	47.1000000	9.5333333	470600	93200	NT41	NL32-02	P	PPL		LS	00				N				TRIESEN	Triesen	Triesen	1993-12-22
-1	-1187186	-1749206	47.1166667	9.5333333	470700	93200	NT41	NL32-02	A	ADM1 		LS	00				N				TRIESENBERG	Triesenberg	Triesenberg	1993-12-22
-1	-1187187	-1749207	47.1166667	9.5333333	470700	93200	NT41	NL32-02	P	PPL		LS	00				N				TRIESENBERG	Triesenberg	Triesenberg	1993-12-22
-1	-1187188	-1749208	47.2500000	9.5333333	471500	93200	NT43	NL32-02	H	MRSH 		LS	00				N				UNTERESRIET	Unteres Riet	Unteres Riet	1993-12-22
-1	-1187189	-1749209	47.1333333	9.5166667	470800	93100	NT32	NL32-02	A	ADM1 		LS	00				N				VADUZ	Vaduz	Vaduz	1993-12-22
-1	-1187190	-1749210	47.1333333	9.5166667	470800	93100	NT32	NL32-02	P	PPLC 		LS	00				N				VADUZ	Vaduz	Vaduz	1995-04-26
-1	419571	535542	47.0833333	9.5833333	470500	93500	NT41	NL32-02	T	VAL		LS	00				N				VALUNA	Valüna	Valuna	1999-01-26
-1	-1187191	-1749211	47.2333333	9.5333333	471400	93200	NT43	NL32-02	P	PPLX 		LS	00				N				VORDERERSCHELLENBERG	Vorderer Schellenberg	Vorderer Schellenberg	1993-12-22
-1	-1187192	-1749212	47.0500000	9.5833333	470300	93500	NT41	NL32-02	T	PK		LS	00				N				VORDERGRAUSPITZ	Vorder-Grauspitz	Vorder-Grauspitz	1993-12-22
-1	419567	535537	47.1000000	9.5333333	470600	93200	NT41	NL32-02	P	PPL		LS	00				V				WANGERBARG	Wangerbärg	Wangerbarg	1999-01-26
-1	419567	535572	47.1000000	9.5333333	470600	93200	NT41	NL32-02	P	PPL		LS	00				N				WANGERBERG	Wangerberg	Wangerberg	1999-01-26
+RC	UFI	UNI	LAT	LONG	DMS_LAT	DMS_LONG	MGRS	JOG	FC	DSG	PC	CC1	ADM1	ADM2	POP	ELEV	CC2	NT	LC	SHORT_FORM	GENERIC	SORT_NAME	FULL_NAME	FULL_NAME_ND	MODIFY_DATE
+1	-1187145	-1749126	47.066667	9.5	470400	93000	32TNT3796512694	NL32-02	A	ADM1		LS	01					V				BALZERS	Balzers	Balzers	2004-10-27
+1	-1187145	9224799	47.066667	9.5	470400	93000	32TNT3796512694	NL32-02	A	ADM1		LS	01					N		Balzers	Gemeinde	GEMEINDEBALZERS	Gemeinde Balzers	Gemeinde Balzers	2004-10-27
+1	-1187145	9224888	47.066667	9.5	470400	93000	32TNT3796512694	NL32-02	A	ADM1		LS	01					V				BALZERSMALS	Balzers / Mäls	Balzers / Mals	2004-10-27
+1	-1187146	-1749127	47.066667	9.5	470400	93000	32TNT3796512694	NL32-02	P	PPLA		LS	01					N				BALZERS	Balzers	Balzers	2004-10-27
+1	-1187147	-1749128	47.216667	9.5	471300	93000	32TNT3785929363	NL32-02	P	PPL		LS	03					N				BENDERN	Bendern	Bendern	2004-10-27
+1	-1187148	-1749129	47.066667	9.616667	470400	93700	32TNT4682412757	NL32-02	T	PASS		LS	00					N				BETTLERJOCH	Bettlerjoch	Bettlerjoch	1993-12-22
+1	-1187149	-1749131	47.166667	9.55	471000	93300	32TNT4168423832	NL32-02	T	MTS		LS	00					N				DREISCHWESTERN	Drei Schwestern	Drei Schwestern	1993-12-22
+1	-1187149	-1749132	47.166667	9.55	471000	93300	32TNT4168423832	NL32-02	T	MTS		LS	00					V				DREYSCHWESTERN	Drey Schwestern	Drey Schwestern	1993-12-22
+1	-1187150	-1749134	47.216667	9.516667	471300	93100	32TNT3912129371	NL32-02	A	ADM1		LS	02					V				ESCHEN	Eschen	Eschen	2004-10-27
+1	-1187150	-1749136	47.216667	9.516667	471300	93100	32TNT3912129371	NL32-02	A	ADM1		LS	02					V				ESCHENNEDELN	Eschen-Nedeln	Eschen-Nedeln	2004-10-27
+1	-1187150	9224821	47.216667	9.516667	471300	93100	32TNT3912129371	NL32-02	A	ADM1		LS	02					N		Eschen	Gemeinde	GEMEINDEESCHEN	Gemeinde Eschen	Gemeinde Eschen	2004-10-27
+1	-1187150	9224897	47.216667	9.516667	471300	93100	32TNT3912129371	NL32-02	A	ADM1		LS	02					V				ESCHENNENDELN	Eschen / Nendeln	Eschen / Nendeln	2004-10-27
+1	-1187151	-1749135	47.216667	9.516667	471300	93100	32TNT3912129371	NL32-02	P	PPLA		LS	02					N				ESCHEN	Eschen	Eschen	2004-10-27
+1	-1187152	-1749133	47.05	9.566667	470300	93400	32TNT4304110876	NL32-02	T	MT		LS	00					V				ENDERLINHORN	Enderlin Horn	Enderlin Horn	1993-12-22
+1	-1187152	-1749137	47.05	9.566667	470300	93400	32TNT4304110876	NL32-02	T	MT		LS	00					N				FALKNIS	Falknis	Falknis	1993-12-22
+1	-1187152	-1749138	47.05	9.566667	470300	93400	32TNT4304110876	NL32-02	T	MT		LS	00					V				FALKNISHORN	Falknis Horn	Falknis Horn	1993-12-22
+1	-1187153	-1749139	47.2	9.583333	471200	93500	32TNT4418227555	NL32-02	T	MT		LS	00					N				FRASTANZERSAND	Frastanzer Sand	Frastanzer Sand	1993-12-22
+1	-1187154	-1749140	47.133333	9.55	470800	93300	32TNT4171020128	NL32-02	T	MT		LS	00					N				FURSTENSTEIG	Fürstensteig	Furstensteig	1993-12-22
+1	-1187155	-1749141	47.15	9.616667	470900	93700	32TNT4675122018	NL32-02	T	MT		LS	00					N				GALLINAKOPF	Gallinakopf	Gallinakopf	1993-12-22
+1	-1187156	-1749143	47.216667	9.5	471300	93000	32TNT3785929363	NL32-02	A	ADM1		LS	03					V				GAMPRIN	Gamprin	Gamprin	2004-10-27
+1	-1187156	-1749145	47.216667	9.5	471300	93000	32TNT3785929363	NL32-02	A	ADM1		LS	03					V				GAMPRINBENDERN	Gamprin-Bendern	Gamprin-Bendern	2004-10-27
+1	-1187156	9224845	47.216667	9.5	471300	93000	32TNT3785929363	NL32-02	A	ADM1		LS	03					V				GEMEINDEGAMPRINBENDERN	Gemeinde Gamprin-Bendern	Gemeinde Gamprin-Bendern	2004-10-27
+1	-1187156	9224847	47.216667	9.5	471300	93000	32TNT3785929363	NL32-02	A	ADM1		LS	03					N		Gamprin	Gemeinde	GEMEINDEGAMPRIN	Gemeinde Gamprin	Gemeinde Gamprin	2004-10-27
+1	-1187157	-1749142	47.216667	9.5	471300	93000	32TNT3785929363	NL32-02	P	PPLA		LS	03					V				GAMBRIN	Gambrin	Gambrin	2004-10-27
+1	-1187157	-1749144	47.216667	9.5	471300	93000	32TNT3785929363	NL32-02	P	PPLA		LS	03					N				GAMPRIN	Gamprin	Gamprin	2004-10-27
+1	-1187157	9224858	47.216667	9.5	471300	93000	32TNT3785929363	NL32-02	P	PPLA		LS	03					V				GAMPRINBENDERN	Gamprin-Bendern	Gamprin-Bendern	2004-10-27
+1	-1187158	-1749146	47.166667	9.566667	471000	93400	32TNT4294723841	NL32-02	T	MT		LS	00					N				GARSELLAKOPF	Garsellakopf	Garsellakopf	1993-12-22
+1	-1187159	-1749149	47.233333	9.533333	471400	93200	32TNT4037031232	NL32-02	P	PPLX		LS	08					V				HINTERERSCHELLENBERG	Hinterer Schellenberg	Hinterer Schellenberg	2004-10-27
+1	-1187159	9246078	47.233333	9.533333	471400	93200	32TNT4037031232	NL32-02	P	PPLX		LS	08					V				HINTERSCHELLENBERG	Hinter-Schellenberg	Hinter-Schellenberg	2004-10-27
+1	-1187159	9246168	47.233333	9.533333	471400	93200	32TNT4037031232	NL32-02	P	PPLX		LS	08					N				HINTERSCHELLENBERG	Hinterschellenberg	Hinterschellenberg	2004-10-27
+1	-1187160	-1749147	47.05	9.583333	470300	93500	32TNT4430710886	NL32-02	T	PK		LS	00					V				GRAUSPITZ	Grauspitz	Grauspitz	1993-12-22
+1	-1187160	-1749150	47.05	9.583333	470300	93500	32TNT4430710886	NL32-02	T	PK		LS	00					N				HINTERGRAUSPITZ	Hinter-Grauspitz	Hinter-Grauspitz	1993-12-22
+1	-1187161	-1749151	47.166667	9.533333	471000	93200	32TNT4042123823	NL32-02	A	PCLI		LS	00					V				LICHTENSTEIN	Lichtenstein	Lichtenstein	2007-02-28
+1	-1187161	-1749153	47.166667	9.533333	471000	93200	32TNT4042123823	NL32-02	A	PCLI		LS	00					C	eng			PRINCIPALITYOFLIECHTENSTEIN	Principality of Liechtenstein	Principality of Liechtenstein	2007-02-28
+1	-1187161	-1749154	47.166667	9.533333	471000	93200	32TNT4042123823	NL32-02	A	PCLI		LS	00					N	deu	Liechtenstein	Fürstentum	FURSTENTUMLIECHTENSTEIN	Fürstentum Liechtenstein	Furstentum Liechtenstein	2007-02-28
+1	-1187162	-1749155	47.133333	9.616667	470800	93700	32TNT4676620166	NL32-02	T	PASS		LS	00					V				MATLAJOCH	Matla Joch	Matla Joch	1994-04-28
+1	-1187162	-1749158	47.133333	9.616667	470800	93700	32TNT4676620166	NL32-02	T	PASS		LS	00				LS	N				MATTAJOCH	Mattajoch	Mattajoch	1994-04-28
+1	-1187162	-1749159	47.133333	9.616667	470800	93700	32TNT4676620166	NL32-02	T	PASS		LS	00				AU	N				MATLERJOCH	Matlerjoch	Matlerjoch	1994-04-28
+1	-1187163	-1749161	47.216667	9.533333	471300	93200	32TNT4038329380	NL32-02	A	ADM1		LS	04					V				MAUREN	Mauren	Mauren	2004-10-27
+1	-1187163	-1749163	47.216667	9.533333	471300	93200	32TNT4038329380	NL32-02	A	ADM1		LS	04					V				MAURENSCHAANWALD	Mauren-Schaanwald	Mauren-Schaanwald	2004-10-27
+1	-1187163	9224862	47.216667	9.533333	471300	93200	32TNT4038329380	NL32-02	A	ADM1		LS	04					N		Mauren	Gemeinde	GEMEINDEMAUREN	Gemeinde Mauren	Gemeinde Mauren	2004-10-27
+1	-1187164	-1749160	47.216667	9.533333	471300	93200	32TNT4038329380	NL32-02	P	PPLA		LS	04					V				MAUERN	Mauern	Mauern	2004-10-27
+1	-1187164	-1749162	47.216667	9.533333	471300	93200	32TNT4038329380	NL32-02	P	PPLA		LS	04					N				MAUREN	Mauren	Mauren	2004-10-27
+1	-1187165	-1749164	47.233333	9.533333	471400	93200	32TNT4037031232	NL32-02	P	PPLX		LS	08					V				MITTLERERSCHELLENBERG	Mittlerer Schellenberg	Mittlerer Schellenberg	2004-10-27
+1	-1187165	9246077	47.233333	9.533333	471400	93200	32TNT4037031232	NL32-02	P	PPLX		LS	08					V				MITTLERSCHELLENBERG	Mittler-Schellenberg	Mittler-Schellenberg	2004-10-27
+1	-1187165	9246167	47.233333	9.533333	471400	93200	32TNT4037031232	NL32-02	P	PPLX		LS	08					N				MITTLERSCHELLENBERG	Mittlerschellenberg	Mittlerschellenberg	2004-10-27
+1	-1187166	-1749165	47.05	9.6	470300	93600	32TNT4557310895	NL32-02	T	MT		LS	00					N				NAAFKOPF	Naafkopf	Naafkopf	1993-12-22
+1	-1187166	-1749166	47.05	9.6	470300	93600	32TNT4557310895	NL32-02	T	MT		LS	00					V				NAUFKOPF	Nauf Kopf	Nauf Kopf	1993-12-22
+1	-1187167	-1749167	47.2	9.55	471200	93300	32TNT4165827536	NL32-02	P	PPL		LS	02					N				NENDELN	Nendeln	Nendeln	2004-10-27
+1	-1187168	-1749168	47.116667	9.633333	470700	93800	32TNT4804518324	NL32-02	T	MT		LS	00					V				OCHSENBERG	Ochsenberg	Ochsenberg	1993-12-22
+1	-1187168	-1749169	47.116667	9.633333	470700	93800	32TNT4804518324	NL32-02	T	MT		LS	00					N				OCHSENKOPF	Ochsenkopf	Ochsenkopf	1993-12-22
+1	-1187169	-1749170	47.183333	9.533333	471100	93200	32TNT4040825676	NL32-02	A	ADM1		LS	05					V				PLANKEN	Planken	Planken	2004-10-27
+1	-1187169	9224865	47.183333	9.533333	471100	93200	32TNT4040825676	NL32-02	A	ADM1		LS	05					N		Planken	Gemeinde	GEMEINDEPLANKEN	Gemeinde Planken	Gemeinde Planken	2004-10-27
+1	-1187170	-1749130	47.183333	9.533333	471100	93200	32TNT4040825676	NL32-02	P	PPLA		LS	05					V				BLANKEN	Blanken	Blanken	2004-10-27
+1	-1187170	-1749171	47.183333	9.533333	471100	93200	32TNT4040825676	NL32-02	P	PPLA		LS	05					N				PLANKEN	Planken	Planken	2004-10-27
+1	-1187171	-1749172	47.05	9.75	470300	94500	32TNT5696610993	NL32-02	T	MTS		LS	00					V				RATIKON	Rätikon	Ratikon	1993-12-22
+1	-1187171	-1749174	47.05	9.75	470300	94500	32TNT5696610993	NL32-02	T	MTS		LS	00					V				RHAETIKON	Rhaetikon	Rhaetikon	1993-12-22
+1	-1187171	-1749175	47.05	9.75	470300	94500	32TNT5696610993	NL32-02	T	MTS		LS	00					N				RHATIKON	Rhätikon	Rhatikon	1993-12-22
+1	-1187171	-1749176	47.05	9.75	470300	94500	32TNT5696610993	NL32-02	T	MTS		LS	00					V				RHATIKONMOUNTAINS	Rhätikon Mountains	Rhatikon Mountains	1993-12-22
+1	-1187173	-1749190	47.233333	9.516667	471400	93100	32TNT3910931224	NL32-02	A	ADM1		LS	06					V				RUGGELL	Ruggell	Ruggell	2004-10-27
+1	-1187173	9224866	47.233333	9.516667	471400	93100	32TNT3910931224	NL32-02	A	ADM1		LS	06					N		Ruggell	Gemeinde	GEMEINDERUGGELL	Gemeinde Ruggell	Gemeinde Ruggell	2004-10-27
+1	-1187174	-1749189	47.233333	9.516667	471400	93100	32TNT3910931224	NL32-02	P	PPLA		LS	06					V				RUGELL	Rugell	Rugell	2004-10-27
+1	-1187174	-1749191	47.233333	9.516667	471400	93100	32TNT3910931224	NL32-02	P	PPLA		LS	06					N				RUGGELL	Ruggell	Ruggell	2004-10-27
+1	-1187175	-1749192	47.233333	9.633333	471400	93800	32TNT4793931289	NL32-02	H	STM		LS	00					N				SAMINA	Samina	Samina	1993-12-22
+1	-1187176	-1749193	47.166667	9.583333	471000	93500	32TNT4421023851	NL32-02	T	VAL		LS	00					N				SAMINATAL	Saminatal	Saminatal	1993-12-22
+1	-1187176	-1749194	47.166667	9.583333	471000	93500	32TNT4421023851	NL32-02	T	VAL		LS	00					V				SAMINATHAL	Samina Thal	Samina Thal	1993-12-22
+1	-1187177	-1749195	47.1	9.633333	470600	93800	32TNT4806016471	NL32-02	T	PASS		LS	00					N				SAREISERJOCH	Sareiser Joch	Sareiser Joch	1993-12-22
+1	-1187178	-1749196	47.166667	9.5	471000	93000	32TNT3789423807	NL32-02	A	ADM1		LS	07					V				SCHAAN	Schaan	Schaan	2004-10-27
+1	-1187178	9224868	47.166667	9.5	471000	93000	32TNT3789423807	NL32-02	A	ADM1		LS	07					N		Schaan	Gemeinde	GEMEINDESCHAAN	Gemeinde Schaan	Gemeinde Schaan	2004-10-27
+1	-1187179	-1749197	47.166667	9.5	471000	93000	32TNT3789423807	NL32-02	P	PPLA		LS	07					N				SCHAAN	Schaan	Schaan	2004-10-27
+1	-1187179	-1749199	47.166667	9.5	471000	93000	32TNT3789423807	NL32-02	P	PPLA		LS	07					V				SCHAN	Schan	Schan	2004-10-27
+1	-1187180	-1749198	47.216667	9.566667	471300	93400	32TNT4290729398	NL32-02	P	PPL		LS	04					N				SCHAANWALD	Schaanwald	Schaanwald	2004-10-27
+1	-1187181	-1749157	47.133333	9.633333	470800	93800	32TNT4803020176	NL32-02	T	MT		LS	00					V				MATLERKOPF	Matler Kopf	Matler Kopf	1993-12-22
+1	-1187181	-1749200	47.133333	9.633333	470800	93800	32TNT4803020176	NL32-02	T	MT		LS	00					N				SCHEIENKOPF	Scheienkopf	Scheienkopf	1993-12-22
+1	-1187181	-1749203	47.133333	9.633333	470800	93800	32TNT4803020176	NL32-02	T	MT		LS	00					V				SCHEUENKOPF	Scheuenkopf	Scheuenkopf	1993-12-22
+1	-1187182	-1749201	47.233333	9.533333	471400	93200	32TNT4037031232	NL32-02	A	ADM1		LS	08					V				SCHELLENBERG	Schellenberg	Schellenberg	2004-10-27
+1	-1187182	9224871	47.233333	9.533333	471400	93200	32TNT4037031232	NL32-02	A	ADM1		LS	08					N		Schellenberg	Gemeinde	GEMEINDESCHELLENBERG	Gemeinde Schellenberg	Gemeinde Schellenberg	2004-10-27
+1	-1187183	-1749202	47.233333	9.533333	471400	93200	32TNT4037031232	NL32-02	P	PPLA		LS	08					N				SCHELLENBERG	Schellenberg	Schellenberg	2004-10-27
+1	-1187184	-1749204	47.1	9.533333	470600	93200	32TNT4047116415	NL32-02	A	ADM1		LS	09					V				TRIESEN	Triesen	Triesen	2004-10-27
+1	-1187184	9224876	47.1	9.533333	470600	93200	32TNT4047116415	NL32-02	A	ADM1		LS	09					N		Triesen	Gemeinde	GEMEINDETRIESEN	Gemeinde Triesen	Gemeinde Triesen	2004-10-27
+1	-1187185	-1749205	47.1	9.533333	470600	93200	32TNT4047116415	NL32-02	P	PPLA		LS	09					N				TRIESEN	Triesen	Triesen	2004-10-27
+1	-1187186	-1749206	47.116667	9.533333	470700	93200	32TNT4045918267	NL32-02	A	ADM1		LS	10					V				TRIESENBERG	Triesenberg	Triesenberg	2004-10-27
+1	-1187186	9224880	47.116667	9.533333	470700	93200	32TNT4045918267	NL32-02	A	ADM1		LS	10					N		Triesenberg	Gemeinde	GEMEINDETRIESENBERG	Gemeinde Triesenberg	Gemeinde Triesenberg	2004-10-27
+1	-1187186	9224895	47.116667	9.533333	470700	93200	32TNT4045918267	NL32-02	A	ADM1		LS	10					V				TRIESENBERGSTEGMALBUN	Triesenberg / Steg / Malbun	Triesenberg / Steg / Malbun	2004-10-27
+1	-1187187	-1749207	47.116667	9.533333	470700	93200	32TNT4045918267	NL32-02	P	PPLA		LS	10					N				TRIESENBERG	Triesenberg	Triesenberg	2004-10-27
+1	-1187188	-1749208	47.25	9.533333	471500	93200	32TNT4035733084	NL32-02	H	MRSH		LS	00					N				UNTERESRIET	Unteres Riet	Unteres Riet	1993-12-22
+1	-1187189	-1749209	47.133333	9.516667	470800	93100	32TNT3918220111	NL32-02	A	ADM1		LS	11					V				VADUZ	Vaduz	Vaduz	2004-10-27
+1	-1187189	9224884	47.133333	9.516667	470800	93100	32TNT3918220111	NL32-02	A	ADM1		LS	11					N		Vaduz	Gemeinde	GEMEINDEVADUZ	Gemeinde Vaduz	Gemeinde Vaduz	2004-10-27
+1	-1187190	-1749210	47.133333	9.516667	470800	93100	32TNT3918220111	NL32-02	P	PPLC		LS	11					N				VADUZ	Vaduz	Vaduz	2004-10-27
+1	-1187191	-1749211	47.233333	9.533333	471400	93200	32TNT4037031232	NL32-02	P	PPLX		LS	08					V				VORDERERSCHELLENBERG	Vorderer Schellenberg	Vorderer Schellenberg	2004-10-27
+1	-1187191	9246076	47.233333	9.533333	471400	93200	32TNT4037031232	NL32-02	P	PPLX		LS	08					V				VORDERSCHELLENBERG	Vorder-Schellenberg	Vorder-Schellenberg	2004-10-27
+1	-1187191	9246166	47.233333	9.533333	471400	93200	32TNT4037031232	NL32-02	P	PPLX		LS	08					N				VORDERSCHELLENBERG	Vorderschellenberg	Vorderschellenberg	2004-10-27
+1	-1187192	-1749148	47.05	9.583333	470300	93500	32TNT4430710886	NL32-02	T	PK		LS	00					V				GRAUSPITZ	Grauspitz	Grauspitz	1993-12-22
+1	-1187192	-1749212	47.05	9.583333	470300	93500	32TNT4430710886	NL32-02	T	PK		LS	00					N				VORDERGRAUSPITZ	Vorder-Grauspitz	Vorder-Grauspitz	1993-12-22
+1	419565	535533	47.05	9.5	470300	93000	32TNT3797710842	NL32-02	P	PPL		LS	01					N				MALS	Mäls	Mals	2004-10-27
+1	419566	535536	47.05	9.55	470300	93300	32TNT4177510867	NL32-02	T	VAL		LS	00					N				LAWENA	Lawena	Lawena	1999-01-26
+1	419567	535537	47.1	9.533333	470600	93200	32TNT4047116415	NL32-02	P	PPL		LS	10					V				WANGERBARG	Wangerbärg	Wangerbarg	2004-10-27
+1	419567	535572	47.1	9.533333	470600	93200	32TNT4047116415	NL32-02	P	PPL		LS	10					N				WANGERBERG	Wangerberg	Wangerberg	2004-10-27
+1	419568	535538	47.116667	9.566667	470700	93400	32TNT4298718285	NL32-02	P	PPL		LS	10					N				SUCKA	Sücka	Sucka	2004-10-27
+1	419569	535539	47.125	9.533333	470730	93200	32TNT4045219193	NL32-02	P	PPL		LS	10					V				ROTABODA	Rotaboda	Rotaboda	2004-10-27
+1	419569	535573	47.125	9.533333	470730	93200	32TNT4045219193	NL32-02	P	PPL		LS	10					N				ROTENBODEN	Rotenboden	Rotenboden	2004-10-27
+1	419570	535541	47.133333	9.55	470800	93300	32TNT4171020128	NL32-02	P	PPL		LS	10					N				SILUM	Silum	Silum	2004-10-27
+1	419571	535542	47.083333	9.583333	470500	93500	32TNT4427914590	NL32-02	T	VAL		LS	00					N				VALUNA	Valüna	Valuna	1999-01-26
+1	419572	535543	47.133333	9.533333	470800	93200	32TNT4044620119	NL32-02	P	PPL		LS	10					N				MASESCHA	Masescha	Masescha	2004-10-27
+1	419573	535544	47.133333	9.533333	470800	93200	32TNT4044620119	NL32-02	P	PPL		LS	10					N				GAFLEI	Gaflei	Gaflei	2004-10-27
+1	419574	535545	47.15	9.5	470900	93000	32TNT3790621955	NL32-02	P	PPL		LS	11					V				MOLIHOLZ	Möliholz	Moliholz	2004-10-27
+1	419574	535574	47.15	9.5	470900	93000	32TNT3790621955	NL32-02	P	PPL		LS	11					N				MUHLEHOLZ	Mühleholz	Muhleholz	2004-10-27
+1	419575	535546	47.15	9.516667	470900	93100	32TNT3917021963	NL32-02	P	PPL		LS	11					V				EBAHOLZ	Ebaholz	Ebaholz	2004-10-27
+1	419575	535575	47.15	9.516667	470900	93100	32TNT3917021963	NL32-02	P	PPL		LS	11					N				EBENHOLZ	Ebenholz	Ebenholz	2004-10-27

Modified: branches/WIP-pyshapelib-Unicode/thuban/Extensions/gns2shp/test/test_gns2shp.py
===================================================================
--- branches/WIP-pyshapelib-Unicode/thuban/Extensions/gns2shp/test/test_gns2shp.py	2008-08-08 23:39:11 UTC (rev 2864)
+++ branches/WIP-pyshapelib-Unicode/thuban/Extensions/gns2shp/test/test_gns2shp.py	2008-09-05 19:45:58 UTC (rev 2865)
@@ -48,7 +48,7 @@
         n = gns2shp(filename, dest_filename)
 
         # is the number of shapes correct?
-        eq(n, 88) # what gns2shp reports
+        eq(n, 109) # what gns2shp reports
         # and now the actually written ones
         shp = shapelib.ShapeFile(dest_filename)
         numshapes, shapetype, mins, maxs = shp.info()
@@ -61,7 +61,7 @@
         field_types = { 'RC': FTInteger,
                         'UFI': FTInteger,
                         'UNI': FTInteger,
-                        'UTM': FTString,
+                        'MGRS': FTString,
                         'JOG': FTString,
                         'FC': FTString,
                         'DSG': FTString,
@@ -69,7 +69,8 @@
                         'CC1': FTString,
                         'ADM1': FTString,
                         'ADM2': FTString,
-                        'DIM': FTInteger,
+                        'POP': FTInteger,
+                        'ELEV': FTInteger,
                         'CC2': FTString,
                         'NT': FTString,
                         'LC': FTString,


Property changes on: branches/WIP-pyshapelib-Unicode/thuban/Extensions/importAPR
___________________________________________________________________
Name: svn:ignore
   + *.pyc
*~




Property changes on: branches/WIP-pyshapelib-Unicode/thuban/Extensions/importMP
___________________________________________________________________
Name: svn:ignore
   + *.pyc
*~



Added: branches/WIP-pyshapelib-Unicode/thuban/Extensions/importMP/README
===================================================================
--- branches/WIP-pyshapelib-Unicode/thuban/Extensions/importMP/README	2008-08-08 23:39:11 UTC (rev 2864)
+++ branches/WIP-pyshapelib-Unicode/thuban/Extensions/importMP/README	2008-09-05 19:45:58 UTC (rev 2865)
@@ -0,0 +1,11 @@
+This extension imports Polish Map Files, the format used by Garmin GPS
+receivers.
+
+There's quite a complete description of the format here
+http://www.cgpsmapper.com/download/cGPSmapper-UsrMan-v02.4.pdf
+
+The extension works by first creating shapefiles that represent the data in the
+MP file and then loading the shapefiles in to thuban, so it effectively works
+like a MP to Shapefile converter, also.
+
+

Added: branches/WIP-pyshapelib-Unicode/thuban/Extensions/importMP/__init__.py
===================================================================
--- branches/WIP-pyshapelib-Unicode/thuban/Extensions/importMP/__init__.py	2008-08-08 23:39:11 UTC (rev 2864)
+++ branches/WIP-pyshapelib-Unicode/thuban/Extensions/importMP/__init__.py	2008-09-05 19:45:58 UTC (rev 2865)
@@ -0,0 +1,22 @@
+# Copyright (c) 2008 by Intevation GmbH
+# Authors:
+# Anthony Lenton <anthony at except.com.ar>
+#
+# This program is free software under the GPL (>=v2)
+# Read the file COPYING coming with Thuban for details.
+
+# import the actual module
+import importMP
+
+# perform the registration of the extension
+from Thuban import _
+from Thuban.UI.extensionregistry import ExtensionDesc, ext_registry
+
+ext_registry.add(ExtensionDesc(
+    name = 'importMP',
+    version = '0.1.1',
+    authors= [ 'Anthony Lenton' ],
+    copyright = '2008 by Intevation GmbH',
+    desc = _("Import a Polish Map File (.mp)\n" \
+             "and convert it to Thuban.")))
+

Added: branches/WIP-pyshapelib-Unicode/thuban/Extensions/importMP/importMP.py
===================================================================
--- branches/WIP-pyshapelib-Unicode/thuban/Extensions/importMP/importMP.py	2008-08-08 23:39:11 UTC (rev 2864)
+++ branches/WIP-pyshapelib-Unicode/thuban/Extensions/importMP/importMP.py	2008-09-05 19:45:58 UTC (rev 2865)
@@ -0,0 +1,305 @@
+# Copyright (c) 2008 by Intevation GmbH
+# Authors:
+# Anthony Lenton <anthony at except.com.ar>
+#
+# This program is free software under the GPL (>=v2)
+# Read the file COPYING coming with Thuban for details.
+
+""" A Polish Map File parser.  This module contains the UI and shapefile
+    saving code . """
+
+import os
+import wx
+
+if __name__ != '__main__':
+    from Thuban.UI.command import registry, Command
+    from Thuban import _
+    from Thuban.UI.mainwindow import main_menu
+    from Thuban.UI import internal_from_wxstring
+
+from Thuban.Model.layer import Layer
+from Thuban.Model.classification import Classification, ClassGroupProperties
+from Thuban.Model.classification import ClassGroupSingleton
+from Thuban.Model.color import Color
+import shapelib
+import dbflib
+from pfm import MPParser
+
+def pfm2shp (src_fname, dest_fname):
+    """Convert a file from Polish Map File into Shapefiles. """
+    fp = open(src_fname)
+    parser = MPParser()
+    parser.parse (fp)
+    
+    poi_shp_filename = dest_fname + '_poi.shp'
+    poi_dbf_filename = dest_fname + '_poi.dbf'
+    poi_shp = shapelib.create(poi_shp_filename, shapelib.SHPT_POINT)
+    poi_dbf = dbflib.create(poi_dbf_filename)
+    poi_dbf.add_field('Label', dbflib.FTString, 80, 0)
+    del poi_dbf
+    poi_dbf = dbflib.open(poi_dbf_filename, 'r+b')
+    i = 0
+    for poi in parser.pois:
+        obj = shapelib.SHPObject(shapelib.SHPT_POINT, i,
+                                 [[(poi['long'], poi['lat'])]])
+        poi_shp.write_object(-1, obj)
+        poi_dbf.write_record(i, { 'Label': poi.get('Label', '') })
+        i += 1
+    del poi_shp
+    del poi_dbf
+
+    polygon_shp_filename = dest_fname + '_polygon.shp'
+    polygon_dbf_filename = dest_fname + '_polygon.dbf'
+    polygon_shp = shapelib.create(polygon_shp_filename, shapelib.SHPT_POLYGON)
+    polygon_dbf = dbflib.create(polygon_dbf_filename)
+    polygon_dbf.add_field('Label', dbflib.FTString, 80, 0)
+    polygon_dbf.add_field('Type', dbflib.FTString, 80, 0)
+    del polygon_dbf
+    polygon_dbf = dbflib.open(polygon_dbf_filename, 'r+b')
+    i = 0
+    for poly in parser.polygons:
+        if poly['Type'].lower() == '0x4b': # Skip background
+            continue
+        obj = shapelib.SHPObject(shapelib.SHPT_POLYGON, i,
+                                 [zip (poly['long'], poly['lat'])])
+        polygon_shp.write_object(-1, obj)
+        polygon_dbf.write_record(i, {'Label': poly.get('Label', ''),
+                                     'Type': poly.get('parsedType', '')})
+        i += 1
+    del polygon_shp
+    del polygon_dbf
+
+    bg_shp_filename = dest_fname + '_bg.shp'
+    bg_dbf_filename = dest_fname + '_bg.dbf'
+    bg_shp = shapelib.create(bg_shp_filename, shapelib.SHPT_POLYGON)
+    bg_dbf = dbflib.create(bg_dbf_filename)
+    bg_dbf.add_field('Label', dbflib.FTString, 80, 0)
+    bg_dbf.add_field('Type', dbflib.FTString, 8, 0)
+    del bg_dbf
+    bg_dbf = dbflib.open(bg_dbf_filename, 'r+b')
+    i = 0
+    for poly in parser.polygons:
+        if poly['Type'].lower() == '0x4b': # Process background
+            obj = shapelib.SHPObject(shapelib.SHPT_POLYGON, i,
+                                     [zip (poly['long'], poly['lat'])])
+            bg_shp.write_object(-1, obj)
+            bg_dbf.write_record(i, {'Label': poly.get('Label', ''),
+                                    'Type': poly.get('Type', '')})
+            i += 1
+    del bg_shp
+    del bg_dbf
+
+    road_shp_filename = dest_fname + '_road.shp'
+    road_dbf_filename = dest_fname + '_road.dbf'
+    road_shp = shapelib.create(road_shp_filename, shapelib.SHPT_ARC)
+    road_dbf = dbflib.create(road_dbf_filename)
+    road_dbf.add_field('Label', dbflib.FTString, 80, 0)
+    road_dbf.add_field('Type', dbflib.FTString, 80, 0)
+    del road_dbf
+    road_dbf = dbflib.open(road_dbf_filename, 'r+b')
+    i = 0
+    for poly in parser.polylines:
+        obj = shapelib.SHPObject(shapelib.SHPT_ARC,
+                                 i, [zip (poly['long'], poly['lat'])])
+        road_shp.write_object(-1, obj)
+        road_dbf.write_record(i, {'Label': poly.get('Label', ''),
+                                  'Type': poly.get('parsedType', '')})
+        i += 1
+    del road_shp
+    del road_dbf
+    return parser
+
+def getPolygonClassification(polygons):
+    """ Returns a Classification with the needed ClassGroups to describe the
+        provided polygons """
+    clazz = Classification()
+    waterProps = ClassGroupProperties()
+    waterProps.SetFill (Color (0.7, 0.7, 1))
+    vegetProps = ClassGroupProperties()
+    vegetProps.SetFill (Color (0.7, 1, 0.7))
+    buildProps = ClassGroupProperties()
+    buildProps.SetFill (Color (0.6, 0.6, 0.6))
+    iceProps = ClassGroupProperties()
+    iceProps.SetFill (Color (1, 1, 1))
+    earthProps = ClassGroupProperties()
+    earthProps.SetFill (Color (0.9, 0.6, 0.3))
+    
+    typeProps = {'Parking Garage': buildProps, 'City': buildProps,
+                 'Car Park (Parking Lot)': buildProps, 'Glacier': iceProps,
+                 'University': buildProps, 'Hospital': buildProps,
+                 'Cemetery': buildProps, 'City Park': vegetProps,
+                 'National park': vegetProps, 'Reservation': vegetProps,
+                 'Depth area - blue 4': waterProps,
+                 'Depth area - blue 5': waterProps,
+                 'Depth area - blue 2': waterProps,
+                 'Depth area - blue 3': waterProps,
+                 'Depth area - blue 1': waterProps, 'Tundra': iceProps,
+                 'Man made area': buildProps, 'Industrial': buildProps,
+                 'Airport Runway': buildProps, 'Land - urban': buildProps,
+                 'Military': buildProps, 'Intermittent River/Lake': waterProps,
+                 'Lake': waterProps, 'Depth area - white 1': waterProps,
+                 'Airport': buildProps, 'State Park': vegetProps,
+                 'Land - non-urban': earthProps, 'Ocean': waterProps,
+                 'Scrub': vegetProps, 'River': waterProps, 'Bridge': buildProps,
+                 'Golf': vegetProps, 'Depth area - white': waterProps,
+                 'Marina': waterProps, 'Blue-Unknown': waterProps,
+                 'Orchard or plantation': vegetProps, 'Flats': earthProps,
+                 'Woods': vegetProps, 'Wetland': earthProps, 'Sea': waterProps,
+                 'Shopping Centre': buildProps, 'Land - white': iceProps,
+                 'Sport': buildProps}
+
+    types = list(set([p['parsedType'] for p in polygons]))
+    for t in types:
+        if t in typeProps.keys():
+            group = ClassGroupSingleton (value=t, props=typeProps[t], label=t)
+            clazz.AppendGroup (group)
+    return clazz
+
+def getPolylineClassification(polylines):
+    """ Returns a Classification with the needed ClassGroups to describe the
+        provided polylines """
+    clazz = Classification()
+    waterProps = ClassGroupProperties()
+    waterProps.SetLineColor (Color (0.5, 0.5, 0.8))
+    minorProps = ClassGroupProperties()
+    minorProps.SetLineColor (Color (0.1, 0.9, 0.1))
+    majorProps = ClassGroupProperties()
+    majorProps.SetLineColor (Color (1, 1, 0.1))
+    roadProps = ClassGroupProperties()
+    roadProps.SetLineColor (Color (0.4, 0.4, 0.4))
+    railProps = ClassGroupProperties()
+    railProps.SetLineColor (Color (0.2, 0.2, 0.2))
+    earthProps = ClassGroupProperties()
+    earthProps.SetLineColor (Color (0.9, 0.6, 0.3))
+    boundProps = ClassGroupProperties()
+    boundProps.SetLineColor (Color (0.1, 0.1, 0.1))
+    dangerProps = ClassGroupProperties()
+    dangerProps.SetLineColor (Color (1, 0.1, 0.1))
+
+    typeProps = {'River channel': waterProps, 'Alley-thick': roadProps,
+                 'Principal Highway-thick': minorProps,
+                 'Intermittent River': waterProps, 'Airport Runway': roadProps,
+                 'Danger line': dangerProps, 'Ramp': roadProps,
+                 'Arterial Road-medium': minorProps,
+                 'Major Highway-thick': majorProps,
+                 'Principal Highway-medium': majorProps, 'River': waterProps,
+                 'International Boundary': boundProps,
+                 'County Boundary': boundProps, 'Political Boundary':boundProps,
+                 'Ferry': waterProps, 'Bridge': roadProps, 'Road': roadProps,
+                 'Stream-thin': waterProps, 'Track/Trail': earthProps,
+                 'Railroad': railProps, 'Unpaved Road-thin': earthProps,
+                 'Arterial Road-thick': minorProps, 'Road-thin': roadProps,
+                 'Major Highway Connector-thick': majorProps,
+                 'Roundabout': minorProps}
+
+    types = list(set([p['parsedType'] for p in polylines]))
+    for t in types:
+        if t in typeProps.keys():
+            group = ClassGroupSingleton (value=t, props=typeProps[t], label=t)
+            clazz.AppendGroup (group)
+    return clazz
+
+def getBackgroundClassification():
+    """ Returns a Classification with a ClassGroup for the
+        background polygon """
+    clazz = Classification()
+    bgProps = ClassGroupProperties()
+    bgProps.SetFill (Color (1, 1, 0.9))
+    grp = ClassGroupSingleton (value="0x4b", props=bgProps, label="Background")
+    clazz.AppendGroup (grp)
+    return clazz
+
+
+
+def import_mp_dialog(context):
+    """Request filename from user and run importing of mp file.
+
+    context -- The Thuban context.
+    """
+    dlg = wx.FileDialog(context.mainwindow,
+                       _("Select MP file"), ".", "",
+                       _("Polish Map Files (*.mp)|*.mp|") +
+                       _("Text Files (*.txt)|*.txt|") +
+                       _("All Files (*.*)|*.*"),
+                       wx.OPEN|wx.OVERWRITE_PROMPT)
+    if dlg.ShowModal() == wx.ID_OK:
+        pfm_filename = internal_from_wxstring(dlg.GetPath())
+        dlg.Destroy()
+    else:
+        return
+
+    if pfm_filename.find ('.') == -1:
+        basename = filename
+    else:
+        basename = pfm_filename[:pfm_filename.rfind ('.')]
+
+    parser = pfm2shp (pfm_filename, basename)
+    # Now load the newly created shapefile
+    poi_filename = basename + '_poi.shp'
+    bg_filename = basename + '_bg.shp'
+    road_filename = basename + '_road.shp'
+    polygon_filename = basename + '_polygon.shp'
+    title = os.path.splitext(os.path.basename(pfm_filename))[0]
+    map = context.mainwindow.canvas.Map()
+    has_layers = map.HasLayers()
+
+    try:
+        store = context.session.OpenShapefile(bg_filename)
+    except IOError:
+        # the layer couldn't be opened
+        context.mainwindow.RunMessageBox(_('Add PFM Layer'),
+                           _("Can't open the file '%s'.") % bg_filename)
+    else:
+        layer = Layer(title + ' - Background', store)
+        layer.SetClassificationColumn ('Type')
+        layer.SetClassification (getBackgroundClassification())
+        map.AddLayer(layer)
+    try:
+        store = context.session.OpenShapefile(poi_filename)
+    except IOError:
+        # the layer couldn't be opened
+        context.mainwindow.RunMessageBox(_('Add PFM Layer'),
+                           _("Can't open the file '%s'.") % poi_filename)
+    else:
+        layer = Layer(title + ' - Points', store)
+        map.AddLayer(layer)
+
+    try:
+        store = context.session.OpenShapefile(polygon_filename)
+    except IOError:
+        # the layer couldn't be opened
+        context.mainwindow.RunMessageBox(_('Add PFM Layer'),
+                           _("Can't open the file '%s'.") % polygon_filename)
+    else:
+        layer = Layer(title + ' - Polygons', store)
+        layer.SetClassificationColumn ('Type')
+        layer.SetClassification (getPolygonClassification(parser.polygons))
+        map.AddLayer(layer)
+
+    try:
+        store = context.session.OpenShapefile(road_filename)
+    except IOError:
+        # the layer couldn't be opened
+        context.mainwindow.RunMessageBox(_('Add PFM Layer'),
+                           _("Can't open the file '%s'.") % road_filename)
+    else:
+        layer = Layer(title + ' - Lines', store)
+        layer.SetClassificationColumn ('Type')
+        layer.SetClassification (getPolylineClassification(parser.polylines))
+        map.AddLayer(layer)
+
+    if not has_layers:
+        # if we're adding a layer to an empty map, fit the
+        # new map to the window
+        context.mainwindow.canvas.FitMapToWindow()
+
+# register the new command
+registry.Add(Command('import-mp', _("(experimental) ") + _('Import PFM-file'),
+                     import_mp_dialog, helptext=_('Import a Polish Map File')))
+
+# find the extension menu (create it anew if not found)
+extensions_menu = main_menu.FindOrInsertMenu('extensions',
+                                               _('E&xtensions'))
+
+# finally add the new entry to the menu
+extensions_menu.InsertItem('import-mp')

Added: branches/WIP-pyshapelib-Unicode/thuban/Extensions/importMP/pfm.py
===================================================================
--- branches/WIP-pyshapelib-Unicode/thuban/Extensions/importMP/pfm.py	2008-08-08 23:39:11 UTC (rev 2864)
+++ branches/WIP-pyshapelib-Unicode/thuban/Extensions/importMP/pfm.py	2008-09-05 19:45:58 UTC (rev 2865)
@@ -0,0 +1,361 @@
+# Copyright (C) 2008 by Intevation GmbH
+# Authors:
+# Anthony Lenton <anthony at except.com.ar>
+#
+# This program is free software under the GPL (>=v2)
+# Read the file COPYING coming with Thuban for details.
+
+""" A Polish Map File parser.  This module contains the MPParser class, 
+    that does the real weight lifting for the importMP module. """
+
+import re
+
+class MPParseError(Exception):
+    def __init__(self, lNum, reason):
+        self.reason = reason
+        self.lineNumber = lNum
+    def __str__(self):
+        return "Line %d: %s" % (self.lineNumber, repr(self.reason))
+    def __repr__(self):
+        return "Line %d: %s" % (self.lineNumber, repr(self.reason))
+
+# These dictionaries should probably be moved in to a separate file
+polylineTypes = {'0x01': 'Major Highway-thick',
+                 '0x02': 'Principal Highway-thick',
+                 '0x03': 'Principal Highway-medium',
+                 '0x04': 'Arterial Road-medium',
+                 '0x05': 'Arterial Road-thick',
+                 '0x06': 'Road-thin',
+                 '0x07': 'Alley-thick',
+                 '0x08': 'Ramp',
+                 '0x09': 'Ramp',
+                 '0x0a': 'Unpaved Road-thin',
+                 '0x0b': 'Major Highway Connector-thick',
+                 '0x0c': 'Roundabout',
+                 '0x14': 'Railroad',
+                 '0x15': 'Shoreline',
+                 '0x16': 'Track/Trail',
+                 '0x18': 'Stream-thin',
+                 '0x19': 'Time-Zone',
+                 '0x1a': 'Ferry',
+                 '0x1b': 'Ferry',
+                 '0x1c': 'Political Boundary',
+                 '0x1d': 'County Boundary',
+                 '0x1e': 'International Boundary',
+                 '0x1f': 'River',
+                 '0x20': 'Land Contour (thin)',
+                 '0x21': 'Land Contour (medium)',
+                 '0x22': 'Land Contour (thick)',
+                 '0x23': 'Depth Contour (thin)',
+                 '0x24': 'Depth Contour (medium)',
+                 '0x25': 'Depth Contour (thick)',
+                 '0x26': 'Intermittent River',
+                 '0x27': 'Airport Runway',
+                 '0x28': 'Pipeline',
+                 '0x29': 'Power line',
+                 '0x2a': 'Marine Boundary (no line)',
+                 '0x2b': 'Marine Hazard (no line)',
+                 '0x0100': 'Miscellaneous line',
+                 '0x0101': 'Line',
+                 '0x0102': 'Cartographic line',
+                 '0x0103': 'Road',
+                 '0x0104': 'Clearing line',
+                 '0x0105': 'Contour line',
+                 '0x0106': 'Overhead cable',
+                 '0x0107': 'Bridge',
+                 '0x0108': 'Recommended route',
+                 '0x0109': 'Chart border',
+                 '0x0300': 'Depth contour',
+                 '0x0301': 'Depth contour value',
+                 '0x0307': 'Intertidal zone border',
+                 '0x0400': 'Obstruction line',
+                 '0x0401': 'Submarine cable',
+                 '0x0402': 'Submarine pipeline',
+                 '0x0403': 'Pile barrier',
+                 '0x0404': 'Fishing stakes',
+                 '0x0405': 'Supply pipeline area',
+                 '0x0406': 'Submarine cable area',
+                 '0x0407': 'Dumping ground',
+                 '0x0408': 'Explosive dumping ground',
+                 '0x0409': 'Danger line',
+                 '0x040a': 'Overhead cable',
+                 '0x040b': 'Submerged construction',
+                 '0x040c': 'Pier/jetty',
+                 '0x0500': 'Restriction',
+                 '0x0501': 'Anchoring prohibited',
+                 '0x0502': 'Fishing prohibited',
+                 '0x0503': 'Prohibited area',
+                 '0x0504': 'Military practice area',
+                 '0x0505': 'Anchoring and fishing prohibited',
+                 '0x0506': 'Limit of nature reservation',
+                 '0x0507': 'Restricted area',
+                 '0x0508': 'Minefield',
+                 '0x0600': 'Miscellaneous line',
+                 '0x0601': 'Cartographic line',
+                 '0x0602': 'Traffic separation line',
+                 '0x0603': 'International maritime boundary',
+                 '0x0604': 'Straight territorial sea baseline',
+                 '0x0605': 'Seaward limit of territorial sea',
+                 '0x0606': 'Anchorage area',
+                 '0x0607': 'Quarantine anchorage area',
+                 '0x0608': 'Fishery zone',
+                 '0x0609': 'Swept area',
+                 '0x060a': 'Traffic separation zone',
+                 '0x060b': 'Limit of exclusive economic zone',
+                 '0x060c': 'Established direction of traffic flow',
+                 '0x060d': 'Recommended direction of traffic flow',
+                 '0x060e': 'Harbour limit',
+                 '0x060f': 'Inadequately surveyed area',
+                 '0x0610': 'Inshore traffic zone',
+                 '0x0611': 'Limit of traffic lane',
+                 '0x0701': 'River channel',
+                 '0x0702': 'Submerged object',
+                 '0x0706': 'Chart boundary'}
+
+polygonTypes = {'0x01': 'City',
+                '0x02': 'City',
+                '0x03': 'City',
+                '0x04': 'Military',
+                '0x05': 'Car Park (Parking Lot)',
+                '0x06': 'Parking Garage',
+                '0x07': 'Airport',
+                '0x08': 'Shopping Centre',
+                '0x09': 'Marina',
+                '0x0a': 'University',
+                '0x0b': 'Hospital',
+                '0x0c': 'Industrial',
+                '0x0d': 'Reservation',
+                '0x0e': 'Airport Runway',
+                '0x13': 'Man made area',
+                '0x14': 'National park',
+                '0x15': 'National park',
+                '0x16': 'National park',
+                '0x17': 'City Park',
+                '0x18': 'Golf',
+                '0x19': 'Sport',
+                '0x1a': 'Cemetery',
+                '0x1e': 'State Park',
+                '0x1f': 'State Park',
+                '0x28': 'Ocean',
+                '0x3b': 'Blue-Unknown',
+                '0x32': 'Sea',
+                '0x3b': 'Blue-Unknown',
+                '0x3c': 'Lake',
+                '0x3d': 'Lake',
+                '0x3e': 'Lake',
+                '0x3f': 'Lake',
+                '0x40': 'Lake',
+                '0x41': 'Lake',
+                '0x42': 'Lake',
+                '0x43': 'Lake',
+                '0x44': 'Lake',
+                '0x45': 'Blue-Unknown',
+                '0x46': 'River',
+                '0x47': 'River',
+                '0x48': 'River',
+                '0x49': 'River',
+                '0x4b': 'Background',
+                '0x4c': 'Intermittent River/Lake',
+                '0x4d': 'Glacier',
+                '0x4e': 'Orchard or plantation',
+                '0x4f': 'Scrub',
+                '0x50': 'Woods',
+                '0x51': 'Wetland',
+                '0x52': 'Tundra',
+                '0x53': 'Flats',
+                '0x0100': 'Land - white',
+                '0x0101': 'Land - non-urban',
+                '0x0102': 'Land - urban',
+                '0x0103': 'Chart exclusion area',
+                '0x0104': 'Chart background',
+                '0x0105': 'Bridge',
+                '0x0300': 'Depth area - white 1',
+                '0x0301': 'Intertidal zone',
+                '0x0302': 'Depth area - blue 1',
+                '0x0303': 'Depth area - blue 2',
+                '0x0304': 'Depth area - blue 3',
+                '0x0305': 'Depth area - blue 4',
+                '0x0306': 'Depth area - blue 5',
+                '0x0307': 'Depth area - white',
+                '0x0400': 'Obstruction (invisible)',
+                '0x0401': 'Submarine cable (invisible)',
+                '0x0402': 'Submarine pipeline (invisible)',
+                '0x0403': 'Pile barrier (invisible)',
+                '0x0404': 'Fishing stakes (invisible)',
+                '0x0405': 'Supply pipeline area/line (invisible)',
+                '0x0406': 'Submarine cable area/line (invisible)',
+                '0x0407': 'Dumping ground (invisible)',
+                '0x0408': 'Explosive dumping ground (invisible)',
+                '0x0409': 'Danger line (invisible)',
+                '0x040a': 'Overhead cable (invisible)',
+                '0x040b': 'Submerged construction (invisible)',
+                '0x040c': 'Pier/jetty (invisible)',
+                '0x0500': 'Restriction area/line (invisible)',
+                '0x0501': 'Anchoring prohibited (invisible)',
+                '0x0502': 'Fishing prohibited (invisible)',
+                '0x0503': 'Prohibited area (invisible)',
+                '0x0504': 'Military practice area (invisible)',
+                '0x0505': 'Anchoring and fishing prohibited (invisible)',
+                '0x0506': 'Limit of nature reservation (invisible)',
+                '0x0507': 'Restricted area (invisible)',
+                '0x0508': 'Minefield (invisible)',
+                '0x0600': 'Miscellaneous area',
+                '0x0601': 'Cartographic area',
+                '0x0602': 'Traffic separation area',
+                '0x0603': 'International maritime boundary',
+                '0x0604': 'Straight territorial sea baseline',
+                '0x0605': 'Seaward limit of territorial sea',
+                '0x0606': 'Anchorage area',
+                '0x0607': 'Quarantine anchorage area',
+                '0x0608': 'Fishery zone',
+                '0x0609': 'Swept area',
+                '0x060a': 'Traffic separation zone',
+                '0x060b': 'Limit of exclusive economic zone',
+                '0x060c': 'Established direction of traffic flow',
+                '0x0701': 'Fishing area',
+                '0x0702': 'Restricted area',
+                '0x0703': 'Anchorage area',
+                '0x0704': 'Fishing Hot Spots chart'}
+
+class MPParser(object):
+    """ Polish Map File parser.  The main method is 'parse', which
+        receives a file object as its single argument.  The results of
+        the parsing can then be retrieved via 'pois', 'polygons', 'polylines',
+        and other attributes.
+    """
+    fields = {'poi': ['Data0', 'Label', 'Origin0'],
+              'rgn10': ['Data0', 'Label', 'Origin0'],
+              'rgn20': ['Data0', 'Label', 'Origin0'],
+              'polyline': ['Type', 'Data0', 'Origin0', 'Label'],
+              'rgn40': ['Type', 'Data0', 'Origin0', 'Label'],
+              'polygon': ['Type', 'Data0', 'Origin0', 'Label'],
+              'rgn80': ['Type', 'Data0', 'Origin0', 'Label'],
+              'img id': ['Name'] }
+    def __init__(self):
+        self.pois = []
+        self.polygons = []
+        self.polylines = []
+        self.parsedLines = 0
+        self.parsedSections = 0
+        self.mapName = ""
+
+    def parse (self, fp):
+        """ Parse a map file. 'fp' should be a readable file object.
+            After parsing the results can be accessed using 'pois', 'polylines',
+            'polygons', and other attributes.
+            Returns a dictionary with the results of the parsing, but this can
+            be most often discarded directly """
+        def sectionBounder (line):
+            return line[0] == '[' and line[-1] == ']'
+        def sectionEnd (line):
+            return (sectionBounder (line) and
+                   (line.lower() == '[end]' or
+                   line.lower().startswith('[end-')))
+        def sectionStart (line):
+            return sectionBounder (line) and not sectionEnd (line)
+        parsed = {}
+        for kind in self.fields.keys():
+            parsed[kind] = []
+        inSection = False
+        sectionName = None
+        lNum = 0 # Number of lines parsed so far
+        sNum = 0 # Number of sections parsed so far
+        for line in fp.readlines():
+            lNum += 1
+            line = line.strip()
+            if len(line) == 0 or line[0] == ';': # Drop blank lines and comments
+                continue
+            if not inSection:
+                if not sectionBounder (line):
+                    raise MPParseError (lNum, "Line not within a section")
+                elif sectionEnd (line):
+                    raise MPParseError (lNum, "Section End without a section")
+                else:
+                    sectionName = line[1:-1].lower()
+                    section = {}
+                    inSection = True
+                    sNum += 1
+            else:
+                if not sectionBounder (line):
+                    if sectionName in self.fields.keys():
+                        parts = line.split('=',1)
+                        if len(parts) != 2:
+                            raise MPParseError (lNum, "Invalid line")
+                        key, value = map(str.strip, parts)
+                        if key in self.fields[sectionName]:
+                            section[key] = value
+                elif sectionStart (line):
+                    raise MPParseError (lNum, "Section Start within a section")
+                else:
+                    if line.startswith ('[end-') and line[5:-1] != sectionName:
+                        raise MPParseError (lNum, "Section name mismatch")
+                    if sectionName in self.fields.keys():
+                        parsed[sectionName].append (section)
+                    inSection = False
+        # These last checks are a bit pedantic (not needed to do our
+        # job) but we're validating the source file a bit.
+        if inSection:
+            raise MPParseError (lNum, "End-of-file found within a section")
+        if len(parsed['img id']) == 0:
+            raise MPParseError (lNum, "No [IMG ID] section found")
+        elif len(parsed['img id']) > 1:
+            raise MPParseError (lNum, "Multiple [IMG ID] sections found")
+        else:
+            self.mapName = parsed['img id'][0].get ('Name', "")
+
+        # Ok, enough checks, set the data!
+        self.parsedLines = lNum
+        self.parsedSections = sNum
+
+        self.pois = parsed['poi'] + parsed['rgn10'] + parsed['rgn20']
+        twople = re.compile(r'\([-+]?(?P<lat>\d+(\.\d*)?|\.\d+), ' \
+                             r'*[-+]?(?P<long>\d+(\.\d*)?|\.\d+)\)')
+        for poi in self.pois:
+            assert poi.has_key ('Data0') or poi.has_key ('Origin0')
+            data = poi.get('Data0', poi.get('Origin0'))
+            match = twople.match (data)
+            if not match is None:
+                poi['long'] = -float (match.group('long'))
+                poi['lat'] = -float (match.group('lat'))
+        self.polygons = parsed['polygon'] + parsed['rgn80']
+        for poly in self.polygons:
+            poly['long'] = []
+            poly['lat'] = []
+            assert poly.has_key ('Data0') or poly.has_key ('Origin0')
+            data = poly.get('Data0', poly.get('Origin0'))
+            while len(data) > 0:
+                match = twople.match (data)
+                if not match is None:
+                    poly['long'].append (-float (match.group('long')))
+                    poly['lat'].append (-float (match.group('lat')))
+                    data = data[match.end() + 1:]
+            if poly['long'][-1] != poly['long'][0] or poly['lat'][-1] != poly['lat'][0]:
+                poly['long'].append(poly['long'][0])
+                poly['lat'].append(poly['lat'][0])
+            try:
+                poly['parsedType'] = polygonTypes[poly['Type']]
+            except KeyError, e:
+                # Attempt to read 0xe as 0x0e, for example
+                newType = '0x0' + poly['Type'][2:]
+                poly['parsedType'] = polygonTypes.get(newType, "")
+
+        self.polylines = parsed['polyline'] + parsed['rgn40']
+        for poly in self.polylines:
+            poly['long'] = []
+            poly['lat'] = []
+            assert poly.has_key ('Data0') or poly.has_key ('Origin0')
+            data = poly.get('Data0', poly.get('Origin0'))
+            while len(data) > 0:
+                match = twople.match (data)
+                if not match is None:
+                    poly['long'].append (-float (match.group('long')))
+                    poly['lat'].append (-float (match.group('lat')))
+                    data = data[match.end() + 1:]
+            try:
+                poly['parsedType'] = polylineTypes[poly['Type']]
+            except KeyError, e:
+                # Attempt to read 0xe as 0x0e, for example
+                newType = '0x0' + poly['Type'][2:]
+                poly['parsedType'] = polylineTypes.get(newType, "")
+        return parsed
+


Property changes on: branches/WIP-pyshapelib-Unicode/thuban/Extensions/importMP/test
___________________________________________________________________
Name: svn:ignore
   + *.pyc
*~



Added: branches/WIP-pyshapelib-Unicode/thuban/Extensions/importMP/test/snippets.py
===================================================================
--- branches/WIP-pyshapelib-Unicode/thuban/Extensions/importMP/test/snippets.py	2008-08-08 23:39:11 UTC (rev 2864)
+++ branches/WIP-pyshapelib-Unicode/thuban/Extensions/importMP/test/snippets.py	2008-09-05 19:45:58 UTC (rev 2865)
@@ -0,0 +1,492 @@
+# This file contains snippets used by the testing functions.
+# They should be in alphabetical order
+
+bounderMismatch = """
+[img 1]
+[end-yonk]
+"""
+
+caseSensitivity1 = """
+[IMG ID]
+[END-IMG ID]
+"""
+
+caseSensitivity2 = """
+[img ID]
+[enD-IMG id]
+"""
+
+caseSensitivity3 = """
+[ImG Id]
+[EnD-imG iD]
+"""
+
+doubleSectionClose = """
+[img id]
+[end-img id]
+[end-img id]
+"""
+
+headerWithComments = """[img id]
+This=is a test MPFile
+;I have no idea what it's about, But I shouldn't care
+; I do know that this is a comment
+; So it should be removed.
+; And blank lines should be removed too.
+
+=This isn't a comment.
+T=his; isn't either
+   ; let's say this is a comment
+   ; to be a bit more robust
+[end]
+"""
+
+incompleteSection = """
+[img id]
+"""
+
+justHeader = """
+[img id]
+Dummy=I'm a fake MPFile
+[end]
+"""
+
+mapWithName = """
+[img id]
+Name = My Test Map
+[end]
+"""
+
+miniLobos = """
+[IMG ID]
+CodePage=850
+LblCoding=9
+ID=54010076
+Name=Lobos
+[END-IMG ID]
+
+[Countries]
+Country1=Argentina~[0x1d]ARG
+[END-Countries]
+
+[Regions]
+Region1=Buenos Aires~[0x1d]BA
+CountryIdx1=1
+[END-Regions]
+
+[Cities]
+City1=Abbott
+RegionIdx1=1
+[END-Cities]
+
+[ZipCodes]
+ZipCode1=7200
+[END-ZipCodes]
+
+[Restrict]
+Nod=155306
+TraffPoints=155988,155306,155988
+TraffRoads=8609,8609
+Time=
+[END-Restrict]
+
+[DICTIONARY]
+;           0        1         2         3         4   
+;           1234567890123456789012345678901234567890123
+Level1RGN40=1111111111110000000111011111111111111111111
+Level2RGN40=1111111111110000000111011111111111111111111
+Level3RGN40=1111100101110000000111011111111011011101100
+Level4RGN40=1111000001110000000010001111111001001000000
+Level5RGN40=1100000000000000000010001011110000000000000
+Level6RGN40=1000000000000000000010001000010000000000000
+[END-DICTIONARY]
+
+[POI]
+Type=0x2500
+Label=Peaje Saladillo
+EndLevel=6
+StreetDesc=Ruta 205 Km. 167,00
+Data0=(-35.51966,-59.67464)
+[END]
+
+[POI]
+Type=0x4400
+Label=ACA
+EndLevel=6
+Data0=(-35.70035,-58.88981)
+[END]
+
+[POI]
+Type=0x5903
+Label=Saladillo
+EndLevel=6
+Data0=(-35.60043,-59.81360)
+[END]
+
+[POI]
+Type=0x6401
+EndLevel=6
+Data0=(-35.65026,-58.85069)
+[END]
+
+[POLYLINE]
+Type=0xa
+EndLevel=6
+RoadID=1970
+RouteParam=3,0,0,0,0,0,0,0,0,0,0,0
+Data0=(-35.07797,-59.09923),(-35.08840,-59.11088)
+Nod1=0,34258,0
+Nod2=1,34259,0
+[END]
+
+[POLYLINE]
+Type=0xa
+EndLevel=6
+RoadID=1973
+RouteParam=3,0,0,0,0,0,0,0,0,0,0,0
+Data0=(-35.24004,-59.48067),(-35.24277,-59.49114),(-35.24497,-59.49020)
+Nod1=0,29389,0
+Nod2=2,29386,0
+[END]
+
+[POLYGON]
+Type=0x17
+Label=Plaza Arturo Illia
+EndLevel=6
+Data0=(-35.76743,-58.49350),(-35.76776,-58.49378),(-35.76782,-58.49371)
+[END]
+
+"""
+
+missingZeroType = """
+[IMG ID]
+[END]
+
+[POLYGON]
+Type=0x0e
+Label=An Airport Runway
+EndLevel=6
+Data0=(-35.76743,-58.49350),(-35.76776,-58.49378),(-35.76782,-58.49371)
+[END]
+
+[POLYGON]
+Type=0xe
+Label=Another Airport Runway
+EndLevel=6
+Data0=(-35.76743,-58.49350),(-35.76776,-58.49378),(-35.76782,-58.49371)
+[END]
+
+"""
+
+mixedPois = """
+[IMG ID]
+[END]
+
+[RGN20]
+Type=0xd
+Label=BIALET MASSE
+City=Y
+CityIdx=17
+Origin0=(-31.315284,-64.461891)
+[END-RGN20]
+
+[RGN20]
+Type=0xc
+Label=VALLE HERMOSO
+City=Y
+CityIdx=184
+Origin0=(-31.117530,-64.482666)
+[END-RGN20]
+
+[RGN10]
+Type=0x3002
+Label=MATERNIDAD
+CityIdx=44
+Origin0=(-31.423515,-64.163887)
+[END-RGN10]
+
+[RGN10]
+Type=0x2b01
+Label=HOTEL
+CityIdx=92
+Origin0=(-31.092639,-64.477066)
+[END-RGN10]
+
+[POI]
+Type=0x2f08
+Label=Est. Salvador Maria
+EndLevel=6
+StreetDesc=F. C. G. R.
+CityIdx=28
+Data0=(-35.30298,-59.16738)
+[END]
+
+[POI]
+Type=0xe00
+Label=Salvador Maria
+EndLevel=6
+City=Y
+CityIdx=28
+Data0=(-35.29979,-59.16765)
+[END]
+
+"""
+
+mixedRGN40sAndPolylines = """
+[IMG ID]
+[END]
+
+[RGN40]
+Type=0x18
+Data0=(-31.172805,-64.999877),(-31.170059,-64.997474)
+[END-RGN40]
+
+[RGN40]
+Type=0x18
+Data0=(-31.124225,-64.999877),(-31.137958,-64.982543)
+[END-RGN40]
+
+[POLYLINE]
+Type=0xa
+EndLevel=6
+RoadID=4532
+RouteParam=3,0,0,0,0,0,0,0,0,0,0,0
+Data0=(-35.39861,-59.34420),(-35.40269,-59.34945)
+Nod1=0,29465,0
+Nod2=1,29456,0
+[END]
+
+[POLYLINE]
+Type=0xa
+EndLevel=6
+RoadID=4433
+RouteParam=3,0,0,0,0,0,0,0,0,0,0,0
+Data0=(-35.38428,-59.32179),(-35.37814,-59.31504)
+Nod1=0,29646,0
+Nod2=1,34580,0
+[END]
+
+"""
+
+mixedRGN80sAndPolygons = """
+[IMG ID]
+[END]
+
+[RGN80]
+Type=0x41
+Label=LA QUINTANA
+Data0=(-31.839323,-64.431465),(-31.843271,-64.430091),(-31.848936,-64.435241)
+[END-RGN80]
+
+[RGN80]
+Type=0x3c
+Label=EMBALSE LOS MOLINOS
+Data0=(-31.826664,-64.571586),(-31.826664,-64.572616),(-31.826320,-64.572273)
+[END-RGN80]
+
+[POLYGON]
+Type=0x19
+EndLevel=6
+Data0=(-35.40248,-59.32782),(-35.40348,-59.32778),(-35.40357,-59.32937)
+[END]
+
+[POLYGON]
+Type=0xb
+EndLevel=6
+Data0=(-35.40273,-59.32503),(-35.40338,-59.32611),(-35.40402,-59.32553)
+[END]
+
+"""
+
+nonsenseBounder = """
+[img id]
+[yonk]
+"""
+
+nothingness = ""
+
+polyTypes = """
+[IMG ID]
+[END]
+
+[POLYLINE]
+Type=0x1
+Data0=(-35.38428,-59.32179),(-35.37814,-59.31504)
+[END]
+
+[POLYGON]
+Type=0x1
+Data0=(-35.40273,-59.32503),(-35.40338,-59.32611)
+[END]
+
+"""
+
+RGN10s = """
+[IMG ID]
+[END]
+
+[RGN10]
+Type=0x2f04
+Label=FALDA DEL CARMEN
+CityIdx=6
+Origin0=(-31.583763,-64.456230)
+[END-RGN10]
+
+[RGN10]
+Type=0x2f03
+Label=BERTA MOTORSPORT
+CityIdx=6
+Origin0=(-31.647449,-64.408508)
+[END-RGN10]
+
+[RGN10]
+Type=0x2f01
+Label=ESSO
+CityIdx=6
+Origin0=(-31.658950,-64.409706)
+[END-RGN10]
+
+[RGN10]
+Type=0x2f01
+Label=YPF
+CityIdx=6
+Origin0=(-31.658950,-64.409019)
+[END-RGN10]
+"""
+
+RGN20s = """
+[IMG ID]
+[END]
+
+[RGN20]
+Type=0xc
+Label=MINA CLAVERO
+City=Y
+CityIdx=122
+Origin0=(-31.724071,-65.003494)
+[END-RGN20]
+
+[RGN20]
+Type=0x6
+Label=VILLA GENERAL BELGRANO
+City=Y
+CityIdx=200
+Origin0=(-31.976524,-64.558883)
+[END-RGN20]
+
+[RGN20]
+Type=0xb
+Label=LA FALDA
+City=Y
+CityIdx=92
+Origin0=(-31.099506,-64.477340)
+[END-RGN20]
+
+[RGN20]
+Type=0xd
+Label=VILLA CAEIRO
+City=Y
+CityIdx=190
+Origin0=(-31.291595,-64.462577)
+[END-RGN20]
+"""
+
+RGN40s = """
+[IMG ID]
+[END]
+
+[RGN40]
+Type=0x1f
+Label=RIO LOS CONDORITOS
+Data0=(-31.688133,-64.676124),(-31.686073,-64.674064),(-31.685730,-64.673210)
+[END-RGN40]
+
+[RGN40]
+Type=0x18
+Data0=(-31.463600,-64.859291),(-31.451927,-64.880577),(-31.446777,-64.897911)
+[END-RGN40]
+
+[RGN40]
+Type=0x18
+Data0=(-31.529861,-64.898086),(-31.530376,-64.900314),(-31.526428,-64.909240)
+[END-RGN40]
+
+[RGN40]
+Type=0x14
+Data0=(-30.821243,-64.993354),(-30.830513,-64.999877)
+[END-RGN40]
+"""
+
+RGN80s = """
+[IMG ID]
+[END]
+
+[RGN80]
+Type=0x41
+Data0=(-30.129791,-64.816200),(-30.133224,-64.814140),(-30.137859,-64.818092)
+[END-RGN80]
+
+[RGN80]
+Type=0x3
+Data0=(-30.712581,-64.813629),(-30.713096,-64.808303),(-30.720478,-64.803672)
+[END-RGN80]
+
+[RGN80]
+Type=0x41
+Label=LA QUINTANA
+Data0=(-31.839323,-64.431465),(-31.843271,-64.430091),(-31.848936,-64.435241)
+[END-RGN80]
+
+[RGN80]
+Type=0x3c
+Label=EMBALSE LOS MOLINOS
+Data0=(-31.826664,-64.571586),(-31.826664,-64.572616),(-31.826320,-64.572273)
+[END-RGN80]
+
+"""
+
+
+twoHeaderSections = """
+[img id]
+[end]
+; And now, for something completely different:
+[img id]
+[end]
+"""
+
+weirdTypes = """
+[IMG ID]
+[END]
+
+[POI]
+Type=0x999999
+Data0=(-35.51966,-59.67464)
+[END]
+
+[POI]
+Type=-3.14e27
+Data0=(-35.60043,-59.81360)
+[END]
+
+[POI]
+Type=Sarasa
+Data0=(-35.70035,-58.88981)
+[END]
+
+[POLYLINE]
+Type=0x123456789
+Data0=(-35.07797,-59.09923),(-35.08840,-59.11088)
+[END]
+
+[POLYLINE]
+Type=1919191919191919191919191919
+Data0=(-35.24004,-59.48067),(-35.24277,-59.49114),(-35.24497,-59.49020)
+[END]
+
+[POLYGON]
+Type=NobodyExpectsTheSpanishInquisition
+Data0=(-35.76743,-58.49350),(-35.76776,-58.49378),(-35.76782,-58.49371)
+[END]
+
+"""
+

Added: branches/WIP-pyshapelib-Unicode/thuban/Extensions/importMP/test/test_pfm.py
===================================================================
--- branches/WIP-pyshapelib-Unicode/thuban/Extensions/importMP/test/test_pfm.py	2008-08-08 23:39:11 UTC (rev 2864)
+++ branches/WIP-pyshapelib-Unicode/thuban/Extensions/importMP/test/test_pfm.py	2008-09-05 19:45:58 UTC (rev 2865)
@@ -0,0 +1,138 @@
+# Copyright (c) 2008 by Intevation GmbH
+# Authors:
+# Anthony Lenton <anthony at except.com.ar>
+#
+# This program is free software under the GPL (>=v2)
+# Read the file COPYING coming with Thuban for details.
+
+"""
+Tests for the PFM importer.
+"""
+import unittest
+from StringIO import StringIO
+from Extensions.importMP.pfm import MPParser, MPParseError
+import snippets
+
+class TestPFM (unittest.TestCase):
+    def testInitialValue(self):
+        """ Check that the parser has good initial values """
+        parser = MPParser()
+        self.assertEquals (parser.mapName, "")
+        self.assertEquals (parser.parsedLines, 0)
+        self.assertEquals (parser.parsedSections, 0)
+        self.assertEquals (parser.pois, [])
+        self.assertEquals (parser.polygons, [])
+        self.assertEquals (parser.polylines, [])
+
+    def testParsedLines(self):
+        """ Check that comments and blank lines are skipped correctly """
+        parser = MPParser()
+        parser.parse (StringIO(snippets.justHeader))
+        self.assertEquals (parser.parsedLines, 4)
+        parser = MPParser()
+        parser.parse (StringIO(snippets.headerWithComments))
+        self.assertEquals (parser.parsedLines, 12)
+
+    def testSections (self):
+        """ Check that sections are matched up properly """
+        parser = MPParser()
+        parser.parse (StringIO(snippets.justHeader))
+        self.assertEquals (parser.parsedSections, 1)
+        parser = MPParser()
+        mp = StringIO (snippets.nonsenseBounder)        
+        self.assertRaises (MPParseError, parser.parse, mp)
+        parser = MPParser()
+        mp = StringIO (snippets.bounderMismatch)
+        self.assertRaises (MPParseError, parser.parse, mp)
+        parser = MPParser()
+        mp = StringIO (snippets.doubleSectionClose)
+        self.assertRaises (MPParseError, parser.parse, mp)
+
+    def testCaseInsensitive (self):
+        """ Check that no exception is raised if capitals are used"""
+        parser = MPParser()
+        parser.parse (StringIO (snippets.caseSensitivity1))
+        parser = MPParser()
+        parser.parse (StringIO (snippets.caseSensitivity2))
+        parser = MPParser()
+        parser.parse (StringIO (snippets.caseSensitivity3))
+
+    def testIncompleteSection (self):
+        """ Check that an exception is raised if the last section is
+            left open """
+        parser = MPParser()
+        mp = StringIO(snippets.incompleteSection)
+        self.assertRaises (MPParseError, parser.parse, mp)
+
+    def testHeaderSection (self):
+        """ Check that the header section is parsed """
+        parser = MPParser ()
+        mp = StringIO(snippets.nothingness)
+        self.assertRaises (MPParseError, parser.parse, mp)
+        parser = MPParser()
+        mp = StringIO(snippets.twoHeaderSections)
+        self.assertRaises (MPParseError, parser.parse, mp)
+        parser = MPParser()
+        parser.parse(StringIO(snippets.mapWithName))
+        self.assertEquals (parser.mapName, "My Test Map")
+
+    def testSample (self):
+        parser = MPParser()
+        parser.parse (StringIO(snippets.miniLobos))
+        self.assertEquals(len(parser.pois), 4)
+        self.assertEquals(len(parser.polylines), 2)
+        self.assertEquals(len(parser.polygons), 1)
+
+    def testPolylines (self):
+        parser = MPParser()
+        parser.parse (StringIO(snippets.RGN40s))
+        self.assertEquals(len(parser.polylines), 4)
+        parser = MPParser()
+        parser.parse (StringIO(snippets.mixedRGN40sAndPolylines))
+        self.assertEquals(len(parser.polylines), 4)
+       
+    def testPolygons (self):
+        parser = MPParser()
+        parser.parse (StringIO(snippets.RGN80s))
+        self.assertEquals(len(parser.polygons), 4)
+        parser = MPParser()
+        parser.parse (StringIO(snippets.mixedRGN80sAndPolygons))
+        self.assertEquals(len(parser.polygons), 4)
+       
+    def testPois (self):
+        parser = MPParser()
+        parser.parse (StringIO(snippets.RGN10s))
+        self.assertEquals(len(parser.pois), 4)
+        parser = MPParser()
+        parser.parse (StringIO(snippets.RGN20s))
+        self.assertEquals(len(parser.pois), 4)
+        parser = MPParser()
+        parser.parse (StringIO(snippets.mixedPois))
+        self.assertEquals(len(parser.pois), 6)
+
+    def testDontCrashWithWeirdTypes (self):
+        parser = MPParser()
+        parser.parse (StringIO(snippets.weirdTypes))
+        self.assertEquals(len(parser.pois), 3)
+        self.assertEquals(len(parser.polylines), 2)
+        self.assertEquals(len(parser.polygons), 1)
+
+    def testMissingTwoCharFormatWorks (self):
+        """ Test that if the type 0xe works as well as 0x0e, for example"""
+        parser = MPParser()
+        parser.parse (StringIO(snippets.missingZeroType))
+        self.assertEquals(len(parser.polygons), 2)
+        self.assertEquals(parser.polygons[0]['parsedType'], "Airport Runway")
+        self.assertEquals(parser.polygons[1]['parsedType'], "Airport Runway")
+
+    def testTypesAreTheRightKind (self):
+        """ Test that types from polylines and polygons come from the
+            right list of types """
+        p = MPParser()
+        p.parse (StringIO(snippets.polyTypes))
+        self.assertEquals(p.polygons[0]['parsedType'], "City")
+        self.assertEquals(p.polylines[0]['parsedType'], "Major Highway-thick")
+
+if __name__ == "__main__":
+    unittest.main()
+


Property changes on: branches/WIP-pyshapelib-Unicode/thuban/Extensions/mouseposition
___________________________________________________________________
Name: svn:ignore
   + *.pyc
*~




Property changes on: branches/WIP-pyshapelib-Unicode/thuban/Extensions/ogr
___________________________________________________________________
Name: svn:ignore
   + *.pyc
*~




Property changes on: branches/WIP-pyshapelib-Unicode/thuban/Extensions/ogr/test
___________________________________________________________________
Name: svn:ignore
   + *.pyc
*~




Property changes on: branches/WIP-pyshapelib-Unicode/thuban/Extensions/svgexport
___________________________________________________________________
Name: svn:ignore
   + *.pyc
*~




Property changes on: branches/WIP-pyshapelib-Unicode/thuban/Extensions/svgexport/test
___________________________________________________________________
Name: svn:ignore
   + *.pyc
*~




Property changes on: branches/WIP-pyshapelib-Unicode/thuban/Extensions/umn_mapserver
___________________________________________________________________
Name: svn:ignore
   + *.pyc
*~



Modified: branches/WIP-pyshapelib-Unicode/thuban/Extensions/umn_mapserver/mapfile.py
===================================================================
--- branches/WIP-pyshapelib-Unicode/thuban/Extensions/umn_mapserver/mapfile.py	2008-08-08 23:39:11 UTC (rev 2864)
+++ branches/WIP-pyshapelib-Unicode/thuban/Extensions/umn_mapserver/mapfile.py	2008-09-05 19:45:58 UTC (rev 2865)
@@ -42,6 +42,7 @@
 from Thuban.Model.classification import ClassGroupDefault, \
                                         ClassGroupSingleton, ClassGroupRange
 
+import mapscript
 from mapscript import layerObj, classObj, colorObj, styleObj, rectObj, symbolObj, \
                       pointObj, lineObj
                       
@@ -84,17 +85,30 @@
 scalebar_style_type = { 0:"0",
                         1:"1" }
 
-scalebar_position_type = { 0:"ul",
-                           1:"lr",
-                           2:"ur",
-                           3:"ll",
-                           6:"uc",
-                           7:"lc"}
+scalebar_position_type = { mapscript.MS_UL:"ul",
+                           mapscript.MS_LR:"lr",
+                           mapscript.MS_UR:"ur",
+                           mapscript.MS_LL:"ll",
+                           mapscript.MS_UC:"uc",
+                           mapscript.MS_LC:"lc"}
 
 layer_status_type = { 0:"OFF",
                       1:"ON",
                       2:"default"}
 
+layer_connection_type = { mapscript.MS_INLINE:"inline",
+                          mapscript.MS_SHAPEFILE:"shapefile",
+                          mapscript.MS_TILED_SHAPEFILE:"tiled shapefile",
+                          mapscript.MS_SDE:"sde",
+                          mapscript.MS_OGR:"ogr",
+                          mapscript.MS_POSTGIS:"postgis",
+                          mapscript.MS_WMS:"wms",
+                          mapscript.MS_ORACLESPATIAL:"oracle spatial",
+                          mapscript.MS_WFS:"wfs",
+                          mapscript.MS_GRATICULE:"graticule",
+                          mapscript.MS_MYGIS:"mygis",
+                          mapscript.MS_RASTER:"raster"}
+
 legend_position_type = { 0:"ul",
                          1:"lr",
                          2:"ur",
@@ -306,14 +320,14 @@
     defines a single symbol which is used in the Symbolset
     
     the following settings are used:
-    name, type,
+    name, type, filled,
     
     the following settings are not used:
-    sizex, sizey, points, numpoints, filled, stylelength,
+    sizex, sizey, points, numpoints, stylelength,
     style, imagepath, transparent, transparentcolor, character, antialias,
     font, gap, position, linecap, linejoin, linejoinmaxsize, setPoints(),
     getPoints(), setStyle()
-    """    
+    """
     def __init__(self, mf_symbol = "newone"):
         # create a circle Object like shown in Thuban
         # because Thuban don't support other symbols
@@ -321,13 +335,14 @@
 	# TODO: include the options to create a symbol, but
 	#      first implement a methode to edit Symbols in Thuban
         if mf_symbol == "newone":
-            mf_symbol = symbolObj("")            
+            mf_symbol = symbolObj("")
             newpoint = pointObj()
             newpoint.x = 1
             newpoint.y = 1
             newline = lineObj()
             newline.add(newpoint)
             mf_symbol.setPoints(newline)
+            mf_symbol.type = mapscript.MS_SYMBOL_ELLIPSE
         
         self._symbol = mf_symbol
     
@@ -409,7 +424,7 @@
     createLegendIcon(), insertStyle(), removeStyle(), moveStyleUp(),
     moveStyleDown()
     """
-    def __init__(self, mf_class):
+    def __init__(self, mf_class, map):
         """
         Initialized a class from them given mapscript Class Object
 	with a list of the included styles.
@@ -417,10 +432,11 @@
 	wich are holt as a List i think.
         """
         self._clazz = mf_class
+        self.map = map
         self._styles = []
         self._numstyles = mf_class.numstyles
         for i in range(0,self._numstyles,1):
-            self._styles.append(MF_Style(mf_class.getStyle(i)))
+            self._styles.append(MF_Style(mf_class.getStyle(i)), self.map)
         
         if self._clazz.getExpressionString() == '"(null)"':
             self._expression = None
@@ -464,24 +480,39 @@
         """
         added a thuban style object to the mapobject
         """
-        new_styleobj = MF_Style(styleObj(self._clazz))
         if type == "line":
+            new_styleobj = MF_Style(styleObj(self._clazz), self.map)
             new_styleobj.set_color(tb_style.GetLineColor())
+            new_styleobj.set_width(tb_style.GetLineWidth())
         elif type == "point":
             # set a default symbol to show circles not only a small dot
             # symbol "circle" must create before
             # TODO: create a Symbol (more see MF_SymbolSet)
             # first the default symbol circle will be created and the size 8
-            new_styleobj.set_symbolname('circle')
-            new_styleobj.set_size(8)
-            if tb_style.GetLineColor() != Transparent:
-                new_styleobj.set_linecolor(tb_style.GetLineColor())
-            new_styleobj.set_color(tb_style.GetFill())
+            new_styleobj = MF_Style(styleObj(self._clazz), self.map)
+            if tb_style.GetFill() == Transparent:
+                new_styleobj.set_symbolname('circle')
+                if tb_style.GetLineColor() != Transparent:
+                    new_styleobj.set_color(tb_style.GetLineColor())
+            else:
+                new_styleobj.set_symbolname('circle_filled')
+                new_styleobj.set_color(tb_style.GetFill())
+                if tb_style.GetLineColor() != Transparent:
+                    new_styleobj.set_linecolor(tb_style.GetLineColor())
+            new_styleobj.set_size(9)
         else:
-            new_styleobj.set_size(tb_style.GetLineWidth())
+    # Suppose this is a polygon.  We'll need two styles for applying
+    # the background color and outline width, as explained in
+    # http://mapserver.gis.umn.edu/docs/faq/faqsection_view?section=Map%20Output
+            if tb_style.GetFill() != Transparent:
+                new_styleobj = MF_Style(styleObj(self._clazz), self.map)
+                new_styleobj.set_color(tb_style.GetFill())
+    # And a second style.
+    # The order here matters (first the background, then the
             if tb_style.GetLineColor() != Transparent:
+                new_styleobj = MF_Style(styleObj(self._clazz), self.map)
                 new_styleobj.set_linecolor(tb_style.GetLineColor())
-            new_styleobj.set_color(tb_style.GetFill())
+                new_styleobj.set_width(tb_style.GetLineWidth())
 
 
 
@@ -501,7 +532,7 @@
     labelmaxscale, sizeunits, maxfeatures, offsite, transform, labelcache
     postlabelcache, labelitem, labelsizeitem, labelangleitem, labelitemindex
     labelsizeitemindex, labelangleitemindex, tileitem, tileindex, units
-    connection, connectiontype, numitems, filteritem, styleitem, requires
+    numitems, filteritem, styleitem, requires
     labelrequires, transparency, dump, debug, numprocessing, numjoins,
     removeClass(), open(), close(), getShape(), getNumResults(), getResult()
     getItem(), promote(), demote(), draw(), drawQuery(), queryByAttributes()
@@ -513,21 +544,19 @@
     getProcessing(), clearProcessing()   
     """
 
-    def __init__(self, mf_layer):
+    def __init__(self, mf_layer, map):
         """
 	Creates the Layer Object from the mapscript Layer Object.
 	the class objects in the layer object will be stored in
 	an array. The metadata are created as a new object.
         """
         self._mf_layer = mf_layer
-
+        self.map = map
         # Create Classes 
         # there could be more then 1 
-        i = -1
         self._classes = []
-        while i < self._mf_layer.numclasses-1:
-            i += 1
-            self._classes.append(MF_Class(self._mf_layer.getClass(i)))
+        for i in range (self._mf_layer.numclasses):
+            self._classes.append(MF_Class(self._mf_layer.getClass(i), self.map))
             
         self._projection = MF_Projection(self._mf_layer.getProjection())
         
@@ -543,6 +572,12 @@
     def get_data(self):
         return self._mf_layer.data
 
+    def get_connection(self):
+        return self._mf_layer.connnection
+
+    def get_connectiontype(self):
+        return self._mf_layer.connectiontype
+
     def get_classes(self):
         return self._classes
     
@@ -582,11 +617,17 @@
         self._mf_layer.name = newname 
     
     def set_data(self, newdata, type="shape"):
-        if type == "raster":
+        if type == "shape":
+            self._mf_layer.data = newdata[:-4]
+        else:
             self._mf_layer.data = newdata
-        else:
-            self._mf_layer.data = newdata[:-4]
-    
+
+    def set_connection (self, newconnection):
+        self._mf_layer.connection = newconnection
+
+    def set_connectiontype (self, newtype):
+        self._mf_layer.connectiontype = newtype
+
     def set_status(self, newstatus):
         # status can set to true or false from thuban.
         # but mapserver supports the default value
@@ -622,7 +663,7 @@
         """
         Add a thuban class object
         """ 
-        new_class = MF_Class(classObj(self._mf_layer))
+        new_class = MF_Class(classObj(self._mf_layer), self.map)
         self._classes.append(new_class)
         # set the class name to the Label form thuban if given,
         # else set it to the value
@@ -705,7 +746,7 @@
         new_class.set_status(tb_class.IsVisible())
 
     def remove_allclasses(self):
-        for i in range(0,len(self.get_classes()), 1):
+        for i in range(len(self.get_classes())):
             self._mf_layer.removeClass(i)
         self.set_classes([])
 
@@ -869,7 +910,7 @@
         self._layers = []
         self._i = 0
         while self._i < self._mf_map.numlayers:
-            self._layers.append(MF_Layer(self._mf_map.getLayer(self._i)))
+            self._layers.append(MF_Layer(self._mf_map.getLayer(self._i)), self)
             self._i += 1
 
         # Shapepath if not set, shapepath will be empty
@@ -886,7 +927,7 @@
         the new layer must create inside the mapobj, because mapscript
         need the mapscript object as parameter for layerObj
         """
-        new_layer = MF_Layer(layerObj(self._mf_map))
+        new_layer = MF_Layer(layerObj(self._mf_map), self)
         self._layers.append(new_layer)
         # the new created layer must remove from the mapobject
         # because all layer will create new in export.
@@ -988,18 +1029,17 @@
         self._mf_map.name = newname
     
     def set_extent(self, newextent):
-        # TODO: add the shown extend here instead of the total
-        # if no size is set or if it is zero, the size will set to 1.
-        if self.get_size()[0] == - 1:
-            print "define the size first to set extent"
-            print "size is now set to (1,1)"
-            self.set_size(1,1)
-        # if an empty map is export newextent will be none
+        """ Set the map's extent.  The map's size should already have been
+            set when you call this function, so this function will fail
+            if not.  Setting the size after the extent produces undesired
+            results anyway. """
+        width, height = self.get_size()
+        if width <= 0 or height <= 0:
+            raise mapscript.MapServerError, \
+                  "No size set before calling set_extent"
         if newextent:
-            self._newrect = MF_Rectangle(rectObj(newextent[0],newextent[1], \
-                                    newextent[2],newextent[3]))
-            self._mf_map.setExtent(newextent[0],newextent[1], \
-                                    newextent[2],newextent[3])    
+            self._newrect = MF_Rectangle(rectObj(*newextent))
+            self._mf_map.setExtent(*newextent)
     
     def set_size(self, newwidth, newheight):
         self._mf_map.width = newwidth
@@ -1034,12 +1074,13 @@
         # don't know why this error is produced and why it works
         # if it is placed here instead of the beginning.
         from Extensions.umn_mapserver.mf_import import AnnotationLayer
+        from Thuban.Model.postgisdb import PostGISShapeStore
         if hasattr(tb_layer,"extension_umn_layerobj"):
             #print tb_layer.extension_umn_layerobj
-            #new_layer = MF_Layer(layerObj(self._mf_map))
+            #new_layer = MF_Layer(layerObj(self._mf_map), self)
             new_layer = tb_layer.extension_umn_layerobj
         else:
-            new_layer = MF_Layer(layerObj(self._mf_map))
+            new_layer = MF_Layer(layerObj(self._mf_map), self)
             self._layers.append(new_layer)
             tb_layer.extension_umn_layerobj = new_layer
         new_layer.remove_allclasses()
@@ -1057,7 +1098,19 @@
             new_layer.set_status(tb_layer.Visible())
             new_layer.set_data(tb_layer.ShapeStore().FileName())
         else:
-            new_layer.set_data(tb_layer.ShapeStore().FileName())
+            if isinstance (tb_layer.ShapeStore(), PostGISShapeStore):
+                data = "%s from %s" % (tb_layer.ShapeStore().geometry_column,
+                                       tb_layer.ShapeStore().tablename)
+                new_layer.set_data (data, type="postgis")
+                params = []
+                for name in ("host", "port", "dbname", "user", "password"):
+                    val = getattr(tb_layer.ShapeStore().db, name)
+                    if val:
+                        params.append("%s=%s" % (name, val))
+                new_layer.set_connection (" ".join(params))
+                new_layer.set_connectiontype (mapscript.MS_POSTGIS)
+            else:
+                new_layer.set_data(tb_layer.ShapeStore().FileName())
             new_layer.set_status(tb_layer.Visible())
             new_layer.set_type(tb_layer.ShapeType())
             if tb_layer.GetClassificationColumn():
@@ -1347,7 +1400,7 @@
                 self._initcode, self._epsgcode = self._mfprojstring.split(':')
             else:  
                 self._params = []  
-                self._params = self._mfprojstring.split("+")
+                self._params = [p.strip() for p in self._mfprojstring.split("+")]
                 if self._params[0] == "":
                     self._params.remove("")
 
@@ -1403,14 +1456,14 @@
     """
     The following parameters, which the mapscript style obj
     contains, are used:
-    color, backgroundcolor, outlinecolor, size, symbolname
+    color, backgroundcolor, outlinecolor, size, symbolname, width
 
     The following are not used:
     symbol, sizescaled, minsize, maxsize, offsetx, offsety,
     antialias
     """
  
-    def __init__(self, mf_style):
+    def __init__(self, mf_style, map):
         """
 	Create a style object from the given mapscript style object.
 	The color Object from the color and the outlinecolor parameter
@@ -1419,6 +1472,7 @@
 	it will set to 'None'.
         """
         self._style = mf_style
+        self.map = map
         if self._style.color.red == -1:
             self._color = None
         else:
@@ -1431,6 +1485,9 @@
     def get_color(self):
         return self._color
     
+    def get_width(self):
+        return self._style.width
+    
     def get_outlinecolor(self):
         return self._outlinecolor
    
@@ -1450,11 +1507,14 @@
         new_color.set_thubancolor(tb_color)
         self._color = new_color
         self._style.color = new_color.get_mfcolor()
-    
+
     def set_size(self, newsize):
         self._style.size = newsize
+
+    def set_width(self, newwidth):
+        self._style.width = newwidth
     
     def set_symbolname(self, newsymbol):
         # its possible to use stringnames instead of numbers
-        self._style.symbolname = newsymbol
+        self._style.setSymbolByName (self.map._mf_map, newsymbol)
 

Modified: branches/WIP-pyshapelib-Unicode/thuban/Extensions/umn_mapserver/mf_export.py
===================================================================
--- branches/WIP-pyshapelib-Unicode/thuban/Extensions/umn_mapserver/mf_export.py	2008-08-08 23:39:11 UTC (rev 2864)
+++ branches/WIP-pyshapelib-Unicode/thuban/Extensions/umn_mapserver/mf_export.py	2008-09-05 19:45:58 UTC (rev 2865)
@@ -25,11 +25,11 @@
 import os
 
 # mapscript
+import mapscript
 from mapscript import mapObj
 
 # wxPython support
-from wx import FileDialog, \
-                        ID_OK, SAVE, OVERWRITE_PROMPT
+from wx import FileDialog, MessageDialog, OK, ID_OK, SAVE, OVERWRITE_PROMPT
 
 # Thuban
 # use _() already now for all strings that may later be translated
@@ -109,12 +109,17 @@
     """
     Added a circle object like the one shown in thuban
     """
-    if map.get_symbolset().get_symbol(1):
+    if map.get_symbolset().get_symbol(2):
         return
     else:
         new_symbol = MF_Symbol()
         new_symbol.set_name("circle")
-        new_symbol.set_type(2)
+        new_symbol.set_type(mapscript.MS_SYMBOL_ELLIPSE)
+        new_symbol.set_filled(False)
+        map.get_symbolset().add_symbol(new_symbol)
+        new_symbol = MF_Symbol()
+        new_symbol.set_name("circle_filled")
+        new_symbol.set_type(mapscript.MS_SYMBOL_ELLIPSE)
         new_symbol.set_filled(True)
         map.get_symbolset().add_symbol(new_symbol)
 
@@ -124,8 +129,8 @@
     that the file is generated automatic
     """
     thuban_umn_comment = "# \n" + \
-                                "# Map file generated by Thuban (umn_mapserver Extension) \n" + \
-                                "# \n \n"
+             "# Map file generated by Thuban (umn_mapserver Extension) \n" + \
+             "# \n \n"
     datafile = os.path.join(path,file)
     
     in_file = open(datafile,"r")
@@ -143,7 +148,12 @@
     the mapobj
     """
     theMap = context.mainwindow.canvas.Map().extension_umn_mapobj
-    
+    width, height = theMap.get_size() 
+    if width <= 0 or height <= 0:
+        dlg = MessageDialog (context.mainwindow,
+                 "You must set the map size before exporting", "Warning", OK)
+        dlg.ShowModal()
+        return
     dlg = FileDialog(context.mainwindow, "Save file as...", ".", "", 
                        "UMN MapServer Mapfiles (*.map)|*.map|"     \
                        "All files (*.*)|*.*",
@@ -155,12 +165,12 @@
     else:
         return
 
+    #add symbol
+    add_circle_symbol(theMap)
+    
     # set all thuban context to the mapobj
     thuban_to_map(context, theMap)
 
-    #add symbol
-    add_circle_symbol(theMap)
-    
     # shapepath vom mapfile
     theMap.set_shapepath("")
 

Modified: branches/WIP-pyshapelib-Unicode/thuban/Extensions/umn_mapserver/mf_handle.py
===================================================================
--- branches/WIP-pyshapelib-Unicode/thuban/Extensions/umn_mapserver/mf_handle.py	2008-08-08 23:39:11 UTC (rev 2864)
+++ branches/WIP-pyshapelib-Unicode/thuban/Extensions/umn_mapserver/mf_handle.py	2008-09-05 19:45:58 UTC (rev 2865)
@@ -214,8 +214,15 @@
         self.Show(False)
 
     def OnOK(self, event):
-        self.tb_map_umn.set_size(int(self.text_width.GetValue()), 
-                                 int(self.text_height.GetValue()))
+        try:
+            width = int(self.text_width.GetValue())
+            height = int(self.text_height.GetValue())
+        except ValueError, e:
+            dlg = wx.MessageDialog (self, "Width / Height: " + str(e),
+                                    "Warning", wx.OK)
+            dlg.ShowModal()
+            return
+        self.tb_map_umn.set_size(width, height)
         self.tb_map_umn.set_units(self.choice_units.GetStringSelection())
         if self.choice_status.GetStringSelection() == "True":
             self.tb_map_umn.set_status(True)

Modified: branches/WIP-pyshapelib-Unicode/thuban/Extensions/umn_mapserver/mf_import.py
===================================================================
--- branches/WIP-pyshapelib-Unicode/thuban/Extensions/umn_mapserver/mf_import.py	2008-08-08 23:39:11 UTC (rev 2864)
+++ branches/WIP-pyshapelib-Unicode/thuban/Extensions/umn_mapserver/mf_import.py	2008-09-05 19:45:58 UTC (rev 2865)
@@ -652,7 +652,7 @@
         if len(selectedlayer) != 0:
             # thuban map context
             tb_map = context.mainwindow.canvas.Map()
-            # set the titel and projection
+            # set the title and projection
             tb_map.SetTitle(mapobj.get_name())
             set_projection_to_tb(tb_map,mapobj)
 

Modified: branches/WIP-pyshapelib-Unicode/thuban/Extensions/umn_mapserver/test/test_mapserver.py
===================================================================
--- branches/WIP-pyshapelib-Unicode/thuban/Extensions/umn_mapserver/test/test_mapserver.py	2008-08-08 23:39:11 UTC (rev 2864)
+++ branches/WIP-pyshapelib-Unicode/thuban/Extensions/umn_mapserver/test/test_mapserver.py	2008-09-05 19:45:58 UTC (rev 2865)
@@ -18,6 +18,7 @@
 # Import the testmodul from python
 import unittest
 
+import mapscript
 from mapscript import mapObj
 
 # Import  necessary classes from Thuban
@@ -53,7 +54,7 @@
         Testing Color Objects from MapServer.
         """
         # IMAGECOLOR  255 255 255
-        testcolor = MF_Color(self.testMap.imagecolor)        
+        testcolor = MF_Color(self.testMap.imagecolor)
         self.eq(testcolor.get_red(), 255)
         self.eq(testcolor.get_green(), 255)
         self.eq(testcolor.get_blue(), 255)
@@ -195,7 +196,7 @@
         # or maybe a grafik
         self.eq(testlayer.get_data(), "test")
         # check projection (used the pojection obj a little bit)
-        self.eq(testlayer.get_projection().get_projection(), "+proj=latlong+ellps=clrk66")
+        self.eq(testlayer.get_projection().get_projection(), "+proj=latlong +ellps=clrk66")
         # TYPE POLYGON
         self.eq(testlayer.get_type(), "point")
         testlayer.set_type("circle")
@@ -232,7 +233,7 @@
         """
         testscalebar = MF_Scalebar(self.testMap.scalebar)
         self.eq(testscalebar.get_position(mode="string"),"ll")
-        self.eq(testscalebar.get_position(), 3)
+        self.eq(testscalebar.get_position(), mapscript.MS_LL)
         self.eq(testscalebar.get_intervals(), 4)
         self.eq(testscalebar.get_status(mode="string"), "OFF")
 


Property changes on: branches/WIP-pyshapelib-Unicode/thuban/Extensions/wms
___________________________________________________________________
Name: svn:ignore
   + *.pyc
*~



Modified: branches/WIP-pyshapelib-Unicode/thuban/Extensions/wms/__init__.py
===================================================================
--- branches/WIP-pyshapelib-Unicode/thuban/Extensions/wms/__init__.py	2008-08-08 23:39:11 UTC (rev 2864)
+++ branches/WIP-pyshapelib-Unicode/thuban/Extensions/wms/__init__.py	2008-09-05 19:45:58 UTC (rev 2865)
@@ -1,17 +1,17 @@
-# Copyright (c) 2003, 2004 by Intevation GmbH
+# Copyright (c) 2003, 2004, 2008 by Intevation GmbH
 # Authors:
 # Jan-Oliver Wagner <jan at intevation.de> (2003, 2004)
+# Didrik Pinte <dpinte at dipole-consulting.com> (2008)
 #
 # This program is free software under the GPL (>=v2)
 # Read the file COPYING coming with Thuban for details.
 
-# first try out whether we can import the required module
-# of the PyOGCLib.
+# first try out whether we can import the required module OWSLib
 ok = True
 try:
-    import ogclib.WMSClient
+    import owslib
 except:
-    print "Problems with PyOGCLib (not installed?)"
+    print "Problems with OWSLib (not installed?)"
     ok = False
 
 if ok:
@@ -22,7 +22,7 @@
 
     ext_registry.add(ExtensionDesc(
         name = 'WMS',
-        version = '0.2.0',
-        authors= [ 'Jan-Oliver Wagner', 'Martin Schulze' ],
-        copyright = '2003, 2004 Intevation GmbH',
+        version = '0.3.0',
+        authors= [ 'Didrik Pinte', 'Jan-Oliver Wagner', 'Martin Schulze' ],
+        copyright = '2003, 2004, 2008 Intevation GmbH',
         desc = _("Provide layers via OGC WMS.")))

Modified: branches/WIP-pyshapelib-Unicode/thuban/Extensions/wms/layer.py
===================================================================
--- branches/WIP-pyshapelib-Unicode/thuban/Extensions/wms/layer.py	2008-08-08 23:39:11 UTC (rev 2864)
+++ branches/WIP-pyshapelib-Unicode/thuban/Extensions/wms/layer.py	2008-09-05 19:45:58 UTC (rev 2865)
@@ -1,5 +1,6 @@
-# Copyright (c) 2003, 2004, 2007 by Intevation GmbH
+# Copyright (c) 2003, 2004, 2007, 2008 by Intevation GmbH
 # Authors:
+# Didrik Pinte <dpinte at dipole-consulting.com>
 # Jan-Oliver Wagner <jan at intevation.de>
 # Martin Schulze <joey at infodrom.org>
 #
@@ -39,10 +40,10 @@
     GetMapImg(width, height, bbox)
 
 Requirements:
-    - PyOGCLib <http://www.sourceforge.net/projects/pyogclib>
+    - OWSLib <http://trac.gispython.org/projects/PCL/wiki/OwsLib>
 
-Requires the ogclib installed regularily on the system or checked out
-next to the Thuban checkout.  Or set the PYTHONPATH to the PyOGCLib
+Requires the owslib installed regularily on the system or checked out
+next to the Thuban checkout.  Or set the PYTHONPATH to the OWSLib
 directory before starting Thuban.
 
 """
@@ -52,17 +53,14 @@
 # $Id$
 
 
-from Thuban import internal_from_unicode
+from Thuban import internal_from_unicode, _
 from Thuban.Model.layer import BaseLayer
 from Thuban.Model.resource import get_system_proj_file, EPSG_PROJ_FILE, \
      EPSG_DEPRECATED_PROJ_FILE
 from Thuban.UI.common import ThubanBeginBusyCursor, ThubanEndBusyCursor
 
-from capabilities import WMSCapabilities
+from owslib.wms import WebMapService
 
-from ogclib.WMSClient import WMSClient
-
-
 def epsg_code_to_projection(epsg):
     """Find the projection for the given epsg code.
 
@@ -107,11 +105,12 @@
 
         # Change the cursor to demonstrate that we're busy but working
         ThubanBeginBusyCursor()
-        self.capabilities = WMSCapabilities(url)
+        self.wmsserver = WebMapService(url, version="1.1.1")
+        self.capabilities = [op.name for op in self.wmsserver.operations]
         ThubanEndBusyCursor()
 
         # name of the top layer of the remote map
-        foo = self.capabilities.getLayers()
+        foo = list(self.wmsserver.contents)                   
         if len(foo) == 0:
             self.error_msg = _('No layers found in remote resource:\n'\
                                '%s') % url
@@ -120,30 +119,33 @@
         self.wms_layers = [top_layer]
 
         # first projection of the top layer
-        foo = self.capabilities.getLayerSRS(top_layer)
+        foo = self.wmsserver[top_layer].crsOptions
         if len(foo) == 0:
             self.error_msg = _('No LatLonBoundingBox found for top layer %s')\
                              % top_layer
             return
-        top_srs = foo[0]
+        top_srs = foo[0][foo[0].index(":")+1:]
 
         # BoundingBox of the top layer
-        bbox = self.capabilities.getLayerBBox(top_layer, top_srs)
-        if len(bbox) == 0:
-            self.error_msg = _('No BoundingBox found for layer %s and EPSG:')\
+        bbox = self.wmsserver[top_layer].boundingBox
+        if bbox is None or len(bbox) == 0:
+            self.error_msg = _('No BoundingBox found for layer %s and EPSG %s')\
                              % (top_layer, top_srs)
-            return
-        self.bbox = (float(bbox['minx']),
-                     float(bbox['miny']),
-                     float(bbox['maxx']),
-                     float(bbox['maxy']))
+            self.bbox = None
+        else :
+            self.bbox = (float(bbox[0]),
+                     float(bbox[1]),
+                     float(bbox[2]),
+                     float(bbox[3]))
 
         # LatLonBox of the top layer
-        bbox = self.capabilities.getLayerLatLonBBox(top_layer)
-        self.latlonbbox = (float(bbox['minx']),
-                           float(bbox['miny']),
-                           float(bbox['maxx']),
-                           float(bbox['maxy']))
+        bbox = self.wmsserver[top_layer].boundingBoxWGS84
+        self.latlonbbox = (float(bbox[0]),
+                     float(bbox[1]),
+                     float(bbox[2]),
+                     float(bbox[3]))
+        if self.bbox is None:
+            self.bbox =self.latlonbbox
 
         # get projection
         p = epsg_code_to_projection(top_srs)
@@ -157,14 +159,14 @@
 
         # pre-determine the used format
         self.wmsformat, self.format = \
-            self.calcFormat(self.capabilities.getFormats())
+        self.calcFormat(self.wmsserver.getOperationByName('GetMap').formatOptions)
         if self.wmsformat is None:
             self.error_msg = \
                 _('No supported image format found in remote resource')
             return
 
         # get and set the title
-        self.SetTitle(internal_from_unicode(self.capabilities.getTitle()))
+        self.SetTitle(internal_from_unicode(self.wmsserver.identification.title))
 
 
     def LatLongBoundingBox(self):
@@ -251,7 +253,7 @@
         assuming that JPEG will always be supported on the server side
         with this encoding.
         """
-        return self.capabilities.getFormats()
+        return self.wmsserver.getOperationByName('GetMap').formatOptions
 
 
     def getLayers(self):
@@ -264,7 +266,7 @@
         title but doesn't have to have a name associated to it as
         well.  If no layers were found, an empty list is returned.
         """
-        return self.capabilities.getLayers()
+        return list(self.wmsserver.contents)
 
 
     def getLayerTitle(self, layer):
@@ -276,7 +278,7 @@
         If no such title or no such layer exists, an empty string is
         returned.
         """
-        return self.capabilities.getLayerTitle(layer)
+        return self.wmsserver[layer].title
 
 
     def getWMSFormat(self):
@@ -329,12 +331,15 @@
         # Change the cursor to demonstrate that we're busy but working
         ThubanBeginBusyCursor()
 
-        wmsclient = WMSClient()
-
         epsg_id = int(self.GetProjection().EPSGCode())
 
-        wms_response = wmsclient.getMap(self.url, self.wmsformat, width, height,
-                                   epsg_id, bbox_dict,
-                                   self.wms_layers, version = self.capabilities.getVersion())
+        wms_response = self.wmsserver.getmap(layers=self.wms_layers, 
+                                             styles=None, 
+                                             srs="EPSG:%s" % epsg_id, 
+                                             bbox=bbox, 
+                                             size=(width, height), 
+                                             format=self.wmsformat, 
+                                             transparent=True)
         ThubanEndBusyCursor()
-        return wms_response, self.format
+        
+        return wms_response.read() , self.format

Modified: branches/WIP-pyshapelib-Unicode/thuban/Extensions/wms/wms.py
===================================================================
--- branches/WIP-pyshapelib-Unicode/thuban/Extensions/wms/wms.py	2008-08-08 23:39:11 UTC (rev 2864)
+++ branches/WIP-pyshapelib-Unicode/thuban/Extensions/wms/wms.py	2008-09-05 19:45:58 UTC (rev 2865)
@@ -1,5 +1,6 @@
-# Copyright (C) 2003, 2004 by Intevation GmbH
+# Copyright (C) 2003, 2004, 2008 by Intevation GmbH
 # Authors:
+# Didrik Pinte <dpinte at dipole-consulting.com> (2008)
 # Jan-Oliver Wagner <jan at intevation.de> (2003, 2004)
 # Bernhard Herzog <bh at intevation.de> (2004)
 # Martin Schulze <joey at infodrom.org> (2004)
@@ -9,12 +10,6 @@
 
 """
 Provide layers via OGC WMS.
-
-This extension is in a very experimental stage!
-It just demonstrates how to add a special
-layer into Thuban via an extension.
-Some things are not wired, so be prepared for Exceptions
-everywhere.
 """
 
 __version__ = "$Revision$"
@@ -78,8 +73,8 @@
 
         self.combo_value = wx.ComboBox(self, self.ID_COMBOVALUE, size=(500,-1))
         self.combo_value.Append("")
-        self.combo_value.Append('http://demo.intevation.org/cgi-bin/frida-wms?')
-        self.combo_value.Append('http://wms.jpl.nasa.gov/wms.cgi?')
+        self.combo_value.Append('http://demo.intevation.org/cgi-bin/frida-wms')
+        self.combo_value.Append('http://wms.jpl.nasa.gov/wms.cgi')
         self.combo_value.SetSelection(0)
 
         button_ok = wx.Button(self, wx.ID_OK, _("OK"))

Modified: branches/WIP-pyshapelib-Unicode/thuban/NEWS
===================================================================
--- branches/WIP-pyshapelib-Unicode/thuban/NEWS	2008-08-08 23:39:11 UTC (rev 2864)
+++ branches/WIP-pyshapelib-Unicode/thuban/NEWS	2008-09-05 19:45:58 UTC (rev 2865)
@@ -1,4 +1,18 @@
+Changes up to Thuban 1.2.x DRAFT
+==========================
 
+- Problem fixes:
+
+  + Fix for shptreemodule.c coming from Debian #469007.
+  + DTDs 1.1 and 1.2.1 session files are valid DTDs again (Bernhard Herzog).
+  + Fix for Mac and wx 2.8. (Didrik Pinte)
+  + Minor improvements in code and documentation (Bernhard Reiter).
+
+ - Extensions
+
+   + wms: experimental migrated to owslib 0.3 (Didrik Pinte)
+
+
 Changes up to Thuban 1.2.1 (released 2008-02-03)
 ===========================
  - Rendering: Thuban's accelerated shapefile renderer is now 
@@ -54,7 +68,7 @@
    + wms: Some attemps to revive, but found out that PyOGClib is abandoned
      and does not work anymore. Needs work.
 
-   + Extentions are now all under the menu entry with the same name,
+   + Extensions are now all under the menu entry with the same name,
      their maturity will be indicated by leading string in the menu text. 
 
    + New installation wide configuration file thuban_cfg.py which by
@@ -88,7 +102,7 @@
 
  - Support for pysqlite2. (Didrik Pinte)
 
- - Added packagin directory, which already has an example how
+ - Added packaging directory, which already has an example how
    to load all extensions on windows. (Didrik Pinte)
 
  - Updated code to support new style wxPython 2.6 imports. So

Modified: branches/WIP-pyshapelib-Unicode/thuban/README
===================================================================
--- branches/WIP-pyshapelib-Unicode/thuban/README	2008-08-08 23:39:11 UTC (rev 2864)
+++ branches/WIP-pyshapelib-Unicode/thuban/README	2008-09-05 19:45:58 UTC (rev 2865)
@@ -21,9 +21,19 @@
 About 4000 years ago it was the north star.
 
 
-Requirements
+Installation
 ------------
+As with most software there are two ways to install Thuban:
+a) Use a prepared package specific for your operating system.
+   This is the most convenient way. The packager will have the instructions
+   how to do this in detail, this is why it is not further described here.
+   A decent package management system will also handle the requirements.
 
+b) Build and install the software manually from sources.
+
+Requirements for building and running Thuban.
+------------
+
 Thuban requires the following software to be installed:
 
   Python     2.3.5    http://www.python.org
@@ -54,9 +64,12 @@
 Note that extensions might have their own additional requirements.
 
 
-Installation
-------------
+Building and installing
+-----------------------
 
+(First make sure the development variants of the software listed
+in the "Requirements" section above is installed.)
+
 Building Thuban (this compiles the extension modules but leaves them in
 a directory under build/):
 

Modified: branches/WIP-pyshapelib-Unicode/thuban/Resources/XML/thuban-1.1.dtd
===================================================================
--- branches/WIP-pyshapelib-Unicode/thuban/Resources/XML/thuban-1.1.dtd	2008-08-08 23:39:11 UTC (rev 2864)
+++ branches/WIP-pyshapelib-Unicode/thuban/Resources/XML/thuban-1.1.dtd	2008-09-05 19:45:58 UTC (rev 2865)
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!--    thuban-1.1.dtd
 
-    Copyright (C) 2001, 2003, 2004, 2005 by Intevation GmbH
+    Copyright (C) 2001, 2003, 2004, 2005, 2008 by Intevation GmbH
     Authors:
         Jan-Oliver Wagner <jan at intevation.de>
         Bernhard Herzog <bh at intevation.de>
@@ -180,8 +180,8 @@
 
 <!-- Classification data -->
 <!ELEMENT classification (clnull?, clpoint*, clrange*, clpattern*, clcont*)>
-<!ATTLIST classification field CDATA>
-<!ATTLIST classification field_type CDATA>
+<!ATTLIST classification field CDATA #IMPLIED>
+<!ATTLIST classification field_type CDATA #IMPLIED>
 
 <!ELEMENT clnull (cldata*)>
 <!ELEMENT clpoint (cldata*)>

Modified: branches/WIP-pyshapelib-Unicode/thuban/Resources/XML/thuban-1.2.1.dtd
===================================================================
--- branches/WIP-pyshapelib-Unicode/thuban/Resources/XML/thuban-1.2.1.dtd	2008-08-08 23:39:11 UTC (rev 2864)
+++ branches/WIP-pyshapelib-Unicode/thuban/Resources/XML/thuban-1.2.1.dtd	2008-09-05 19:45:58 UTC (rev 2865)
@@ -177,8 +177,8 @@
 
 <!-- Classification data -->
 <!ELEMENT classification (clnull?, clpoint*, clrange*, clpattern*, clcont*)>
-<!ATTLIST classification field CDATA>
-<!ATTLIST classification field_type CDATA>
+<!ATTLIST classification field CDATA #IMPLIED>
+<!ATTLIST classification field_type CDATA #IMPLIED>
 
 <!ELEMENT clnull (cldata*)>
 <!ELEMENT clpoint (cldata*)>


Property changes on: branches/WIP-pyshapelib-Unicode/thuban/Thuban
___________________________________________________________________
Name: svn:ignore
   + *.pyc
*~




Property changes on: branches/WIP-pyshapelib-Unicode/thuban/Thuban/Lib
___________________________________________________________________
Name: svn:ignore
   + *.pyc
*~




Property changes on: branches/WIP-pyshapelib-Unicode/thuban/Thuban/Model
___________________________________________________________________
Name: svn:ignore
   + *.pyc
*~



Modified: branches/WIP-pyshapelib-Unicode/thuban/Thuban/Model/load.py
===================================================================
--- branches/WIP-pyshapelib-Unicode/thuban/Thuban/Model/load.py	2008-08-08 23:39:11 UTC (rev 2864)
+++ branches/WIP-pyshapelib-Unicode/thuban/Thuban/Model/load.py	2008-09-05 19:45:58 UTC (rev 2865)
@@ -161,9 +161,9 @@
         """Clear all instance variables to cut cyclic references.
 
         The GC would have collected the loader eventually but it can
-	happen that it doesn't run at all until Thuban is closed (2.3
-	but not 2.2 tries a bit harder and forces a collection when the
-	interpreter terminates)
+        happen that it doesn't run at all until Thuban is closed (2.3
+        but not 2.2 tries a bit harder and forces a collection when the
+        interpreter terminates)
         """
         self.__dict__.clear()
 
@@ -528,8 +528,8 @@
         self.aLayer = None
 
     def start_classification(self, name, qname, attrs):
-    	# field and field_type are optional because the classification
-	# can also be empty, ie. have only a default.
+        # field and field_type are optional because the classification
+        # can also be empty, ie. have only a default.
         attrs = self.check_attrs(name, attrs,
                                  [AttrDesc("field", False),
                                   AttrDesc("field_type", False)])
@@ -537,7 +537,7 @@
         field = attrs["field"]
         fieldType = attrs["field_type"]
 
-	if field == "": return # no need to set classification column.
+        if field == "": return # no need to set classification column.
 
         dbFieldType = self.aLayer.GetFieldType(field)
 


Property changes on: branches/WIP-pyshapelib-Unicode/thuban/Thuban/UI
___________________________________________________________________
Name: svn:ignore
   + *.pyc
*~



Modified: branches/WIP-pyshapelib-Unicode/thuban/Thuban/UI/legend.py
===================================================================
--- branches/WIP-pyshapelib-Unicode/thuban/Thuban/UI/legend.py	2008-08-08 23:39:11 UTC (rev 2864)
+++ branches/WIP-pyshapelib-Unicode/thuban/Thuban/UI/legend.py	2008-09-05 19:45:58 UTC (rev 2865)
@@ -718,7 +718,7 @@
 
     def __init__(self, parent, map, mainWindow):
         # While the width is fixed, get the height _now_.
-        dc = wx.MemoryDC()
+        dc = wx.ScreenDC()
         textwidth, textheight = dc.GetTextExtent("%d"%0)
         self.width = 210
         self.height = textheight + 3*2 + 8

Modified: branches/WIP-pyshapelib-Unicode/thuban/Thuban/thuban_cfg.py
===================================================================
--- branches/WIP-pyshapelib-Unicode/thuban/Thuban/thuban_cfg.py	2008-08-08 23:39:11 UTC (rev 2864)
+++ branches/WIP-pyshapelib-Unicode/thuban/Thuban/thuban_cfg.py	2008-09-05 19:45:58 UTC (rev 2865)
@@ -30,6 +30,16 @@
     print x
 
 try:
+    import Extensions.importMP
+except Exception, x:
+    print x
+
+try:
+    import Extensions.gMapTiles
+except Exception, x:
+    print x
+
+try:
     import Extensions.mouseposition
 except Exception, x:
     print x
@@ -52,9 +62,8 @@
 except Exception, x:
     print x
 
-# disabled for 1.2.1 release because PyOGCLib is buggy
-#try:
-#    import Extensions.wms
-#except Exception, x:
-#    print x
+try:
+    import Extensions.wms
+except Exception, x:
+    print x
 

Modified: branches/WIP-pyshapelib-Unicode/thuban/libraries/pyshapelib/shptreemodule.c
===================================================================
--- branches/WIP-pyshapelib-Unicode/thuban/libraries/pyshapelib/shptreemodule.c	2008-08-08 23:39:11 UTC (rev 2864)
+++ branches/WIP-pyshapelib-Unicode/thuban/libraries/pyshapelib/shptreemodule.c	2008-09-05 19:45:58 UTC (rev 2865)
@@ -42,7 +42,7 @@
 shptree_dealloc(SHPTreeObject * self)
 {
     api->SHPDestroyTree(self->tree);
-    PyMem_DEL(self);
+    PyObject_Del(self);
 }
 
 /* Return the repr of the wrapper */

Modified: branches/WIP-pyshapelib-Unicode/thuban/setup.py
===================================================================
--- branches/WIP-pyshapelib-Unicode/thuban/setup.py	2008-08-08 23:39:11 UTC (rev 2864)
+++ branches/WIP-pyshapelib-Unicode/thuban/setup.py	2008-09-05 19:45:58 UTC (rev 2865)
@@ -349,8 +349,8 @@
 
 #add the Lib content to the output
 if os.path.isdir("Lib"):
-	for d in os.listdir("Lib"):
-		data_files.append(("Lib", ["Lib/"+d]))
+        for d in os.listdir("Lib"):
+                data_files.append(("Lib", ["Lib/"+d]))
 
 
 #
@@ -967,14 +967,14 @@
         # Obviously have to build before we can install
 
         # add gdal to the build
-	for (dirpath, dnames, fnames) in os.walk('gdal'):			
-		files_in_dir = []
-		dp = '/'.join(dirpath.split('\\'))
-		for f in fnames:
-			if os.path.isfile(os.path.join(dirpath,f)):			
-				files_in_dir.append( dp + '/' + f)		
-		if len(files_in_dir) > 0:
-			data_files.append(( dp , files_in_dir))
+        for (dirpath, dnames, fnames) in os.walk('gdal'):                       
+                files_in_dir = []
+                dp = '/'.join(dirpath.split('\\'))
+                for f in fnames:
+                        if os.path.isfile(os.path.join(dirpath,f)):                     
+                                files_in_dir.append( dp + '/' + f)              
+                if len(files_in_dir) > 0:
+                        data_files.append(( dp , files_in_dir))
         # add thubaninit to the build
 
 
@@ -1096,7 +1096,7 @@
             "warn_dir": 0,
             "extra_files": ["COPYING", "Lib/proj.dll"],
             }
-	install_options["extra_files"].extend(self.get_gdal_content())
+        install_options["extra_files"].extend(self.get_gdal_content())
 
         # don't make a symlink because we're simulating windows, so
         # that we can generate the iss-file even on Linux
@@ -1108,12 +1108,12 @@
         '''
         Return the list of files in the gdal directory of the Thuban installation
         '''
-	gdal_files = []
-	for (dirpath, dnames, fnames) in os.walk('gdal'):		    
-	    if len(fnames) > 0:
-	        for file in fnames :
-		    gdal_files.append(dirpath + os.sep + file)
-	return gdal_files
+        gdal_files = []
+        for (dirpath, dnames, fnames) in os.walk('gdal'):
+            if len(fnames) > 0:
+                for file in fnames :
+                    gdal_files.append(dirpath + os.sep + file)
+        return gdal_files
 
 class thuban_build_docs(Command):
 
@@ -1205,8 +1205,8 @@
       packages = ["Thuban", "Thuban.Lib", "Thuban.Model", "Thuban.UI",
                   "Extensions", "Extensions.gns2shp", "Extensions.wms",
                   "Extensions.importAPR", "Extensions.profiling", 
-		          "Extensions.svgexport", "Extensions.mouseposition", 
-		          "Extensions.bboxdump", "Extensions.ogr", 
+                          "Extensions.svgexport", "Extensions.mouseposition", 
+                          "Extensions.bboxdump", "Extensions.ogr", 
                   "Extensions.umn_mapserver"],
       ext_modules = extensions,
       py_modules = py_modules,


Property changes on: branches/WIP-pyshapelib-Unicode/thuban/test
___________________________________________________________________
Name: svn:ignore
   + *.pyc
*~



Modified: branches/WIP-pyshapelib-Unicode/thuban/test/postgissupport.py
===================================================================
--- branches/WIP-pyshapelib-Unicode/thuban/test/postgissupport.py	2008-08-08 23:39:11 UTC (rev 2864)
+++ branches/WIP-pyshapelib-Unicode/thuban/test/postgissupport.py	2008-09-05 19:45:58 UTC (rev 2865)
@@ -527,20 +527,22 @@
     first one found (looking under contrib first).  
 
     Debian (umcoming Etch) can do several version of postgresql
-    and thus has changed the paths. We try one location
-    in datadir2 only for Debian Etch postgresql-8.1.
+    and thus has changed the paths. We try locations for
+    postgresql-8.1 and 8.3.
 
     If the file is not found the return value is None.
     """
     bindir = run_config_script("pg_config --bindir").strip()
     datadir = os.path.join(bindir, "..", "share", "postgresql")
     datadir2 = os.path.join("/", "usr", "share", "postgresql-8.1-postgis")
+    datadir3 = os.path.join("/", "usr", "share", "postgresql-8.3-postgis")
 
     for filename in [os.path.join(datadir, "contrib", "postgis.sql"),
                      os.path.join(datadir, "postgis.sql"),
                      os.path.join(datadir, "lwpostgis.sql"),
                      os.path.join(datadir, "contrib", "lwpostgis.sql"),
-                     os.path.join(datadir2, "lwpostgis.sql") \
+                     os.path.join(datadir2, "lwpostgis.sql"),
+                     os.path.join(datadir3, "lwpostgis.sql"),
                     ]:
         if os.path.exists(filename):
             return filename

Modified: branches/WIP-pyshapelib-Unicode/thuban/test/test_baserenderer.py
===================================================================
--- branches/WIP-pyshapelib-Unicode/thuban/test/test_baserenderer.py	2008-08-08 23:39:11 UTC (rev 2864)
+++ branches/WIP-pyshapelib-Unicode/thuban/test/test_baserenderer.py	2008-09-05 19:45:58 UTC (rev 2865)
@@ -102,7 +102,7 @@
                                resolution, dimensions, options):
 
         if not Thuban.Model.resource.has_gdal_support():
-            raise support.SkipTest("No gdal support")
+            raise support.SkipTest(Thuban.Model.resource.gdal_support_status)
 
         #print srcProj, dstProj,extents, resolution, dimensions, options
 
@@ -281,7 +281,7 @@
 
     def test_projected_raster_layer(self):
         if not Thuban.Model.resource.has_gdal_support():
-            raise support.SkipTest("No gdal support")
+            raise support.SkipTest(Thuban.Model.resource.gdal_support_status)
 
         layer = RasterLayer("raster layer",
                             os.path.join("..", "Data", "iceland",
@@ -347,7 +347,7 @@
 
     def test_projected_raster_decimalcommalocale(self):
         if not Thuban.Model.resource.has_gdal_support():
-            raise support.SkipTest("No gdal support")
+            raise support.SkipTest(Thuban.Model.resource.gdal_support_status)
 
         def _do_project_island():
             """Project island.tif and return result."""
@@ -381,7 +381,7 @@
         returned by gdalwarp.ProjectRasterFile to a BMP file data.
         """
         if not Thuban.Model.resource.has_gdal_support():
-            raise support.SkipTest("No gdal support")
+            raise support.SkipTest(Thuban.Model.resource.gdal_support_status)
 
         map = Map("TestBaseRenderer")
 

Modified: branches/WIP-pyshapelib-Unicode/thuban/test/test_layer.py
===================================================================
--- branches/WIP-pyshapelib-Unicode/thuban/test/test_layer.py	2008-08-08 23:39:11 UTC (rev 2864)
+++ branches/WIP-pyshapelib-Unicode/thuban/test/test_layer.py	2008-09-05 19:45:58 UTC (rev 2865)
@@ -226,7 +226,7 @@
 
     def test_raster_layer(self):
         if not Thuban.Model.resource.has_gdal_support():
-            raise support.SkipTest("No gdal support")
+            raise support.SkipTest(Thuban.Model.resource.gdal_support_status)
 
         filename = self.build_path("island.tif")
         layer = RasterLayer("Test RasterLayer", filename)
@@ -475,7 +475,7 @@
 
     def test_raster_layer(self):
         if not Thuban.Model.resource.has_gdal_support():
-            raise support.SkipTest("No gdal support")
+            raise support.SkipTest(Thuban.Model.resource.gdal_support_status)
 
 
         filename = self.build_path("island.tif")

Added: branches/WIP-pyshapelib-Unicode/thuban/test/test_mapservpostgis.py
===================================================================
--- branches/WIP-pyshapelib-Unicode/thuban/test/test_mapservpostgis.py	2008-08-08 23:39:11 UTC (rev 2864)
+++ branches/WIP-pyshapelib-Unicode/thuban/test/test_mapservpostgis.py	2008-09-05 19:45:58 UTC (rev 2865)
@@ -0,0 +1,60 @@
+import unittest
+import os, sys
+import support
+from Thuban.Model.layer import Layer
+from Thuban.Model.map import Map
+from Thuban.Model.session import Session
+from Thuban.UI.context import Context
+from Thuban.Lib.connector import ConnectorError
+
+from test_postgis_db import PostGISStaticTests
+from Thuban.Model.postgisdb import PostGISShapeStore
+
+mapscriptAvailable=True
+try:
+    import mapscript
+    from Extensions.umn_mapserver.mf_export import thuban_to_map
+    from Extensions.umn_mapserver.mapfile import MF_Map
+except ImportError:
+    mapscriptAvailable=False
+    
+
+class DummyMainWindow(object):
+    def __init__(self, canvas):
+        self.canvas = canvas
+
+class DummyCanvas(object):
+    def __init__(self, map):
+        self.map = map
+    def Map(self):
+        return self.map
+    def VisibleExtent (self):
+        return self.map.BoundingBox()
+
+class TestPostGISMFExport(PostGISStaticTests):
+    def setUp(self):
+        PostGISStaticTests.setUp(self)
+        self.store = PostGISShapeStore(self.db, "political_multi")
+
+    def testExport(self):
+        if not mapscriptAvailable:
+            raise support.SkipTest("Couldn't import mapscript module")
+        session = Session("A Session")
+        map = Map("A Map")
+        session.AddMap(map)
+        layer = Layer("PostGIS Layer", self.store)
+        map.AddLayer(layer)
+        mainwindow = DummyMainWindow(DummyCanvas(map))
+        context = Context(None, session, mainwindow)
+        mf = MF_Map(mapscript.mapObj(""))
+        mf.set_size (600, 500)
+        thuban_to_map (context, mf)
+        try:
+            map.Destroy()
+        except ConnectorError:
+            pass
+        session.Destroy()
+
+if __name__ == "__main__":
+    support.run_tests()
+

Modified: branches/WIP-pyshapelib-Unicode/thuban/test/test_save.py
===================================================================
--- branches/WIP-pyshapelib-Unicode/thuban/test/test_save.py	2008-08-08 23:39:11 UTC (rev 2864)
+++ branches/WIP-pyshapelib-Unicode/thuban/test/test_save.py	2008-09-05 19:45:58 UTC (rev 2865)
@@ -160,7 +160,7 @@
                     <classification>
                         <clnull label="">
                             <cldata fill="None" stroke="#000000"
-		    	        stroke_width="1"/>
+                                stroke_width="1"/>
                         </clnull>
                     </classification>
                 </layer>
@@ -232,7 +232,7 @@
                     <classification>
                         <clnull label="">
                             <cldata fill="None" stroke="#000000"
-		    	        stroke_width="1"/>
+                                stroke_width="1"/>
                         </clnull>
                     </classification>
                 </layer>
@@ -505,7 +505,7 @@
                         <classification>
                             <clnull label="">
                                 <cldata fill="None" stroke="#000000"
-				        stroke_width="1"/>
+                                        stroke_width="1"/>
                             </clnull>
                         </classification>
                     </layer>
@@ -532,8 +532,8 @@
             def _fetch_table_information(self):
                 # pretend that we've found a geometry column
                 self.geometry_column = "the_geom"
-		# pretend this is a ARC shape type.
-		self.shape_type = SHAPETYPE_ARC
+                # pretend this is a ARC shape type.
+                self.shape_type = SHAPETYPE_ARC
             def IDColumn(self):
                 """Return an object with a name attribute with value 'gid'"""
                 class dummycol:
@@ -576,7 +576,7 @@
                         <classification>
                             <clnull label="">
                                 <cldata fill="None" stroke="#000000"
-		    	            stroke_width="1"/>
+                                    stroke_width="1"/>
                             </clnull>
                         </classification>
                     </layer>



More information about the Thuban-commits mailing list