mirror of
https://github.com/osm2pgsql-dev/osm2pgsql.git
synced 2025-08-22 19:42:12 +00:00
osm2pgsql - make experimental version current, move previous implementation to legacy
This commit is contained in:
818
osm2pgsql.c
818
osm2pgsql.c
@ -1,30 +1,28 @@
|
||||
/*
|
||||
#-----------------------------------------------------------------------------
|
||||
# osm2pgsql - converts planet.osm file into PostgreSQL
|
||||
# compatible output suitable to be rendered by mapnik
|
||||
# Use: osm2pgsql planet.osm > planet.sql
|
||||
#-----------------------------------------------------------------------------
|
||||
# Original Python implementation by Artem Pavlenko
|
||||
# Re-implementation by Jon Burgess, Copyright 2006
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or
|
||||
# modify it under the terms of the GNU General Public License
|
||||
# as published by the Free Software Foundation; either version 2
|
||||
# of the License, or (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
#-----------------------------------------------------------------------------
|
||||
#-----------------------------------------------------------------------------
|
||||
# osm2pgsql - converts planet.osm file into PostgreSQL
|
||||
# compatible output suitable to be rendered by mapnik
|
||||
# Use: osm2pgsql planet.osm.bz2
|
||||
#-----------------------------------------------------------------------------
|
||||
# Original Python implementation by Artem Pavlenko
|
||||
# Re-implementation by Jon Burgess, Copyright 2006
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or
|
||||
# modify it under the terms of the GNU General Public License
|
||||
# as published by the Free Software Foundation; either version 2
|
||||
# of the License, or (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
#-----------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
#define _GNU_SOURCE
|
||||
|
||||
#include <stdio.h>
|
||||
#include <unistd.h>
|
||||
#include <stdlib.h>
|
||||
@ -34,609 +32,277 @@
|
||||
#include <libxml/xmlstring.h>
|
||||
#include <libxml/xmlreader.h>
|
||||
|
||||
#include "osmtypes.h"
|
||||
#include "build_geometry.h"
|
||||
#include "keyvals.h"
|
||||
#include "middle-pgsql.h"
|
||||
#include "middle-ram.h"
|
||||
#include "output-pgsql.h"
|
||||
#include "sanitizer.h"
|
||||
#include "reprojection.h"
|
||||
|
||||
#if 0
|
||||
#define DEBUG printf
|
||||
#else
|
||||
#define DEBUG(x, ...)
|
||||
#endif
|
||||
|
||||
struct tagDesc {
|
||||
const char *name;
|
||||
const char *type;
|
||||
const int polygon;
|
||||
};
|
||||
|
||||
static struct tagDesc exportTags[] = {
|
||||
{"name", "text", 0},
|
||||
{"place", "text", 0},
|
||||
{"landuse", "text", 1},
|
||||
{"leisure", "text", 1},
|
||||
{"natural", "text", 1},
|
||||
{"man_made","text", 0},
|
||||
{"waterway","text", 0},
|
||||
{"highway", "text", 0},
|
||||
{"foot", "text", 0},
|
||||
{"horse", "text", 0},
|
||||
{"bicycle", "text", 0},
|
||||
{"motorcar","text", 0},
|
||||
{"residence","text", 0},
|
||||
{"railway", "text", 0},
|
||||
{"amenity", "text", 1},
|
||||
{"tourism", "text", 1},
|
||||
{"learning","text", 0},
|
||||
{"building","text", 1},
|
||||
{"bridge", "text", 0},
|
||||
{"layer", "text", 0},
|
||||
{"junction","text", 0},
|
||||
{"sport", "text", 1},
|
||||
{"route", "text", 0},
|
||||
{"aeroway", "text", 0}
|
||||
};
|
||||
|
||||
static const char *table_name_point = "planet_osm_point";
|
||||
static const char *table_name_line = "planet_osm_line";
|
||||
static const char *table_name_polygon = "planet_osm_polygon";
|
||||
|
||||
#define MAX_ID_NODE (35000000)
|
||||
#define MAX_ID_SEGMENT (35000000)
|
||||
|
||||
struct osmNode {
|
||||
double lon;
|
||||
double lat;
|
||||
};
|
||||
|
||||
struct osmSegment {
|
||||
unsigned int from;
|
||||
unsigned int to;
|
||||
};
|
||||
|
||||
struct osmWay {
|
||||
char *values;
|
||||
char *wkt;
|
||||
};
|
||||
|
||||
static struct osmNode nodes[MAX_ID_NODE+1];
|
||||
static struct osmSegment segments[MAX_ID_SEGMENT+1];
|
||||
|
||||
static int count_node, count_all_node, max_node;
|
||||
static int count_segment, count_all_segment, max_segment;
|
||||
static int count_way, count_all_way, max_way;
|
||||
static int count_node, max_node;
|
||||
static int count_segment, max_segment;
|
||||
static int count_way, max_way;
|
||||
static int count_way_seg;
|
||||
|
||||
struct keyval {
|
||||
char *key;
|
||||
char *value;
|
||||
struct keyval *next;
|
||||
struct keyval *prev;
|
||||
};
|
||||
struct middle_t *mid;
|
||||
struct output_t *out;
|
||||
|
||||
/* Since {node,segment,way} elements are not nested we can guarantee the
|
||||
values in an end tag must match those of the corresponding
|
||||
start tag and can therefore be cached.
|
||||
*/
|
||||
static double node_lon, node_lat;
|
||||
static int seg_to, seg_from;
|
||||
static struct keyval tags, segs;
|
||||
static int osm_id;
|
||||
|
||||
static struct keyval keys, tags, segs;
|
||||
|
||||
|
||||
void usage(const char *arg0)
|
||||
{
|
||||
fprintf(stderr, "Usage error:\n\t%s planet.osm > planet.sql\n", arg0);
|
||||
fprintf(stderr, "or\n\tgzip -dc planet.osm.gz | %s - | gzip -c > planet.sql.gz\n", arg0);
|
||||
}
|
||||
|
||||
void initList(struct keyval *head)
|
||||
{
|
||||
head->next = head;
|
||||
head->prev = head;
|
||||
head->key = NULL;
|
||||
head->value = NULL;
|
||||
}
|
||||
|
||||
void freeItem(struct keyval *p)
|
||||
{
|
||||
free(p->key);
|
||||
free(p->value);
|
||||
free(p);
|
||||
}
|
||||
|
||||
|
||||
unsigned int countList(struct keyval *head)
|
||||
{
|
||||
struct keyval *p = head->next;
|
||||
unsigned int count = 0;
|
||||
|
||||
while(p != head) {
|
||||
count++;
|
||||
p = p->next;
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
int listHasData(struct keyval *head)
|
||||
{
|
||||
return (head->next != head);
|
||||
}
|
||||
|
||||
|
||||
char *getItem(struct keyval *head, const char *name)
|
||||
{
|
||||
struct keyval *p = head->next;
|
||||
while(p != head) {
|
||||
if (!strcmp(p->key, name))
|
||||
return p->value;
|
||||
p = p->next;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
struct keyval *popItem(struct keyval *head)
|
||||
{
|
||||
struct keyval *p = head->next;
|
||||
if (p == head)
|
||||
return NULL;
|
||||
|
||||
head->next = p->next;
|
||||
p->next->prev = head;
|
||||
|
||||
p->next = NULL;
|
||||
p->prev = NULL;
|
||||
|
||||
return p;
|
||||
}
|
||||
|
||||
|
||||
void pushItem(struct keyval *head, struct keyval *item)
|
||||
{
|
||||
item->next = head;
|
||||
item->prev = head->prev;
|
||||
head->prev->next = item;
|
||||
head->prev = item;
|
||||
}
|
||||
|
||||
int addItem(struct keyval *head, const char *name, const char *value, int noDupe)
|
||||
{
|
||||
struct keyval *item;
|
||||
|
||||
if (noDupe) {
|
||||
item = head->next;
|
||||
while (item != head) {
|
||||
if (!strcmp(item->value, value) && !strcmp(item->key, name)) {
|
||||
//fprintf(stderr, "Discarded %s=%s\n", name, value);
|
||||
return 1;
|
||||
}
|
||||
item = item->next;
|
||||
}
|
||||
}
|
||||
|
||||
item = malloc(sizeof(struct keyval));
|
||||
|
||||
if (!item) {
|
||||
fprintf(stderr, "Error allocating keyval\n");
|
||||
return 2;
|
||||
}
|
||||
|
||||
item->key = strdup(name);
|
||||
item->value = strdup(value);
|
||||
|
||||
item->next = head->next;
|
||||
item->prev = head;
|
||||
head->next->prev = item;
|
||||
head->next = item;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void resetList(struct keyval *head)
|
||||
{
|
||||
struct keyval *item;
|
||||
|
||||
while((item = popItem(head)))
|
||||
freeItem(item);
|
||||
}
|
||||
|
||||
size_t WKT(int polygon)
|
||||
{
|
||||
while (listHasData(&segs))
|
||||
{
|
||||
struct keyval *p;
|
||||
unsigned int id, to, from;
|
||||
double x0, y0, x1, y1;
|
||||
p = popItem(&segs);
|
||||
id = strtoul(p->value, NULL, 10);
|
||||
freeItem(p);
|
||||
|
||||
from = segments[id].from;
|
||||
to = segments[id].to;
|
||||
|
||||
x0 = nodes[from].lon;
|
||||
y0 = nodes[from].lat;
|
||||
x1 = nodes[to].lon;
|
||||
y1 = nodes[to].lat;
|
||||
add_segment(x0,y0,x1,y1);
|
||||
}
|
||||
return build_geometry(polygon);
|
||||
}
|
||||
|
||||
static int update;
|
||||
|
||||
void StartElement(xmlTextReaderPtr reader, const xmlChar *name)
|
||||
{
|
||||
xmlChar *xid, *xlat, *xlon, *xfrom, *xto, *xk, *xv;
|
||||
unsigned int id, to, from;
|
||||
double lon, lat;
|
||||
char *k;
|
||||
xmlChar *xid, *xlat, *xlon, *xfrom, *xto, *xk, *xv;
|
||||
char *k;
|
||||
|
||||
if (xmlStrEqual(name, BAD_CAST "node")) {
|
||||
struct osmNode *node;
|
||||
xid = xmlTextReaderGetAttribute(reader, BAD_CAST "id");
|
||||
xlon = xmlTextReaderGetAttribute(reader, BAD_CAST "lon");
|
||||
xlat = xmlTextReaderGetAttribute(reader, BAD_CAST "lat");
|
||||
assert(xid); assert(xlon); assert(xlat);
|
||||
id = strtoul((char *)xid, NULL, 10);
|
||||
lon = strtod((char *)xlon, NULL);
|
||||
lat = strtod((char *)xlat, NULL);
|
||||
if (xmlStrEqual(name, BAD_CAST "node")) {
|
||||
xid = xmlTextReaderGetAttribute(reader, BAD_CAST "id");
|
||||
xlon = xmlTextReaderGetAttribute(reader, BAD_CAST "lon");
|
||||
xlat = xmlTextReaderGetAttribute(reader, BAD_CAST "lat");
|
||||
assert(xid); assert(xlon); assert(xlat);
|
||||
|
||||
assert(id > 0);
|
||||
assert(id < MAX_ID_NODE);
|
||||
osm_id = strtol((char *)xid, NULL, 10);
|
||||
node_lon = strtod((char *)xlon, NULL);
|
||||
node_lat = strtod((char *)xlat, NULL);
|
||||
|
||||
if (id > max_node)
|
||||
max_node = id;
|
||||
if (osm_id > max_node)
|
||||
max_node = osm_id;
|
||||
|
||||
count_all_node++;
|
||||
if (count_all_node%10000 == 0)
|
||||
fprintf(stderr, "\rProcessing: Node(%dk)", count_all_node/1000);
|
||||
count_node++;
|
||||
if (count_node%10000 == 0)
|
||||
fprintf(stderr, "\rProcessing: Node(%dk)", count_node/1000);
|
||||
|
||||
node = &nodes[id];
|
||||
node->lon = lon;
|
||||
node->lat = lat;
|
||||
xmlFree(xid);
|
||||
xmlFree(xlon);
|
||||
xmlFree(xlat);
|
||||
} else if (xmlStrEqual(name, BAD_CAST "segment")) {
|
||||
xid = xmlTextReaderGetAttribute(reader, BAD_CAST "id");
|
||||
xfrom = xmlTextReaderGetAttribute(reader, BAD_CAST "from");
|
||||
xto = xmlTextReaderGetAttribute(reader, BAD_CAST "to");
|
||||
assert(xid); assert(xfrom); assert(xto);
|
||||
osm_id = strtol((char *)xid, NULL, 10);
|
||||
seg_from = strtol((char *)xfrom, NULL, 10);
|
||||
seg_to = strtol((char *)xto, NULL, 10);
|
||||
|
||||
DEBUG("NODE(%d) %f %f\n", id, lon, lat);
|
||||
addItem(&keys, "id", (char *)xid, 0);
|
||||
if (osm_id > max_segment)
|
||||
max_segment = osm_id;
|
||||
|
||||
xmlFree(xid);
|
||||
xmlFree(xlon);
|
||||
xmlFree(xlat);
|
||||
} else if (xmlStrEqual(name, BAD_CAST "segment")) {
|
||||
xid = xmlTextReaderGetAttribute(reader, BAD_CAST "id");
|
||||
xfrom = xmlTextReaderGetAttribute(reader, BAD_CAST "from");
|
||||
xto = xmlTextReaderGetAttribute(reader, BAD_CAST "to");
|
||||
assert(xid); assert(xfrom); assert(xto);
|
||||
id = strtoul((char *)xid, NULL, 10);
|
||||
from = strtoul((char *)xfrom, NULL, 10);
|
||||
to = strtoul((char *)xto, NULL, 10);
|
||||
if (count_segment == 0)
|
||||
fprintf(stderr, "\n");
|
||||
|
||||
assert(id > 0);
|
||||
assert(id < MAX_ID_SEGMENT);
|
||||
count_segment++;
|
||||
if (count_segment%10000 == 0)
|
||||
fprintf(stderr, "\rProcessing: Segment(%dk)", count_segment/1000);
|
||||
|
||||
if (id > max_segment)
|
||||
max_segment = id;
|
||||
xmlFree(xid);
|
||||
xmlFree(xfrom);
|
||||
xmlFree(xto);
|
||||
} else if (xmlStrEqual(name, BAD_CAST "tag")) {
|
||||
xk = xmlTextReaderGetAttribute(reader, BAD_CAST "k");
|
||||
assert(xk);
|
||||
|
||||
if (count_all_segment == 0)
|
||||
fprintf(stderr, "\n");
|
||||
/* 'created_by' is very common and not interesting to mapnik renderer */
|
||||
if (strcmp((char *)xk, "created_by")) {
|
||||
char *p;
|
||||
xv = xmlTextReaderGetAttribute(reader, BAD_CAST "v");
|
||||
assert(xv);
|
||||
k = (char *)xmlStrdup(xk);
|
||||
while ((p = strchr(k, ':')))
|
||||
*p = '_';
|
||||
while ((p = strchr(k, ' ')))
|
||||
*p = '_';
|
||||
|
||||
count_all_segment++;
|
||||
if (count_all_segment%10000 == 0)
|
||||
fprintf(stderr, "\rProcessing: Segment(%dk)", count_all_segment/1000);
|
||||
addItem(&tags, k, (char *)xv, 0);
|
||||
xmlFree(k);
|
||||
xmlFree(xv);
|
||||
}
|
||||
xmlFree(xk);
|
||||
} else if (xmlStrEqual(name, BAD_CAST "way")) {
|
||||
xid = xmlTextReaderGetAttribute(reader, BAD_CAST "id");
|
||||
assert(xid);
|
||||
osm_id = strtol((char *)xid, NULL, 10);
|
||||
|
||||
if (!nodes[to].lat && !nodes[to].lon) {
|
||||
DEBUG("SEGMENT(%d), NODE(%d) is missing\n", id, to);
|
||||
} else if (!nodes[from].lat && !nodes[from].lon) {
|
||||
DEBUG("SEGMENT(%d), NODE(%d) is missing\n", id, from);
|
||||
} else {
|
||||
if (from != to) {
|
||||
struct osmSegment *segment;
|
||||
segment = &segments[id];
|
||||
segment->to = to;
|
||||
segment->from = from;
|
||||
if (osm_id > max_way)
|
||||
max_way = osm_id;
|
||||
|
||||
count_segment++;
|
||||
DEBUG("SEGMENT(%d) %d, %d\n", id, from, to);
|
||||
}
|
||||
}
|
||||
if (count_way == 0)
|
||||
fprintf(stderr, "\n");
|
||||
|
||||
xmlFree(xid);
|
||||
xmlFree(xfrom);
|
||||
xmlFree(xto);
|
||||
} else if (xmlStrEqual(name, BAD_CAST "tag")) {
|
||||
char *p;
|
||||
xk = xmlTextReaderGetAttribute(reader, BAD_CAST "k");
|
||||
xv = xmlTextReaderGetAttribute(reader, BAD_CAST "v");
|
||||
assert(xk); assert(xv);
|
||||
k = (char *)xmlStrdup(xk);
|
||||
count_way++;
|
||||
if (count_way%1000 == 0)
|
||||
fprintf(stderr, "\rProcessing: Way(%dk)", count_way/1000);
|
||||
|
||||
while ((p = strchr(k, ':')))
|
||||
*p = '_';
|
||||
while ((p = strchr(k, ' ')))
|
||||
*p = '_';
|
||||
xmlFree(xid);
|
||||
} else if (xmlStrEqual(name, BAD_CAST "seg")) {
|
||||
xid = xmlTextReaderGetAttribute(reader, BAD_CAST "id");
|
||||
assert(xid);
|
||||
|
||||
addItem(&tags, k, (char *)xv, 0);
|
||||
DEBUG("\t%s = %s\n", xk, xv);
|
||||
xmlFree(k);
|
||||
xmlFree(xk);
|
||||
xmlFree(xv);
|
||||
} else if (xmlStrEqual(name, BAD_CAST "way")) {
|
||||
xid = xmlTextReaderGetAttribute(reader, BAD_CAST "id");
|
||||
assert(xid);
|
||||
id = strtoul((char *)xid, NULL, 10);
|
||||
addItem(&keys, "id", (char *)xid, 0);
|
||||
DEBUG("WAY(%s)\n", xid);
|
||||
|
||||
if (id > max_way)
|
||||
max_way = id;
|
||||
|
||||
if (count_all_way == 0)
|
||||
fprintf(stderr, "\n");
|
||||
|
||||
count_all_way++;
|
||||
if (count_all_way%1000 == 0)
|
||||
fprintf(stderr, "\rProcessing: Way(%dk)", count_all_way/1000);
|
||||
|
||||
xmlFree(xid);
|
||||
} else if (xmlStrEqual(name, BAD_CAST "seg")) {
|
||||
xid = xmlTextReaderGetAttribute(reader, BAD_CAST "id");
|
||||
assert(xid);
|
||||
id = strtoul((char *)xid, NULL, 10);
|
||||
if (!id || (id > MAX_ID_SEGMENT))
|
||||
DEBUG("\tSEG(%s) - invalid segment ID\n", xid);
|
||||
else if (!segments[id].from || !segments[id].to)
|
||||
DEBUG("\tSEG(%s) - missing segment\n", xid);
|
||||
else {
|
||||
if (addItem(&segs, "id", (char *)xid, 1)) {
|
||||
const char *way_id = getItem(&keys, "id");
|
||||
if (!way_id) way_id = "???";
|
||||
//fprintf(stderr, "Way %s with duplicate segment id %d\n", way_id, id);
|
||||
if (addItem(&segs, "id", (char *)xid, 1))
|
||||
count_way_seg++;
|
||||
}
|
||||
DEBUG("\tSEG(%s)\n", xid);
|
||||
}
|
||||
xmlFree(xid);
|
||||
} else if (xmlStrEqual(name, BAD_CAST "osm")) {
|
||||
/* ignore */
|
||||
} else {
|
||||
fprintf(stderr, "%s: Unknown element name: %s\n", __FUNCTION__, name);
|
||||
}
|
||||
|
||||
xmlFree(xid);
|
||||
} else if (xmlStrEqual(name, BAD_CAST "osm")) {
|
||||
/* ignore */
|
||||
} else {
|
||||
fprintf(stderr, "%s: Unknown element name: %s\n", __FUNCTION__, name);
|
||||
}
|
||||
}
|
||||
|
||||
void EndElement(xmlTextReaderPtr reader, const xmlChar *name)
|
||||
{
|
||||
unsigned int id;
|
||||
|
||||
DEBUG("%s: %s\n", __FUNCTION__, name);
|
||||
|
||||
if (xmlStrEqual(name, BAD_CAST "node")) {
|
||||
int i;
|
||||
char *values = NULL, *names = NULL;
|
||||
char *osm_id = getItem(&keys, "id");
|
||||
if (!osm_id) {
|
||||
fprintf(stderr, "%s: Node ID not in keys\n", __FUNCTION__);
|
||||
resetList(&keys);
|
||||
resetList(&tags);
|
||||
return;
|
||||
}
|
||||
id = strtoul(osm_id, NULL, 10);
|
||||
//assert(nodes[id].lat && nodes[id].lon);
|
||||
for (i=0; i < sizeof(exportTags) / sizeof(exportTags[0]); i++) {
|
||||
char *v;
|
||||
if ((v = getItem(&tags, exportTags[i].name))) {
|
||||
if (values) {
|
||||
char *oldval = values, *oldnam = names;
|
||||
asprintf(&names, "%s,\"%s\"", oldnam, exportTags[i].name);
|
||||
asprintf(&values, "%s,$$%s$$", oldval, v);
|
||||
free(oldnam);
|
||||
free(oldval);
|
||||
} else {
|
||||
asprintf(&names, "\"%s\"", exportTags[i].name);
|
||||
asprintf(&values, "$$%s$$", v);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (values) {
|
||||
count_node++;
|
||||
printf("insert into %s (osm_id,%s,way) values "
|
||||
"(%s,%s,GeomFromText('POINT(%.15g %.15g)',4326));\n",
|
||||
table_name_point,names,osm_id,values,nodes[id].lon, nodes[id].lat);
|
||||
}
|
||||
resetList(&keys);
|
||||
resetList(&tags);
|
||||
free(values);
|
||||
free(names);
|
||||
} else if (xmlStrEqual(name, BAD_CAST "segment")) {
|
||||
resetList(&tags);
|
||||
} else if (xmlStrEqual(name, BAD_CAST "tag")) {
|
||||
/* Separate tag list so tag stack unused */
|
||||
} else if (xmlStrEqual(name, BAD_CAST "way")) {
|
||||
int i, polygon = 0;
|
||||
char *values = NULL, *names = NULL;
|
||||
char *osm_id = getItem(&keys, "id");
|
||||
|
||||
if (!osm_id) {
|
||||
fprintf(stderr, "%s: WAY ID not in keys\n", __FUNCTION__);
|
||||
resetList(&keys);
|
||||
resetList(&tags);
|
||||
resetList(&segs);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!listHasData(&segs)) {
|
||||
DEBUG("%s: WAY(%s) has no segments\n", __FUNCTION__, osm_id);
|
||||
resetList(&keys);
|
||||
resetList(&tags);
|
||||
resetList(&segs);
|
||||
return;
|
||||
}
|
||||
id = strtoul(osm_id, NULL, 10);
|
||||
|
||||
for (i=0; i < sizeof(exportTags) / sizeof(exportTags[0]); i++) {
|
||||
char *v;
|
||||
if ((v = getItem(&tags, exportTags[i].name))) {
|
||||
if (values) {
|
||||
char *oldval = values, *oldnam = names;
|
||||
asprintf(&names, "%s,\"%s\"", oldnam, exportTags[i].name);
|
||||
asprintf(&values, "%s,$$%s$$", oldval, v);
|
||||
free(oldnam);
|
||||
free(oldval);
|
||||
} else {
|
||||
asprintf(&names, "\"%s\"", exportTags[i].name);
|
||||
asprintf(&values, "$$%s$$", v);
|
||||
}
|
||||
polygon |= exportTags[i].polygon;
|
||||
}
|
||||
}
|
||||
if (values) {
|
||||
size_t wkt_size = WKT(polygon);
|
||||
|
||||
if (wkt_size)
|
||||
{
|
||||
unsigned i;
|
||||
for (i=0;i<wkt_size;i++)
|
||||
{
|
||||
const char * wkt = get_wkt(i);
|
||||
if (strlen(wkt)) {
|
||||
if (polygon) {
|
||||
printf("insert into %s (osm_id,%s,way) values (%s,%s,GeomFromText('%s',4326));\n", table_name_polygon,names,osm_id,values,wkt);
|
||||
}
|
||||
else {
|
||||
printf("insert into %s (osm_id,%s,way) values (%s,%s,GeomFromText('%s',4326));\n", table_name_line,names,osm_id,values,wkt);
|
||||
}
|
||||
count_way++;
|
||||
}
|
||||
}
|
||||
clear_wkts();
|
||||
}
|
||||
}
|
||||
|
||||
resetList(&keys);
|
||||
resetList(&tags);
|
||||
resetList(&segs);
|
||||
free(values);
|
||||
free(names);
|
||||
} else if (xmlStrEqual(name, BAD_CAST "seg")) {
|
||||
/* ignore */
|
||||
} else if (xmlStrEqual(name, BAD_CAST "osm")) {
|
||||
/* ignore */
|
||||
} else {
|
||||
fprintf(stderr, "%s: Unknown element name: %s\n", __FUNCTION__, name);
|
||||
}
|
||||
if (xmlStrEqual(name, BAD_CAST "node")) {
|
||||
reproject(&node_lat, &node_lon);
|
||||
mid->nodes_set(osm_id, node_lat, node_lon, &tags);
|
||||
resetList(&tags);
|
||||
} else if (xmlStrEqual(name, BAD_CAST "segment")) {
|
||||
mid->segments_set(osm_id, seg_from, seg_to, &tags);
|
||||
resetList(&tags);
|
||||
} else if (xmlStrEqual(name, BAD_CAST "way")) {
|
||||
mid->ways_set(osm_id, &segs, &tags);
|
||||
resetList(&tags);
|
||||
resetList(&segs);
|
||||
} else if (xmlStrEqual(name, BAD_CAST "tag")) {
|
||||
/* ignore */
|
||||
} else if (xmlStrEqual(name, BAD_CAST "seg")) {
|
||||
/* ignore */
|
||||
} else if (xmlStrEqual(name, BAD_CAST "osm")) {
|
||||
/* ignore */
|
||||
} else {
|
||||
fprintf(stderr, "%s: Unknown element name: %s\n", __FUNCTION__, name);
|
||||
}
|
||||
}
|
||||
|
||||
static void processNode(xmlTextReaderPtr reader) {
|
||||
xmlChar *name;
|
||||
name = xmlTextReaderName(reader);
|
||||
if (name == NULL)
|
||||
name = xmlStrdup(BAD_CAST "--");
|
||||
xmlChar *name;
|
||||
name = xmlTextReaderName(reader);
|
||||
if (name == NULL)
|
||||
name = xmlStrdup(BAD_CAST "--");
|
||||
|
||||
switch(xmlTextReaderNodeType(reader)) {
|
||||
case XML_READER_TYPE_ELEMENT:
|
||||
StartElement(reader, name);
|
||||
if (xmlTextReaderIsEmptyElement(reader))
|
||||
EndElement(reader, name); /* No end_element for self closing tags! */
|
||||
break;
|
||||
case XML_READER_TYPE_END_ELEMENT:
|
||||
EndElement(reader, name);
|
||||
break;
|
||||
case XML_READER_TYPE_SIGNIFICANT_WHITESPACE:
|
||||
/* Ignore */
|
||||
break;
|
||||
default:
|
||||
fprintf(stderr, "Unknown node type %d\n", xmlTextReaderNodeType(reader));
|
||||
break;
|
||||
}
|
||||
switch(xmlTextReaderNodeType(reader)) {
|
||||
case XML_READER_TYPE_ELEMENT:
|
||||
StartElement(reader, name);
|
||||
if (xmlTextReaderIsEmptyElement(reader))
|
||||
EndElement(reader, name); /* No end_element for self closing tags! */
|
||||
break;
|
||||
case XML_READER_TYPE_END_ELEMENT:
|
||||
EndElement(reader, name);
|
||||
break;
|
||||
case XML_READER_TYPE_SIGNIFICANT_WHITESPACE:
|
||||
/* Ignore */
|
||||
break;
|
||||
default:
|
||||
fprintf(stderr, "Unknown node type %d\n", xmlTextReaderNodeType(reader));
|
||||
break;
|
||||
}
|
||||
|
||||
xmlFree(name);
|
||||
xmlFree(name);
|
||||
}
|
||||
|
||||
void streamFile(char *filename) {
|
||||
xmlTextReaderPtr reader;
|
||||
int ret;
|
||||
static int streamFile(char *filename) {
|
||||
xmlTextReaderPtr reader;
|
||||
int ret = 0;
|
||||
|
||||
reader = xmlNewTextReaderFilename(filename);
|
||||
if (reader != NULL) {
|
||||
ret = xmlTextReaderRead(reader);
|
||||
while (ret == 1) {
|
||||
processNode(reader);
|
||||
ret = xmlTextReaderRead(reader);
|
||||
}
|
||||
// reader = xmlNewTextReaderFilename(filename);
|
||||
reader = sanitizerOpen(filename);
|
||||
|
||||
if (ret != 0) {
|
||||
fprintf(stderr, "%s : failed to parse\n", filename);
|
||||
return;
|
||||
}
|
||||
if (reader != NULL) {
|
||||
ret = xmlTextReaderRead(reader);
|
||||
while (ret == 1) {
|
||||
processNode(reader);
|
||||
ret = xmlTextReaderRead(reader);
|
||||
}
|
||||
|
||||
xmlFreeTextReader(reader);
|
||||
} else {
|
||||
fprintf(stderr, "Unable to open %s\n", filename);
|
||||
}
|
||||
if (ret != 0) {
|
||||
fprintf(stderr, "%s : failed to parse\n", filename);
|
||||
return ret;
|
||||
}
|
||||
|
||||
xmlFreeTextReader(reader);
|
||||
} else {
|
||||
fprintf(stderr, "Unable to open %s\n", filename);
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
void exit_nicely(void)
|
||||
{
|
||||
fprintf(stderr, "Error occurred, cleaning up\n");
|
||||
out->cleanup();
|
||||
mid->cleanup();
|
||||
exit(1);
|
||||
}
|
||||
|
||||
static void usage(const char *arg0)
|
||||
{
|
||||
fprintf(stderr, "Usage error:\n\t%s planet.osm\n", arg0);
|
||||
fprintf(stderr, "or\n\tgzip -dc planet.osm.gz | %s -\n", arg0);
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
int i;
|
||||
if (argc != 2) {
|
||||
usage(argv[0]);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if (argc != 2) {
|
||||
usage(argv[0]);
|
||||
exit(1);
|
||||
}
|
||||
// use getopt
|
||||
update = 0;
|
||||
|
||||
initList(&tags);
|
||||
initList(&segs);
|
||||
|
||||
initList(&keys);
|
||||
initList(&tags);
|
||||
initList(&segs);
|
||||
LIBXML_TEST_VERSION
|
||||
|
||||
LIBXML_TEST_VERSION
|
||||
project_init();
|
||||
|
||||
//mid = &mid_pgsql;
|
||||
mid = &mid_ram;
|
||||
out = &out_pgsql;
|
||||
|
||||
printf("drop table %s ;\n", table_name_point);
|
||||
printf("create table %s ( osm_id int4",table_name_point);
|
||||
for (i=0; i < sizeof(exportTags) / sizeof(exportTags[0]); i++)
|
||||
printf(",\"%s\" %s", exportTags[i].name, exportTags[i].type);
|
||||
printf(" );\n");
|
||||
printf("select AddGeometryColumn('%s', 'way', 4326, 'POINT', 2 );\n", table_name_point);
|
||||
|
||||
printf("drop table %s ;\n", table_name_line);
|
||||
printf("create table %s ( osm_id int4",table_name_line);
|
||||
for (i=0; i < sizeof(exportTags) / sizeof(exportTags[0]); i++)
|
||||
printf(",\"%s\" %s", exportTags[i].name, exportTags[i].type);
|
||||
printf(" );\n");
|
||||
printf("select AddGeometryColumn('%s', 'way', 4326, 'LINESTRING', 2 );\n", table_name_line);
|
||||
|
||||
printf("drop table %s ;\n", table_name_polygon);
|
||||
printf("create table %s ( osm_id int4",table_name_polygon);
|
||||
for (i=0; i < sizeof(exportTags) / sizeof(exportTags[0]); i++)
|
||||
printf(",\"%s\" %s", exportTags[i].name, exportTags[i].type);
|
||||
printf(" );\n");
|
||||
printf("select AddGeometryColumn('%s', 'way', 4326, 'GEOMETRY', 2 );\n", table_name_polygon);
|
||||
|
||||
printf("begin;\n");
|
||||
streamFile(argv[1]);
|
||||
printf("commit;\n");
|
||||
|
||||
printf("vacuum analyze %s;\n", table_name_point);
|
||||
printf("vacuum analyze %s;\n", table_name_line);
|
||||
printf("vacuum analyze %s;\n", table_name_polygon);
|
||||
|
||||
printf("CREATE INDEX way_index0 ON %s USING GIST (way GIST_GEOMETRY_OPS);\n", table_name_point);
|
||||
printf("ALTER TABLE %s ALTER COLUMN way SET NOT NULL;\n",table_name_point);
|
||||
printf("CLUSTER way_index0 on %s;\n",table_name_point);
|
||||
printf("vacuum analyze %s;\n", table_name_point);
|
||||
|
||||
printf("CREATE INDEX way_index1 ON %s USING GIST (way GIST_GEOMETRY_OPS);\n", table_name_line);
|
||||
printf("ALTER TABLE %s ALTER COLUMN way SET NOT NULL;\n",table_name_line);
|
||||
printf("ALTER TABLE %s ADD COLUMN z_order int4 default 0;\n",table_name_line);
|
||||
printf("CLUSTER way_index1 on %s;\n",table_name_line);
|
||||
printf("vacuum analyze %s;\n", table_name_line);
|
||||
|
||||
printf("CREATE INDEX way_index2 ON %s USING GIST (way GIST_GEOMETRY_OPS);\n", table_name_polygon);
|
||||
printf("ALTER TABLE %s ALTER COLUMN way SET NOT NULL;\n",table_name_polygon);
|
||||
printf("CLUSTER way_index2 on %s;\n",table_name_polygon);
|
||||
printf("vacuum analyze %s;\n", table_name_polygon);
|
||||
mid->start(!update);
|
||||
out->start(!update);
|
||||
|
||||
xmlCleanupParser();
|
||||
xmlMemoryDump();
|
||||
if (streamFile(argv[1]) != 0)
|
||||
exit_nicely();
|
||||
|
||||
fprintf(stderr, "\n");
|
||||
xmlCleanupParser();
|
||||
xmlMemoryDump();
|
||||
|
||||
fprintf(stderr, "Node stats: out(%d), total(%d), max(%d)\n", count_node, count_all_node, max_node);
|
||||
fprintf(stderr, "Segment stats: out(%d), total(%d), max(%d)\n", count_segment, count_all_segment, max_segment);
|
||||
fprintf(stderr, "Way stats: out(%d), total(%d), max(%d)\n", count_way, count_all_way, max_way);
|
||||
fprintf(stderr, "Way stats: duplicate segments in ways %d\n", count_way_seg);
|
||||
fprintf(stderr, "\n");
|
||||
fprintf(stderr, "Node stats: total(%d), max(%d)\n", count_node, max_node);
|
||||
fprintf(stderr, "Segment stats: total(%d), max(%d)\n", count_segment, max_segment);
|
||||
fprintf(stderr, "Way stats: total(%d), max(%d)\n", count_way, max_way);
|
||||
fprintf(stderr, "Way stats: duplicate segments in ways %d\n", count_way_seg);
|
||||
|
||||
return 0;
|
||||
fprintf(stderr, "\n\nEnding data import\n");
|
||||
mid->end();
|
||||
|
||||
fprintf(stderr, "\n\nRunning analysis on intermediate data\n");
|
||||
mid->analyze();
|
||||
|
||||
fprintf(stderr, "\n\nOutput processing\n");
|
||||
|
||||
//mid->iterate_nodes(out->node);
|
||||
mid->iterate_ways(out->way);
|
||||
|
||||
//out->process(mid);
|
||||
mid->stop();
|
||||
out->stop();
|
||||
|
||||
project_exit();
|
||||
|
||||
fprintf(stderr, "\n");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
Reference in New Issue
Block a user