Changeset 12778 in osm for applications/editors/josm/plugins/agpifoj/src/org
- Timestamp:
- 2009-01-01T18:28:53+01:00 (16 years ago)
- Location:
- applications/editors/josm/plugins/agpifoj/src/org/openstreetmap/josm/plugins/agpifoj
- Files:
-
- 5 edited
Legend:
- Unmodified
- Added
- Removed
-
applications/editors/josm/plugins/agpifoj/src/org/openstreetmap/josm/plugins/agpifoj/AgpifojDialog.java
r12746 r12778 1 1 // License: GPL. Copyright 2007 by Christian Gallioz (aka khris78) 2 // Parts of code from Geotagged plugin (by Rob Neild) 2 // Parts of code from Geotagged plugin (by Rob Neild) 3 3 // and the core JOSM source code (by Immanuel Scholz and others) 4 4 … … 34 34 private ImageDisplay imgDisplay = new ImageDisplay(); 35 35 private boolean centerView = false; 36 36 37 37 // Only one instance of that class 38 38 static private AgpifojDialog INSTANCE = null; 39 39 40 40 public static AgpifojDialog getInstance() { 41 41 if (INSTANCE == null) { … … 51 51 throw new IllegalStateException("Agpifoj dialog should not be instanciated twice !"); 52 52 } 53 53 54 54 INSTANCE = this; 55 55 56 56 JPanel content = new JPanel(); 57 57 content.setLayout(new BorderLayout()); 58 58 59 59 content.add(imgDisplay, BorderLayout.CENTER); 60 60 61 61 JPanel buttons = new JPanel(); 62 62 buttons.setLayout(new FlowLayout()); 63 63 64 64 JButton button; 65 65 66 66 Dimension buttonDim = new Dimension(26,26); 67 67 button = new JButton(); … … 72 72 button.setPreferredSize(buttonDim); 73 73 buttons.add(button); 74 74 75 75 button = new JButton(); 76 76 button.setIcon(ImageProvider.get("dialogs", "delete")); … … 80 80 button.setPreferredSize(buttonDim); 81 81 buttons.add(button); 82 82 83 83 button = new JButton(); 84 84 button.setIcon(ImageProvider.get("dialogs", "next")); … … 88 88 button.setPreferredSize(buttonDim); 89 89 buttons.add(button); 90 90 91 91 JToggleButton tb = new JToggleButton(); 92 92 tb.setIcon(ImageProvider.get("dialogs", "centreview")); … … 96 96 tb.setPreferredSize(buttonDim); 97 97 buttons.add(tb); 98 98 99 99 button = new JButton(); 100 100 button.setIcon(ImageProvider.get("dialogs", "zoom-best-fit")); … … 104 104 button.setPreferredSize(buttonDim); 105 105 buttons.add(button); 106 106 107 107 content.add(buttons, BorderLayout.SOUTH); 108 108 109 109 add(content, BorderLayout.CENTER); 110 110 111 111 } 112 112 … … 120 120 currentLayer.showPreviousPhoto(); 121 121 } 122 122 123 123 } else if (COMMAND_CENTERVIEW.equals(e.getActionCommand())) { 124 124 centerView = ((JToggleButton) e.getSource()).isSelected(); … … 126 126 Main.map.mapView.zoomTo(currentEntry.pos, Main.map.mapView.getScale()); 127 127 } 128 128 129 129 } else if (COMMAND_ZOOM.equals(e.getActionCommand())) { 130 130 imgDisplay.zoomBestFitOrOne(); 131 131 132 132 } else if (COMMAND_REMOVE.equals(e.getActionCommand())) { 133 133 if (currentLayer != null) { … … 135 135 } 136 136 } 137 137 138 138 } 139 139 … … 144 144 private AgpifojLayer currentLayer = null; 145 145 private ImageEntry currentEntry = null; 146 146 147 147 public void displayImage(AgpifojLayer layer, ImageEntry entry) { 148 148 synchronized(this) { … … 151 151 return; 152 152 } 153 153 154 154 if (centerView && Main.map != null && entry != null && entry.pos != null) { 155 155 Main.map.mapView.zoomTo(entry.pos, Main.map.mapView.getScale()); … … 159 159 currentEntry = entry; 160 160 } 161 161 162 162 if (entry != null) { 163 163 imgDisplay.setImage(entry.file); -
applications/editors/josm/plugins/agpifoj/src/org/openstreetmap/josm/plugins/agpifoj/AgpifojLayer.java
r12747 r12778 1 1 // License: GPL. Copyright 2007 by Christian Gallioz (aka khris78) 2 // Parts of code from Geotagged plugin (by Rob Neild) 2 // Parts of code from Geotagged plugin (by Rob Neild) 3 3 // and the core JOSM source code (by Immanuel Scholz and others) 4 4 … … 48 48 49 49 List<ImageEntry> data; 50 50 51 51 private Icon icon = ImageProvider.get("dialogs/agpifoj-marker"); 52 52 private Icon selectedIcon = ImageProvider.get("dialogs/agpifoj-marker-selected"); 53 53 54 54 private int currentPhoto = -1; 55 55 56 56 /* 57 57 * Stores info about each image … … 83 83 84 84 /** Loads a set of images, while displaying a dialog that indicates what the plugin is currently doing. 85 * In facts, this object is instantiated with a list of files. These files may be JPEG files or 86 * directories. In case of directories, they are scanned to find all the images they contain. 87 * Then all the images that have be found are loaded as ImageEntry instances. 85 * In facts, this object is instantiated with a list of files. These files may be JPEG files or 86 * directories. In case of directories, they are scanned to find all the images they contain. 87 * Then all the images that have be found are loaded as ImageEntry instances. 88 88 */ 89 89 private static final class Loader extends PleaseWaitRunnable { … … 93 93 private final File[] selection; 94 94 private HashSet<String> loadedDirectories = new HashSet<String>(); 95 95 96 96 public Loader(File[] selection) { 97 97 super(tr("Extracting GPS locations from EXIF")); … … 108 108 errorMessage += tr("One of the selected files was null !!!"); 109 109 } 110 110 111 111 if (cancelled) { 112 112 return; 113 113 } 114 114 115 115 Main.pleaseWaitDlg.currentAction.setText(tr("Read photos...")); 116 116 … … 121 121 Main.pleaseWaitDlg.progress.setMaximum(files.size()); 122 122 Main.pleaseWaitDlg.progress.setValue(progress); 123 123 124 124 for (File f : files) { 125 125 … … 149 149 } 150 150 151 private void addRecursiveFiles(List<File> files, File[] sel) { 151 private void addRecursiveFiles(List<File> files, File[] sel) { 152 152 boolean nullFile = false; 153 153 154 154 for (File f : sel) { 155 155 156 156 if(cancelled) { 157 157 break; 158 158 } 159 159 160 160 if (f == null) { 161 161 nullFile = true; 162 162 163 163 } else if (f.isDirectory()) { 164 164 String canonical = null; … … 167 167 } catch (IOException e) { 168 168 e.printStackTrace(); 169 errorMessage += tr("Unable to get canonical path for directory {0}\n", 169 errorMessage += tr("Unable to get canonical path for directory {0}\n", 170 170 f.getAbsolutePath()); 171 171 } 172 172 173 173 if (canonical == null || loadedDirectories.contains(canonical)) { 174 174 continue; … … 176 176 loadedDirectories.add(canonical); 177 177 } 178 178 179 179 File[] children = f.listFiles(AgpifojPlugin.JPEG_FILE_FILTER); 180 180 if (children != null) { … … 189 189 errorMessage += tr("Error while getting files from directory {0}\n", f.getPath()); 190 190 } 191 191 192 192 } else { 193 193 files.add(f); 194 194 } 195 195 } 196 196 197 197 if (nullFile) { 198 198 throw new NullPointerException(); … … 251 251 @Override 252 252 public Component[] getMenuEntries() { 253 253 254 254 JMenuItem correlateItem = new JMenuItem(tr("Correlate to GPX"), ImageProvider.get("dialogs/gpx2img")); 255 255 correlateItem.addActionListener(new CorrelateGpxWithImages(this)); … … 283 283 AgpifojLayer l = (AgpifojLayer) from; 284 284 285 ImageEntry selected = null; 285 ImageEntry selected = null; 286 286 if (l.currentPhoto >= 0) { 287 287 selected = l.data.get(l.currentPhoto); 288 288 } 289 289 290 290 data.addAll(l.data); 291 291 Collections.sort(data); 292 292 293 293 // Supress the double photos. 294 294 if (data.size() > 1) { … … 304 304 } 305 305 } 306 306 307 307 if (selected != null) { 308 308 for (int i = 0; i < data.size() ; i++) { … … 314 314 } 315 315 } 316 316 317 317 name = l.name; 318 318 319 319 } 320 320 … … 324 324 int iconWidth = icon.getIconWidth() / 2; 325 325 int iconHeight = icon.getIconHeight() / 2; 326 326 327 327 for (ImageEntry e : data) { 328 328 if (e.pos != null) { … … 331 331 Rectangle r = new Rectangle(p.x - iconWidth, 332 332 p.y - iconHeight, 333 icon.getIconWidth(), 333 icon.getIconWidth(), 334 334 icon.getIconHeight()); 335 335 icon.paintIcon(mv, g, r.x, r.y); 336 336 } 337 337 } 338 338 339 339 // Draw the selection on top of the other pictures. 340 340 if (currentPhoto >= 0 && currentPhoto < data.size()) { … … 346 346 Rectangle r = new Rectangle(p.x - selectedIcon.getIconWidth() / 2, 347 347 p.y - selectedIcon.getIconHeight() / 2, 348 selectedIcon.getIconWidth(), 348 selectedIcon.getIconWidth(), 349 349 selectedIcon.getIconHeight()); 350 350 selectedIcon.paintIcon(mv, g, r.x, r.y); … … 361 361 /* 362 362 * Extract gps from image exif 363 * 363 * 364 364 * If successful, fills in the LatLon and EastNorth attributes of passed in 365 365 * image; … … 414 414 } 415 415 } 416 416 417 417 public void showNextPhoto() { 418 418 if (data != null && data.size() > 0) { … … 427 427 Main.main.map.repaint(); 428 428 } 429 429 430 430 public void showPreviousPhoto() { 431 431 if (data != null && data.size() > 0) { … … 440 440 Main.main.map.repaint(); 441 441 } 442 442 443 443 public void removeCurrentPhoto() { 444 444 if (data != null && data.size() > 0 && currentPhoto >= 0 && currentPhoto < data.size()) { … … 455 455 Main.main.map.repaint(); 456 456 } 457 457 458 458 private MouseAdapter mouseAdapter = null; 459 459 … … 481 481 continue; 482 482 Point p = Main.map.mapView.getPoint(e.pos); 483 Rectangle r = new Rectangle(p.x - icon.getIconWidth() / 2, 484 p.y - icon.getIconHeight() / 2, 485 icon.getIconWidth(), 483 Rectangle r = new Rectangle(p.x - icon.getIconWidth() / 2, 484 p.y - icon.getIconHeight() / 2, 485 icon.getIconWidth(), 486 486 icon.getIconHeight()); 487 487 if (r.contains(ev.getPoint())) { -
applications/editors/josm/plugins/agpifoj/src/org/openstreetmap/josm/plugins/agpifoj/AgpifojPlugin.java
r12747 r12778 1 1 // License: GPL. Copyright 2007 by Christian Gallioz (aka khris78) 2 // Parts of code from Geotagged plugin (by Rob Neild) 2 // Parts of code from Geotagged plugin (by Rob Neild) 3 3 // and the core JOSM source code (by Immanuel Scholz and others) 4 4 … … 23 23 24 24 public class AgpifojPlugin extends Plugin { 25 26 static class JpegFileFilter extends javax.swing.filechooser.FileFilter 25 26 static class JpegFileFilter extends javax.swing.filechooser.FileFilter 27 27 implements java.io.FileFilter { 28 28 29 29 @Override public boolean accept(File f) { 30 30 if (f.isDirectory()) { … … 40 40 } 41 41 }; 42 42 43 43 static final JpegFileFilter JPEG_FILE_FILTER = new JpegFileFilter(); 44 44 45 45 private class Action extends JosmAction { 46 46 … … 59 59 fc.setAcceptAllFileFilterUsed(false); 60 60 fc.setFileFilter(JPEG_FILE_FILTER); 61 61 62 62 fc.showOpenDialog(Main.parent); 63 63 64 64 File[] sel = fc.getSelectedFiles(); 65 65 if (sel == null || sel.length == 0) { 66 66 return; 67 67 } 68 68 69 69 Main.pref.put("tagimages.lastdirectory", fc.getCurrentDirectory().getPath()); 70 70 71 71 AgpifojLayer.create(sel); 72 72 } 73 73 } 74 74 75 75 public AgpifojPlugin() { 76 76 MainMenu.add(Main.main.menu.fileMenu, new Action()); -
applications/editors/josm/plugins/agpifoj/src/org/openstreetmap/josm/plugins/agpifoj/CorrelateGpxWithImages.java
r12747 r12778 1 1 // License: GPL. Copyright 2007 by Christian Gallioz (aka khris78) 2 // Parts of code from Geotagged plugin (by Rob Neild) 2 // Parts of code from Geotagged plugin (by Rob Neild) 3 3 // and the core JOSM source code (by Immanuel Scholz and others) 4 4 … … 64 64 import org.xml.sax.SAXException; 65 65 66 /** This class displays the window to select the GPX file and the offset (timezone + delta). 66 /** This class displays the window to select the GPX file and the offset (timezone + delta). 67 67 * Then it correlates the images of the layer with that GPX file. 68 68 */ … … 76 76 long offset; 77 77 } 78 78 79 79 AgpifojLayer yLayer = null; 80 80 81 81 private static class GpxDataWrapper { 82 82 String name; 83 83 GpxData data; 84 84 File file; 85 85 86 86 public GpxDataWrapper(String name, GpxData data, File file) { 87 87 this.name = name; 88 this.data = data; 88 this.data = data; 89 89 this.file = file; 90 90 } 91 91 92 92 public String toString() { 93 93 return name; 94 94 } 95 95 } 96 96 97 97 Vector gpxLst = new Vector(); 98 98 JPanel panel = null; … … 103 103 JRadioButton rbUntaggedImg = null; 104 104 JRadioButton rbNoExifImg = null; 105 106 /** This class is called when the user doesn't find the GPX file he needs in the files that have 105 106 /** This class is called when the user doesn't find the GPX file he needs in the files that have 107 107 * been loaded yet. It displays a FileChooser dialog to select the GPX file to be loaded. 108 */ 108 */ 109 109 private class LoadGpxDataActionListener implements ActionListener { 110 110 111 111 public void actionPerformed(ActionEvent arg0) { 112 112 JFileChooser fc = new JFileChooser(Main.pref.get("lastDirectory")); … … 118 118 @Override public boolean accept(File f) { 119 119 return (f.isDirectory() 120 || f .getName().toLowerCase().endsWith(".gpx") 120 || f .getName().toLowerCase().endsWith(".gpx") 121 121 || f.getName().toLowerCase().endsWith(".gpx.gz")); 122 122 } … … 129 129 if (sel == null) 130 130 return; 131 131 132 132 try { 133 133 panel.setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR)); 134 134 135 135 Main.pref.put("lastDirectory", sel.getPath()); 136 136 137 137 for (int i = gpxLst.size() - 1 ; i >= 0 ; i--) { 138 138 if (gpxLst.get(i) instanceof GpxDataWrapper) { 139 GpxDataWrapper wrapper = (GpxDataWrapper) gpxLst.get(i); 139 GpxDataWrapper wrapper = (GpxDataWrapper) gpxLst.get(i); 140 140 if (sel.equals(wrapper.file)) { 141 141 cbGpx.setSelectedIndex(i); 142 142 if (!sel.getName().equals(wrapper.name)) { 143 JOptionPane.showMessageDialog(Main.parent, 143 JOptionPane.showMessageDialog(Main.parent, 144 144 tr("File {0} is loaded yet under the name \"{1}\"", sel.getName(), wrapper.name)); 145 145 } … … 154 154 iStream = new GZIPInputStream(new FileInputStream(sel)); 155 155 } else { 156 iStream = new FileInputStream(sel); 156 iStream = new FileInputStream(sel); 157 157 } 158 158 data = new GpxReader(iStream, sel).data; 159 159 data.storageFile = sel; 160 160 161 161 } catch (SAXException x) { 162 162 x.printStackTrace(); … … 168 168 return; 169 169 } 170 170 171 171 loadedGpxData.add(data); 172 172 if (gpxLst.get(0) instanceof String) { … … 180 180 } 181 181 } 182 183 /** This action listener is called when the user has a photo of the time of his GPS receiver. It 182 183 /** This action listener is called when the user has a photo of the time of his GPS receiver. It 184 184 * displays the list of photos of the layer, and upon selection displays the selected photo. 185 * From that photo, the user can key in the time of the GPS. 186 * Then values of timezone and delta are set. 185 * From that photo, the user can key in the time of the GPS. 186 * Then values of timezone and delta are set. 187 187 * @author chris 188 188 * … … 195 195 ImageDisplay imgDisp; 196 196 JList imgList; 197 197 198 198 public void actionPerformed(ActionEvent arg0) { 199 199 SimpleDateFormat dateFormat = new SimpleDateFormat("dd/MM/yyyy HH:mm:ss"); … … 203 203 panel.add(new JLabel(tr("<html>Take a photo of your GPS receiver while it displays the time.<br>" 204 204 + "Display that photo here.<br>" 205 + "And then, simply capture the time you read on the photo and select a timezone<hr></html>")), 205 + "And then, simply capture the time you read on the photo and select a timezone<hr></html>")), 206 206 BorderLayout.NORTH); 207 207 208 208 imgDisp = new ImageDisplay(); 209 209 imgDisp.setPreferredSize(new Dimension(300, 225)); 210 210 panel.add(imgDisp, BorderLayout.CENTER); 211 211 212 212 JPanel panelTf = new JPanel(); 213 213 panelTf.setLayout(new GridBagLayout()); 214 214 215 215 GridBagConstraints gc = new GridBagConstraints(); 216 216 gc.gridx = gc.gridy = 0; … … 227 227 gc.gridwidth = 2; 228 228 panelTf.add(lbExifTime, gc); 229 229 230 230 gc.gridx = 0; 231 231 gc.gridy = 1; … … 247 247 gc.weightx = 0.2; 248 248 panelTf.add(new JLabel(tr(" [dd/mm/yyyy hh:mm:ss]")), gc); 249 249 250 250 gc.gridx = 0; 251 251 gc.gridy = 2; … … 255 255 gc.anchor = GridBagConstraints.WEST; 256 256 panelTf.add(new JLabel(tr("I'm in the timezone of: ")), gc); 257 257 258 258 Vector vtTimezones = new Vector<String>(); 259 259 String[] tmp = TimeZone.getAvailableIDs(); 260 260 261 261 for (String tzStr : tmp) { 262 262 TimeZone tz = TimeZone.getTimeZone(tzStr); 263 263 264 264 String tzDesc = new StringBuffer(tzStr).append(" (") 265 265 .append(formatTimezone(tz.getRawOffset() / 3600000.0)) … … 267 267 vtTimezones.add(tzDesc); 268 268 } 269 269 270 270 Collections.sort(vtTimezones); 271 271 272 272 cbTimezones = new JComboBox(vtTimezones); 273 273 274 274 String tzId = Main.pref.get("tagimages.timezoneid", ""); 275 275 TimeZone defaultTz; … … 279 279 defaultTz = TimeZone.getTimeZone(tzId); 280 280 } 281 281 282 282 cbTimezones.setSelectedItem(new StringBuffer(defaultTz.getID()).append(" (") 283 283 .append(formatTimezone(defaultTz.getRawOffset() / 3600000.0)) 284 284 .append(')').toString()); 285 285 286 286 gc.gridx = 1; 287 287 gc.weightx = 1.0; … … 289 289 gc.fill = GridBagConstraints.HORIZONTAL; 290 290 panelTf.add(cbTimezones, gc); 291 291 292 292 panel.add(panelTf, BorderLayout.SOUTH); 293 293 294 294 JPanel panelLst = new JPanel(); 295 295 panelLst.setLayout(new BorderLayout()); 296 296 297 297 imgList = new JList(new AbstractListModel() { 298 298 public Object getElementAt(int i) { … … 312 312 Date date = yLayer.data.get(index).time; 313 313 if (date != null) { 314 lbExifTime.setText(new SimpleDateFormat("dd/MM/yyyy HH:mm:ss").format(date)); 314 lbExifTime.setText(new SimpleDateFormat("dd/MM/yyyy HH:mm:ss").format(date)); 315 315 tfGpsTime.setText(new SimpleDateFormat("dd/MM/yyyy ").format(date)); 316 316 tfGpsTime.setCaretPosition(tfGpsTime.getText().length()); 317 317 tfGpsTime.setEnabled(true); 318 } else { 318 } else { 319 319 lbExifTime.setText(tr("No date")); 320 320 tfGpsTime.setText(""); … … 322 322 } 323 323 } 324 324 325 325 }); 326 326 panelLst.add(new JScrollPane(imgList), BorderLayout.CENTER); 327 327 328 328 JButton openButton = new JButton(tr("Open an other photo")); 329 329 openButton.addActionListener(new ActionListener() { … … 349 349 } 350 350 if (date != null) { 351 lbExifTime.setText(new SimpleDateFormat("dd/MM/yyyy HH:mm:ss").format(date)); 351 lbExifTime.setText(new SimpleDateFormat("dd/MM/yyyy HH:mm:ss").format(date)); 352 352 tfGpsTime.setText(new SimpleDateFormat("dd/MM/yyyy ").format(date)); 353 353 tfGpsTime.setEnabled(true); 354 } else { 354 } else { 355 355 lbExifTime.setText(tr("No date")); 356 356 tfGpsTime.setText(""); … … 360 360 }); 361 361 panelLst.add(openButton, BorderLayout.PAGE_END); 362 362 363 363 panel.add(panelLst, BorderLayout.LINE_START); 364 364 365 365 boolean isOk = false; 366 366 while (! isOk) { … … 370 370 } 371 371 372 long delta; 373 372 long delta; 373 374 374 try { 375 delta = dateFormat.parse(lbExifTime.getText()).getTime() 375 delta = dateFormat.parse(lbExifTime.getText()).getTime() 376 376 - dateFormat.parse(tfGpsTime.getText()).getTime(); 377 377 } catch(ParseException e) { 378 JOptionPane.showMessageDialog(Main.parent, tr("Error while parsing the date.\n" 379 + "Please use the requested format"), 378 JOptionPane.showMessageDialog(Main.parent, tr("Error while parsing the date.\n" 379 + "Please use the requested format"), 380 380 tr("Invalid date"), JOptionPane.ERROR_MESSAGE ); 381 381 continue; 382 382 } 383 383 384 384 String selectedTz = (String) cbTimezones.getSelectedItem(); 385 385 int pos = selectedTz.lastIndexOf('('); 386 386 tzId = selectedTz.substring(0, pos - 1); 387 String tzValue = selectedTz.substring(pos + 1, selectedTz.length() - 1); 388 387 String tzValue = selectedTz.substring(pos + 1, selectedTz.length() - 1); 388 389 389 Main.pref.put("tagimages.timezoneid", tzId); 390 390 tfOffset.setText(Long.toString(delta / 1000)); 391 391 tfTimezone.setText(tzValue); 392 392 393 393 isOk = true; 394 395 } 396 397 } 398 } 399 394 395 } 396 397 } 398 } 399 400 400 public CorrelateGpxWithImages(AgpifojLayer layer) { 401 401 this.yLayer = layer; … … 409 409 Layer cur = iterLayer.next(); 410 410 if (cur instanceof GpxLayer) { 411 gpxLst.add(new GpxDataWrapper(((GpxLayer) cur).name, 412 ((GpxLayer) cur).data, 413 ((GpxLayer) cur).data.storageFile)); 411 gpxLst.add(new GpxDataWrapper(((GpxLayer) cur).name, 412 ((GpxLayer) cur).data, 413 ((GpxLayer) cur).data.storageFile)); 414 414 } 415 415 } 416 416 for (GpxData data : loadedGpxData) { 417 gpxLst.add(new GpxDataWrapper(data.storageFile.getName(), 417 gpxLst.add(new GpxDataWrapper(data.storageFile.getName(), 418 418 data, 419 data.storageFile)); 420 } 421 419 data.storageFile)); 420 } 421 422 422 if (gpxLst.size() == 0) { 423 423 gpxLst.add(tr("<No GPX track loaded yet>")); 424 424 } 425 425 426 426 JPanel panelCb = new JPanel(); 427 427 panelCb.setLayout(new FlowLayout()); 428 428 429 429 panelCb.add(new JLabel(tr("GPX track: "))); 430 430 431 431 cbGpx = new JComboBox(gpxLst); 432 432 panelCb.add(cbGpx); 433 433 434 434 JButton buttonOpen = new JButton(tr("Open another GPX trace")); 435 435 buttonOpen.setIcon(ImageProvider.get("agpifoj-open")); 436 436 buttonOpen.addActionListener(new LoadGpxDataActionListener()); 437 437 438 438 panelCb.add(buttonOpen); 439 439 440 440 JPanel panelTf = new JPanel(); 441 441 panelTf.setLayout(new GridBagLayout()); 442 442 443 443 GridBagConstraints gc = new GridBagConstraints(); 444 444 gc.anchor = GridBagConstraints.WEST; 445 445 446 446 gc.gridx = gc.gridy = 0; 447 447 gc.gridwidth = gc.gridheight = 1; … … 464 464 gc.weighty = 0.0; 465 465 panelTf.add(tfTimezone, gc); 466 466 467 467 gc.gridx = 0; 468 468 gc.gridy = 1; … … 493 493 gc.weighty = 1.0; 494 494 panelTf.add(buttonViewGpsPhoto, gc); 495 495 496 496 gc.gridx = 0; 497 497 gc.gridy = 2; … … 500 500 gc.weightx = gc.weighty = 0.0; 501 501 panelTf.add(new JLabel(tr("Update position for: ")), gc); 502 502 503 503 gc.gridx = 1; 504 504 gc.gridy = 2; … … 510 510 rbAllImg = new JRadioButton(tr("All images")); 511 511 panelTf.add(rbAllImg, gc); 512 512 513 513 gc.gridx = 1; 514 514 gc.gridy = 3; … … 520 520 rbNoExifImg = new JRadioButton(tr("Images with no exif position")); 521 521 panelTf.add(rbNoExifImg, gc); 522 522 523 523 gc.gridx = 1; 524 524 gc.gridy = 4; … … 530 530 rbUntaggedImg = new JRadioButton(tr("Not yet tagged images")); 531 531 panelTf.add(rbUntaggedImg, gc); 532 532 533 533 ButtonGroup group = new ButtonGroup(); 534 534 group.add(rbAllImg); 535 535 group.add(rbNoExifImg); 536 536 group.add(rbUntaggedImg); 537 537 538 538 rbUntaggedImg.setSelected(true); 539 539 540 540 panel = new JPanel(); 541 541 panel.setLayout(new BorderLayout()); 542 542 543 543 panel.add(panelCb, BorderLayout.PAGE_START); 544 544 panel.add(panelTf, BorderLayout.CENTER); … … 555 555 556 556 if (item == null || ! (item instanceof GpxDataWrapper)) { 557 JOptionPane.showMessageDialog(Main.parent, tr("You should select a GPX track"), 557 JOptionPane.showMessageDialog(Main.parent, tr("You should select a GPX track"), 558 558 tr("No selected GPX track"), JOptionPane.ERROR_MESSAGE ); 559 559 continue; … … 563 563 Float timezoneValue = parseTimezone(tfTimezone.getText().trim()); 564 564 if (timezoneValue == null) { 565 JOptionPane.showMessageDialog(Main.parent, tr("Error while parsing timezone.\nExpected format: {0}", "+H:MM"), 565 JOptionPane.showMessageDialog(Main.parent, tr("Error while parsing timezone.\nExpected format: {0}", "+H:MM"), 566 566 tr("Invalid timezone"), JOptionPane.ERROR_MESSAGE); 567 567 continue; 568 568 } 569 569 gpstimezone = timezoneValue.floatValue(); 570 570 571 571 String deltaText = tfOffset.getText().trim(); 572 572 if (deltaText.length() > 0) { … … 574 574 delta = Long.parseLong(deltaText); 575 575 } catch(NumberFormatException nfe) { 576 JOptionPane.showMessageDialog(Main.parent, tr("Error while parsing offset.\nExpected format: {0}", "number"), 576 JOptionPane.showMessageDialog(Main.parent, tr("Error while parsing offset.\nExpected format: {0}", "number"), 577 577 tr("Invalid offset"), JOptionPane.ERROR_MESSAGE); 578 578 continue; … … 581 581 delta = 0; 582 582 } 583 583 584 584 Main.pref.put("tagimages.doublegpstimezone", Double.toString(gpstimezone)); 585 585 Main.pref.put("tagimages.gpstimezone", Long.toString(- ((long) gpstimezone))); 586 586 Main.pref.put("tagimages.delta", Long.toString(delta * 1000)); 587 587 588 588 isOk = true; 589 589 } 590 590 591 591 // Construct a list of images that have a date, and sort them on the date. 592 592 ArrayList<ImageEntry> dateImgLst = new ArrayList<ImageEntry>(yLayer.data.size()); … … 597 597 } 598 598 } 599 599 600 600 } else if (rbNoExifImg.isSelected()) { 601 601 for (ImageEntry e : yLayer.data) { … … 605 605 } 606 606 607 } else { // rbUntaggedImg.isSelected() 607 } else { // rbUntaggedImg.isSelected() 608 608 for (ImageEntry e : yLayer.data) { 609 609 if (e.time != null && e.coor == null) { … … 612 612 } 613 613 } 614 614 615 615 int matched = matchGpxTrack(dateImgLst, selectedGpx.data, (long) (gpstimezone * 3600000) + delta * 1000); 616 616 617 // Search whether an other layer has yet defined some bounding box. 617 // Search whether an other layer has yet defined some bounding box. 618 618 // If none, we'll zoom to the bounding box of the layer with the photos. 619 619 Collection<Layer> layerCol = Main.map.mapView.getAllLayers(); 620 620 Iterator<Layer> layerIter = layerCol.iterator(); 621 boolean boundingBoxedLayerFound = false; 621 boolean boundingBoxedLayerFound = false; 622 622 while (layerIter.hasNext()) { 623 623 Layer l = layerIter.next(); … … 636 636 Main.map.mapView.recalculateCenterScale(bbox); 637 637 } 638 638 639 639 Main.main.map.repaint(); 640 640 641 641 JOptionPane.showMessageDialog(Main.parent, tr("Found {0} matchs of {1} in GPX track {2}", matched, dateImgLst.size(), selectedGpx.name), 642 tr("GPX Track loaded"), 643 ((dateImgLst.size() > 0 && matched == 0) ? JOptionPane.WARNING_MESSAGE 642 tr("GPX Track loaded"), 643 ((dateImgLst.size() > 0 && matched == 0) ? JOptionPane.WARNING_MESSAGE 644 644 : JOptionPane.INFORMATION_MESSAGE)); 645 645 646 646 } 647 647 648 648 private int matchGpxTrack(ArrayList<ImageEntry> dateImgLst, GpxData selectedGpx, long offset) { 649 649 int ret = 0; 650 650 651 651 Collections.sort(dateImgLst, new Comparator<ImageEntry>() { 652 652 public int compare(ImageEntry arg0, ImageEntry arg1) { … … 654 654 } 655 655 }); 656 656 657 657 PrimaryDateParser dateParser = new PrimaryDateParser(); 658 658 659 659 for (GpxTrack trk : selectedGpx.tracks) { 660 660 for (Collection<WayPoint> segment : trk.trackSegs) { 661 661 662 662 long prevDateWp = 0; 663 663 WayPoint prevWp = null; 664 664 665 665 for (WayPoint curWp : segment) { 666 667 String curDateWpStr = (String) curWp.attr.get("time"); 666 667 String curDateWpStr = (String) curWp.attr.get("time"); 668 668 if (curDateWpStr != null) { 669 669 670 670 try { 671 671 long curDateWp = dateParser.parse(curDateWpStr).getTime() + offset; 672 672 ret += matchPoints(dateImgLst, prevWp, prevDateWp, curWp, curDateWp); 673 673 674 674 prevWp = curWp; 675 675 prevDateWp = curDateWp; … … 710 710 } catch (Exception e) { 711 711 } 712 713 while(i >= 0 712 713 while(i >= 0 714 714 && dateImgLst.get(i).time.getTime() == curDateWp) { 715 dateImgLst.get(i).pos = curWp.eastNorth; 715 dateImgLst.get(i).pos = curWp.eastNorth; 716 716 dateImgLst.get(i).coor = Main.proj.eastNorth2latlon(dateImgLst.get(i).pos); 717 717 dateImgLst.get(i).speed = speed; … … 720 720 i--; 721 721 } 722 722 723 723 if (prevDateWp != 0) { 724 724 long imgDate; 725 while(i >= 0 725 while(i >= 0 726 726 && (imgDate = dateImgLst.get(i).time.getTime()) > prevDateWp) { 727 727 dateImgLst.get(i).pos = new EastNorth( 728 728 prevWp.eastNorth.east() + ((curWp.eastNorth.east() - prevWp.eastNorth.east()) * (imgDate - prevDateWp)) / (curDateWp - prevDateWp), 729 prevWp.eastNorth.north() + ((curWp.eastNorth.north() - prevWp.eastNorth.north()) * (imgDate - prevDateWp)) / (curDateWp - prevDateWp)); 729 prevWp.eastNorth.north() + ((curWp.eastNorth.north() - prevWp.eastNorth.north()) * (imgDate - prevDateWp)) / (curDateWp - prevDateWp)); 730 730 dateImgLst.get(i).coor = Main.proj.eastNorth2latlon(dateImgLst.get(i).pos); 731 731 dateImgLst.get(i).speed = speed; 732 732 if (curElevation != null && prevElevation != null) { 733 733 dateImgLst.get(i).elevation = prevElevation + ((curElevation - prevElevation) * (imgDate - prevDateWp)) / (curDateWp - prevDateWp); 734 } 734 } 735 735 ret++; 736 736 i--; … … 757 757 return curIndex; 758 758 } 759 759 760 760 int curIndex = 0; 761 761 int startIndex=0; … … 782 782 private String formatTimezone(double timezone) { 783 783 StringBuffer ret = new StringBuffer(); 784 784 785 785 if (timezone < 0) { 786 786 ret.append('-'); … … 795 795 } 796 796 ret.append(minutes); 797 797 798 798 return ret.toString(); 799 799 } 800 800 801 801 private Float parseTimezone(String timezone) { 802 803 804 805 802 if (timezone.length() == 0) { 803 return new Float(0); 804 } 805 806 806 char sgnTimezone = '+'; 807 807 StringBuffer hTimezone = new StringBuffer(); … … 817 817 break; 818 818 case '+' : 819 case '-' : 819 case '-' : 820 820 if (state == 1) { 821 821 sgnTimezone = c; … … 825 825 } 826 826 break; 827 case ':' : 828 case '.' : 827 case ':' : 828 case '.' : 829 829 if (state == 2) { 830 830 state = 3; … … 833 833 } 834 834 break; 835 case '0' : case '1' : case '2' : case '3' : case '4' : 835 case '0' : case '1' : case '2' : case '3' : case '4' : 836 836 case '5' : case '6' : case '7' : case '8' : case '9' : 837 837 switch(state) { 838 case 1 : 839 case 2 : 838 case 1 : 839 case 2 : 840 840 state = 2; 841 841 hTimezone.append(c); 842 842 break; 843 case 3 : 843 case 3 : 844 844 mTimezone.append(c); 845 845 break; 846 default : 846 default : 847 847 return null; 848 848 } 849 849 break; 850 default : 850 default : 851 851 return null; 852 852 } 853 853 } 854 854 855 855 int h = 0; 856 856 int m = 0; 857 857 try { 858 859 860 861 858 h = Integer.parseInt(hTimezone.toString()); 859 if (mTimezone.length() > 0) { 860 m = Integer.parseInt(mTimezone.toString()); 861 } 862 862 } catch (NumberFormatException nfe) { 863 864 865 } 866 863 // Invalid timezone 864 return null; 865 } 866 867 867 if (h > 12 || m > 59 ) { 868 868 return null; 869 869 } else { 870 871 } 872 } 873 874 /** Return the distance in meters between 2 points 870 return new Float((h + m / 60.0) * (sgnTimezone == '-' ? -1 : 1)); 871 } 872 } 873 874 /** Return the distance in meters between 2 points 875 875 * Formula and earth radius from : http://en.wikipedia.org/wiki/Great-circle_distance */ 876 876 public double getDistance(WayPoint p1, WayPoint p2) { 877 877 double p1Lat = p1.latlon.lat() * Math.PI / 180; 878 double p1Lon = p1.latlon.lon() * Math.PI / 180; 878 double p1Lon = p1.latlon.lon() * Math.PI / 180; 879 879 double p2Lat = p2.latlon.lat() * Math.PI / 180; 880 880 double p2Lon = p2.latlon.lon() * Math.PI / 180; 881 double ret = Math.atan2(Math.sqrt(Math.pow(Math.cos(p2Lat) * Math.sin(p2Lon - p1Lon), 2) 881 double ret = Math.atan2(Math.sqrt(Math.pow(Math.cos(p2Lat) * Math.sin(p2Lon - p1Lon), 2) 882 882 + Math.pow(Math.cos(p1Lat) * Math.sin(p2Lat) 883 - Math.sin(p1Lat) * Math.cos(p2Lat) * Math.cos(p2Lon - p1Lon), 2)), 884 Math.sin(p1Lat) * Math.sin(p2Lat) 883 - Math.sin(p1Lat) * Math.cos(p2Lat) * Math.cos(p2Lon - p1Lon), 2)), 884 Math.sin(p1Lat) * Math.sin(p2Lat) 885 885 + Math.cos(p1Lat) * Math.cos(p2Lat) * Math.cos(p2Lon - p1Lon)) 886 886 * 6372795; // Earth radius, in meters -
applications/editors/josm/plugins/agpifoj/src/org/openstreetmap/josm/plugins/agpifoj/ImageDisplay.java
r10258 r12778 25 25 26 26 public class ImageDisplay extends JComponent { 27 27 28 28 /** The file that is currently displayed */ 29 29 private File file = null; 30 30 31 31 /** The image currently displayed */ 32 32 private Image image = null; 33 33 34 34 /** The image currently displayed */ 35 35 private boolean errorLoading = false; 36 37 /** The rectangle (in image coordinates) of the image that is visible. This rectangle is calculated 36 37 /** The rectangle (in image coordinates) of the image that is visible. This rectangle is calculated 38 38 * each time the zoom is modified */ 39 39 private Rectangle visibleRect = null; 40 40 41 41 /** When a selection is done, the rectangle of the selection (in image coordinates) */ 42 42 private Rectangle selectedRect = null; … … 46 46 47 47 private String osdText = null; 48 48 49 49 /** The thread that reads the images. */ 50 50 private class LoadImageRunnable implements Runnable { 51 51 52 52 File file = null; 53 53 54 54 public LoadImageRunnable(File file) { 55 55 this.file = file; 56 56 } 57 57 58 58 public void run() { 59 59 Image img = Toolkit.getDefaultToolkit().createImage(file.getPath()); 60 60 tracker.addImage(img, 1); 61 61 62 62 // Wait for the end of loading 63 63 while (! tracker.checkID(1, true)) { 64 64 if (this.file != ImageDisplay.this.file) { 65 // The file has changed 65 // The file has changed 66 66 tracker.removeImage(img); 67 67 return; … … 77 77 error = true; 78 78 } 79 79 80 80 synchronized(ImageDisplay.this) { 81 81 if (this.file != ImageDisplay.this.file) { 82 // The file has changed 82 // The file has changed 83 83 tracker.removeImage(img); 84 84 return; … … 93 93 } 94 94 } 95 95 96 96 private class ImgDisplayMouseListener implements MouseListener, MouseWheelListener, MouseMotionListener { 97 97 98 98 boolean mouseIsDragging = false; 99 99 Point mousePointInImg = null; 100 101 /** Zoom in and out, trying to preserve the point of the image that was under the mouse cursor 102 * at the same place */ 100 101 /** Zoom in and out, trying to preserve the point of the image that was under the mouse cursor 102 * at the same place */ 103 103 public void mouseWheelMoved(MouseWheelEvent e) { 104 104 File file; 105 105 Image image; 106 106 Rectangle visibleRect; 107 107 108 108 synchronized (ImageDisplay.this) { 109 109 file = ImageDisplay.this.file; … … 111 111 visibleRect = ImageDisplay.this.visibleRect; 112 112 } 113 113 114 114 mouseIsDragging = false; 115 115 selectedRect = null; 116 116 117 117 if (image == null) { 118 118 return; 119 119 } 120 120 121 // Calculate the mouse cursor position in image coordinates, so that we can center the zoom 122 // on that mouse position. 121 // Calculate the mouse cursor position in image coordinates, so that we can center the zoom 122 // on that mouse position. 123 123 if (e.getClickCount() == 1 || mousePointInImg == null) { 124 124 mousePointInImg = comp2imgCoord(visibleRect, e.getX(), e.getY()); 125 125 } 126 126 127 127 // Applicate the zoom to the visible rectangle in image coordinates 128 128 if (e.getWheelRotation() > 0) { … … 133 133 visibleRect.height = visibleRect.height * 2 / 3; 134 134 } 135 135 136 136 // Check that the zoom doesn't exceed 2:1 137 137 if (visibleRect.width < getSize().width / 2) { … … 141 141 visibleRect.height = getSize().height / 2; 142 142 } 143 143 144 144 // Set the same ratio for the visible rectangle and the display area 145 145 int hFact = visibleRect.height * getSize().width; … … 150 150 visibleRect.height = wFact / getSize().width; 151 151 } 152 152 153 153 // The size of the visible rectangle is limited by the image size. 154 154 checkVisibleRectSize(image, visibleRect); 155 155 156 156 // Set the position of the visible rectangle, so that the mouse cursor doesn't move on the image. 157 157 Rectangle drawRect = calculateDrawImageRectangle(visibleRect); 158 158 visibleRect.x = mousePointInImg.x + ((drawRect.x - e.getX()) * visibleRect.width) / drawRect.width; 159 159 visibleRect.y = mousePointInImg.y + ((drawRect.y - e.getY()) * visibleRect.height) / drawRect.height; 160 160 161 161 // The position is also limited by the image size 162 162 checkVisibleRectPos(image, visibleRect); 163 163 164 164 synchronized(ImageDisplay.this) { 165 165 if (ImageDisplay.this.file == file) { … … 176 176 Image image; 177 177 Rectangle visibleRect; 178 178 179 179 synchronized (ImageDisplay.this) { 180 180 file = ImageDisplay.this.file; … … 190 190 return; 191 191 } 192 192 193 193 // Calculate the translation to set the clicked point the center of the view. 194 194 Point click = comp2imgCoord(visibleRect, e.getX(), e.getY()); 195 195 Point center = getCenterImgCoord(visibleRect); 196 196 197 197 visibleRect.x += click.x - center.x; 198 198 visibleRect.y += click.y - center.y; 199 199 200 200 checkVisibleRectPos(image, visibleRect); 201 201 202 202 synchronized(ImageDisplay.this) { 203 203 if (ImageDisplay.this.file == file) { … … 208 208 } 209 209 210 /** Initialize the dragging, either with button 1 (simple dragging) or button 3 (selection of 210 /** Initialize the dragging, either with button 1 (simple dragging) or button 3 (selection of 211 211 * a picture part) */ 212 212 public void mousePressed(MouseEvent e) { … … 216 216 return; 217 217 } 218 218 219 219 File file; 220 220 Image image; 221 221 Rectangle visibleRect; 222 222 223 223 synchronized (ImageDisplay.this) { 224 224 file = ImageDisplay.this.file; … … 251 251 return; 252 252 } 253 253 254 254 File file; 255 255 Image image; 256 256 Rectangle visibleRect; 257 257 258 258 synchronized (ImageDisplay.this) { 259 259 file = ImageDisplay.this.file; … … 279 279 } 280 280 ImageDisplay.this.repaint(); 281 281 282 282 } else if (selectedRect != null) { 283 283 Point p = comp2imgCoord(visibleRect, e.getX(), e.getY()); … … 300 300 return; 301 301 } 302 302 303 303 File file; 304 304 Image image; 305 305 Rectangle visibleRect; 306 306 307 307 synchronized (ImageDisplay.this) { 308 308 file = ImageDisplay.this.file; … … 319 319 if (mouseIsDragging) { 320 320 mouseIsDragging = false; 321 321 322 322 } else if (selectedRect != null) { 323 323 int oldWidth = selectedRect.width; … … 331 331 selectedRect.height = getSize().height / 2; 332 332 } 333 333 334 334 // Set the same ratio for the visible rectangle and the display area 335 335 int hFact = selectedRect.height * getSize().width; … … 340 340 selectedRect.height = wFact / getSize().width; 341 341 } 342 342 343 343 // Keep the center of the selection 344 344 if (selectedRect.width != oldWidth) { … … 348 348 selectedRect.y -= (selectedRect.height - oldHeight) / 2; 349 349 } 350 350 351 351 checkVisibleRectSize(image, selectedRect); 352 352 checkVisibleRectPos(image, selectedRect); 353 353 354 354 synchronized (ImageDisplay.this) { 355 355 if (file == ImageDisplay.this.file) { 356 356 ImageDisplay.this.visibleRect = selectedRect; 357 357 } 358 } 358 } 359 359 selectedRect = null; 360 360 ImageDisplay.this.repaint(); … … 370 370 public void mouseMoved(MouseEvent e) { 371 371 } 372 372 373 373 private void checkPointInVisibleRect(Point p, Rectangle visibleRect) { 374 374 if (p.x < visibleRect.x) { … … 386 386 } 387 387 } 388 388 389 389 public ImageDisplay() { 390 390 ImgDisplayMouseListener mouseListener = new ImgDisplayMouseListener(); … … 393 393 addMouseMotionListener(mouseListener); 394 394 } 395 395 396 396 public void setImage(File file) { 397 397 synchronized(this) { … … 410 410 this.osdText = text; 411 411 } 412 412 413 413 public void paintComponent(Graphics g) { 414 414 Image image; … … 416 416 Rectangle visibleRect; 417 417 boolean errorLoading; 418 418 419 419 synchronized(this) { 420 420 image = this.image; … … 423 423 errorLoading = this.errorLoading; 424 424 } 425 425 426 426 if (file == null) { 427 427 g.setColor(Color.black); … … 447 447 } else { 448 448 Rectangle target = calculateDrawImageRectangle(visibleRect); 449 g.drawImage(image, 450 target.x, target.y, target.x + target.width, target.y + target.height, 451 visibleRect.x, visibleRect.y, visibleRect.x + visibleRect.width, visibleRect.y + visibleRect.height, 449 g.drawImage(image, 450 target.x, target.y, target.x + target.width, target.y + target.height, 451 visibleRect.x, visibleRect.y, visibleRect.x + visibleRect.width, visibleRect.y + visibleRect.height, 452 452 null); 453 453 if (selectedRect != null) { 454 454 Point topLeft = img2compCoord(visibleRect, selectedRect.x, selectedRect.y); 455 Point bottomRight = img2compCoord(visibleRect, 456 selectedRect.x + selectedRect.width, 455 Point bottomRight = img2compCoord(visibleRect, 456 selectedRect.x + selectedRect.width, 457 457 selectedRect.y + selectedRect.height); 458 458 g.setColor(new Color(128, 128, 128, 180)); … … 502 502 } 503 503 } 504 504 505 505 private final Point img2compCoord(Rectangle visibleRect, int xImg, int yImg) { 506 506 Rectangle drawRect = calculateDrawImageRectangle(visibleRect); … … 524 524 int x, y, w, h; 525 525 x = 0; 526 y = 0; 526 y = 0; 527 527 w = size.width; 528 528 h = size.height; 529 529 530 530 int wFact = w * visibleRect.height; 531 531 int hFact = h * visibleRect.width; … … 546 546 Image image; 547 547 Rectangle visibleRect; 548 548 549 549 synchronized (this) { 550 550 file = ImageDisplay.this.file; … … 560 560 // The display is not at best fit. => Zoom to best fit 561 561 visibleRect = new Rectangle(0, 0, image.getWidth(null), image.getHeight(null)); 562 562 563 563 } else { 564 564 // The display is at best fit => zoom to 1:1 565 565 Point center = getCenterImgCoord(visibleRect); 566 visibleRect = new Rectangle(center.x - getWidth() / 2, center.y - getHeight() / 2, 566 visibleRect = new Rectangle(center.x - getWidth() / 2, center.y - getHeight() / 2, 567 567 getWidth(), getHeight()); 568 568 checkVisibleRectPos(image, visibleRect); 569 569 } 570 570 571 571 synchronized(this) { 572 572 if (file == this.file) {
Note:
See TracChangeset
for help on using the changeset viewer.