]> gitweb.fperrin.net Git - GpsPrune.git/blob - tim/prune/correlate/PhotoCorrelator.java
f5f86b1ab36982565a44d9cac29d9bd7aff7ee46
[GpsPrune.git] / tim / prune / correlate / PhotoCorrelator.java
1 package tim.prune.correlate;
2
3 import javax.swing.JOptionPane;
4 import javax.swing.JTable;
5
6 import tim.prune.App;
7 import tim.prune.DataSubscriber;
8 import tim.prune.I18nManager;
9 import tim.prune.UpdateMessageBroker;
10 import tim.prune.data.DataPoint;
11 import tim.prune.data.MediaList;
12 import tim.prune.data.Photo;
13 import tim.prune.data.PhotoList;
14 import tim.prune.data.TimeDifference;
15 import tim.prune.undo.UndoCorrelatePhotos;
16
17 /**
18  * Class to manage the automatic correlation of photos to points
19  * including the GUI stuff to control the correlation options
20  */
21 public class PhotoCorrelator extends Correlator
22 {
23         /**
24          * Constructor
25          * @param inApp App object to report actions to
26          */
27         public PhotoCorrelator(App inApp) {
28                 super(inApp);
29         }
30
31
32         /** Get the name key */
33         public String getNameKey() {
34                 return "function.correlatephotos";
35         }
36
37         /** @return type key */
38         protected String getMediaTypeKey() {
39                 return "photo";
40         }
41
42         /** @return photo list*/
43         protected MediaList getMediaList() {
44                 return _app.getTrackInfo().getPhotoList();
45         }
46
47         /**
48          * Create a preview of the correlate action using the selected time difference
49          * @param inTimeDiff TimeDifference to use for preview
50          * @param inShowWarning true to show warning if all points out of range
51          */
52         protected void createPreview(TimeDifference inTimeDiff, boolean inShowWarning)
53         {
54                 TimeDifference timeLimit = parseTimeLimit();
55                 double angDistLimit = parseDistanceLimit();
56                 MediaPreviewTableModel model = new MediaPreviewTableModel("dialog.correlate.select.photoname");
57                 PhotoList photos = _app.getTrackInfo().getPhotoList();
58                 // Loop through photos deciding whether to set correlate flag or not
59                 int numPhotos = photos.getNumPhotos();
60                 for (int i=0; i<numPhotos; i++)
61                 {
62                         Photo photo = photos.getPhoto(i);
63                         PointMediaPair pair = getPointPairForMedia(_app.getTrackInfo().getTrack(), photo, inTimeDiff);
64                         MediaPreviewTableRow row = new MediaPreviewTableRow(pair);
65                         // Don't try to correlate photos which don't have points either side
66                         boolean correlatePhoto = pair.isValid();
67                         // Don't select photos which already have a point
68                         if (photo.getCurrentStatus() != Photo.Status.NOT_CONNECTED) {correlatePhoto = false;}
69                         // Check time limits, distance limits
70                         if (timeLimit != null && correlatePhoto) {
71                                 long numSecs = pair.getMinSeconds();
72                                 correlatePhoto = (numSecs <= timeLimit.getTotalSeconds());
73                         }
74                         if (angDistLimit > 0.0 && correlatePhoto)
75                         {
76                                 final double angDistPair = DataPoint.calculateRadiansBetween(pair.getPointBefore(), pair.getPointAfter());
77                                 double frac = pair.getFraction();
78                                 if (frac > 0.5) {frac = 1 - frac;}
79                                 final double angDistPhoto = angDistPair * frac;
80                                 correlatePhoto = (angDistPhoto < angDistLimit);
81                         }
82                         // Don't select photos which are already correlated to the same point
83                         if (pair.getSecondsBefore() == 0L && pair.getPointBefore().isDuplicate(photo.getDataPoint())) {
84                                 correlatePhoto = false;
85                         }
86                         row.setCorrelateFlag(correlatePhoto);
87                         model.addRow(row);
88                 }
89                 _previewTable.setModel(model);
90                 // Set distance units
91                 model.setDistanceUnits(getSelectedDistanceUnits());
92                 // Set column widths
93                 _previewTable.setAutoResizeMode(JTable.AUTO_RESIZE_ALL_COLUMNS);
94                 final int[] colWidths = {150, 160, 100, 100, 50};
95                 for (int i=0; i<model.getColumnCount(); i++) {
96                         _previewTable.getColumnModel().getColumn(i).setPreferredWidth(colWidths[i]);
97                 }
98                 // check if any photos found
99                 _okButton.setEnabled(model.hasAnySelected());
100                 if (inShowWarning && !model.hasAnySelected())
101                 {
102                         JOptionPane.showMessageDialog(_dialog, I18nManager.getText("dialog.correlate.alloutsiderange"),
103                                 I18nManager.getText(getNameKey()), JOptionPane.ERROR_MESSAGE);
104                 }
105         }
106
107
108         /**
109          * Finish the correlation by modifying the track
110          * and passing the Undo information back to the App
111          */
112         protected void finishCorrelation()
113         {
114                 PointMediaPair[] pointPairs = getPointPairs();
115                 if (pointPairs == null || pointPairs.length <= 0) {return;}
116
117                 // begin to construct undo information
118                 UndoCorrelatePhotos undo = new UndoCorrelatePhotos(_app.getTrackInfo());
119                 // loop over Photos
120                 int arraySize = pointPairs.length;
121                 int i = 0, numPhotos = 0;
122                 int numPointsToCreate = 0;
123                 PointMediaPair pair = null;
124                 for (i=0; i<arraySize; i++)
125                 {
126                         pair = pointPairs[i];
127                         if (pair != null && pair.isValid())
128                         {
129                                 if (pair.getMinSeconds() == 0L)
130                                 {
131                                         // exact match
132                                         Photo pointPhoto = pair.getPointBefore().getPhoto();
133                                         if (pointPhoto == null)
134                                         {
135                                                 // photo coincides with photoless point so connect the two
136                                                 pair.getPointBefore().setPhoto((Photo) pair.getMedia());
137                                                 pair.getMedia().setDataPoint(pair.getPointBefore());
138                                         }
139                                         else if (pointPhoto.equals(pair.getMedia())) {
140                                                 // photo is already connected, nothing to do
141                                         }
142                                         else {
143                                                 // point is already connected to a different photo, so need to clone point
144                                                 numPointsToCreate++;
145                                         }
146                                 }
147                                 else
148                                 {
149                                         // photo time falls between two points, so need to interpolate new one
150                                         numPointsToCreate++;
151                                 }
152                                 numPhotos++;
153                         }
154                 }
155                 // Second loop, to create points if necessary
156                 if (numPointsToCreate > 0)
157                 {
158                         // make new array for added points
159                         DataPoint[] addedPoints = new DataPoint[numPointsToCreate];
160                         int pointNum = 0;
161                         DataPoint pointToAdd = null;
162                         for (i=0; i<arraySize; i++)
163                         {
164                                 pair = pointPairs[i];
165                                 if (pair != null && pair.isValid())
166                                 {
167                                         pointToAdd = null;
168                                         if (pair.getMinSeconds() == 0L && pair.getPointBefore().getPhoto() != null
169                                          && !pair.getPointBefore().getPhoto().equals(pair.getMedia()))
170                                         {
171                                                 // clone point
172                                                 pointToAdd = pair.getPointBefore().clonePoint();
173                                         }
174                                         else if (pair.getMinSeconds() > 0L)
175                                         {
176                                                 // interpolate point
177                                                 pointToAdd = DataPoint.interpolate(pair.getPointBefore(), pair.getPointAfter(), pair.getFraction());
178                                         }
179                                         if (pointToAdd != null)
180                                         {
181                                                 // link photo to point
182                                                 pointToAdd.setPhoto((Photo) pair.getMedia());
183                                                 pair.getMedia().setDataPoint(pointToAdd);
184                                                 // set to start of segment so not joined in track
185                                                 pointToAdd.setSegmentStart(true);
186                                                 // add to point array
187                                                 addedPoints[pointNum] = pointToAdd;
188                                                 pointNum++;
189                                         }
190                                 }
191                         }
192                         // expand track
193                         _app.getTrackInfo().getTrack().appendPoints(addedPoints);
194                 }
195
196                 // send undo information back to controlling app
197                 undo.setNumPhotosCorrelated(numPhotos);
198                 _app.completeFunction(undo, ("" + numPhotos + " "
199                          + (numPhotos==1?I18nManager.getText("confirm.correlatephotos.single"):I18nManager.getText("confirm.correlatephotos.multi"))));
200                 // observers already informed by track update if new points created
201                 if (numPointsToCreate == 0) {
202                         UpdateMessageBroker.informSubscribers(DataSubscriber.SELECTION_CHANGED);
203                 }
204         }
205 }