Ticket #16472: 16472.2.patch

File 16472.2.patch, 11.2 KB (added by taylor.smock, 5 years ago)

WIP: DO NOT APPLY -- this code applies to attachment:16472.patch, and is an attempt to figure out where azimuth/polar angles are being flipped

  • src/org/openstreetmap/josm/gui/layer/geoimage/ImageDisplay.java

    diff --git a/src/org/openstreetmap/josm/gui/layer/geoimage/ImageDisplay.java b/src/org/openstreetmap/josm/gui/layer/geoimage/ImageDisplay.java
    index f8fab1e1c6..daac93f6cd 100644
    a b public class ImageDisplay extends JComponent implements Destroyable, PreferenceC  
    260260        @Override
    261261        public void run() {
    262262            try {
    263                 Dimension target = new Dimension(MAX_WIDTH.get(), MAX_WIDTH.get());
     263                Dimension target = new Dimension(4 * MAX_WIDTH.get(), 4 * MAX_WIDTH.get());
    264264                BufferedImage img = entry.read(target);
    265265                if (img == null) {
    266266                    synchronized (ImageDisplay.this) {
  • src/org/openstreetmap/josm/gui/layer/geoimage/viewers/projections/Equirectangular.java

    diff --git a/src/org/openstreetmap/josm/gui/layer/geoimage/viewers/projections/Equirectangular.java b/src/org/openstreetmap/josm/gui/layer/geoimage/viewers/projections/Equirectangular.java
    index a85acbcc88..643d401cec 100644
    a b import java.util.Set;  
    1414
    1515import org.openstreetmap.josm.data.imagery.street_level.Projections;
    1616import org.openstreetmap.josm.gui.layer.geoimage.ImageDisplay;
    17 import org.openstreetmap.josm.gui.util.GuiHelper;
    1817import org.openstreetmap.josm.gui.util.imagery.CameraPlane;
    1918import org.openstreetmap.josm.gui.util.imagery.Vector3D;
     19import org.openstreetmap.josm.tools.Logging;
    2020
    2121/**
    2222 * A class for showing 360 images that use the equirectangular projection
    public class Equirectangular extends ComponentAdapter implements IImageViewer {  
    3434
    3535    @Override
    3636    public void paintImage(Graphics g, BufferedImage image, Rectangle target, Rectangle visibleRect) {
    37         this.cameraPlane.mapping(image, this.offscreenImage);
     37        final CameraPlane currentCameraPlane;
     38        final BufferedImage currentOffscreenImage;
     39        synchronized (this) {
     40            currentCameraPlane = this.cameraPlane;
     41            currentOffscreenImage = this.offscreenImage;
     42        }
     43        currentCameraPlane.mapping(image, currentOffscreenImage);
    3844        if (target == null) {
    39             target = new Rectangle(0, 0, offscreenImage.getWidth(null), offscreenImage.getHeight(null));
     45            target = new Rectangle(0, 0, currentOffscreenImage.getWidth(null), currentOffscreenImage.getHeight(null));
    4046        }
    41         g.drawImage(offscreenImage, target.x, target.y, target.x + target.width, target.y + target.height,
     47        g.drawImage(currentOffscreenImage, target.x, target.y, target.x + target.width, target.y + target.height,
    4248                visibleRect.x, visibleRect.y, visibleRect.x + visibleRect.width, visibleRect.y + visibleRect.height,
    4349                null);
    4450    }
    public class Equirectangular extends ComponentAdapter implements IImageViewer {  
    6167            final ImageDisplay imgDisplay = (ImageDisplay) component;
    6268            // FIXME: Do something so that the types of the images are the same between the offscreenImage and
    6369            // the image entry
    64             this.offscreenImage = new BufferedImage(imgDisplay.getWidth(), imgDisplay.getHeight(),
     70            final CameraPlane currentCameraPlane;
     71            synchronized (this) {
     72                currentCameraPlane = this.cameraPlane;
     73            }
     74            final BufferedImage temporaryOffscreenImage = new BufferedImage(imgDisplay.getWidth(), imgDisplay.getHeight(),
    6575                    BufferedImage.TYPE_3BYTE_BGR);
     76
    6677            Vector3D currentRotation = null;
    67             if (this.cameraPlane != null) {
    68                 currentRotation = this.cameraPlane.getRotation();
     78            if (currentCameraPlane != null) {
     79                currentRotation = currentCameraPlane.getRotation();
     80                Logging.error(currentRotation.toString());
    6981            }
    70             this.cameraPlane = new CameraPlane(imgDisplay.getWidth(), imgDisplay.getHeight());
     82            final CameraPlane temporaryCameraPlane = new CameraPlane(imgDisplay.getWidth(), imgDisplay.getHeight());
    7183            if (currentRotation != null) {
    72                 this.cameraPlane.setRotation(currentRotation);
     84                temporaryCameraPlane.setRotation(currentRotation);
     85            }
     86            synchronized (this) {
     87                this.cameraPlane = temporaryCameraPlane;
     88                this.offscreenImage = temporaryOffscreenImage;
    7389            }
    74             GuiHelper.runInEDT(imgDisplay::invalidate);
     90            //GuiHelper.runInEDT(imgDisplay::revalidate);
    7591        }
    7692    }
    7793
  • src/org/openstreetmap/josm/gui/util/imagery/CameraPlane.java

    diff --git a/src/org/openstreetmap/josm/gui/util/imagery/CameraPlane.java b/src/org/openstreetmap/josm/gui/util/imagery/CameraPlane.java
    index 1a4b491a0d..e63c0526d1 100644
    a b import java.awt.image.DataBufferInt;  
    1010import java.util.stream.IntStream;
    1111import javax.annotation.Nullable;
    1212
    13 import org.openstreetmap.josm.tools.Logging;
    14 
    1513/**
    1614 * The plane that the camera appears on and rotates around.
    1715 */
    public class CameraPlane {  
    155153     * @param to The new point
    156154     */
    157155    public void setRotationFromDelta(final Point from, final Point to) {
    158         try {
    159             Vector3D f1 = vectors[from.x][from.y];
    160             Vector3D t1 = vectors[to.x][to.y];
    161             double deltaPolarAngle = f1.getPolarAngle() - t1.getPolarAngle();
    162             double deltaAzimuthalAngle = t1.getAzimuthalAngle() - f1.getAzimuthalAngle();
    163             double polarAngle = this.rotation.getPolarAngle() + deltaPolarAngle;
    164             double azimuthalAngle = this.rotation.getAzimuthalAngle() + deltaAzimuthalAngle;
    165             this.setRotation(azimuthalAngle, polarAngle);
    166         } catch (ArrayIndexOutOfBoundsException e) {
    167             Logging.error(e);
     156        // Bound check (bounds are essentially the image viewer component)
     157        if (from.x < 0 || from.y < 0 || to.x < 0 || to.y < 0
     158            || from.x > this.vectors.length || from.y > this.vectors[0].length
     159            || to.x > this.vectors.length || to.y > this.vectors[0].length) {
     160            return;
    168161        }
     162        Vector3D f1 = this.vectors[from.x][from.y];
     163        Vector3D t1 = this.vectors[to.x][to.y];
     164        double deltaPolarAngle = f1.getPolarAngle() - t1.getPolarAngle();
     165        double deltaAzimuthalAngle = t1.getAzimuthalAngle() - f1.getAzimuthalAngle();
     166        double polarAngle = this.rotation.getPolarAngle() + deltaPolarAngle;
     167        double azimuthalAngle = this.rotation.getAzimuthalAngle() + deltaAzimuthalAngle;
     168        this.setRotation(azimuthalAngle, polarAngle);
    169169    }
    170170
    171171    /**
    public class CameraPlane {  
    183183
    184184    synchronized void setRotation(double azimuthalAngle, double polarAngle) {
    185185        // Note: Something, somewhere, is switching the two.
    186         // So the bounds are flipped. FIXME sometime
     186        // FIXME: Figure out what is switching them and why
    187187        // Prevent us from going much outside 2pi
    188188        if (polarAngle < 0) {
    189189            polarAngle = polarAngle + TWO_PI;
    public class CameraPlane {  
    203203        return rotate(vec, 1);
    204204    }
    205205
     206    /**
     207     * Rotate a vector using the current rotation
     208     * @param vec The vector to rotate
     209     * @param rotationFactor Used to determine if using left hand rule or right hand rule (1 for RHR)
     210     * @return A rotated vector
     211     */
    206212    private Vector3D rotate(final Vector3D vec, final int rotationFactor) {
    207         double vecX, vecY, vecZ;
    208         // Rotate around z axis first
    209         vecZ = vec.getZ() * this.rotation.getAzimuthalAngleCos() - vec.getY() * this.rotation.getAzimuthalAngleSin();
    210         vecY = vec.getZ() * this.rotation.getAzimuthalAngleSin() + vec.getY() * this.rotation.getAzimuthalAngleCos();
    211         vecX = vecZ * this.rotation.getPolarAngleSin() * rotationFactor + vec.getX() * this.rotation.getPolarAngleCos();
    212         vecZ = vecZ * this.rotation.getPolarAngleCos() - vec.getX() * this.rotation.getPolarAngleSin() * rotationFactor;
     213        // @formatting:off
     214        /* Full rotation matrix for a yaw-pitch-roll
     215         * yaw = alpha, pitch = beta, roll = gamma (typical representations)
     216         * [cos(alpha), -sin(alpha), 0 ]   [cos(beta), 0, sin(beta) ]   [1,     0     ,     0      ]   [x]   [x1]
     217         * |sin(alpha), cos(alpha), 0  | . |0        , 1, 0         | . |0, cos(gamma), -sin(gamma)| . |y| = |y1|
     218         * [0         ,       0    , 1 ]   [-sin(beta), 0, cos(beta)]   [0, sin(gamma), cos(gamma) ]   [z]   [z1]
     219         * which becomes
     220         * x1 = y(cos(alpha)sin(beta)sin(gamma) - sin(alpha)cos(gamma)) + z(cos(alpha)sin(beta)cos(gamma) + sin(alpha)sin(gamma)) + x cos(alpha)cos(beta)
     221         * y1 = y(sin(alpha)sin(beta)sin(gamma) + cos(alpha)cos(gamma)) + z(sin(alpha)sin(beta)cos(gamma) - cos(alpha)sin(gamma)) + x sin(alpha)cos(beta)
     222         * z1 = y cos(beta)sin(gamma) + z cos(beta)cos(gamma) - x sin(beta)
     223         */
     224        // @formatting:on
     225        double vecX;
     226        double vecY;
     227        double vecZ;
     228        // We only do pitch/roll (we specifically do not do roll -- this would lead to tilting the image)
     229        // So yaw (alpha) -> azimuthalAngle, pitch (beta) -> polarAngle, roll (gamma) -> 0 (sin(gamma) -> 0, cos(gamma) -> 1)
     230        if (true) {
     231            // gamma is set here just to make it slightly easier to tilt images in the future -- we just have to set the gamma somewhere else.
     232            final int gamma = 0;
     233            final double sinGamma = Math.sin(gamma);
     234            final double cosGamma = Math.cos(gamma);
     235            final double cosAlpha = this.rotation.getAzimuthalAngleCos();
     236            final double sinAlpha = this.rotation.getAzimuthalAngleSin();
     237            final double cosBeta = this.rotation.getPolarAngleCos();
     238            final double sinBeta = this.rotation.getPolarAngleSin();
     239            final double x = vec.getX();
     240            final double y = vec.getY();
     241            final double z = vec.getZ();
     242            vecX = y * (cosAlpha * sinBeta * sinGamma - sinAlpha * cosGamma)
     243                    + z * (cosAlpha * sinBeta * cosGamma + sinAlpha * sinGamma) + x * cosAlpha * cosBeta;
     244            vecY = y * (sinAlpha * sinBeta * sinGamma + cosAlpha * cosGamma)
     245                    + z * (sinAlpha * sinBeta * cosGamma - cosAlpha * sinGamma) + x * sinAlpha * cosBeta;
     246            vecZ = y * cosBeta * sinGamma + z * cosBeta * cosGamma - x * sinBeta;
     247        } else {
     248            // This is the original Mapillary code
     249            // Rotate around z axis first
     250            vecZ = vec.getZ() * this.rotation.getAzimuthalAngleCos() - vec.getY() * this.rotation.getAzimuthalAngleSin();
     251            vecY = vec.getZ() * this.rotation.getAzimuthalAngleSin() + vec.getY() * this.rotation.getAzimuthalAngleCos();
     252            vecX = vecZ * this.rotation.getPolarAngleSin() * rotationFactor + vec.getX() * this.rotation.getPolarAngleCos();
     253            vecZ = vecZ * this.rotation.getPolarAngleCos() - vec.getX() * this.rotation.getPolarAngleSin() * rotationFactor;
     254        }
    213255        return new Vector3D(vecX, vecY, vecZ);
    214256    }
    215257