Diff of /trunk/src/map.c

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

revision 154 by harbaum, Tue Mar 31 06:31:53 2009 UTC revision 234 by harbaum, Mon Jul 20 20:15:10 2009 UTC
# Line 55  static void map_statusbar(map_t *map, ma Line 55  static void map_statusbar(map_t *map, ma
55    
56    gboolean collision = FALSE;    gboolean collision = FALSE;
57    tag_t *tags = tag;    tag_t *tags = tag;
58      while(tag) {
59    if(id == ID_ILLEGAL)      if(!collision && info_tag_key_collision(tags, tag))
60      str = g_strdup_printf(_("Unknown item"));        collision = TRUE;
61    else {      tag = tag->next;
     str = g_strdup_printf("%s #%ld", item_str, id);  
   
     /* add some tags ... */  
     /*  
      *  XXX Should we just try to present only the name or the ref (or the  
      *  alt_name, old_name, whatever) here?  Hurling a load of tags in the  
      *  user's face in some unpredictable, uninformative order isn't very  
      *  friendly.  
      *  
      *  Actually, a tag_short_desc() function would be useful in dialogs  
      *  nd user messages too.  
      */  
     while(tag) {  
       if(!collision && info_tag_key_collision(tags, tag))  
         collision = TRUE;  
   
       /* we don't have much space, so ignore created_by tag */  
       if(!osm_is_creator_tag(tag)) {  
         char *old = str;  
         str = g_strdup_printf("%s, %s=%s", old, tag->key, tag->value);  
         g_free(old);  
       }  
       tag = tag->next;  
     }  
62    }    }
63    
64      str = osm_object_get_speaking_name(&map_item->object);
65    statusbar_set(map->appdata, str, collision);    statusbar_set(map->appdata, str, collision);
66    g_free(str);    g_free(str);
67  }  }
# Line 167  static void map_node_select(appdata_t *a Line 144  static void map_node_select(appdata_t *a
144      gint h = gdk_pixbuf_get_height(map_item->object.node->icon_buf);      gint h = gdk_pixbuf_get_height(map_item->object.node->icon_buf);
145      /* icons are technically square, so a radius slightly bigger */      /* icons are technically square, so a radius slightly bigger */
146      /* than sqrt(2)*MAX(w,h) should fit nicely */      /* than sqrt(2)*MAX(w,h) should fit nicely */
147      radius =  0.75 * map->style->icon.scale * ((w>h)?w:h);      radius = 0.75 * map->style->icon.scale * ((w>h)?w:h);
148    }    }
149    
150      radius *= map->state->detail;
151    map_hl_circle_new(map, CANVAS_GROUP_NODES_HL, new_map_item,    map_hl_circle_new(map, CANVAS_GROUP_NODES_HL, new_map_item,
152                      x, y, radius, map->style->highlight.color);                      x, y, radius, map->style->highlight.color);
153    
# Line 198  void map_way_select(appdata_t *appdata, Line 176  void map_way_select(appdata_t *appdata,
176    map_statusbar(map, map_item);    map_statusbar(map, map_item);
177    icon_bar_map_item_selected(appdata, map_item, TRUE);    icon_bar_map_item_selected(appdata, map_item, TRUE);
178    gtk_widget_set_sensitive(appdata->menu_item_map_hide_sel, TRUE);    gtk_widget_set_sensitive(appdata->menu_item_map_hide_sel, TRUE);
179    
180    gint arrow_width = (map_item->object.way->draw.flags & OSM_DRAW_FLAG_BG)?    gint arrow_width = ((map_item->object.way->draw.flags & OSM_DRAW_FLAG_BG)?
181      map->style->highlight.width + map_item->object.way->draw.bg.width/2:                        map->style->highlight.width + map_item->object.way->draw.bg.width/2:
182      map->style->highlight.width + map_item->object.way->draw.width/2;                        map->style->highlight.width + map_item->object.way->draw.width/2)
183        * map->state->detail;
184    
185    node_chain_t *node_chain = map_item->object.way->node_chain;    node_chain_t *node_chain = map_item->object.way->node_chain;
186    node_t *last = NULL;    node_t *last = NULL;
# Line 259  void map_way_select(appdata_t *appdata, Line 238  void map_way_select(appdata_t *appdata,
238        gint y = node_chain->node->lpos.y;        gint y = node_chain->node->lpos.y;
239    
240        map_hl_circle_new(map, CANVAS_GROUP_NODES_IHL, new_map_item,        map_hl_circle_new(map, CANVAS_GROUP_NODES_IHL, new_map_item,
241                          x, y, map->style->node.radius,                          x, y, map->style->node.radius * map->state->detail,
242                          map->style->highlight.node_color);                          map->style->highlight.node_color);
243      }      }
244    
# Line 287  void map_way_select(appdata_t *appdata, Line 266  void map_way_select(appdata_t *appdata,
266      new_map_item->highlight = TRUE;      new_map_item->highlight = TRUE;
267    
268      map_hl_polyline_new(map, CANVAS_GROUP_WAYS_HL, new_map_item, points,      map_hl_polyline_new(map, CANVAS_GROUP_WAYS_HL, new_map_item, points,
269                  (map_item->object.way->draw.flags & OSM_DRAW_FLAG_BG)?                   ((map_item->object.way->draw.flags & OSM_DRAW_FLAG_BG)?
270                  2*map->style->highlight.width + map_item->object.way->draw.bg.width:                   2*map->style->highlight.width + map_item->object.way->draw.bg.width:
271                  2*map->style->highlight.width + map_item->object.way->draw.width,                   2*map->style->highlight.width + map_item->object.way->draw.width)
272                  map->style->highlight.color);                  * map->state->detail, map->style->highlight.color);
273    
274      canvas_points_free(points);      canvas_points_free(points);
275    }    }
276  }  }
# Line 299  void map_way_select(appdata_t *appdata, Line 278  void map_way_select(appdata_t *appdata,
278  void map_relation_select(appdata_t *appdata, relation_t *relation) {  void map_relation_select(appdata_t *appdata, relation_t *relation) {
279    map_t *map = appdata->map;    map_t *map = appdata->map;
280    
281    printf("highlighting relation %ld\n", relation->id);    printf("highlighting relation "ITEM_ID_FORMAT"\n", relation->id);
282    
283    g_assert(!map->highlight);    g_assert(!map->highlight);
284    map_highlight_t **hl = &map->highlight;    map_highlight_t **hl = &map->highlight;
# Line 318  void map_relation_select(appdata_t *appd Line 297  void map_relation_select(appdata_t *appd
297    while(member) {    while(member) {
298      canvas_item_t *item = NULL;      canvas_item_t *item = NULL;
299    
300      switch(member->type) {      switch(member->object.type) {
301    
302      case NODE: {      case NODE: {
303        node_t *node = member->node;        node_t *node = member->object.node;
304        printf("  -> node %ld\n", node->id);        printf("  -> node "ITEM_ID_FORMAT"\n", node->id);
305    
306        item = canvas_circle_new(map->canvas, CANVAS_GROUP_NODES_HL,        item = canvas_circle_new(map->canvas, CANVAS_GROUP_NODES_HL,
307                          node->lpos.x, node->lpos.y,                          node->lpos.x, node->lpos.y,
# Line 331  void map_relation_select(appdata_t *appd Line 310  void map_relation_select(appdata_t *appd
310        } break;        } break;
311    
312      case WAY: {      case WAY: {
313        way_t *way = member->way;        way_t *way = member->object.way;
314        /* a way needs at least 2 points to be drawn */        /* a way needs at least 2 points to be drawn */
315        guint nodes = osm_way_number_of_nodes(way);        guint nodes = osm_way_number_of_nodes(way);
316        if(nodes > 1) {        if(nodes > 1) {
# Line 400  void map_item_deselect(appdata_t *appdat Line 379  void map_item_deselect(appdata_t *appdat
379        osm_tags_free(appdata->map->last_node_tags);        osm_tags_free(appdata->map->last_node_tags);
380    
381      appdata->map->last_node_tags =      appdata->map->last_node_tags =
382        osm_tags_copy(appdata->map->selected.object.node->tag, FALSE);        osm_tags_copy(appdata->map->selected.object.node->tag);
383    } else if(appdata->map->selected.object.type == WAY) {    } else if(appdata->map->selected.object.type == WAY) {
384      if(appdata->map->last_way_tags)      if(appdata->map->last_way_tags)
385        osm_tags_free(appdata->map->last_way_tags);        osm_tags_free(appdata->map->last_way_tags);
386    
387      appdata->map->last_way_tags =      appdata->map->last_way_tags =
388        osm_tags_copy(appdata->map->selected.object.way->tag, FALSE);        osm_tags_copy(appdata->map->selected.object.way->tag);
389    }    }
390    
391    /* remove statusbar message */    /* remove statusbar message */
# Line 472  static canvas_item_t *map_node_new(map_t Line 451  static canvas_item_t *map_node_new(map_t
451    else    else
452      map_item->item = canvas_image_new(map->canvas, CANVAS_GROUP_NODES,      map_item->item = canvas_image_new(map->canvas, CANVAS_GROUP_NODES,
453        node->icon_buf,        node->icon_buf,
454        node->lpos.x - map->style->icon.scale/2 *        node->lpos.x - map->style->icon.scale/2 * map->state->detail *
455                        gdk_pixbuf_get_width(node->icon_buf),                        gdk_pixbuf_get_width(node->icon_buf),
456        node->lpos.y - map->style->icon.scale/2 *        node->lpos.y - map->style->icon.scale/2 * map->state->detail *
457                        gdk_pixbuf_get_height(node->icon_buf),                        gdk_pixbuf_get_height(node->icon_buf),
458                map->style->icon.scale,map->style->icon.scale);                        map->state->detail * map->style->icon.scale,
459                          map->state->detail * map->style->icon.scale);
460    
461    canvas_item_set_zoom_max(map_item->item, node->zoom_max);    canvas_item_set_zoom_max(map_item->item,
462                               node->zoom_max / (2 * map->state->detail));
463    
464    /* attach map_item to nodes map_item_chain */    /* attach map_item to nodes map_item_chain */
465    map_item_chain_t **chain = &node->map_item_chain;    map_item_chain_t **chain = &node->map_item_chain;
# Line 540  static canvas_item_t *map_way_new(map_t Line 521  static canvas_item_t *map_way_new(map_t
521      map_item->item = canvas_polyline_new(map->canvas, group, points, width, color);      map_item->item = canvas_polyline_new(map->canvas, group, points, width, color);
522    }    }
523    
524    canvas_item_set_zoom_max(map_item->item, way->draw.zoom_max);    canvas_item_set_zoom_max(map_item->item,
525                               way->draw.zoom_max / (2 * map->state->detail));
526    
527    /* a ways outline itself is never dashed */    /* a ways outline itself is never dashed */
528    if (group != CANVAS_GROUP_WAYS_OL)    if (group != CANVAS_GROUP_WAYS_OL)
# Line 590  void map_way_draw(map_t *map, way_t *way Line 572  void map_way_draw(map_t *map, way_t *way
572      }      }
573    
574      /* draw way */      /* draw way */
575        float width = way->draw.width * map->state->detail;
576    
577      if(way->draw.flags & OSM_DRAW_FLAG_AREA) {      if(way->draw.flags & OSM_DRAW_FLAG_AREA) {
578        map_way_new(map, CANVAS_GROUP_POLYGONS, way, points,        map_way_new(map, CANVAS_GROUP_POLYGONS, way, points,
579                    way->draw.width, way->draw.color, way->draw.area.color);                    width, way->draw.color, way->draw.area.color);
580      } else {      } else {
581    
582        if(way->draw.flags & OSM_DRAW_FLAG_BG) {        if(way->draw.flags & OSM_DRAW_FLAG_BG) {
583          map_way_new(map, CANVAS_GROUP_WAYS_INT, way, points,          map_way_new(map, CANVAS_GROUP_WAYS_INT, way, points,
584                      way->draw.width, way->draw.color, NO_COLOR);                      width, way->draw.color, NO_COLOR);
585    
586          map_way_new(map, CANVAS_GROUP_WAYS_OL, way, points,          map_way_new(map, CANVAS_GROUP_WAYS_OL, way, points,
587                      way->draw.bg.width, way->draw.bg.color, NO_COLOR);                      way->draw.bg.width * map->state->detail,
588                        way->draw.bg.color, NO_COLOR);
589    
590        } else        } else
591          map_way_new(map, CANVAS_GROUP_WAYS, way, points,          map_way_new(map, CANVAS_GROUP_WAYS, way, points,
592                      way->draw.width, way->draw.color, NO_COLOR);                      width, way->draw.color, NO_COLOR);
593      }      }
594      canvas_points_free(points);      canvas_points_free(points);
595    }    }
# Line 617  void map_node_draw(map_t *map, node_t *n Line 602  void map_node_draw(map_t *map, node_t *n
602    
603    if(!node->ways)    if(!node->ways)
604      map_node_new(map, node,      map_node_new(map, node,
605                   map->style->node.radius,                   map->style->node.radius * map->state->detail,
606                   map->style->node.border_radius,                   map->style->node.border_radius * map->state->detail,
607                   map->style->node.fill_color,                   map->style->node.fill_color,
608                   map->style->node.color);                   map->style->node.color);
609    
610    else if(map->style->node.show_untagged || osm_node_has_tag(node))    else if(map->style->node.show_untagged || osm_node_has_tag(node))
611      map_node_new(map, node,      map_node_new(map, node,
612                   map->style->node.radius, 0,                   map->style->node.radius * map->state->detail, 0,
613                   map->style->node.color, 0);                   map->style->node.color, 0);
614  }  }
615    
# Line 677  static void map_item_init(style_t *style Line 662  static void map_item_init(style_t *style
662  void map_item_redraw(appdata_t *appdata, map_item_t *map_item) {  void map_item_redraw(appdata_t *appdata, map_item_t *map_item) {
663    map_item_t item = *map_item;    map_item_t item = *map_item;
664    
665      /* a relation cannot be redraws as it doesn't have a visual */
666      /* representation */
667      if(map_item->object.type == RELATION)
668        return;
669    
670    /* check if the item to be redrawn is the selected one */    /* check if the item to be redrawn is the selected one */
671    gboolean is_selected = FALSE;    gboolean is_selected = FALSE;
672    if(map_item->object.ptr == appdata->map->selected.object.ptr) {    if(map_item->object.ptr == appdata->map->selected.object.ptr) {
# Line 882  map_item_t *map_item_at(map_t *map, gint Line 872  map_item_t *map_item_at(map_t *map, gint
872    
873    switch(map_item->object.type) {    switch(map_item->object.type) {
874    case NODE:    case NODE:
875      printf("  item is node #%ld\n", map_item->object.node->id);      printf("  item is node #"ITEM_ID_FORMAT"\n", map_item->object.node->id);
876      break;      break;
877    case WAY:    case WAY:
878      printf("  item is way #%ld\n", map_item->object.way->id);      printf("  item is way #"ITEM_ID_FORMAT"\n", map_item->object.way->id);
879      break;      break;
880    default:    default:
881      printf("  unknown item\n");      printf("  unknown item\n");
# Line 911  map_item_t *map_real_item_at(map_t *map, Line 901  map_item_t *map_real_item_at(map_t *map,
901        parent = map_item->object.node->map_item_chain->map_item;        parent = map_item->object.node->map_item_chain->map_item;
902    
903      if(parent)      if(parent)
904        printf("  using parent item node #%ld\n", parent->object.node->id);        printf("  using parent item node #" ITEM_ID_FORMAT "\n",
905                 parent->object.node->id);
906      break;      break;
907    
908    case WAY:    case WAY:
# Line 919  map_item_t *map_real_item_at(map_t *map, Line 910  map_item_t *map_real_item_at(map_t *map,
910        parent = map_item->object.way->map_item_chain->map_item;        parent = map_item->object.way->map_item_chain->map_item;
911    
912      if(parent)      if(parent)
913        printf("  using parent item way #%ld\n", parent->object.way->id);        printf("  using parent item way #" ITEM_ID_FORMAT "\n",
914                 parent->object.way->id);
915      break;      break;
916    
917    default:    default:
# Line 1005  static gboolean map_limit_zoom(map_t *ma Line 997  static gboolean map_limit_zoom(map_t *ma
997          }          }
998      }      }
999      if (*zoom != oldzoom) {      if (*zoom != oldzoom) {
1000          printf("Can't zoom further out\n");          printf("Can't zoom further out (%f)\n", *zoom);
1001          return 1;          return 1;
1002      }      }
1003      return 0;      return 0;
# Line 1286  void map_highlight_refresh(appdata_t *ap Line 1278  void map_highlight_refresh(appdata_t *ap
1278  }  }
1279    
1280  void map_way_delete(appdata_t *appdata, way_t *way) {  void map_way_delete(appdata_t *appdata, way_t *way) {
1281    printf("deleting way #%ld from map and osm\n", way->id);    printf("deleting way #" ITEM_ID_FORMAT " from map and osm\n", way->id);
1282    
1283    /* remove it visually from the screen */    /* remove it visually from the screen */
1284    map_item_chain_destroy(&way->map_item_chain);    map_item_chain_destroy(&way->map_item_chain);
# Line 1364  static void map_touchnode_update(appdata Line 1356  static void map_touchnode_update(appdata
1356      /* don't highlight the dragged node itself and don't highlight */      /* don't highlight the dragged node itself and don't highlight */
1357      /* deleted ones */      /* deleted ones */
1358      if((node != cur_node) && (!(node->flags & OSM_FLAG_DELETED))) {      if((node != cur_node) && (!(node->flags & OSM_FLAG_DELETED))) {
1359        gint nx = x - node->lpos.x;        gint nx = abs(x - node->lpos.x);
1360        gint ny = y - node->lpos.y;        gint ny = abs(y - node->lpos.y);
1361    
1362        if((nx < map->style->node.radius) && (ny < map->style->node.radius) &&        if((nx < map->style->node.radius) && (ny < map->style->node.radius) &&
1363           (nx*nx + ny*ny < map->style->node.radius * map->style->node.radius))           (nx*nx + ny*ny < map->style->node.radius * map->style->node.radius))
# Line 1379  static void map_touchnode_update(appdata Line 1371  static void map_touchnode_update(appdata
1371    if(!map->touchnode && map->action.way) {    if(!map->touchnode && map->action.way) {
1372      node_chain_t *chain = map->action.way->node_chain;      node_chain_t *chain = map->action.way->node_chain;
1373      while(!map->touchnode && chain && chain->next) {      while(!map->touchnode && chain && chain->next) {
1374        gint nx = x - chain->node->lpos.x;        gint nx = abs(x - chain->node->lpos.x);
1375        gint ny = y - chain->node->lpos.y;        gint ny = abs(y - chain->node->lpos.y);
1376    
1377        if((nx < map->style->node.radius) && (ny < map->style->node.radius) &&        if((nx < map->style->node.radius) && (ny < map->style->node.radius) &&
1378           (nx*nx + ny*ny < map->style->node.radius * map->style->node.radius))           (nx*nx + ny*ny < map->style->node.radius * map->style->node.radius))
# Line 1738  gboolean map_key_press_event(appdata_t * Line 1730  gboolean map_key_press_event(appdata_t *
1730    return FALSE;    return FALSE;
1731  }  }
1732    
1733    void map_state_reset(map_state_t *state) {
1734      if(!state) return;
1735    
1736      state->zoom = 0.25;
1737      state->detail = 1.0;
1738    
1739      /* todo: try to scroll to center of screen */
1740      state->scroll_offset.x = 0;
1741      state->scroll_offset.y = 0;
1742    }
1743    
1744    map_state_t *map_state_new(void) {
1745      map_state_t *state = g_new0(map_state_t, 1);
1746      map_state_reset(state);
1747      return state;
1748    }
1749    
1750  GtkWidget *map_new(appdata_t *appdata) {  GtkWidget *map_new(appdata_t *appdata) {
1751    map_t *map = appdata->map = g_new0(map_t, 1);    map_t *map = appdata->map = g_new0(map_t, 1);
1752    
# Line 1753  GtkWidget *map_new(appdata_t *appdata) { Line 1762  GtkWidget *map_new(appdata_t *appdata) {
1762      map->state = appdata->project->map_state;      map->state = appdata->project->map_state;
1763    } else {    } else {
1764      printf("Creating new map state\n");      printf("Creating new map state\n");
1765      map->state = g_new0(map_state_t, 1);      map->state = map_state_new();
     map->state->zoom = 0.25;  
1766    }    }
1767    
1768    map->state->refcount++;    map->state->refcount++;
# Line 1764  GtkWidget *map_new(appdata_t *appdata) { Line 1772  GtkWidget *map_new(appdata_t *appdata) {
1772    map->appdata = appdata;    map->appdata = appdata;
1773    map->action.type = MAP_ACTION_IDLE;    map->action.type = MAP_ACTION_IDLE;
1774    
1775    map->canvas = canvas_new(map->style->background.color);    map->canvas = canvas_new();
   canvas_set_antialias(map->canvas, !appdata->settings->no_antialias);  
1776    
1777    GtkWidget *canvas_widget = canvas_get_widget(map->canvas);    GtkWidget *canvas_widget = canvas_get_widget(map->canvas);
1778    
# Line 1794  GtkWidget *map_new(appdata_t *appdata) { Line 1801  GtkWidget *map_new(appdata_t *appdata) {
1801  void map_init(appdata_t *appdata) {  void map_init(appdata_t *appdata) {
1802    map_t *map = appdata->map;    map_t *map = appdata->map;
1803    
1804      /* update canvas background color */
1805      canvas_set_background(map->canvas, map->style->background.color);
1806    
1807    /* set initial zoom */    /* set initial zoom */
1808    map_set_zoom(map, map->state->zoom, FALSE);    map_set_zoom(map, map->state->zoom, FALSE);
1809    josm_elemstyles_colorize_world(map->style, appdata->osm);    josm_elemstyles_colorize_world(map->style, appdata->osm);
# Line 1833  void map_clear(appdata_t *appdata, gint Line 1843  void map_clear(appdata_t *appdata, gint
1843  void map_paint(appdata_t *appdata) {  void map_paint(appdata_t *appdata) {
1844    map_t *map = appdata->map;    map_t *map = appdata->map;
1845    
   /* user may have changed antialias settings */  
   canvas_set_antialias(map->canvas, !appdata->settings->no_antialias);  
   
1846    josm_elemstyles_colorize_world(map->style, appdata->osm);    josm_elemstyles_colorize_world(map->style, appdata->osm);
1847    map_draw(map, appdata->osm);    map_draw(map, appdata->osm);
1848  }  }
# Line 1943  void map_action_ok(appdata_t *appdata) { Line 1950  void map_action_ok(appdata_t *appdata) {
1950      /* save changes to bg_offset in project */      /* save changes to bg_offset in project */
1951      appdata->project->wms_offset.x = map->bg.offset.x;      appdata->project->wms_offset.x = map->bg.offset.x;
1952      appdata->project->wms_offset.y = map->bg.offset.y;      appdata->project->wms_offset.y = map->bg.offset.y;
     appdata->project->dirty = TRUE;  
1953      break;      break;
1954    
1955    default:    default:
# Line 1967  void map_delete_selected(appdata_t *appd Line 1973  void map_delete_selected(appdata_t *appd
1973    /* deleting the selected item de-selects it ... */    /* deleting the selected item de-selects it ... */
1974    map_item_deselect(appdata);    map_item_deselect(appdata);
1975    
1976    undo_remember_delete(appdata, item.object.type, item.object.ptr);    undo_remember_delete(appdata, &item.object);
1977    
1978    switch(item.object.type) {    switch(item.object.type) {
1979    case NODE:    case NODE:
1980      printf("request to delete node #%ld\n", item.object.node->id);      printf("request to delete node #" ITEM_ID_FORMAT "\n",
1981               item.object.node->id);
1982    
1983      /* check if this node is part of a way with two nodes only. */      /* check if this node is part of a way with two nodes only. */
1984      /* we cannot delete this as this would also delete the way */      /* we cannot delete this as this would also delete the way */
# Line 2032  void map_delete_selected(appdata_t *appd Line 2039  void map_delete_selected(appdata_t *appd
2039      break;      break;
2040    
2041    case WAY:    case WAY:
2042      printf("request to delete way #%ld\n", item.object.way->id);      printf("request to delete way #" ITEM_ID_FORMAT "\n", item.object.way->id);
2043      map_way_delete(appdata, item.object.way);      map_way_delete(appdata, item.object.way);
2044      break;      break;
2045    
# Line 2045  void map_delete_selected(appdata_t *appd Line 2052  void map_delete_selected(appdata_t *appd
2052    
2053  /* ----------------------- track related stuff ----------------------- */  /* ----------------------- track related stuff ----------------------- */
2054    
2055    static gboolean track_pos2lpos(bounds_t *bounds, pos_t *pos, lpos_t *lpos) {
2056      pos2lpos(bounds, pos, lpos);
2057    
2058      /* check if point is within bounds */
2059      return ((lpos->x >= bounds->min.x) && (lpos->x <= bounds->max.x) &&
2060              (lpos->y >= bounds->min.y) && (lpos->y <= bounds->max.y));
2061    }
2062    
2063  void map_track_draw_seg(map_t *map, track_seg_t *seg) {  void map_track_draw_seg(map_t *map, track_seg_t *seg) {
2064      bounds_t *bounds = map->appdata->osm->bounds;
2065    
2066    /* a track_seg needs at least 2 points to be drawn */    /* a track_seg needs at least 2 points to be drawn */
2067    guint pnum = track_seg_points(seg);    guint pnum = track_seg_points(seg);
2068    printf("seg of length %d\n", pnum);    printf("seg of length %d\n", pnum);
2069    
2070    if(pnum == 1) {    if(!pnum)
2071      g_assert(!seg->item);      return;
2072    
2073      seg->item = canvas_circle_new(map->canvas, CANVAS_GROUP_TRACK,    /* nothing should have been drawn by now ... */
2074            seg->track_point->lpos.x, seg->track_point->lpos.y,    g_assert(!seg->item_chain);
2075            map->style->track.width/2.0, 0, map->style->track.color, NO_COLOR);  
2076    }    track_item_chain_t **itemP = &seg->item_chain;
2077      track_point_t *track_point = seg->track_point;
2078      while(track_point) {
2079        lpos_t lpos;
2080    
2081        /* skip all points not on screen */
2082        track_point_t *last = NULL;
2083        while(track_point && !track_pos2lpos(bounds, &track_point->pos, &lpos)) {
2084          last = track_point;
2085          track_point = track_point->next;
2086        }
2087    
2088        int visible = 0;
2089    
2090        /* count nodes that _are_ on screen */
2091        track_point_t *tmp = track_point;
2092        while(tmp && track_pos2lpos(bounds, &tmp->pos, &lpos)) {
2093          tmp = tmp->next;
2094          visible++;
2095        }
2096    
2097        /* actually start drawing with the last position that was offscreen */
2098        /* so the track nicely enters the viewing area */
2099        if(last) {
2100          track_point = last;
2101          visible++;
2102        }
2103    
2104        /* also use last one that's offscreen to nicely leave the visible area */
2105        if(tmp && tmp->next)
2106          visible++;
2107    
   if(pnum > 1) {  
   
2108      /* allocate space for nodes */      /* allocate space for nodes */
2109      canvas_points_t *points = canvas_points_new(pnum);      canvas_points_t *points = canvas_points_new(visible);
2110    
2111      int point = 0;      printf("visible are %d\n", visible);
2112      track_point_t *track_point = seg->track_point;      int point;
2113      while(track_point) {      for(point=0;point<visible;point++) {
2114        points->coords[point++] = track_point->lpos.x;        track_pos2lpos(bounds, &track_point->pos, &lpos);
2115        points->coords[point++] = track_point->lpos.y;  
2116          points->coords[2*point+0] = lpos.x;
2117          points->coords[2*point+1] = lpos.y;
2118        track_point = track_point->next;        track_point = track_point->next;
2119      }      }
   
     /* there may be a circle (one point line) */  
     if(seg->item)  
       canvas_item_destroy(seg->item);  
2120    
2121      seg->item = canvas_polyline_new(map->canvas, CANVAS_GROUP_TRACK,      *itemP = g_new0(track_item_chain_t, 1);
2122            points, map->style->track.width, map->style->track.color);      (*itemP)->item = canvas_polyline_new(map->canvas, CANVAS_GROUP_TRACK,
2123                     points, map->style->track.width, map->style->track.color);
2124        itemP = &(*itemP)->next;
2125    
2126      canvas_points_free(points);      canvas_points_free(points);
2127    }    }
2128  }  }
2129    
2130    /* update the last visible fragment of this segment since a */
2131    /* gps position may have been added */
2132  void map_track_update_seg(map_t *map, track_seg_t *seg) {  void map_track_update_seg(map_t *map, track_seg_t *seg) {
2133      bounds_t *bounds = map->appdata->osm->bounds;
2134    
2135      printf("-- APPENDING TO TRACK --\n");
2136    
2137    /* a track_seg needs at least 2 points to be drawn */    /* a track_seg needs at least 2 points to be drawn */
2138    guint pnum = track_seg_points(seg);    guint pnum = track_seg_points(seg);
2139    printf("seg of length %d\n", pnum);    printf("seg of length %d\n", pnum);
2140    
2141    if(pnum > 1) {    /* there are two cases: either the second last point was on screen */
2142      /* or it wasn't. We'll have to start a new screen item if the latter */
2143      /* is the case */
2144    
2145      /* search last point */
2146      track_point_t *begin = seg->track_point, *second_last = seg->track_point;
2147      lpos_t lpos;
2148      while(second_last && second_last->next && second_last->next->next) {
2149        if(!track_pos2lpos(bounds, &second_last->pos, &lpos))
2150          begin = second_last;
2151    
2152        second_last = second_last->next;
2153      }
2154      track_point_t *last = second_last->next;
2155    
2156      /* since we are updating an existing track, it sure has at least two */
2157      /* points, second_last must be valid and its "next" (last) also */
2158      g_assert(second_last);
2159      g_assert(last);
2160    
2161      /* check if the last and second_last points are visible */
2162      gboolean last_is_visible =
2163        track_pos2lpos(bounds, &last->pos, &lpos);
2164      gboolean second_last_is_visible =
2165        track_pos2lpos(bounds, &second_last->pos, &lpos);
2166    
2167      /* if both are invisible, then nothing has changed on screen */
2168      if(!last_is_visible && !second_last_is_visible) {
2169        printf("second_last and last entry are invisible -> doing nothing\n");
2170        return;
2171      }
2172    
2173      /* search last element in item chain */
2174      track_item_chain_t *item = seg->item_chain;
2175      while(item && item->next)
2176        item = item->next;
2177    
2178      if(second_last_is_visible) {
2179        /* there must be something already on the screen and there must */
2180        /* be visible nodes in the chain */
2181        g_assert(item);
2182        g_assert(begin);
2183    
2184        printf("second_last is visible -> append\n");
2185    
2186      /* allocate space for nodes */      /* count points to be placed */
2187      canvas_points_t *points = canvas_points_new(pnum);      int npoints = 0;
2188        track_point_t *tmp = begin;
2189        while(tmp) {
2190          tmp = tmp->next;
2191          npoints++;
2192        }
2193    
2194        printf("updating last segment to %d points\n", npoints);
2195    
2196        canvas_points_t *points = canvas_points_new(npoints);
2197    
2198        gint point = 0;
2199        while(begin) {
2200          track_pos2lpos(bounds, &begin->pos, &lpos);
2201          canvas_point_set_pos(points, point++, &lpos);
2202          begin = begin->next;
2203        }
2204    
2205      int point = 0;      canvas_item_set_points(item->item, points);
2206      track_point_t *track_point = seg->track_point;      canvas_points_free(points);
2207      while(track_point) {  
2208        canvas_point_set_pos(points, point++, &track_point->lpos);    } else {
2209        track_point = track_point->next;      printf("second last is invisible -> start new screen segment\n");
2210    
2211        /* the search for the "begin" ends with the second_last item */
2212        /* verify the last one also */
2213        if(begin->next && !track_pos2lpos(bounds, &begin->next->pos, &lpos))
2214          begin = begin->next;
2215    
2216        item->next = g_new0(track_item_chain_t, 1);
2217        item = item->next;
2218    
2219        /* count points to be placed */
2220        int npoints = 0;
2221        track_point_t *tmp = begin;
2222        while(tmp) {
2223          tmp = tmp->next;
2224          npoints++;
2225        }
2226    
2227        printf("attaching new segment with %d points\n", npoints);
2228    
2229        canvas_points_t *points = canvas_points_new(npoints);
2230    
2231        gint point = 0;
2232        while(begin) {
2233          track_pos2lpos(bounds, &begin->pos, &lpos);
2234          canvas_point_set_pos(points, point++, &lpos);
2235          begin = begin->next;
2236      }      }
2237    
2238      g_assert(seg->item);      item->item = canvas_polyline_new(map->canvas, CANVAS_GROUP_TRACK,
2239      canvas_item_set_points(seg->item, points);                   points, map->style->track.width, map->style->track.color);
2240    
2241      canvas_points_free(points);      canvas_points_free(points);
2242    }    }
2243    
2244  }  }
2245    
2246  void map_track_draw(map_t *map, track_t *track) {  void map_track_draw(map_t *map, track_t *track) {
# Line 2125  void map_track_remove(appdata_t *appdata Line 2263  void map_track_remove(appdata_t *appdata
2263    /* remove all segments */    /* remove all segments */
2264    track_seg_t *seg = track->track_seg;    track_seg_t *seg = track->track_seg;
2265    while(seg) {    while(seg) {
2266      if(seg->item) {      track_item_chain_t *item = seg->item_chain;
2267        canvas_item_destroy(seg->item);      while(item) {
2268        seg->item = NULL;        track_item_chain_t *next = item->next;
2269          canvas_item_destroy(item->item);
2270          item = next;
2271      }      }
2272    
2273        seg->item_chain = NULL;
2274      seg = seg->next;      seg = seg->next;
2275    }    }
2276  }  }
2277    
2278  void map_track_pos(appdata_t *appdata, lpos_t *lpos) {  void map_track_pos(appdata_t *appdata, pos_t *pos) {
2279    if(appdata->track.gps_item) {    if(appdata->track.gps_item) {
2280      canvas_item_destroy(appdata->track.gps_item);      canvas_item_destroy(appdata->track.gps_item);
2281      appdata->track.gps_item = NULL;      appdata->track.gps_item = NULL;
2282    }    }
2283    
2284    if(lpos)    if(pos) {
2285        lpos_t lpos;
2286        pos2lpos(appdata->osm->bounds, pos, &lpos);
2287    
2288      appdata->track.gps_item =      appdata->track.gps_item =
2289        canvas_circle_new(appdata->map->canvas, CANVAS_GROUP_GPS,        canvas_circle_new(appdata->map->canvas, CANVAS_GROUP_GPS,
2290          lpos->x, lpos->y, appdata->map->style->track.width/2.0, 0,          lpos.x, lpos.y, appdata->map->style->track.width/2.0, 0,
2291                          appdata->map->style->track.gps_color, NO_COLOR);                          appdata->map->style->track.gps_color, NO_COLOR);
2292      }
2293  }  }
2294    
2295  /* ------------------- map background ------------------ */  /* ------------------- map background ------------------ */
# Line 2205  void map_hide_selected(appdata_t *appdat Line 2350  void map_hide_selected(appdata_t *appdat
2350    }    }
2351    
2352    way_t *way = map->selected.object.way;    way_t *way = map->selected.object.way;
2353    printf("hiding way #%ld\n", way->id);    printf("hiding way #" ITEM_ID_FORMAT "\n", way->id);
2354    
2355    map_item_deselect(appdata);    map_item_deselect(appdata);
2356    way->flags |= OSM_FLAG_HIDDEN;    way->flags |= OSM_FLAG_HIDDEN;
# Line 2231  void map_show_all(appdata_t *appdata) { Line 2376  void map_show_all(appdata_t *appdata) {
2376    gtk_widget_set_sensitive(appdata->menu_item_map_show_all, FALSE);    gtk_widget_set_sensitive(appdata->menu_item_map_show_all, FALSE);
2377  }  }
2378    
2379    static void map_detail_change(map_t *map, float detail) {
2380      appdata_t *appdata = map->appdata;
2381    
2382      /* deselecting anything allows us not to care about automatic deselection */
2383      /* as well as items becoming invisible by the detail change */
2384      map_item_deselect(appdata);
2385    
2386      map->state->detail = detail;
2387      printf("changing detail factor to %f\n", map->state->detail);
2388    
2389      banner_busy_start(appdata, 1, _("Redrawing"));
2390      map_clear(appdata, MAP_LAYER_OBJECTS_ONLY);
2391      map_paint(appdata);
2392      banner_busy_stop(appdata);
2393    }
2394    
2395    #define DETAIL_STEP 1.5
2396    
2397    void map_detail_increase(map_t *map) {
2398      if(!map) return;
2399      map_detail_change(map, map->state->detail * DETAIL_STEP);
2400    }
2401    
2402    void map_detail_decrease(map_t *map) {
2403      if(!map) return;
2404      map_detail_change(map, map->state->detail / DETAIL_STEP);
2405    }
2406    
2407    void map_detail_normal(map_t *map) {
2408      if(!map) return;
2409      map_detail_change(map, 1.0);
2410    }
2411    
2412  // vim:et:ts=8:sw=2:sts=2:ai  // vim:et:ts=8:sw=2:sts=2:ai

Legend:
Removed from v.154  
changed lines
  Added in v.234