+
+/******************* Track handling routines *****************/
+
+static void
+gps_track_init(struct gps_track_t *track)
+{
+ /* Save a spot at the end for the NULL termination */
+ track->points = (gpointer)g_new0(double*, NUM_TRACK_GROUPS + 1);
+ track->cur_point = 0;
+ track->cur_group = 0;
+ track->num_points = 1; /* starts at 1 so realloc logic works */
+ track->line = NULL;
+}
+
+static void
+gps_track_clear(struct gps_track_t *track)
+{
+ int pi;
+ for (pi = 0; pi < NUM_TRACK_GROUPS; pi++) {
+ if (track->points[pi] != NULL) {
+ g_free(track->points[pi]);
+ track->points[pi] = NULL;
+ }
+ }
+ track->cur_point = 0;
+ track->cur_group = 0;
+ track->num_points = 1; /* starts at 1 so realloc logic works */
+}
+
+static void
+gps_track_free(struct gps_track_t *track)
+{
+ gps_track_clear(track);
+ g_free(track->points);
+}
+
+/* add a new track group (points in a track group are connected, and
+ * separated from points in other track groups).
+ */
+static void
+gps_track_group_incr(struct gps_track_t *track)
+{
+ gdouble (**points)[3] = track->points; /* for simplicity */
+
+ /* Just return if they increment it again before any points have
+ * been added.
+ */
+ if (points[track->cur_group] == NULL) {
+ return;
+ }
+
+ g_debug("track_group_incr: incrementing track group to %u.",
+ track->cur_group + 1);
+
+ track->cur_group++;
+ track->cur_point = 0;
+ track->num_points = 1; /* starts at 1 so realloc logic works */
+
+ if (track->cur_group >= NUM_TRACK_GROUPS) {
+ g_debug("track_group_incr: current track group %u is at max %u, "
+ "shifting groups.",
+ track->cur_group, NUM_TRACK_GROUPS);
+
+ /* Free the oldest one which falls off the end */
+ g_free(points[0]);
+
+ /* shift the rest down, last one should always be NULL already */
+ /* note we alloc NUM_TRACK_GROUPS+1 */
+ for (int pi = 0; pi < NUM_TRACK_GROUPS; pi++) {
+ points[pi] = points[pi+1];
+ }
+
+ /* always write into the last group */
+ track->cur_group = NUM_TRACK_GROUPS - 1;
+ }
+}
+
+static void
+gps_track_add_point(struct gps_track_t *track, gdouble lat, gdouble lon,
+ gdouble elevation)
+{
+ gdouble (**points)[3] = track->points; /* for simplicity */
+
+ g_debug("GritsPluginGPS: track_add_point");
+
+ g_assert(track->cur_group < NUM_TRACK_GROUPS &&
+ (track->cur_point <= track->num_points));
+
+ /* resize/allocate the point group if the current one is full */
+ if (track->cur_point >= track->num_points - 1) {
+ guint new_size = track->num_points == 1 ?
+ NUM_TRACK_POINTS :
+ track->num_points * NUM_TRACK_POINTS_FACTOR;
+ g_debug("GritsPluginGPS: track_add_point: reallocating points "
+ "array from %u points to %u points.\n",
+ track->num_points, new_size);
+ points[track->cur_group] = (gpointer)g_renew(gdouble,
+ points[track->cur_group], 3*(new_size+1));
+ track->num_points = new_size;
+ }
+
+ g_assert(points[track->cur_group] != NULL);
+
+ /* Add the coordinate */
+ lle2xyz(lat, lon, elevation,
+ &points[track->cur_group][track->cur_point][0],
+ &points[track->cur_group][track->cur_point][1],
+ &points[track->cur_group][track->cur_point][2]);
+
+ track->cur_point++;
+
+ /* make sure last point is always 0s so the line drawing stops. */
+ points[track->cur_group][track->cur_point][0] = 0.0;
+ points[track->cur_group][track->cur_point][1] = 0.0;
+ points[track->cur_group][track->cur_point][2] = 0.0;
+}
+
+