GIS/InstallationGuidelines/Linux: osm2pgsql_centroid.patch
File osm2pgsql_centroid.patch, 18.3 KB (added by , 14 years ago) |
---|
-
output.h
29 29 const char *expire_tiles_filename; /* File name to output expired tiles list to */ 30 30 int enable_hstore; /* add an additional hstore column with objects key/value pairs */ 31 31 int enable_multi; /* Output multi-geometries intead of several simple geometries */ 32 int enable_centroid; /* Generate an additional geometry column that contains the center of the geometry */ 32 33 const char** hstore_columns; /* list of columns that should be written into their own hstore column */ 33 34 int n_hstore_columns; /* number of hstore columns */ 34 35 }; -
build_geometry.cpp
21 21 */ 22 22 23 23 #include <iostream> 24 #include <cstdio> 24 25 #include <cstring> 25 26 #include <cstdlib> 26 27 #include <exception> … … 60 61 typedef std::auto_ptr<Geometry> geom_ptr; 61 62 62 63 static std::vector<std::string> wkts; 64 static std::vector<std::string> wkt_centroids; 63 65 static std::vector<double> areas; 64 66 65 67 … … 81 83 std::auto_ptr<LinearRing> shell(gf.createLinearRing(coords.release())); 82 84 geom = geom_ptr(gf.createPolygon(shell.release(), new std::vector<Geometry *>)); 83 85 geom->normalize(); // Fix direction of ring 86 87 // this function seems not to be used anymore so centroid functionality is not implemented here 88 // see get_wkt_split 84 89 } else { 85 90 if (coords->getSize() < 2) 86 91 return NULL; … … 104 109 } 105 110 } 106 111 107 108 size_t get_wkt_split(osmNode *nodes, int count, int polygon, double split_at) { 112 size_t get_wkt_split(osmNode *nodes, int count, int polygon, double split_at, int enable_centroid) { 109 113 GeometryFactory gf; 110 114 std::auto_ptr<CoordinateSequence> coords(gf.getCoordinateSequenceFactory()->create(0, 2)); 111 115 double area; 112 116 WKTWriter wktw; 113 117 size_t wkt_size = 0; 118 char centroid[100]; 114 119 115 120 try 116 121 { … … 130 135 std::string wkt = wktw.write(geom.get()); 131 136 wkts.push_back(wkt); 132 137 areas.push_back(area); 138 139 // centroid of a closed way 140 if(enable_centroid) 141 { 142 Point* p = geom->getInteriorPoint(); 143 snprintf(centroid, sizeof(centroid), "POINT(%.15g %.15g)", p->getX(), p->getY()); 144 wkt_centroids.push_back(centroid); 145 } 146 133 147 wkt_size++; 134 148 } else { 135 149 if (coords->getSize() < 2) … … 147 161 std::string wkt = wktw.write(geom.get()); 148 162 wkts.push_back(wkt); 149 163 areas.push_back(0); 164 165 // centroid of a linear way 166 if(enable_centroid) 167 { 168 // the interior point is always on an edge of the line 169 Point* p = geom->getInteriorPoint(); 170 171 // the centroid is not always part of the line 172 // Point* p = geom->getCentroid(); 173 174 // interpolate a point on the geometry, needs geos >= 3.2 175 // Point* p = geom->interpolate(0.5); 176 177 snprintf(centroid, sizeof(centroid), "POINT(%.15g %.15g)", p->getX(), p->getY()); 178 wkt_centroids.push_back(centroid); 179 } 180 150 181 wkt_size++; 151 182 distance=0; 152 183 segment = std::auto_ptr<CoordinateSequence>(gf.getCoordinateSequenceFactory()->create(0, 2)); … … 182 213 return result; 183 214 } 184 215 216 char * get_wkt_centroid(size_t index) 217 { 218 if( wkt_centroids.size() <= index ) 219 return NULL; 220 221 char *result; 222 result = (char*) std::malloc( wkt_centroids[index].length() + 1); 223 224 // At least give some idea of why we about to seg fault 225 if (!result) std::cerr << std::endl << "Unable to allocate memory: " << (wkt_centroids[index].length() + 1) << std::endl; 226 227 std::strcpy(result, wkt_centroids[index].c_str()); 228 return result; 229 } 230 185 231 double get_area(size_t index) 186 232 { 187 233 return areas[index]; … … 191 237 { 192 238 wkts.clear(); 193 239 areas.clear(); 240 wkt_centroids.clear(); 194 241 } 195 242 196 243 static int coords2nodes(CoordinateSequence * coords, struct osmNode ** nodes) { … … 291 338 return 1; 292 339 } 293 340 294 size_t build_geometry(int osm_id, struct osmNode **xnodes, int *xcount, int make_polygon, int enable_multi, double split_at ) {341 size_t build_geometry(int osm_id, struct osmNode **xnodes, int *xcount, int make_polygon, int enable_multi, double split_at, int enable_centroid) { 295 342 size_t wkt_size = 0; 296 343 std::auto_ptr<std::vector<Geometry*> > lines(new std::vector<Geometry*>); 297 344 GeometryFactory gf; 298 345 geom_ptr geom; 299 346 char centroid[100]; 347 300 348 try 301 349 { 302 350 for (int c=0; xnodes[c]; c++) { … … 359 407 std::string wkt = writer.write(geom.get()); 360 408 wkts.push_back(wkt); 361 409 areas.push_back(0); 410 411 // centroid of a route-relation (linear) 412 if(enable_centroid) 413 { 414 Point* p = geom->getInteriorPoint(); 415 snprintf(centroid, sizeof(centroid), "POINT(%.15g %.15g)", p->getX(), p->getY()); 416 wkt_centroids.push_back(centroid); 417 } 418 362 419 wkt_size++; 363 420 distance=0; 364 421 segment = std::auto_ptr<CoordinateSequence>(gf.getCoordinateSequenceFactory()->create(0, 2)); … … 457 514 std::string text = writer.write(multipoly.get()); 458 515 wkts.push_back(text); 459 516 areas.push_back(multipoly->getArea()); 517 518 // centroid of a multipolygon relation (area) with more 519 // then one outer way in in multi-geometry mode 520 if(enable_centroid) 521 { 522 Point* p = multipoly->getInteriorPoint(); 523 snprintf(centroid, sizeof(centroid), "POINT(%.15g %.15g)", p->getX(), p->getY()); 524 wkt_centroids.push_back(centroid); 525 } 526 460 527 wkt_size++; 461 528 } 462 529 else … … 467 534 std::string text = writer.write(poly); 468 535 wkts.push_back(text); 469 536 areas.push_back(poly->getArea()); 537 538 // centroid of a multipolygon relation (area) 539 if(enable_centroid) 540 { 541 Point* p = poly->getInteriorPoint(); 542 snprintf(centroid, sizeof(centroid), "POINT(%.15g %.15g)", p->getX(), p->getY()); 543 wkt_centroids.push_back(centroid); 544 } 545 470 546 wkt_size++; 471 547 delete(poly); 472 548 } -
osm2pgsql.c
180 180 printf(" \tthat start with the specified string, eg --hstore-column \"name:\" will\n"); 181 181 printf(" \tproduce an extra hstore column that contains all name:xx tags\n"); 182 182 printf(" -G|--multi-geometry\t\tGenerate multi-geometry features in postgresql tables.\n"); 183 printf(" -n|--centroid\t\tGenerate an additional geometry column that contains the center of the geometry.\n"); 183 184 printf(" -h|--help\t\tHelp information.\n"); 184 185 printf(" -v|--verbose\t\tVerbose output.\n"); 185 186 printf("\n"); … … 299 300 int expire_tiles_zoom_min = -1; 300 301 int enable_hstore = 0; 301 302 int enable_multi = 0; 303 int enable_centroid = 0; 302 304 const char *expire_tiles_filename = "dirty_tiles"; 303 305 const char *db = "gis"; 304 306 const char *username=NULL; … … 352 354 {"hstore", 0, 0, 'k'}, 353 355 {"hstore-column", 1, 0, 'z'}, 354 356 {"multi-geometry", 0, 0, 'G'}, 357 {"centroid", 0, 0, 'n'}, 355 358 {"input-reader", 1, 0, 'r'}, 356 359 {"version", 0, 0, 'V'}, 357 360 {0, 0, 0, 0} … … 397 400 hstore_columns[n_hstore_columns-1] = optarg; 398 401 break; 399 402 case 'G': enable_multi=1; break; 403 case 'n': enable_centroid=1; break; 400 404 case 'r': input_reader = optarg; break; 401 405 case 'h': long_usage_bool=1; break; 402 406 case 'V': exit(EXIT_SUCCESS); … … 469 473 options.expire_tiles_zoom_min = expire_tiles_zoom_min; 470 474 options.expire_tiles_filename = expire_tiles_filename; 471 475 options.enable_multi = enable_multi; 476 options.enable_centroid = enable_centroid; 472 477 options.enable_hstore = enable_hstore; 473 478 options.hstore_columns = hstore_columns; 474 479 options.n_hstore_columns = n_hstore_columns; -
build_geometry.h
32 32 int parse_wkt(const char * wkt, struct osmNode *** xnodes, int ** xcount, int * polygon); 33 33 34 34 char *get_wkt_simple(struct osmNode *, int count, int polygon); 35 size_t get_wkt_split(struct osmNode *, int count, int polygon, double split_at );35 size_t get_wkt_split(struct osmNode *, int count, int polygon, double split_at, int enable_centroid); 36 36 37 37 char* get_wkt(size_t index); 38 char * get_wkt_centroid(size_t index); 38 39 double get_area(size_t index); 39 size_t build_geometry(int osm_id, struct osmNode **xnodes, int *xcount, int make_polygon, int enable_multi, double split_at );40 size_t build_geometry(int osm_id, struct osmNode **xnodes, int *xcount, int make_polygon, int enable_multi, double split_at, int enable_centroid); 40 41 void clear_wkts(); 41 42 42 43 #ifdef __cplusplus -
output-pgsql.c
51 51 unsigned int buflen; 52 52 int copyMode; 53 53 char *columns; 54 int hasCentroidColumn; 54 55 } tables [] = { 55 56 { .name = "%s_point", .type = "POINT" }, 56 57 { .name = "%s_line", .type = "LINESTRING"}, … … 265 266 /* Return to copy mode if we dropped out */ 266 267 if( !tables[table].copyMode ) 267 268 { 268 pgsql_exec(sql_conn, PGRES_COPY_IN, "COPY %s (%s,way) FROM STDIN", tables[table].name, tables[table].columns); 269 if( tables[table].hasCentroidColumn == 1 ) 270 pgsql_exec(sql_conn, PGRES_COPY_IN, "COPY %s (%s,way,centroid) FROM STDIN", tables[table].name, tables[table].columns); 271 else 272 pgsql_exec(sql_conn, PGRES_COPY_IN, "COPY %s (%s,way) FROM STDIN", tables[table].name, tables[table].columns); 273 269 274 tables[table].copyMode = 1; 270 275 } 271 276 /* If the combination of old and new data is too big, flush old data */ … … 631 636 632 637 633 638 634 static void write_wkts(int id, struct keyval *tags, const char *wkt, enum table_id table )639 static void write_wkts(int id, struct keyval *tags, const char *wkt, enum table_id table, const char *wkt_centroid) 635 640 { 636 641 637 642 static char *sql; … … 674 679 sprintf(sql, "SRID=%d;", SRID); 675 680 copy_to_table(table, sql); 676 681 copy_to_table(table, wkt); 682 683 if(wkt_centroid && tables[table].hasCentroidColumn == 1) 684 { 685 sprintf(sql, "\tSRID=%d;", SRID); 686 copy_to_table(table, sql); 687 copy_to_table(table, wkt_centroid); 688 } 689 677 690 copy_to_table(table, "\n"); 678 691 } 679 692 … … 800 813 else 801 814 split_at = 100 * 1000; 802 815 803 wkt_size = get_wkt_split(nodes, count, polygon, split_at );816 wkt_size = get_wkt_split(nodes, count, polygon, split_at, Options->enable_centroid); 804 817 805 818 for (i=0;i<wkt_size;i++) 806 819 { 807 820 char *wkt = get_wkt(i); 821 char *wkt_centroid = NULL; 808 822 823 if(Options->enable_centroid) 824 wkt_centroid = get_wkt_centroid(i); 825 809 826 if (wkt && strlen(wkt)) { 810 827 /* FIXME: there should be a better way to detect polygons */ 811 828 if (!strncmp(wkt, "POLYGON", strlen("POLYGON")) || !strncmp(wkt, "MULTIPOLYGON", strlen("MULTIPOLYGON"))) { … … 816 833 snprintf(tmp, sizeof(tmp), "%f", area); 817 834 addItem(tags, "way_area", tmp, 0); 818 835 } 819 write_wkts(id, tags, wkt, t_poly );836 write_wkts(id, tags, wkt, t_poly, wkt_centroid); 820 837 } else { 821 838 expire_tiles_from_nodes_line(nodes, count); 822 write_wkts(id, tags, wkt, t_line );839 write_wkts(id, tags, wkt, t_line, wkt_centroid); 823 840 if (roads) 824 write_wkts(id, tags, wkt, t_roads );841 write_wkts(id, tags, wkt, t_roads, wkt_centroid); 825 842 } 826 843 } 827 844 free(wkt); 845 if(wkt_centroid) free(wkt_centroid); 828 846 } 829 847 clear_wkts(); 830 848 … … 1026 1044 else 1027 1045 split_at = 100 * 1000; 1028 1046 1029 wkt_size = build_geometry(id, xnodes, xcount, make_polygon, Options->enable_multi, split_at );1047 wkt_size = build_geometry(id, xnodes, xcount, make_polygon, Options->enable_multi, split_at, Options->enable_centroid); 1030 1048 1031 1049 if (!wkt_size) { 1032 1050 resetList(&tags); … … 1037 1055 for (i=0;i<wkt_size;i++) 1038 1056 { 1039 1057 char *wkt = get_wkt(i); 1058 char *wkt_centroid = NULL; 1040 1059 1060 if(Options->enable_centroid) 1061 wkt_centroid = get_wkt_centroid(i); 1062 1041 1063 if (wkt && strlen(wkt)) { 1042 1064 expire_tiles_from_wkt(wkt, -id); 1043 1065 /* FIXME: there should be a better way to detect polygons */ … … 1048 1070 snprintf(tmp, sizeof(tmp), "%f", area); 1049 1071 addItem(&tags, "way_area", tmp, 0); 1050 1072 } 1051 write_wkts(-id, &tags, wkt, t_poly );1073 write_wkts(-id, &tags, wkt, t_poly, wkt_centroid); 1052 1074 } else { 1053 write_wkts(-id, &tags, wkt, t_line );1075 write_wkts(-id, &tags, wkt, t_line, wkt_centroid); 1054 1076 if (roads) 1055 write_wkts(-id, &tags, wkt, t_roads );1077 write_wkts(-id, &tags, wkt, t_roads, wkt_centroid); 1056 1078 } 1057 1079 } 1058 1080 free(wkt); … … 1088 1110 // If we are making a boundary then also try adding any relations which form complete rings 1089 1111 // The linear variants will have already been processed above 1090 1112 if (make_boundary) { 1091 wkt_size = build_geometry(id, xnodes, xcount, 1, Options->enable_multi, split_at );1113 wkt_size = build_geometry(id, xnodes, xcount, 1, Options->enable_multi, split_at, Options->enable_centroid); 1092 1114 for (i=0;i<wkt_size;i++) 1093 1115 { 1094 1116 char *wkt = get_wkt(i); 1117 char *wkt_centroid = NULL; 1095 1118 1119 if(Options->enable_centroid) 1120 wkt_centroid = get_wkt_centroid(i); 1121 1096 1122 if (strlen(wkt)) { 1097 1123 expire_tiles_from_wkt(wkt, -id); 1098 1124 /* FIXME: there should be a better way to detect polygons */ … … 1103 1129 snprintf(tmp, sizeof(tmp), "%f", area); 1104 1130 addItem(&tags, "way_area", tmp, 0); 1105 1131 } 1106 write_wkts(-id, &tags, wkt, t_poly );1132 write_wkts(-id, &tags, wkt, t_poly, wkt_centroid); 1107 1133 } 1108 1134 } 1109 1135 free(wkt); … … 1210 1236 pgsql_exec(sql_conn, PGRES_COMMAND_OK, "%s", sql); 1211 1237 pgsql_exec(sql_conn, PGRES_TUPLES_OK, "SELECT AddGeometryColumn('%s', 'way', %d, '%s', 2 );\n", 1212 1238 tables[i].name, SRID, tables[i].type ); 1239 1240 // if a centroid-column is requested, we need another geometry column 1241 if(Options->enable_centroid && strcmp(tables[i].type, "POINT") != 0) 1242 { 1243 pgsql_exec(sql_conn, PGRES_TUPLES_OK, "SELECT AddGeometryColumn('%s', 'centroid', %d, 'POINT', 2 );\n", 1244 tables[i].name, SRID ); 1245 1246 pgsql_exec(sql_conn, PGRES_COMMAND_OK, "ALTER TABLE %s ALTER COLUMN way SET NOT NULL;\n", tables[i].name); 1247 1248 tables[i].hasCentroidColumn = 1; 1249 } 1250 1213 1251 pgsql_exec(sql_conn, PGRES_COMMAND_OK, "ALTER TABLE %s ALTER COLUMN way SET NOT NULL;\n", tables[i].name); 1214 1252 /* slim mode needs this to be able to apply diffs */ 1215 1253 if( Options->slim ) … … 1277 1315 if (Options->enable_hstore) strcat(sql,",tags"); 1278 1316 1279 1317 tables[i].columns = strdup(sql); 1280 pgsql_exec(sql_conn, PGRES_COPY_IN, "COPY %s (%s,way) FROM STDIN", tables[i].name, tables[i].columns); 1318 if( tables[i].hasCentroidColumn == 1 ) 1319 pgsql_exec(sql_conn, PGRES_COPY_IN, "COPY %s (%s,way,centroid) FROM STDIN", tables[i].name, tables[i].columns); 1320 else 1321 pgsql_exec(sql_conn, PGRES_COPY_IN, "COPY %s (%s,way) FROM STDIN", tables[i].name, tables[i].columns); 1281 1322 1282 1323 tables[i].copyMode = 1; 1283 1324 } -
output-gazetteer.c
878 878 xnodes[count] = NULL; 879 879 xcount[count] = 0; 880 880 881 wkt_size = build_geometry(id, xnodes, xcount, 1, 1, 1000000 );881 wkt_size = build_geometry(id, xnodes, xcount, 1, 1, 1000000, 0); 882 882 for (i=0;i<wkt_size;i++) 883 883 { 884 884 char *wkt = get_wkt(i); -
parse-xml2.c
347 347 EndElement(name, osmdata); 348 348 break; 349 349 case XML_READER_TYPE_SIGNIFICANT_WHITESPACE: 350 case XML_READER_TYPE_COMMENT: 350 351 /* Ignore */ 351 352 break; 352 353 default: 353 fprintf(stderr, "Unknown node type %d\n", xmlTextReaderNodeType(reader));354 fprintf(stderr, "Unknown xml-node type %d\n", xmlTextReaderNodeType(reader)); 354 355 break; 355 356 } 356 357