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

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

osm2pgsql - make experimental version current, move previous implementation to legacy

File size: 8.8 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            while ((p = strchr(k, ' ')))
123                *p = '_';
124
125            addItem(&tags, k, (char *)xv, 0);
126            xmlFree(k);
127            xmlFree(xv);
128        }
129        xmlFree(xk);
130    } else if (xmlStrEqual(name, BAD_CAST "way")) {
131        xid  = xmlTextReaderGetAttribute(reader, BAD_CAST "id");
132        assert(xid);
133        osm_id   = strtol((char *)xid, NULL, 10);
134
135        if (osm_id > max_way)
136            max_way = osm_id;
137
138        if (count_way == 0)
139            fprintf(stderr, "\n");
140
141        count_way++;
142        if (count_way%1000 == 0) 
143            fprintf(stderr, "\rProcessing: Way(%dk)", count_way/1000);
144
145        xmlFree(xid);
146    } else if (xmlStrEqual(name, BAD_CAST "seg")) {
147        xid  = xmlTextReaderGetAttribute(reader, BAD_CAST "id");
148        assert(xid);
149
150        if (addItem(&segs, "id", (char *)xid, 1))
151            count_way_seg++;
152
153        xmlFree(xid);
154    } else if (xmlStrEqual(name, BAD_CAST "osm")) {
155        /* ignore */
156    } else {
157        fprintf(stderr, "%s: Unknown element name: %s\n", __FUNCTION__, name);
158    }
159}
160
161void EndElement(xmlTextReaderPtr reader, const xmlChar *name)
162{
163    if (xmlStrEqual(name, BAD_CAST "node")) {
164       reproject(&node_lat, &node_lon);
165       mid->nodes_set(osm_id, node_lat, node_lon, &tags);
166        resetList(&tags);
167    } else if (xmlStrEqual(name, BAD_CAST "segment")) {
168        mid->segments_set(osm_id, seg_from, seg_to, &tags);
169        resetList(&tags);
170    } else if (xmlStrEqual(name, BAD_CAST "way")) {
171        mid->ways_set(osm_id, &segs, &tags);
172        resetList(&tags);
173        resetList(&segs);
174    } else if (xmlStrEqual(name, BAD_CAST "tag")) {
175        /* ignore */
176    } else if (xmlStrEqual(name, BAD_CAST "seg")) {
177        /* ignore */
178    } else if (xmlStrEqual(name, BAD_CAST "osm")) {
179        /* ignore */
180    } else {
181        fprintf(stderr, "%s: Unknown element name: %s\n", __FUNCTION__, name);
182    }
183}
184
185static void processNode(xmlTextReaderPtr reader) {
186    xmlChar *name;
187    name = xmlTextReaderName(reader);
188    if (name == NULL)
189        name = xmlStrdup(BAD_CAST "--");
190       
191    switch(xmlTextReaderNodeType(reader)) {
192        case XML_READER_TYPE_ELEMENT:
193            StartElement(reader, name); 
194            if (xmlTextReaderIsEmptyElement(reader))
195                EndElement(reader, name); /* No end_element for self closing tags! */
196            break;
197        case XML_READER_TYPE_END_ELEMENT:
198            EndElement(reader, name);
199            break;
200        case XML_READER_TYPE_SIGNIFICANT_WHITESPACE:
201            /* Ignore */
202            break;
203        default:
204            fprintf(stderr, "Unknown node type %d\n", xmlTextReaderNodeType(reader));
205            break;
206    }
207
208    xmlFree(name);
209}
210
211static int streamFile(char *filename) {
212    xmlTextReaderPtr reader;
213    int ret = 0;
214
215//    reader = xmlNewTextReaderFilename(filename);
216    reader = sanitizerOpen(filename);
217
218    if (reader != NULL) {
219        ret = xmlTextReaderRead(reader);
220        while (ret == 1) {
221            processNode(reader);
222            ret = xmlTextReaderRead(reader);
223        }
224
225        if (ret != 0) {
226            fprintf(stderr, "%s : failed to parse\n", filename);
227            return ret;
228        }
229
230        xmlFreeTextReader(reader);
231    } else {
232        fprintf(stderr, "Unable to open %s\n", filename);
233        return 1;
234    }
235    return 0;
236}
237
238void exit_nicely(void)
239{
240    fprintf(stderr, "Error occurred, cleaning up\n");
241    out->cleanup();
242    mid->cleanup();
243    exit(1);
244}
245 
246static void usage(const char *arg0)
247{
248    fprintf(stderr, "Usage error:\n\t%s planet.osm\n", arg0);
249    fprintf(stderr, "or\n\tgzip -dc planet.osm.gz | %s -\n", arg0);
250}
251
252int main(int argc, char *argv[])
253{
254    if (argc != 2) {
255        usage(argv[0]);
256        exit(1);
257    }
258
259    // use getopt
260    update = 0;
261 
262    initList(&tags);
263    initList(&segs);
264
265    LIBXML_TEST_VERSION
266
267    project_init();
268                   
269    //mid = &mid_pgsql;
270    mid = &mid_ram;
271    out = &out_pgsql;
272
273    mid->start(!update);
274    out->start(!update);
275
276    if (streamFile(argv[1]) != 0)
277        exit_nicely();
278
279    xmlCleanupParser();
280    xmlMemoryDump();
281
282    fprintf(stderr, "\n");
283    fprintf(stderr, "Node stats: total(%d), max(%d)\n", count_node, max_node);
284    fprintf(stderr, "Segment stats: total(%d), max(%d)\n", count_segment, max_segment);
285    fprintf(stderr, "Way stats: total(%d), max(%d)\n", count_way, max_way);
286    fprintf(stderr, "Way stats: duplicate segments in ways %d\n", count_way_seg);
287
288    fprintf(stderr, "\n\nEnding data import\n");
289    mid->end();
290
291    fprintf(stderr, "\n\nRunning analysis on intermediate data\n");
292    mid->analyze();
293
294    fprintf(stderr, "\n\nOutput processing\n");
295
296    //mid->iterate_nodes(out->node);
297    mid->iterate_ways(out->way);
298
299    //out->process(mid);
300    mid->stop();
301    out->stop();
302
303    project_exit();
304
305    fprintf(stderr, "\n");
306
307    return 0;
308}
Note: See TracBrowser for help on using the repository browser.