altoslib/altosuilib: Update library version to 7
[fw/altos] / altoslib / AltosKML.java
1 /*
2  * Copyright © 2010 Keith Packard <keithp@keithp.com>
3  *
4  * This program is free software; you can redistribute it and/or modify
5  * it under the terms of the GNU General Public License as published by
6  * the Free Software Foundation; version 2 of the License.
7  *
8  * This program is distributed in the hope that it will be useful, but
9  * WITHOUT ANY WARRANTY; without even the implied warranty of
10  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
11  * General Public License for more details.
12  *
13  * You should have received a copy of the GNU General Public License along
14  * with this program; if not, write to the Free Software Foundation, Inc.,
15  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
16  */
17
18 package org.altusmetrum.altoslib_7;
19
20 import java.io.*;
21 import java.util.*;
22
23 class KMLWriter extends PrintWriter {
24         public PrintWriter printf(String format, Object ... arguments) {
25                 return printf(Locale.ROOT, format, arguments);
26         }
27
28         public KMLWriter(File name) throws FileNotFoundException {
29                 super(name);
30         }
31 }
32
33 public class AltosKML implements AltosWriter {
34
35         File                    name;
36         PrintWriter             out;
37         int                     flight_state = -1;
38         AltosState              prev = null;
39         double                  gps_start_altitude;
40
41         static final String[] kml_state_colors = {
42                 "FF000000",     // startup
43                 "FF000000",     // idle
44                 "FF000000",     // pad
45                 "FF0000FF",     // boost
46                 "FF4080FF",     // fast
47                 "FF00FFFF",     // coast
48                 "FFFF0000",     // drogue
49                 "FF00FF00",     // main
50                 "FF000000",     // landed
51                 "FFFFFFFF",     // invalid
52                 "FFFF0000",     // stateless
53         };
54
55         static String state_color(int state) {
56                 if (state < 0 || kml_state_colors.length <= state)
57                         return kml_state_colors[AltosLib.ao_flight_invalid];
58                 return kml_state_colors[state];
59         }
60
61         static final String kml_header_start =
62                 "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" +
63                 "<kml xmlns=\"http://www.opengis.net/kml/2.2\">\n" +
64                 "<Document>\n" +
65                 "  <name>AO Flight#%d S/N: %03d</name>\n" +
66                 "  <description>\n";
67         static final String kml_header_end =
68                 "  </description>\n" +
69                 "  <open>0</open>\n";
70
71         static final String kml_style_start =
72                 "  <Style id=\"ao-flightstate-%s\">\n" +
73                 "    <LineStyle><color>%s</color><width>4</width></LineStyle>\n" +
74                 "    <BalloonStyle>\n" +
75                 "      <text>\n";
76
77         static final String kml_style_end =
78                 "      </text>\n" +
79                 "    </BalloonStyle>\n" +
80                 "  </Style>\n";
81
82         static final String kml_placemark_start =
83                 "  <Placemark>\n" +
84                 "    <name>%s</name>\n" +
85                 "    <styleUrl>#ao-flightstate-%s</styleUrl>\n" +
86                 "    <LineString>\n" +
87                 "      <tessellate>1</tessellate>\n" +
88                 "      <altitudeMode>absolute</altitudeMode>\n" +
89                 "      <coordinates>\n";
90
91         static final String kml_coord_fmt =
92         "        %.7f,%.7f,%.7f <!-- alt %12.7f time %12.7f sats %d -->\n";
93
94         static final String kml_placemark_end =
95                 "      </coordinates>\n" +
96                 "    </LineString>\n" +
97                 "  </Placemark>\n";
98
99         static final String kml_footer =
100                 "</Document>\n" +
101                 "</kml>\n";
102
103         void start (AltosState record) {
104                 out.printf(kml_header_start, record.flight, record.serial);
105                 out.printf("Date:   %04d-%02d-%02d\n",
106                            record.gps.year, record.gps.month, record.gps.day);
107                 out.printf("Time:     %2d:%02d:%02d\n",
108                            record.gps.hour, record.gps.minute, record.gps.second);
109                 out.printf("%s", kml_header_end);
110         }
111
112         boolean started = false;
113
114         void state_start(AltosState state) {
115                 String  state_name = AltosLib.state_name(state.state);
116                 String  state_color = state_color(state.state);
117                 out.printf(kml_style_start, state_name, state_color);
118                 out.printf("\tState: %s\n", state_name);
119                 out.printf("%s", kml_style_end);
120                 out.printf(kml_placemark_start, state_name, state_name);
121         }
122
123         void state_end(AltosState state) {
124                 out.printf("%s", kml_placemark_end);
125         }
126
127         void coord(AltosState state) {
128                 AltosGPS        gps = state.gps;
129                 double          altitude;
130
131                 if (state.height() != AltosLib.MISSING)
132                         altitude = state.height() + gps_start_altitude;
133                 else
134                         altitude = gps.alt;
135                 out.printf(kml_coord_fmt,
136                            gps.lon, gps.lat,
137                            altitude, (double) gps.alt,
138                            state.time, gps.nsat);
139         }
140
141         void end() {
142                 out.printf("%s", kml_footer);
143         }
144
145         public void close() {
146                 if (prev != null) {
147                         state_end(prev);
148                         end();
149                         prev = null;
150                 }
151                 if (out != null) {
152                         out.close();
153                         out = null;
154                 }
155         }
156
157         public void write(AltosState state) {
158                 AltosGPS        gps = state.gps;
159
160                 if (gps == null)
161                         return;
162
163                 if (gps.lat == AltosLib.MISSING)
164                         return;
165                 if (gps.lon == AltosLib.MISSING)
166                         return;
167                 if (!started) {
168                         start(state);
169                         started = true;
170                         gps_start_altitude = gps.alt;
171                 }
172                 if (prev != null && prev.gps_sequence == state.gps_sequence)
173                         return;
174                 if (state.state != flight_state) {
175                         flight_state = state.state;
176                         if (prev != null) {
177                                 coord(state);
178                                 state_end(prev);
179                         }
180                         state_start(state);
181                 }
182                 coord(state);
183                 prev = state;
184         }
185
186         public void write(AltosStateIterable states) {
187                 for (AltosState state : states) {
188                         if ((state.set & AltosState.set_gps) != 0)
189                                 write(state);
190                 }
191         }
192
193         public AltosKML(File in_name) throws FileNotFoundException {
194                 name = in_name;
195                 out = new KMLWriter(name);
196         }
197
198         public AltosKML(String in_string) throws FileNotFoundException {
199                 this(new File(in_string));
200         }
201 }