Add coordinate interpolation method + improve unit tests

This commit is contained in:
SiboVG 2024-09-21 04:39:47 +01:00
parent c3614330b9
commit 19f8e3c8f3
2 changed files with 133 additions and 29 deletions

View File

@ -311,6 +311,20 @@ public final class Coordinate implements Cloneable, Serializable {
}
return new Coordinate(x1, y1, z1, w1);
}
/**
* Interpolate between two coordinates. The fraction is the weight of the other coordinate.
* @param other Coordinate to interpolate to.
* @param fraction Interpolation fraction (0 = this, 1 = other).
* @return Interpolated coordinate.
*/
public Coordinate interpolate(Coordinate other, double fraction) {
double x1 = this.x + (other.x - this.x) * fraction;
double y1 = this.y + (other.y - this.y) * fraction;
double z1 = this.z + (other.z - this.z) * fraction;
double w1 = this.weight + (other.weight - this.weight) * fraction;
return new Coordinate(x1, y1, z1, w1);
}
/**

View File

@ -9,54 +9,144 @@ public class CoordinateTest {
private static final double EPS = 0.0000000001;
@Test
public void coordinateTest() {
public void testConstructors() {
Coordinate c1 = new Coordinate();
assertCoordinateEquals(new Coordinate(0, 0, 0, 0), c1);
Coordinate c2 = new Coordinate(1);
assertCoordinateEquals(new Coordinate(1, 0, 0, 0), c2);
Coordinate c3 = new Coordinate(1, 2);
assertCoordinateEquals(new Coordinate(1, 2, 0, 0), c3);
Coordinate c4 = new Coordinate(1, 2, 3);
assertCoordinateEquals(new Coordinate(1, 2, 3, 0), c4);
Coordinate c5 = new Coordinate(1, 2, 3, 4);
assertCoordinateEquals(new Coordinate(1, 2, 3, 4), c5);
}
@Test
public void testSetters() {
Coordinate x = new Coordinate(1, 1, 1, 1);
Coordinate y = new Coordinate(1, 2, 3, 4);
assertCoordinateEquals(new Coordinate(2, 1, 1, 1), x.setX(2));
assertCoordinateEquals(new Coordinate(1, 2, 1, 1), x.setY(2));
assertCoordinateEquals(new Coordinate(1, 1, 2, 1), x.setZ(2));
assertCoordinateEquals(new Coordinate(1, 1, 1, 2), x.setWeight(2));
assertCoordinateEquals(new Coordinate(2, 3, 4, 1), x.setXYZ(y).add(1, 1, 1));
assertFalse(x.isNaN());
assertTrue(x.setX(Double.NaN).isNaN());
Coordinate y = new Coordinate(1, 2, 3, 4);
assertCoordinateEquals(new Coordinate(1, 2, 3, 1), x.setXYZ(y));
}
@Test
public void testIsWeighted() {
assertTrue(new Coordinate(1, 1, 1, 1).isWeighted());
assertFalse(new Coordinate(1, 1, 1, 0).isWeighted());
}
@Test
public void testIsNaN() {
assertFalse(new Coordinate(1, 1, 1, 1).isNaN());
assertTrue(new Coordinate(Double.NaN, 1, 1, 1).isNaN());
assertTrue(new Coordinate(1, Double.NaN, 1, 1).isNaN());
assertTrue(new Coordinate(1, 1, Double.NaN, 1).isNaN());
assertTrue(new Coordinate(1, 1, 1, Double.NaN).isNaN());
assertTrue(Coordinate.NaN.isNaN());
}
assertTrue(x.isWeighted());
assertFalse(x.setWeight(0).isWeighted());
@Test
public void testAdd() {
Coordinate x = new Coordinate(1, 1, 1, 1);
Coordinate y = new Coordinate(1, 2, 3, 4);
assertCoordinateEquals(x, x.add(Coordinate.NUL));
assertCoordinateEquals(new Coordinate(2, 3, 4, 5), x.add(y));
assertCoordinateEquals(new Coordinate(2, 3, 4, 1), x.add(1, 2, 3));
assertCoordinateEquals(new Coordinate(2, 3, 4, 5), x.add(1, 2, 3, 4));
}
@Test
public void testSub() {
Coordinate x = new Coordinate(1, 1, 1, 1);
Coordinate y = new Coordinate(1, 2, 3, 4);
assertCoordinateEquals(new Coordinate(0, -1, -2, 1), x.sub(y));
assertCoordinateEquals(new Coordinate(0, -1, -2, 1), x.sub(1, 2, 3));
assertCoordinateEquals(new Coordinate(2, 4, 6, 8), y.multiply(2));
assertEquals(1 + 2 + 3, y.dot(x), EPS);
assertEquals(1 + 2 + 3, x.dot(y), EPS);
assertEquals(1 + 2 + 3, Coordinate.dot(x, y), EPS);
assertEquals(x.dot(x), x.length2(), EPS);
assertEquals(y.dot(y), y.length2(), EPS);
assertEquals(3.7416573867739413, y.length(), EPS);
assertEquals(1, y.normalize().length(), EPS);
assertCoordinateEquals(new Coordinate(1.75, 1.75, 1.75, 4),
new Coordinate(1, 1, 1, 1).average(new Coordinate(2, 2, 2, 3)));
assertCoordinateEquals(new Coordinate(1, 1, 1, 1),
new Coordinate(1, 1, 1, 1).average(new Coordinate(2, 2, 2, 0)));
assertCoordinateEquals(new Coordinate(1.5, 1.5, 1.5, 0),
new Coordinate(1, 1, 1, 0).average(new Coordinate(2, 2, 2, 0)));
}
private void assertCoordinateEquals(Coordinate a, Coordinate b) {
assertEquals(a, b);
assertEquals(a.weight, b.weight, EPS);
@Test
public void testMultiply() {
Coordinate x = new Coordinate(1, 2, 3, 4);
assertCoordinateEquals(new Coordinate(2, 4, 6, 8), x.multiply(2));
assertCoordinateEquals(new Coordinate(1, 4, 9, 16), x.multiply(x));
}
@Test
public void testDot() {
Coordinate x = new Coordinate(1, 1, 1, 1);
Coordinate y = new Coordinate(1, 2, 3, 4);
assertEquals(6, x.dot(y), EPS);
assertEquals(6, y.dot(x), EPS);
assertEquals(6, Coordinate.dot(x, y), EPS);
}
@Test
public void testLength() {
Coordinate x = new Coordinate(3, 4, 0, 1);
assertEquals(5, x.length(), EPS);
assertEquals(25, x.length2(), EPS);
}
@Test
public void testMax() {
assertEquals(3, new Coordinate(1, -2, 3, 4).max(), EPS);
}
@Test
public void testNormalize() {
Coordinate x = new Coordinate(3, 4, 0, 2);
Coordinate normalized = x.normalize();
assertEquals(1, normalized.length(), EPS);
assertEquals(2, normalized.weight, EPS);
}
@Test
public void testCross() {
Coordinate x = new Coordinate(1, 0, 0);
Coordinate y = new Coordinate(0, 1, 0);
assertCoordinateEquals(new Coordinate(0, 0, 1), x.cross(y));
assertCoordinateEquals(new Coordinate(0, 0, 1), Coordinate.cross(x, y));
}
@Test
public void testAverage() {
Coordinate x = new Coordinate(1, 2, 4, 1);
Coordinate y = new Coordinate(3, 5, 9, 1);
assertCoordinateEquals(new Coordinate(2, 3.5, 6.5, 2), x.average(y));
y = new Coordinate(3, 5, 9, 3);
assertCoordinateEquals(new Coordinate(2.5, 4.25, 7.75, 4), x.average(y));
}
@Test
public void testInterpolate() {
Coordinate x = new Coordinate(0, 0, 0, 0);
Coordinate y = new Coordinate(10, 10, 10, 10);
assertCoordinateEquals(new Coordinate(5, 5, 5, 5), x.interpolate(y, 0.5));
}
private void assertCoordinateEquals(Coordinate expected, Coordinate actual) {
assertEquals(expected.x, actual.x, EPS);
assertEquals(expected.y, actual.y, EPS);
assertEquals(expected.z, actual.z, EPS);
assertEquals(expected.weight, actual.weight, EPS);
}
}