Exemple #1
0
/** Re-calculates extent of a polyline.
 * @param pl Polyline
 * @param x X coordinate
 * @param y Y coordinate
 */
static void poly_recalcextent(poly* pl)
{
    double* xs = pl->x;
    double* ys = pl->y;
    extent* e = &pl->e;
    int n = pl->n;
    int i;

    extent_clear(e);
    for (i = 0; i < n; ++i)
        extent_update(e, xs[i], ys[i]);
}
Exemple #2
0
static gboolean
on_map_button_release_event(GtkWidget *widget,
			    GdkEventButton *event, area_context_t *context) {

  OsmGpsMap *map = OSM_GPS_MAP(widget);
  osm_gps_map_osd_t *osd = osm_gps_map_osd_get(map);

  if(!std::isnan(context->map.start.rlon) &&
     !std::isnan(context->map.start.rlat)) {

    OsmGpsMapPoint start = context->map.start;
    OsmGpsMapPoint end = osm_gps_map_convert_screen_to_geographic(map, event->x, event->y);

    GSList *box = pos_append_rad(nullptr, start.rlat, start.rlon);
    box = pos_append_rad(box, end.rlat,   start.rlon);
    box = pos_append_rad(box, end.rlat,   end.rlon);
    box = pos_append_rad(box, start.rlat, end.rlon);
    box = pos_append_rad(box, start.rlat, start.rlon);

    osm_gps_map_add_track(map, box);

    if(start.rlat < end.rlat) {
      context->bounds.min.lat = RAD2DEG(start.rlat);
      context->bounds.max.lat = RAD2DEG(end.rlat);
    } else {
      context->bounds.min.lat = RAD2DEG(end.rlat);
      context->bounds.max.lat = RAD2DEG(start.rlat);
    }

    if(start.rlon < end.rlon) {
      context->bounds.min.lon = RAD2DEG(start.rlon);
      context->bounds.max.lon = RAD2DEG(end.rlon);
    } else {
      context->bounds.min.lon = RAD2DEG(end.rlon);
      context->bounds.max.lon = RAD2DEG(start.rlon);
    }

    area_main_update(context);
    direct_update(context);
    extent_update(context);

    context->map.start.rlon = context->map.start.rlat = NAN;
  }

  /* osm-gps-map needs this event to handle the OSD */
  if(osd->check(osd, TRUE, event->x, event->y) != OSD_NONE)
    return FALSE;

  /* returning true here disables dragging in osm-gps-map */
  return osm_gps_map_osd_get_state(map) == TRUE ? FALSE : TRUE;
}
Exemple #3
0
/** Appends a point to the tail of a polyline.
 * @param pl Polyline
 * @param x X coordinate
 * @param y Y coordinate
 */
void poly_addpoint(poly* pl, double x, double y)
{
    if (isnan(x) || isnan(y))
        gu_quit("poly_addpoint(): NaN detected");

    if (pl->n == pl->nallocated) {
        pl->x = realloc(pl->x, pl->nallocated * sizeof(double) * 2);
        pl->y = realloc(pl->y, pl->nallocated * sizeof(double) * 2);
        pl->nallocated *= 2;
    }

    pl->x[pl->n] = x;
    pl->y[pl->n] = y;
    pl->n++;
    extent_update(&pl->e, x, y);
}
Exemple #4
0
static void callback_fetch_mm_clicked(area_context_t *context) {
  dbus_mm_pos_t mmpos;
  if(!dbus_mm_set_position(&mmpos)) {
    error_dlg(_("Unable to communicate with Maemo Mapper. "
              "You need to have Maemo Mapper installed to use this feature."),
              context->dialog.get());
    return;
  }

  if(!mmpos.valid) {
    error_dlg(_("No valid position received yet. You need to "
           "scroll or zoom the Maemo Mapper view in order to force it to send "
           "its current view position to osm2go."), context->dialog.get());
    return;
  }

  /* maemo mapper is fourth tab (page 3) */
  if(!current_tab_is(context, "M.Mapper"))
    return;

  /* maemo mapper pos data ... */
  pos_float_t center_lat = mmpos.pos.lat;
  pos_float_t center_lon = mmpos.pos.lon;
  int zoom = mmpos.zoom;

  if(!pos_lat_valid(center_lat) || !pos_lon_valid(center_lon))
    return;

  double vscale = DEG2RAD(POS_EQ_RADIUS);
  double height = 8 * (1<<zoom) / vscale;
  context->bounds.min.lat = center_lat - height;
  context->bounds.max.lat = center_lat + height;

  double hscale = DEG2RAD(cos(DEG2RAD(center_lat)) * POS_EQ_RADIUS);
  double width  = 16 * (1<<zoom) / hscale;
  context->bounds.min.lon = center_lon - width;
  context->bounds.max.lon = center_lon + width;

  area_main_update(context);

  /* also update other tabs */
  direct_update(context);
  extent_update(context);
  map_update(context, false);
}
Exemple #5
0
static void callback_modified_direct(area_context_t *context) {
  /* direct is second tab (page 1) */
  if(!current_tab_is(context, TAB_LABEL_DIRECT))
    return;

  /* parse the fields from the direct entry pad */
  if(unlikely(!pos_lat_get(context->direct.minlat, context->bounds.min.lat) ||
              !pos_lon_get(context->direct.minlon, context->bounds.min.lon) ||
              !pos_lat_get(context->direct.maxlat, context->bounds.max.lat) ||
              !pos_lon_get(context->direct.maxlon, context->bounds.max.lon)))
    return;

  area_main_update(context);

  /* also adjust other views */
  extent_update(context);
  map_update(context, false);
}
Exemple #6
0
/* Appends a point to the tail of a polyline.
 * @param pl Polyline
 * @param x X coordinate
 * @param y Y coordinate
 */
void poly_addpoint(poly* pl, double x, double y)
{
    if (isnan(x) || isnan(y)) {
        fflush(stdout);
        fprintf(stderr, "error: poly_addpoint(): NaN detected\n");
        exit(1);
    }

    if (pl->n == pl->nallocated) {
        pl->x = realloc(pl->x, pl->nallocated * sizeof(double) * 2);
        pl->y = realloc(pl->y, pl->nallocated * sizeof(double) * 2);
        pl->nallocated *= 2;
    }

    pl->x[pl->n] = x;
    pl->y[pl->n] = y;
    pl->n++;
    extent_update(&pl->e, x, y);
}
Exemple #7
0
/** Removes a point at a given position from a polyline.
 * @param pl Polyline
 * @param index Position
 */
void poly_deletepoint(poly* pl, int index)
{
    double xx = pl->x[index];
    double yy = pl->y[index];
    extent* e = &pl->e;

    memmove(&pl->x[index], &pl->x[index + 1], (pl->n - index - 1) * sizeof(double));
    memmove(&pl->y[index], &pl->y[index + 1], (pl->n - index - 1) * sizeof(double));
    pl->n--;

    if (e->xmin == xx || e->xmax == xx || e->ymin == yy || e->ymax == yy) {
        double* x = pl->x;
        double* y = pl->y;
        int i;

        extent_clear(e);
        for (i = 0; i < pl->n; ++i)
            extent_update(e, x[i], y[i]);
    }
}
Exemple #8
0
/** Adds a point to a polyline at a given position.
 * No action for invalid index.
 * @param pl Polyline
 * @param index Index
 * @param x X coordinate
 * @param y Y coordinate
 */
void poly_addpointat(poly* pl, int index, double x, double y)
{
    if (index > pl->n - 1) {
        poly_addpoint(pl, x, y);
        return;
    }

    if (pl->n == pl->nallocated) {
        pl->x = realloc(pl->x, pl->nallocated * sizeof(double) * 2);
        pl->y = realloc(pl->y, pl->nallocated * sizeof(double) * 2);
        pl->nallocated *= 2;
    }

    memmove(&pl->x[index + 1], &pl->x[index], (pl->n - index) * sizeof(double));
    memmove(&pl->y[index + 1], &pl->x[index], (pl->n - index) * sizeof(double));
    pl->x[index] = x;
    pl->y[index] = y;
    pl->n++;
    extent_update(&pl->e, x, y);
}
Exemple #9
0
bool area_edit_t::run() {
  GtkWidget *vbox;

  area_context_t context(*this,
                         gtk_dialog_new_with_buttons(_("Area editor"),
                                               GTK_WINDOW(parent), GTK_DIALOG_MODAL,
                                               GTK_STOCK_CANCEL, GTK_RESPONSE_REJECT,
                                               GTK_STOCK_OK, GTK_RESPONSE_ACCEPT,
                                               nullptr));

  osm2go_platform::dialog_size_hint(context.dialog, osm2go_platform::MISC_DIALOG_HIGH);
  context.warning = gtk_dialog_add_button(context.dialog, _("Warning"), GTK_RESPONSE_HELP);

  gtk_button_set_image(GTK_BUTTON(context.warning),
                       gtk_image_new_from_icon_name("dialog-warning", GTK_ICON_SIZE_BUTTON));
  g_signal_connect_swapped(context.warning, "clicked",
                           G_CALLBACK(on_area_warning_clicked), &context);

  /* ------------- fetch from map ------------------------ */

  context.map.needs_redraw = false;
  context.map.widget = OSM_GPS_MAP(g_object_new(OSM_TYPE_GPS_MAP,
                                                "map-source", OSM_GPS_MAP_SOURCE_OPENSTREETMAP,
                                                "proxy-uri", g_getenv("http_proxy"),
                                                "auto-center", FALSE,
                                                "tile-cache", nullptr,
                                                nullptr));

  osm_gps_map_osd_select_init(context.map.widget);

  g_signal_connect_swapped(context.map.widget, "configure-event",
                           G_CALLBACK(on_map_configure), &context);
  g_signal_connect(context.map.widget, "button-press-event",
                   G_CALLBACK(on_map_button_press_event), &context);
  g_signal_connect(context.map.widget, "motion-notify-event",
                   G_CALLBACK(on_map_motion_notify_event), &context);
  g_signal_connect(context.map.widget, "button-release-event",
                   G_CALLBACK(on_map_button_release_event), &context);

  /* install handler for timed updates of the gps button */
  osm2go_platform::Timer timer;
  timer.restart(1, map_gps_update, &context);
  context.map.start.rlon = context.map.start.rlat = NAN;

  osm2go_platform::notebook_append_page(context.notebook, GTK_WIDGET(context.map.widget), _(TAB_LABEL_MAP));

  /* ------------ direct min/max edit --------------- */

  vbox = gtk_vbox_new(FALSE, 10);

  GtkTable *table = GTK_TABLE(gtk_table_new(3, 4, FALSE));  // x, y
  gtk_table_set_col_spacings(table, 10);
  gtk_table_set_row_spacings(table, 5);

  context.direct.minlat = pos_lat_entry_new(bounds.min.lat);
  table_attach(table, context.direct.minlat, 0, 0);
  GtkWidget *label = gtk_label_new(_("to"));
  table_attach(table,  label, 1, 0);
  context.direct.maxlat = pos_lat_entry_new(bounds.max.lat);
  table_attach(table, context.direct.maxlat, 2, 0);

  context.direct.minlon = pos_lon_entry_new(bounds.min.lon);
  table_attach(table, context.direct.minlon, 0, 1);
  label = gtk_label_new(_("to"));
  table_attach(table,  label, 1, 1);
  context.direct.maxlon = pos_lon_entry_new(bounds.max.lon);
  table_attach(table, context.direct.maxlon, 2, 1);

  /* setup this page */
  g_signal_connect_swapped(context.direct.minlat, "changed",
                           G_CALLBACK(callback_modified_direct), &context);
  g_signal_connect_swapped(context.direct.minlon, "changed",
                           G_CALLBACK(callback_modified_direct), &context);
  g_signal_connect_swapped(context.direct.maxlat, "changed",
                           G_CALLBACK(callback_modified_direct), &context);
  g_signal_connect_swapped(context.direct.maxlon, "changed",
                           G_CALLBACK(callback_modified_direct), &context);

  /* --- hint --- */
  label = gtk_label_new(_("(recommended min/max diff <0.03 degrees)"));
  gtk_table_attach_defaults(table, label, 0, 3, 2, 3);

  const GdkColor *color = osm2go_platform::invalid_text_color();
  /* error label */
  context.direct.error = gtk_label_new(nullptr);
  gtk_widget_modify_fg(context.direct.error, GTK_STATE_NORMAL, color);
  gtk_table_attach_defaults(table, context.direct.error, 0, 3, 3, 4);

  gtk_box_pack_start(GTK_BOX(vbox), GTK_WIDGET(table), FALSE, FALSE, 0);
  osm2go_platform::notebook_append_page(context.notebook, vbox, _(TAB_LABEL_DIRECT));

  /* ------------- center/extent edit ------------------------ */

  vbox = gtk_vbox_new(FALSE, 10);
  table = GTK_TABLE(gtk_table_new(3, 5, FALSE));  // x, y
  gtk_table_set_col_spacings(table, 10);
  gtk_table_set_row_spacings(table, 5);

  label = gtk_label_new(_("Center:"));
  gtk_misc_set_alignment(GTK_MISC(label), 1.f, 0.5f);
  gtk_table_attach_defaults(table,  label, 0, 1, 0, 1);
  context.extent.lat = pos_lat_entry_new(0.0);
  gtk_table_attach_defaults(table, context.extent.lat, 1, 2, 0, 1);
  context.extent.lon = pos_lon_entry_new(0.0);
  gtk_table_attach_defaults(table, context.extent.lon, 2, 3, 0, 1);

  gtk_table_set_row_spacing(table, 0, 10);

  label = gtk_label_new(_("Width:"));
  gtk_misc_set_alignment(GTK_MISC(label), 1.f, 0.5f);
  gtk_table_attach_defaults(table,  label, 0, 1, 1, 2);
  context.extent.width = osm2go_platform::entry_new();
  gtk_table_attach_defaults(table, context.extent.width, 1, 2, 1, 2);

  label = gtk_label_new(_("Height:"));
  gtk_misc_set_alignment(GTK_MISC(label), 1.f, 0.5f);
  gtk_table_attach_defaults(table,  label, 0, 1, 2, 3);
  context.extent.height = osm2go_platform::entry_new();
  gtk_table_attach_defaults(table,
			    context.extent.height, 1, 2, 2, 3);

  std::vector<const char *> units(2);
  units[0] = _("mi");
  units[1] = _("km");
  context.extent.mil_km = osm2go_platform::combo_box_new(_("Unit"), units, 1);

  gtk_table_attach(table, context.extent.mil_km, 2, 3, 1, 3,
		   static_cast<GtkAttachOptions>(0), static_cast<GtkAttachOptions>(0),
		   0, 0);

  /* setup this page */
  extent_update(&context);

  /* connect signals after inital update to avoid confusion */
  g_signal_connect_swapped(context.extent.lat, "changed",
                           G_CALLBACK(callback_modified_extent), &context);
  g_signal_connect_swapped(context.extent.lon, "changed",
                           G_CALLBACK(callback_modified_extent), &context);
  g_signal_connect_swapped(context.extent.width, "changed",
                           G_CALLBACK(callback_modified_extent), &context);
  g_signal_connect_swapped(context.extent.height, "changed",
                           G_CALLBACK(callback_modified_extent), &context);
  g_signal_connect_swapped(context.extent.mil_km, "changed",
                           G_CALLBACK(callback_modified_unit), &context);

  /* --- hint --- */
  label = gtk_label_new(_("(recommended width/height < 2km/1.25mi)"));
  gtk_table_attach_defaults(table, label, 0, 3, 3, 4);

  /* error label */
  context.extent.error = gtk_label_new(nullptr);
  gtk_widget_modify_fg(context.extent.error, GTK_STATE_NORMAL, color);
  gtk_table_attach_defaults(table, context.extent.error, 0, 3, 4, 5);

  gtk_box_pack_start(GTK_BOX(vbox), GTK_WIDGET(table), FALSE, FALSE, 0);
  osm2go_platform::notebook_append_page(context.notebook, vbox, _(TAB_LABEL_EXTENT));

#ifdef HAS_MAEMO_MAPPER
  /* ------------- fetch from maemo mapper ------------------------ */

  vbox = gtk_vbox_new(FALSE, 8);
  context.mmapper.fetch = osm2go_platform::button_new_with_label(_("Get from Maemo Mapper"));
  gtk_box_pack_start(GTK_BOX(vbox), context.mmapper.fetch, FALSE, FALSE, 0);

  g_signal_connect_swapped(context.mmapper.fetch, "clicked",
                           G_CALLBACK(callback_fetch_mm_clicked), &context);

  /* --- hint --- */
  label = gtk_label_new(_("(recommended MM zoom level < 7)"));
  gtk_box_pack_start(GTK_BOX(vbox), label, FALSE, FALSE, 0);

  osm2go_platform::notebook_append_page(context.notebook, vbox, _("M.Mapper"));
#endif

  /* ------------------------------------------------------ */

  gtk_box_pack_start(context.dialog.vbox(), context.notebook, TRUE, TRUE, 0);

  g_signal_connect(osm2go_platform::notebook_get_gtk_notebook(context.notebook),
                   "switch-page", G_CALLBACK(on_page_switch), &context);

  gtk_widget_show_all(context.dialog.get());

  area_main_update(&context);

  bool ok = false;
  int response;
  do {
    response = gtk_dialog_run(context.dialog);

    if(GTK_RESPONSE_ACCEPT == response) {
      if(area_warning(&context)) {
        /* copy modified values back to given storage */
        bounds = context.bounds;
        ok = true;
        break;
      }
    }
  } while(response == GTK_RESPONSE_HELP || response == GTK_RESPONSE_ACCEPT);

  return ok;
}