Index: output.h
===================================================================
--- output.h	(revision 24469)
+++ output.h	(working copy)
@@ -29,6 +29,7 @@
   const char *expire_tiles_filename;	/* File name to output expired tiles list to */
   int enable_hstore; /* add an additional hstore column with objects key/value pairs */
   int enable_multi; /* Output multi-geometries intead of several simple geometries */
+  int enable_centroid; /* Generate an additional geometry column that contains the center of the geometry */
   const char** hstore_columns; /* list of columns that should be written into their own hstore column */
   int n_hstore_columns; /* number of hstore columns */
 };
Index: build_geometry.cpp
===================================================================
--- build_geometry.cpp	(revision 24469)
+++ build_geometry.cpp	(working copy)
@@ -21,6 +21,7 @@
 */
 
 #include <iostream>
+#include <cstdio>
 #include <cstring>
 #include <cstdlib>
 #include <exception>
@@ -60,6 +61,7 @@
 typedef std::auto_ptr<Geometry> geom_ptr;
 
 static std::vector<std::string> wkts;
+static std::vector<std::string> wkt_centroids;
 static std::vector<double> areas;
 
 
@@ -81,6 +83,9 @@
             std::auto_ptr<LinearRing> shell(gf.createLinearRing(coords.release()));
             geom = geom_ptr(gf.createPolygon(shell.release(), new std::vector<Geometry *>));
             geom->normalize(); // Fix direction of ring
+            
+            // this function seems not to be used anymore so centroid functionality is not implemented here
+            //   see get_wkt_split
         } else {
             if (coords->getSize() < 2)
                 return NULL;
@@ -104,13 +109,13 @@
     }
 }
 
-
-size_t get_wkt_split(osmNode *nodes, int count, int polygon, double split_at) {
+size_t get_wkt_split(osmNode *nodes, int count, int polygon, double split_at, int enable_centroid) {
     GeometryFactory gf;
     std::auto_ptr<CoordinateSequence> coords(gf.getCoordinateSequenceFactory()->create(0, 2));
     double area;
     WKTWriter wktw;
     size_t wkt_size = 0;
+    char centroid[100];
 
     try
     {
@@ -130,6 +135,15 @@
             std::string wkt = wktw.write(geom.get());
             wkts.push_back(wkt);
             areas.push_back(area);
+            
+            // centroid of a closed way
+            if(enable_centroid)
+            {
+                Point* p = geom->getInteriorPoint();
+                snprintf(centroid, sizeof(centroid), "POINT(%.15g %.15g)", p->getX(), p->getY());
+                wkt_centroids.push_back(centroid);
+            }
+            
             wkt_size++;
         } else {
             if (coords->getSize() < 2)
@@ -147,6 +161,23 @@
                     std::string wkt = wktw.write(geom.get());
                     wkts.push_back(wkt);
                     areas.push_back(0);
+                    
+                    // centroid of a linear way
+                    if(enable_centroid)
+                    {
+                        // the interior point is always on an edge of the line
+                        Point* p = geom->getInteriorPoint();
+                        
+                        // the centroid is not always part of the line
+                        // Point* p = geom->getCentroid();
+                        
+                        // interpolate a point on the geometry, needs geos >= 3.2
+                        // Point* p = geom->interpolate(0.5);
+                        
+                        snprintf(centroid, sizeof(centroid), "POINT(%.15g %.15g)", p->getX(), p->getY());
+                        wkt_centroids.push_back(centroid);
+                    }
+                    
                     wkt_size++;
                     distance=0;
                     segment = std::auto_ptr<CoordinateSequence>(gf.getCoordinateSequenceFactory()->create(0, 2));
@@ -182,6 +213,21 @@
 	return result;
 }
 
+char * get_wkt_centroid(size_t index)
+{
+    if( wkt_centroids.size() <= index )
+        return NULL;
+
+    char *result;
+    result = (char*) std::malloc( wkt_centroids[index].length() + 1);
+    
+    // At least give some idea of why we about to seg fault
+    if (!result) std::cerr << std::endl << "Unable to allocate memory: " << (wkt_centroids[index].length() + 1) << std::endl;
+    
+    std::strcpy(result, wkt_centroids[index].c_str());
+    return result;
+}
+
 double get_area(size_t index)
 {
     return areas[index];
@@ -191,6 +237,7 @@
 {
    wkts.clear();
    areas.clear();
+   wkt_centroids.clear();
 }
 
 static int coords2nodes(CoordinateSequence * coords, struct osmNode ** nodes) {
@@ -291,12 +338,13 @@
     return 1;
 }
 
-size_t build_geometry(int osm_id, struct osmNode **xnodes, int *xcount, int make_polygon, int enable_multi, double split_at) {
+size_t build_geometry(int osm_id, struct osmNode **xnodes, int *xcount, int make_polygon, int enable_multi, double split_at, int enable_centroid) {
     size_t wkt_size = 0;
     std::auto_ptr<std::vector<Geometry*> > lines(new std::vector<Geometry*>);
     GeometryFactory gf;
     geom_ptr geom;
-
+    char centroid[100];
+    
     try
     {
         for (int c=0; xnodes[c]; c++) {
@@ -359,6 +407,15 @@
                         std::string wkt = writer.write(geom.get());
                         wkts.push_back(wkt);
                         areas.push_back(0);
+                        
+                        // centroid of a route-relation (linear)
+                        if(enable_centroid)
+                        {
+                            Point* p = geom->getInteriorPoint();
+                            snprintf(centroid, sizeof(centroid), "POINT(%.15g %.15g)", p->getX(), p->getY());
+                            wkt_centroids.push_back(centroid);
+                        }
+                        
                         wkt_size++;
                         distance=0;
                         segment = std::auto_ptr<CoordinateSequence>(gf.getCoordinateSequenceFactory()->create(0, 2));
@@ -457,6 +514,16 @@
                 std::string text = writer.write(multipoly.get());
                 wkts.push_back(text);
                 areas.push_back(multipoly->getArea());
+                
+                // centroid of a multipolygon relation (area) with more 
+                // then one outer way in in multi-geometry mode
+                if(enable_centroid)
+                {
+                    Point* p = multipoly->getInteriorPoint();
+                    snprintf(centroid, sizeof(centroid), "POINT(%.15g %.15g)", p->getX(), p->getY());
+                    wkt_centroids.push_back(centroid);
+                }
+                
                 wkt_size++;
             }
             else
@@ -467,6 +534,15 @@
                     std::string text = writer.write(poly);
                     wkts.push_back(text);
                     areas.push_back(poly->getArea());
+                    
+                    // centroid of a multipolygon relation (area)
+                    if(enable_centroid)
+                    {
+                        Point* p = poly->getInteriorPoint();
+                        snprintf(centroid, sizeof(centroid), "POINT(%.15g %.15g)", p->getX(), p->getY());
+                        wkt_centroids.push_back(centroid);
+                    }
+                    
                     wkt_size++;
                     delete(poly);
                 }
Index: osm2pgsql.c
===================================================================
--- osm2pgsql.c	(revision 24469)
+++ osm2pgsql.c	(working copy)
@@ -180,6 +180,7 @@
     printf("                     \tthat start with the specified string, eg --hstore-column \"name:\" will\n");
     printf("                     \tproduce an extra hstore column that contains all name:xx tags\n");
     printf("   -G|--multi-geometry\t\tGenerate multi-geometry features in postgresql tables.\n");
+    printf("   -n|--centroid\t\tGenerate an additional geometry column that contains the center of the geometry.\n");
     printf("   -h|--help\t\tHelp information.\n");
     printf("   -v|--verbose\t\tVerbose output.\n");
     printf("\n");
@@ -299,6 +300,7 @@
     int expire_tiles_zoom_min = -1;
     int enable_hstore = 0;
     int enable_multi = 0;
+    int enable_centroid = 0;
     const char *expire_tiles_filename = "dirty_tiles";
     const char *db = "gis";
     const char *username=NULL;
@@ -352,6 +354,7 @@
             {"hstore", 0, 0, 'k'},
             {"hstore-column", 1, 0, 'z'},
             {"multi-geometry", 0, 0, 'G'},
+            {"centroid", 0, 0, 'n'},
 	    {"input-reader", 1, 0, 'r'},
             {"version", 0, 0, 'V'},
             {0, 0, 0, 0}
@@ -397,6 +400,7 @@
                 hstore_columns[n_hstore_columns-1] = optarg;
                 break;
 	    case 'G': enable_multi=1; break;
+        case 'n': enable_centroid=1; break;
 	    case 'r': input_reader = optarg; break;
             case 'h': long_usage_bool=1; break;
   	    case 'V': exit(EXIT_SUCCESS);
@@ -469,6 +473,7 @@
     options.expire_tiles_zoom_min = expire_tiles_zoom_min;
     options.expire_tiles_filename = expire_tiles_filename;
     options.enable_multi = enable_multi;
+    options.enable_centroid = enable_centroid;
     options.enable_hstore = enable_hstore;
     options.hstore_columns = hstore_columns;
     options.n_hstore_columns = n_hstore_columns;
Index: build_geometry.h
===================================================================
--- build_geometry.h	(revision 24469)
+++ build_geometry.h	(working copy)
@@ -32,11 +32,12 @@
 int parse_wkt(const char * wkt, struct osmNode *** xnodes, int ** xcount, int * polygon);
 
 char *get_wkt_simple(struct osmNode *, int count, int polygon);
-size_t get_wkt_split(struct osmNode *, int count, int polygon, double split_at);
+size_t get_wkt_split(struct osmNode *, int count, int polygon, double split_at, int enable_centroid);
 
 char* get_wkt(size_t index);
+char * get_wkt_centroid(size_t index);
 double get_area(size_t index);
-size_t build_geometry(int osm_id, struct osmNode **xnodes, int *xcount, int make_polygon, int enable_multi, double split_at);
+size_t build_geometry(int osm_id, struct osmNode **xnodes, int *xcount, int make_polygon, int enable_multi, double split_at, int enable_centroid);
 void clear_wkts();
 
 #ifdef __cplusplus
Index: output-pgsql.c
===================================================================
--- output-pgsql.c	(revision 24469)
+++ output-pgsql.c	(working copy)
@@ -51,6 +51,7 @@
     unsigned int buflen;
     int copyMode;
     char *columns;
+    int hasCentroidColumn;
 } tables [] = {
     { .name = "%s_point",   .type = "POINT"     },
     { .name = "%s_line",    .type = "LINESTRING"},
@@ -265,7 +266,11 @@
     /* Return to copy mode if we dropped out */
     if( !tables[table].copyMode )
     {
-        pgsql_exec(sql_conn, PGRES_COPY_IN, "COPY %s (%s,way) FROM STDIN", tables[table].name, tables[table].columns);
+        if( tables[table].hasCentroidColumn == 1 )
+            pgsql_exec(sql_conn, PGRES_COPY_IN, "COPY %s (%s,way,centroid) FROM STDIN", tables[table].name, tables[table].columns);
+        else
+            pgsql_exec(sql_conn, PGRES_COPY_IN, "COPY %s (%s,way) FROM STDIN", tables[table].name, tables[table].columns);
+        
         tables[table].copyMode = 1;
     }
     /* If the combination of old and new data is too big, flush old data */
@@ -631,7 +636,7 @@
 
 
 
-static void write_wkts(int id, struct keyval *tags, const char *wkt, enum table_id table)
+static void write_wkts(int id, struct keyval *tags, const char *wkt, enum table_id table, const char *wkt_centroid)
 {
   
     static char *sql;
@@ -674,6 +679,14 @@
     sprintf(sql, "SRID=%d;", SRID);
     copy_to_table(table, sql);
     copy_to_table(table, wkt);
+    
+    if(wkt_centroid && tables[table].hasCentroidColumn == 1)
+    {
+        sprintf(sql, "\tSRID=%d;", SRID);
+        copy_to_table(table, sql);
+        copy_to_table(table, wkt_centroid);
+    }
+    
     copy_to_table(table, "\n");
 }
 
@@ -800,12 +813,16 @@
     else
         split_at = 100 * 1000;
 
-    wkt_size = get_wkt_split(nodes, count, polygon, split_at);
+    wkt_size = get_wkt_split(nodes, count, polygon, split_at, Options->enable_centroid);
 
     for (i=0;i<wkt_size;i++)
     {
         char *wkt = get_wkt(i);
+        char *wkt_centroid = NULL;
 
+        if(Options->enable_centroid)
+            wkt_centroid = get_wkt_centroid(i);
+
         if (wkt && strlen(wkt)) {
             /* FIXME: there should be a better way to detect polygons */
             if (!strncmp(wkt, "POLYGON", strlen("POLYGON")) || !strncmp(wkt, "MULTIPOLYGON", strlen("MULTIPOLYGON"))) {
@@ -816,15 +833,16 @@
                     snprintf(tmp, sizeof(tmp), "%f", area);
                     addItem(tags, "way_area", tmp, 0);
                 }
-                write_wkts(id, tags, wkt, t_poly);
+                write_wkts(id, tags, wkt, t_poly, wkt_centroid);
             } else {
                 expire_tiles_from_nodes_line(nodes, count);
-                write_wkts(id, tags, wkt, t_line);
+                write_wkts(id, tags, wkt, t_line, wkt_centroid);
                 if (roads)
-                    write_wkts(id, tags, wkt, t_roads);
+                    write_wkts(id, tags, wkt, t_roads, wkt_centroid);
             }
         }
         free(wkt);
+        if(wkt_centroid) free(wkt_centroid);
     }
     clear_wkts();
 	
@@ -1026,7 +1044,7 @@
     else
         split_at = 100 * 1000;
 
-    wkt_size = build_geometry(id, xnodes, xcount, make_polygon, Options->enable_multi, split_at);
+    wkt_size = build_geometry(id, xnodes, xcount, make_polygon, Options->enable_multi, split_at, Options->enable_centroid);
 
     if (!wkt_size) {
         resetList(&tags);
@@ -1037,7 +1055,11 @@
     for (i=0;i<wkt_size;i++)
     {
         char *wkt = get_wkt(i);
+        char *wkt_centroid = NULL;
 
+        if(Options->enable_centroid)
+            wkt_centroid = get_wkt_centroid(i);
+
         if (wkt && strlen(wkt)) {
             expire_tiles_from_wkt(wkt, -id);
             /* FIXME: there should be a better way to detect polygons */
@@ -1048,11 +1070,11 @@
                     snprintf(tmp, sizeof(tmp), "%f", area);
                     addItem(&tags, "way_area", tmp, 0);
                 }
-                write_wkts(-id, &tags, wkt, t_poly);
+                write_wkts(-id, &tags, wkt, t_poly, wkt_centroid);
             } else {
-                write_wkts(-id, &tags, wkt, t_line);
+                write_wkts(-id, &tags, wkt, t_line, wkt_centroid);
                 if (roads)
-                    write_wkts(-id, &tags, wkt, t_roads);
+                    write_wkts(-id, &tags, wkt, t_roads, wkt_centroid);
             }
         }
         free(wkt);
@@ -1088,11 +1110,15 @@
     // If we are making a boundary then also try adding any relations which form complete rings
     // The linear variants will have already been processed above
     if (make_boundary) {
-        wkt_size = build_geometry(id, xnodes, xcount, 1, Options->enable_multi, split_at);
+        wkt_size = build_geometry(id, xnodes, xcount, 1, Options->enable_multi, split_at, Options->enable_centroid);
         for (i=0;i<wkt_size;i++)
         {
             char *wkt = get_wkt(i);
+            char *wkt_centroid = NULL;
 
+            if(Options->enable_centroid)
+                wkt_centroid = get_wkt_centroid(i);
+
             if (strlen(wkt)) {
                 expire_tiles_from_wkt(wkt, -id);
                 /* FIXME: there should be a better way to detect polygons */
@@ -1103,7 +1129,7 @@
                         snprintf(tmp, sizeof(tmp), "%f", area);
                         addItem(&tags, "way_area", tmp, 0);
                     }
-                    write_wkts(-id, &tags, wkt, t_poly);
+                    write_wkts(-id, &tags, wkt, t_poly, wkt_centroid);
                 }
             }
             free(wkt);
@@ -1210,6 +1236,18 @@
             pgsql_exec(sql_conn, PGRES_COMMAND_OK, "%s", sql);
             pgsql_exec(sql_conn, PGRES_TUPLES_OK, "SELECT AddGeometryColumn('%s', 'way', %d, '%s', 2 );\n",
                         tables[i].name, SRID, tables[i].type );
+            
+            // if a centroid-column is requested, we need another geometry column
+            if(Options->enable_centroid && strcmp(tables[i].type, "POINT") != 0)
+            {
+                pgsql_exec(sql_conn, PGRES_TUPLES_OK, "SELECT AddGeometryColumn('%s', 'centroid', %d, 'POINT', 2 );\n",
+                            tables[i].name, SRID );
+                
+                pgsql_exec(sql_conn, PGRES_COMMAND_OK, "ALTER TABLE %s ALTER COLUMN way SET NOT NULL;\n", tables[i].name);
+                
+                tables[i].hasCentroidColumn = 1;
+            }
+            
             pgsql_exec(sql_conn, PGRES_COMMAND_OK, "ALTER TABLE %s ALTER COLUMN way SET NOT NULL;\n", tables[i].name);
             /* slim mode needs this to be able to apply diffs */
             if( Options->slim )
@@ -1277,7 +1315,10 @@
 	if (Options->enable_hstore) strcat(sql,",tags");
 
 	tables[i].columns = strdup(sql);
-        pgsql_exec(sql_conn, PGRES_COPY_IN, "COPY %s (%s,way) FROM STDIN", tables[i].name, tables[i].columns);
+        if( tables[i].hasCentroidColumn == 1 )
+            pgsql_exec(sql_conn, PGRES_COPY_IN, "COPY %s (%s,way,centroid) FROM STDIN", tables[i].name, tables[i].columns);
+        else
+            pgsql_exec(sql_conn, PGRES_COPY_IN, "COPY %s (%s,way) FROM STDIN", tables[i].name, tables[i].columns);
 
         tables[i].copyMode = 1;
     }
Index: output-gazetteer.c
===================================================================
--- output-gazetteer.c	(revision 24469)
+++ output-gazetteer.c	(working copy)
@@ -878,7 +878,7 @@
       xnodes[count] = NULL;
       xcount[count] = 0;
 
-      wkt_size = build_geometry(id, xnodes, xcount, 1, 1, 1000000);
+      wkt_size = build_geometry(id, xnodes, xcount, 1, 1, 1000000, 0);
       for (i=0;i<wkt_size;i++)
       {
          char *wkt = get_wkt(i);
Index: parse-xml2.c
===================================================================
--- parse-xml2.c	(revision 24469)
+++ parse-xml2.c	(working copy)
@@ -347,10 +347,11 @@
 	    EndElement(name, osmdata);
             break;
         case XML_READER_TYPE_SIGNIFICANT_WHITESPACE:
+        case XML_READER_TYPE_COMMENT:
             /* Ignore */
             break;
         default:
-            fprintf(stderr, "Unknown node type %d\n", xmlTextReaderNodeType(reader));
+            fprintf(stderr, "Unknown xml-node type %d\n", xmlTextReaderNodeType(reader));
             break;
     }
 
