mirror of
https://github.com/osm2pgsql-dev/osm2pgsql.git
synced 2025-08-19 16:28:16 +00:00
osm2pgsql 0.07: Make UTF8sanitize optional since it is generally no longer required. Add option to output in latlong format
This commit is contained in:
2
Makefile
2
Makefile
@ -1,5 +1,5 @@
|
||||
PACKAGE:=osm2pgsql
|
||||
VERSION:=0.06
|
||||
VERSION:=0.07
|
||||
SVN:=$(shell date +%Y%m%d)
|
||||
|
||||
CFLAGS += -O2 -Wall -Wextra
|
||||
|
@ -85,6 +85,7 @@ struct Interior
|
||||
static std::vector<Segment> segs;
|
||||
static std::vector<std::string> wkts;
|
||||
static std::vector<Interior> interiors;
|
||||
static std::vector<double> areas;
|
||||
|
||||
|
||||
int is_simple(const char* wkt)
|
||||
@ -115,10 +116,17 @@ void get_interior(size_t index, double *y, double *x)
|
||||
*x = interiors[index].x;
|
||||
*y = interiors[index].y;
|
||||
}
|
||||
|
||||
double get_area(size_t index)
|
||||
{
|
||||
return areas[index];
|
||||
}
|
||||
|
||||
void clear_wkts()
|
||||
{
|
||||
wkts.clear();
|
||||
interiors.clear();
|
||||
areas.clear();
|
||||
}
|
||||
|
||||
size_t build_geometry(int polygon, int osm_id)
|
||||
@ -175,11 +183,11 @@ size_t build_geometry(int polygon, int osm_id)
|
||||
{
|
||||
std::auto_ptr<LinearRing> ring(factory.createLinearRing(pline->getCoordinates()));
|
||||
std::auto_ptr<Polygon> poly(factory.createPolygon(factory.createLinearRing(pline->getCoordinates()),0));
|
||||
|
||||
if (poly->getArea() > ext_area) {
|
||||
double poly_area = poly->getArea();
|
||||
if (poly_area > ext_area) {
|
||||
if (ext_area > 0.0)
|
||||
interior->push_back(exterior.release());
|
||||
ext_area = poly->getArea();
|
||||
ext_area = poly_area;
|
||||
exterior = ring;
|
||||
//std::cerr << "Found bigger ring, area(" << ext_area << ") " << writer.write(poly.get()) << std::endl;
|
||||
} else {
|
||||
@ -191,16 +199,18 @@ size_t build_geometry(int polygon, int osm_id)
|
||||
std::string text = writer.write(pline.get());
|
||||
wkts.push_back(text);
|
||||
interiors.push_back(Interior(0,0));
|
||||
++wkt_size;
|
||||
areas.push_back(0.0);
|
||||
wkt_size++;
|
||||
}
|
||||
}
|
||||
|
||||
if (ext_area > 0.0) {
|
||||
std::auto_ptr<Polygon> poly(factory.createPolygon(exterior.release(), interior.release()));
|
||||
std::string text = writer.write(poly.get());
|
||||
//std::cerr << "Result: area(" << poly->getArea() << ") " << writer.write(poly.get()) << std::endl;
|
||||
wkts.push_back(text);
|
||||
interiors.push_back(Interior(poly.get()));
|
||||
//std::cerr << "Result: area(" << poly->getArea() << ") " << writer.write(poly.get()) << std::endl;
|
||||
areas.push_back(ext_area);
|
||||
wkt_size++;
|
||||
}
|
||||
} else {
|
||||
@ -210,6 +220,7 @@ size_t build_geometry(int polygon, int osm_id)
|
||||
std::string text = writer.write(pline.get());
|
||||
wkts.push_back(text);
|
||||
interiors.push_back(Interior(0,0));
|
||||
areas.push_back(0.0);
|
||||
++wkt_size;
|
||||
}
|
||||
}
|
||||
|
@ -31,6 +31,7 @@ int is_simple(const char* wkt);
|
||||
void add_segment(double x0,double y0,double x1, double y1);
|
||||
char* get_wkt(size_t index);
|
||||
void get_interior(size_t index, double *y, double *x);
|
||||
double get_area(size_t index);
|
||||
size_t build_geometry(int polygon, int osm_id);
|
||||
void clear_wkts();
|
||||
|
||||
|
12
input.c
12
input.c
@ -151,3 +151,15 @@ int inputClose(void *context)
|
||||
free(ctx);
|
||||
return 0;
|
||||
}
|
||||
|
||||
xmlTextReaderPtr inputUTF8(const char *name)
|
||||
{
|
||||
void *ctx = inputOpen(name);
|
||||
|
||||
if (!ctx) {
|
||||
fprintf(stderr, "Input reader create failed for: %s\n", name);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return xmlReaderForIO(readFile, inputClose, (void *)ctx, NULL, NULL, 0);
|
||||
}
|
||||
|
3
input.h
3
input.h
@ -1,10 +1,11 @@
|
||||
#ifndef INPUT_H
|
||||
#define INPUT_H
|
||||
|
||||
int inputRead(void *context, char * buffer, int len);
|
||||
int readFile(void *context, char * buffer, int len);
|
||||
int inputClose(void *context);
|
||||
void *inputOpen(const char *name);
|
||||
char inputGetChar(void *context);
|
||||
int inputEof(void *context);
|
||||
xmlTextReaderPtr inputUTF8(const char *name);
|
||||
|
||||
#endif
|
||||
|
@ -206,7 +206,7 @@ int addItem(struct keyval *head, const char *name, const char *value, int noDupe
|
||||
item->key = strdup(name);
|
||||
item->value = strdup(value);
|
||||
#endif
|
||||
|
||||
|
||||
item->next = head->next;
|
||||
item->prev = head;
|
||||
head->next->prev = item;
|
||||
|
@ -613,7 +613,8 @@ static void pgsql_end(void)
|
||||
}
|
||||
}
|
||||
|
||||
static int pgsql_start(const char *db)
|
||||
#define __unused __attribute__ ((unused))
|
||||
static int pgsql_start(const char *db, int latlong __unused)
|
||||
{
|
||||
char sql[2048];
|
||||
PGresult *res;
|
||||
|
15
middle-ram.c
15
middle-ram.c
@ -23,10 +23,10 @@
|
||||
/* Store +-20,000km Mercator co-ordinates as fixed point 32bit number with maximum precision */
|
||||
/* Scale is chosen such that 40,000 * SCALE < 2^32 */
|
||||
#define FIXED_POINT
|
||||
//#define SCALE 10000000
|
||||
#define SCALE 100
|
||||
#define DOUBLE_TO_FIX(x) ((x) * SCALE)
|
||||
#define FIX_TO_DOUBLE(x) (((double)x) / SCALE)
|
||||
|
||||
static int scale = 100;
|
||||
#define DOUBLE_TO_FIX(x) ((x) * scale)
|
||||
#define FIX_TO_DOUBLE(x) (((double)x) / scale)
|
||||
|
||||
struct ramNode {
|
||||
#ifdef FIXED_POINT
|
||||
@ -338,8 +338,13 @@ static void ram_end(void)
|
||||
}
|
||||
|
||||
#define __unused __attribute__ ((unused))
|
||||
static int ram_start(const char * db __unused)
|
||||
static int ram_start(const char * db __unused, int latlong)
|
||||
{
|
||||
// latlong has a range of +-180, mercator +-20000
|
||||
// The fixed poing scaling needs adjusting accordingly to
|
||||
// be stored accurately in an int
|
||||
scale = latlong ? 10000000 : 100;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
2
middle.h
2
middle.h
@ -10,7 +10,7 @@
|
||||
#include "keyvals.h"
|
||||
|
||||
struct middle_t {
|
||||
int (*start)(const char *db);
|
||||
int (*start)(const char *db, int latlong);
|
||||
void (*stop)(void);
|
||||
void (*cleanup)(void);
|
||||
void (*analyze)(void);
|
||||
|
57
osm2pgsql.c
57
osm2pgsql.c
@ -43,6 +43,7 @@
|
||||
#include "sanitizer.h"
|
||||
#include "reprojection.h"
|
||||
#include "text-tree.h"
|
||||
#include "input.h"
|
||||
|
||||
static int count_node, max_node;
|
||||
static int count_segment, max_segment;
|
||||
@ -62,6 +63,7 @@ static struct keyval tags, segs;
|
||||
static int osm_id;
|
||||
|
||||
int verbose;
|
||||
int latlong;
|
||||
|
||||
static void printStatus(void)
|
||||
{
|
||||
@ -165,7 +167,8 @@ void StartElement(xmlTextReaderPtr reader, const xmlChar *name)
|
||||
void EndElement(const xmlChar *name)
|
||||
{
|
||||
if (xmlStrEqual(name, BAD_CAST "node")) {
|
||||
reproject(&node_lat, &node_lon);
|
||||
if (!latlong)
|
||||
reproject(&node_lat, &node_lon);
|
||||
mid->nodes_set(osm_id, node_lat, node_lon, &tags);
|
||||
resetList(&tags);
|
||||
} else if (xmlStrEqual(name, BAD_CAST "segment")) {
|
||||
@ -214,12 +217,14 @@ static void processNode(xmlTextReaderPtr reader) {
|
||||
xmlFree(name);
|
||||
}
|
||||
|
||||
static int streamFile(char *filename) {
|
||||
static int streamFile(char *filename, int sanitize) {
|
||||
xmlTextReaderPtr reader;
|
||||
int ret = 0;
|
||||
|
||||
// reader = xmlNewTextReaderFilename(filename);
|
||||
reader = sanitizerOpen(filename);
|
||||
if (sanitize)
|
||||
reader = sanitizerOpen(filename);
|
||||
else
|
||||
reader = inputUTF8(filename);
|
||||
|
||||
if (reader != NULL) {
|
||||
ret = xmlTextReaderRead(reader);
|
||||
@ -260,16 +265,19 @@ static void usage(const char *arg0)
|
||||
fprintf(stderr, "\nThis will import the data from the OSM file(s) into a PostgreSQL database\n");
|
||||
fprintf(stderr, "suitable for use by the Mapnik renderer\n");
|
||||
fprintf(stderr, "\nOptions:\n");
|
||||
fprintf(stderr, " -a --append\tAdd the OSM file into the database without removing\n");
|
||||
fprintf(stderr, " \texisting data.\n");
|
||||
fprintf(stderr, " -c --create\tRemove existing data from the database. This is the \n");
|
||||
fprintf(stderr, " \tdefault if --append is not specified.\n");
|
||||
fprintf(stderr, " -d --database\tThe name of the PostgreSQL database to connect\n");
|
||||
fprintf(stderr, " \tto (default: gis).\n");
|
||||
fprintf(stderr, " -s --slim\t\tStore temporary data in the database. This greatly\n");
|
||||
fprintf(stderr, " \t\treduces the RAM usage but is much slower.\n");
|
||||
fprintf(stderr, " -h --help\t\tHelp information.\n");
|
||||
fprintf(stderr, " -v --verbose\tVerbose output.\n");
|
||||
fprintf(stderr, " -a|--append\t\tAdd the OSM file into the database without removing\n");
|
||||
fprintf(stderr, " \t\texisting data.\n");
|
||||
fprintf(stderr, " -c|--create\t\tRemove existing data from the database. This is the \n");
|
||||
fprintf(stderr, " \t\tdefault if --append is not specified.\n");
|
||||
fprintf(stderr, " -d|--database\tThe name of the PostgreSQL database to connect\n");
|
||||
fprintf(stderr, " \tto (default: gis).\n");
|
||||
fprintf(stderr, " -l|--latlong\t\tStore data in degrees of latitude & longitude.\n");
|
||||
fprintf(stderr, " -u|--utf8-sanitize\tRepair bad UTF8 input data (present in planet\n");
|
||||
fprintf(stderr, " \tdumps prior to August 2007). Adds about 10%% overhead.\n");
|
||||
fprintf(stderr, " -s|--slim\t\tStore temporary data in the database. This greatly\n");
|
||||
fprintf(stderr, " \t\treduces the RAM usage but is much slower.\n");
|
||||
fprintf(stderr, " -h|--help\t\tHelp information.\n");
|
||||
fprintf(stderr, " -v|--verbose\t\tVerbose output.\n");
|
||||
fprintf(stderr, "\n");
|
||||
}
|
||||
|
||||
@ -278,6 +286,7 @@ int main(int argc, char *argv[])
|
||||
int append=0;
|
||||
int create=0;
|
||||
int slim=0;
|
||||
int sanitize=0;
|
||||
const char *db = "gis";
|
||||
|
||||
fprintf(stderr, "osm2pgsql SVN version %s $Rev$ \n\n", VERSION);
|
||||
@ -293,22 +302,26 @@ int main(int argc, char *argv[])
|
||||
{"append", 0, 0, 'a'},
|
||||
{"create", 0, 0, 'c'},
|
||||
{"database", 1, 0, 'd'},
|
||||
{"latlong", 0, 0, 'l'},
|
||||
{"verbose", 0, 0, 'v'},
|
||||
{"slim", 0, 0, 's'},
|
||||
{"utf8-sanitize", 0, 0, 'u'},
|
||||
{"help", 0, 0, 'h'},
|
||||
{0, 0, 0, 0}
|
||||
};
|
||||
|
||||
c = getopt_long (argc, argv, "acd:hsv", long_options, &option_index);
|
||||
c = getopt_long (argc, argv, "acd:hlsuv", long_options, &option_index);
|
||||
if (c == -1)
|
||||
break;
|
||||
|
||||
switch (c) {
|
||||
case 'a': append=1; break;
|
||||
case 'c': create=1; break;
|
||||
case 'v': verbose=1; break;
|
||||
case 's': slim=1; break;
|
||||
case 'd': db=optarg; break;
|
||||
case 'a': append=1; break;
|
||||
case 'c': create=1; break;
|
||||
case 'v': verbose=1; break;
|
||||
case 's': slim=1; break;
|
||||
case 'u': sanitize=1; break;
|
||||
case 'l': latlong=1; break;
|
||||
case 'd': db=optarg; break;
|
||||
|
||||
case 'h':
|
||||
case '?':
|
||||
@ -338,8 +351,8 @@ int main(int argc, char *argv[])
|
||||
|
||||
while (optind < argc) {
|
||||
fprintf(stderr, "\nReading in file: %s\n", argv[optind]);
|
||||
mid->start(db);
|
||||
if (streamFile(argv[optind]) != 0)
|
||||
mid->start(db, latlong);
|
||||
if (streamFile(argv[optind], sanitize) != 0)
|
||||
exit_nicely();
|
||||
mid->end();
|
||||
mid->analyze();
|
||||
|
@ -74,7 +74,8 @@ static struct {
|
||||
{"tourism", "text", 1},
|
||||
{"tunnel", "text", 0},
|
||||
{"waterway", "text", 0},
|
||||
{"z_order", "int4", 0}
|
||||
{"z_order", "int4", 0},
|
||||
{"way_area", "real", 0}
|
||||
};
|
||||
static const unsigned int numTags = sizeof(exportTags) / sizeof(*exportTags);
|
||||
|
||||
@ -428,9 +429,16 @@ static int pgsql_out_way(int id, struct keyval *tags, struct osmSegLL *segll, in
|
||||
for (i=0;i<wkt_size;i++)
|
||||
{
|
||||
char *wkt = get_wkt(i);
|
||||
|
||||
if (strlen(wkt)) {
|
||||
/* FIXME: there should be a better way to detect polygons */
|
||||
if (!strncmp(wkt, "POLYGON", strlen("POLYGON"))) {
|
||||
double area = get_area(i);
|
||||
if (area > 0.0) {
|
||||
char tmp[32];
|
||||
snprintf(tmp, sizeof(tmp), "%f", area);
|
||||
addItem(tags, "way_area", tmp, 0);
|
||||
}
|
||||
write_wkts(id, tags, wkt, sql_conns[t_poly]);
|
||||
add_parking_node(id, tags, i);
|
||||
} else {
|
||||
@ -511,21 +519,6 @@ static int pgsql_out_start(const char *db, int append)
|
||||
exit_nicely();
|
||||
}
|
||||
PQclear(res);
|
||||
} else {
|
||||
if (i == t_poly) {
|
||||
sql[0] = '\0';
|
||||
strcat(sql, "ALTER TABLE ");
|
||||
strcat(sql, tables[i].name);
|
||||
strcat(sql, " DROP COLUMN way_area;\n");
|
||||
|
||||
res = PQexec(sql_conn, sql);
|
||||
if (PQresultStatus(res) != PGRES_COMMAND_OK) {
|
||||
fprintf(stderr, "%s failed: %s\n", sql, PQerrorMessage(sql_conn));
|
||||
PQclear(res);
|
||||
exit_nicely();
|
||||
}
|
||||
PQclear(res);
|
||||
}
|
||||
}
|
||||
|
||||
sql[0] = '\0';
|
||||
@ -586,6 +579,10 @@ static void pgsql_out_stop(int append)
|
||||
strcat(sql, ";\n");
|
||||
|
||||
if (!append) {
|
||||
strcat(sql, "ALTER TABLE ");
|
||||
strcat(sql, tables[i].name);
|
||||
strcat(sql, " ALTER COLUMN way SET NOT NULL;\n");
|
||||
|
||||
strcat(sql, "CREATE INDEX way_index");
|
||||
strcat(sql, tmp);
|
||||
strcat(sql, " ON ");
|
||||
@ -597,23 +594,7 @@ static void pgsql_out_stop(int append)
|
||||
strcat(sql, " ON ");
|
||||
strcat(sql, tables[i].name);
|
||||
strcat(sql, " (z_order);\n");
|
||||
|
||||
strcat(sql, "ALTER TABLE ");
|
||||
strcat(sql, tables[i].name);
|
||||
strcat(sql, " ALTER COLUMN way SET NOT NULL;\n");
|
||||
|
||||
}
|
||||
|
||||
if (i == t_poly) {
|
||||
strcat(sql, "ALTER TABLE ");
|
||||
strcat(sql, tables[i].name);
|
||||
strcat(sql, " ADD COLUMN way_area real;\n");
|
||||
|
||||
strcat(sql, "UPDATE ");
|
||||
strcat(sql, tables[i].name);
|
||||
strcat(sql, " SET way_area=area(way);\n");
|
||||
}
|
||||
|
||||
strcat(sql, "CLUSTER way_index");
|
||||
strcat(sql, tmp);
|
||||
strcat(sql, " ON ");
|
||||
|
Reference in New Issue
Block a user