source: subversion/applications/utils/coastcheck/osm2coast.c @ 29269

Last change on this file since 29269 was 29236, checked in by pnorman, 7 years ago

Update osm2coast to hopefully be 64-bit safe

File size: 9.3 KB
RevLine 
[6729]1/*
2#-----------------------------------------------------------------------------
3# osm2coast - extracts coastline data from planet.
4# Use: osm2coast planet.osm.gz >coastline.osm
5#-----------------------------------------------------------------------------
6# by Martijn van Oosterhout 2007
7#
8# This program is free software; you can redistribute it and/or
9# modify it under the terms of the GNU General Public License
10# as published by the Free Software Foundation; either version 2
11# of the License, or (at your option) any later version.
12#
13# This program is distributed in the hope that it will be useful,
14# but WITHOUT ANY WARRANTY; without even the implied warranty of
15# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16# GNU General Public License for more details.
17#
18# You should have received a copy of the GNU General Public License
19# along with this program; if not, write to the Free Software
20# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
21#-----------------------------------------------------------------------------
22*/
23
24#define _GNU_SOURCE
25#include <stdio.h>
26#include <unistd.h>
27#include <stdlib.h>
28#include <string.h>
29#include <assert.h>
30#include <getopt.h>
31#include <errno.h>
32#include <math.h>
33#include <stdint.h>
34
35#include <libxml/xmlstring.h>
36#include <libxml/xmlreader.h>
37
38#include "input.h"
39
[29236]40#define MAX_NODE_ID (3000000000L)
[19561]41#define MAX_NODES_PER_WAY 2000
[6729]42
43static int count_node,    max_node;
44static int count_way,     max_way;
45static int count_rel,     max_rel;
46
47/* Since {node,way} elements are not nested we can guarantee the
48   values in an end tag must match those of the corresponding
49   start tag and can therefore be cached.
50*/
51static double node_lon, node_lat;
[29236]52static int64_t *nds;
53static long int nd_count;
[6729]54static unsigned char *bitmap;
55int pass, wanted;
[29236]56static long int osm_id;
[6729]57
58static void printStatus(void)
59{
60  if( isatty(STDERR_FILENO) )
61    fprintf(stderr, "\rProcessing: Node(%dk) Way(%dk) Relation(%dk)",
62            count_node/1000, count_way/1000, count_rel/1000);
63}
64
65
66void StartElement(xmlTextReaderPtr reader, const xmlChar *name)
67{
68    xmlChar *xid, *xlat, *xlon, *xk, *xv /*, *xrole, *xtype*/;
69
70    if (xmlStrEqual(name, BAD_CAST "node")) {
71        if( pass == 1 )
72        {
73            xid  = xmlTextReaderGetAttribute(reader, BAD_CAST "id");
74            xlon = xmlTextReaderGetAttribute(reader, BAD_CAST "lon");
75            xlat = xmlTextReaderGetAttribute(reader, BAD_CAST "lat");
76            assert(xid); assert(xlon); assert(xlat);
77
78            osm_id  = strtol((char *)xid, NULL, 10);
79            node_lon = strtod((char *)xlon, NULL);
80            node_lat = strtod((char *)xlat, NULL);
81
82            if (osm_id > max_node)
83                max_node = osm_id;
84
85            xmlFree(xid);
86            xmlFree(xlon);
87            xmlFree(xlat);
88        }
89        count_node++;
90        if (count_node%10000 == 0)
91            printStatus();
92    } else if (xmlStrEqual(name, BAD_CAST "tag")) {
93        if( pass == 0 )
94        {
95            xk = xmlTextReaderGetAttribute(reader, BAD_CAST "k");
96            xv = xmlTextReaderGetAttribute(reader, BAD_CAST "v");
97            assert(xk);
98
99            /* 'created_by' and 'source' are common and not interesting to mapnik renderer */
100            if (strcmp((char *)xk, "natural")==0 && strcmp((char *)xv, "coastline")==0)
101                wanted = 1;
102            xmlFree(xv);
103            xmlFree(xk);
104        }
105    } else if (xmlStrEqual(name, BAD_CAST "way")) {
106        xid  = xmlTextReaderGetAttribute(reader, BAD_CAST "id");
107        assert(xid);
108        osm_id = strtol((char *)xid, NULL, 10);
109
110        if (osm_id > max_way)
111            max_way = osm_id;
112
113        count_way++;
114        if (count_way%1000 == 0)
115            printStatus();
116
117        wanted = 0;
118        nd_count = 0;
119        xmlFree(xid);
120    } else if (xmlStrEqual(name, BAD_CAST "nd")) {
121        xid  = xmlTextReaderGetAttribute(reader, BAD_CAST "ref");
122        assert(xid);
123
[29236]124        long int id = strtol((char *)xid, NULL, 10);
[20083]125        if( id > 0 && nd_count <= MAX_NODES_PER_WAY)
[16765]126            nds[nd_count] = id;
127        nd_count++;
[6729]128        xmlFree(xid);
129    } else if (xmlStrEqual(name, BAD_CAST "relation")) {
130        count_rel++;
131        if (count_rel%1000 == 0)
132            printStatus();
133
134    } else if (xmlStrEqual(name, BAD_CAST "member")) {
135        /* ignore */
136    } else if (xmlStrEqual(name, BAD_CAST "osm")) {
137        /* ignore */
138    } else if (xmlStrEqual(name, BAD_CAST "bound")) {
139        /* ignore */
[15133]140    } else if (xmlStrEqual(name, BAD_CAST "changeset")) {
141        /* ignore */
[6729]142    } else {
143        fprintf(stderr, "%s: Unknown element name: %s\n", __FUNCTION__, name);
144    }
145}
146
147void EndElement(const xmlChar *name)
148{
149    if (xmlStrEqual(name, BAD_CAST "node")) {
150        if( pass == 1 )
151        {
[7969]152            if( osm_id > MAX_NODE_ID )
153            {
[29236]154              fprintf( stderr, "Exceeded maximum node ID: %ld\n", MAX_NODE_ID );
[7969]155              exit(1);
156            }
[6729]157            if( bitmap[ osm_id >> 3 ] & (1<<(osm_id&7)) )
[29236]158                printf( "<node id=\"%ld\" lat=\"%f\" lon=\"%f\" />\n", osm_id, node_lat, node_lon );
[6729]159        }
160    } else if (xmlStrEqual(name, BAD_CAST "way")) {
[20083]161        if( nd_count > MAX_NODES_PER_WAY )
[6729]162        {
[29236]163            fprintf(stderr, "Exceeded maximum node count (%ld > %d) way=%ld\n", nd_count, MAX_NODES_PER_WAY, osm_id );
[6729]164        }
165
166        if( pass == 0 && wanted )
167        {
[29236]168            long int i;
169            printf( "<way id=\"%ld\">\n", osm_id );
[6729]170            for( i=0; i<nd_count; i++ )
171            {
[7969]172                if( nds[i] > MAX_NODE_ID )
173                {
[29236]174                  fprintf( stderr, "Exceeded maximum node ID: %ld\n", MAX_NODE_ID );
[7969]175                  exit(1);
176                }
[6729]177                bitmap[ nds[i] >> 3 ] |= (1<<(nds[i]&7));
[29236]178                printf( "<nd ref=\"%ld\" />\n", nds[i] );
[6729]179            }
180            printf( "</way>\n" );
181        }
182    } else if (xmlStrEqual(name, BAD_CAST "relation")) {
183        /* ignore */
184    } else if (xmlStrEqual(name, BAD_CAST "tag")) {
185        /* ignore */
186    } else if (xmlStrEqual(name, BAD_CAST "nd")) {
187        /* ignore */
188    } else if (xmlStrEqual(name, BAD_CAST "member")) {
189        /* ignore */
190    } else if (xmlStrEqual(name, BAD_CAST "osm")) {
191        printStatus();
192    } else if (xmlStrEqual(name, BAD_CAST "bound")) {
193        /* ignore */
[15133]194    } else if (xmlStrEqual(name, BAD_CAST "changeset")) {
195        /* ignore */
[6729]196    } else {
197        fprintf(stderr, "%s: Unknown element name: %s\n", __FUNCTION__, name);
198    }
199}
200
201static void processNode(xmlTextReaderPtr reader) {
202    xmlChar *name;
203    name = xmlTextReaderName(reader);
204    if (name == NULL)
205        name = xmlStrdup(BAD_CAST "--");
206       
207    switch(xmlTextReaderNodeType(reader)) {
208        case XML_READER_TYPE_ELEMENT:
209            StartElement(reader, name);
210            if (xmlTextReaderIsEmptyElement(reader))
211                EndElement(name); /* No end_element for self closing tags! */
212            break;
213        case XML_READER_TYPE_END_ELEMENT:
214            EndElement(name);
215            break;
216        case XML_READER_TYPE_SIGNIFICANT_WHITESPACE:
217            /* Ignore */
218            break;
219        default:
220            fprintf(stderr, "Unknown node type %d\n", xmlTextReaderNodeType(reader));
221            break;
222    }
223
224    xmlFree(name);
225}
226
227static int streamFile(char *filename) {
228    xmlTextReaderPtr reader;
229    int ret = 0;
230
231    reader = inputUTF8(filename);
232
233    if (reader != NULL) {
234        ret = xmlTextReaderRead(reader);
235        while (ret == 1) {
236            processNode(reader);
237            ret = xmlTextReaderRead(reader);
238        }
239
240        if (ret != 0) {
241            fprintf(stderr, "%s : failed to parse\n", filename);
242            return ret;
243        }
244
245        xmlFreeTextReader(reader);
246    } else {
247        fprintf(stderr, "Unable to open %s\n", filename);
248        return 1;
249    }
250    return 0;
251}
252
253void exit_nicely(void)
254{
255    fprintf(stderr, "Error occurred, cleaning up\n");
256    exit(1);
257}
258 
259static void usage(const char *arg0)
260{
261    const char *name = basename(arg0);
262
263    fprintf(stderr, "Usage:\n");
264    fprintf(stderr, "\t%s planet.osm.gz >coastline.osm\n", name);
265    fprintf(stderr, "\n");
266}
267
268int main(int argc, char *argv[])
269{
270    fprintf(stderr, "osm2coast SVN version %s $Rev: 4895 $ \n", VERSION);
271
272    if (argc != 2) {
273        usage(argv[0]);
274        exit(EXIT_FAILURE);
275    }
276   
277    nice(10);
278
279    LIBXML_TEST_VERSION
280
[20083]281    nds = malloc( sizeof(nds[0]) * (MAX_NODES_PER_WAY + 1) );
[6729]282    bitmap = calloc( MAX_NODE_ID /8 + 1, 1 );
283   
284    count_node = max_node = 0;
285    count_way = max_way = 0;
286    count_rel = max_rel = 0;
287
[7969]288    printf("<osm version=\"0.5\">\n");
[6729]289    fprintf(stderr, "\nReading in file: %s\n", argv[1]);
290    if (streamFile(argv[1]) != 0)
291        exit_nicely();
292
293    pass = 1;
294   
295    count_node = max_node = 0;
296    count_way = max_way = 0;
297    count_rel = max_rel = 0;
298
299    fprintf(stderr, "\nReading in file: %s\n", argv[1]);
300    if (streamFile(argv[1]) != 0)
301        exit_nicely();
302
[7969]303    /* Try to detect output error */
304    if( printf("</osm>\n") < 0 )
305      exit(1);
[6729]306    xmlCleanupParser();
307    xmlMemoryDump();
308
309    if (count_node || count_way || count_rel) {
310        fprintf(stderr, "\n");
311        fprintf(stderr, "Node stats: total(%d), max(%d)\n", count_node, max_node);
312        fprintf(stderr, "Way stats: total(%d), max(%d)\n", count_way, max_way);
313        fprintf(stderr, "Relation stats: total(%d), max(%d)\n", count_rel, max_rel);
314    }
315
316    return 0;
317}
318
Note: See TracBrowser for help on using the repository browser.