I've been working on code to generate a list of dirty tiles while importing the deltas. The attached patch introduces 2 new commandline options: "-e <zoomlevel>" and "-o <dirty tile list output file>". So, specifying "-e 17 -o /tmp/dirty_tiles" when importing a delta will cause osm2pgsql to generate a list of all zoom level 17 tiles which the delta has made dirty and store it in /tmp/dirty_tiles.

Proviso: for polygons, it currently takes a simplistic approach of drawing a bounding box around the whole polygon and marking every tile in the box as dirty. If the bounding box is large (over 30x30Km) the polygon is treated as a line instead, so only the perimeter will be marked as dirty (this is so that huge polygons don't expire vast numbers of tiles and is based on the assumption that we probably aren't going to shade the area of massive polygons).

The dirty tile list is maintained in memory as a binary tree and dumped to disk at the end of the run.

I'm running this code on OpenPisteMap and it seems to be working ok. Does anyone have any objection to me committing these changes to the OpenStreetMap subversion server?

 - Steve
   xmpp:[email protected]   sip:[email protected]   http://www.nexusuk.org/

     Servatis a periculum, servatis a maleficum - Whisper, Evanescence
Index: output.h
===================================================================
--- output.h    (revision 13558)
+++ output.h    (working copy)
@@ -10,6 +10,7 @@
 #ifndef OUTPUT_H
 #define OUTPUT_H
 
+#include "middle.h"
 #include "keyvals.h"
 
 struct output_options {
@@ -22,6 +23,8 @@
   int cache;       /* Memory usable for cache in MB */
   struct middle_t *mid;  /* Mid storage to use */
   const char *style;     /* style file to use */
+  int expire_tiles_zoom;       /* Zoom level for tile expiry list */
+  const char *expire_tiles_filename;   /* File name to output expired tiles 
list to */
 };
 
 struct output_t {
Index: build_geometry.cpp
===================================================================
--- build_geometry.cpp  (revision 13558)
+++ build_geometry.cpp  (working copy)
@@ -176,6 +176,85 @@
    areas.clear();
 }
 
+static int coords2nodes(CoordinateSequence * coords, struct osmNode ** nodes) {
+    size_t                     num_coords;
+    size_t                     i;
+    Coordinate         coord;
+
+    num_coords = coords->getSize();
+    *nodes = (struct osmNode *) malloc(num_coords * sizeof(struct osmNode));
+
+    for (i = 0; i < num_coords; i++) {
+        coord = coords->getAt(i);
+        (*nodes)[i].lon = coord.x;
+        (*nodes)[i].lat = coord.y;
+    }
+    return num_coords;
+}
+
+int parse_wkt(const char * wkt, struct osmNode *** xnodes, int ** xcount, int 
* polygon) {
+    GeometryFactory            gf;
+    WKTReader          reader(&gf);
+    std::string                wkt_string(wkt);
+    Geometry *         geometry;
+    const Geometry *   subgeometry;
+    GeometryCollection *       gc;
+    CoordinateSequence *       coords;
+    size_t                     num_geometries;
+    size_t                     i;
+       
+    *polygon = 0;
+    try {
+        geometry = reader.read(wkt_string);
+        switch (geometry->getGeometryTypeId()) {
+            // Single geometries
+            case geos::GEOS_POLYGON:
+                // Drop through
+            case geos::GEOS_LINEARRING:
+                *polygon = 1;
+                // Drop through
+            case geos::GEOS_POINT:
+                // Drop through
+            case geos::GEOS_LINESTRING:
+                *xnodes = (struct osmNode **) malloc(2 * sizeof(struct osmNode 
*));
+                *xcount = (int *) malloc(sizeof(int));
+                coords = geometry->getCoordinates();
+                (*xcount)[0] = coords2nodes(coords, &((*xnodes)[0]));
+                (*xnodes)[1] = NULL;
+                delete coords;
+                break;
+            // Geometry collections
+            case geos::GEOS_MULTIPOLYGON:
+                *polygon = 1;
+                // Drop through
+            case geos::GEOS_MULTIPOINT:
+                // Drop through
+            case geos::GEOS_MULTILINESTRING:
+                gc = (GeometryCollection *) geometry;
+                num_geometries = gc->getNumGeometries();
+                *xnodes = (struct osmNode **) malloc((num_geometries + 1) * 
sizeof(struct osmNode *));
+                *xcount = (int *) malloc(num_geometries * sizeof(int));
+                for (i = 0; i < num_geometries; i++) {
+                    subgeometry = gc->getGeometryN(i);
+                    coords = subgeometry->getCoordinates();
+                    (*xcount)[0] = coords2nodes(coords, &((*xnodes)[i]));
+                    delete coords;
+                }
+                (*xnodes)[i] = NULL;
+                break;
+            default:
+                std::cerr << std::endl << "unexpected object type while 
processing PostGIS data" << std::endl;
+                delete geometry;
+                return -1;
+        }
+        delete geometry;
+    } catch (...) {
+        std::cerr << std::endl << "excepton caught parsing PostGIS data" << 
std::endl;
+        return -1;
+    }
+    return 0;
+}
+
 size_t build_geometry(int osm_id, struct osmNode **xnodes, int *xcount, int 
make_polygon) {
     size_t wkt_size = 0;
     std::auto_ptr<std::vector<Geometry*> > lines(new std::vector<Geometry*>);
Index: osm2pgsql.c
===================================================================
--- osm2pgsql.c (revision 13558)
+++ osm2pgsql.c (working copy)
@@ -481,6 +481,8 @@
     fprintf(stderr, "   -W|--password\tForce password prompt.\n");
     fprintf(stderr, "   -H|--host\t\tDatabase server hostname or socket 
location.\n");
     fprintf(stderr, "   -P|--port\t\tDatabase server port.\n");
+    fprintf(stderr, "   -e|--expire-tiles zoom\tCreate a tile expiry list for 
a zoom level.\n");
+    fprintf(stderr, "   -o|--expire-output filename\tOutput filename for 
expired tiles list.\n");
     fprintf(stderr, "   -h|--help\t\tHelp information.\n");
     fprintf(stderr, "   -v|--verbose\t\tVerbose output.\n");
     fprintf(stderr, "\n");
@@ -571,6 +573,8 @@
     int sanitize=0;
     int pass_prompt=0;
     int projection = PROJ_SPHERE_MERC;
+    int expire_tiles_zoom = -1;
+    const char *expire_tiles_filename = "dirty_tiles";
     const char *db = "gis";
     const char *username=NULL;
     const char *host=NULL;
@@ -607,10 +611,12 @@
             {"port",     1, 0, 'P'},
             {"help",     0, 0, 'h'},
             {"style",    1, 0, 'S'},
+            {"expire-tiles", 1, 0, 'e'},
+            {"expire-output", 1, 0, 'o'},
             {0, 0, 0, 0}
         };
 
-        c = getopt_long (argc, argv, "ab:cd:hlmMp:suvU:WH:P:E:C:S:", 
long_options, &option_index);
+        c = getopt_long (argc, argv, "ab:cd:hlmMp:suvU:WH:P:E:C:S:e:o:", 
long_options, &option_index);
         if (c == -1)
             break;
 
@@ -633,6 +639,8 @@
             case 'H': host=optarg; break;
             case 'P': port=optarg; break;
             case 'S': style=optarg; break;
+            case 'e': expire_tiles_zoom=atoi(optarg); break;
+            case 'o': expire_tiles_filename=optarg; break;
 
             case 'h':
             case '?':
@@ -690,6 +698,8 @@
     options.mid = slim ? &mid_pgsql : &mid_ram;
     options.cache = cache;
     options.style = style;
+    options.expire_tiles_zoom = expire_tiles_zoom;
+    options.expire_tiles_filename = expire_tiles_filename;
     out = &out_pgsql;
 
     out->start(&options);
Index: middle.h
===================================================================
--- middle.h    (revision 13558)
+++ middle.h    (working copy)
@@ -7,6 +7,8 @@
 #ifndef MIDDLE_H
 #define MIDDLE_H
 
+#include "osmtypes.h"
+
 struct keyval;
 struct member;
 struct output_options;
Index: expire-tiles.c
===================================================================
--- expire-tiles.c      (revision 0)
+++ expire-tiles.c      (revision 0)
@@ -0,0 +1,352 @@
+/*
+ * Dirty tile list generation
+ *
+ * Steve Hill <[email protected]>
+ */
+
+#include <libpq-fe.h>
+#include <math.h>
+#include <stdlib.h>
+#include "expire-tiles.h"
+#include "output.h"
+#include "pgsql.h"
+#include "build_geometry.h"
+
+#define EARTH_CIRCUMFERENCE            40075016.68
+#define HALF_EARTH_CIRCUMFERENCE       (EARTH_CIRCUMFERENCE / 2)
+#define TILE_EXPIRY_LEEWAY             0.5             // How many tiles worth 
of space to leave either side of a changed feature
+#define EXPIRE_TILES_MAX_BBOX          30000           // Maximum width or 
height of a bounding box (metres)
+
+struct tile_subtree {
+       struct tile_subtree *   less;
+       struct tile_subtree *   greater;
+       int                     y;
+};
+
+struct tile_tree {
+       struct tile_tree *      less;
+       struct tile_tree *      greater;
+       int                     x;
+       struct tile_subtree *   subtree;
+};
+
+static int                             map_width;
+static double                          tile_width;
+static const struct output_options *   Options;
+static struct tile_tree *              dirty = NULL;
+static int                             outcount;
+
+static void add_to_subtree(struct tile_subtree ** tree, int y) {
+       while (*tree) {
+               if (y < (*tree)->y) tree = &((*tree)->less);
+               else if (y > (*tree)->y) tree = &((*tree)->greater);
+               else return;    // Already in the tree
+       }
+       *tree = calloc(1, sizeof(**tree));
+       (*tree)->y = y;
+}
+
+static void add_to_tree(struct tile_tree ** tree, int x, int y) {
+       while (*tree) {
+               if (x < (*tree)->x) tree = &((*tree)->less);
+               else if (x > (*tree)->x) tree = &((*tree)->greater);
+               else {
+                       add_to_subtree(&((*tree)->subtree), y);
+                       return;
+               }
+       }
+       *tree = calloc(1, sizeof(**tree));
+       (*tree)->x = x;
+       add_to_subtree(&((*tree)->subtree), y);
+}
+
+static void output_and_destroy_subtree(FILE * outfile, struct tile_subtree ** 
tree, int x) {
+       if (! *tree) return;
+       output_and_destroy_subtree(outfile, &((*tree)->less), x);
+       if (outfile) {
+               outcount++;
+               if ((outcount <= 1) || (! (outcount % 1000))) {
+                       fprintf(stderr, "\rWriting dirty tile list (%iK)", 
outcount / 1000);
+                       fflush(stderr);
+               }
+               fprintf(outfile, "%i/%i/%i\n", Options->expire_tiles_zoom, x, 
(*tree)->y);
+       }
+       output_and_destroy_subtree(outfile, &((*tree)->greater), x);
+       free(*tree);
+}
+
+static void output_and_destroy_tree(FILE * outfile, struct tile_tree ** tree) {
+       if (! *tree) return;
+       output_and_destroy_tree(outfile, &((*tree)->less));
+       output_and_destroy_subtree(outfile, &((*tree)->subtree), (*tree)->x);
+       output_and_destroy_tree(outfile, &((*tree)->greater));
+       free(*tree);
+}
+
+void expire_tiles_stop(void) {
+       FILE *  outfile;
+
+       outcount = 0;
+       outfile = fopen(Options->expire_tiles_filename, "a");
+       output_and_destroy_tree(outfile, &dirty);
+       if (outfile) fclose(outfile);
+       else fprintf(stderr, "Failed to open expired tiles file.  Tile expiry 
list will now be written!\n");
+}
+
+void expire_tiles_init(const struct output_options *options) {
+       Options = options;
+       map_width = pow(2,Options->expire_tiles_zoom);
+       tile_width = EARTH_CIRCUMFERENCE / map_width;
+}
+
+static double coords_to_tile_x(double lon) {
+       return map_width * (0.5 + (lon / EARTH_CIRCUMFERENCE));
+}
+
+static double coords_to_tile_y(double lat) {
+       return map_width * (0.5 - (lat / EARTH_CIRCUMFERENCE));
+}
+
+static void expire_tile(int x, int y) {
+       add_to_tree(&dirty, x, y);
+}
+
+static int normalise_tile_x_coord(int x) {
+       x %= map_width;
+       if (x < 0) x = (map_width - x) + 1;
+       return x;
+}
+
+/*
+ * Expire tiles that a line crosses
+ */
+static void expire_tiles_from_line(double lon_a, double lat_a, double lon_b, 
double lat_b) {
+       double  tile_x_a;
+       double  tile_y_a;
+       double  tile_x_b;
+       double  tile_y_b;
+       double  temp;
+       double  x1;
+       double  y1;
+       double  x2;
+       double  y2;
+       double  hyp_len;
+       double  x_len;
+       double  y_len;
+       double  x_step;
+       double  y_step;
+       double  step;
+       double  next_step;
+       int     x;
+       int     y;
+       int     norm_x;
+
+       tile_x_a = coords_to_tile_x(lon_a);
+       tile_y_a = coords_to_tile_y(lat_a);
+       tile_x_b = coords_to_tile_x(lon_b);
+       tile_y_b = coords_to_tile_y(lat_b);
+       if (tile_x_a > tile_x_b) {
+               // We always want the line to go from left to right - swap the 
ends if it doesn't
+               temp = tile_x_b;
+               tile_x_b = tile_x_a;
+               tile_x_a = temp;
+               temp = tile_y_b;
+               tile_y_b = tile_y_a;
+               tile_y_a = temp;
+       }
+
+       x_len = tile_x_b - tile_x_a;
+       if (x_len > map_width / 2) {
+               // If the line is wider than half the map, assume it
+               // crosses the international date line.
+               // These coordinates get normalised again later
+               tile_x_a += map_width;
+               temp = tile_x_b;
+               tile_x_b = tile_x_a;
+               tile_x_a = temp;
+               temp = tile_y_b;
+               tile_y_b = tile_y_a;
+               tile_y_a = temp;
+       }
+       y_len = tile_y_b - tile_y_a;
+       hyp_len = sqrt(pow(x_len, 2) + pow(y_len, 2));  // Pythagoras
+       x_step = x_len / hyp_len;
+       y_step = y_len / hyp_len;
+//     fprintf(stderr, "Expire from line (%f,%f),(%f,%f) [%f,%f],[%f,%f] %fx%f 
hyp_len = %f\n", lon_a, lat_a, lon_b, lat_b, tile_x_a, tile_y_a, tile_x_b, 
tile_y_b, x_len, y_len, hyp_len);
+       
+       for (step = 0; step <= hyp_len; step ++) {
+               // Interpolate points 1 tile width apart
+               next_step = step + 1;
+               if (next_step > hyp_len) next_step = hyp_len;
+               x1 = tile_x_a + ((double)step * x_step);
+               y1 = tile_y_a + ((double)step * y_step);
+               x2 = tile_x_a + ((double)next_step * x_step);
+               y2 = tile_y_a + ((double)next_step * y_step);
+               
+//             printf("Expire from subline (%f,%f),(%f,%f)\n", x1, y1, x2, y2);
+               // The line (x1,y1),(x2,y2) is up to 1 tile width long
+               // x1 will always be <= x2
+               // We could be smart and figure out the exact tiles intersected,
+               // but for simplicity, treat the coordinates as a bounding box
+               // and expire everything within that box.
+               if (y1 > y2) {
+                       temp = y2;
+                       y2 = y1;
+                       y1 = temp;
+               }
+               for (x = x1 - TILE_EXPIRY_LEEWAY; x <= x2 + TILE_EXPIRY_LEEWAY; 
x ++) {
+                       norm_x =  normalise_tile_x_coord(x);
+                       for (y = y1 - TILE_EXPIRY_LEEWAY; y <= y2 + 
TILE_EXPIRY_LEEWAY; y ++) {
+                               expire_tile(norm_x, y);
+                       }
+               }
+       }
+}
+
+/*
+ * Expire tiles within a bounding box
+ */
+int expire_tiles_from_bbox(double min_lon, double min_lat, double max_lon, 
double max_lat) {
+       double          width;
+       double          height;
+       int             min_tile_x;
+       int             min_tile_y;
+       int             max_tile_x;
+       int             max_tile_y;
+       int             iterator_x;
+       int             iterator_y;
+       int             norm_x;
+       int             ret;
+
+       if (Options->expire_tiles_zoom < 0) return 0;
+       width = max_lon - min_lon;
+       height = max_lat - min_lat;
+       if (width > HALF_EARTH_CIRCUMFERENCE + 1) {
+               // Over half the planet's width within the bounding box - 
assume the
+               // box crosses the international date line and split it into 
two boxes
+               ret = expire_tiles_from_bbox(-HALF_EARTH_CIRCUMFERENCE, 
min_lat, min_lon, max_lat);
+               ret += expire_tiles_from_bbox(max_lon, min_lat, 
HALF_EARTH_CIRCUMFERENCE, max_lat);
+               return ret;
+       }
+
+       if (width > EXPIRE_TILES_MAX_BBOX) return -1;
+       if (height > EXPIRE_TILES_MAX_BBOX) return -1;
+
+//     printf("Expire from bbox (%f,%f)-(%f,%f) %fx%f\n", min_lon, min_lat, 
min_lon, min_lat, width, height);
+
+       // Convert the box's Mercator coordinates into tile coordinates
+       min_tile_x = coords_to_tile_x(min_lon) - TILE_EXPIRY_LEEWAY;
+       max_tile_y = coords_to_tile_x(min_lat) + TILE_EXPIRY_LEEWAY;
+       max_tile_x = coords_to_tile_x(min_lon) + TILE_EXPIRY_LEEWAY;
+       min_tile_y = coords_to_tile_x(min_lat) - TILE_EXPIRY_LEEWAY;
+       if (min_tile_x < 0) min_tile_x = 0;
+       if (min_tile_y < 0) min_tile_y = 0;
+       if (max_tile_x > map_width) max_tile_x = map_width;
+       if (max_tile_y > map_width) max_tile_y = map_width;
+//     printf("BBOX: (%f %f) - (%f %f) [%i %i] - [%i %i]\n", min_lon, min_lat, 
max_lon, max_lat, min_tile_x, min_tile_y, max_tile_x, max_tile_y);
+       for (iterator_x = min_tile_x; iterator_x <= max_tile_x; iterator_x ++) {
+               norm_x =  normalise_tile_x_coord(iterator_x);
+               for (iterator_y = min_tile_y; iterator_y <= max_tile_y; 
iterator_y ++) {
+                       expire_tile(norm_x, iterator_y);
+               }
+       }
+       return 0;
+}
+
+void expire_tiles_from_nodes_line(struct osmNode * nodes, int count) {
+       int     i;
+       double  last_lat;
+       double  last_lon;
+
+       if (Options->expire_tiles_zoom < 0) return;
+//     fprintf(stderr, "Expire from nodes_line (%i)\n", count);
+       if (count < 1) return;
+       last_lat = nodes[0].lat;
+       last_lon = nodes[0].lon;
+       if (count < 2) {
+               expire_tiles_from_bbox(last_lon, last_lat, last_lon, last_lat);
+               return;
+       }
+       for (i = 1; i < count; i ++) {
+               expire_tiles_from_line(last_lon, last_lat, nodes[i].lon, 
nodes[i].lat);
+               last_lat = nodes[i].lat;
+               last_lon = nodes[i].lon;
+       }
+}
+
+/*
+ * Calculate a bounding box from a list of nodes and expire all tiles within it
+ */
+void expire_tiles_from_nodes_poly(struct osmNode * nodes, int count, int 
osm_id) {
+       int     i;
+       int     got_coords = 0;
+       double  min_lon = 0.0;
+       double  min_lat = 0.0;
+       double  max_lon = 0.0;
+       double  max_lat = 0.0;
+        
+       if (Options->expire_tiles_zoom < 0) return;
+//     printf("Expire from nodes_poly (%i)\n", count);
+       for (i = 0; i < count; i++) {
+               if ((! got_coords) || (nodes[i].lon < min_lon)) min_lon = 
nodes[i].lon;
+               if ((! got_coords) || (nodes[i].lat < min_lat)) min_lat = 
nodes[i].lat;
+               if ((! got_coords) || (nodes[i].lon > max_lon)) max_lon = 
nodes[i].lon;
+               if ((! got_coords) || (nodes[i].lat > max_lat)) max_lat = 
nodes[i].lat;
+               got_coords = 1;
+       }
+       if (got_coords) {
+               if (expire_tiles_from_bbox(min_lon, min_lat, max_lon, max_lat)) 
{
+                       // Bounding box too big - just expire tiles on the line
+                       fprintf(stderr, "\rLarge polygon (%.0f x %.0f metres, 
OSM ID %i) - only expiring perimeter\n", max_lon - min_lon, max_lat - min_lat, 
osm_id);
+                       expire_tiles_from_nodes_line(nodes, count);
+               }
+       }
+}
+
+static void expire_tiles_from_xnodes_poly(struct osmNode ** xnodes, int * 
xcount, int osm_id) {
+       int     i;
+
+       if (Options->expire_tiles_zoom < 0) return;
+        for (i = 0; xnodes[i]; i++) expire_tiles_from_nodes_poly(xnodes[i], 
xcount[i], osm_id);
+}
+
+static void expire_tiles_from_xnodes_line(struct osmNode ** xnodes, int * 
xcount) {
+       int     i;
+
+        for (i = 0; xnodes[i]; i++) expire_tiles_from_nodes_line(xnodes[i], 
xcount[i]);
+}
+
+void expire_tiles_from_wkt(const char * wkt, int osm_id) {
+       struct osmNode **       xnodes;
+       int *                   xcount;
+       int                     polygon;
+       int                     i;
+
+       if (! parse_wkt(wkt, &xnodes, &xcount, &polygon)) {
+               if (polygon) expire_tiles_from_xnodes_poly(xnodes, xcount, 
osm_id);
+               else expire_tiles_from_xnodes_line(xnodes, xcount);
+               for (i = 0; xnodes[i]; i++) free(xnodes[i]);
+               free(xnodes);
+               free(xcount);
+       }
+}
+
+void expire_tiles_from_db(PGconn * sql_conn, int osm_id) {
+       PGresult *      res;
+       char            tmp[16];
+       char const *    paramValues[1];
+       int             tuple;
+       char *          wkt;
+
+       if (Options->expire_tiles_zoom < 0) return;
+       snprintf(tmp, sizeof(tmp), "%d", osm_id);
+       paramValues[0] = tmp;
+       res = pgsql_execPrepared(sql_conn, "get_way", 1, paramValues, 
PGRES_TUPLES_OK);
+       for (tuple = 0; tuple < PQntuples(res); tuple++) {
+               wkt = PQgetvalue(res, tuple, 0);
+               expire_tiles_from_wkt(wkt, osm_id);
+       }
+       PQclear(res);
+}
+
+
Index: expire-tiles.h
===================================================================
--- expire-tiles.h      (revision 0)
+++ expire-tiles.h      (revision 0)
@@ -0,0 +1,14 @@
+#ifndef EXPIRE_TILES_H
+#define EXPIRE_TILES_H
+
+#include "output.h"
+
+void expire_tiles_init(const struct output_options *options);
+void expire_tiles_stop(void);
+int expire_tiles_from_bbox(double min_lon, double min_lat, double max_lon, 
double max_lat);
+void expire_tiles_from_nodes_line(struct osmNode * nodes, int count);
+void expire_tiles_from_nodes_poly(struct osmNode * nodes, int count, int 
osm_id);
+void expire_tiles_from_wkt(const char * wkt, int osm_id);
+void expire_tiles_from_db(PGconn * sql_conn, int osm_id);
+
+#endif
Index: build_geometry.h
===================================================================
--- build_geometry.h    (revision 13558)
+++ build_geometry.h    (working copy)
@@ -29,6 +29,8 @@
 
 #include "osmtypes.h"
 
+int parse_wkt(const char * wkt, struct osmNode *** xnodes, int ** xcount, int 
* polygon);
+
 char *get_wkt_simple(struct osmNode *, int count, int polygon, double *area, 
double *int_x, double *int_y);
 
 char* get_wkt(size_t index);
Index: output-pgsql.c
===================================================================
--- output-pgsql.c      (revision 13558)
+++ output-pgsql.c      (working copy)
@@ -26,6 +26,7 @@
 #include "build_geometry.h"
 #include "middle.h"
 #include "pgsql.h"
+#include "expire-tiles.h"
 
 #define SRID (project_getprojinfo()->srs)
 
@@ -431,6 +432,7 @@
     char sql[2048], *v;
     int i;
 
+    expire_tiles_from_bbox(node_lon, node_lat, node_lon, node_lat);
     sprintf(sql, "%d\t", id);
     copy_to_table(t_point, sql);
 
@@ -628,6 +630,7 @@
     if (wkt && strlen(wkt)) {
        /* FIXME: there should be a better way to detect polygons */
        if (!strncmp(wkt, "POLYGON", strlen("POLYGON"))) {
+            expire_tiles_from_nodes_poly(nodes, count, id);
            if (area > 0.0) {
                char tmp[32];
                snprintf(tmp, sizeof(tmp), "%f", area);
@@ -636,6 +639,7 @@
            write_wkts(id, tags, wkt, t_poly);
            add_parking_node(id, tags, interior_lat, interior_lon);
        } else {
+            expire_tiles_from_nodes_line(nodes, count);
            write_wkts(id, tags, wkt, t_line);
            if (roads)
                write_wkts(id, tags, wkt, t_roads);
@@ -835,6 +839,7 @@
         char *wkt = get_wkt(i);
 
         if (strlen(wkt)) {
+            expire_tiles_from_wkt(wkt, -id);
             /* FIXME: there should be a better way to detect polygons */
             if (!strncmp(wkt, "POLYGON", strlen("POLYGON"))) {
                 double area = get_area(i);
@@ -951,11 +956,14 @@
             if( Options->slim )
                 pgsql_exec(sql_conn, PGRES_COMMAND_OK, "CREATE INDEX %s_pkey 
ON %s USING BTREE (osm_id);\n", tables[i].name, tables[i].name);
         }
+        pgsql_exec(sql_conn, PGRES_COMMAND_OK, "PREPARE get_way (int4) AS 
SELECT AsText(way) FROM %s WHERE osm_id = $1;\n", tables[i].name);
 
         pgsql_exec(sql_conn, PGRES_COPY_IN, "COPY %s FROM STDIN", 
tables[i].name);
         tables[i].copyMode = 1;
     }
 
+    expire_tiles_init(options);
+
     options->mid->start(options);
 
     return 0;
@@ -1049,6 +1057,8 @@
 
     pgsql_out_cleanup();
     free_style();
+
+    expire_tiles_stop();
 }
 
 static int pgsql_add_node(int id, double lat, double lon, struct keyval *tags)
@@ -1163,6 +1173,7 @@
         exit_nicely();
     }
     pgsql_pause_copy(&tables[t_point]);
+    expire_tiles_from_db(tables[t_point].sql_conn, osm_id);
     pgsql_exec(tables[t_point].sql_conn, PGRES_COMMAND_OK, "DELETE FROM %s 
WHERE osm_id = %d", tables[t_point].name, osm_id );
     Options->mid->nodes_delete(osm_id);
     return 0;
@@ -1177,6 +1188,9 @@
     pgsql_pause_copy(&tables[t_roads]);
     pgsql_pause_copy(&tables[t_line]);
     pgsql_pause_copy(&tables[t_poly]);
+    expire_tiles_from_db(tables[t_roads].sql_conn, osm_id);
+    expire_tiles_from_db(tables[t_line].sql_conn, osm_id);
+    expire_tiles_from_db(tables[t_poly].sql_conn, osm_id);
     pgsql_exec(tables[t_roads].sql_conn, PGRES_COMMAND_OK, "DELETE FROM %s 
WHERE osm_id = %d", tables[t_roads].name, osm_id );
     pgsql_exec(tables[t_line].sql_conn, PGRES_COMMAND_OK, "DELETE FROM %s 
WHERE osm_id = %d", tables[t_line].name, osm_id );
     pgsql_exec(tables[t_poly].sql_conn, PGRES_COMMAND_OK, "DELETE FROM %s 
WHERE osm_id = %d", tables[t_poly].name, osm_id );
@@ -1201,6 +1215,9 @@
     pgsql_pause_copy(&tables[t_roads]);
     pgsql_pause_copy(&tables[t_line]);
     pgsql_pause_copy(&tables[t_poly]);
+    expire_tiles_from_db(tables[t_roads].sql_conn, -osm_id);
+    expire_tiles_from_db(tables[t_line].sql_conn, -osm_id);
+    expire_tiles_from_db(tables[t_poly].sql_conn, -osm_id);
     pgsql_exec(tables[t_roads].sql_conn, PGRES_COMMAND_OK, "DELETE FROM %s 
WHERE osm_id = %d", tables[t_roads].name, -osm_id );
     pgsql_exec(tables[t_line].sql_conn, PGRES_COMMAND_OK, "DELETE FROM %s 
WHERE osm_id = %d", tables[t_line].name, -osm_id );
     pgsql_exec(tables[t_poly].sql_conn, PGRES_COMMAND_OK, "DELETE FROM %s 
WHERE osm_id = %d", tables[t_poly].name, -osm_id );
_______________________________________________
dev mailing list
[email protected]
http://lists.openstreetmap.org/listinfo/dev

Reply via email to