63 const gchar **attribute_names,
const gchar **attribute_values,
64 gpointer ueer_data, GError **
error);
66 gpointer user_data, GError **
error);
67static void _gpx_parser_text(GMarkupParseContext *context,
const gchar *text, gsize text_len,
68 gpointer user_data, GError **
error);
78 return g_date_time_compare(pa->
time, pb->
time);
92 GMarkupParseContext *ctx = NULL;
96 GMappedFile *gpxmf = g_mapped_file_new(filename,
FALSE, &err);
99 gchar *gpxmf_content = g_mapped_file_get_contents(gpxmf);
100 const gint gpxmf_size = g_mapped_file_get_length(gpxmf);
107 if(gpxmf_content[0] ==
'\xef' && gpxmf_content[1] ==
'\xbb' && gpxmf_content[2] ==
'\xbf')
111 ctx = g_markup_parse_context_new(&
_gpx_parser, 0, gpx, NULL);
112 g_markup_parse_context_parse(ctx, gpxmf_content + bom_offset, gpxmf_size - bom_offset, &err);
116 g_markup_parse_context_free(ctx);
117 g_mapped_file_unref(gpxmf);
127 fprintf(stderr,
"dt_gpx_new: %s\n", err->message);
131 if(ctx) g_markup_parse_context_free(ctx);
135 if(gpxmf) g_mapped_file_unref(gpxmf);
148 g_date_time_unref(trkpt->
time);
177 for(GList *item = gpx->
trkpts; item; item = g_list_next(item))
183 const gint cmp = g_date_time_compare(timestamp, tp->
time);
184 if((
IS_NULL_PTR(item->next) && cmp >= 0) || (cmp <= 0))
194 const gint cmp_n = g_date_time_compare(timestamp, tp_next->
time);
195 if(item->next && cmp_n <= 0)
197 GTimeSpan seg_diff = g_date_time_difference(tp_next->
time, tp->
time);
198 GTimeSpan diff = g_date_time_difference(timestamp, tp->
time);
199 if(seg_diff == 0 || diff == 0)
214 const double lat2 = tp_next->
latitude;
219 const double f = (
double)diff / (
double)seg_diff;
225 lon = lon1 + (lon2 - lon1) *
f;
226 lat = lat1 + (lat2 - lat1) *
f;
275 const gchar **attribute_names,
const gchar **attribute_values,
276 gpointer user_data, GError **
error)
283 if(strcmp(element_name,
"trk") == 0)
291 if(strcmp(element_name,
"trkpt") == 0)
295 fprintf(stderr,
"broken GPX file, new trkpt element before the previous ended.\n");
299 const gchar **attribute_name = attribute_names;
300 const gchar **attribute_value = attribute_values;
315 while(*attribute_name)
317 if(strcmp(*attribute_name,
"lon") == 0)
319 else if(strcmp(*attribute_name,
"lat") == 0)
329 fprintf(stderr,
"broken GPX file, failed to get lon/lat attribute values for trkpt\n");
334 fprintf(stderr,
"broken GPX file, trkpt element doesn't have lon/lat attributes\n");
338 else if(strcmp(element_name,
"time") == 0)
344 else if(strcmp(element_name,
"ele") == 0)
350 else if(strcmp(element_name,
"name") == 0)
354 else if(strcmp(element_name,
"trkseg") == 0)
368 fprintf(stderr,
"broken GPX file, element '%s' found outside of trkpt.\n", element_name);
379 if(strcmp(element_name,
"trk") == 0)
383 else if(strcmp(element_name,
"trkpt") == 0)
391 else if(strcmp(element_name,
"trkseg") == 0)
401void _gpx_parser_text(GMarkupParseContext *context,
const gchar *text, gsize text_len, gpointer user_data,
423 fprintf(stderr,
"broken GPX file, failed to pars is8601 time '%s' for trackpoint\n", text);
449 GList *ts = g_list_nth(gpx->
trksegs, segid);
454 for(GList *tp = tps; tp; tp = g_list_next(tp))
457 if(tpd->
segid != segid)
return pts;
461 pts = g_list_prepend(pts,
p);
471 double lat2,
double lon2,
474 const double lat_rad_1 = lat1 *
M_PI / 180;
475 const double lat_rad_2 = lat2 *
M_PI / 180;
476 const double lon_rad_1 = lon1 *
M_PI / 180;
477 const double lon_rad_2 = lon2 *
M_PI / 180;
478 const double delta_lat_rad = lat_rad_2 - lat_rad_1;
479 const double delta_lon_rad = lon_rad_2 - lon_rad_1;
480 const double sin_delta_lat_rad = sin(delta_lat_rad / 2);
481 const double sin_delta_lon_rad = sin(delta_lon_rad / 2);
483 const double a = sin_delta_lat_rad * sin_delta_lat_rad +
484 cos(lat_rad_1) * cos(lat_rad_2) *
485 sin_delta_lon_rad * sin_delta_lon_rad;
486 *
delta = 2 * atan2(sqrt(a), sqrt(1 - a));
492 const double lat2,
const double lon2,
494 const gboolean first_time,
498 static double lat_rad_1;
499 static double sin_lat_rad_1;
500 static double cos_lat_rad_1;
501 static double lat_rad_2;
502 static double sin_lat_rad_2;
503 static double cos_lat_rad_2;
504 static double lon_rad_1;
505 static double sin_lon_rad_1;
506 static double cos_lon_rad_1;
507 static double lon_rad_2;
508 static double sin_lon_rad_2;
509 static double cos_lon_rad_2;
510 static double sin_delta;
514 lat_rad_1 = lat1 *
M_PI / 180;
515 sin_lat_rad_1 = sin(lat_rad_1);
516 cos_lat_rad_1 = cos(lat_rad_1);
517 lat_rad_2 = lat2 *
M_PI / 180;
518 sin_lat_rad_2 = sin(lat_rad_2);
519 cos_lat_rad_2 = cos(lat_rad_2);
520 lon_rad_1 = lon1 *
M_PI / 180;
521 sin_lon_rad_1 = sin(lon_rad_1);
522 cos_lon_rad_1 = cos(lon_rad_1);
523 lon_rad_2 = lon2 *
M_PI / 180;
524 sin_lon_rad_2 = sin(lon_rad_2);
525 cos_lon_rad_2 = cos(lon_rad_2);
526 sin_delta = sin(
delta);
529 const double a = sin((1 -
f) *
delta) / sin_delta;
530 const double b = sin(
f *
delta) / sin_delta;
531 const double x = a * cos_lat_rad_1 * cos_lon_rad_1 + b * cos_lat_rad_2 * cos_lon_rad_2;
532 const double y = a * cos_lat_rad_1 * sin_lon_rad_1 + b * cos_lat_rad_2 * sin_lon_rad_2;
533 const double z = a * sin_lat_rad_1 + b * sin_lat_rad_2;
534 const double lat_rad = atan2(z, sqrt(
x *
x + y * y));
535 const double lon_rad = atan2(y,
x);
static void error(char *msg)
static const dt_aligned_pixel_simd_t const dt_adaptation_t const float p
const dt_aligned_pixel_t f
#define IS_NULL_PTR(p)
C is way too permissive with !=, == and if(var) checks, which can mean too many things depending on w...
static gboolean g_list_shorter_than(const GList *list, unsigned len)
void dt_gpx_destroy(struct dt_gpx_t *gpx)
GList * dt_gpx_get_trkpts(struct dt_gpx_t *gpx, const guint segid)
static gint _sort_track(gconstpointer a, gconstpointer b)
static void _gpx_parser_text(GMarkupParseContext *context, const gchar *text, gsize text_len, gpointer user_data, GError **error)
static GMarkupParser _gpx_parser
void _track_seg_free(dt_gpx_track_segment_t *trkseg)
static void _gpx_parser_end_element(GMarkupParseContext *context, const gchar *element_name, gpointer user_data, GError **error)
gboolean dt_gpx_get_location(struct dt_gpx_t *gpx, GDateTime *timestamp, dt_image_geoloc_t *geoloc)
@ GPX_PARSER_ELEMENT_NAME
@ GPX_PARSER_ELEMENT_TRKPT
@ GPX_PARSER_ELEMENT_NONE
@ GPX_PARSER_ELEMENT_TIME
static gint _sort_segment(gconstpointer a, gconstpointer b)
dt_gpx_t * dt_gpx_new(const gchar *filename)
void _track_pts_free(dt_gpx_track_point_t *trkpt)
void dt_gpx_geodesic_intermediate_point(const double lat1, const double lon1, const double lat2, const double lon2, const double delta, const gboolean first_time, double f, double *lat, double *lon)
GList * dt_gpx_get_trkseg(struct dt_gpx_t *gpx)
static void _gpx_parser_start_element(GMarkupParseContext *ctx, const gchar *element_name, const gchar **attribute_names, const gchar **attribute_values, gpointer ueer_data, GError **error)
void dt_gpx_geodesic_distance(double lat1, double lon1, double lat2, double lon2, double *d, double *delta)
#define DT_MINIMUM_ANGULAR_DELTA_FOR_GEODESIC
gboolean invalid_track_point
_gpx_parser_element_t current_parser_element
dt_gpx_track_point_t * current_track_point
dt_gpx_track_point_t * trkpt
typedef double((*spd)(unsigned long int wavelength, double TempK))