/******************************************************************************* * 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.util.Iterator; import java.util.Observable; import org.andnav.osm.util.GeoPoint; import android.os.Bundle; import com.geeksville.util.IntArray; /** * Provides a compact in memory list of a series of locations * * @author kevinh Also supports serializing/deserializing to Android bundles for * IPC. */ public class LocationList extends Observable implements ILocationList { /** * latitude in _microdegrees_ (to save space/work with google maps) (degrees * * 1e6) */ public IntArray latitudeE6; /** * latitude in _microdegrees_ (to save space/work with google maps) (degrees * * 1e6) */ public IntArray longitudeE6; /** * Altitude in millimeters */ public IntArray altitudeMM; public IntArray timeMsec; /** * Create an empty location list */ public LocationList() { latitudeE6 = new IntArray(); longitudeE6 = new IntArray(); altitudeMM = new IntArray(); timeMsec = new IntArray(); } /** * Create a location list with reserved capacity * * @param numPoints */ public LocationList(int numPoints) { latitudeE6 = new IntArray(numPoints); longitudeE6 = new IntArray(numPoints); altitudeMM = new IntArray(numPoints); timeMsec = new IntArray(numPoints); } /** * Deserialize from a bundle * * @param src */ public LocationList(Bundle src) { latitudeE6 = new IntArray(src.getIntArray("latitudes")); longitudeE6 = new IntArray(src.getIntArray("longitudes")); altitudeMM = new IntArray(src.getIntArray("altitudes")); timeMsec = new IntArray(src.getIntArray("timemsec")); } /** * Deserialize from a DB * * @param cursor * we will close this cursor at the end of extraction */ /* * public LocationList(Cursor cursor) { int latCol = * cursor.getColumnIndexOrThrow(LocationLogDbAdapter.KEY_LATITUDE); int * longCol = * cursor.getColumnIndexOrThrow(LocationLogDbAdapter.KEY_LONGITUDE); int * altCol = cursor.getColumnIndexOrThrow(LocationLogDbAdapter.KEY_ALTITUDE); * * int numPts = cursor.getCount(); * * latitudeE6 = new IntArray(numPts); longitudeE6 = new IntArray(numPts); * altitude = new IntArray(numPts); * * for (int i = 0; i < numPts; i++) { latitudeE6.add((int) * (cursor.getDouble(latCol) * 1e6)); longitudeE6.add((int) * (cursor.getDouble(longCol) * 1e6)); altitude.add(cursor.getInt(altCol)); * * cursor.moveToNext(); } * * cursor.close(); } */ /** * Add a point to the end of our tracklog * * @param latitude * @param longitude * @param altitudeMM */ public void add(double latitude, double longitude, int altitudeMM, int timeMsec) { latitudeE6.add((int) (latitude * 1e6)); longitudeE6.add((int) (longitude * 1e6)); this.altitudeMM.add(altitudeMM); this.timeMsec.add(timeMsec); setChanged(); notifyObservers(); } /** * Serialize to a bundle * * @param bundle */ public void writeTo(Bundle bundle) { bundle.putIntArray("latitudes", latitudeE6.toArray()); bundle.putIntArray("longitudes", longitudeE6.toArray()); bundle.putIntArray("altitudes", altitudeMM.toArray()); bundle.putIntArray("timemsec", timeMsec.toArray()); } /* * (non-Javadoc) * * @see com.geeksville.location.ILocationList#numPoints() */ public int numPoints() { return timeMsec.length(); // Read the last incremented field, so we will // always underestimate the number of points // if we have a race condition } /* * (non-Javadoc) * * @see com.geeksville.location.ILocationList#getGeoPoint(int) */ public GeoPoint getGeoPoint(int i) { return new GeoPoint(latitudeE6.get(i), longitudeE6.get(i)); } /** * Altitude in millimeters * * @param i * point num * @return */ public int getAltitudeMM(int i) { return altitudeMM.get(i); } /** * Number of milliseconds since start of tracklog * * @param i * @return */ public int getTimeMsec(int i) { return timeMsec.get(i); } /** * Find the # of udegs between the two furthest points (useful for zooming) * * @return */ public int latitudeSpanE6() { return spanE6(latitudeE6); } /** * Find the # of udegs between the two furthest points (useful for zooming) * * @return */ public int longitudeSpanE6() { return spanE6(longitudeE6); } /** * Find the # of udegs between the two furthest points (useful for zooming) * * @return */ private int spanE6(IntArray pts) { int n = pts.length(); if (n == 0) return 0; int lowest = pts.get(0); int highest = lowest; for (int i = 1; i < n; i++) { int p = pts.get(i); if (p < lowest) lowest = p; else if (p > highest) highest = p; } return highest - lowest; } @Override public Iterator<GeoPoint> iterator() { // TODO Auto-generated method stub return new Iterator<GeoPoint>() { private int pos = 0; @Override public boolean hasNext() { return pos < numPoints(); } @Override public GeoPoint next() { return getGeoPoint(pos++); } @Override public void remove() { throw new UnsupportedOperationException(); } }; } }