Changeset 9726 in josm


Ignore:
Timestamp:
2016-02-03T20:57:12+01:00 (9 years ago)
Author:
simon04
Message:

see #12485 - Wrong GPX Correlation, add unit test

Regression from r9383, confusion between s and ms.

Location:
trunk
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/org/openstreetmap/josm/gui/layer/geoimage/CorrelateGpxWithImages.java

    r9698 r9726  
    8080import org.openstreetmap.josm.tools.GBC;
    8181import org.openstreetmap.josm.tools.ImageProvider;
     82import org.openstreetmap.josm.tools.Pair;
    8283import org.openstreetmap.josm.tools.Utils;
    8384import org.openstreetmap.josm.tools.date.DateUtils;
     
    10001001    }
    10011002
     1003    static class NoGpxTimestamps extends Exception {
     1004    }
     1005
     1006    /**
     1007     * Tries to auto-guess the timezone and offset.
     1008     *
     1009     * @param imgs the images to correlate
     1010     * @param gpx the gpx track to correlate to
     1011     * @return a pair of timezone (in hours) and offset (in seconds)
     1012     * @throws IndexOutOfBoundsException when there are no images
     1013     * @throws NoGpxTimestamps when the gpx track does not contain a timestamp
     1014     */
     1015    static Pair<Double, Long> autoGuess(List<ImageEntry> imgs, GpxData gpx) throws IndexOutOfBoundsException, NoGpxTimestamps {
     1016
     1017        // Init variables
     1018        long firstExifDate = imgs.get(0).getExifTime().getTime() / 1000;
     1019
     1020        long firstGPXDate = -1;
     1021        // Finds first GPX point
     1022        outer: for (GpxTrack trk : gpx.tracks) {
     1023            for (GpxTrackSegment segment : trk.getSegments()) {
     1024                for (WayPoint curWp : segment.getWayPoints()) {
     1025                    try {
     1026                        final Date parsedTime = curWp.setTimeFromAttribute();
     1027                        if (parsedTime != null) {
     1028                            firstGPXDate = parsedTime.getTime() / 1000;
     1029                            break outer;
     1030                        }
     1031                    } catch (Exception e) {
     1032                        Main.warn(e);
     1033                    }
     1034                }
     1035            }
     1036        }
     1037
     1038        if (firstGPXDate < 0) {
     1039            throw new NoGpxTimestamps();
     1040        }
     1041
     1042        // seconds
     1043        long diff = firstExifDate - firstGPXDate;
     1044
     1045        double diffInH = (double) diff / (60 * 60);    // hours
     1046
     1047        // Find day difference
     1048        int dayOffset = (int) Math.round(diffInH / 24); // days
     1049        double tz = diff - dayOffset * 24 * 60 * 60L;  // seconds
     1050
     1051        // In hours, rounded to two decimal places
     1052        tz = (double) Math.round(tz * 100 / (60 * 60)) / 100;
     1053
     1054        // Due to imprecise clocks we might get a "+3:28" timezone, which should obviously be 3:30 with
     1055        // -2 minutes offset. This determines the real timezone and finds offset.
     1056        final double timezone = (double) Math.round(tz * 2) / 2; // hours, rounded to one decimal place
     1057        final long delta = Math.round(diff - timezone * 60 * 60); // seconds
     1058        return Pair.create(timezone, delta);
     1059    }
     1060
    10021061    private class AutoGuessActionListener implements ActionListener {
    10031062
     
    10111070            List<ImageEntry> imgs = getSortedImgList();
    10121071
    1013             // no images found, exit
    1014             if (imgs.isEmpty()) {
     1072            try {
     1073                final Pair<Double, Long> r = autoGuess(imgs, gpx);
     1074                timezone = r.a;
     1075                delta = r.b;
     1076            } catch (IndexOutOfBoundsException ex) {
    10151077                JOptionPane.showMessageDialog(Main.parent,
    10161078                        tr("The selected photos do not contain time information."),
    10171079                        tr("Photos do not contain time information"), JOptionPane.WARNING_MESSAGE);
    10181080                return;
    1019             }
    1020 
    1021             // Init variables
    1022             long firstExifDate = imgs.get(0).getExifTime().getTime()/1000;
    1023 
    1024             long firstGPXDate = -1;
    1025             // Finds first GPX point
    1026             outer: for (GpxTrack trk : gpx.tracks) {
    1027                 for (GpxTrackSegment segment : trk.getSegments()) {
    1028                     for (WayPoint curWp : segment.getWayPoints()) {
    1029                         try {
    1030                             final Date parsedTime = curWp.setTimeFromAttribute();
    1031                             if (parsedTime != null) {
    1032                                 firstGPXDate = parsedTime.getTime();
    1033                                 break outer;
    1034                             }
    1035                         } catch (Exception e) {
    1036                             Main.warn(e);
    1037                         }
    1038                     }
    1039                 }
    1040             }
    1041 
    1042             // No GPX timestamps found, exit
    1043             if (firstGPXDate < 0) {
     1081            } catch (NoGpxTimestamps ex) {
    10441082                JOptionPane.showMessageDialog(Main.parent,
    10451083                        tr("The selected GPX track does not contain timestamps. Please select another one."),
     
    10471085                return;
    10481086            }
    1049 
    1050             // seconds
    1051             long diff = firstExifDate - firstGPXDate;
    1052 
    1053             double diffInH = (double) diff/(60*60);    // hours
    1054 
    1055             // Find day difference
    1056             int dayOffset = (int) Math.round(diffInH / 24); // days
    1057             double tz = diff - dayOffset*24*60*60L;  // seconds
    1058 
    1059             // In hours, rounded to two decimal places
    1060             tz = (double) Math.round(tz*100/(60*60)) / 100;
    1061 
    1062             // Due to imprecise clocks we might get a "+3:28" timezone, which should obviously be 3:30 with
    1063             // -2 minutes offset. This determines the real timezone and finds offset.
    1064             timezone = (double) Math.round(tz * 2)/2; // hours, rounded to one decimal place
    1065             delta = Math.round(diff - timezone*60*60); // seconds
    10661087
    10671088            tfTimezone.getDocument().removeDocumentListener(statusBarUpdater);
  • trunk/test/unit/org/openstreetmap/josm/gui/layer/geoimage/CorrelateGpxWithImagesTest.java

    r9669 r9726  
    55
    66import java.util.Arrays;
     7import java.util.Collections;
    78import java.util.TimeZone;
    89
     
    1213import org.openstreetmap.josm.data.gpx.GpxData;
    1314import org.openstreetmap.josm.io.GpxReaderTest;
     15import org.openstreetmap.josm.tools.Pair;
    1416import org.openstreetmap.josm.tools.date.DateUtils;
    1517import org.openstreetmap.josm.tools.date.DateUtilsTest;
     
    5961                i2.getPos()); // interpolated
    6062    }
     63
     64    /**
     65     * Tests automatic guessing of timezone/offset
     66     * @throws Exception if an error occurs
     67     */
     68    @Test
     69    public void testAutoGuess() throws Exception {
     70        final GpxData gpx = GpxReaderTest.parseGpxData("data_nodist/2094047.gpx");
     71        final ImageEntry i0 = new ImageEntry();
     72        i0.setExifTime(DateUtils.fromString("2016:01:03 11:59:54")); // 4 sec before start of GPX
     73        i0.createTmp();
     74        assertEquals(Pair.create(0.0, -4L), CorrelateGpxWithImages.autoGuess(Collections.singletonList(i0), gpx));
     75    }
    6176}
Note: See TracChangeset for help on using the changeset viewer.