void gpsFixCallback (const gps_common::GPSFix::ConstPtr & msg) { // **** get GTK thread lock gdk_threads_enter (); gint pixel_x, pixel_y; OsmGpsMapPoint *point = osm_gps_map_point_new_degrees (msg->latitude, msg->longitude); osm_gps_map_convert_geographic_to_screen (data->map, point, &pixel_x, &pixel_y); if (OSM_IS_GPS_MAP (data->map)) { // **** Center map on gps data received if (data->lock_view) { update_uav_pose_osd (data->osd, TRUE, pixel_x, pixel_y); osm_gps_map_set_center (data->map, msg->latitude, msg->longitude); } else { update_uav_pose_osd (data->osd, FALSE, pixel_x, pixel_y); osm_gps_map_gps_clear (data->map); } // **** Add point to the track osm_gps_map_track_add_point (data->uav_track, point); } // **** release GTK thread lock gdk_threads_leave (); }
static void drag_and_drop_received(GtkWidget *widget, GdkDragContext *context, gint x, gint y, GtkSelectionData *selection_data, guint target_type, guint time, gpointer data) { dt_view_t *self = (dt_view_t*)data; dt_map_t *lib = (dt_map_t*)self->data; gboolean success = FALSE; if((selection_data != NULL) && (selection_data->length >= 0) && target_type == DND_TARGET_IMGID) { float longitude, latitude; int *imgid = (int*)selection_data->data; if(imgid > 0) { OsmGpsMapPoint *pt = osm_gps_map_point_new_degrees(0.0, 0.0); osm_gps_map_convert_screen_to_geographic(lib->map, x, y, pt); osm_gps_map_point_get_degrees(pt, &latitude, &longitude); osm_gps_map_point_free(pt); const dt_image_t *cimg = dt_image_cache_read_get(darktable.image_cache, *imgid); dt_image_t *img = dt_image_cache_write_get(darktable.image_cache, cimg); img->longitude = longitude; img->latitude = latitude; dt_image_cache_write_release(darktable.image_cache, img, DT_IMAGE_CACHE_SAFE); dt_image_cache_read_release(darktable.image_cache, cimg); success = TRUE; } } gtk_drag_finish(context, success, FALSE, time); }
static gboolean _view_map_button_press_callback(GtkWidget *w, GdkEventButton *e, dt_view_t *self) { dt_map_t *lib = (dt_map_t*)self->data; if(e->button == 1) { // check if the click was on an image or just some random position lib->selected_image = _view_map_get_img_at_pos(self, e->x, e->y); if(e->type == GDK_BUTTON_PRESS && lib->selected_image > 0) { lib->start_drag = TRUE; return TRUE; } if(e->type == GDK_2BUTTON_PRESS) { if(lib->selected_image > 0) { // open the image in darkroom DT_CTL_SET_GLOBAL(lib_image_mouse_over_id, lib->selected_image); dt_ctl_switch_mode_to(DT_DEVELOP); return TRUE; } else { // zoom into that position float longitude, latitude; OsmGpsMapPoint *pt = osm_gps_map_point_new_degrees(0.0, 0.0); osm_gps_map_convert_screen_to_geographic(lib->map, e->x, e->y, pt); osm_gps_map_point_get_degrees(pt, &latitude, &longitude); osm_gps_map_point_free(pt); int zoom, max_zoom; g_object_get(G_OBJECT(lib->map), "zoom", &zoom, "max-zoom", &max_zoom, NULL); zoom = MIN(zoom+1, max_zoom); _view_map_center_on_location(self, longitude, latitude, zoom); } return TRUE; } } return FALSE; }
void fcuGpsCallback(const sensor_msgs::NavSatFixConstPtr& gps) { // **** get GTK thread lock gdk_threads_enter(); //fcuGpsData_ = (*gps); if (gps->status.status == sensor_msgs::NavSatStatus::STATUS_NO_FIX) { gtk_container_remove(GTK_CONTAINER(data->box_Gps), GTK_WIDGET (data->status_ok_icon_gps)); gtk_box_pack_end(GTK_BOX (data->box_Gps), data->status_fail_icon_gps, TRUE, TRUE, 0); } else { gtk_container_remove(GTK_CONTAINER(data->box_Gps), GTK_WIDGET (data->status_fail_icon_gps)); gtk_box_pack_end(GTK_BOX (data->box_Gps), data->status_ok_icon_gps, TRUE, TRUE, 0); gint pixel_x, pixel_y; ROS_DEBUG_STREAM("GPS coordinates: " << gps->latitude << ", " << gps->longitude); ROS_DEBUG_STREAM("GPS altitude information: " << gps->altitude); OsmGpsMapPoint *point = osm_gps_map_point_new_degrees(gps->latitude, gps->longitude); osm_gps_map_convert_geographic_to_screen(data->map, point, &pixel_x, &pixel_y); if (OSM_IS_GPS_MAP (data->map)) { // **** Centre map on GPS data received if (data->lock_view) { update_uav_pose_osd(data->osd, TRUE, pixel_x, pixel_y); osm_gps_map_set_center(data->map, gps->latitude, gps->longitude); } else { update_uav_pose_osd(data->osd, FALSE, pixel_x, pixel_y); osm_gps_map_gps_clear(data->map); } // **** Add point to the track osm_gps_map_track_add_point(data->uav_track, point); } } // **** release GTK thread lock gdk_threads_leave(); }
static void _view_map_post_expose(cairo_t *cri, int32_t width_i, int32_t height_i, int32_t pointerx, int32_t pointery, gpointer user_data) { const int ts = 64; OsmGpsMapPoint bb[2], *l=NULL, *center=NULL; int px,py; dt_map_t *lib = (dt_map_t *)user_data; /* get bounding box coords */ osm_gps_map_get_bbox(lib->map, &bb[0], &bb[1]); float bb_0_lat = 0.0, bb_0_lon = 0.0, bb_1_lat = 0.0, bb_1_lon = 0.0; osm_gps_map_point_get_degrees(&bb[0], &bb_0_lat, &bb_0_lon); osm_gps_map_point_get_degrees(&bb[1], &bb_1_lat, &bb_1_lon); /* make the bounding box a little bigger to the west and south */ float lat0 = 0.0, lon0 = 0.0, lat1 = 0.0, lon1 = 0.0; OsmGpsMapPoint *pt0 = osm_gps_map_point_new_degrees(0.0, 0.0), *pt1 = osm_gps_map_point_new_degrees(0.0, 0.0); osm_gps_map_convert_screen_to_geographic(lib->map, 0, 0, pt0); osm_gps_map_convert_screen_to_geographic(lib->map, 1.5*ts, 1.5*ts, pt1); osm_gps_map_point_get_degrees(pt0, &lat0, &lon0); osm_gps_map_point_get_degrees(pt1, &lat1, &lon1); osm_gps_map_point_free(pt0); osm_gps_map_point_free(pt1); double south_border = lat0 - lat1, west_border = lon1 - lon0; /* get map view state and store */ int zoom = osm_gps_map_get_zoom(lib->map); center = osm_gps_map_get_center(lib->map); dt_conf_set_float("plugins/map/longitude", center->rlon); dt_conf_set_float("plugins/map/latitude", center->rlat); dt_conf_set_int("plugins/map/zoom", zoom); osm_gps_map_point_free(center); /* let's reset and reuse the main_query statement */ DT_DEBUG_SQLITE3_CLEAR_BINDINGS(lib->statements.main_query); DT_DEBUG_SQLITE3_RESET(lib->statements.main_query); /* bind bounding box coords for the main query */ DT_DEBUG_SQLITE3_BIND_DOUBLE(lib->statements.main_query, 1, bb_0_lon - west_border); DT_DEBUG_SQLITE3_BIND_DOUBLE(lib->statements.main_query, 2, bb_1_lon); DT_DEBUG_SQLITE3_BIND_DOUBLE(lib->statements.main_query, 3, bb_0_lat); DT_DEBUG_SQLITE3_BIND_DOUBLE(lib->statements.main_query, 4, bb_1_lat - south_border); /* query collection ids */ while(sqlite3_step(lib->statements.main_query) == SQLITE_ROW) { int32_t imgid = sqlite3_column_int(lib->statements.main_query, 0); cairo_set_source_rgba(cri, 0, 0, 0, 0.4); /* free l if allocated */ if (l) osm_gps_map_point_free(l); /* for each image check if within bbox */ const dt_image_t *cimg = dt_image_cache_read_get(darktable.image_cache, imgid); double longitude = cimg->longitude; double latitude = cimg->latitude; dt_image_cache_read_release(darktable.image_cache, cimg); if(isnan(latitude) || isnan(longitude)) continue; l = osm_gps_map_point_new_degrees(latitude, longitude); /* translate l into screen coords */ osm_gps_map_convert_geographic_to_screen(lib->map, l, &px, &py); /* dependent on scale draw different overlays */ if (zoom >= 14) { dt_mipmap_buffer_t buf; dt_mipmap_size_t mip = dt_mipmap_cache_get_matching_size(darktable.mipmap_cache, ts, ts); dt_mipmap_cache_read_get(darktable.mipmap_cache, &buf, imgid, mip, 0); cairo_surface_t *surface = NULL; if(buf.buf) { float ms = fminf( ts/(float)buf.width, ts/(float)buf.height); #if 0 // this doesn't work since osm-gps-map always gives 0/0 as mouse coords :( /* find out if the cursor is over the image */ if(pointerx >= px && pointerx <= (px + buf.width*ms + 4) && pointery <= (py - 8) && pointery >= (py - buf.height*ms - 8 - 4)) { printf("over\n"); cairo_set_source_rgba(cri, 1, 0, 0, 0.7); } // else // printf("%d/%d, %d/%d\n", px, py, pointerx, pointery); #endif const int32_t stride = cairo_format_stride_for_width (CAIRO_FORMAT_RGB24, buf.width); surface = cairo_image_surface_create_for_data (buf.buf, CAIRO_FORMAT_RGB24, buf.width, buf.height, stride); cairo_pattern_set_filter(cairo_get_source(cri), CAIRO_FILTER_NEAREST); cairo_save(cri); /* first of lets draw a pin */ cairo_move_to(cri, px, py); cairo_line_to(cri, px+8, py-8); cairo_line_to(cri, px+4, py-8); cairo_fill(cri); /* and the frame around image */ cairo_move_to(cri, px+2, py-8); cairo_line_to(cri, px+2 + (buf.width*ms) + 4, py-8); cairo_line_to(cri, px+2 + (buf.width*ms) + 4 , py-8-(buf.height*ms) - 4); cairo_line_to(cri, px+2 , py-8-(buf.height*ms) - 4); cairo_fill(cri); /* draw image*/ cairo_translate(cri, px+4, py - 8 - (buf.height*ms) - 2); cairo_scale(cri, ms, ms); cairo_set_source_surface (cri, surface, 0, 0); cairo_paint(cri); cairo_restore(cri); cairo_surface_destroy(surface); } } else { /* just draw a patch indicating that there is images at the location */ cairo_rectangle(cri, px-8, py-8, 16, 16); cairo_fill(cri); } } }
static void _view_map_changed_callback(OsmGpsMap *map, dt_view_t *self) { dt_map_t *lib = (dt_map_t *)self->data; const int ts = 64; OsmGpsMapPoint bb[2]; /* get bounding box coords */ osm_gps_map_get_bbox(map, &bb[0], &bb[1]); float bb_0_lat = 0.0, bb_0_lon = 0.0, bb_1_lat = 0.0, bb_1_lon = 0.0; osm_gps_map_point_get_degrees(&bb[0], &bb_0_lat, &bb_0_lon); osm_gps_map_point_get_degrees(&bb[1], &bb_1_lat, &bb_1_lon); /* make the bounding box a little bigger to the west and south */ float lat0 = 0.0, lon0 = 0.0, lat1 = 0.0, lon1 = 0.0; OsmGpsMapPoint *pt0 = osm_gps_map_point_new_degrees(0.0, 0.0), *pt1 = osm_gps_map_point_new_degrees(0.0, 0.0); osm_gps_map_convert_screen_to_geographic(map, 0, 0, pt0); osm_gps_map_convert_screen_to_geographic(map, 1.5*ts, 1.5*ts, pt1); osm_gps_map_point_get_degrees(pt0, &lat0, &lon0); osm_gps_map_point_get_degrees(pt1, &lat1, &lon1); osm_gps_map_point_free(pt0); osm_gps_map_point_free(pt1); double south_border = lat0 - lat1, west_border = lon1 - lon0; /* get map view state and store */ int zoom; float center_lat, center_lon; g_object_get(G_OBJECT(map), "zoom", &zoom, "latitude", ¢er_lat, "longitude", ¢er_lon, NULL); dt_conf_set_float("plugins/map/longitude", center_lon); dt_conf_set_float("plugins/map/latitude", center_lat); dt_conf_set_int("plugins/map/zoom", zoom); /* let's reset and reuse the main_query statement */ DT_DEBUG_SQLITE3_CLEAR_BINDINGS(lib->statements.main_query); DT_DEBUG_SQLITE3_RESET(lib->statements.main_query); /* bind bounding box coords for the main query */ DT_DEBUG_SQLITE3_BIND_DOUBLE(lib->statements.main_query, 1, bb_0_lon - west_border); DT_DEBUG_SQLITE3_BIND_DOUBLE(lib->statements.main_query, 2, bb_1_lon); DT_DEBUG_SQLITE3_BIND_DOUBLE(lib->statements.main_query, 3, bb_0_lat); DT_DEBUG_SQLITE3_BIND_DOUBLE(lib->statements.main_query, 4, bb_1_lat - south_border); DT_DEBUG_SQLITE3_BIND_DOUBLE(lib->statements.main_query, 5, center_lat); DT_DEBUG_SQLITE3_BIND_DOUBLE(lib->statements.main_query, 6, center_lon); /* remove the old images */ osm_gps_map_image_remove_all(map); if(lib->images) { g_slist_foreach(lib->images, (GFunc) g_free, NULL); g_slist_free(lib->images); lib->images = NULL; } /* add all images to the map */ gboolean needs_redraw = FALSE; dt_mipmap_size_t mip = dt_mipmap_cache_get_matching_size(darktable.mipmap_cache, ts, ts); while(sqlite3_step(lib->statements.main_query) == SQLITE_ROW) { int imgid = sqlite3_column_int(lib->statements.main_query, 0); dt_mipmap_buffer_t buf; dt_mipmap_cache_read_get(darktable.mipmap_cache, &buf, imgid, mip, DT_MIPMAP_BEST_EFFORT); if(buf.buf) { uint8_t *scratchmem = dt_mipmap_cache_alloc_scratchmem(darktable.mipmap_cache); uint8_t *buf_decompressed = dt_mipmap_cache_decompress(&buf, scratchmem); uint8_t *rgbbuf = g_malloc((buf.width+2)*(buf.height+2)*3); memset(rgbbuf, 64, (buf.width+2)*(buf.height+2)*3); for(int i=1; i<=buf.height; i++) for(int j=1; j<=buf.width; j++) for(int k=0; k<3; k++) rgbbuf[(i*(buf.width+2)+j)*3+k] = buf_decompressed[((i-1)*buf.width+j-1)*4+2-k]; int w=ts, h=ts; if(buf.width < buf.height) w = (buf.width*ts)/buf.height; // portrait else h = (buf.height*ts)/buf.width; // landscape GdkPixbuf *source = gdk_pixbuf_new_from_data(rgbbuf, GDK_COLORSPACE_RGB, FALSE, 8, (buf.width+2), (buf.height+2), (buf.width+2)*3, NULL, NULL); GdkPixbuf *scaled = gdk_pixbuf_scale_simple(source, w, h, GDK_INTERP_HYPER); //TODO: add back the arrow on the left lower corner of the image, pointing to the location const dt_image_t *cimg = dt_image_cache_read_get(darktable.image_cache, imgid); dt_map_image_t *entry = (dt_map_image_t*)g_malloc(sizeof(dt_map_image_t)); entry->imgid = imgid; entry->image = osm_gps_map_image_add_with_alignment(map, cimg->latitude, cimg->longitude, scaled, 0, 1); entry->width = w; entry->height = h; lib->images = g_slist_prepend(lib->images, entry); dt_image_cache_read_release(darktable.image_cache, cimg); if(source) g_object_unref(source); if(scaled) g_object_unref(scaled); g_free(rgbbuf); } else needs_redraw = TRUE; dt_mipmap_cache_read_release(darktable.mipmap_cache, &buf); } // not exactly thread safe, but should be good enough for updating the display static int timeout_event_source = 0; if(needs_redraw && timeout_event_source == 0) timeout_event_source = g_timeout_add_seconds(1, _view_map_redraw, self); // try again in a second, maybe some pictures have loaded by then else timeout_event_source = 0; }