Changeset 141 for trunk/osm05.c


Ignore:
Timestamp:
Oct 16, 2009, 12:25:53 AM (5 years ago)
Author:
simon
Message:

Merge the 'client-library-split' branch into trunk

New Features:

  • Split the project into a library and a client
  • Relicense all code as LGPL
  • Remove all global variables
  • Make most functions thread-safe (Exceptions: parsing maps and rules)
  • Add a GObject based API
  • Add zoom level 18 support
  • Add capability to query and edit rules

Note: This code was created during the Google Summer of Code 2009.

Location:
trunk
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • trunk

  • trunk/osm05.c

    r57 r141  
    11/* 
    22 * Memphis - Cairo Rederer for OSM in C 
    3  * Copyright (C) 2008  <marius.rieder@durchmesser.ch> 
     3 * Copyright (C) 2008  Marius Rieder <marius.rieder@durchmesser.ch> 
    44 * 
    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. 
     5 * This library is free software; you can redistribute it and/or 
     6 * modify it under the terms of the GNU Lesser General Public 
     7 * License as published by the Free Software Foundation; either 
     8 * version 2.1 of the License, or (at your option) any later version. 
    99 * 
    10  * This program is distributed in the hope that it will be useful, 
     10 * This library is distributed in the hope that it will be useful, 
    1111 * 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. 
     12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU 
     13 * Lesser General Public License for more details. 
    1414 * 
    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. 
     15 * You should have received a copy of the GNU Lesser General Public 
     16 * License along with this library; if not, write to the Free Software 
     17 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA 
    1818 */ 
     19 
    1920#include <glib.h> 
    2021#include <glib/gstdio.h> 
    21  
    2222#include <time.h> 
    2323#include <expat.h> 
    24 #include <stdio.h> 
    2524#include <string.h> 
    2625 
    2726#include "list.h" 
    2827#include "mlib.h" 
    29 #include "main.h" 
    3028#include "osm05.h" 
     29#include "memphis-data-pool.h" 
    3130 
    3231#define BUFFSIZE 1024 
    3332 
    34 // External Vars 
    35 extern memphisOpt   *opts; 
    36 extern GStringChunk *stringChunk; 
    37 extern GTree        *stringTree; 
    38  
    39 // Pointers to work with 
    40 osmTag      *cTag = NULL; 
    41 osmNode     *cNode = NULL; 
    42 osmWay      *cWay = NULL; 
    43  
    44 // Counts 
    45 int     cntTag = 0; 
    46 int     cntNd = 0; 
     33typedef struct mapUserData_ mapUserData; 
     34struct mapUserData_ { 
     35  // Pointers to work with 
     36  osmTag *cTag; 
     37  osmNode *cNode; 
     38  osmWay *cWay; 
     39  MemphisDataPool *pool; 
     40  // Collected Data 
     41  osmFile *osm; 
     42  // Counts (used for debugging only!) 
     43  int cntTag; 
     44  int cntNd; 
     45  gint8 debug_level; 
     46}; 
    4747 
    4848/** 
     
    5656static void XMLCALL 
    5757osmStartElement(void *userData, const char *name, const char **atts) { 
    58     osmFile *osm = (osmFile *) userData; 
    59      if (opts->debug > 1) 
    60         fprintf(stdout,"osm05startElement\n"); 
     58    mapUserData *data = (mapUserData *) userData; 
     59    osmFile *osm = data->osm; 
     60    GStringChunk *stringChunk = data->pool->stringChunk; 
     61    GTree *stringTree = data->pool->stringTree; 
     62    gint8 debug_level = data->debug_level; 
     63     
     64    if (debug_level > 1) 
     65        g_fprintf (stdout, "osm05startElement\n"); 
    6166    // Parsing Bounds 
    6267    if (strncmp((char *) name, "bounds", 6) == 0) { 
    63         if (opts->debug > 1) 
    64             fprintf(stdout,"Parsing Bounds\n"); 
     68        if (debug_level > 1) 
     69            g_fprintf (stdout, "Parsing Bounds\n"); 
    6570        while (*atts != NULL) { 
    6671            if(strcmp((char *) *(atts), "minlat" ) == 0) { 
     
    7883    // Parsing Node 
    7984    else if (strncmp((char *) name, "node", 4) == 0) { 
    80         if (opts->debug > 1) 
    81             fprintf(stdout,"Parsing Node\n"); 
    82         cNode = g_new(osmNode, 1); 
     85        if (debug_level > 1) 
     86            g_fprintf (stdout, "Parsing Node\n"); 
     87        data->cNode = g_new(osmNode, 1); 
    8388        while (*atts != NULL) { 
    8489            if(strcmp((char *) *(atts), "id") == 0) { 
    85                 sscanf((char *) *(atts+1),"%i",&cNode->id); 
     90                sscanf((char *) *(atts+1),"%i",&data->cNode->id); 
    8691            } else if(strcmp((char *) *(atts), "lat") == 0) { 
    87                 sscanf((char *) *(atts+1),"%f",&cNode->lat); 
     92                sscanf((char *) *(atts+1),"%f",&data->cNode->lat); 
    8893            } else if(strcmp((char *) *(atts), "lon") == 0) { 
    89                 sscanf((char *) *(atts+1),"%f",&cNode->lon); 
     94                sscanf((char *) *(atts+1),"%f",&data->cNode->lon); 
    9095            } 
    9196            atts+=2; 
    9297        } 
    9398 
    94         cNode->tag = NULL; 
    95         cNode->layer = 0; 
     99        data->cNode->tag = NULL; 
     100        data->cNode->layer = 0; 
    96101 
    97102        // Insert Node 
    98103        osm->nodecnt++; 
    99         g_hash_table_insert(osm->nodeidx, &cNode->id, cNode); 
    100         LL_PREPEND(cNode,osm->nodes); 
    101  
    102         if (opts->debug > 1) 
    103             fprintf(stdout,"NODE: %i %f %f\n", cNode->id, cNode->lat, cNode->lon); 
     104        g_hash_table_insert(osm->nodeidx, &data->cNode->id, data->cNode); 
     105        LL_PREPEND(data->cNode, osm->nodes); 
     106 
     107        if (debug_level > 1) 
     108            g_fprintf (stdout, "NODE: %i %f %f\n", data->cNode->id, 
     109                    data->cNode->lat, data->cNode->lon); 
    104110    } 
    105111    // Parsing Tags 
    106112    else if (strncmp((char *) name, "tag", 4) == 0) { 
    107         if (opts->debug > 1) 
    108             fprintf(stdout,"Parsing Tag\n"); 
    109  
    110         if (!cNode && !cWay) // End if ther is nothing to add the tag to 
     113        if (debug_level > 1) 
     114            g_fprintf (stdout, "Parsing Tag\n"); 
     115 
     116        if (!data->cNode && !data->cWay) // End if there is nothing to add the tag to 
    111117            return; 
    112118             
     
    123129            } else if(strncmp((char *) *(atts), "v", 1) == 0) { 
    124130                if(strcmp(k, "layer") == 0) { 
    125                     if (cNode) 
    126                         sscanf((char *) *(atts+1),"%hi",& cNode->layer); 
    127                     else if (cWay) 
    128                         sscanf((char *) *(atts+1),"%hi",& cWay->layer); 
     131                    if (data->cNode) 
     132                        sscanf((char *) *(atts+1),"%hi",& data->cNode->layer); 
     133                    else if (data->cWay) 
     134                        sscanf((char *) *(atts+1),"%hi",& data->cWay->layer); 
    129135                    return; 
    130136                } else if(strcmp(k, "name") == 0) { 
    131                     if (cWay) { 
    132                         cWay->name = m_string_chunk_get(stringChunk, stringTree,  
     137                    if (data->cWay) { 
     138                        data->cWay->name = m_string_chunk_get(stringChunk, stringTree,  
    133139                                                        (char *) *(atts+1)); 
    134140                    } 
     
    140146        } 
    141147         
    142         cTag = g_new(osmTag, 1); 
    143         cTag->key = m_string_chunk_get(stringChunk, stringTree, k); 
    144         cTag->value = m_string_chunk_get(stringChunk, stringTree, v); 
     148        data->cTag = g_new(osmTag, 1); 
     149        data->cTag->key = m_string_chunk_get(stringChunk, stringTree, k); 
     150        data->cTag->value = m_string_chunk_get(stringChunk, stringTree, v); 
    145151         
    146         if (opts->debug > 1) 
    147             fprintf(stdout,"Tag: %s => %s\n", cTag->key, cTag->value); 
    148  
    149         cntTag++; 
    150         if (cNode) 
    151             LL_INSERT_KEY(cTag,cNode->tag); 
    152         else if (cWay) 
    153             LL_INSERT_KEY(cTag,cWay->tag); 
    154  
    155         cTag = NULL; 
     152        if (debug_level > 1) 
     153            g_fprintf (stdout, "Tag: %s => %s\n", data->cTag->key, data->cTag->value); 
     154 
     155        data->cntTag++; 
     156        if (data->cNode) 
     157            LL_INSERT_KEY(data->cTag, data->cNode->tag); 
     158        else if (data->cWay) 
     159            LL_INSERT_KEY(data->cTag, data->cWay->tag); 
     160 
     161        data->cTag = NULL; 
    156162    } 
    157163    // Parsing Way 
    158164    else if (strncmp((char *) name, "way", 3) == 0) { 
    159         if (opts->debug > 1) 
    160             fprintf(stdout,"Parsing Way\n"); 
    161         cWay = g_new(osmWay, 1); 
     165        if (debug_level > 1) 
     166            g_fprintf (stdout, "Parsing Way\n"); 
     167        data->cWay = g_new(osmWay, 1); 
    162168        while (*atts != NULL) { 
    163169            if(strncmp((char *) *(atts), "id", 2) == 0) { 
    164                 sscanf((char *) *(atts+1),"%i",&cWay->id); 
     170                sscanf((char *) *(atts+1), "%i", &data->cWay->id); 
    165171                break; 
    166172            } 
     
    168174        } 
    169175 
    170         cWay->tag = NULL; 
    171         cWay->nd = NULL; 
    172         cWay->name = NULL; 
    173         cWay->layer = 0; 
     176        data->cWay->tag = NULL; 
     177        data->cWay->nd = NULL; 
     178        data->cWay->name = NULL; 
     179        data->cWay->layer = 0; 
    174180 
    175181        // Insert Way 
    176182        osm->waycnt++; 
    177         LL_PREPEND(cWay,osm->ways); 
    178  
    179         if (opts->debug > 1) 
    180             fprintf(stdout,"WAY(%i)\n", cWay->id); 
     183        LL_PREPEND(data->cWay, osm->ways); 
     184 
     185        if (debug_level > 1) 
     186            g_fprintf (stdout, "WAY(%i)\n", data->cWay->id); 
    181187    } 
    182188    // Parsing WayNode 
    183189    else if (strncmp((char *) name, "nd", 2) == 0) { 
    184         if (opts->debug > 1) 
    185             fprintf(stdout,"Parsing Nd\n"); 
     190        if (debug_level > 1) 
     191            g_fprintf (stdout, "Parsing Nd\n"); 
    186192        int ref = 0; 
    187193        while (*atts != NULL) { 
     
    194200 
    195201        if (ref) { 
    196             cntNd++; 
     202            data->cntNd++; 
    197203            osmNode *n; 
    198204             
     
    204210 
    205211            // Insert WayNode 
    206             cWay->nd = g_slist_prepend(cWay->nd, n); 
    207  
    208             if (opts->debug > 1) 
    209                 fprintf(stdout," ND( %f %f )\n", n->lat, n->lon); 
    210  
    211             cNode=NULL; 
     212            data->cWay->nd = g_slist_prepend(data->cWay->nd, n); 
     213 
     214            if (debug_level > 1) 
     215                g_fprintf (stdout, " ND( %f %f )\n", n->lat, n->lon); 
     216 
     217            data->cNode = NULL; 
    212218        } 
    213219    } 
     
    224230static void XMLCALL 
    225231osmEndElement(void *userData, const char *name) { 
    226     if (opts->debug > 1) 
    227         fprintf(stdout,"osm05endElement\n"); 
     232    mapUserData *data = (mapUserData *) userData; 
     233    gint8 debug_level = data->debug_level; 
     234     
     235    if (debug_level > 1) 
     236        g_fprintf(stdout, "osm05endElement\n"); 
    228237    if (strncmp((char *) name, "node", 4) == 0) { 
    229         cNode = NULL; 
     238        data->cNode = NULL; 
    230239    } else if (strncmp((char *) name, "way", 3) == 0) { 
    231         if (cWay->nd != NULL) 
    232             cWay->nd = g_slist_reverse(cWay->nd); 
    233         cWay = NULL; 
     240        if (data->cWay->nd != NULL) 
     241            data->cWay->nd = g_slist_reverse(data->cWay->nd); 
     242        data->cWay = NULL; 
    234243    } 
    235244} 
     
    238247 * rulesetRead 
    239248 */ 
    240 osmFile* osmRead(char *filename) { 
    241     if (opts->debug > 1) 
    242         fprintf(stdout,"osmRead\n"); 
    243  
    244     // Init vars 
    245     cntTag = 0; 
    246     cntNd = 0; 
     249osmFile* osmRead(const char *filename, gint8 debug_level) { 
     250    if (debug_level > 1) 
     251        g_fprintf (stdout, "osmRead\n"); 
    247252 
    248253    // Local Vars 
     
    254259    int done; 
    255260    char *buf; 
    256     osmFile *osm = NULL; 
     261    osmFile *osm; 
     262    mapUserData *data; 
    257263     
    258264    // Test file 
    259265    if (!g_file_test (filename, G_FILE_TEST_IS_REGULAR)) { 
    260         fprintf(stderr,"Error: \"%s\" is not a file.\n",filename); 
     266        g_critical ("Error: \"%s\" is not a file.\n", filename); 
    261267        return NULL; 
    262268    } 
     
    268274    FILE *fd = fopen(filename,"r"); 
    269275    if(fd == NULL) { 
    270         fprintf(stderr,"Error: Can't open file \"%s\"\n",filename); 
     276        g_critical ("Error: Can't open file \"%s\"\n", filename); 
    271277        return NULL; 
    272278    } 
     279 
     280    // Init vars 
     281    data = g_new(mapUserData, 1); 
     282    data->cTag = NULL; 
     283    data->cNode = NULL; 
     284    data->cWay = NULL; 
     285    data->pool = memphis_data_pool_new (); 
     286    data->cntTag = 0; 
     287    data->cntNd = 0; 
     288    data->debug_level = debug_level; 
    273289 
    274290    osm = g_new(osmFile, 1); 
     
    282298    osm->maxlon = -190; 
    283299    osm->maxlat = -190; 
    284  
    285     if (opts->debug > 0) { 
    286         fprintf(stdout," OSM parsing   0%%"); 
     300    data->osm = osm; 
     301 
     302    if (debug_level > 0) { 
     303        g_fprintf (stdout, " OSM parsing   0%%"); 
    287304        fflush(stdout); 
    288305    } 
     
    291308    XML_Parser parser = XML_ParserCreate(NULL); 
    292309    XML_SetElementHandler(parser, osmStartElement, osmEndElement); 
    293     XML_SetUserData(parser, osm); 
     310    XML_SetUserData(parser, data); 
    294311 
    295312    // Create Buffer 
     
    300317        len = (int)fread(buf, 1, BUFFSIZE, fd); 
    301318        if (ferror(fd)) { 
    302             fprintf(stderr, "Read error\n"); 
    303             return NULL;; 
     319            g_fprintf (stderr, "Read error\n"); 
     320            return NULL; 
    304321        } 
    305322        read += len; 
    306         if (opts->debug > 0) { 
    307             fprintf(stdout,"\r OSM parsing % 3i%%", (int)((read*100)/size)); 
     323        if (debug_level > 0) { 
     324            g_fprintf (stdout, "\r OSM parsing % 3i%%", (int)((read*100)/size)); 
    308325            fflush(stdout); 
    309326        } 
    310327        done = len < sizeof(buf); 
    311328        if (XML_Parse(parser, buf, len, done) == XML_STATUS_ERROR) { 
    312             fprintf(stderr, "Parse error at line %iu:\n%s\n", 
     329            g_fprintf (stderr, "Parse error at line %iu:\n%s\n", 
    313330                (int) XML_GetCurrentLineNumber(parser), 
    314331                XML_ErrorString(XML_GetErrorCode(parser))); 
     
    345362 
    346363    g_hash_table_destroy(osm->nodeidx); 
    347     osm->nodeidx=NULL; 
    348      
    349     if (opts->debug > 0) 
     364    osm->nodeidx = NULL; 
     365     
     366    if (debug_level > 0) 
    350367        fprintf(stdout,"\r OSM parsing done. (%i/%i/%i/%i) [%fs]\n", 
    351                 osm->nodecnt, osm->waycnt, cntTag, cntNd, 
     368                osm->nodecnt, osm->waycnt, data->cntTag, data->cntNd, 
    352369                g_timer_elapsed(tOsmRead,NULL)); 
    353370     
    354371    g_timer_destroy(tOsmRead); 
     372    g_free(data); 
    355373 
    356374    return(osm); 
     375} 
     376 
     377osmFile* osmRead_from_buffer (const char *buffer, guint size, gint8 debug_level) { 
     378    if (debug_level > 1) 
     379        g_fprintf (stdout, "osmRead\n"); 
     380 
     381    g_assert (buffer != NULL && size > 0); 
     382 
     383    // Local Vars 
     384    GTimer *tOsmRead = g_timer_new(); 
     385    int isDone = 0; 
     386    osmFile *osm; 
     387    mapUserData *data; 
     388 
     389    // Init vars 
     390    data = g_new(mapUserData, 1); 
     391    data->cTag = NULL; 
     392    data->cNode = NULL; 
     393    data->cWay = NULL; 
     394    data->pool = memphis_data_pool_new (); 
     395    data->cntTag = 0; 
     396    data->cntNd = 0; 
     397    data->debug_level = debug_level; 
     398 
     399    osm = g_new(osmFile, 1); 
     400    osm->nodes = NULL; 
     401    osm->nodeidx = g_hash_table_new(g_int_hash, g_int_equal); 
     402    osm->nodecnt = 0; 
     403    osm->ways = NULL; 
     404    osm->waycnt = 0; 
     405    osm->minlon = -190; 
     406    osm->minlat = -190; 
     407    osm->maxlon = -190; 
     408    osm->maxlat = -190; 
     409 
     410    data->osm = osm; 
     411 
     412    if (debug_level > 0) { 
     413        g_fprintf (stdout, " OSM parsing   0%%"); 
     414        fflush(stdout); 
     415    } 
     416 
     417    // Create XML Parser 
     418    XML_Parser parser = XML_ParserCreate(NULL); 
     419    XML_SetElementHandler(parser, osmStartElement, osmEndElement); 
     420    XML_SetUserData(parser, data); 
     421 
     422    // Parse the buffer 
     423    if (XML_Parse (parser, buffer, size, isDone) == XML_STATUS_ERROR) { 
     424        g_fprintf (stderr, "Parse error at line %iu:\n%s\n", 
     425            (int) XML_GetCurrentLineNumber(parser), 
     426            XML_ErrorString(XML_GetErrorCode(parser))); 
     427        exit (-1); 
     428    } 
     429 
     430    // Cleaning Memory 
     431    XML_ParserFree(parser); 
     432 
     433    // No bounds set 
     434    if(osm->minlon == -190 || osm->minlat == -190 || 
     435        osm->maxlon == -190 || osm->maxlat == -190) { 
     436 
     437        osm->minlon = 360.0; 
     438        osm->minlat = 180.0; 
     439        osm->maxlon = -360.0; 
     440        osm->maxlat = -180.0; 
     441 
     442        osmNode *node; 
     443        LIST_FOREACH(node, osm->nodes) { 
     444            if(node->lon < osm->minlon) 
     445                osm->minlon = node->lon; 
     446            if(node->lat < osm->minlat) 
     447                osm->minlat = node->lat; 
     448            if(node->lon > osm->maxlon) 
     449                osm->maxlon = node->lon; 
     450            if(node->lat > osm->maxlat) 
     451                osm->maxlat = node->lat; 
     452        } 
     453    } 
     454 
     455    g_hash_table_destroy(osm->nodeidx); 
     456    osm->nodeidx = NULL; 
     457     
     458    if (debug_level > 0) 
     459        fprintf(stdout,"\r OSM parsing done. (%i/%i/%i/%i) [%fs]\n", 
     460                osm->nodecnt, osm->waycnt, data->cntTag, data->cntNd, 
     461                g_timer_elapsed(tOsmRead,NULL)); 
     462     
     463    g_timer_destroy(tOsmRead); 
     464 
     465    return osm; 
    357466} 
    358467 
     
    398507    g_free(lnode); 
    399508    g_free(osm); 
    400 }; 
     509} 
    401510 
    402511/* 
Note: See TracChangeset for help on using the changeset viewer.