package tim.prune.data;
+import tim.prune.config.Config;
+
/**
* Class to represent a single data point in the series
* including all its fields
private Coordinate _latitude = null, _longitude = null;
private Altitude _altitude;
private Timestamp _timestamp = null;
+ /** Attached photo */
private Photo _photo = null;
+ /** Attached audio clip */
+ private AudioClip _audio = null;
private String _waypointName = null;
- private boolean _pointValid = false;
-
+ private boolean _startOfSegment = false;
+ private boolean _markedForDeletion = false;
+ private int _modifyCount = 0;
/**
* Constructor
* @param inFieldList list of fields
* @param inAltFormat altitude format
*/
- public DataPoint(String[] inValueArray, FieldList inFieldList, int inAltFormat)
+ public DataPoint(String[] inValueArray, FieldList inFieldList, Altitude.Format inAltFormat)
{
// save data
_fieldValues = inValueArray;
// save list of fields
_fieldList = inFieldList;
+ // Remove double quotes around values
+ removeQuotes(_fieldValues);
// parse fields into objects
- parseFields(inAltFormat);
+ parseFields(null, inAltFormat);
}
/**
* Parse the string values into objects eg Coordinates
+ * @param inField field which has changed, or null for all
* @param inAltFormat altitude format
*/
- private void parseFields(int inAltFormat)
+ private void parseFields(Field inField, Altitude.Format inAltFormat)
{
- _latitude = new Latitude(getFieldValue(Field.LATITUDE));
- _longitude = new Longitude(getFieldValue(Field.LONGITUDE));
- _altitude = new Altitude(getFieldValue(Field.ALTITUDE), inAltFormat);
- _timestamp = new Timestamp(getFieldValue(Field.TIMESTAMP));
- _waypointName = getFieldValue(Field.WAYPT_NAME);
+ if (inField == null || inField == Field.LATITUDE) {
+ _latitude = new Latitude(getFieldValue(Field.LATITUDE));
+ }
+ if (inField == null || inField == Field.LONGITUDE) {
+ _longitude = new Longitude(getFieldValue(Field.LONGITUDE));
+ }
+ if (inField == null || inField == Field.ALTITUDE) {
+ _altitude = new Altitude(getFieldValue(Field.ALTITUDE), inAltFormat);
+ }
+ if (inField == null || inField == Field.TIMESTAMP) {
+ _timestamp = new Timestamp(getFieldValue(Field.TIMESTAMP));
+ }
+ if (inField == null || inField == Field.WAYPT_NAME) {
+ _waypointName = getFieldValue(Field.WAYPT_NAME);
+ }
+ if (inField == null || inField == Field.NEW_SEGMENT)
+ {
+ String segmentStr = getFieldValue(Field.NEW_SEGMENT);
+ if (segmentStr != null) {segmentStr = segmentStr.trim();}
+ _startOfSegment = (segmentStr != null && (segmentStr.equals("1") || segmentStr.toUpperCase().equals("Y")));
+ }
}
public DataPoint(Coordinate inLatitude, Coordinate inLongitude, Altitude inAltitude)
{
// Only these three fields are available
- _fieldValues = new String[0];
- _fieldList = new FieldList();
+ _fieldValues = new String[3];
+ Field[] fields = {Field.LATITUDE, Field.LONGITUDE, Field.ALTITUDE};
+ _fieldList = new FieldList(fields);
_latitude = inLatitude;
+ _fieldValues[0] = inLatitude.output(Coordinate.FORMAT_NONE);
_longitude = inLongitude;
- _altitude = inAltitude;
+ _fieldValues[1] = inLongitude.output(Coordinate.FORMAT_NONE);
+ if (inAltitude == null) {
+ _altitude = Altitude.NONE;
+ }
+ else {
+ _altitude = inAltitude;
+ _fieldValues[2] = "" + inAltitude.getValue();
+ }
_timestamp = new Timestamp(null);
}
* Set (or edit) the specified field value
* @param inField Field to set
* @param inValue value to set
+ * @param inUndo true if undo operation, false otherwise
*/
- public void setFieldValue(Field inField, String inValue)
+ public void setFieldValue(Field inField, String inValue, boolean inUndo)
{
// See if this data point already has this field
int fieldIndex = _fieldList.getFieldIndex(inField);
}
// Set field value in array
_fieldValues[fieldIndex] = inValue;
+ // Increment edit count on all field edits except segment
+ if (inField != Field.NEW_SEGMENT) {
+ setModified(inUndo);
+ }
// Change Coordinate, Altitude, Name or Timestamp fields after edit
- if (_altitude != null)
- {
- parseFields(_altitude.getFormat());
+ if (_altitude != null && _altitude.getFormat() != Altitude.Format.NO_FORMAT) {
+ // Altitude already present so reuse format
+ parseFields(inField, _altitude.getFormat());
}
- else
- {
- // use default altitude format of metres
- parseFields(Altitude.FORMAT_METRES);
+ else {
+ // use default altitude format from config
+ parseFields(inField, Config.getUnitSet().getDefaultAltitudeFormat());
}
}
+ /**
+ * Either increment or decrement the modify count, depending on whether it's an undo or not
+ * @param inUndo true for undo, false otherwise
+ */
+ public void setModified(boolean inUndo)
+ {
+ if (!inUndo) {
+ _modifyCount++;
+ }
+ else {
+ _modifyCount--;
+ }
+ }
+ /**
+ * @return field list for this point
+ */
+ public FieldList getFieldList()
+ {
+ return _fieldList;
+ }
+
+ /** @param inFlag true for start of track segment */
+ public void setSegmentStart(boolean inFlag)
+ {
+ setFieldValue(Field.NEW_SEGMENT, inFlag?"1":null, false);
+ }
+
+ /**
+ * Mark the point for deletion
+ * @param inFlag true to delete, false to keep
+ */
+ public void setMarkedForDeletion(boolean inFlag) {
+ _markedForDeletion = inFlag;
+ }
+
+ /** @return latitude */
public Coordinate getLatitude()
{
return _latitude;
}
+ /** @return longitude */
public Coordinate getLongitude()
{
return _longitude;
}
+ /** @return true if point has altitude */
public boolean hasAltitude()
{
return _altitude.isValid();
}
+ /** @return altitude */
public Altitude getAltitude()
{
return _altitude;
}
+ /** @return true if point has timestamp */
public boolean hasTimestamp()
{
return _timestamp.isValid();
}
+ /** @return timestamp */
public Timestamp getTimestamp()
{
return _timestamp;
}
+ /** @return waypoint name, if any */
public String getWaypointName()
{
return _waypointName;
}
+ /** @return true if start of new track segment */
+ public boolean getSegmentStart()
+ {
+ return _startOfSegment;
+ }
+
+ /** @return true if point marked for deletion */
+ public boolean getDeleteFlag()
+ {
+ return _markedForDeletion;
+ }
+
/**
* @return true if point has a waypoint name
*/
return (_waypointName != null && !_waypointName.equals(""));
}
+ /**
+ * @return true if point has been modified since loading
+ */
+ public boolean isModified()
+ {
+ return _modifyCount > 0;
+ }
/**
* Compare two DataPoint objects to see if they are duplicates
{
return !inOther.isWaypoint();
}
- else
- {
- return (inOther._waypointName != null && inOther._waypointName.equals(_waypointName));
- }
+ return (inOther._waypointName != null && inOther._waypointName.equals(_waypointName));
}
* Set the photo for this data point
* @param inPhoto Photo object
*/
- public void setPhoto(Photo inPhoto)
- {
+ public void setPhoto(Photo inPhoto) {
_photo = inPhoto;
+ _modifyCount++;
}
-
/**
* @return associated Photo object
*/
- public Photo getPhoto()
- {
+ public Photo getPhoto() {
return _photo;
}
+ /**
+ * Set the audio clip for this point
+ * @param inAudio audio object
+ */
+ public void setAudio(AudioClip inAudio) {
+ _audio = inAudio;
+ _modifyCount++;
+ }
+
+ /**
+ * @return associated audio object
+ */
+ public AudioClip getAudio() {
+ return _audio;
+ }
+
+ /**
+ * Attach the given media object according to type
+ * @param inMedia either a photo or an audio clip
+ */
+ public void attachMedia(MediaObject inMedia)
+ {
+ if (inMedia != null) {
+ if (inMedia instanceof Photo) {
+ setPhoto((Photo) inMedia);
+ inMedia.setDataPoint(this);
+ }
+ else if (inMedia instanceof AudioClip) {
+ setAudio((AudioClip) inMedia);
+ inMedia.setDataPoint(this);
+ }
+ }
+ }
/**
* @return true if the point is valid
return _latitude.isValid() && _longitude.isValid();
}
+ /**
+ * @return true if the point has either a photo or audio attached
+ */
+ public boolean hasMedia() {
+ return _photo != null || _audio != null;
+ }
+
+ /**
+ * @return name of attached photo and/or audio
+ */
+ public String getMediaName()
+ {
+ String mediaName = null;
+ if (_photo != null) mediaName = _photo.getName();
+ if (_audio != null)
+ {
+ if (mediaName == null) {
+ mediaName = _audio.getName();
+ }
+ else {
+ mediaName = mediaName + ", " + _audio.getName();
+ }
+ }
+ return mediaName;
+ }
/**
* Interpolate a set of points between this one and the given one
public DataPoint[] interpolate(DataPoint inEndPoint, int inNumPoints)
{
DataPoint[] range = new DataPoint[inNumPoints];
- Coordinate endLatitude = inEndPoint.getLatitude();
- Coordinate endLongitude = inEndPoint.getLongitude();
- Altitude endAltitude = inEndPoint.getAltitude();
-
// Loop over points
for (int i=0; i<inNumPoints; i++)
{
- Coordinate latitude = Coordinate.interpolate(_latitude, endLatitude, i, inNumPoints);
- Coordinate longitude = Coordinate.interpolate(_longitude, endLongitude, i, inNumPoints);
- Altitude altitude = Altitude.interpolate(_altitude, endAltitude, i, inNumPoints);
+ Coordinate latitude = Coordinate.interpolate(_latitude, inEndPoint.getLatitude(), i, inNumPoints);
+ Coordinate longitude = Coordinate.interpolate(_longitude, inEndPoint.getLongitude(), i, inNumPoints);
+ Altitude altitude = Altitude.interpolate(_altitude, inEndPoint.getAltitude(), i, inNumPoints);
range[i] = new DataPoint(latitude, longitude, altitude);
}
return range;
}
+ /**
+ * Interpolate between the two given points
+ * @param inStartPoint start point
+ * @param inEndPoint end point
+ * @param inFrac fractional distance from first point (0.0 to 1.0)
+ * @return new DataPoint object between two given ones
+ */
+ public static DataPoint interpolate(DataPoint inStartPoint, DataPoint inEndPoint, double inFrac)
+ {
+ if (inStartPoint == null || inEndPoint == null) {return null;}
+ return new DataPoint(
+ Coordinate.interpolate(inStartPoint.getLatitude(), inEndPoint.getLatitude(), inFrac),
+ Coordinate.interpolate(inStartPoint.getLongitude(), inEndPoint.getLongitude(), inFrac),
+ Altitude.interpolate(inStartPoint.getAltitude(), inEndPoint.getAltitude(), inFrac)
+ );
+ }
/**
* Calculate the number of radians between two points (for distance calculation)
*/
public DataPoint clonePoint()
{
- // Copy all values
+ // Copy all values (note that photo not copied)
String[] valuesCopy = new String[_fieldValues.length];
System.arraycopy(_fieldValues, 0, valuesCopy, 0, _fieldValues.length);
// Make new object to hold cloned data
/**
- * Restore the contents from another point
- * @param inOther point containing contents to copy
- * @return true if successful
+ * Remove all single and double quotes surrounding each value
+ * @param inValues array of values
*/
- public boolean restoreContents(DataPoint inOther)
+ private static void removeQuotes(String[] inValues)
{
- if (inOther != null)
+ if (inValues == null) {return;}
+ for (int i=0; i<inValues.length; i++)
{
- // Copy string values across
- _fieldValues = inOther._fieldValues;
- if (_altitude != null)
- {
- parseFields(_altitude.getFormat());
- }
- else
- {
- // use default altitude format of metres
- parseFields(Altitude.FORMAT_METRES);
+ inValues[i] = removeQuotes(inValues[i]);
+ }
+ }
+
+ /**
+ * Remove any single or double quotes surrounding a value
+ * @param inValue value to modify
+ * @return modified String
+ */
+ private static String removeQuotes(String inValue)
+ {
+ if (inValue == null) {return inValue;}
+ final int len = inValue.length();
+ if (len <= 1) {return inValue;}
+ // get the first and last characters
+ final char firstChar = inValue.charAt(0);
+ final char lastChar = inValue.charAt(len-1);
+ if (firstChar == lastChar)
+ {
+ if (firstChar == '\"' || firstChar == '\'') {
+ return inValue.substring(1, len-1);
}
- return true;
}
- return false;
+ return inValue;
+ }
+
+ /**
+ * Get string for debug
+ * @see java.lang.Object#toString()
+ */
+ public String toString()
+ {
+ return "[Lat=" + getLatitude().toString() + ", Lon=" + getLongitude().toString() + "]";
}
}