Ticket #18121: patch_align_images.patch

File patch_align_images.patch, 8.4 KB (added by francois2, 5 years ago)

Align images in the photoadjust plugin

  • plugins/photoadjust/src/org/openstreetmap/josm/plugins/photoadjust/InterpolateImages.java

    Cannot display: file marked as a binary type.
    svn:mime-type = application/java-archive
     
     1// License: GPL. For details, see LICENSE file.
     2package org.openstreetmap.josm.plugins.photoadjust;
     3
     4import static org.openstreetmap.josm.tools.I18n.tr;
     5
     6import java.awt.event.ActionEvent;
     7import java.awt.geom.Point2D;
     8import java.util.Collections;
     9import java.util.List;
     10import java.util.Optional;
     11
     12import org.openstreetmap.josm.actions.JosmAction;
     13import org.openstreetmap.josm.data.ImageData;
     14import org.openstreetmap.josm.data.ImageData.ImageDataUpdateListener;
     15import org.openstreetmap.josm.data.coor.LatLon;
     16import org.openstreetmap.josm.gui.MainApplication;
     17import org.openstreetmap.josm.gui.MapView;
     18import org.openstreetmap.josm.gui.layer.Layer;
     19import org.openstreetmap.josm.gui.layer.LayerManager.LayerAddEvent;
     20import org.openstreetmap.josm.gui.layer.LayerManager.LayerChangeListener;
     21import org.openstreetmap.josm.gui.layer.LayerManager.LayerOrderChangeEvent;
     22import org.openstreetmap.josm.gui.layer.LayerManager.LayerRemoveEvent;
     23import org.openstreetmap.josm.gui.layer.geoimage.GeoImageLayer;
     24import org.openstreetmap.josm.gui.layer.geoimage.ImageEntry;
     25
     26/**
     27 * Interpolate a part of a geotagged sequence
     28 */
     29public class InterpolateImages extends JosmAction implements LayerChangeListener, ImageDataUpdateListener {
     30
     31    public InterpolateImages() {
     32        super(tr("Interpolate position between the 2 images"),
     33                null,
     34                tr("Interpolate images position between the 2 selected images"),
     35                null, false, false);
     36
     37        installAdapters();
     38        updateEnabledState();
     39    }
     40
     41    @Override
     42    public void actionPerformed(ActionEvent evt) {
     43        if (!getLayerWithTwoSelectedImages().isPresent()) {
     44            return;
     45        }
     46        GeoImageLayer layer = getLayerWithTwoSelectedImages().get();
     47        ImageData data = layer.getImageData();
     48
     49        interpolate(data, MainApplication.getMap().mapView);
     50    }
     51
     52    public void interpolate(ImageData data, MapView mapView) {
     53        List<ImageEntry> images = data.getImages();
     54        List<ImageEntry> selectedImages = data.getSelectedImages();
     55        Collections.sort(selectedImages);
     56        ImageEntry firstPhoto = selectedImages.get(0);
     57        ImageEntry lastPhoto = selectedImages.get(1);
     58        final Point2D firstPos = mapView.getPoint2D(firstPhoto.getPos());
     59        final Point2D lastPos = mapView.getPoint2D(lastPhoto.getPos());
     60        int nbSegments = images.indexOf(lastPhoto) - images.indexOf(firstPhoto);
     61        double firstPosX = firstPos.getX();
     62        double firstPosY = firstPos.getY();
     63        double offsetX = (lastPos.getX() - firstPosX) / nbSegments;
     64        double offsetY = (lastPos.getY() - firstPosY) / nbSegments;
     65        int firstIndex = images.indexOf(firstPhoto);
     66        for (int idx = 1; idx < nbSegments; idx++) {
     67            ImageEntry image = images.get(firstIndex + idx);
     68            LatLon newPos = mapView.getLatLon(
     69                        firstPosX + offsetX * idx,
     70                    firstPosY + offsetY * idx
     71                    );
     72            image.setPos(newPos);
     73            image.flagNewGpsData();
     74        }
     75        data.notifyImageUpdate();
     76    }
     77
     78    @Override
     79    protected void installAdapters() {
     80        MainApplication.getLayerManager().addLayerChangeListener(this);
     81    }
     82
     83    @Override
     84    protected void updateEnabledState() {
     85        setEnabled(getLayerWithTwoSelectedImages().isPresent());
     86    }
     87
     88    private static Optional<GeoImageLayer> getLayerWithTwoSelectedImages() {
     89        List<GeoImageLayer> list = MainApplication.getLayerManager().getLayersOfType(GeoImageLayer.class);
     90        return list.stream().filter(l -> l.getImageData().getSelectedImages().size() == 2).findFirst();
     91    }
     92
     93    @Override
     94    public void layerAdded(LayerAddEvent evt) {
     95        Layer layer = evt.getAddedLayer();
     96        if (layer instanceof GeoImageLayer) {
     97            ((GeoImageLayer) layer).getImageData().addImageDataUpdateListener(this);
     98        }
     99    }
     100
     101    @Override
     102    public void layerRemoving(LayerRemoveEvent evt) {
     103        Layer layer = evt.getRemovedLayer();
     104
     105        if (layer instanceof GeoImageLayer) {
     106            ((GeoImageLayer) layer).getImageData().removeImageDataUpdateListener(this);
     107        }
     108        updateEnabledState();
     109    }
     110
     111    @Override
     112    public void layerOrderChanged(LayerOrderChangeEvent evt) {}
     113
     114    @Override
     115    public void imageDataUpdated(ImageData data) {}
     116
     117    @Override
     118    public void selectedImageChanged(ImageData data) {
     119        updateEnabledState();
     120    }
     121}
  • plugins/photoadjust/src/org/openstreetmap/josm/plugins/photoadjust/PhotoAdjustPlugin.java

     
    88import java.util.List;
    99
    1010import org.openstreetmap.josm.gui.MainApplication;
     11import org.openstreetmap.josm.gui.MainMenu;
    1112import org.openstreetmap.josm.gui.MapFrame;
    1213import org.openstreetmap.josm.gui.layer.Layer;
    1314import org.openstreetmap.josm.gui.layer.MainLayerManager.ActiveLayerChangeEvent;
     
    3738        super(info);
    3839        GeoImageLayer.registerMenuAddition(new UntaggedGeoImageLayerAction());
    3940        PhotoPropertyEditor.init();
     41        MainMenu menu = MainApplication.getMenu();
     42        MainMenu.add(menu.toolsMenu, new InterpolateImages());
    4043        initAdapters();
    4144    }
    4245
  • plugins/photoadjust/test/unit/org/openstreetmap/josm/plugins/photoadjust/InterpolateImagesTest.java

     
     1package org.openstreetmap.josm.plugins.photoadjust;
     2
     3import java.awt.geom.Point2D;
     4import java.io.File;
     5import java.util.ArrayList;
     6
     7import org.junit.Test;
     8import org.openstreetmap.josm.data.ImageData;
     9import org.openstreetmap.josm.data.coor.CachedLatLon;
     10import org.openstreetmap.josm.data.coor.LatLon;
     11import org.openstreetmap.josm.gui.MapView;
     12import org.openstreetmap.josm.gui.layer.geoimage.ImageEntry;
     13
     14import mockit.Delegate;
     15import mockit.Expectations;
     16import mockit.Mocked;
     17
     18public class InterpolateImagesTest {
     19
     20    @Test
     21    public void testInterpolate(@Mocked(stubOutClassInitialization=true) MapView view) {
     22        InterpolateImages interpolate = new InterpolateImages();
     23        ArrayList<ImageEntry> list = new ArrayList<>();
     24        ImageEntry first = new ImageEntry(new File("test1"));
     25        ImageEntry last = new ImageEntry(new File("test3"));
     26        ImageEntry middle = new ImageEntry(new File("test2"));
     27        list.add(first);
     28        list.add(middle);
     29        list.add(last);
     30
     31        ImageData data = new ImageData(list);
     32        new Expectations(first) {{
     33            first.getPos(); result = new CachedLatLon(0, 0);
     34        }};
     35        new Expectations(last) {{
     36            last.getPos(); result = new CachedLatLon(1, 1);
     37        }};
     38        new Expectations(middle) {{
     39            middle.setPos(new LatLon(0, 0));
     40            middle.flagNewGpsData();
     41        }};
     42        new Expectations(view) {{
     43            view.getPoint2D((LatLon) any); result = new Delegate() {
     44                Point2D aDelegateMethod(LatLon pos) {
     45                    return pos.getX() == 0 ? new Point2D.Double(0, 0) : new Point2D.Double(10, 5);
     46                }
     47            };
     48            view.getLatLon(5.0, 2.5); result = new LatLon(0, 0);
     49        }};
     50        new Expectations(data) {{
     51            data.notifyImageUpdate();
     52        }};
     53
     54        data.addImageToSelection(first);
     55        data.addImageToSelection(last);
     56        interpolate.interpolate(data, view);
     57    }
     58
     59}