Changeset 18065 in josm for trunk/src/org


Ignore:
Timestamp:
2021-07-18T15:40:42+02:00 (3 years ago)
Author:
Don-vip
Message:

fix #21131 - allow to edit direction/position of sequence of geo-images without GPX track

Location:
trunk/src/org/openstreetmap/josm
Files:
1 added
6 edited

Legend:

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

    r18061 r18065  
    2626
    2727    /**
    28      * Match a list of photos to a gpx track with a given offset.
     28     * Match a list of photos to a gpx track with given settings.
    2929     * All images need a exifTime attribute and the List must be sorted according to these times.
    3030     * @param images images to match
     
    3535    public static int matchGpxTrack(List<? extends GpxImageEntry> images, GpxData selectedGpx, GpxImageCorrelationSettings settings) {
    3636        int ret = 0;
     37
     38        if (Logging.isDebugEnabled()) {
     39            Logging.debug("Correlating {0} images to {1} GPX track segments using {2}",
     40                    images.size(), selectedGpx.getTrackSegsCount(), settings);
     41        }
    3742
    3843        boolean trkInt, trkTag, segInt, segTag;
     
    7378        WayPoint prevWp = null;
    7479
    75         for (List<List<WayPoint>> segs : loadTracks(selectedGpx.tracks)) {
     80        for (List<List<WayPoint>> segs : loadTracks(selectedGpx.getTracks())) {
    7681            boolean firstSegment = true;
    7782            for (List<WayPoint> wps : segs) {
  • trunk/src/org/openstreetmap/josm/data/gpx/GpxImageCorrelationSettings.java

    r18061 r18065  
    5959        return directionPositionSettings;
    6060    }
     61
     62    @Override
     63    public String toString() {
     64        return "[offset=" + offset + ", forceTags=" + forceTags
     65                + ", directionPositionSettings=" + directionPositionSettings + ']';
     66    }
    6167}
  • trunk/src/org/openstreetmap/josm/data/gpx/GpxImageDirectionPositionSettings.java

    r18061 r18065  
    7070        return elevationShift;
    7171    }
     72
     73    @Override
     74    public String toString() {
     75        return "[setImageDirection=" + setImageDirection
     76                + ", imageDirectionAngleOffset=" + imageDirectionAngleOffset + ", shiftImageX=" + shiftImageX
     77                + ", shiftImageY=" + shiftImageY + ", elevationShift=" + elevationShift + ']';
     78    }
    7279}
  • trunk/src/org/openstreetmap/josm/data/gpx/GpxImageEntry.java

    r18014 r18065  
    1111import java.util.Locale;
    1212import java.util.Objects;
     13import java.util.Optional;
    1314import java.util.function.Consumer;
    1415
     
    512513     * {@link #applyTmp()} or {@link #discardTmp()} if the temporary variable
    513514     * is not needed anymore.
    514      */
    515     public void createTmp() {
     515     * @return the fresh copy.
     516     */
     517    public GpxImageEntry createTmp() {
    516518        tmp = new GpxImageEntry(this);
    517519        tmp.tmp = null;
     520        return tmp;
    518521    }
    519522
     
    765768        }
    766769    }
     770
     771    /**
     772     * Returns a {@link WayPoint} representation of this GPX image entry.
     773     * @return a {@code WayPoint} representation of this GPX image entry (containing position, instant and elevation)
     774     * @since 18065
     775     */
     776    public WayPoint asWayPoint() {
     777        CachedLatLon position = getPos();
     778        WayPoint wpt = null;
     779        if (position != null) {
     780            wpt = new WayPoint(position);
     781            wpt.setInstant(Optional.ofNullable(exifGpsTime).orElse(exifTime));
     782            Double ele = getElevation();
     783            if (ele != null) {
     784                wpt.put(GpxConstants.PT_ELE, ele.toString());
     785            }
     786        }
     787        return wpt;
     788    }
    767789}
  • trunk/src/org/openstreetmap/josm/gui/layer/geoimage/CorrelateGpxWithImages.java

    r18061 r18065  
    2424import java.io.File;
    2525import java.text.ParseException;
    26 import java.util.Comparator;
    2726import java.util.List;
     27import java.util.Objects;
    2828import java.util.TimeZone;
    2929import java.util.concurrent.TimeUnit;
    3030import java.util.function.Consumer;
    31 import java.util.stream.Collectors;
    3231
    3332import javax.swing.AbstractAction;
     
    5251import org.openstreetmap.josm.data.gpx.GpxImageCorrelation;
    5352import org.openstreetmap.josm.data.gpx.GpxImageCorrelationSettings;
    54 import org.openstreetmap.josm.data.gpx.GpxImageEntry;
    5553import org.openstreetmap.josm.data.gpx.GpxTimeOffset;
    5654import org.openstreetmap.josm.data.gpx.GpxTimezone;
     
    152150            case CANCEL:
    153151                if (yLayer != null) {
    154                     for (ImageEntry ie : yLayer.getImageData().getImages()) {
    155                         ie.discardTmp();
    156                     }
     152                    yLayer.discardTmp();
    157153                    yLayer.updateBufferAndRepaint();
    158154                }
     
    188184                }
    189185
    190                 for (ImageEntry ie : yLayer.getImageData().getImages()) {
    191                     ie.applyTmp();
    192                 }
    193 
     186                yLayer.applyTmp();
    194187                yLayer.updateBufferAndRepaint();
    195188
    196189                break;
    197190            default:
    198                 throw new IllegalStateException();
     191                throw new IllegalStateException(Integer.toString(result));
    199192            }
    200193        }
     
    469462        JLabel labelPosition = new JLabel(tr("Override position for: "));
    470463
    471         int numAll = getSortedImgList(true, true).size();
    472         int numExif = numAll - getSortedImgList(false, true).size();
    473         int numTagged = numAll - getSortedImgList(true, false).size();
     464        int numAll = yLayer.getSortedImgList(true, true).size();
     465        int numExif = numAll - yLayer.getSortedImgList(false, true).size();
     466        int numTagged = numAll - yLayer.getSortedImgList(true, false).size();
    474467
    475468        cbExifImg = new JCheckBox(tr("Images with geo location in exif data ({0}/{1})", numExif, numAll));
     
    581574        statusBar.add(statusBarText);
    582575
    583         RepaintTheMapListener repaintTheMap = new RepaintTheMapListener();
     576        RepaintTheMapListener repaintTheMap = new RepaintTheMapListener(yLayer);
    584577        pDirectionPosition.addFocusListenerOnComponent(repaintTheMap);
    585578        tfTimezone.addFocusListener(repaintTheMap);
     
    703696            // The selection of images we are about to correlate may have changed.
    704697            // So reset all images.
    705             for (ImageEntry ie: yLayer.getImageData().getImages()) {
    706                 ie.discardTmp();
    707             }
     698            yLayer.discardTmp();
    708699
    709700            // Construct a list of images that have a date, and sort them on the date.
    710701            List<ImageEntry> dateImgLst = getSortedImgList();
    711702            // Create a temporary copy for each image
    712             dateImgLst.forEach(ie -> {
    713                 ie.createTmp();
    714                 ie.getTmp().unflagNewGpsData();
    715             });
     703            dateImgLst.forEach(ie -> ie.createTmp().unflagNewGpsData());
    716704
    717705            GpxDataWrapper selGpx = selectedGPX(false);
     
    731719    }
    732720
    733     private class RepaintTheMapListener implements FocusListener {
     721    static class RepaintTheMapListener implements FocusListener {
     722
     723        private final GeoImageLayer yLayer;
     724
     725        RepaintTheMapListener(GeoImageLayer yLayer) {
     726            this.yLayer = Objects.requireNonNull(yLayer);
     727        }
     728
    734729        @Override
    735730        public void focusGained(FocusEvent e) { // do nothing
     
    877872
    878873    private List<ImageEntry> getSortedImgList() {
    879         return getSortedImgList(cbExifImg.isSelected(), cbTaggedImg.isSelected());
    880     }
    881 
    882     /**
    883      * Returns a list of images that fulfill the given criteria.
    884      * Default setting is to return untagged images, but may be overwritten.
    885      * @param exif also returns images with exif-gps info
    886      * @param tagged also returns tagged images
    887      * @return matching images
    888      */
    889     private List<ImageEntry> getSortedImgList(boolean exif, boolean tagged) {
    890         return yLayer.getImageData().getImages().stream()
    891                 .filter(GpxImageEntry::hasExifTime)
    892                 .filter(e -> e.getExifCoor() == null || exif)
    893                 .filter(e -> tagged || !e.isTagged() || e.getExifCoor() != null)
    894                 .sorted(Comparator.comparing(ImageEntry::getExifInstant))
    895                 .collect(Collectors.toList());
     874        return yLayer.getSortedImgList(cbExifImg.isSelected(), cbTaggedImg.isSelected());
    896875    }
    897876
  • trunk/src/org/openstreetmap/josm/gui/layer/geoimage/GeoImageLayer.java

    r18035 r18065  
    22package org.openstreetmap.josm.gui.layer.geoimage;
    33
     4import static java.util.stream.Collectors.toList;
    45import static org.openstreetmap.josm.tools.I18n.tr;
    56import static org.openstreetmap.josm.tools.I18n.trn;
     
    2122import java.io.File;
    2223import java.util.ArrayList;
     24import java.util.Arrays;
    2325import java.util.Collection;
     26import java.util.Collections;
     27import java.util.Comparator;
    2428import java.util.LinkedList;
    2529import java.util.List;
     30import java.util.Objects;
    2631import java.util.concurrent.ExecutorService;
    2732import java.util.concurrent.Executors;
     
    3136
    3237import org.openstreetmap.josm.actions.AutoScaleAction;
     38import org.openstreetmap.josm.actions.ExpertToggleAction;
    3339import org.openstreetmap.josm.actions.RenameLayerAction;
    3440import org.openstreetmap.josm.actions.mapmode.MapMode;
     
    4046import org.openstreetmap.josm.data.ImageData.ImageDataUpdateListener;
    4147import org.openstreetmap.josm.data.gpx.GpxData;
    42 import org.openstreetmap.josm.data.gpx.WayPoint;
     48import org.openstreetmap.josm.data.gpx.GpxImageEntry;
     49import org.openstreetmap.josm.data.gpx.GpxTrack;
    4350import org.openstreetmap.josm.data.osm.visitor.BoundingXYVisitor;
    4451import org.openstreetmap.josm.gui.MainApplication;
     
    7279    GpxLayer gpxLayer;
    7380    GpxLayer gpxFauxLayer;
     81    GpxData gpxFauxData;
    7482
    7583    private CorrelateGpxWithImages gpxCorrelateAction;
     
    247255        entries.add(SeparatorLayerAction.INSTANCE);
    248256        entries.add(getGpxCorrelateAction());
     257        if (ExpertToggleAction.isExpert()) {
     258            entries.add(new EditImagesSequenceAction(this));
     259        }
    249260        entries.add(new ShowThumbnailAction(this));
    250261        if (!menuAdditions.isEmpty()) {
     
    807818        if (gpxLayer != null) return getGpxLayer();
    808819        if (gpxFauxLayer == null) {
    809             GpxData gpxData = new GpxData();
    810             for (ImageEntry image : data.getImages()) {
    811                 gpxData.addWaypoint(new WayPoint(image.getPos()));
    812             }
    813             gpxFauxLayer = new GpxLayer(gpxData);
     820            gpxFauxLayer = new GpxLayer(getFauxGpxData());
    814821        }
    815822        return gpxFauxLayer;
     823    }
     824
     825    /**
     826     * Returns a faux GPX data built from the images or the associated GPX layer data.
     827     * @return A faux GPX data or the associated GPX layer data
     828     * @since 18065
     829     */
     830    public synchronized GpxData getFauxGpxData() {
     831        if (gpxLayer != null) return getGpxLayer().data;
     832        if (gpxFauxData == null) {
     833            gpxFauxData = new GpxData();
     834            gpxFauxData.addTrack(new GpxTrack(Arrays.asList(
     835                    data.getImages().stream().map(ImageEntry::asWayPoint).filter(Objects::nonNull).collect(toList())),
     836                    Collections.emptyMap()));
     837        }
     838        return gpxFauxData;
    816839    }
    817840
     
    870893        return data;
    871894    }
     895
     896    void applyTmp() {
     897        data.getImages().forEach(ImageEntry::applyTmp);
     898    }
     899
     900    void discardTmp() {
     901        data.getImages().forEach(ImageEntry::discardTmp);
     902    }
     903
     904    /**
     905     * Returns a list of images that fulfill the given criteria.
     906     * Default setting is to return untagged images, but may be overwritten.
     907     * @param exif also returns images with exif-gps info
     908     * @param tagged also returns tagged images
     909     * @return matching images
     910     */
     911    List<ImageEntry> getSortedImgList(boolean exif, boolean tagged) {
     912        return data.getImages().stream()
     913                .filter(GpxImageEntry::hasExifTime)
     914                .filter(e -> e.getExifCoor() == null || exif)
     915                .filter(e -> tagged || !e.isTagged() || e.getExifCoor() != null)
     916                .sorted(Comparator.comparing(ImageEntry::getExifInstant))
     917                .collect(toList());
     918    }
    872919}
Note: See TracChangeset for help on using the changeset viewer.