Changeset 17878 in josm


Ignore:
Timestamp:
2021-05-06T22:44:54+02:00 (3 months ago)
Author:
simon04
Message:

fix #11710 - Re-geotagging hides pictures that are not covered by GPX track (patch by Bjoeni)

Location:
trunk
Files:
4 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/org/openstreetmap/josm/data/gpx/GpxImageCorrelation.java

    r17715 r17878  
    230230                }
    231231                long tagms = TimeUnit.MINUTES.toMillis(tagTime);
    232                 if (curTmp.getPos() == null &&
     232                if (!curTmp.hasNewGpsData() &&
    233233                        (Math.abs(time - curWpTime) <= tagms
    234234                        || Math.abs(prevWpTime - time) <= tagms)) {
     
    256256                    break;
    257257                }
    258                 if (curTmp.getPos() == null) {
     258                if (!curTmp.hasNewGpsData()) {
    259259                    // The values of timeDiff are between 0 and 1, it is not seconds but a dimensionless variable
    260260                    double timeDiff = (double) (imgTime - prevWpTime) / Math.abs(curWpTime - prevWpTime);
  • trunk/src/org/openstreetmap/josm/data/gpx/GpxImageEntry.java

    r17715 r17878  
    572572            gpsTime = tmp.gpsTime;
    573573            exifImgDir = tmp.exifImgDir;
    574             isNewGpsData = tmp.isNewGpsData;
     574            isNewGpsData = isNewGpsData || tmp.isNewGpsData;
    575575            tmp = null;
    576576        }
  • trunk/src/org/openstreetmap/josm/gui/layer/geoimage/CorrelateGpxWithImages.java

    r17732 r17878  
    10911091            List<ImageEntry> dateImgLst = getSortedImgList();
    10921092            // Create a temporary copy for each image
    1093             for (ImageEntry ie : dateImgLst) {
     1093            dateImgLst.forEach(ie -> {
    10941094                ie.createTmp();
    1095                 ie.getTmp().setPos(null);
    1096             }
     1095                ie.getTmp().unflagNewGpsData();
     1096            });
    10971097
    10981098            GpxDataWrapper selGpx = selectedGPX(false);
  • trunk/test/unit/org/openstreetmap/josm/data/gpx/GpxImageCorrelationTest.java

    r17715 r17878  
    77import static org.junit.jupiter.api.Assertions.assertTrue;
    88
     9import java.io.IOException;
    910import java.util.Arrays;
    1011import java.util.List;
    1112
    1213import org.junit.jupiter.api.BeforeAll;
     14import org.junit.jupiter.api.BeforeEach;
     15import org.junit.jupiter.api.MethodOrderer.Alphanumeric;
    1316import org.junit.jupiter.api.Test;
     17import org.junit.jupiter.api.TestInstance;
     18import org.junit.jupiter.api.TestInstance.Lifecycle;
     19import org.junit.jupiter.api.TestMethodOrder;
    1420import org.junit.jupiter.api.extension.RegisterExtension;
    1521import org.openstreetmap.josm.TestUtils;
     
    2228import org.openstreetmap.josm.tools.date.DateUtils;
    2329import org.openstreetmap.josm.tools.date.DateUtilsTest;
     30import org.xml.sax.SAXException;
    2431
    2532import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
     
    2835 * Unit tests of {@link GpxImageCorrelation} class.
    2936 */
     37@TestMethodOrder(Alphanumeric.class)
     38@TestInstance(Lifecycle.PER_CLASS)
    3039class GpxImageCorrelationTest {
    3140
     
    3746    public JOSMTestRules test = new JOSMTestRules();
    3847
     48    GpxData gpx;
     49    GpxImageEntry ib, i0, i1, i2, i3, i4, i5, i6, i7;
     50    List<GpxImageEntry> images;
     51    IPreferences s;
     52
    3953    /**
    4054     * Setup test.
     55     * @throws IOException if an error occurs during reading.
     56     * @throws SAXException if a SAX error occurs
    4157     */
    4258    @BeforeAll
    43     public static void setUp() {
     59    public void setUp() throws IOException, SAXException {
     60        s = Config.getPref();
    4461        DateUtilsTest.setTimeZone(DateUtils.UTC);
    45     }
    46 
    47     /**
    48      * Tests matching of images to a GPX track.
    49      * @throws Exception if the track cannot be parsed
    50      */
    51     @Test
    52     void testMatchGpxTrack() throws Exception {
    53         IPreferences s = Config.getPref();
    54         final GpxData gpx = GpxReaderTest.parseGpxData(TestUtils.getTestDataRoot() + "tracks/tracks.gpx");
     62
     63        gpx = GpxReaderTest.parseGpxData(TestUtils.getTestDataRoot() + "tracks/tracks.gpx");
    5564        assertEquals(5, gpx.tracks.size());
    5665        assertEquals(1, gpx.tracks.iterator().next().getSegments().size());
    5766        assertEquals(128, gpx.tracks.iterator().next().getSegments().iterator().next().getWayPoints().size());
    5867
    59         final GpxImageEntry ib = new GpxImageEntry();
     68        ib = new GpxImageEntry();
    6069        ib.setExifTime(DateUtils.parseInstant("2016:01:03 11:54:58")); // 5 minutes before start of GPX
    61         ib.createTmp();
    62         final GpxImageEntry i0 = new GpxImageEntry();
     70
     71        i0 = new GpxImageEntry();
    6372        i0.setExifTime(DateUtils.parseInstant("2016:01:03 11:59:54")); // 4 sec before start of GPX
    64         i0.createTmp();
    65         final GpxImageEntry i1 = new GpxImageEntry();
     73
     74        i1 = new GpxImageEntry();
    6675        i1.setExifTime(DateUtils.parseInstant("2016:01:03 12:04:01"));
    67         i1.createTmp();
    68         final GpxImageEntry i2 = new GpxImageEntry();
     76        i1.setPos(new CachedLatLon(2, 3)); //existing position inside the track, should always be overridden
     77
     78        i2 = new GpxImageEntry();
    6979        i2.setExifTime(DateUtils.parseInstant("2016:01:03 12:04:57"));
    70         i2.createTmp();
    71         final GpxImageEntry i3 = new GpxImageEntry();
     80
     81        i3 = new GpxImageEntry();
    7282        i3.setExifTime(DateUtils.parseInstant("2016:01:03 12:05:05"));
    73         i3.createTmp();
    74         final GpxImageEntry i4 = new GpxImageEntry(); //Image close to two points with elevation, but without time
     83
     84        i4 = new GpxImageEntry(); //Image close to two points with elevation, but without time
    7585        i4.setExifTime(DateUtils.parseInstant("2016:01:03 12:05:20"));
    76         i4.createTmp();
    77         final GpxImageEntry i5 = new GpxImageEntry(); //between two tracks, closer to first
     86
     87        i5 = new GpxImageEntry(); //between two tracks, closer to first
    7888        i5.setExifTime(DateUtils.parseInstant("2016:01:03 12:07:00"));
    79         i5.createTmp();
    80         final GpxImageEntry i6 = new GpxImageEntry(); //between two tracks, closer to second (more than 1 minute from any track)
     89
     90        i6 = new GpxImageEntry(); //between two tracks, closer to second (more than 1 minute from any track)
    8191        i6.setExifTime(DateUtils.parseInstant("2016:01:03 12:07:45"));
    82         i6.createTmp();
    83 
    84         List<GpxImageEntry> images = Arrays.asList(ib, i0, i1, i2, i3, i4, i5, i6);
    85 
    86         // TEST #1: default settings
    87         // tag images within 2 minutes to tracks/segments, interpolate between segments only
     92
     93        i7 = new GpxImageEntry();
     94        i7.setExifTime(DateUtils.parseInstant("2021:01:01 00:00:00"));
     95        i7.setPos(new CachedLatLon(1, 2)); //existing position outside the track
     96        // the position should never be null (should keep the old position if not overridden, see #11710)
     97
     98        images = Arrays.asList(ib, i0, i1, i2, i3, i4, i5, i6, i7);
     99    }
     100
     101    @BeforeEach
     102    void clearTmp() {
     103        for (GpxImageEntry i : images) {
     104            i.discardTmp();
     105            i.createTmp();
     106        }
     107    }
     108
     109    /**
     110     * Tests matching of images to a GPX track.
     111     *
     112     * TEST #1: default settings
     113     * tag images within 2 minutes to tracks/segments, interpolate between segments only
     114     */
     115    @Test
     116    void testMatchGpxTrack1() {
    88117        assertEquals(7, GpxImageCorrelation.matchGpxTrack(images, gpx, 0, false));
    89118        assertEquals(null, ib.getPos());
     
    91120        assertEquals(new CachedLatLon(47.196979885920882, 8.79541271366179), i1.getPos()); // exact match
    92121        assertEquals(new CachedLatLon(47.197319911792874, 8.792139580473304), i3.getPos()); // exact match
    93         assertEquals(new CachedLatLon((47.197131179273129 + 47.197186248376966) / 2, (8.792974585667253 + 8.792809881269932) / 2),
    94                 i2.getPos()); // interpolated
    95         assertEquals(new CachedLatLon(47.197568312311816, 8.790292849679897),
    96                 i4.getPos()); // interpolated between points without timestamp
    97         assertEquals(new CachedLatLon(47.19819249585271, 8.78536943346262),
    98                 i5.getPos()); // tagged to last WP of first track, because closer and within 2 min (default setting)
    99         assertEquals(new CachedLatLon(47.20138901844621, 8.774476982653141),
    100                 i6.getPos()); // tagged to first WP of second track, because closer and within 2 min (default setting)
    101         assertFalse(ib.hasNewGpsData());
     122        assertEquals(new CachedLatLon((47.197131179273129 + 47.197186248376966) / 2,
     123                (8.792974585667253 + 8.792809881269932) / 2), i2.getPos()); // interpolated
     124        assertEquals(new CachedLatLon(47.197568312311816, 8.790292849679897), i4.getPos()); // interpolated between points without timestamp
     125        // tagged to last WP of first track, because closer and within 2 min (default setting):
     126        assertEquals(new CachedLatLon(47.19819249585271, 8.78536943346262), i5.getPos());
     127        // tagged to first WP of second track, because closer and within 2 min (default setting):
     128        assertEquals(new CachedLatLon(47.20138901844621, 8.774476982653141), i6.getPos());
     129        assertEquals(new CachedLatLon(1, 2), i7.getPos()); //existing EXIF data is kept
     130        assertFalse(ib.hasNewGpsData() || i7.hasNewGpsData());
    102131        assertTrue(i0.hasNewGpsData() && i1.hasNewGpsData() && i2.hasNewGpsData() && i3.hasNewGpsData()
    103132                && i4.hasNewGpsData() && i5.hasNewGpsData() && i6.hasNewGpsData());
     
    124153        assertEquals(DateUtils.parseInstant("2016:01:03 12:04:57"), i2.getGpsInstant());
    125154        assertEquals(DateUtils.parseInstant("2016:01:03 12:05:05"), i3.getGpsInstant());
    126 
    127         clearTmp(images);
    128 
    129         // TEST #2: Disable all interpolation and tagging close to tracks. Only i1-i4 are tagged
    130 
     155    }
     156
     157    /**
     158     * Tests matching of images to a GPX track.
     159     *
     160     * TEST #2: Disable all interpolation and tagging close to tracks. Only i1-i4 are tagged
     161     */
     162    @Test
     163    void testMatchGpxTrack2() {
    131164        s.putBoolean("geoimage.trk.tag", false);
    132165        s.putBoolean("geoimage.trk.int", false);
     
    138171        assertEquals(null, i0.getPos());
    139172        assertEquals(new CachedLatLon(47.196979885920882, 8.79541271366179), i1.getPos());
    140         assertEquals(new CachedLatLon((47.197131179273129 + 47.197186248376966) / 2, (8.792974585667253 + 8.792809881269932) / 2), i2.getPos());
     173        assertEquals(new CachedLatLon((47.197131179273129 + 47.197186248376966) / 2,
     174                (8.792974585667253 + 8.792809881269932) / 2), i2.getPos());
    141175        assertEquals(new CachedLatLon(47.197319911792874, 8.792139580473304), i3.getPos());
    142176        assertEquals(new CachedLatLon(47.197568312311816, 8.790292849679897), i4.getPos());
    143177        assertEquals(null, i5.getPos());
    144178        assertEquals(null, i6.getPos());
    145 
    146         clearTmp(images);
    147 
    148         // TEST #3: Disable all interpolation and allow tagging within 1 minute of a track. i0-i5 are tagged.
    149         // i6 will not be tagged, because it's 68 seconds away from the next waypoint in either direction
    150 
     179    }
     180
     181    /**
     182     * Tests matching of images to a GPX track.
     183     *
     184     * TEST #3: Disable all interpolation and allow tagging within 1 minute of a track. i0-i5 are tagged.
     185     * i6 will not be tagged, because it's 68 seconds away from the next waypoint in either direction
     186     * i7 will keep the old position
     187     */
     188    @Test
     189    void testMatchGpxTrack3() {
    151190        s.putBoolean("geoimage.trk.tag", true);
    152191        s.putBoolean("geoimage.trk.tag.time", true);
    153192        s.putInt("geoimage.trk.tag.time.val", 1);
    154 
    155193        s.putBoolean("geoimage.trk.int", false);
    156194        s.putBoolean("geoimage.seg.tag", false);
     
    161199        assertEquals(new CachedLatLon(47.19286847859621, 8.79732714034617), i0.getPos());
    162200        assertEquals(new CachedLatLon(47.196979885920882, 8.79541271366179), i1.getPos());
    163         assertEquals(new CachedLatLon((47.197131179273129 + 47.197186248376966) / 2, (8.792974585667253 + 8.792809881269932) / 2), i2.getPos());
     201        assertEquals(new CachedLatLon((47.197131179273129 + 47.197186248376966) / 2,
     202                (8.792974585667253 + 8.792809881269932) / 2), i2.getPos());
    164203        assertEquals(new CachedLatLon(47.197319911792874, 8.792139580473304), i3.getPos());
    165204        assertEquals(new CachedLatLon(47.197568312311816, 8.790292849679897), i4.getPos());
    166205        assertEquals(new CachedLatLon(47.19819249585271, 8.78536943346262), i5.getPos());
    167206        assertEquals(null, i6.getPos());
    168 
    169         clearTmp(images);
    170 
    171         // TEST #4: Force tagging (parameter forceTags=true, no change of configuration). All images will be tagged
    172         // i5-i6 will now be interpolated, therefore it will have an elevation and different coordinates than in tests above
    173 
    174         assertEquals(8, GpxImageCorrelation.matchGpxTrack(images, gpx, 0, true));
     207        assertEquals(new CachedLatLon(1, 2), i7.getPos());
     208    }
     209
     210    /**
     211     * Tests matching of images to a GPX track.
     212     *
     213     * TEST #4: Force tagging (parameter forceTags=true, no change of configuration). All images will be tagged
     214     * i5-i6 will now be interpolated, therefore it will have an elevation and different coordinates than in tests above
     215     * i7 will be at the end of the track
     216     */
     217    @Test
     218    void testMatchGpxTrack4() {
     219        assertEquals(9, GpxImageCorrelation.matchGpxTrack(images, gpx, 0, true));
    175220        assertEquals(new CachedLatLon(47.19286847859621, 8.79732714034617), ib.getPos());
    176221        assertEquals(new CachedLatLon(47.19286847859621, 8.79732714034617), i0.getPos());
    177222        assertEquals(new CachedLatLon(47.196979885920882, 8.79541271366179), i1.getPos());
    178         assertEquals(new CachedLatLon((47.197131179273129 + 47.197186248376966) / 2, (8.792974585667253 + 8.792809881269932) / 2), i2.getPos());
     223        assertEquals(new CachedLatLon((47.197131179273129 + 47.197186248376966) / 2,
     224                (8.792974585667253 + 8.792809881269932) / 2), i2.getPos());
    179225        assertEquals(new CachedLatLon(47.197319911792874, 8.792139580473304), i3.getPos());
    180226        assertEquals(new CachedLatLon(47.197568312311816, 8.790292849679897), i4.getPos());
     
    185231        assertEquals(Double.valueOf(437.395070423), i6.getElevation(), 0.000001);
    186232
    187         clearTmp(images);
    188 
    189         // TEST #5: Force tagging (parameter forceTags=false, but configuration changed).
    190         // Results same as #4
    191 
     233        assertEquals(new CachedLatLon(47.20126815140247, 8.77192972227931), i7.getPos());
     234    }
     235
     236    /**
     237     * Tests matching of images to a GPX track.
     238     *
     239     * TEST #5: Force tagging (parameter forceTags=false, but configuration changed).
     240     * Results same as #4
     241     */
     242    @Test
     243    void testMatchGpxTrack5() {
    192244        s.putBoolean("geoimage.trk.tag", true);
    193245        s.putBoolean("geoimage.trk.tag.time", false);
     
    202254        s.putBoolean("geoimage.seg.int.dist", false);
    203255
    204         assertEquals(8, GpxImageCorrelation.matchGpxTrack(images, gpx, 0, false));
     256        assertEquals(9, GpxImageCorrelation.matchGpxTrack(images, gpx, 0, false));
    205257        assertEquals(new CachedLatLon(47.19286847859621, 8.79732714034617), ib.getPos());
    206258        assertEquals(new CachedLatLon(47.19286847859621, 8.79732714034617), i0.getPos());
    207259        assertEquals(new CachedLatLon(47.196979885920882, 8.79541271366179), i1.getPos());
    208         assertEquals(new CachedLatLon((47.197131179273129 + 47.197186248376966) / 2, (8.792974585667253 + 8.792809881269932) / 2), i2.getPos());
     260        assertEquals(new CachedLatLon((47.197131179273129 + 47.197186248376966) / 2,
     261                (8.792974585667253 + 8.792809881269932) / 2), i2.getPos());
    209262        assertEquals(new CachedLatLon(47.197319911792874, 8.792139580473304), i3.getPos());
    210263        assertEquals(new CachedLatLon(47.197568312311816, 8.790292849679897), i4.getPos());
     
    215268        assertEquals(Double.valueOf(437.395070423), i6.getElevation(), 0.000001);
    216269
    217         clearTmp(images);
    218 
    219         // TEST #6: Disable tagging but allow interpolation when tracks are less than 500m apart. i0-i4 are tagged.
    220         // i5-i6 will not be tagged, because the tracks are 897m apart.
    221         // not checking all the coordinates again, did that 5 times already, just the number of matched images
    222 
     270        assertEquals(new CachedLatLon(47.20126815140247, 8.77192972227931), i7.getPos());
     271    }
     272
     273    /**
     274     * Tests matching of images to a GPX track.
     275     *
     276     * TEST #6: Disable tagging but allow interpolation when tracks are less than 500m apart. i0-i4 are tagged.
     277     * i5-i6 will not be tagged, because the tracks are 897m apart.
     278     * not checking all the coordinates again, did that 5 times already, just the number of matched images
     279     */
     280    @Test
     281    void testMatchGpxTrack6() {
    223282        s.putBoolean("geoimage.trk.tag", false);
    224283        s.putBoolean("geoimage.trk.int", true);
     
    230289
    231290        assertEquals(4, GpxImageCorrelation.matchGpxTrack(images, gpx, 0, false));
    232         clearTmp(images);
    233 
    234         // TEST #7: Disable tagging but allow interpolation when tracks are less than 1000m apart. i0-i6 are tagged.
    235         // i5-i6 will be tagged, because the tracks are 897m apart.
    236 
     291    }
     292
     293    /**
     294     * Tests matching of images to a GPX track.
     295     *
     296     * TEST #7: Disable tagging but allow interpolation when tracks are less than 1000m apart. i0-i6 are tagged.
     297     * i5-i6 will be tagged, because the tracks are 897m apart.
     298     */
     299    @Test
     300    void testMatchGpxTrack7() {
     301        s.putBoolean("geoimage.trk.tag", false);
     302        s.putBoolean("geoimage.trk.int", true);
     303        s.putBoolean("geoimage.trk.int.time", false);
     304        s.putBoolean("geoimage.trk.int.dist", true);
    237305        s.putInt("geoimage.trk.int.dist.val", 1000);
     306        s.putBoolean("geoimage.seg.tag", false);
     307        s.putBoolean("geoimage.seg.int", false);
    238308
    239309        assertEquals(6, GpxImageCorrelation.matchGpxTrack(images, gpx, 0, false));
    240         clearTmp(images);
    241 
    242         // TEST #8: Disable tagging but allow interpolation when tracks are less than 2 min apart. i0-i4 are tagged.
    243         // i5-i6 will not be tagged, because the tracks are 2.5min apart.
    244 
     310    }
     311
     312    /**
     313     * Tests matching of images to a GPX track.
     314     *
     315     * TEST #8: Disable tagging but allow interpolation when tracks are less than 2 min apart. i0-i4 are tagged.
     316     * i5-i6 will not be tagged, because the tracks are 2.5min apart.
     317     */
     318    @Test
     319    void testMatchGpxTrack8() {
    245320        s.putBoolean("geoimage.trk.tag", false);
    246321        s.putBoolean("geoimage.trk.int", true);
     
    252327
    253328        assertEquals(4, GpxImageCorrelation.matchGpxTrack(images, gpx, 0, false));
    254         clearTmp(images);
    255 
    256         // TEST #9: Disable tagging but allow interpolation when tracks are less than 3 min apart. i0-i6 are tagged.
    257         // i5-i6 will be tagged, because the tracks are 2.5min apart.
    258 
     329    }
     330
     331    /**
     332     * Tests matching of images to a GPX track.
     333     *
     334     * TEST #9: Disable tagging but allow interpolation when tracks are less than 3 min apart. i0-i6 are tagged.
     335     * i5-i6 will be tagged, because the tracks are 2.5min apart.
     336     */
     337    @Test
     338    void testMatchGpxTrack9() {
     339        s.putBoolean("geoimage.trk.tag", false);
     340        s.putBoolean("geoimage.trk.int", true);
     341        s.putBoolean("geoimage.trk.int.time", true);
    259342        s.putInt("geoimage.trk.int.time.val", 3);
     343        s.putBoolean("geoimage.trk.int.dist", false);
     344        s.putBoolean("geoimage.seg.tag", false);
     345        s.putBoolean("geoimage.seg.int", false);
    260346
    261347        assertEquals(6, GpxImageCorrelation.matchGpxTrack(images, gpx, 0, false));
    262 
    263     }
    264 
    265     private void clearTmp(List<GpxImageEntry> imgs) {
    266         for (GpxImageEntry i : imgs) {
    267             i.discardTmp();
    268             i.createTmp();
    269         }
    270348    }
    271349
Note: See TracChangeset for help on using the changeset viewer.