source: subversion/applications/utils/export/osm2pgsql/osm2pgsql.c @ 3210

Last change on this file since 3210 was 3052, checked in by jonb, 13 years ago

osm2pgsql: improve help text, allow - to be used again

File size: 8.9 KB
Line 
1/*
2#-----------------------------------------------------------------------------
3# osm2pgsql - converts planet.osm file into PostgreSQL
4# compatible output suitable to be rendered by mapnik
5# Use: osm2pgsql planet.osm.bz2
6#-----------------------------------------------------------------------------
7# Original Python implementation by Artem Pavlenko
8# Re-implementation by Jon Burgess, Copyright 2006
9#
10# This program is free software; you can redistribute it and/or
11# modify it under the terms of the GNU General Public License
12# as published by the Free Software Foundation; either version 2
13# of the License, or (at your option) any later version.
14#
15# This program is distributed in the hope that it will be useful,
16# but WITHOUT ANY WARRANTY; without even the implied warranty of
17# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18# GNU General Public License for more details.
19#
20# You should have received a copy of the GNU General Public License
21# along with this program; if not, write to the Free Software
22# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
23#-----------------------------------------------------------------------------
24*/
25
26#include <stdio.h>
27#include <unistd.h>
28#include <stdlib.h>
29#include <string.h>
30#include <assert.h>
31
32#include <libxml/xmlstring.h>
33#include <libxml/xmlreader.h>
34
35#include "osmtypes.h"
36#include "build_geometry.h"
37#include "keyvals.h"
38#include "middle-pgsql.h"
39#include "middle-ram.h"
40#include "output-pgsql.h"
41#include "sanitizer.h"
42#include "reprojection.h"
43
44static int count_node,    max_node;
45static int count_segment, max_segment;
46static int count_way,     max_way;
47static int count_way_seg;
48
49struct middle_t *mid;
50struct output_t *out;
51
52/* Since {node,segment,way} elements are not nested we can guarantee the
53   values in an end tag must match those of the corresponding
54   start tag and can therefore be cached.
55*/
56static double node_lon, node_lat;
57static int seg_to, seg_from;
58static struct keyval tags, segs;
59static int osm_id;
60
61static int update;
62
63void StartElement(xmlTextReaderPtr reader, const xmlChar *name)
64{
65    xmlChar *xid, *xlat, *xlon, *xfrom, *xto, *xk, *xv;
66    char *k;
67
68    if (xmlStrEqual(name, BAD_CAST "node")) {
69        xid  = xmlTextReaderGetAttribute(reader, BAD_CAST "id");
70        xlon = xmlTextReaderGetAttribute(reader, BAD_CAST "lon");
71        xlat = xmlTextReaderGetAttribute(reader, BAD_CAST "lat");
72        assert(xid); assert(xlon); assert(xlat);
73
74        osm_id  = strtol((char *)xid, NULL, 10);
75        node_lon = strtod((char *)xlon, NULL);
76        node_lat = strtod((char *)xlat, NULL);
77
78        if (osm_id > max_node) 
79            max_node = osm_id;
80
81        count_node++;
82        if (count_node%10000 == 0) 
83            fprintf(stderr, "\rProcessing: Node(%dk)", count_node/1000);
84
85        xmlFree(xid);
86        xmlFree(xlon);
87        xmlFree(xlat);
88    } else if (xmlStrEqual(name, BAD_CAST "segment")) {
89        xid   = xmlTextReaderGetAttribute(reader, BAD_CAST "id");
90        xfrom = xmlTextReaderGetAttribute(reader, BAD_CAST "from");
91        xto   = xmlTextReaderGetAttribute(reader, BAD_CAST "to");
92        assert(xid); assert(xfrom); assert(xto);
93        osm_id = strtol((char *)xid, NULL, 10);
94        seg_from = strtol((char *)xfrom, NULL, 10);
95        seg_to   = strtol((char *)xto, NULL, 10);
96
97        if (osm_id > max_segment) 
98            max_segment = osm_id;
99
100        if (count_segment == 0) 
101            fprintf(stderr, "\n");
102
103        count_segment++;
104        if (count_segment%10000 == 0) 
105            fprintf(stderr, "\rProcessing: Segment(%dk)", count_segment/1000);
106
107        xmlFree(xid);
108        xmlFree(xfrom);
109        xmlFree(xto);
110    } else if (xmlStrEqual(name, BAD_CAST "tag")) {
111        xk = xmlTextReaderGetAttribute(reader, BAD_CAST "k");
112        assert(xk);
113
114        /* 'created_by' is very common and not interesting to mapnik renderer */
115        if (strcmp((char *)xk, "created_by")) {
116            char *p;
117            xv = xmlTextReaderGetAttribute(reader, BAD_CAST "v");
118            assert(xv);
119            k  = (char *)xmlStrdup(xk);
120            while ((p = strchr(k, ' ')))
121                *p = '_';
122
123            addItem(&tags, k, (char *)xv, 0);
124            xmlFree(k);
125            xmlFree(xv);
126        }
127        xmlFree(xk);
128    } else if (xmlStrEqual(name, BAD_CAST "way")) {
129        xid  = xmlTextReaderGetAttribute(reader, BAD_CAST "id");
130        assert(xid);
131        osm_id   = strtol((char *)xid, NULL, 10);
132
133        if (osm_id > max_way)
134            max_way = osm_id;
135
136        if (count_way == 0)
137            fprintf(stderr, "\n");
138
139        count_way++;
140        if (count_way%1000 == 0) 
141            fprintf(stderr, "\rProcessing: Way(%dk)", count_way/1000);
142
143        xmlFree(xid);
144    } else if (xmlStrEqual(name, BAD_CAST "seg")) {
145        xid  = xmlTextReaderGetAttribute(reader, BAD_CAST "id");
146        assert(xid);
147
148        if (addItem(&segs, "id", (char *)xid, 1))
149            count_way_seg++;
150
151        xmlFree(xid);
152    } else if (xmlStrEqual(name, BAD_CAST "osm")) {
153        /* ignore */
154    } else {
155        fprintf(stderr, "%s: Unknown element name: %s\n", __FUNCTION__, name);
156    }
157}
158
159void EndElement(xmlTextReaderPtr reader, const xmlChar *name)
160{
161    if (xmlStrEqual(name, BAD_CAST "node")) {
162       reproject(&node_lat, &node_lon);
163       mid->nodes_set(osm_id, node_lat, node_lon, &tags);
164        resetList(&tags);
165    } else if (xmlStrEqual(name, BAD_CAST "segment")) {
166        mid->segments_set(osm_id, seg_from, seg_to, &tags);
167        resetList(&tags);
168    } else if (xmlStrEqual(name, BAD_CAST "way")) {
169        mid->ways_set(osm_id, &segs, &tags);
170        resetList(&tags);
171        resetList(&segs);
172    } else if (xmlStrEqual(name, BAD_CAST "tag")) {
173        /* ignore */
174    } else if (xmlStrEqual(name, BAD_CAST "seg")) {
175        /* ignore */
176    } else if (xmlStrEqual(name, BAD_CAST "osm")) {
177        /* ignore */
178    } else {
179        fprintf(stderr, "%s: Unknown element name: %s\n", __FUNCTION__, name);
180    }
181}
182
183static void processNode(xmlTextReaderPtr reader) {
184    xmlChar *name;
185    name = xmlTextReaderName(reader);
186    if (name == NULL)
187        name = xmlStrdup(BAD_CAST "--");
188       
189    switch(xmlTextReaderNodeType(reader)) {
190        case XML_READER_TYPE_ELEMENT:
191            StartElement(reader, name); 
192            if (xmlTextReaderIsEmptyElement(reader))
193                EndElement(reader, name); /* No end_element for self closing tags! */
194            break;
195        case XML_READER_TYPE_END_ELEMENT:
196            EndElement(reader, name);
197            break;
198        case XML_READER_TYPE_SIGNIFICANT_WHITESPACE:
199            /* Ignore */
200            break;
201        default:
202            fprintf(stderr, "Unknown node type %d\n", xmlTextReaderNodeType(reader));
203            break;
204    }
205
206    xmlFree(name);
207}
208
209static int streamFile(char *filename) {
210    xmlTextReaderPtr reader;
211    int ret = 0;
212
213//    reader = xmlNewTextReaderFilename(filename);
214    reader = sanitizerOpen(filename);
215
216    if (reader != NULL) {
217        ret = xmlTextReaderRead(reader);
218        while (ret == 1) {
219            processNode(reader);
220            ret = xmlTextReaderRead(reader);
221        }
222
223        if (ret != 0) {
224            fprintf(stderr, "%s : failed to parse\n", filename);
225            return ret;
226        }
227
228        xmlFreeTextReader(reader);
229    } else {
230        fprintf(stderr, "Unable to open %s\n", filename);
231        return 1;
232    }
233    return 0;
234}
235
236void exit_nicely(void)
237{
238    fprintf(stderr, "Error occurred, cleaning up\n");
239    out->cleanup();
240    mid->cleanup();
241    exit(1);
242}
243 
244static void usage(const char *arg0)
245{
246    fprintf(stderr, "Usage error:\n\t%s planet.osm\n", arg0);
247    fprintf(stderr, "\nor read a .bzip2 or .gz file directly\n\t%s planet.osm.bz2\n", arg0);
248    fprintf(stderr, "\nor use 7za to decompress and pipe the data in\n\t7za x -so ~/osm/planet/planet-070516.osm.7z | %s -\n", arg0);
249}
250
251int main(int argc, char *argv[])
252{
253    if (argc != 2) {
254        usage(argv[0]);
255        exit(1);
256    }
257
258    // use getopt
259    update = 0;
260 
261    initList(&tags);
262    initList(&segs);
263
264    LIBXML_TEST_VERSION
265
266    project_init();
267                   
268    //mid = &mid_pgsql;
269    mid = &mid_ram;
270    out = &out_pgsql;
271
272    mid->start(!update);
273    out->start(!update);
274
275    if (streamFile(argv[1]) != 0)
276        exit_nicely();
277
278    xmlCleanupParser();
279    xmlMemoryDump();
280
281    fprintf(stderr, "\n");
282    fprintf(stderr, "Node stats: total(%d), max(%d)\n", count_node, max_node);
283    fprintf(stderr, "Segment stats: total(%d), max(%d)\n", count_segment, max_segment);
284    fprintf(stderr, "Way stats: total(%d), max(%d)\n", count_way, max_way);
285    fprintf(stderr, "Way stats: duplicate segments in ways %d\n", count_way_seg);
286
287    fprintf(stderr, "\n\nEnding data import\n");
288    mid->end();
289
290    fprintf(stderr, "\n\nRunning analysis on intermediate data\n");
291    mid->analyze();
292
293    fprintf(stderr, "\n\nOutput processing\n");
294
295    //mid->iterate_nodes(out->node);
296    mid->iterate_ways(out->way);
297
298    //out->process(mid);
299    mid->stop();
300    out->stop();
301
302    project_exit();
303
304    fprintf(stderr, "\n");
305
306    return 0;
307}
Note: See TracBrowser for help on using the repository browser.