wiki:LibMemphis

Version 57 (modified by simon, 4 years ago) (diff)

use c code highlighting

LibMemphis

Libmemphis is a generic glib/cairo based OSM renderer library. It draws maps on arbitrary cairo surfaces.

Code: source:trunk

svn co https://svn.openstreetmap.ch/svn/memphis/trunk memphis
./autogen.sh
make
sudo make install

If you want to enable very verbose debug messages use:

./configure --enable-debug

Example application:

cd demos
./tile-renderer
or
./tile-renderer <zoom level> <map file>

Renders the file map.osm to png tiles (into the folder demos/tiles).

Usage

Compiling a project that uses libmemphis is simple. Make sure that you installed pkg-config.

gcc your-app.c -o your-app `pkg-config --cflags --libs memphis-0.1`

API

Header:

#include <memphis/memphis.h>

Class MemphisRenderer:

The tile renderer implements the 'Slippy Map Tilename' specification, like Mapnik and Osmarender. It supports zoom level 12 to 18, projected with the Mercator projection. Every level has 2zoom level images in x and y direction (enumarated from 0 to 2zoom level-1). Tiles without data are rendered filled with the background color of the map.

MemphisRenderer* memphis_renderer_new ();
MemphisRenderer* memphis_renderer_new_full (MemphisRuleSet *rules, MemphisMap *map);
void memphis_renderer_free (MemphisRenderer *r);

void memphis_renderer_set_rule_set (MemphisRenderer *r, MemphisRuleSet *rules);
MemphisRuleSet* memphis_renderer_get_rule_set (MemphisRenderer *r);

void memphis_renderer_set_map (MemphisRenderer *r, MemphisMap *map);
MemphisMap* memphis_renderer_get_map (MemphisRenderer *r);

void memphis_renderer_set_resolution (MemphisRenderer *r, guint resolution);
guint memphis_renderer_get_resolution (MemphisRenderer *r);

void memphis_renderer_draw_png (MemphisRenderer *r, gchar *filename, guint zoom_level); // emulates the old behavior, will be removed someday
void memphis_renderer_draw_tile (MemphisRenderer *r,
    cairo_t *cr, 
    guint x, 
    guint y, 
    guint zoom_level);

gint memphis_renderer_get_row_count (MemphisRenderer *renderer, guint zoom_level);
gint memphis_renderer_get_column_count (MemphisRenderer *renderer, guint zoom_level);
gint memphis_renderer_get_min_x_tile (MemphisRenderer *renderer, guint zoom_level);
gint memphis_renderer_get_max_x_tile (MemphisRenderer *renderer, guint zoom_level);
gint memphis_renderer_get_min_y_tile (MemphisRenderer *renderer, guint zoom_level);
gint memphis_renderer_get_max_y_tile (MemphisRenderer *renderer, guint zoom_level);
gboolean memphis_renderer_tile_has_data (MemphisRenderer *renderer, guint x, guint y, guint zoom_level);

Class MemphisMap:

MemphisMap* memphis_map_new ();
void memphis_map_free (MemphisMap *map);

void memphis_map_load_from_file (MemphisMap *map, const gchar *filename);
void memphis_map_load_from_data (MemphisMap *map, const gchar *data, guint size);

void memhis_map_get_bounding_box (MemphisMap *map, 
    gdouble *minlat, gdouble *minlon,
    gdouble *maxlat, gdouble *maxlon);

Class MemphisRuleSet:

MemphisRuleSet* memphis_rule_set_new ();
void memphis_rule_set_free (MemphisRuleSet *rules);

void memphis_rule_set_load_from_file (MemphisRuleSet *rules, const gchar *filename);
void memphis_rule_set_load_from_data (MemphisRuleSet *rules, const gchar *data, guint size);

void memphis_rule_set_set_bg_color (MemphisRuleSet *rules,
    guint8 r,
    guint8 g,
    guint8 b,
    guint8 a);
void memphis_rule_set_get_bg_color (MemphisRuleSet *self,
    guint8 *r, 
    guint8 *g, 
    guint8 *b,
    guint8 *a);

/* returns a list of rule id strings of the form: key1|key2|...|keyN:value1|value2|...|valueM 
   Example: "waterway:river|stream|canal"
*/
GList* memphis_rule_set_get_rule_ids (MemphisRuleSet *rules);

void memphis_rule_set_set_rule (MemphisRuleSet *rules, MemphisRule *rule);
MemphisRule* memphis_rule_set_get_rule (MemphisRuleSet *rules, const gchar *id);
gboolean memphis_rule_set_remove_rule (MemphisRuleSet *rules, const gchar *id);

Boxed struct MemphisRule:

typedef enum {
  MEMPHIS_RULE_TYPE_UNKNOWN,
  MEMPHIS_RULE_TYPE_NODE,
  MEMPHIS_RULE_TYPE_WAY,
  MEMPHIS_RULE_TYPE_RELATION
} MemphisRuleType;

typedef struct {
  guint8 z_min;
  guint8 z_max;
  guint8 color_red;
  guint8 color_green;
  guint8 color_blue;
  guint8 color_alpha;
  gchar *style;
  gdouble size;
} MemphisRuleAttr;

typedef struct {
  gchar **keys;
  gchar **values;
  MemphisRuleType type;
  MemphisRuleAttr *polygon;
  MemphisRuleAttr *line;
  MemphisRuleAttr *border;
  MemphisRuleAttr *text;
} MemphisRule;

MemphisRule * memphis_rule_new ();
MemphisRule * memphis_rule_copy (const MemphisRule *rule);
void memphis_rule_free (MemphisRule *rule);

Class MemphisDataPool:

A singleton that provides a shared pool of efficient memory (i.e. a GStringChunk and a GTree for strings).

MemphisDataPool* memphis_data_pool_new ();

Debugging helper functions:

memphis-debug messages can be enabled with ./configure --enable-debug.

void memphis_debug (const gchar *format, ...);
void memphis_info (const gchar *format, ...);

void memphis_debug_set_print_progress (gboolean show_progress);
gboolean memphis_debug_get_print_progress ();

Done

  • Relicense all code as LGPL.
  • Remove all global variables.
  • Make it more thread safe.
  • Create a GObject based API.
  • Add zoom level 18 support.
  • Add capability to query and edit rules.
  • Autotools based build system.
  • Unit tests for the API (tests/unit-tests or 'make check').
  • New debug level infrastructure. (ticket #16)

Roadmap

  • Code cleanup
  • Create autogenerated documentation and example client code.

Issues

  • Parsing maps and rules is not thread safe because of the shared MemphisDataPool.
  • Code is scatterd between new and old files. In my opinion, all code should be moved into the class files one day.
  • Some data structures should be merged with the classes. e.g. osmFile, cfgRules.