1 package tim.prune.data;
5 import tim.prune.UpdateMessageBroker;
6 import tim.prune.edit.FieldEdit;
7 import tim.prune.edit.FieldEditList;
11 * Class to hold all track information,
12 * including track points and waypoints
17 private DataPoint[] _dataPoints = null;
19 private double[] _xValues = null;
20 private double[] _yValues = null;
21 private boolean _scaled = false;
22 private int _numPoints = 0;
23 private boolean _mixedData = false;
25 private FieldList _masterFieldList = null;
27 private AltitudeRange _altitudeRange = null;
28 private DoubleRange _latRange = null, _longRange = null;
29 private DoubleRange _xRange = null, _yRange = null;
33 * Constructor for empty track
38 _masterFieldList = new FieldList(null);
39 // make empty DataPoint array
40 _dataPoints = new DataPoint[0];
48 * Load method, for initialising and reinitialising data
49 * @param inFieldArray array of Field objects describing fields
50 * @param inPointArray 2d object array containing data
51 * @param inAltFormat altitude format
53 public void load(Field[] inFieldArray, Object[][] inPointArray, int inAltFormat)
55 if (inFieldArray == null || inPointArray == null)
61 _masterFieldList = new FieldList(inFieldArray);
62 // make DataPoint object from each point in inPointList
63 _dataPoints = new DataPoint[inPointArray.length];
64 String[] dataArray = null;
66 for (int p=0; p < inPointArray.length; p++)
68 dataArray = (String[]) inPointArray[p];
69 // Convert to DataPoint objects
70 DataPoint point = new DataPoint(dataArray, _masterFieldList, inAltFormat);
73 _dataPoints[pointIndex] = point;
77 _numPoints = pointIndex;
78 // Set first track point to be start of segment
79 DataPoint firstTrackPoint = getNextTrackPoint(0);
80 if (firstTrackPoint != null) {
81 firstTrackPoint.setSegmentStart(true);
88 ////////////////// Modification methods //////////////////////
92 * Combine this Track with new data
93 * @param inOtherTrack other track to combine
95 public void combine(Track inOtherTrack)
98 _masterFieldList = _masterFieldList.merge(inOtherTrack._masterFieldList);
99 // expand data array and add other track's data points
100 int totalPoints = getNumPoints() + inOtherTrack.getNumPoints();
101 DataPoint[] mergedPoints = new DataPoint[totalPoints];
102 System.arraycopy(_dataPoints, 0, mergedPoints, 0, getNumPoints());
103 System.arraycopy(inOtherTrack._dataPoints, 0, mergedPoints, getNumPoints(), inOtherTrack.getNumPoints());
104 _dataPoints = mergedPoints;
105 // combine point count
106 _numPoints = totalPoints;
107 // needs to be scaled again
110 UpdateMessageBroker.informSubscribers();
115 * Crop the track to the given size - subsequent points are not (yet) deleted
116 * @param inNewSize new number of points in track
118 public void cropTo(int inNewSize)
120 if (inNewSize >= 0 && inNewSize < getNumPoints())
122 _numPoints = inNewSize;
123 // needs to be scaled again
125 UpdateMessageBroker.informSubscribers();
131 * Compress the track to the given resolution
132 * @param inResolution resolution
133 * @return number of points deleted
135 public int compress(int inResolution)
137 // (maybe should be separate thread?)
138 // (maybe should be in separate class?)
139 // (maybe should be based on subtended angles instead of distances?)
141 if (inResolution <= 0) return 0;
143 // Establish range of track and minimum range between points
145 double wholeScale = _xRange.getMaximum() - _xRange.getMinimum();
146 double yscale = _yRange.getMaximum() - _yRange.getMinimum();
147 if (yscale > wholeScale) wholeScale = yscale;
148 double minDist = wholeScale / inResolution;
150 // Keep track of segment start flags of the deleted points
151 boolean setSegment = false;
152 // Copy selected points
153 DataPoint[] newPointArray = new DataPoint[_numPoints];
154 int[] pointIndices = new int[_numPoints];
155 for (int i=0; i<_numPoints; i++)
157 DataPoint point = _dataPoints[i];
158 boolean keepPoint = true;
159 // Don't delete waypoints or photo points
160 if (!point.isWaypoint() && point.getPhoto() == null)
162 // go through newPointArray to check for range
163 for (int j=0; j<numCopied && keepPoint; j++)
165 // calculate distance between point j and current point
166 double pointDist = Math.abs(_xValues[i] - _xValues[pointIndices[j]])
167 + Math.abs(_yValues[i] - _yValues[pointIndices[j]]);
168 if (pointDist < minDist)
174 newPointArray[numCopied] = point;
175 pointIndices[numCopied] = i;
177 // set segment flag if it's the first track point
178 if (setSegment && !point.isWaypoint())
180 point.setSegmentStart(true);
186 // point will be removed, so check segment flag
187 if (point.getSegmentStart()) {setSegment = true;}
191 // Copy array references
192 int numDeleted = _numPoints - numCopied;
195 _dataPoints = new DataPoint[numCopied];
196 System.arraycopy(newPointArray, 0, _dataPoints, 0, numCopied);
197 _numPoints = _dataPoints.length;
205 * Halve the track by deleting alternate points
206 * @return number of points deleted
210 if (_numPoints < 100) return 0;
211 int newSize = _numPoints / 2;
212 int numDeleted = _numPoints - newSize;
213 DataPoint[] newPointArray = new DataPoint[newSize];
214 // Delete alternate points
215 for (int i=0; i<newSize; i++)
216 newPointArray[i] = _dataPoints[i*2];
217 // Copy array references
218 _dataPoints = newPointArray;
219 _numPoints = _dataPoints.length;
221 UpdateMessageBroker.informSubscribers();
227 * Delete the specified point
228 * @param inIndex point index
229 * @return true if successful
231 public boolean deletePoint(int inIndex)
233 boolean answer = deleteRange(inIndex, inIndex);
239 * Delete the specified range of points from the Track
240 * @param inStart start of range (inclusive)
241 * @param inEnd end of range (inclusive)
242 * @return true if successful
244 public boolean deleteRange(int inStart, int inEnd)
246 if (inStart < 0 || inEnd < 0 || inEnd < inStart)
248 // no valid range selected so can't delete
251 // check through range to be deleted, and see if any new segment flags present
252 boolean hasSegmentStart = false;
253 DataPoint nextTrackPoint = getNextTrackPoint(inEnd+1);
254 if (nextTrackPoint != null) {
255 for (int i=inStart; i<=inEnd && !hasSegmentStart; i++) {
256 hasSegmentStart |= _dataPoints[i].getSegmentStart();
258 // If segment break found, make sure next trackpoint also has break
259 if (hasSegmentStart) {nextTrackPoint.setSegmentStart(true);}
261 // valid range, let's delete it
262 int numToDelete = inEnd - inStart + 1;
263 DataPoint[] newPointArray = new DataPoint[_numPoints - numToDelete];
264 // Copy points before the selected range
267 System.arraycopy(_dataPoints, 0, newPointArray, 0, inStart);
269 // Copy points after the deleted one(s)
270 if (inEnd < (_numPoints - 1))
272 System.arraycopy(_dataPoints, inEnd + 1, newPointArray, inStart,
273 _numPoints - inEnd - 1);
275 // Copy points over original array
276 _dataPoints = newPointArray;
277 _numPoints -= numToDelete;
278 // needs to be scaled again
285 * Delete all the duplicate points in the track
286 * @return number of points deleted
288 public int deleteDuplicates()
290 // loop through Track counting duplicates first
291 boolean[] dupes = new boolean[_numPoints];
294 for (i=1; i<_numPoints; i++)
296 DataPoint p1 = _dataPoints[i];
297 // Loop through all points before this one
298 for (j=0; j<i && !dupes[i]; j++)
300 DataPoint p2 = _dataPoints[j];
301 if (p1.isDuplicate(p2))
310 // Make new resized array and copy DataPoints over
311 DataPoint[] newPointArray = new DataPoint[_numPoints - numDupes];
313 for (i=0; i<_numPoints; i++)
317 newPointArray[j] = _dataPoints[i];
321 // Copy array references
322 _dataPoints = newPointArray;
323 _numPoints = _dataPoints.length;
331 * Reverse the specified range of points
332 * @param inStart start index
333 * @param inEnd end index
334 * @return true if successful, false otherwise
336 public boolean reverseRange(int inStart, int inEnd)
338 if (inStart < 0 || inEnd < 0 || inStart >= inEnd || inEnd >= _numPoints)
342 // calculate how many point swaps are required
343 int numPointsToReverse = (inEnd - inStart + 1) / 2;
345 for (int i=0; i<numPointsToReverse; i++)
347 // swap pairs of points
348 p = _dataPoints[inStart + i];
349 _dataPoints[inStart + i] = _dataPoints[inEnd - i];
350 _dataPoints[inEnd - i] = p;
352 // adjust segment starts
353 shiftSegmentStarts(inStart, inEnd);
354 // Find first track point and following track point, and set segment starts to true
355 DataPoint firstTrackPoint = getNextTrackPoint(inStart);
356 if (firstTrackPoint != null) {firstTrackPoint.setSegmentStart(true);}
357 DataPoint nextTrackPoint = getNextTrackPoint(inEnd+1);
358 if (nextTrackPoint != null) {nextTrackPoint.setSegmentStart(true);}
359 // needs to be scaled again
361 UpdateMessageBroker.informSubscribers();
367 * Merge the track segments within the given range
368 * @param inStart start index
369 * @param inEnd end index
370 * @return true if successful
372 public boolean mergeTrackSegments(int inStart, int inEnd)
374 boolean firstTrackPoint = true;
375 // Loop between start and end
376 for (int i=inStart; i<=inEnd; i++) {
377 DataPoint point = getPoint(i);
378 // Set all segments to false apart from first track point
379 if (point != null && !point.isWaypoint()) {
380 point.setSegmentStart(firstTrackPoint);
381 firstTrackPoint = false;
384 // Find following track point, if any
385 DataPoint nextPoint = getNextTrackPoint(inEnd+1);
386 if (nextPoint != null) {nextPoint.setSegmentStart(true);}
387 UpdateMessageBroker.informSubscribers();
392 * Collect all waypoints to the start or end of the track
393 * @param inAtStart true to collect at start, false for end
394 * @return true if successful, false if no change
396 public boolean collectWaypoints(boolean inAtStart)
398 // Check for mixed data, numbers of waypoints & nons
399 int numWaypoints = 0, numNonWaypoints = 0;
400 boolean wayAfterNon = false, nonAfterWay = false;
401 DataPoint[] waypoints = new DataPoint[_numPoints];
402 DataPoint[] nonWaypoints = new DataPoint[_numPoints];
403 DataPoint point = null;
404 for (int i=0; i<_numPoints; i++)
406 point = _dataPoints[i];
407 if (point.isWaypoint())
409 waypoints[numWaypoints] = point;
411 wayAfterNon |= (numNonWaypoints > 0);
415 nonWaypoints[numNonWaypoints] = point;
417 nonAfterWay |= (numWaypoints > 0);
420 // Exit if the data is already in the specified order
421 if (numWaypoints == 0 || numNonWaypoints == 0
422 || (inAtStart && !wayAfterNon && nonAfterWay)
423 || (!inAtStart && wayAfterNon && !nonAfterWay))
428 // Copy the arrays back into _dataPoints in the specified order
431 System.arraycopy(waypoints, 0, _dataPoints, 0, numWaypoints);
432 System.arraycopy(nonWaypoints, 0, _dataPoints, numWaypoints, numNonWaypoints);
436 System.arraycopy(nonWaypoints, 0, _dataPoints, 0, numNonWaypoints);
437 System.arraycopy(waypoints, 0, _dataPoints, numNonWaypoints, numWaypoints);
439 // needs to be scaled again
441 UpdateMessageBroker.informSubscribers();
447 * Interleave all waypoints by each nearest track point
448 * @return true if successful, false if no change
450 public boolean interleaveWaypoints()
452 // Separate waypoints and find nearest track point
453 int numWaypoints = 0;
454 DataPoint[] waypoints = new DataPoint[_numPoints];
455 int[] pointIndices = new int[_numPoints];
456 DataPoint point = null;
458 for (i=0; i<_numPoints; i++)
460 point = _dataPoints[i];
461 if (point.isWaypoint())
463 waypoints[numWaypoints] = point;
464 pointIndices[numWaypoints] = getNearestPointIndex(
465 _xValues[i], _yValues[i], -1.0, true);
469 // Exit if data not mixed
470 if (numWaypoints == 0 || numWaypoints == _numPoints)
473 // Loop round points copying to correct order
474 DataPoint[] dataCopy = new DataPoint[_numPoints];
476 for (i=0; i<_numPoints; i++)
478 point = _dataPoints[i];
479 // if it's a track point, copy it
480 if (!point.isWaypoint())
482 dataCopy[copyIndex] = point;
485 // check for waypoints with this index
486 for (int j=0; j<numWaypoints; j++)
488 if (pointIndices[j] == i)
490 dataCopy[copyIndex] = waypoints[j];
495 // Copy data back to track
496 _dataPoints = dataCopy;
497 // needs to be scaled again to recalc x, y
499 UpdateMessageBroker.informSubscribers();
505 * Interpolate extra points between two selected ones
506 * @param inStartIndex start index of interpolation
507 * @param inNumPoints num points to insert
508 * @return true if successful
510 public boolean interpolate(int inStartIndex, int inNumPoints)
513 if (inStartIndex < 0 || inStartIndex >= _numPoints || inNumPoints <= 0)
516 // get start and end points
517 DataPoint startPoint = getPoint(inStartIndex);
518 DataPoint endPoint = getPoint(inStartIndex + 1);
520 // Make array of points to insert
521 DataPoint[] insertedPoints = startPoint.interpolate(endPoint, inNumPoints);
523 // Insert points into track
524 return insertRange(insertedPoints, inStartIndex + 1);
529 * Append the specified points to the end of the track
530 * @param inPoints DataPoint objects to add
532 public void appendPoints(DataPoint[] inPoints)
534 // Insert points into track
535 if (inPoints != null && inPoints.length > 0)
537 insertRange(inPoints, _numPoints);
539 // needs to be scaled again to recalc x, y
541 UpdateMessageBroker.informSubscribers();
545 //////// information methods /////////////
549 * Get the point at the given index
550 * @param inPointNum index number, starting at 0
551 * @return DataPoint object, or null if out of range
553 public DataPoint getPoint(int inPointNum)
555 if (inPointNum > -1 && inPointNum < getNumPoints())
557 return _dataPoints[inPointNum];
564 * @return altitude range of points as AltitudeRange object
566 public AltitudeRange getAltitudeRange()
568 if (!_scaled) scalePoints();
569 return _altitudeRange;
572 * @return the number of (valid) points in the track
574 public int getNumPoints()
580 * @return The range of x values as a DoubleRange object
582 public DoubleRange getXRange()
584 if (!_scaled) scalePoints();
589 * @return The range of y values as a DoubleRange object
591 public DoubleRange getYRange()
593 if (!_scaled) scalePoints();
598 * @return The range of lat values as a DoubleRange object
600 public DoubleRange getLatRange()
602 if (!_scaled) scalePoints();
606 * @return The range of lon values as a DoubleRange object
608 public DoubleRange getLonRange()
610 if (!_scaled) scalePoints();
615 * @param inPointNum point index, starting at 0
616 * @return scaled x value of specified point
618 public double getX(int inPointNum)
620 if (!_scaled) scalePoints();
621 return _xValues[inPointNum];
625 * @param inPointNum point index, starting at 0
626 * @return scaled y value of specified point
628 public double getY(int inPointNum)
630 if (!_scaled) scalePoints();
631 return _yValues[inPointNum];
635 * @return the master field list
637 public FieldList getFieldList()
639 return _masterFieldList;
644 * Checks if any data exists for the specified field
645 * @param inField Field to examine
646 * @return true if data exists for this field
648 public boolean hasData(Field inField)
650 return hasData(inField, 0, _numPoints-1);
655 * Checks if any data exists for the specified field in the specified range
656 * @param inField Field to examine
657 * @param inStart start of range to check
658 * @param inEnd end of range to check (inclusive)
659 * @return true if data exists for this field
661 public boolean hasData(Field inField, int inStart, int inEnd)
663 for (int i=inStart; i<=inEnd; i++)
665 if (_dataPoints[i].getFieldValue(inField) != null)
675 * @return true if track contains waypoints and trackpoints
677 public boolean hasMixedData()
679 if (!_scaled) scalePoints();
685 * Collect all the waypoints into the given List
686 * @param inList List to fill with waypoints
688 public void getWaypoints(List inList)
692 // loop over points and copy all waypoints into list
693 for (int i=0; i<=_numPoints-1; i++)
695 if (_dataPoints[i] != null && _dataPoints[i].isWaypoint())
697 inList.add(_dataPoints[i]);
704 * Search for the given Point in the track and return the index
705 * @param inPoint Point to look for
706 * @return index of Point, if any or -1 if not found
708 public int getPointIndex(DataPoint inPoint)
712 // Loop over points in track
713 for (int i=0; i<=_numPoints-1; i++)
715 if (_dataPoints[i] == inPoint)
726 ///////// Internal processing methods ////////////////
730 * Scale all the points in the track to gain x and y values
733 private void scalePoints()
735 // Loop through all points in track, to see limits of lat, long and altitude
736 _longRange = new DoubleRange();
737 _latRange = new DoubleRange();
738 _altitudeRange = new AltitudeRange();
740 boolean hasWaypoint = false, hasTrackpoint = false;
741 for (p=0; p < getNumPoints(); p++)
743 DataPoint point = getPoint(p);
744 if (point != null && point.isValid())
746 _longRange.addValue(point.getLongitude().getDouble());
747 _latRange.addValue(point.getLatitude().getDouble());
748 if (point.getAltitude().isValid())
750 _altitudeRange.addValue(point.getAltitude());
752 if (point.isWaypoint())
755 hasTrackpoint = true;
758 _mixedData = hasWaypoint && hasTrackpoint;
760 // Use medians to centre at 0
761 double longMedian = (_longRange.getMaximum() + _longRange.getMinimum()) / 2.0;
762 double latMedian = (_latRange.getMaximum() + _latRange.getMinimum()) / 2.0;
763 double longFactor = Math.cos(latMedian / 180.0 * Math.PI); // Function of median latitude
765 // Loop over points and calculate scales
766 _xValues = new double[getNumPoints()];
767 _yValues = new double[getNumPoints()];
768 _xRange = new DoubleRange();
769 _yRange = new DoubleRange();
770 for (p=0; p < getNumPoints(); p++)
772 DataPoint point = getPoint(p);
775 _xValues[p] = (point.getLongitude().getDouble() - longMedian) * longFactor;
776 _xRange.addValue(_xValues[p]);
777 _yValues[p] = (point.getLatitude().getDouble() - latMedian);
778 _yRange.addValue(_yValues[p]);
786 * Find the nearest point to the specified x and y coordinates
787 * or -1 if no point is within the specified max distance
788 * @param inX x coordinate
789 * @param inY y coordinate
790 * @param inMaxDist maximum distance from selected coordinates
791 * @param inJustTrackPoints true if waypoints should be ignored
792 * @return index of nearest point or -1 if not found
794 public int getNearestPointIndex(double inX, double inY, double inMaxDist, boolean inJustTrackPoints)
796 int nearestPoint = 0;
797 double nearestDist = -1.0;
799 for (int i=0; i < getNumPoints(); i++)
801 if (!inJustTrackPoints || !_dataPoints[i].isWaypoint())
803 currDist = Math.abs(_xValues[i] - inX) + Math.abs(_yValues[i] - inY);
804 if (currDist < nearestDist || nearestDist < 0.0)
807 nearestDist = currDist;
811 // Check whether it's within required distance
812 if (nearestDist > inMaxDist && inMaxDist > 0.0)
821 * Get the next track point starting from the given index
822 * @param inStartIndex index to start looking from
823 * @return next track point, or null if end of data reached
825 public DataPoint getNextTrackPoint(int inStartIndex)
827 return getNextTrackPoint(inStartIndex, 1);
831 * Get the previous track point starting from the given index
832 * @param inStartIndex index to start looking from
833 * @return next track point, or null if end of data reached
835 public DataPoint getPreviousTrackPoint(int inStartIndex)
837 return getNextTrackPoint(inStartIndex, -1);
841 * Get the next track point starting from the given index
842 * @param inStartIndex index to start looking from
843 * @param inIncrement increment to add to point index, +1 for next, -1 for previous
844 * @return next track point, or null if end of data reached
846 private DataPoint getNextTrackPoint(int inStartIndex, int inIncrement)
848 // Loop forever over points
849 for (int i=inStartIndex; ; i+=inIncrement)
851 DataPoint point = getPoint(i);
852 // Exit if end of data reached - there wasn't a track point
853 if (point == null) {return null;}
854 if (point.isValid() && !point.isWaypoint()) {
855 // next track point found
862 * Shift all the segment start flags in the given range by 1
863 * Method used by reverse range and its undo
864 * @param inStartIndex start of range, inclusive
865 * @param inEndIndex end of range, inclusive
867 public void shiftSegmentStarts(int inStartIndex, int inEndIndex)
869 boolean prevFlag = true;
870 boolean currFlag = true;
871 for (int i=inStartIndex; i<= inEndIndex; i++)
873 DataPoint point = getPoint(i);
874 if (point != null && !point.isWaypoint())
877 currFlag = point.getSegmentStart();
879 point.setSegmentStart(prevFlag);
885 ////////////////// Cloning and replacing ///////////////////
888 * Clone the array of DataPoints
889 * @return shallow copy of DataPoint objects
891 public DataPoint[] cloneContents()
893 DataPoint[] clone = new DataPoint[getNumPoints()];
894 System.arraycopy(_dataPoints, 0, clone, 0, getNumPoints());
900 * Clone the specified range of data points
901 * @param inStart start index (inclusive)
902 * @param inEnd end index (inclusive)
903 * @return shallow copy of DataPoint objects
905 public DataPoint[] cloneRange(int inStart, int inEnd)
908 if (inEnd >= 0 && inEnd >= inStart)
910 numSelected = inEnd - inStart + 1;
912 DataPoint[] result = new DataPoint[numSelected>0?numSelected:0];
915 System.arraycopy(_dataPoints, inStart, result, 0, numSelected);
922 * Re-insert the specified point at the given index
923 * @param inPoint point to insert
924 * @param inIndex index at which to insert the point
925 * @return true if it worked, false otherwise
927 public boolean insertPoint(DataPoint inPoint, int inIndex)
929 if (inIndex > _numPoints || inPoint == null)
933 // Make new array to copy points over to
934 DataPoint[] newPointArray = new DataPoint[_numPoints + 1];
937 System.arraycopy(_dataPoints, 0, newPointArray, 0, inIndex);
939 newPointArray[inIndex] = inPoint;
940 if (inIndex < _numPoints)
942 System.arraycopy(_dataPoints, inIndex, newPointArray, inIndex+1, _numPoints - inIndex);
944 // Change over to new array
945 _dataPoints = newPointArray;
947 // needs to be scaled again
949 UpdateMessageBroker.informSubscribers();
955 * Re-insert the specified point range at the given index
956 * @param inPoints point array to insert
957 * @param inIndex index at which to insert the points
958 * @return true if it worked, false otherwise
960 public boolean insertRange(DataPoint[] inPoints, int inIndex)
962 if (inIndex > _numPoints || inPoints == null)
966 // Make new array to copy points over to
967 DataPoint[] newPointArray = new DataPoint[_numPoints + inPoints.length];
970 System.arraycopy(_dataPoints, 0, newPointArray, 0, inIndex);
972 System.arraycopy(inPoints, 0, newPointArray, inIndex, inPoints.length);
973 if (inIndex < _numPoints)
975 System.arraycopy(_dataPoints, inIndex, newPointArray, inIndex+inPoints.length, _numPoints - inIndex);
977 // Change over to new array
978 _dataPoints = newPointArray;
979 _numPoints += inPoints.length;
980 // needs to be scaled again
982 UpdateMessageBroker.informSubscribers();
988 * Replace the track contents with the given point array
989 * @param inContents array of DataPoint objects
990 * @return true on success
992 public boolean replaceContents(DataPoint[] inContents)
994 // master field array stays the same
995 // (would need to store field array too if we wanted to redo a load)
996 // replace data array
997 _dataPoints = inContents;
998 _numPoints = _dataPoints.length;
1000 UpdateMessageBroker.informSubscribers();
1006 * Edit the specified point
1007 * @param inPoint point to edit
1008 * @param inEditList list of edits to make
1009 * @return true if successful
1011 public boolean editPoint(DataPoint inPoint, FieldEditList inEditList)
1013 if (inPoint != null && inEditList != null && inEditList.getNumEdits() > 0)
1015 // remember if coordinates have changed
1016 boolean coordsChanged = false;
1017 // go through edits one by one
1018 int numEdits = inEditList.getNumEdits();
1019 for (int i=0; i<numEdits; i++)
1021 FieldEdit edit = inEditList.getEdit(i);
1022 inPoint.setFieldValue(edit.getField(), edit.getValue());
1023 // check coordinates
1024 coordsChanged |= (edit.getField().equals(Field.LATITUDE)
1025 || edit.getField().equals(Field.LONGITUDE) || edit.getField().equals(Field.ALTITUDE));
1027 // set photo status if coordinates have changed
1028 if (inPoint.getPhoto() != null && coordsChanged)
1030 inPoint.getPhoto().setCurrentStatus(PhotoStatus.CONNECTED);
1032 // point possibly needs to be scaled again
1034 // trigger listeners
1035 UpdateMessageBroker.informSubscribers();