/*******************************************************************************
* Gaggle is Copyright 2010 by Geeksville Industries LLC, a California limited liability corporation.
*
* Gaggle is distributed under a dual license. We've chosen this approach because within Gaggle we've used a number
* of components that Geeksville Industries LLC might reuse for commercial products. Gaggle can be distributed under
* either of the two licenses listed below.
*
* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* Commercial Distribution License
* If you would like to distribute Gaggle (or portions thereof) under a license other than
* the "GNU General Public License, version 2", contact Geeksville Industries. Geeksville Industries reserves
* the right to release Gaggle source code under a commercial license of its choice.
*
* GNU Public License, version 2
* All other distribution of Gaggle must conform to the terms of the GNU Public License, version 2. The full
* text of this license is included in the Gaggle source, see assets/manual/gpl-2.0.txt.
******************************************************************************/
package com.geeksville.location;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import android.location.Location;
import android.util.Log;
/**
* Reads IGC files
*
* @author kevinh
*
*/
public class IGCReader {
BufferedReader inData;
SimpleDateFormat formater = new SimpleDateFormat("HHmmss");
private static final String TAG = "IGCReader";
/**
* populated in our location objects
*/
String provider;
public IGCReader(String provider, InputStream stream) {
inData = new BufferedReader(new InputStreamReader(stream));
}
public void close() throws IOException {
inData.close();
}
/**
* read the next location from the file (or null for eof)
*
* @return
* @throws ParseException
* @throws IOException
*/
public Location readLocation() throws ParseException, IOException {
Location res = null;
do {
String line = inData.readLine();
if (line == null)
return null; // eof
if (line.startsWith("B")) {
// This is a position record
// B
// HHMMSS - time UTC
// DDMMmmmN(or S) latitude
// DDDMMmmmE(or W) longitude
// A (3d valid) or V (2d only)
// PPPPP pressure altitude (00697 in this case)
// GGGGG alt above WGS ellipsode (00705 in this case)
// GSP is 000 here (ground speed in km/hr)
// B2109233921018N12239641WA0051600526000
// int hr = Integer.parseInt(line.substring(1, 3));
// int min = Integer.parseInt(line.substring(3, 5));
// int sec = Integer.parseInt(line.substring(5, 7));
String timestr = line.substring(1, 7);
int latdeg = Integer.parseInt(line.substring(7, 9));
int latmin = Integer.parseInt(line.substring(9, 11));
double latminfract = Integer.parseInt(line.substring(11, 14));
char latdir = line.charAt(14);
int longdeg = Integer.parseInt(line.substring(15, 18));
int longmin = Integer.parseInt(line.substring(18, 20));
double longminfract = Integer.parseInt(line.substring(20, 23));
char longdir = line.charAt(23);
int alt = Integer.parseInt(line.substring(25, 25 + 5));
double lat = (latdeg + (latmin + latminfract / 1000) / 60.0)
* (latdir == 'N' ? 1 : -1);
double ltude = (longdeg + (longmin + longminfract / 1000) / 60.0)
* (longdir == 'E' ? 1 : -1);
// Date d = new Date(); // Claim the flight is happening now
Date d = formater.parse(timestr);
// FIXME - we should also pay attention to the TZ and the date
// stored in the file header
res = new Location(provider);
res.setAltitude(alt);
res.setTime(d.getTime());
res.setLatitude(lat);
res.setLongitude(ltude);
// Log.d(TAG, "SimPos: " + lat + "," + ltude + "," + alt);
}
} while (res == null);
return res;
}
/**
* Return an in memory copy of just the points in this IGC file
*
* @return
*/
public LocationList toLocationList() {
LocationList l = new LocationList();
long firstTime = -1;
Location p;
try {
while ((p = readLocation()) != null) {
long newTime = p.getTime();
if (firstTime == -1)
firstTime = newTime;
l.add(p.getLatitude(), p.getLongitude(), (int) (p.getAltitude() * 1000.0),
(int) (newTime - firstTime));
}
} catch (Exception ex) {
Log.w(TAG, "Malformed IGC file - ignoring error");
}
return l;
}
}