Changeset 9742 in josm for trunk


Ignore:
Timestamp:
2016-02-05T00:31:52+01:00 (9 years ago)
Author:
simon04
Message:

fix #12486 - Gpx/image correlation: allow sub-second offset

The textfield allows to input offsets in 1/1000s ("1.234" = 1234ms).
The seconds slider in the manual adjustment allows offsets of 1/10s.

Location:
trunk
Files:
2 edited

Legend:

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

    r9741 r9742  
    3535import java.util.Hashtable;
    3636import java.util.List;
     37import java.util.Locale;
    3738import java.util.Objects;
    3839import java.util.TimeZone;
     
    869870        public void actionPerformed(ActionEvent arg0) {
    870871
    871             long diff = delta.getSeconds() + Math.round(timezone.getHours() * 60 * 60);
    872 
    873             double diffInH = (double) diff/(60*60);    // hours
    874 
    875             // Find day difference
    876             final int dayOffset = (int) Math.round(diffInH / 24); // days
    877             double tmz = diff - dayOffset*24*60*60L;  // seconds
    878 
    879             // In hours, rounded to two decimal places
    880             tmz = (double) Math.round(tmz*100/(60*60)) / 100;
    881 
    882             // Due to imprecise clocks we might get a "+3:28" timezone, which should obviously be 3:30 with
    883             // -2 minutes offset. This determines the real timezone and finds offset.
    884             double fixTimezone = (double) Math.round(tmz * 2)/2; // hours, rounded to one decimal place
    885             int offset = (int) Math.round(diff - fixTimezone*60*60) - dayOffset*24*60*60; // seconds
     872            final Offset offset = Offset.milliseconds(
     873                    delta.getMilliseconds() + Math.round(timezone.getHours() * 60 * 60 * 1000));
     874            final int dayOffset = offset.getDayOffset();
     875            final Pair<Timezone, Offset> timezoneOffsetPair = offset.withoutDayOffset().splitOutTimezone();
    886876
    887877            // Info Labels
     
    895885            Dictionary<Integer, JLabel> labelTable = new Hashtable<>();
    896886            // CHECKSTYLE.OFF: ParenPad
    897             labelTable.put(-24, new JLabel("-12:00"));
    898             labelTable.put(-12, new JLabel( "-6:00"));
    899             labelTable.put(  0, new JLabel(  "0:00"));
    900             labelTable.put( 12, new JLabel(  "6:00"));
    901             labelTable.put( 24, new JLabel( "12:00"));
     887            for (int i = -12; i <= 12; i += 6) {
     888                labelTable.put(i * 2, new JLabel(new Timezone(i).formatTimezone()));
     889            }
    902890            // CHECKSTYLE.ON: ParenPad
    903891            sldTimezone.setLabelTable(labelTable);
     
    911899            // Seconds slider
    912900            final JLabel lblSeconds = new JLabel();
    913             final JSlider sldSeconds = new JSlider(-60, 60, 0);
     901            final JSlider sldSeconds = new JSlider(-600, 600, 0);
    914902            sldSeconds.setPaintLabels(true);
    915             sldSeconds.setMajorTickSpacing(30);
     903            labelTable = new Hashtable<>();
     904            // CHECKSTYLE.OFF: ParenPad
     905            for (int i = -60; i <= 60; i += 30) {
     906                labelTable.put(i * 10, new JLabel(Offset.seconds(i).formatOffset()));
     907            }
     908            // CHECKSTYLE.ON: ParenPad
     909            sldSeconds.setLabelTable(labelTable);
     910            sldSeconds.setMajorTickSpacing(300);
    916911
    917912            // This is called whenever one of the sliders is moved.
     
    920915                @Override
    921916                public void stateChanged(ChangeEvent e) {
    922                     // parse slider position into real timezone
    923                     double tz = Math.abs(sldTimezone.getValue());
    924                     String zone = tz % 2 == 0
    925                     ? (int) Math.floor(tz/2) + ":00"
    926                             : (int) Math.floor(tz/2) + ":30";
    927                     if (sldTimezone.getValue() < 0) {
    928                         zone = '-' + zone;
    929                     }
    930 
    931                     lblTimezone.setText(tr("Timezone: {0}", zone));
     917                    timezone = new Timezone(sldTimezone.getValue() / 2.);
     918
     919                    lblTimezone.setText(tr("Timezone: {0}", timezone.formatTimezone()));
    932920                    lblMinutes.setText(tr("Minutes: {0}", sldMinutes.getValue()));
    933                     lblSeconds.setText(tr("Seconds: {0}", sldSeconds.getValue()));
    934 
    935                     try {
    936                         timezone = Timezone.parseTimezone(zone);
    937                     } catch (ParseException pe) {
    938                         throw new RuntimeException(pe);
    939                     }
    940                     delta = Offset.seconds(sldMinutes.getValue() * 60 + sldSeconds.getValue() + 24 * 60 * 60L * dayOffset); // add the day offset
     921                    lblSeconds.setText(tr("Seconds: {0}", Offset.milliseconds(100 * sldSeconds.getValue()).formatOffset()));
     922
     923                    delta = Offset.milliseconds(100 * sldSeconds.getValue()
     924                            + 1000L * 60 * sldMinutes.getValue()
     925                            + 1000L * 60 * 60 * 24 * dayOffset);
    941926
    942927                    tfTimezone.getDocument().removeDocumentListener(statusBarUpdater);
     
    972957            // and inform the user about it.
    973958            try {
    974                 sldTimezone.setValue((int) (fixTimezone*2));
    975                 sldMinutes.setValue(offset / 60);
    976                 sldSeconds.setValue(offset % 60);
     959                sldTimezone.setValue((int) (timezoneOffsetPair.a.getHours() * 2));
     960                sldMinutes.setValue((int) (timezoneOffsetPair.b.getSeconds() / 60));
     961                final long deciSeconds = timezoneOffsetPair.b.getMilliseconds() / 100;
     962                sldSeconds.setValue((int) (deciSeconds % 60));
    977963            } catch (Exception e) {
    978964                JOptionPane.showMessageDialog(Main.parent,
     
    10161002
    10171003        // Init variables
    1018         long firstExifDate = imgs.get(0).getExifTime().getTime() / 1000;
     1004        long firstExifDate = imgs.get(0).getExifTime().getTime();
    10191005
    10201006        long firstGPXDate = -1;
     
    10261012                        final Date parsedTime = curWp.setTimeFromAttribute();
    10271013                        if (parsedTime != null) {
    1028                             firstGPXDate = parsedTime.getTime() / 1000;
     1014                            firstGPXDate = parsedTime.getTime();
    10291015                            break outer;
    10301016                        }
     
    10401026        }
    10411027
    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(new Timezone(timezone), Offset.seconds(delta));
     1028        return Offset.milliseconds(firstExifDate - firstGPXDate).splitOutTimezone();
    10591029    }
    10601030
     
    14701440
    14711441        String formatOffset() {
    1472             return Long.toString(milliseconds / 1000);
     1442            if (milliseconds % 1000 == 0) {
     1443                return Long.toString(milliseconds / 1000);
     1444            } else if (milliseconds % 100 == 0) {
     1445                return String.format(Locale.ENGLISH, "%.1f", milliseconds / 1000.);
     1446            } else {
     1447                return String.format(Locale.ENGLISH, "%.3f", milliseconds / 1000.);
     1448            }
    14731449        }
    14741450
     
    14811457                        offset = offset.substring(1);
    14821458                    }
    1483                     return Offset.seconds(Long.parseLong(offset));
     1459                    return Offset.milliseconds(Math.round(Double.parseDouble(offset) * 1000));
    14841460                } catch (NumberFormatException nfe) {
    14851461                    throw new ParseException(error, 0);
     
    14881464                return Offset.ZERO;
    14891465            }
     1466        }
     1467
     1468        int getDayOffset() {
     1469            final double diffInH = (double) getMilliseconds() / 1000. / 60 / 60; // hours
     1470
     1471            // Find day difference
     1472            return (int) Math.round(diffInH / 24);
     1473        }
     1474
     1475        Offset withoutDayOffset() {
     1476            return milliseconds(getMilliseconds() - getDayOffset() * 24 * 60 * 60 * 1000);
     1477        }
     1478
     1479        Pair<Timezone, Offset> splitOutTimezone() {
     1480            // In hours, rounded to two decimal places
     1481            double tz = (double) Math.round(withoutDayOffset().getSeconds() * 100 / (60 * 60)) / 100;
     1482
     1483            // Due to imprecise clocks we might get a "+3:28" timezone, which should obviously be 3:30 with
     1484            // -2 minutes offset. This determines the real timezone and finds offset.
     1485            final double timezone = (double) Math.round(tz * 2) / 2; // hours, rounded to one decimal place
     1486            final long delta = Math.round(getMilliseconds() - timezone * 60 * 60 * 1000); // milliseconds
     1487            return Pair.create(new Timezone(timezone), Offset.milliseconds(delta));
    14901488        }
    14911489
  • trunk/test/unit/org/openstreetmap/josm/gui/layer/geoimage/CorrelateGpxWithImagesTest.java

    r9741 r9742  
    9999        assertEquals("123", CorrelateGpxWithImages.Offset.seconds(123).formatOffset());
    100100        assertEquals("-4242", CorrelateGpxWithImages.Offset.seconds(-4242).formatOffset());
     101        assertEquals("0.1", CorrelateGpxWithImages.Offset.milliseconds(100).formatOffset());
     102        assertEquals("0.120", CorrelateGpxWithImages.Offset.milliseconds(120).formatOffset());
     103        assertEquals("0.123", CorrelateGpxWithImages.Offset.milliseconds(123).formatOffset());
     104        assertEquals("1.2", CorrelateGpxWithImages.Offset.milliseconds(1200).formatOffset());
     105        assertEquals("1.234", CorrelateGpxWithImages.Offset.milliseconds(1234).formatOffset());
    101106    }
    102107
     
    107112        assertEquals(-4242L, CorrelateGpxWithImages.Offset.parseOffset("-4242").getSeconds());
    108113        assertEquals(0L, CorrelateGpxWithImages.Offset.parseOffset("-0").getSeconds());
     114        assertEquals(100L, CorrelateGpxWithImages.Offset.parseOffset("0.1").getMilliseconds());
     115        assertEquals(123L, CorrelateGpxWithImages.Offset.parseOffset("0.123").getMilliseconds());
     116        assertEquals(-42420L, CorrelateGpxWithImages.Offset.parseOffset("-42.42").getMilliseconds());
     117    }
     118
     119    @Test
     120    public void testSplitOutTimezone() throws Exception {
     121        assertEquals("+1:00", CorrelateGpxWithImages.Offset.seconds(3602).splitOutTimezone().a.formatTimezone());
     122        assertEquals("2", CorrelateGpxWithImages.Offset.seconds(3602).splitOutTimezone().b.formatOffset());
     123        assertEquals("-7:00", CorrelateGpxWithImages.Offset.seconds(-7 * 3600 + 123).splitOutTimezone().a.formatTimezone());
     124        assertEquals("123", CorrelateGpxWithImages.Offset.seconds(-7 * 3600 + 123).splitOutTimezone().b.formatOffset());
     125        assertEquals(1, CorrelateGpxWithImages.Offset.seconds(35 * 3600 + 421).getDayOffset());
     126        assertEquals(11 * 3600 + 421, CorrelateGpxWithImages.Offset.seconds(35 * 3600 + 421).withoutDayOffset().getSeconds());
     127        assertEquals("+11:00", CorrelateGpxWithImages.Offset.seconds(35 * 3600 + 421).splitOutTimezone().a.formatTimezone());
     128        assertEquals(86400 + 421, CorrelateGpxWithImages.Offset.seconds(35 * 3600 + 421).splitOutTimezone().b.getSeconds());
     129        assertEquals(421, CorrelateGpxWithImages.Offset.seconds(35 * 3600 + 421).withoutDayOffset().splitOutTimezone().b.getSeconds());
     130        assertEquals("+1:00", CorrelateGpxWithImages.Offset.milliseconds(3602987).splitOutTimezone().a.formatTimezone());
     131        assertEquals("2.987", CorrelateGpxWithImages.Offset.milliseconds(3602987).splitOutTimezone().b.formatOffset());
    109132    }
    110133}
Note: See TracChangeset for help on using the changeset viewer.