+static const char *kml_state_colours[] = {
+ "FF000000",
+ "FF000000",
+ "FF000000",
+ "FF0000FF",
+ "FF4080FF",
+ "FF00FFFF",
+ "FFFF0000",
+ "FF00FF00",
+ "FF000000",
+ "FFFFFFFF"
+};
+
+static int plot_colors[3][3] = {
+ { 0, 0x90, 0 }, /* height */
+ { 0xa0, 0, 0 }, /* speed */
+ { 0, 0, 0xc0 }, /* accel */
+};
+
+#define PLOT_HEIGHT 0
+#define PLOT_SPEED 1
+#define PLOT_ACCEL 2
+
+static void
+plot_perioddata(struct cc_perioddata *d, char *axis_label, char *plot_label,
+ double min_time, double max_time, int plot_type)
+{
+ double *times;
+ double ymin, ymax;
+ int ymin_i, ymax_i;
+ int i;
+ int start, stop;
+
+ if (!cc_perioddata_limits(d, min_time, max_time, &start, &stop))
+ return;
+
+ times = calloc(stop - start + 1, sizeof (double));
+ for (i = start; i <= stop; i++)
+ times[i-start] = i * d->step / 100.0;
+
+ ymin_i = cc_perioddata_min(d, min_time, max_time);
+ ymax_i = cc_perioddata_max(d, min_time, max_time);
+ ymin = d->data[ymin_i];
+ ymax = d->data[ymax_i];
+ plscol0(1, 0, 0, 0);
+ plscol0(2, plot_colors[plot_type][0], plot_colors[plot_type][1], plot_colors[plot_type][2]);
+ plcol0(1);
+ plenv(times[0], times[stop-start],
+ ymin, ymax, 0, 2);
+ pllab("Time", axis_label, plot_label);
+ plcol0(2);
+ plline(stop - start + 1, times, d->data + start);
+ free(times);
+}
+
+static void
+plot_timedata(struct cc_timedata *d, char *axis_label, char *plot_label,
+ double min_time, double max_time, int plot_type)
+{
+ double *times;
+ double *values;
+ double ymin, ymax;
+ int ymin_i, ymax_i;
+ int i;
+ int start = -1, stop = -1;
+ double start_time = 0, stop_time = 0;
+ int num;
+
+ for (i = 0; i < d->num; i++) {
+ if (start < 0 && d->data[i].time >= min_time) {
+ start_time = d->data[i].time;
+ start = i;
+ }
+ if (d->data[i].time <= max_time) {
+ stop_time = d->data[i].time;
+ stop = i;
+ }
+ }
+
+ times = calloc(stop - start + 1, sizeof (double));
+ values = calloc(stop - start + 1, sizeof (double));
+
+ ymin_i = cc_timedata_min(d, min_time, max_time);
+ ymax_i = cc_timedata_max(d, min_time, max_time);
+ ymin = d->data[ymin_i].value;
+ ymax = d->data[ymax_i].value;
+ for (i = start; i <= stop; i++) {
+ times[i-start] = (d->data[i].time - start_time)/100.0;
+ values[i-start] = d->data[i].value;
+ }
+ plscol0(1, 0, 0, 0);
+ plscol0(2, plot_colors[plot_type][0], plot_colors[plot_type][1], plot_colors[plot_type][2]);
+ plcol0(1);
+ plenv(times[0], times[stop-start], ymin, ymax, 0, 2);
+ pllab("Time", axis_label, plot_label);
+ plcol0(2);
+ plline(stop - start + 1, times, values);
+ free(times);
+ free(values);
+}
+
+static struct cc_perioddata *
+merge_data(struct cc_perioddata *first, struct cc_perioddata *last, double split_time)
+{
+ int i;
+ struct cc_perioddata *pd;
+ int num;
+ double start_time, stop_time;
+ double t;
+
+ pd = calloc(1, sizeof (struct cc_perioddata));
+ start_time = first->start;
+ stop_time = last->start + last->step * last->num;
+ num = (stop_time - start_time) / first->step;
+ pd->num = num;
+ pd->data = calloc(num, sizeof (double));
+ pd->start = first->start;
+ pd->step = first->step;
+ for (i = 0; i < num; i++) {
+ t = pd->start + i * pd->step;
+ if (t <= split_time) {
+ pd->data[i] = first->data[i];
+ } else {
+ int j;
+
+ j = (t - last->start) / last->step;
+ if (j < 0 || j >= last->num)
+ pd->data[i] = 0;
+ else
+ pd->data[i] = last->data[j];
+ }
+ }
+ return pd;
+}
+
+static const char kml_header_start[] =
+ "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
+ "<kml xmlns=\"http://www.opengis.net/kml/2.2\">\n"
+ "<Document>\n"
+ " <name>%s</name>\n"
+ " <description>\n";
+static const char kml_header_end[] =
+ " </description>\n"
+ " <open>0</open>\n";
+
+static const char kml_style_start[] =
+ " <Style id=\"ao-flightstate-%s\">\n"
+ " <LineStyle><color>%s</color><width>4</width></LineStyle>\n"
+ " <BalloonStyle>\n"
+ " <text>\n";
+static const char kml_style_end[] =
+ " </text>\n"
+ " </BalloonStyle>\n"
+ " </Style>\n";
+
+static const char kml_placemark_start[] =
+ " <Placemark>\n"
+ " <name>%s</name>\n"
+ " <styleUrl>#ao-flightstate-%s</styleUrl>\n"
+ " <LineString>\n"
+ " <tessellate>1</tessellate>\n"
+ " <altitudeMode>absolute</altitudeMode>\n"
+ " <coordinates>\n";
+
+static const char kml_coord_fmt[] =
+ " %12.7f, %12.7f, %12.7f <!-- alt %12.7f time %12.7f sats %d -->\n";
+
+static const char kml_placemark_end[] =
+ " </coordinates>\n"
+ " </LineString>\n"
+ " </Placemark>\n";
+
+static const char kml_footer[] =
+ " </coordinates>\n"
+ " </LineString>\n"
+ " </Placemark>\n"
+ "</Document>\n"
+ "</kml>\n";
+
+static unsigned
+gps_daytime(struct cc_gpselt *gps)
+{
+ return ((gps->hour * 60 +
+ gps->minute) * 60 +
+ gps->second) * 1000;
+}
+
+int
+daytime_hour(unsigned daytime)
+{
+ return daytime / 1000 / 60 / 60;
+}
+
+int
+daytime_minute(unsigned daytime)
+{
+ return (daytime / 1000 / 60) % 60;
+}
+
+int
+daytime_second(unsigned daytime)
+{
+ return (daytime / 1000) % 60;
+}
+
+int
+daytime_millisecond(unsigned daytime)
+{
+ return daytime % 1000;
+}
+
+static unsigned
+compute_daytime_ms(double time, struct cc_gpsdata *gps)
+{
+ int i;
+ unsigned gps_start_daytime, gps_stop_daytime;
+
+ if (time <= gps->data[0].time) {
+ gps_stop_daytime = gps_daytime(&gps->data[0]);
+ return gps_stop_daytime - (gps->data[0].time - time) * 10;
+ }
+ for (i = 0; i < gps->num - 1; i++)
+ if (time > gps->data[i].time)
+ break;
+ gps_start_daytime = gps_daytime(&gps->data[i]);
+ if (i == gps->num - 1) {
+ return gps_start_daytime + (time - gps->data[i].time) * 10;
+ } else {
+ unsigned gps_period_daytime;
+ double gps_period_time;
+ double time_since_start;
+
+ gps_stop_daytime = gps_daytime(&gps->data[i + 1]);
+
+ /* range of gps daytime values */
+ gps_period_daytime = gps_stop_daytime - gps_start_daytime;
+
+ /* range of gps time values */
+ gps_period_time = gps->data[i+1].time - gps->data[i].time;
+
+ /* sample time after first gps time */
+ time_since_start = time - gps->data[i].time;
+
+ return gps_start_daytime +
+ gps_period_daytime * time_since_start / gps_period_time;
+ }
+}
+
+static void
+analyse_flight(struct cc_flightraw *f, FILE *summary_file, FILE *detail_file,
+ FILE *raw_file, char *plot_name, FILE *gps_file, FILE *kml_file)