1 package tim.prune.data;
4 * Class to represent a single data point in the series
5 * including all its fields
6 * Can be either a track point or a waypoint
10 // Hold these as Strings? Or FieldValue objects?
11 private String[] _fieldValues = null;
13 private FieldList _fieldList = null;
14 // Special fields for coordinates
15 private Coordinate _latitude = null, _longitude = null;
16 private Altitude _altitude;
17 private Timestamp _timestamp = null;
18 private boolean _pointValid = false;
21 // TODO: Make it possible to turn track point into waypoint - may need to alter FieldList
25 * @param inValueArray array of String values
26 * @param inFieldList list of fields
27 * @param inAltFormat altitude format
29 public DataPoint(String[] inValueArray, FieldList inFieldList, int inAltFormat)
32 _fieldValues = inValueArray;
33 // save list of fields
34 _fieldList = inFieldList;
37 _latitude = new Latitude(getFieldValue(Field.LATITUDE));
38 _longitude = new Longitude(getFieldValue(Field.LONGITUDE));
39 _altitude = new Altitude(getFieldValue(Field.ALTITUDE), inAltFormat);
40 _timestamp = new Timestamp(getFieldValue(Field.TIMESTAMP));
45 * Private constructor for artificially generated points (eg interpolated)
46 * @param inLatitude latitude
47 * @param inLongitude longitude
48 * @param inAltitude altitude
50 private DataPoint(Coordinate inLatitude, Coordinate inLongitude, Altitude inAltitude)
52 // Only these three fields are available
53 _fieldValues = new String[0];
54 _fieldList = new FieldList();
55 _latitude = inLatitude;
56 _longitude = inLongitude;
57 _altitude = inAltitude;
58 _timestamp = new Timestamp(null);
63 * Get the value for the given field
64 * @param inField field to interrogate
65 * @return value of field
67 public String getFieldValue(Field inField)
69 return getFieldValue(_fieldList.getFieldIndex(inField));
74 * Get the value at the given index
75 * @param inIndex index number starting at zero
76 * @return field value, or null if not found
78 public String getFieldValue(int inIndex)
80 if (_fieldValues == null || inIndex < 0 || inIndex >= _fieldValues.length)
82 return _fieldValues[inIndex];
86 public Coordinate getLatitude()
90 public Coordinate getLongitude()
94 public boolean hasAltitude()
96 return _altitude.isValid();
98 public Altitude getAltitude()
102 public boolean hasTimestamp()
104 return _timestamp.isValid();
106 public Timestamp getTimestamp()
112 * @return true if point has a waypoint name
114 public boolean isWaypoint()
116 String name = getFieldValue(Field.WAYPT_NAME);
117 return (name != null && !name.equals(""));
121 * Compare two DataPoint objects to see if they
123 * @param inOther other object to compare
124 * @return true if the points are equivalent
126 public boolean isDuplicate(DataPoint inOther)
128 if (inOther == null) return false;
129 if (_longitude == null || _latitude == null
130 || inOther._longitude == null || inOther._latitude == null)
134 // Compare latitude and longitude
135 if (!_longitude.equals(inOther._longitude) || !_latitude.equals(inOther._latitude))
139 // Note that conversion from decimal to dms can make non-identical points into duplicates
140 // Compare description (if any)
141 String name1 = getFieldValue(Field.WAYPT_NAME);
142 String name2 = inOther.getFieldValue(Field.WAYPT_NAME);
143 if (name1 == null || name1.equals(""))
145 return (name2 == null || name2.equals(""));
149 return (name2 != null && name2.equals(name1));
155 * @return true if the point is valid
157 public boolean isValid()
159 return _latitude.isValid() && _longitude.isValid();
164 * Interpolate a set of points between this one and the given one
165 * @param inEndPoint end point of interpolation
166 * @param inNumPoints number of points to generate
167 * @return the DataPoint array
169 public DataPoint[] interpolate(DataPoint inEndPoint, int inNumPoints)
171 DataPoint[] range = new DataPoint[inNumPoints];
172 Coordinate endLatitude = inEndPoint.getLatitude();
173 Coordinate endLongitude = inEndPoint.getLongitude();
174 Altitude endAltitude = inEndPoint.getAltitude();
177 for (int i=0; i<inNumPoints; i++)
179 Coordinate latitude = Coordinate.interpolate(_latitude, endLatitude, i, inNumPoints);
180 Coordinate longitude = Coordinate.interpolate(_longitude, endLongitude, i, inNumPoints);
181 Altitude altitude = Altitude.interpolate(_altitude, endAltitude, i, inNumPoints);
182 range[i] = new DataPoint(latitude, longitude, altitude);
189 * Calculate the number of radians between two points (for distance calculation)
190 * @param inPoint1 first point
191 * @param inPoint2 second point
192 * @return angular distance between points in radians
194 public static double calculateRadiansBetween(DataPoint inPoint1, DataPoint inPoint2)
196 if (inPoint1 == null || inPoint2 == null)
198 final double TO_RADIANS = Math.PI / 180.0;
199 // Get lat and long from points
200 double lat1 = inPoint1.getLatitude().getDouble() * TO_RADIANS;
201 double lat2 = inPoint2.getLatitude().getDouble() * TO_RADIANS;
202 double lon1 = inPoint1.getLongitude().getDouble() * TO_RADIANS;
203 double lon2 = inPoint2.getLongitude().getDouble() * TO_RADIANS;
204 // Formula given by Wikipedia:Great-circle_distance as follows:
205 // angle = 2 arcsin( sqrt( (sin ((lat2-lat1)/2))^^2 + cos(lat1)cos(lat2)(sin((lon2-lon1)/2))^^2))
206 double firstSine = Math.sin((lat2-lat1) / 2.0);
207 double secondSine = Math.sin((lon2-lon1) / 2.0);
208 double term2 = Math.cos(lat1) * Math.cos(lat2) * secondSine * secondSine;
209 double answer = 2 * Math.asin(Math.sqrt(firstSine*firstSine + term2));