Skip to content

Instantly share code, notes, and snippets.

@kamituel
Last active July 13, 2017 09:58
Show Gist options
  • Save kamituel/6465125 to your computer and use it in GitHub Desktop.
Save kamituel/6465125 to your computer and use it in GitHub Desktop.
Parsing GPX files (Android compatible).
package pl.kamituel.gpx;
import java.io.IOException;
import java.io.InputStream;
public class GpxParser {
private InputStream mIs = null;
private StringBuilder mStringBuilder = new StringBuilder();
public GpxParser (InputStream is) {
mIs = is;
}
public TrkPt nextTrkPt () throws IOException {
mStringBuilder.delete(0, mStringBuilder.length());
int c;
while ( (c = mIs.read()) != -1 ) {
mStringBuilder.append((char)c);
TrkPt trkpt = new TrkPt();
if (trkpt.parse(mStringBuilder)) {
return trkpt;
}
}
return null;
}
public TrkPtInputStream getTrkPtStream () {
return new TrkPtInputStream(this);
}
}
package pl.kamituel.gpx;
import java.io.IOException;
import java.util.Vector;
/**
* Created by kls on 6/18/13.
*/
public class GpxSmooth {
public static Iterable<TrkPt> compressGpx (GpxParser gpx, Double threshold) throws IOException {
Vector<TrkPt> res = new Vector<TrkPt>();
TrkPt pN = null;
TrkPt pN_1 = null;
TrkPt pN_2 = null;
while ((pN = gpx.nextTrkPt()) != null) {
if (threshold != null && pN_1 != null && pN_2 != null) {
if (distanceFromTheLine(pN, pN_2, pN_1) > threshold) {
res.add(pN);
}
} else {
res.add(pN);
}
pN_2 = pN_1;
pN_1 = pN;
}
return res;
}
public static double distanceFromTheLine(TrkPt p1, TrkPt p2, TrkPt x) {
double A = p1.getLon() - p2.getLon();
double B = p2.getLat() - p1.getLat();
double C = p1.getLat() * (p2.getLon() - p1.getLon()) - p1.getLon() * (p2.getLat() - p1.getLat());
return (A * x.getLat() + B * x.getLon() + C) / Math.sqrt(A*A + B*B);
}
}
package pl.kamituel.gpx;
import java.security.InvalidParameterException;
public class TrkPt {
private final static String START_TAG = "<trkpt ";
private final static String START_ANY_TAG = "<";
private final static String END_TAG_EMPTY = "/>";
private final static String END_TAG_FULL = "</trkpt>";
private final static String ATTR_LAT = "lat=\"";
private final static String ATTR_LON = "lon=\"";
private final static String ELEM_ELE = "<ele>";
private double mLat = 0.0;
private double mLon = 0.0;
private double mEle = Double.MIN_VALUE;
public TrkPt () {
}
private boolean parse (String s) {
int lat = s.indexOf(ATTR_LAT);
int lon = s.indexOf(ATTR_LON);
int ele = s.indexOf(ELEM_ELE);
if (lat < 0 || lon < 0) {
//throw new InvalidParameterException("trkpt without lat or lon attribute");
return false;
}
int endLat = s.indexOf("\"", lat + ATTR_LAT.length());
int endLon = s.indexOf("\"", lon + ATTR_LON.length());
mLat = Double.parseDouble(s.substring(lat+ATTR_LAT.length(), endLat));
mLon = Double.parseDouble(s.substring(lon+ATTR_LON.length(), endLon));
if (ele > 0) {
mEle = Double.parseDouble(s.substring(ele + ELEM_ELE.length(), s.indexOf("<", ele + ELEM_ELE.length())));
}
//System.out.println("lat " + (lat+ATTR_LAT.length()) + " endLat " + endLat);
return true;
}
public boolean parse (StringBuilder s) {
int startTag = s.indexOf(START_TAG);
if (startTag < 0) return false;
int nextTag = s.indexOf(START_ANY_TAG, startTag);
int endTagEmpty = s.indexOf(END_TAG_EMPTY, startTag);
int endTagFull = s.indexOf(END_TAG_FULL, startTag);
if (endTagEmpty + END_TAG_EMPTY.length() == s.length()) {
// It's like <trkpt .../>EOF
//System.out.println("matches 0 " + s.substring(startTag, endTagEmpty + END_TAG_EMPTY.length()));
return parse(s.substring(startTag, endTagEmpty + END_TAG_EMPTY.length()));
} else if (nextTag > 0 && endTagEmpty > 0 && nextTag < endTagEmpty) {
// It's like <trkpt ...><...
if (nextTag == endTagFull) {
// It's like <trkpt ...></trkpt>
return parse(s.substring(startTag, endTagFull + END_TAG_FULL.length()));
} else if (endTagFull > 0) {
// It's like <trkpt ...>...</trkpt>
//System.out.println("matches 2 " + s.substring(startTag, endTagFull + END_TAG_FULL.length()));
return parse(s.substring(startTag, endTagFull + END_TAG_FULL.length()));
} else {
return false;
}
} else if (nextTag > 0 && endTagFull > 0) {
//System.out.println("matches 3 " + s.substring(startTag, endTagFull + END_TAG_FULL.length()));
return parse(s.substring(startTag, endTagFull + END_TAG_FULL.length()));
} else {
//System.out.println("no match " + s.toString());
return false;
}
}
public double getLat() {
return mLat;
}
public double getLon() {
return mLon;
}
public double getEle () {
return mEle;
}
}
package pl.kamituel.gpx;
import java.io.IOException;
import java.io.InputStream;
/**
* Created by kls on 6/19/13.
*/
public class TrkPtInputStream extends InputStream {
private GpxParser mParser;
private StringBuilder mBuffer = new StringBuilder();
public TrkPtInputStream(GpxParser parser) {
mParser = parser;
}
@Override
public int read() throws IOException {
if (mBuffer.length() == 0) {
TrkPt point = mParser.nextTrkPt();
if (point == null) {
return -1;
}
mBuffer.append(point.getLat() + "," + point.getLon() + "\n");
}
int res = mBuffer.charAt(0);
mBuffer.deleteCharAt(0);
return res;
}
}
@ticofab
Copy link

ticofab commented Jan 24, 2016

Should it be useful to anybody, I made a library for this: https://github.com/ticofab/android-gpx-parser .

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment