Ticket #16472: 16472.5.patch
| File 16472.5.patch, 28.0 KB (added by , 5 years ago) |
|---|
-
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 72da2a3a31..5078cb35d6 100644
a b package org.openstreetmap.josm.gui.util.imagery; 4 4 import java.awt.Point; 5 5 import java.awt.geom.Point2D; 6 6 import java.awt.image.BufferedImage; 7 import java.awt.image.DataBuffer;8 import java.awt.image.DataBufferDouble;9 import java.awt.image.DataBufferInt;10 7 import java.util.stream.IntStream; 8 11 9 import javax.annotation.Nullable; 12 10 13 11 /** … … public class CameraPlane { 54 52 this.rotation = new Vector3D(Vector3D.VectorType.RPA, distance, 0, 0); 55 53 this.vectors = new Vector3D[width][height]; 56 54 IntStream.range(0, this.height).parallel().forEach(y -> IntStream.range(0, this.width).parallel() 57 .forEach(x -> this.vectors[x][y] = this.get Vector3D((double) x, y)));55 .forEach(x -> this.vectors[x][y] = this.getNonRotatedVector3D((double) x, y))); 58 56 } 59 57 60 58 /** … … public class CameraPlane { 114 112 } 115 113 116 114 /** 117 * Convert a point to a 3D vector (vectors are cached)115 * Convert a point to a 3D vector (vectors in image are cached) 118 116 * 119 117 * @param x The x coordinate 120 118 * @param y The y coordinate 121 119 * @return The vector 122 120 */ 123 121 public Vector3D getVector3D(final int x, final int y) { 124 Vector3D res; 125 try { 126 res = rotate(vectors[x][y]); 127 } catch (Exception e) { 128 res = Vector3D.DEFAULT_VECTOR_3D; 129 } 130 return res; 122 return this.rotate(this.getNonRotatedVector3D(x, y)); 131 123 } 132 124 133 125 /** … … public class CameraPlane { 138 130 * @return The vector (the middle of the image is 0, 0) 139 131 */ 140 132 public Vector3D getVector3D(final double x, final double y) { 133 return this.rotate(this.getNonRotatedVector3D(x, y)); 134 } 135 136 private Vector3D getNonRotatedVector3D(final int x, final int y) { 137 // Prefer cached vectors 138 if (x >= 0 && y >= 0 && x < this.vectors.length && y < this.vectors[0].length) { 139 return this.vectors[x][y]; 140 } 141 142 return this.getNonRotatedVector3D(x, (double) y); 143 } 144 145 private Vector3D getNonRotatedVector3D(final double x, final double y) { 141 146 return new Vector3D(x - width / 2d, y - height / 2d, this.rotation.getRadialDistance()).normalize(); 142 147 } 143 148 … … public class CameraPlane { 151 156 } 152 157 153 158 /** 154 * Set the rotation from the difference of two points 159 * Set the rotation from the difference of two points on the original plane 155 160 * 156 * @param from The originating point157 * @param to The new point161 * @param fromPoint The originating point 162 * @param toPoint The new point 158 163 */ 159 public void setRotationFromDelta(final Point from, final Point to) { 160 // Bound check (bounds are essentially the image viewer component) 161 if (from.x < 0 || from.y < 0 || to.x < 0 || to.y < 0 162 || from.x > this.vectors.length || from.y > this.vectors[0].length 163 || to.x > this.vectors.length || to.y > this.vectors[0].length) { 164 return; 165 } 166 Vector3D f1 = this.vectors[from.x][from.y]; 167 Vector3D t1 = this.vectors[to.x][to.y]; 168 double deltaPolarAngle = f1.getPolarAngle() - t1.getPolarAngle(); 169 double deltaAzimuthalAngle = t1.getAzimuthalAngle() - f1.getAzimuthalAngle(); 170 double polarAngle = this.rotation.getPolarAngle() + deltaPolarAngle; 171 double azimuthalAngle = this.rotation.getAzimuthalAngle() + deltaAzimuthalAngle; 164 public void setRotationFromDelta(final Point fromPoint, final Point toPoint) { 165 final Vector3D from = this.getVector3D(fromPoint.x, fromPoint.y); 166 final Vector3D to = this.getVector3D(toPoint.x, toPoint.y); 167 final double deltaPolarAngle = from.getPolarAngle() - to.getPolarAngle(); 168 final double deltaAzimuthalAngle = to.getAzimuthalAngle() - from.getAzimuthalAngle(); 169 final double polarAngle = this.rotation.getPolarAngle() + deltaPolarAngle; 170 final double azimuthalAngle = this.rotation.getAzimuthalAngle() + deltaAzimuthalAngle; 172 171 this.setRotation(azimuthalAngle, polarAngle); 173 172 } 174 173 … … public class CameraPlane { 178 177 * @param vec vector pointing new view position. 179 178 */ 180 179 public void setRotation(Vector3D vec) { 181 setRotation(vec.get PolarAngle(), vec.getAzimuthalAngle());180 setRotation(vec.getAzimuthalAngle(), vec.getPolarAngle()); 182 181 } 183 182 184 183 public Vector3D getRotation() { … … public class CameraPlane { 189 188 // Note: Something, somewhere, is switching the two. 190 189 // FIXME: Figure out what is switching them and why 191 190 // Prevent us from going much outside 2pi 192 if ( polarAngle < 0) {193 polarAngle = polarAngle + TWO_PI;194 } else if ( polarAngle > TWO_PI) {195 polarAngle = polarAngle - TWO_PI;191 if (azimuthalAngle < 0) { 192 azimuthalAngle = azimuthalAngle + TWO_PI; 193 } else if (azimuthalAngle > TWO_PI) { 194 azimuthalAngle = azimuthalAngle - TWO_PI; 196 195 } 197 196 // Avoid flipping the camera 198 if ( azimuthalAngle > HALF_PI) {199 azimuthalAngle = HALF_PI;200 } else if ( azimuthalAngle < -HALF_PI) {201 azimuthalAngle = -HALF_PI;197 if (polarAngle > HALF_PI) { 198 polarAngle = HALF_PI; 199 } else if (polarAngle < -HALF_PI) { 200 polarAngle = -HALF_PI; 202 201 } 203 202 this.rotation = new Vector3D(Vector3D.VectorType.RPA, this.rotation.getRadialDistance(), polarAngle, azimuthalAngle); 204 203 } … … public class CameraPlane { 229 228 // We only do pitch/roll (we specifically do not do roll -- this would lead to tilting the image) 230 229 // So yaw (alpha) -> azimuthalAngle, pitch (beta) -> polarAngle, roll (gamma) -> 0 (sin(gamma) -> 0, cos(gamma) -> 1) 231 230 // 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 // Ironically enough, the alpha (yaw) and gama (roll) got reversed somewhere. TODO figure out where and fix this. 231 // Ironically enough, the alpha (yaw) and gama (roll) got reversed somewhere. TODO figure out where and fix it. 232 // z == roll axis 233 // x == pitch axis 234 // y == yaw axis 233 235 final int gamma = 0; 234 final double sin Alpha = Math.sin(gamma);235 final double cos Alpha = Math.cos(gamma);236 final double cos Gamma = this.rotation.getAzimuthalAngleCos();237 final double sin Gamma = this.rotation.getAzimuthalAngleSin();238 final double cos Beta = this.rotation.getPolarAngleCos();239 final double sin Beta = this.rotation.getPolarAngleSin();236 final double sinGamma = Math.sin(gamma); 237 final double cosGamma = Math.cos(gamma); 238 final double cosBeta = this.rotation.getAzimuthalAngleCos(); 239 final double sinBeta = this.rotation.getAzimuthalAngleSin(); 240 final double cosAlpha = this.rotation.getPolarAngleCos(); 241 final double sinAlpha = this.rotation.getPolarAngleSin(); 240 242 final double x = vec.getX(); 241 243 final double y = YAW_DIRECTION * vec.getY(); 242 244 final double z = vec.getZ(); … … public class CameraPlane { 249 251 } 250 252 251 253 public void mapping(BufferedImage sourceImage, BufferedImage targetImage) { 252 DataBuffer sourceBuffer = sourceImage.getRaster().getDataBuffer(); 253 DataBuffer targetBuffer = targetImage.getRaster().getDataBuffer(); 254 // Faster mapping 255 if (sourceBuffer.getDataType() == DataBuffer.TYPE_INT && targetBuffer.getDataType() == DataBuffer.TYPE_INT) { 256 int[] sourceImageBuffer = ((DataBufferInt) sourceImage.getRaster().getDataBuffer()).getData(); 257 int[] targetImageBuffer = ((DataBufferInt) targetImage.getRaster().getDataBuffer()).getData(); 258 IntStream.range(0, targetImage.getHeight()).parallel() 259 .forEach(y -> IntStream.range(0, targetImage.getWidth()).forEach(x -> { 260 final Point2D.Double p = mapPoint(x, y); 261 int tx = (int) (p.x * (sourceImage.getWidth() - 1)); 262 int ty = (int) (p.y * (sourceImage.getHeight() - 1)); 263 int color = sourceImageBuffer[ty * sourceImage.getWidth() + tx]; 264 targetImageBuffer[y * targetImage.getWidth() + x] = color; 265 })); 266 } else if (sourceBuffer.getDataType() == DataBuffer.TYPE_DOUBLE && targetBuffer.getDataType() == DataBuffer.TYPE_DOUBLE) { 267 double[] sourceImageBuffer = ((DataBufferDouble) sourceImage.getRaster().getDataBuffer()).getData(); 268 double[] targetImageBuffer = ((DataBufferDouble) targetImage.getRaster().getDataBuffer()).getData(); 269 IntStream.range(0, targetImage.getHeight()).parallel() 270 .forEach(y -> IntStream.range(0, targetImage.getWidth()).forEach(x -> { 271 final Point2D.Double p = mapPoint(x, y); 272 int tx = (int) (p.x * (sourceImage.getWidth() - 1)); 273 int ty = (int) (p.y * (sourceImage.getHeight() - 1)); 274 double color = sourceImageBuffer[ty * sourceImage.getWidth() + tx]; 275 targetImageBuffer[y * targetImage.getWidth() + x] = color; 276 })); 277 } else { 278 IntStream.range(0, targetImage.getHeight()).parallel() 279 .forEach(y -> IntStream.range(0, targetImage.getWidth()).parallel().forEach(x -> { 280 final Point2D.Double p = mapPoint(x, y); 281 targetImage.setRGB(x, y, sourceImage.getRGB((int) (p.x * (sourceImage.getWidth() - 1)), 282 (int) (p.y * (sourceImage.getHeight() - 1)))); 283 })); 284 } 254 // There can be slightly faster mapping if both data buffers are the same time (image.getRaster().getDataBuffer()) 255 IntStream.range(0, targetImage.getHeight()).parallel() 256 .forEach(y -> IntStream.range(0, targetImage.getWidth()).parallel().forEach(x -> { 257 final Point2D.Double p = mapPoint(x, y); 258 targetImage.setRGB(x, y, sourceImage.getRGB((int) (p.x * (sourceImage.getWidth() - 1)), 259 (int) (p.y * (sourceImage.getHeight() - 1)))); 260 })); 285 261 } 286 262 287 263 /** 288 * Map a real point to the displayed point. This method usescached vectors.264 * Map a real point to the displayed point. This method may use cached vectors. 289 265 * @param x The original x coordinate 290 266 * @param y The original y coordinate 291 267 * @return The scaled (0-1) point in the image. Use {@code p.x * (image.getWidth() - 1)} or {@code p.y * image.getHeight() - 1}. -
src/org/openstreetmap/josm/gui/util/imagery/Vector3D.java
diff --git a/src/org/openstreetmap/josm/gui/util/imagery/Vector3D.java b/src/org/openstreetmap/josm/gui/util/imagery/Vector3D.java index ba98b7d884..2052e351a2 100644
a b public final class Vector3D { 30 30 private final double z; 31 31 /* The following are all lazily calculated, but should always be the same */ 32 32 /** The radius r */ 33 private volatiledouble radialDistance = Double.NaN;33 private double radialDistance = Double.NaN; 34 34 /** The polar angle theta (inclination) */ 35 private volatiledouble polarAngle = Double.NaN;35 private double polarAngle = Double.NaN; 36 36 /** Cosine of polar angle (angle from Z axis, AKA straight up) */ 37 private volatiledouble polarAngleCos = Double.NaN;37 private double polarAngleCos = Double.NaN; 38 38 /** Sine of polar angle (angle from Z axis, AKA straight up) */ 39 private volatiledouble polarAngleSin = Double.NaN;39 private double polarAngleSin = Double.NaN; 40 40 /** The azimuthal angle phi */ 41 private volatiledouble azimuthalAngle = Double.NaN;41 private double azimuthalAngle = Double.NaN; 42 42 /** Cosine of azimuthal angle (angle from X axis) */ 43 private volatiledouble azimuthalAngleCos = Double.NaN;43 private double azimuthalAngleCos = Double.NaN; 44 44 /** Sine of azimuthal angle (angle from X axis) */ 45 private volatiledouble azimuthalAngleSin = Double.NaN;45 private double azimuthalAngleSin = Double.NaN; 46 46 47 47 /** 48 48 * Create a new Vector3D object using the XYZ coordinate system … … public final class Vector3D { 130 130 */ 131 131 public double getPolarAngle() { 132 132 if (Double.isNaN(this.polarAngle)) { 133 // This was Math.atan(x, z) in the Mapillary plugin 134 // This should be Math.atan(y, z) 135 this.polarAngle = Math.atan2(this.x, this.z); 133 if (Double.isNaN(this.radialDistance)) { 134 // Force calculation 135 this.getRadialDistance(); 136 } 137 // Avoid issues where x, y, and z are 0 138 if (this.radialDistance == 0) { 139 this.polarAngle = 0; 140 } else { 141 // This was Math.acos(y / radialDistance) in the Mapillary plugin 142 // This should be Math.acos(z / radialDistance) 143 this.polarAngle = Math.acos(this.z / this.radialDistance); 144 } 136 145 } 137 146 return this.polarAngle; 138 147 } … … public final class Vector3D { 168 177 */ 169 178 public double getAzimuthalAngle() { 170 179 if (Double.isNaN(this.azimuthalAngle)) { 171 if (Double.isNaN(this.radialDistance)) { 172 // Force calculation 173 this.getRadialDistance(); 174 } 175 // Avoid issues where x, y, and z are 0 176 if (this.radialDistance == 0) { 177 this.azimuthalAngle = 0; 178 } else { 179 // This was Math.acos(y / radialDistance) in the Mapillary plugin 180 // This should be Math.acos(z / radialDistance) 181 this.azimuthalAngle = Math.acos(this.y / this.radialDistance); 182 } 180 // This was Math.atan(x, z) in the Mapillary plugin 181 // This should be Math.atan(y, z) 182 this.azimuthalAngle = Math.atan2(this.y, this.z); 183 183 } 184 184 return this.azimuthalAngle; 185 185 } … … public final class Vector3D { 239 239 public boolean equals(Object o) { 240 240 if (o instanceof Vector3D) { 241 241 Vector3D other = (Vector3D) o; 242 return this.x == other.x && this.y == other.y && this.z == other.z; 242 return Double.compare(this.x, other.x) == 0 243 && Double.compare(this.y, other.y) == 0 244 && Double.compare(this.z, other.z) == 0; 243 245 } 244 246 return false; 245 247 } 246 248 247 249 @Override 248 250 public String toString() { 251 // Initialize the various ephemeral objects 252 this.getRadialDistance(); 253 this.getAzimuthalAngle(); 254 this.getPolarAngle(); 249 255 return "[x=" + this.x + ", y=" + this.y + ", z=" + this.z + ", r=" + this.radialDistance + ", inclination=" 250 256 + this.polarAngle + ", azimuthal=" + this.azimuthalAngle + "]"; 251 257 } -
test/unit/org/openstreetmap/josm/gui/util/imagery/CameraPlaneTest.java
diff --git a/test/unit/org/openstreetmap/josm/gui/util/imagery/CameraPlaneTest.java b/test/unit/org/openstreetmap/josm/gui/util/imagery/CameraPlaneTest.java index 03e282a2cc..2868d03d9a 100644
a b import java.awt.geom.Point2D; 9 9 import java.util.stream.Stream; 10 10 11 11 import org.junit.jupiter.api.BeforeEach; 12 import org.junit.jupiter.api.Disabled;13 12 import org.junit.jupiter.api.Test; 14 13 import org.junit.jupiter.params.ParameterizedTest; 15 14 import org.junit.jupiter.params.provider.Arguments; … … class CameraPlaneTest { 20 19 private static final int CAMERA_PLANE_WIDTH = 800; 21 20 private static final int CAMERA_PLANE_HEIGHT = 600; 22 21 22 private static final double MAX_DELTA = 1e-15; 23 23 24 private CameraPlane cameraPlane; 24 25 25 26 @BeforeEach … … class CameraPlaneTest { 28 29 } 29 30 30 31 @Test 31 @Disabled("Currently broken") 32 void testDimensions() { 33 assertAll(() -> assertEquals(CAMERA_PLANE_HEIGHT, this.cameraPlane.getHeight()), 34 () -> assertEquals(CAMERA_PLANE_WIDTH, this.cameraPlane.getWidth())); 35 } 36 37 @Test 32 38 void testSetRotation() { 33 39 Vector3D vec = new Vector3D(0, 0, 1); 34 cameraPlane.setRotation(vec); 35 Vector3D out = cameraPlane.getRotation(); 36 assertAll(() -> assertEquals(280.0830152838839, out.getRadialDistance(), 0.001), 37 () -> assertEquals(0, out.getPolarAngle(), 0.001), () -> assertEquals(0, out.getAzimuthalAngle(), 0.001)); 40 this.cameraPlane.setRotation(vec); 41 Vector3D out = this.cameraPlane.getRotation(); 42 assertAll(() -> assertEquals(280.0830152838839, out.getRadialDistance(), 0.001, "Radial distance"), 43 () -> assertEquals(0, out.getPolarAngle(), 0.001, "Polar angle"), 44 () -> assertEquals(0, out.getAzimuthalAngle(), 0.001, "Azimuth angle")); 45 } 46 47 static Stream<Arguments> testRotationFromDelta() { 48 return Stream.of(Arguments.of(new Point(CAMERA_PLANE_WIDTH - 1, CAMERA_PLANE_HEIGHT / 2), 0, Math.PI), 49 Arguments.of(new Point(0, CAMERA_PLANE_HEIGHT / 2), 0, -Math.PI), 50 Arguments.of(new Point(CAMERA_PLANE_WIDTH / 2, CAMERA_PLANE_HEIGHT - 1), Math.PI / 2, 0), 51 Arguments.of(new Point(CAMERA_PLANE_WIDTH / 2, 0), - Math.PI / 2, 0)); 52 } 53 54 @ParameterizedTest 55 @MethodSource 56 void testRotationFromDelta(final Point to, final double expectedPolarAngle, final double expectedAzimuthalAngle) { 57 final double maxDelta = 1E-15; 58 // Ensure that rotation is set to the default, and it correctly works 59 this.testSetRotation(); 60 final Vector3D initialVector = this.cameraPlane.getRotation(); 61 final Point zero = new Point(CAMERA_PLANE_WIDTH / 2, CAMERA_PLANE_HEIGHT / 2); 62 // This checks that we can correctly rotate to the edge of the image 63 this.cameraPlane.setRotationFromDelta(zero, to); 64 final Vector3D newRotation = this.cameraPlane.getRotation(); 65 assertAll(() -> assertEquals(initialVector.getRadialDistance(), newRotation.getRadialDistance(), "Radial distance should not change"), 66 () -> assertEquals(expectedPolarAngle, newRotation.getPolarAngle(), maxDelta, "Pitch"), 67 () -> assertEquals(expectedAzimuthalAngle, newRotation.getAzimuthalAngle(), maxDelta, "Yaw")); 68 } 69 70 static Stream<Arguments> testMapPoint() { 71 return Stream.of(Arguments.of(new Point2D.Double(0.5, 0.5), new Point2D.Double(CAMERA_PLANE_WIDTH / 2d, CAMERA_PLANE_HEIGHT / 2d), new Vector3D(0, 0, 1)), 72 Arguments.of(new Point2D.Double(0.3472222222222222, 0.5), new Point2D.Double(0, CAMERA_PLANE_HEIGHT / 2d), new Vector3D(0, 0, 1)), 73 Arguments.of(new Point2D.Double(0.6525905178237755, 0.5), new Point2D.Double(CAMERA_PLANE_WIDTH - 1, CAMERA_PLANE_HEIGHT / 2d), new Vector3D(0, 0, 1)), 74 Arguments.of(new Point2D.Double(0.5, 0.7603945765026368), new Point2D.Double(CAMERA_PLANE_WIDTH / 2d, CAMERA_PLANE_HEIGHT - 1), new Vector3D(0, 0, 1)), 75 Arguments.of(new Point2D.Double(0.5, 0.239075212564189), new Point2D.Double(CAMERA_PLANE_WIDTH / 2d, 0), new Vector3D(0, 0, 1))); 76 } 77 78 @ParameterizedTest 79 @MethodSource 80 void testMapPoint(final Point2D.Double expectedScaled, final Point2D.Double initial, final Vector3D rotation) { 81 this.cameraPlane.setRotation(rotation); 82 final Point2D.Double actual = this.cameraPlane.mapPoint(initial.x, initial.y); 83 assertAll(() -> assertEquals(expectedScaled.x, actual.x, MAX_DELTA, "X"), 84 () -> assertEquals(expectedScaled.y, actual.y, MAX_DELTA, "Y")); 85 final Point2D.Double intActual = this.cameraPlane.mapPoint((int) initial.x, (int) initial.y); 86 assertAll(() -> assertEquals(expectedScaled.x, intActual.x, MAX_DELTA, "X"), 87 () -> assertEquals(expectedScaled.y, intActual.y, MAX_DELTA, "Y")); 38 88 } 39 89 40 90 @Test 41 @Disabled("Currently broken")42 91 void testGetVector3D() { 43 92 Vector3D vec = new Vector3D(0, 0, 1); 44 cameraPlane.setRotation(vec); 45 Vector3D out = cameraPlane.getVector3D(new Point(CAMERA_PLANE_WIDTH / 2, CAMERA_PLANE_HEIGHT / 2)); 46 assertAll(() -> assertEquals(0.0, out.getX(), 1.0E-04), () -> assertEquals(0.0, out.getY(), 1.0E-04), 47 () -> assertEquals(1.0, out.getZ(), 1.0E-04)); 93 this.cameraPlane.setRotation(vec); 94 Vector3D out = this.cameraPlane.getVector3D(new Point(CAMERA_PLANE_WIDTH / 2, CAMERA_PLANE_HEIGHT / 2)); 95 assertAll(() -> assertEquals(0.0, out.getX(), 1.0E-04, "X"), 96 () -> assertEquals(0.0, out.getY(), 1.0E-04, "Y"), 97 () -> assertEquals(1.0, out.getZ(), 1.0E-04, "Z")); 48 98 } 49 99 50 100 static Stream<Arguments> testGetVector3DFloat() { … … class CameraPlaneTest { 63 113 @ParameterizedTest 64 114 @MethodSource 65 115 void testGetVector3DFloat(final Vector3D expected, final Point toCheck) { 66 Vector3D out = cameraPlane.getVector3D(toCheck.getX(), toCheck.getY()); 67 assertAll(() -> assertEquals(expected.getX(), out.getX(), 1.0E-04), 68 () -> assertEquals(expected.getY(), out.getY(), 1.0E-04), 69 () -> assertEquals(expected.getZ(), out.getZ(), 1.0E-04), () -> assertEquals(1, 70 Math.sqrt(Math.pow(out.getX(), 2) + Math.pow(out.getY(), 2) + Math.pow(out.getZ(), 2)), 1.0E-04)); 116 Vector3D out = this.cameraPlane.getVector3D(toCheck.getX(), toCheck.getY()); 117 assertAll(() -> assertEquals(expected.getX(), out.getX(), 1.0E-04, "X"), 118 () -> assertEquals(expected.getY(), out.getY(), 1.0E-04, "Y"), 119 () -> assertEquals(expected.getZ(), out.getZ(), 1.0E-04, "Z"), 120 () -> assertEquals(1, Math.sqrt(Math.pow(out.getX(), 2) + Math.pow(out.getY(), 2) + Math.pow(out.getZ(), 2)), 121 1.0E-04, "Radial distance")); 71 122 } 72 123 73 124 @Test 74 @Disabled("Currently broken")75 125 void testMapping() { 76 126 Vector3D vec = new Vector3D(0, 0, 1); 77 cameraPlane.setRotation(vec);78 Vector3D out = cameraPlane.getVector3D(new Point(300, 200));127 this.cameraPlane.setRotation(vec); 128 Vector3D out = this.cameraPlane.getVector3D(new Point(300, 200)); 79 129 Point2D map = UVMapping.getTextureCoordinate(out); 80 assertAll(() -> assertEquals(0.44542099, map.getX(), 1e-8), () -> assertEquals(0.39674936, map.getY(), 1e-8)); 130 assertAll(() -> assertEquals(0.44542099, map.getX(), 1e-8, "X"), 131 () -> assertEquals(0.39674936, map.getY(), 1e-8, "Y")); 81 132 } 82 133 } -
test/unit/org/openstreetmap/josm/gui/util/imagery/Vector3DTest.java
diff --git a/test/unit/org/openstreetmap/josm/gui/util/imagery/Vector3DTest.java b/test/unit/org/openstreetmap/josm/gui/util/imagery/Vector3DTest.java index 5f360956fc..28797d1fc5 100644
a b package org.openstreetmap.josm.gui.util.imagery; 3 3 4 4 import static org.junit.jupiter.api.Assertions.assertAll; 5 5 import static org.junit.jupiter.api.Assertions.assertEquals; 6 import static org.junit.jupiter.api.Assertions.fail;7 6 8 7 import java.util.stream.Stream; 9 8 10 import org.junit.jupiter.api.Disabled; 9 import nl.jqno.equalsverifier.EqualsVerifier; 10 import org.junit.jupiter.api.Test; 11 11 import org.junit.jupiter.params.ParameterizedTest; 12 12 import org.junit.jupiter.params.provider.Arguments; 13 13 import org.junit.jupiter.params.provider.MethodSource; … … import org.junit.jupiter.params.provider.MethodSource; 18 18 */ 19 19 class Vector3DTest { 20 20 21 private static final double MAX_DELTA = 1E-14; 22 21 23 static Stream<Arguments> vectorInformation() { 22 24 return Stream.of( 23 Arguments.of(0, 0, 0, 0), 24 Arguments.of(1, 1, 1, Math.sqrt(3)), 25 Arguments.of(-1, -1, -1, Math.sqrt(3)), 26 Arguments.of(-2, 2, -2, Math.sqrt(12)) 25 // (x, y, z, radialDistance, polarAngle, azimuthAngle) 26 Arguments.of(0, 0, 0, 0, 0, 0), 27 Arguments.of(1, 1, 1, Math.sqrt(3), 0.9553166181245092, Math.PI / 4), 28 Arguments.of(-1, -1, -1, Math.sqrt(3), 2.1862760354652844, -3 * Math.PI / 4), 29 Arguments.of(-2, 2, -2, Math.sqrt(12), 2.1862760354652844, 3 * Math.PI / 4) 27 30 ); 28 31 } 29 32 … … class Vector3DTest { 52 55 @MethodSource("vectorInformation") 53 56 void getRadialDistance(final double x, final double y, final double z, final double radialDistance) { 54 57 final Vector3D vector3D = new Vector3D(x, y, z); 55 assertEquals(radialDistance, vector3D.getRadialDistance() );58 assertEquals(radialDistance, vector3D.getRadialDistance(), MAX_DELTA); 56 59 } 57 60 58 61 @ParameterizedTest 59 62 @MethodSource("vectorInformation") 60 @Disabled("Angle calculations may be corrected")61 void getPolarAngle() {62 fail("Not yet implemented");63 void getPolarAngle(final double x, final double y, final double z, final double ignoredRadialDistance, final double polarAngle) { 64 final Vector3D vector3D = new Vector3D(x, y, z); 65 assertEquals(polarAngle, vector3D.getPolarAngle(), MAX_DELTA); 63 66 } 64 67 65 68 @ParameterizedTest 66 69 @MethodSource("vectorInformation") 67 @Disabled("Angle calculations may be corrected") 68 void getAzimuthalAngle() { 69 fail("Not yet implemented"); 70 void getAzimuthalAngle(final double x, final double y, final double z, 71 final double ignoredRadialDistance, final double ignoredPolarAngle, final double azimuthAngle) { 72 final Vector3D vector3D = new Vector3D(x, y, z); 73 assertEquals(azimuthAngle, vector3D.getAzimuthalAngle(), MAX_DELTA); 70 74 } 71 75 72 76 @ParameterizedTest … … class Vector3DTest { 81 85 82 86 @ParameterizedTest 83 87 @MethodSource("vectorInformation") 84 @Disabled("Angle calculations may be corrected") 85 void testToString() { 86 fail("Not yet implemented"); 88 void testConstructorArgs(final double x, final double y, final double z) { 89 final Vector3D vector3D = new Vector3D(x, y, z); 90 final Vector3D vector3DRPA = new Vector3D(Vector3D.VectorType.RPA, vector3D.getRadialDistance(), 91 vector3D.getPolarAngle(), vector3D.getAzimuthalAngle()); 92 final Vector3D vector3DRAP = new Vector3D(Vector3D.VectorType.RAP, vector3D.getRadialDistance(), 93 vector3D.getAzimuthalAngle(), vector3D.getPolarAngle()); 94 assertAll(() -> assertEquals(vector3D.getX(), vector3DRPA.getX(), MAX_DELTA, "RPA X"), 95 () -> assertEquals(vector3D.getY(), vector3DRPA.getY(), MAX_DELTA, "RPA Y"), 96 () -> assertEquals(vector3D.getZ(), vector3DRPA.getZ(), MAX_DELTA, "RPA Z"), 97 () -> assertEquals(vector3D.getX(), vector3DRAP.getX(), MAX_DELTA, "RAP X"), 98 () -> assertEquals(vector3D.getY(), vector3DRAP.getY(), MAX_DELTA, "RAP Y"), 99 () -> assertEquals(vector3D.getZ(), vector3DRAP.getZ(), MAX_DELTA, "RAP Z")); 100 } 101 102 @ParameterizedTest 103 @MethodSource("vectorInformation") 104 void testToString(final double x, final double y, final double z, 105 final double radialDistance, final double polarAngle, final double azimuthAngle) { 106 final Vector3D vector3D = new Vector3D(x, y, z); 107 assertEquals("[x=" + x + ", y=" + y + ", z=" + z + ", r=" + radialDistance + ", inclination=" 108 + polarAngle + ", azimuthal=" + azimuthAngle + "]", vector3D.toString()); 109 } 110 111 @Test 112 void testEqualsVerifier() { 113 EqualsVerifier.forClass(Vector3D.class) 114 // These fields are all dependendent upon x, y, and z, and should always evaluate to the same numbers 115 .withIgnoredFields("radialDistance", 116 "polarAngle", "polarAngleCos", "polarAngleSin", 117 "azimuthalAngle", "azimuthalAngleCos", "azimuthalAngleSin") 118 .verify(); 87 119 } 88 120 }
