altoslib: Finish AltosState changes. Update version number.
[fw/altos] / altosui / 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 altosui;
19
20 import java.io.*;
21 import org.altusmetrum.altoslib_2.*;
22
23 public class AltosKML implements AltosWriter {
24
25         File                    name;
26         PrintStream             out;
27         int                     flight_state = -1;
28         AltosState              prev = null;
29         double                  gps_start_altitude;
30
31         static final String[] kml_state_colors = {
32                 "FF000000",
33                 "FF000000",
34                 "FF000000",
35                 "FF0000FF",
36                 "FF4080FF",
37                 "FF00FFFF",
38                 "FFFF0000",
39                 "FF00FF00",
40                 "FF000000",
41                 "FFFFFFFF"
42         };
43
44         static final String kml_header_start =
45                 "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" +
46                 "<kml xmlns=\"http://www.opengis.net/kml/2.2\">\n" +
47                 "<Document>\n" +
48                 "  <name>AO Flight#%d S/N: %03d</name>\n" +
49                 "  <description>\n";
50         static final String kml_header_end =
51                 "  </description>\n" +
52                 "  <open>0</open>\n";
53
54         static final String kml_style_start =
55                 "  <Style id=\"ao-flightstate-%s\">\n" +
56                 "    <LineStyle><color>%s</color><width>4</width></LineStyle>\n" +
57                 "    <BalloonStyle>\n" +
58                 "      <text>\n";
59
60         static final String kml_style_end =
61                 "      </text>\n" +
62                 "    </BalloonStyle>\n" +
63                 "  </Style>\n";
64
65         static final String kml_placemark_start =
66                 "  <Placemark>\n" +
67                 "    <name>%s</name>\n" +
68                 "    <styleUrl>#ao-flightstate-%s</styleUrl>\n" +
69                 "    <LineString>\n" +
70                 "      <tessellate>1</tessellate>\n" +
71                 "      <altitudeMode>absolute</altitudeMode>\n" +
72                 "      <coordinates>\n";
73
74         static final String kml_coord_fmt =
75         "        %.7f,%.7f,%.7f <!-- alt %12.7f time %12.7f sats %d -->\n";
76
77         static final String kml_placemark_end =
78                 "      </coordinates>\n" +
79                 "    </LineString>\n" +
80                 "  </Placemark>\n";
81
82         static final String kml_footer =
83                 "</Document>\n" +
84                 "</kml>\n";
85
86         void start (AltosState record) {
87                 out.printf(kml_header_start, record.flight, record.serial);
88                 out.printf("Date:   %04d-%02d-%02d\n",
89                            record.gps.year, record.gps.month, record.gps.day);
90                 out.printf("Time:     %2d:%02d:%02d\n",
91                            record.gps.hour, record.gps.minute, record.gps.second);
92                 out.printf("%s", kml_header_end);
93         }
94
95         boolean started = false;
96
97         void state_start(AltosState state) {
98                 String  state_name = Altos.state_name(state.state);
99                 out.printf(kml_style_start, state_name, kml_state_colors[state.state]);
100                 out.printf("\tState: %s\n", state_name);
101                 out.printf("%s", kml_style_end);
102                 out.printf(kml_placemark_start, state_name, state_name);
103         }
104
105         void state_end(AltosState state) {
106                 out.printf("%s", kml_placemark_end);
107         }
108
109         void coord(AltosState state) {
110                 AltosGPS        gps = state.gps;
111                 double          altitude;
112
113                 if (state.height() != AltosLib.MISSING)
114                         altitude = state.height() + gps_start_altitude;
115                 else
116                         altitude = gps.alt;
117                 out.printf(kml_coord_fmt,
118                            gps.lon, gps.lat,
119                            altitude, (double) gps.alt,
120                            state.time, gps.nsat);
121         }
122
123         void end() {
124                 out.printf("%s", kml_footer);
125         }
126
127         public void close() {
128                 if (prev != null) {
129                         state_end(prev);
130                         end();
131                         prev = null;
132                 }
133         }
134
135         public void write(AltosState state) {
136                 AltosGPS        gps = state.gps;
137
138                 if (gps == null)
139                         return;
140
141                 if (gps.lat == AltosLib.MISSING)
142                         return;
143                 if (gps.lon == AltosLib.MISSING)
144                         return;
145                 if (!started) {
146                         start(state);
147                         started = true;
148                         gps_start_altitude = gps.alt;
149                 }
150                 if (prev != null && prev.gps_sequence == state.gps_sequence)
151                         return;
152                 if (state.state != flight_state) {
153                         flight_state = state.state;
154                         if (prev != null) {
155                                 coord(state);
156                                 state_end(prev);
157                         }
158                         state_start(state);
159                 }
160                 coord(state);
161                 prev = state;
162         }
163
164         public void write(AltosStateIterable states) {
165                 for (AltosState state : states) {
166                         if ((state.set & AltosState.set_gps) != 0)
167                                 write(state);
168                 }
169         }
170
171         public AltosKML(File in_name) throws FileNotFoundException {
172                 name = in_name;
173                 out = new PrintStream(name);
174         }
175
176         public AltosKML(String in_string) throws FileNotFoundException {
177                 this(new File(in_string));
178         }
179 }