Ticket #16472: 16472.2.patch
| File 16472.2.patch, 11.2 KB (added by , 5 years ago) |
|---|
-
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 260 260 @Override 261 261 public void run() { 262 262 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()); 264 264 BufferedImage img = entry.read(target); 265 265 if (img == null) { 266 266 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; 14 14 15 15 import org.openstreetmap.josm.data.imagery.street_level.Projections; 16 16 import org.openstreetmap.josm.gui.layer.geoimage.ImageDisplay; 17 import org.openstreetmap.josm.gui.util.GuiHelper;18 17 import org.openstreetmap.josm.gui.util.imagery.CameraPlane; 19 18 import org.openstreetmap.josm.gui.util.imagery.Vector3D; 19 import org.openstreetmap.josm.tools.Logging; 20 20 21 21 /** 22 22 * A class for showing 360 images that use the equirectangular projection … … public class Equirectangular extends ComponentAdapter implements IImageViewer { 34 34 35 35 @Override 36 36 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); 38 44 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)); 40 46 } 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, 42 48 visibleRect.x, visibleRect.y, visibleRect.x + visibleRect.width, visibleRect.y + visibleRect.height, 43 49 null); 44 50 } … … public class Equirectangular extends ComponentAdapter implements IImageViewer { 61 67 final ImageDisplay imgDisplay = (ImageDisplay) component; 62 68 // FIXME: Do something so that the types of the images are the same between the offscreenImage and 63 69 // 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(), 65 75 BufferedImage.TYPE_3BYTE_BGR); 76 66 77 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()); 69 81 } 70 this.cameraPlane = new CameraPlane(imgDisplay.getWidth(), imgDisplay.getHeight());82 final CameraPlane temporaryCameraPlane = new CameraPlane(imgDisplay.getWidth(), imgDisplay.getHeight()); 71 83 if (currentRotation != null) { 72 this.cameraPlane.setRotation(currentRotation); 84 temporaryCameraPlane.setRotation(currentRotation); 85 } 86 synchronized (this) { 87 this.cameraPlane = temporaryCameraPlane; 88 this.offscreenImage = temporaryOffscreenImage; 73 89 } 74 GuiHelper.runInEDT(imgDisplay::invalidate);90 //GuiHelper.runInEDT(imgDisplay::revalidate); 75 91 } 76 92 } 77 93 -
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; 10 10 import java.util.stream.IntStream; 11 11 import javax.annotation.Nullable; 12 12 13 import org.openstreetmap.josm.tools.Logging;14 15 13 /** 16 14 * The plane that the camera appears on and rotates around. 17 15 */ … … public class CameraPlane { 155 153 * @param to The new point 156 154 */ 157 155 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; 168 161 } 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); 169 169 } 170 170 171 171 /** … … public class CameraPlane { 183 183 184 184 synchronized void setRotation(double azimuthalAngle, double polarAngle) { 185 185 // Note: Something, somewhere, is switching the two. 186 // So the bounds are flipped. FIXME sometime186 // FIXME: Figure out what is switching them and why 187 187 // Prevent us from going much outside 2pi 188 188 if (polarAngle < 0) { 189 189 polarAngle = polarAngle + TWO_PI; … … public class CameraPlane { 203 203 return rotate(vec, 1); 204 204 } 205 205 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 */ 206 212 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 } 213 255 return new Vector3D(vecX, vecY, vecZ); 214 256 } 215 257
