source: trunk/osm05.c @ 15

Last change on this file since 15 was 15, checked in by marius, 6 years ago

adding support for naming ways

  • Property svn:eol-style set to native
  • Property svn:keywords set to "Date Author Id Revision HeadURL"
  • Property svn:mime-type set to text/plain
File size: 9.2 KB
Line 
1/*
2 * Memphis - Cairo Rederer for OSM in C
3 * Copyright (C) 2008  <marius.rieder@durchmesser.ch>
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software Foundation,
17 * Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
18 */
19
20#include <time.h>
21#include <expat.h>
22#include <stdio.h>
23#include <string.h>
24
25#include "compat.h"
26
27#include "list.h"
28#include "strlist.h"
29#include "main.h"
30#include "osm05.h"
31
32#define BUFFSIZE 1024
33
34// External Vars
35extern memphisOpt   *opts;
36extern strList      *keyStrings;
37extern strList      *valStrings;
38
39// Pointers to work with
40osmTag      *cTag = NULL;
41osmNode     *cNode = NULL;
42osmNd       *cNd = NULL;
43osmWay      *cWay = NULL;
44
45// Counts
46int     cntTag = 0;
47int     cntNode = 0;
48int     cntWay = 0;
49int     cntNd = 0;
50
51/**
52 * osmStartElement:
53 * @userdata:  Void
54 * @name:  The element name
55 * @atts: The element attribs
56 *
57 * called when the start of an element has been detected.
58 */
59static void XMLCALL
60osmStartElement(void *userData, const char *name, const char **atts) {
61    osmFile *osm = (osmFile *) userData;
62     if (opts->debug > 1)
63        fprintf(stdout,"osm05startElement\n");
64    // Parsing Bounds
65    if (strncmp((char *) name, "bounds", 6) == 0) {
66        if (opts->debug > 1)
67            fprintf(stdout,"Parsing Bounds\n");
68        while (*atts != NULL) {
69            if(strcmp((char *) *(atts), "minlat" ) == 0) {
70                sscanf((char *) *(atts+1),"%f",&osm->minlat);
71            } else if(strcmp((char *) *(atts), "minlon") == 0) {
72                sscanf((char *) *(atts+1),"%f",&osm->minlon);
73            } else if(strcmp((char *) *(atts), "maxlat") == 0) {
74                sscanf((char *) *(atts+1),"%f",&osm->maxlat);
75            } else if(strcmp((char *) *(atts), "maxlon") == 0) {
76                sscanf((char *) *(atts+1),"%f",&osm->maxlon);
77            }
78            atts+=2;
79        }
80    }
81    // Parsing Node
82    else if (strncmp((char *) name, "node", 4) == 0) {
83        if (opts->debug > 1)
84            fprintf(stdout,"Parsing Node\n");
85        cntNode++;
86        cNode = malloc(sizeof(osmNode));
87        while (*atts != NULL) {
88            if(strcmp((char *) *(atts), "id") == 0) {
89                sscanf((char *) *(atts+1),"%i",&cNode->id);
90            } else if(strcmp((char *) *(atts), "lat") == 0) {
91                sscanf((char *) *(atts+1),"%f",&cNode->lat);
92            } else if(strcmp((char *) *(atts), "lon") == 0) {
93                sscanf((char *) *(atts+1),"%f",&cNode->lon);
94            }
95            atts+=2;
96       }
97
98       cNode->tag = NULL;
99       cNode->layer = 0;
100
101       // Insert Node
102       LL_INSERT_ID(cNode,osm->nodes);
103
104       if (opts->debug > 1)
105           fprintf(stdout,"NODE: %i %f %f\n", cNode->id, cNode->lat, cNode->lon);
106    }
107    // Parsing Tags
108    else if (strncmp((char *) name, "tag", 4) == 0) {
109        if (opts->debug > 1)
110            fprintf(stdout,"Parsing Tag\n");
111        cntTag++;
112        cTag = malloc(sizeof(osmTag));
113        while (*atts != NULL) {
114            if(strncmp((char *) *(atts), "k", 1) == 0) {
115                if(strcmp((char *) *(atts+1), "created_by") == 0) {
116                    free(cTag);
117                    cTag = NULL;
118                    return;
119                }
120                cTag-> key = strlist_get(keyStrings,(char *) *(atts+1));
121            } else if(strncmp((char *) *(atts), "v", 1) == 0) {
122                if(strcmp(cTag->key, "layer") == 0) {
123                    free(cTag);
124                    cTag = NULL;
125                    if (cNode)
126                        sscanf((char *) *(atts+1),"%hi",& cNode->layer);
127                    if (cWay)
128                        sscanf((char *) *(atts+1),"%hi",& cWay->layer);
129                    return;
130                } else if(strcmp(cTag->key, "name") == 0) {
131                    free(cTag);
132                    cTag = NULL;
133                    if (cWay)
134                        cWay->name = strlist_get(valStrings,(char *) *(atts+1));
135                    return;
136                }
137                cTag->value = strlist_get(valStrings,(char *) *(atts+1));
138            }
139            atts+=2;
140       }
141
142       if (opts->debug > 1)
143           fprintf(stdout,"Tag: %s => %s\n", cTag->key, cTag->value);
144
145       if (cNode)
146           LL_INSERT_KEY(cTag,cNode->tag);
147       if (cWay)
148           LL_INSERT_KEY(cTag,cWay->tag);
149
150       cTag = NULL;
151    }
152    // Parsing Way
153    else if (strncmp((char *) name, "way", 3) == 0) {
154        if (opts->debug > 1)
155            fprintf(stdout,"Parsing Way\n");
156        cntWay++;
157        cWay = malloc(sizeof(osmWay));
158        while (*atts != NULL) {
159            if(strncmp((char *) *(atts), "id", 2) == 0) {
160                sscanf((char *) *(atts+1),"%i",&cWay->id);
161                break;
162            }
163            atts+=2;
164       }
165
166       cWay->tag = NULL;
167       cWay->nd = NULL;
168       cWay->name = NULL;
169       cWay->layer = 0;
170
171       // Insert Way
172       LL_INSERT_ID(cWay,osm->ways);
173
174       if (opts->debug > 1)
175           fprintf(stdout,"WAY(%i)\n", cWay->id);
176    }
177    // Parsing WayNode
178    else if (strncmp((char *) name, "nd", 2) == 0) {
179        if (opts->debug > 1)
180            fprintf(stdout,"Parsing Nd\n");
181        cntNd++;
182        int ref = 0;
183        while (*atts != NULL) {
184            if(strncmp((char *) *(atts), "ref", 2) == 0) {
185                sscanf((char *) *(atts+1),"%i",&ref);
186                break;
187            }
188            atts+=2;
189        }
190
191        if (ref) {
192            cNd = malloc(sizeof(osmNd));
193
194            LL_SEARCH_ID(osm->nodes,ref,cNd->node);
195
196            // Insert WayNode
197            LL_APPEND(cNd,cWay->nd);
198
199            if (opts->debug > 1)
200                fprintf(stdout," ND( %f %f )\n", cNd->node->lat, cNd->node->lon);
201
202            cNode=NULL;
203            cNd = NULL;
204        }
205    }
206}
207
208
209/**
210 * osmEndElement:
211 * @userData:  Void
212 * @name:  The element name
213 *
214 * called when the end of an element has been detected.
215 */
216static void XMLCALL
217osmEndElement(void *userData, const char *name) {
218    if (opts->debug > 1)
219        fprintf(stdout,"osm05endElement\n");
220    if (strncmp((char *) name, "node", 4) == 0) {
221        cNode = NULL;
222    } else if (strncmp((char *) name, "way", 3) == 0) {
223        cWay = NULL;
224    }
225}
226
227/**
228 * rulesetRead
229 */
230osmFile* osmRead(char *filename) {
231    if (opts->debug > 1)
232        fprintf(stdout,"osmRead\n");
233
234    // Init vars
235    cntTag = 0;
236    cntNode = 0;
237    cntWay = 0;
238    cntNd = 0;
239
240    // Local Vars
241    short int i = 0;
242    char spin[] = "/-\\|";
243    int len;
244    int done;
245    char *buf;
246    osmFile *osm = NULL;
247
248    // Open file
249    FILE *fd = fopen(filename,"r");
250    if(fd == NULL) {
251        fprintf(stderr,"Error: Can't open file \"%s\"\n",filename);
252        return NULL;
253    }
254
255    osm = malloc(sizeof(osmFile));
256    osm->nodes = NULL;
257    osm->ways = NULL;
258    osm->minlon = -190;
259    osm->minlat = -190;
260    osm->maxlon = -190;
261    osm->maxlat = -190;
262
263    if (opts->debug > 0) {
264        fprintf(stdout," OSM parsing  ");
265        fflush(stdout);
266    }
267
268    long start = (long)clock();
269
270    // Create XML Parser
271    XML_Parser parser = XML_ParserCreate(NULL);
272    XML_SetElementHandler(parser, osmStartElement, osmEndElement);
273    XML_SetUserData(parser, osm);
274
275    // Create Buffer
276    buf = malloc(BUFFSIZE*sizeof(char));
277
278    // Looping over XML
279    while(!feof(fd)) {
280        fprintf(stdout,"\b%c",spin[i++]);
281        fflush(stdout);
282        i = i%4;
283        len = (int)fread(buf, 1, BUFFSIZE, fd);
284        if (ferror(fd)) {
285            fprintf(stderr, "Read error\n");
286            return NULL;;
287        }
288        done = len < sizeof(buf);
289        if (XML_Parse(parser, buf, len, done) == XML_STATUS_ERROR) {
290            fprintf(stderr, "Parse error at line %iu:\n%s\n",
291                (int) XML_GetCurrentLineNumber(parser),
292                XML_ErrorString(XML_GetErrorCode(parser)));
293            exit(-1);
294        }
295    }
296
297    // Cleaning Memory
298    XML_ParserFree(parser);
299    free(buf);
300    fclose(fd);
301
302    // No bounds set
303    if(osm->minlon == -190 || osm->minlat == -190 ||
304       osm->maxlon == -190 || osm->maxlat == -190) {
305
306        osm->minlon = osm->nodes->lon;
307        osm->minlat = osm->nodes->lat;
308        osm->maxlon = osm->nodes->lon;
309        osm->maxlat = osm->nodes->lat;
310
311        osmNode *node;
312        LIST_FOREACH(node, osm->nodes) {
313            if(node->lon < osm->minlon)
314                osm->minlon = node->lon;
315            if(node->lat < osm->minlat)
316                osm->minlat = node->lat;
317            if(node->lon > osm->maxlon)
318                osm->maxlon = node->lon;
319            if(node->lat > osm->maxlat)
320                osm->maxlat = node->lat;
321        }
322    }
323
324    if (opts->debug > 0)
325        fprintf(stdout,"\r OSM parsing done. (%i/%i/%i/%i) [%fs]\n",
326                cntNode, cntWay, cntTag, cntNd,
327                ((long)clock()-start)/(double)CLOCKS_PER_SEC);
328
329    return(osm);
330}
331
332/*
333 * vim: expandtab shiftwidth=4 tabstop=4:
334 */
335
Note: See TracBrowser for help on using the repository browser.