Example #1
0
/**
 * Make a speed/distance map
 */
gdouble *vik_track_make_speed_dist_map ( const VikTrack *tr, guint16 num_chunks )
{
  gdouble *v, *s, *t;
  time_t t1, t2;
  gint i, pt_count, numpts, index;
  GList *iter;
  gdouble duration, total_length, chunk_length;

  if ( ! tr->trackpoints )
    return NULL;

  t1 = VIK_TRACKPOINT(tr->trackpoints->data)->timestamp;
  t2 = VIK_TRACKPOINT(g_list_last(tr->trackpoints)->data)->timestamp;
  duration = t2 - t1;

  if ( !t1 || !t2 || !duration )
    return NULL;

  if (duration < 0) {
    g_warning("negative duration: unsorted trackpoint timestamps?");
    return NULL;
  }

  total_length = vik_track_get_length_including_gaps ( tr );
  chunk_length = total_length / num_chunks;
  pt_count = vik_track_get_tp_count(tr);

  if (chunk_length <= 0) {
    return NULL;
  }

  v = g_malloc ( sizeof(gdouble) * num_chunks );
  s = g_malloc ( sizeof(double) * pt_count );
  t = g_malloc ( sizeof(double) * pt_count );

  // No special handling of segments ATM...
  iter = tr->trackpoints->next;
  numpts = 0;
  s[0] = 0;
  t[0] = VIK_TRACKPOINT(iter->prev->data)->timestamp;
  numpts++;
  while (iter) {
    s[numpts] = s[numpts-1] + vik_coord_diff ( &(VIK_TRACKPOINT(iter->prev->data)->coord), &(VIK_TRACKPOINT(iter->data)->coord) );
    t[numpts] = VIK_TRACKPOINT(iter->data)->timestamp;
    numpts++;
    iter = iter->next;
  }

  // Iterate through a portion of the track to get an average speed for that part
  // This will essentially interpolate between segments, which I think is right given the usage of 'get_length_including_gaps'
  index = 0; /* index of the current trackpoint. */
  for (i = 0; i < num_chunks; i++) {
    // Similar to the make_speed_map, but instead of using a time chunk, use a distance chunk
    if (s[0] + i*chunk_length >= s[index]) {
      gdouble acc_t = 0, acc_s = 0;
      while (s[0] + i*chunk_length >= s[index]) {
	acc_s += (s[index+1]-s[index]);
	acc_t += (t[index+1]-t[index]);
	index++;
      }
      v[i] = acc_s/acc_t;
    }
    else if (i) {
      v[i] = v[i-1];
    }
    else {
      v[i] = 0;
    }
  }
  g_free(s);
  g_free(t);
  return v;
}
Example #2
0
/**
 * Make a distance/time map, heavily based on the vik_track_make_speed_map method
 */
gdouble *vik_track_make_distance_map ( const VikTrack *tr, guint16 num_chunks )
{
  gdouble *v, *s, *t;
  gdouble duration, chunk_dur;
  time_t t1, t2;
  int i, pt_count, numpts, index;
  GList *iter;

  if ( ! tr->trackpoints )
    return NULL;

  t1 = VIK_TRACKPOINT(tr->trackpoints->data)->timestamp;
  t2 = VIK_TRACKPOINT(g_list_last(tr->trackpoints)->data)->timestamp;
  duration = t2 - t1;

  if ( !t1 || !t2 || !duration )
    return NULL;

  if (duration < 0) {
    g_warning("negative duration: unsorted trackpoint timestamps?");
    return NULL;
  }
  pt_count = vik_track_get_tp_count(tr);

  v = g_malloc ( sizeof(gdouble) * num_chunks );
  chunk_dur = duration / num_chunks;

  s = g_malloc(sizeof(double) * pt_count);
  t = g_malloc(sizeof(double) * pt_count);

  iter = tr->trackpoints->next;
  numpts = 0;
  s[0] = 0;
  t[0] = VIK_TRACKPOINT(iter->prev->data)->timestamp;
  numpts++;
  while (iter) {
    s[numpts] = s[numpts-1] + vik_coord_diff ( &(VIK_TRACKPOINT(iter->prev->data)->coord), &(VIK_TRACKPOINT(iter->data)->coord) );
    t[numpts] = VIK_TRACKPOINT(iter->data)->timestamp;
    numpts++;
    iter = iter->next;
  }

  /* In the following computation, we iterate through periods of time of duration chunk_dur.
   * The first period begins at the beginning of the track.  The last period ends at the end of the track.
   */
  index = 0; /* index of the current trackpoint. */
  for (i = 0; i < num_chunks; i++) {
    /* we are now covering the interval from t[0] + i*chunk_dur to t[0] + (i+1)*chunk_dur.
     * find the first trackpoint outside the current interval, averaging the distance between intermediate trackpoints.
     */
    if (t[0] + i*chunk_dur >= t[index]) {
      gdouble acc_s = 0; // No need for acc_t
      while (t[0] + i*chunk_dur >= t[index]) {
	acc_s += (s[index+1]-s[index]);
	index++;
      }
      // The only bit that's really different from the speed map - just keep an accululative record distance
      v[i] = i ? v[i-1]+acc_s : acc_s;
    }
    else if (i) {
      v[i] = v[i-1];
    }
    else {
      v[i] = 0;
    }
  }
  g_free(s);
  g_free(t);
  return v;
}
Example #3
0
/**
 * This uses the 'time' based method to make the graph, (which is a simpler compared to the elevation/distance)
 * This results in a slightly blocky graph when it does not have many trackpoints: <60
 * NB Somehow the elevation/distance applies some kind of smoothing algorithm,
 *   but I don't think any one understands it any more (I certainly don't ATM)
 */
gdouble *vik_track_make_elevation_time_map ( const VikTrack *tr, guint16 num_chunks )
{
  time_t t1, t2;
  gdouble duration, chunk_dur;
  GList *iter = tr->trackpoints;

  if (!iter || !iter->next) /* zero- or one-point track */
    return NULL;

  /* test if there's anything worth calculating */
  gboolean okay = FALSE;
  while ( iter ) {
    if ( VIK_TRACKPOINT(iter->data)->altitude != VIK_DEFAULT_ALTITUDE ) {
      okay = TRUE;
      break;
    }
    iter = iter->next;
  }
  if ( ! okay )
    return NULL;

  t1 = VIK_TRACKPOINT(tr->trackpoints->data)->timestamp;
  t2 = VIK_TRACKPOINT(g_list_last(tr->trackpoints)->data)->timestamp;
  duration = t2 - t1;

  if ( !t1 || !t2 || !duration )
    return NULL;

  if (duration < 0) {
    g_warning("negative duration: unsorted trackpoint timestamps?");
    return NULL;
  }
  gint pt_count = vik_track_get_tp_count(tr);

  // Reset iterator back to the beginning
  iter = tr->trackpoints;

  gdouble *pts = g_malloc ( sizeof(gdouble) * num_chunks ); // The return altitude values
  gdouble *s = g_malloc(sizeof(double) * pt_count); // calculation altitudes
  gdouble *t = g_malloc(sizeof(double) * pt_count); // calculation times

  chunk_dur = duration / num_chunks;

  s[0] = VIK_TRACKPOINT(iter->data)->altitude;
  t[0] = VIK_TRACKPOINT(iter->data)->timestamp;
  iter = tr->trackpoints->next;
  gint numpts = 1;
  while (iter) {
    s[numpts] = VIK_TRACKPOINT(iter->data)->altitude;
    t[numpts] = VIK_TRACKPOINT(iter->data)->timestamp;
    numpts++;
    iter = iter->next;
  }

 /* In the following computation, we iterate through periods of time of duration chunk_dur.
   * The first period begins at the beginning of the track.  The last period ends at the end of the track.
   */
  gint index = 0; /* index of the current trackpoint. */
  gint i;
  for (i = 0; i < num_chunks; i++) {
    /* we are now covering the interval from t[0] + i*chunk_dur to t[0] + (i+1)*chunk_dur.
     * find the first trackpoint outside the current interval, averaging the heights between intermediate trackpoints.
     */
    if (t[0] + i*chunk_dur >= t[index]) {
      gdouble acc_s = s[index]; // initialise to first point
      while (t[0] + i*chunk_dur >= t[index]) {
	acc_s += (s[index+1]-s[index]);
	index++;
      }
      pts[i] = acc_s;
    }
    else if (i) {
      pts[i] = pts[i-1];
    }
    else {
      pts[i] = 0;
    }
  }
  g_free(s);
  g_free(t);

  return pts;
}
Example #4
0
/**
 * @val_analyse_track:
 * @trk: The track to be analyse
 *
 * Function to collect statistics, using the internal track functions
 */
static void val_analyse_track ( VikTrack *trk )
{
	//val_reset ( TS_TRACK );
	gdouble min_alt;
	gdouble max_alt;
	gdouble up;
	gdouble down;

	gdouble  length      = 0.0;
	gdouble  length_gaps = 0.0;
	gdouble  max_speed   = 0.0;
	gulong   trackpoints = 0;
	guint    segments    = 0;

	tracks_stats[TS_TRACKS].count++;

	trackpoints = vik_track_get_tp_count (trk);
	segments    = vik_track_get_segment_count (trk);
	length      = vik_track_get_length (trk);
	length_gaps = vik_track_get_length_including_gaps (trk);
	max_speed   = vik_track_get_max_speed (trk);

    if ( !trk->is_route ) {
		// Eddington number will be in the current Units distance preference
		gdouble e_len;
		switch (a_vik_get_units_distance ()) {
		case VIK_UNITS_DISTANCE_MILES:          e_len = VIK_METERS_TO_MILES(length); break;
		case VIK_UNITS_DISTANCE_NAUTICAL_MILES: e_len = VIK_METERS_TO_NAUTICAL_MILES(length); break;
			//VIK_UNITS_DISTANCE_KILOMETRES
		default: e_len = length/1000.0; break;
		}
		gdouble *gd = g_malloc ( sizeof(gdouble) );
		*gd = e_len;
		tracks_stats[TS_TRACKS].e_list = g_list_prepend ( tracks_stats[TS_TRACKS].e_list, gd );
	}

	int ii;
	for (ii = 0; ii < G_N_ELEMENTS(tracks_stats); ii++) {
		tracks_stats[ii].trackpoints += trackpoints;
		tracks_stats[ii].segments    += segments;
		tracks_stats[ii].length      += length;
		tracks_stats[ii].length_gaps += length_gaps;
		if ( max_speed > tracks_stats[ii].max_speed )
			tracks_stats[ii].max_speed = max_speed;
	}

	if ( vik_track_get_minmax_alt (trk, &min_alt, &max_alt) ) {
		for (ii = 0; ii < G_N_ELEMENTS(tracks_stats); ii++) {
			if ( min_alt < tracks_stats[ii].min_alt )
				tracks_stats[ii].min_alt = min_alt;
			if ( max_alt > tracks_stats[ii].max_alt )
				tracks_stats[ii].max_alt = max_alt;
		}
	}

	vik_track_get_total_elevation_gain (trk, &up, &down );

	for (ii = 0; ii < G_N_ELEMENTS(tracks_stats); ii++) {
		tracks_stats[ii].elev_gain += up;
		tracks_stats[ii].elev_loss += down;
	}

	if ( trk->trackpoints && VIK_TRACKPOINT(trk->trackpoints->data)->timestamp ) {
		time_t t1, t2;
		t1 = VIK_TRACKPOINT(g_list_first(trk->trackpoints)->data)->timestamp;
		t2 = VIK_TRACKPOINT(g_list_last(trk->trackpoints)->data)->timestamp;

		// Assume never actually have a track with a time of 0 (1st Jan 1970)
		for (ii = 0; ii < G_N_ELEMENTS(tracks_stats); ii++) {
			if ( tracks_stats[ii].start_time == 0)
				tracks_stats[ii].start_time = t1;
			if ( tracks_stats[ii].end_time == 0)
				tracks_stats[ii].end_time = t2;
		}

		// Initialize to the first value
		for (ii = 0; ii < G_N_ELEMENTS(tracks_stats); ii++) {
			if (t1 < tracks_stats[ii].start_time)
				tracks_stats[ii].start_time = t1;
			if (t2 > tracks_stats[ii].end_time)
				tracks_stats[ii].end_time = t2;
		}

		for (ii = 0; ii < G_N_ELEMENTS(tracks_stats); ii++) {
			tracks_stats[ii].duration = tracks_stats[ii].duration + (int)(t2-t1);
		}
	}
}