? .ChangeLog.swp
? __init__.py
? build
? ogrextension.patch
? ogrextensionOld.patch
? thubaninit.py
? thubaninit.pyc
? Extensions/__init__.pyc
? Extensions/ogr/.ogrshapes.py.swo
? Extensions/ogr/.ogrstart.py.swp
? Extensions/ogr/__init__.pyc
? Extensions/ogr/ogrdialog.pyc
? Extensions/ogr/ogrshapes.pyc
? Extensions/ogr/ogrstart.pyc
? Extensions/ogr/sampleFiles/fahrrad.gml
? Extensions/ogr/sampleFiles/intellitrim.dgn
? Extensions/ogr/test/.test_OGRShapestore.py.swp
? Extensions/ogr/test/__init__.pyc
? Extensions/ogr/test/test_OGRShapestore.pyc
? Extensions/svgexport/__init__.pyc
? Extensions/svgexport/maplegend.pyc
? Extensions/svgexport/svgmapwriter.pyc
? Extensions/svgexport/svgsaver.pyc
? Extensions/svgexport/test/__init__.pyc
? Extensions/svgexport/test/test_svgmapwriter.pyc
? Thuban/__init__.pyc
? Thuban/version.pyc
? Thuban/Lib/__init__.pyc
? Thuban/Lib/classmapper.pyc
? Thuban/Lib/connector.pyc
? Thuban/Lib/fileutil.pyc
? Thuban/Lib/version.pyc
? Thuban/Model/__init__.pyc
? Thuban/Model/base.pyc
? Thuban/Model/classgen.pyc
? Thuban/Model/classification.pyc
? Thuban/Model/color.pyc
? Thuban/Model/data.pyc
? Thuban/Model/label.pyc
? Thuban/Model/layer.pyc
? Thuban/Model/load.pyc
? Thuban/Model/map.pyc
? Thuban/Model/messages.pyc
? Thuban/Model/postgisdb.pyc
? Thuban/Model/proj.pyc
? Thuban/Model/range.pyc
? Thuban/Model/resource.pyc
? Thuban/Model/save.pyc
? Thuban/Model/scalebar.pyc
? Thuban/Model/session.pyc
? Thuban/Model/table.pyc
? Thuban/Model/transientdb.pyc
? Thuban/Model/wellknowntext.pyc
? Thuban/Model/xmlreader.pyc
? Thuban/Model/xmlwriter.pyc
? Thuban/UI/__init__.pyc
? Thuban/UI/about.pyc
? Thuban/UI/altpathdialog.pyc
? Thuban/UI/application.pyc
? Thuban/UI/baserenderer.pyc
? Thuban/UI/classgen.pyc
? Thuban/UI/classifier.pyc
? Thuban/UI/colordialog.pyc
? Thuban/UI/command.pyc
? Thuban/UI/common.pyc
? Thuban/UI/context.pyc
? Thuban/UI/controls.pyc
? Thuban/UI/dbdialog.pyc
? Thuban/UI/dialogs.pyc
? Thuban/UI/dock.pyc
? Thuban/UI/exceptiondialog.pyc
? Thuban/UI/extensionregistry.pyc
? Thuban/UI/hittest.pyc
? Thuban/UI/identifyview.pyc
? Thuban/UI/join.pyc
? Thuban/UI/labeldialog.pyc
? Thuban/UI/layerproperties.pyc
? Thuban/UI/legend.pyc
? Thuban/UI/main.pyc
? Thuban/UI/mainwindow.pyc
? Thuban/UI/menu.pyc
? Thuban/UI/messages.pyc
? Thuban/UI/multiplechoicedialog.pyc
? Thuban/UI/projdialog.pyc
? Thuban/UI/projlist.pyc
? Thuban/UI/rasterlayerproperties.pyc
? Thuban/UI/renderer.pyc
? Thuban/UI/resource.pyc
? Thuban/UI/scalebar.pyc
? Thuban/UI/selection.pyc
? Thuban/UI/sizers.pyc
? Thuban/UI/tableview.pyc
? Thuban/UI/tree.pyc
? Thuban/UI/view.pyc
? Thuban/UI/viewport.pyc
? test/.test_postgis_db.py.swp
? test/mockgeo.pyc
? test/postgissupport.pyc
? test/support.pyc
? test/temp
? test/test_base.pyc
? test/test_baserenderer.pyc
? test/test_classgen.pyc
? test/test_classification.pyc
? test/test_classmapper.pyc
? test/test_color.pyc
? test/test_command.pyc
? test/test_connector.pyc
? test/test_csv_table.pyc
? test/test_dbf_table.pyc
? test/test_derivedshapestore.pyc
? test/test_export.pyc
? test/test_fileutil.pyc
? test/test_hittest.pyc
? test/test_label.pyc
? test/test_layer.pyc
? test/test_lib_version.pyc
? test/test_load.pyc
? test/test_load_0_2.pyc
? test/test_load_0_8.pyc
? test/test_load_0_9.pyc
? test/test_load_1_0.pyc
? test/test_map.pyc
? test/test_memory_table.pyc
? test/test_menu.pyc
? test/test_mockgeo.pyc
? test/test_postgis_db.pyc
? test/test_postgis_session.pyc
? test/test_proj.pyc
? test/test_range.pyc
? test/test_save.pyc
? test/test_scalebar.pyc
? test/test_selection.pyc
? test/test_session.pyc
? test/test_shapefilestore.pyc
? test/test_transientdb.pyc
? test/test_viewport.pyc
? test/test_wellknowntext.pyc
? test/test_wxproj.pyc
? test/test_xmlsupport.pyc
? test/xmlsupport.pyc
Index: Thuban/Model/data.py
===================================================================
RCS file: /thubanrepository/thuban/Thuban/Model/data.py,v
retrieving revision 1.15
diff -u -3 -r1.15 data.py
--- Thuban/Model/data.py	24 Nov 2003 19:23:08 -0000	1.15
+++ Thuban/Model/data.py	4 Mar 2005 15:14:56 -0000
@@ -28,6 +28,9 @@
 SHAPETYPE_POLYGON = "polygon"
 SHAPETYPE_ARC = "arc"
 SHAPETYPE_POINT = "point"
+SHAPETYPE_UNKNOWN = 0
+SHAPETYPE_GEOMCOLL = 7
+SHAPETYPE_NONE = 100
 
 # mapping from shapelib shapetype constants to our constants
 shapelib_shapetypes = {shapelib.SHPT_POLYGON: SHAPETYPE_POLYGON,
Index: Thuban/Model/layer.py
===================================================================
RCS file: /thubanrepository/thuban/Thuban/Model/layer.py,v
retrieving revision 1.63
diff -u -3 -r1.63 layer.py
--- Thuban/Model/layer.py	16 Feb 2005 21:14:47 -0000	1.63
+++ Thuban/Model/layer.py	4 Mar 2005 15:14:56 -0000
@@ -21,7 +21,8 @@
 
 from color import Transparent, Black
 from base import TitledObject, Modifiable
-from data import SHAPETYPE_POLYGON, SHAPETYPE_ARC, SHAPETYPE_POINT
+from data import SHAPETYPE_POLYGON, SHAPETYPE_ARC, SHAPETYPE_POINT, \
+    SHAPETYPE_UNKNOWN, SHAPETYPE_GEOMCOLL, SHAPETYPE_NONE
 
 import resource
 
@@ -29,7 +30,10 @@
 
 shapetype_names = {SHAPETYPE_POINT: "Point",
                    SHAPETYPE_ARC: "Arc",
-                   SHAPETYPE_POLYGON: "Polygon"}
+                   SHAPETYPE_POLYGON: "Polygon",
+                   SHAPETYPE_UNKNOWN: "unknown",
+                   SHAPETYPE_GEOMCOLL: "Geometry Collection",
+                   SHAPETYPE_NONE: "none"}
 
 class BaseLayer(TitledObject, Modifiable):
 
@@ -334,7 +338,7 @@
         else:
             bottom = max(lminy, bminy)
             top = min(lmaxy, bmaxy)
-        
+
         return (left, bottom, right, top)
 
 
Index: Thuban/Model/load.py
===================================================================
RCS file: /thubanrepository/thuban/Thuban/Model/load.py,v
retrieving revision 1.54
diff -u -3 -r1.54 load.py
--- Thuban/Model/load.py	28 Jan 2005 15:54:00 -0000	1.54
+++ Thuban/Model/load.py	4 Mar 2005 15:14:56 -0000
@@ -44,6 +44,15 @@
 
 import postgisdb
 
+from wxPython.wx import wxMessageDialog, wxOK, wxICON_ERROR
+from Thuban.UI.extensionregistry import ext_registry
+try:
+    from Extensions.ogr import ogrshapes, ogrstart
+    if ogrshapes.has_ogr_support():
+        from Extensions.ogr.ogrshapes import OGRShapeStore
+except ImportError:
+    ogrshapes = None
+
 class LoadError(Exception):
 
     """Exception raised when the thuban file is corrupted
@@ -58,6 +67,14 @@
     """Exception raised to indicate that loading was interrupted by the user"""
 
 
+def has_ogr_extension():
+    """Check, if ogr extension is available."""
+    hasExt = False
+    for ext in ext_registry:
+        if ext.name == "OGRstart":
+            hasExt = True
+    return hasExt
+
 def parse_color(color):
     """Return the color object for the string color.
 
@@ -101,7 +118,7 @@
 
 class SessionLoader(XMLReader):
 
-    def __init__(self, db_connection_callback = None, 
+    def __init__(self, db_connection_callback = None,
                        shapefile_callback = None):
         """Inititialize the Sax handler."""
         XMLReader.__init__(self)
@@ -124,6 +141,7 @@
             'dbshapesource': ("start_dbshapesource", None),
             'fileshapesource': ("start_fileshapesource", None),
             'derivedshapesource': ("start_derivedshapesource", None),
+            'ogrshapesource': ("start_ogrshapesource", None),
             'filetable': ("start_filetable", None),
             'jointable': ("start_jointable", None),
 
@@ -158,9 +176,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()
 
@@ -262,12 +280,12 @@
 
     def open_shapefile(self, filename):
         """Open shapefile, with alternative path handling.
-         
+
            If a shapefile cannot be opened and an IOError is raised, check for
            an alternative. This alternative can be specified interactively by
            the user or taken from a list of (potential) locations, depending on
            the callback implementation.
-            
+
            The alternative is rechecked. If taken from a list the user
            has to confirm the alternative.
         """
@@ -305,6 +323,24 @@
                     raise
         return store
 
+    def open_ogrsource(self, filename, layername, id_column):
+        """Open an ogr datasource.
+
+        The specified datasource is tried to be opened. If the opening
+        fails a LoadError is raised.
+        """
+
+        if (has_ogr_extension() and ogrshapes.has_ogr_support()):
+            try:
+                store = ogrstart.OpenFileShapestore(self.theSession, filename, layername)
+                self.theSession.AddShapeStore(store)
+            except:
+                raise LoadError("The ogr source %s could not be opened."
+                                %filename)
+            return store
+        else:
+            return null
+
     def start_dbconnection(self, name, qname, attrs):
         attrs = self.check_attrs(name, attrs,
                                  [AttrDesc("id", True),
@@ -375,6 +411,7 @@
                                    AttrDesc("filename", True,
                                             conversion = "filename"),
                                    AttrDesc("filetype", True)])
+
         ID = attrs["id"]
         filename = attrs["filename"]
         filetype = attrs["filetype"]
@@ -392,6 +429,28 @@
         self.theSession.AddShapeStore(store)
         self.idmap[attrs["id"]] = store
 
+    def start_ogrshapesource(self, name, qname, attrs):
+        """An ogr datasource is tried to be opened.
+
+        If all required attributes are available, the ogr datasource is assigned
+        to the list of ids.
+        If the datasource could not be opened a LoadError is raised.
+        """
+        attrs = self.check_attrs(name, attrs,
+                                 [AttrDesc("id", True),
+                                  AttrDesc("filename", True),
+                                  AttrDesc("layername", True),
+                                  AttrDesc("id_column", True)])
+
+        ID = attrs["id"]
+        filename = attrs["filename"]
+        layername = attrs["layername"]
+        id_column = attrs["id_column"]
+        try:
+            self.idmap[ID] = self.open_ogrsource(filename, layername, id_column)
+        except:
+            raise LoadError("The ogr source %s could not be opened." %filename)
+
     def start_filetable(self, name, qname, attrs):
         attrs = self.check_attrs(name, attrs,
                                  [AttrDesc("id", True),
@@ -570,7 +629,6 @@
         del self.cl_group, self.cl_prop
 
     def start_clrange(self, name, qname, attrs):
-
         range = attrs.get((None, 'range'), None)
         # for backward compatibility (min/max are not saved)
         min   = attrs.get((None, 'min'), None)
@@ -635,7 +693,7 @@
         pass
 
 
-def load_session(filename, db_connection_callback = None, 
+def load_session(filename, db_connection_callback = None,
                            shapefile_callback = None):
     """Load a Thuban session from the file object file
 
Index: Thuban/Model/save.py
===================================================================
RCS file: /thubanrepository/thuban/Thuban/Model/save.py,v
retrieving revision 1.43
diff -u -3 -r1.43 save.py
--- Thuban/Model/save.py	28 Jan 2005 15:54:00 -0000	1.43
+++ Thuban/Model/save.py	4 Mar 2005 15:14:56 -0000
@@ -32,6 +32,22 @@
 from Thuban.Model.xmlwriter import XMLWriter
 from postgisdb import PostGISConnection, PostGISShapeStore
 
+from Thuban.UI.extensionregistry import ext_registry
+try:
+    from Extensions.ogr import ogrshapes
+    if ogrshapes.has_ogr_support():
+        from Extensions.ogr.ogrshapes import OGRShapeStore
+except ImportError:
+    ogrshapes = None
+
+def has_ogr_extension():
+    """Check, if the ogr extension is available."""
+    hasExt = False
+    for ext in ext_registry:
+        if ext.name == "OGRstart":
+            hasExt = True
+    return hasExt
+
 def relative_filename(dir, filename):
     """Return a filename relative to dir for the absolute file name absname.
 
@@ -242,6 +258,26 @@
                                     "left": self.get_id(left),
                                     "leftcolumn": left_field,
                                     "jointype": container.JoinType()})
+
+            # this should be the same as saving a fileshapestore
+            # after changing the extension concept
+            elif (has_ogr_extension() and ogrshapes.has_ogr_support() and
+                                    isinstance(container, OGRShapeStore)):
+                self.define_id(container.Table(), idvalue)
+                filename = container.FileName()
+                layername = container.Table().TableName()
+                idcolumn = container.Id_column()
+                if idcolumn is None:
+                    idcolumn = ""
+                filetype = container.FileType()
+                # this has to be fileshapesource, not ogrshapesource
+                self.write_element("ogrshapesource",
+                                   {"filetype": filetype,
+                                    "id": idvalue,
+                                    "filename": filename,
+                                    "layername": layername,
+                                    "id_column": idcolumn})
+
             else:
                 raise ValueError("Can't handle container %r" % container)
 
Index: Thuban/UI/classgen.py
===================================================================
RCS file: /thubanrepository/thuban/Thuban/UI/classgen.py,v
retrieving revision 1.36
diff -u -3 -r1.36 classgen.py
--- Thuban/UI/classgen.py	20 Jan 2005 11:45:15 -0000	1.36
+++ Thuban/UI/classgen.py	4 Mar 2005 15:14:57 -0000
@@ -21,9 +21,10 @@
 from Thuban.Model.classification import ClassGroupProperties
 
 from Thuban.Model.table import FIELDTYPE_INT, FIELDTYPE_DOUBLE, \
-     FIELDTYPE_STRING
+    FIELDTYPE_STRING
 
-from Thuban.Model.layer import SHAPETYPE_ARC
+from Thuban.Model.layer import SHAPETYPE_ARC, SHAPETYPE_UNKNOWN, \
+    SHAPETYPE_GEOMCOLL
 from Thuban.Model.range import Range
 from Thuban.UI.common import ThubanBeginBusyCursor, ThubanEndBusyCursor
 
@@ -156,7 +157,8 @@
         psizer.Add(self.propCombo, 1, wxALL | wxGROW, 4)
         sizer.Add(psizer, 0, wxALL | wxGROW, 4)
 
-        if layer.ShapeType() != SHAPETYPE_ARC:
+        if (layer.ShapeType() not in (SHAPETYPE_ARC, SHAPETYPE_UNKNOWN,
+                                      SHAPETYPE_GEOMCOLL)):
             psizer = wxBoxSizer(wxHORIZONTAL)
             self.fix_border_check = wxCheckBox(self, -1, _("Fix Border Color"))
             psizer.Add(self.fix_border_check, 0, wxALL | wxGROW, 4)
Index: Thuban/UI/classifier.py
===================================================================
RCS file: /thubanrepository/thuban/Thuban/UI/classifier.py,v
retrieving revision 1.73
diff -u -3 -r1.73 classifier.py
--- Thuban/UI/classifier.py	8 Feb 2005 20:34:29 -0000	1.73
+++ Thuban/UI/classifier.py	4 Mar 2005 15:14:57 -0000
@@ -36,7 +36,8 @@
 from Thuban.Model.color import Transparent
 
 from Thuban.Model.layer import Layer
-from Thuban.Model.data import SHAPETYPE_ARC, SHAPETYPE_POLYGON, SHAPETYPE_POINT
+from Thuban.Model.data import SHAPETYPE_ARC, SHAPETYPE_POLYGON, SHAPETYPE_POINT, \
+    SHAPETYPE_UNKNOWN, SHAPETYPE_GEOMCOLL, SHAPETYPE_NONE
 
 from Thuban.UI.classgen import ClassGenDialog
 from Thuban.UI.colordialog import ColorDialog
@@ -1350,7 +1351,8 @@
             if new_h > h or new_w > w:
                 return (new_w, new_h)
 
-        elif shapeType == SHAPETYPE_POLYGON:
+        elif shapeType in (SHAPETYPE_POLYGON, SHAPETYPE_UNKNOWN,
+                           SHAPETYPE_GEOMCOLL):
             dc.DrawRectangle(x, y, w, h)
 
         return None
Index: Thuban/UI/renderer.py
===================================================================
RCS file: /thubanrepository/thuban/Thuban/UI/renderer.py,v
retrieving revision 1.58
diff -u -3 -r1.58 renderer.py
--- Thuban/UI/renderer.py	18 Feb 2005 14:54:17 -0000	1.58
+++ Thuban/UI/renderer.py	4 Mar 2005 15:14:57 -0000
@@ -32,7 +32,8 @@
 from Thuban.UI.scalebar import ScaleBar
 
 from Thuban.Model.data import SHAPETYPE_POLYGON, SHAPETYPE_ARC, \
-     SHAPETYPE_POINT, RAW_SHAPEFILE
+     SHAPETYPE_POINT, SHAPETYPE_UNKNOWN, SHAPETYPE_GEOMCOLL, SHAPETYPE_NONE, \
+     RAW_SHAPEFILE
 
 from Thuban.Model.color import Transparent
 import Thuban.Model.resource
@@ -212,8 +213,11 @@
         pen = wxPen(wxBLACK, 3, wxSOLID)
         brush = wxBrush(wxBLACK, wxCROSS_HATCH)
 
+        # if the shapetype is known, use one of the known functions
+        # else ask for low level renderer for each shape in for-loop
         shapetype = layer.ShapeType()
-        useraw, func, param = self.low_level_renderer(layer)
+        if shapetype is not SHAPETYPE_UNKNOWN:
+            useraw, func, param = MapRenderer.low_level_renderer(self, layer)
         args = (pen, brush)
 
         # for point shapes we need to find out the properties
@@ -237,13 +241,175 @@
                 size = group.GetProperties().GetSize()
                 args = (pen, brush, size)
 
-            if useraw:
-                data = shape.RawData()
+            # if layer's shapetype is unknown, determine render function
+            # for each shape
+            if shapetype in (SHAPETYPE_UNKNOWN, SHAPETYPE_NONE):
+                shapeShapetype = shape.ShapeType()
+                # if shape' shapetype is a geometry collection, determine
+                # render function for each geometry in the collection
+                if shapeShapetype is not SHAPETYPE_GEOMCOLL:
+                    useraw, func, param = self.low_level_renderer(layer, shape)
+
+                    if (useraw and shape is not None):
+                        data = shape.RawData()
+                    elif shape is not None:
+                        data = shape.Points()
+                    else:
+                        data = [[]]
+
+                    func(param, data, *args)
+                    if count % 500 == 0:
+                        yield True
+
+                if shapeShapetype == SHAPETYPE_GEOMCOLL:
+                    for i in range(len(shape.GetGeoms())):
+                        count += 1
+                        geom = shape.GetGeom(i)
+                        useraw, func, param = (
+                                        self.low_level_renderer(layer, geom))
+
+                        if useraw:
+                            data = shape.RawData()
+                        else:
+                            data = [shape.Points()[i]]
+
+                        func(param, data, pen, brush)
+                        if count % 500 == 0:
+                            yield True
+
+            else:
+                if (useraw and shape is not None):
+                    data = shape.RawData()
+                elif shape is not None:
+                    data = shape.Points()
+                else:
+                    data = [[]]
+
+                func(param, data, *args)
+                if count % 500 == 0:
+                    yield True
+
+    def draw_shape_layer_incrementally(self, layer):
+
+        """Draw the shape layer layer onto the map incrementally.
+
+        This method is a generator which yields True after every 500
+        shapes.
+        """
+        scale = self.scale
+        offx, offy = self.offset
+
+        map_proj = self.map.projection
+        layer_proj = layer.projection
+
+        brush = self.TRANSPARENT_BRUSH
+        pen   = self.TRANSPARENT_PEN
+
+        old_prop = None
+        old_group = None
+        lc = layer.GetClassification()
+        field = layer.GetClassificationColumn()
+        defaultGroup = lc.GetDefaultGroup()
+        table = layer.ShapeStore().Table()
+
+        if lc.GetNumGroups() == 0:
+            # There's only the default group, so we can pretend that
+            # there is no field to classifiy on which makes things
+            # faster since we don't need the attribute information at
+            # all.
+            field = None
+
+        # Determine which render function to use.
+        # If shapetype is unknown, ask for each shape in loop
+        # which render function to use.
+        shapetype = layer.ShapeType()
+        if shapetype not in (SHAPETYPE_UNKNOWN, SHAPETYPE_GEOMCOLL):
+            useraw, draw_func, draw_func_param = (
+                                MapRenderer.low_level_renderer(self, layer))
+
+        #
+        # Iterate through all shapes that have to be drawn.
+        #
+
+        # Count the shapes drawn so that we can yield every few hundred
+        # shapes
+        count = 0
+
+        # Cache the tools (pens and brushes) for the classification
+        # groups. This is a mapping from the group's ids to the a tuple
+        # (pen, brush)
+        tool_cache = {}
+
+        for shape in self.layer_shapes(layer):
+            count += 1
+            if field is None:
+                group = defaultGroup
             else:
-                data = shape.Points()
-            func(param, data, *args)
-            if count % 500 == 0:
-                yield True
+                value = table.ReadValue(shape.ShapeID(), field)
+                group = lc.FindGroup(value)
+
+            if not group.IsVisible():
+                continue
+
+            try:
+                pen, brush = tool_cache[id(group)]
+            except KeyError:
+                pen, brush = tool_cache[id(group)] \
+                             = self.tools_for_property(group.GetProperties())
+
+            if shapetype in (SHAPETYPE_UNKNOWN, SHAPETYPE_NONE):
+                # if shape's shapetype is a collection, determine render
+                # function for each geometry object in the collection
+                shapeShapetype = shape.ShapeType()
+                if shapeShapetype is not SHAPETYPE_GEOMCOLL:
+                    useraw, draw_func, draw_func_param = (
+                                        self.low_level_renderer(layer, shape))
+                    if useraw:
+                        data = shape.RawData()
+                    else:
+                        data = shape.Points()
+
+                    if draw_func == self.draw_point_shape:
+                        draw_func(draw_func_param, data, pen, brush,
+                               size = group.GetProperties().GetSize())
+                    else:
+                        draw_func(draw_func_param, data, pen, brush)
+                    if count % 500 == 0:
+                        yield True
+
+                if shapeShapetype == SHAPETYPE_GEOMCOLL:
+                    for i in range(len(shape.GetGeoms())):
+                        count += 1
+                        geom = shape.GetGeom(i)
+                        useraw, draw_func, draw_func_param = (
+                                        self.low_level_renderer(layer, geom))
+
+                        if useraw:
+                            data = shape.RawData()
+                        else:
+                            data = [shape.Points()[i]]
+
+                        if draw_func == self.draw_point_shape:
+                            draw_func(draw_func_param, data, pen, brush,
+                                size = group.GetProperties().GetSize())
+                        else:
+                            draw_func(draw_func_param, data, pen, brush)
+                        if count % 500 == 0:
+                            yield True
+
+            else:
+                if useraw:
+                    data = shape.RawData()
+                else:
+                    data = shape.Points()
+
+                if draw_func == self.draw_point_shape:
+                    draw_func(draw_func_param, data, pen, brush,
+                           size = group.GetProperties().GetSize())
+                else:
+                    draw_func(draw_func_param, data, pen, brush)
+                if count % 500 == 0:
+                    yield True
 
     def layer_shapes(self, layer):
         """Return the shapeids covered by the region that has to be redrawn
@@ -282,6 +448,25 @@
 
         return layer.ShapesInRegion((left, bottom, right, top))
 
+    def low_level_renderer(self, layer, shape):
+        """If the layer's shapetype is unknown, the render function has to be
+        determined for each shape.
+
+        If the shapetype is unknown even for the shape, use polygon function
+        to render.
+        """
+        if shape is not None:
+            shapetype = shape.ShapeType()
+        else:
+            return False, None, layer
+        if shapetype == SHAPETYPE_POINT:
+            func = self.draw_point_shape
+        elif shapetype == SHAPETYPE_ARC:
+            func = self.draw_arc_shape
+        else:
+            func = self.draw_polygon_shape
+
+        return False, func, layer
 
 class ExportRenderer(ScreenRenderer):
 
Index: Thuban/UI/viewport.py
===================================================================
RCS file: /thubanrepository/thuban/Thuban/UI/viewport.py,v
retrieving revision 1.20
diff -u -3 -r1.20 viewport.py
--- Thuban/UI/viewport.py	24 Jan 2005 11:19:53 -0000	1.20
+++ Thuban/UI/viewport.py	4 Mar 2005 15:14:57 -0000
@@ -23,7 +23,8 @@
      LAYER_PROJECTION_CHANGED, TITLE_CHANGED, \
      MAP_LAYERS_ADDED, MAP_LAYERS_REMOVED
 from Thuban.Model.data import SHAPETYPE_POLYGON, SHAPETYPE_ARC, \
-     SHAPETYPE_POINT, RAW_SHAPEFILE
+     SHAPETYPE_POINT, SHAPETYPE_UNKNOWN, SHAPETYPE_GEOMCOLL, SHAPETYPE_NONE, \
+     RAW_SHAPEFILE
 from Thuban.Model.label import ALIGN_CENTER, ALIGN_TOP, ALIGN_BOTTOM, \
      ALIGN_LEFT, ALIGN_RIGHT
 from Thuban.Lib.connector import Publisher, Conduit
@@ -471,6 +472,7 @@
         scale = min(scalex, scaley)
         offx = 0.5 * (width - (urx + llx) * scale)
         offy = 0.5 * (height + (ury + lly) * scale)
+
         self.set_view_transform(scale, (offx, offy))
 
     def FitMapToWindow(self):
@@ -490,7 +492,7 @@
         Set the scale so that the layer fits exactly into the window and
         center it in the window.
         """
-        
+
         bbox = layer.LatLongBoundingBox()
         if bbox is not None:
             proj = self.map.GetProjection()
@@ -501,6 +503,7 @@
                 self.FitRectToWindow(bbox)
 
     def FitSelectedToWindow(self):
+        """Fit the selection to window."""
         layer = self.selection.SelectedLayer()
         shapes = self.selection.SelectedShapes()
 
@@ -512,8 +515,16 @@
 
             if bbox is not None:
                 if len(shapes) == 1 and layer.ShapeType() == SHAPETYPE_POINT:
-                    self.ZoomFactor(self.calc_min_max_scales()[1] / self.scale, 
+                    self.ZoomFactor(self.calc_min_max_scales()[1] / self.scale,
+                                    self.proj_to_win(bbox[0], bbox[1]))
+                elif (len(shapes) == 1 and layer.ShapeType()
+                                    in (SHAPETYPE_UNKNOWN, SHAPETYPE_NONE,
+                                        SHAPETYPE_GEOMCOLL)):
+                    if layer.Shape(shapes[0]).ShapeType() == SHAPETYPE_POINT:
+                        self.ZoomFactor(self.calc_min_max_scales()[1]/self.scale,
                                     self.proj_to_win(bbox[0], bbox[1]))
+                    else:
+                        self.FitRectToWindow(bbox)
                 else:
                     self.FitRectToWindow(bbox)
 
@@ -797,6 +808,10 @@
             return self._hit_arc
         elif shapetype == SHAPETYPE_POLYGON:
             return self._hit_polygon
+        elif shapetype == SHAPETYPE_UNKNOWN:
+            return self._hit_unknown
+        elif shapetype == SHAPETYPE_GEOMCOLL:
+            return self._hit_unknown
         else:
             raise ValueError("Unknown shapetype %r" % shapetype)
 
@@ -873,6 +888,44 @@
             return bool(hit)
         return stroked and hit < 0
 
+    def _hit_collection(self, layer, shape, filled, stroked, px, py):
+        """Internal: return whether a click at (px,py) hits one of the
+        shapes in the collection.
+
+        shape has to have a method GetGeoms(), which lists all the objects
+        of the collection.
+        Every geometry has to be tested for being hit with the corresponding
+        method."""
+        geoms = shape.GetGeoms()
+        hit = False
+        for i in range(len(geoms)):
+            geom = geoms[i]
+            geomtype = geom.ShapeType()
+            if geomtype == SHAPETYPE_POINT and not hit:
+                hit = self._hit_point(layer, shape, filled, stroked, px, py)
+            elif geomtype == SHAPETYPE_ARC and not hit:
+                hit = self._hit_arc(layer, shape, filled, stroked, px, py)
+            elif not hit:
+                hit = self._hit_polygon(layer, shape, filled, stroked, px, py)
+        return hit
+
+    def _hit_unknown(self, layer, shape, filled, stroked, px, py):
+        """Internal: return whether a click at (px,py) hits the shape.
+
+        As this method is called for layer with unknown shapetype the
+        hit_function is chosen based on the shapetype of the given shape.
+        Shapes with a shapetype other than point or arc are treated
+        as polygons.
+        """
+        if shape.ShapeType() == SHAPETYPE_POINT:
+            return self._hit_point(layer, shape, filled, stroked, px, py)
+        elif shape.ShapeType() == SHAPETYPE_ARC:
+            return self._hit_arc(layer, shape, filled, stroked, px, py)
+        elif shape.ShapeType() == SHAPETYPE_GEOMCOLL:
+            return self._hit_collection(layer, shape, filled, stroked, px, py)
+        else:
+            return self._hit_polygon(layer, shape, filled, stroked, px, py)
+
     def _find_label_at(self, px, py):
         """Internal: Find the label at (px, py) and return its index
 
@@ -966,15 +1019,26 @@
 
             shapetype = layer.ShapeType()
             if shapetype == SHAPETYPE_POLYGON:
-                shapefile = layer.ShapeStore().Shapefile().cobject()
-                x, y = shape_centroid(shapefile, shape_index,
+                try:
+                    # cobject only exists for shapefiles
+                    # ogr extension does not have this method
+                    shapefile = layer.ShapeStore().Shapefile().cobject()
+                    x, y = shape_centroid(shapefile, shape_index,
                                       map_proj, layer_proj, 1, 1, 0, 0)
-                if map_proj is not None:
-                    x, y = map_proj.Inverse(x, y)
+                    if map_proj is not None:
+                        x, y = map_proj.Inverse(x, y)
+                except:
+                    # OGR has method Centroid(), but it does not work yet
+                    shape = layer.Shape(shape_index)
+                    x, y = shape.Points()[0][0]
+                    if layer_proj is not None:
+                        x, y = layer_proj.Inverse(x, y)
             else:
                 shape = layer.Shape(shape_index)
                 if shapetype == SHAPETYPE_POINT:
                     x, y = shape.Points()[0][0]
+                elif shapetype == SHAPETYPE_GEOMCOLL:
+                    x, y = shape.Points()[0][0]
                 else:
                     # assume SHAPETYPE_ARC
                     points = shape.Points()[0]
@@ -989,6 +1053,12 @@
                 valign = ALIGN_CENTER
             elif shapetype == SHAPETYPE_ARC:
                 halign = ALIGN_LEFT
+                valign = ALIGN_CENTER
+            elif shapetype == SHAPETYPE_UNKNOWN:
+                halign = ALIGN_CENTER
+                valign = ALIGN_CENTER
+            elif shapetype == SHAPETYPE_GEOMCOLL:
+                halign = ALIGN_CENTER
                 valign = ALIGN_CENTER
             label_layer.AddLabel(x, y, text,
                                  halign = halign, valign = valign)
