170 lines
6.0 KiB
Java
170 lines
6.0 KiB
Java
|
package ch.epfl.alpano.dem;
|
||
|
|
||
|
import static ch.epfl.test.TestRandomizer.RANDOM_ITERATIONS;
|
||
|
import static ch.epfl.test.TestRandomizer.newRandom;
|
||
|
import static java.lang.Math.toDegrees;
|
||
|
import static java.lang.Math.toRadians;
|
||
|
import static org.junit.Assert.assertEquals;
|
||
|
import static org.junit.Assert.assertTrue;
|
||
|
|
||
|
import java.util.Random;
|
||
|
|
||
|
import org.junit.Test;
|
||
|
|
||
|
import ch.epfl.alpano.GeoPoint;
|
||
|
import ch.epfl.alpano.Interval1D;
|
||
|
import ch.epfl.alpano.Interval2D;
|
||
|
|
||
|
public class ContinuousElevationModelTest {
|
||
|
private final static Interval2D EXT_100_100 = new Interval2D(
|
||
|
new Interval1D(0, 100),
|
||
|
new Interval1D(0, 100));
|
||
|
|
||
|
private final static Interval2D EXT_13_13 = new Interval2D(
|
||
|
new Interval1D(0, 13),
|
||
|
new Interval1D(0, 13));
|
||
|
|
||
|
@Test(expected = NullPointerException.class)
|
||
|
public void constructorFailsWithNullDEM() {
|
||
|
new ContinuousElevationModel(null);
|
||
|
}
|
||
|
|
||
|
@Test
|
||
|
public void elevationAtReturns0OutsideOfExtent() {
|
||
|
DiscreteElevationModel dDEM = new ConstantElevationDEM(EXT_100_100, 1000);
|
||
|
ContinuousElevationModel cDEM = new ContinuousElevationModel(dDEM);
|
||
|
assertEquals(0, cDEM.elevationAt(pointForSampleIndex(101, 0)), 0);
|
||
|
}
|
||
|
|
||
|
@Test
|
||
|
public void elevationAtReturnsCorrectElevationInsideExtent() {
|
||
|
double elevation = 1000;
|
||
|
DiscreteElevationModel dDEM = new ConstantElevationDEM(EXT_100_100, elevation);
|
||
|
ContinuousElevationModel cDEM = new ContinuousElevationModel(dDEM);
|
||
|
Random rng = newRandom();
|
||
|
for (int i = 0; i < RANDOM_ITERATIONS; ++i) {
|
||
|
double x = rng.nextDouble() * 100d, y = rng.nextDouble() * 100d;
|
||
|
assertEquals(elevation, cDEM.elevationAt(pointForSampleIndex(x, y)), 1e-10);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
@Test
|
||
|
public void elevationAtInterpolatesJustOutsideExtent() {
|
||
|
DiscreteElevationModel dDEM = new ConstantElevationDEM(EXT_100_100, 1000);
|
||
|
ContinuousElevationModel cDEM = new ContinuousElevationModel(dDEM);
|
||
|
assertEquals(500, cDEM.elevationAt(pointForSampleIndex(100.5, 10)), 1e-10);
|
||
|
}
|
||
|
|
||
|
@Test
|
||
|
public void elevationAtReturnsCorrectInterpolatedElevation() {
|
||
|
DiscreteElevationModel dDEM = new ConstantSlopeDEM(EXT_100_100);
|
||
|
ContinuousElevationModel cDEM = new ContinuousElevationModel(dDEM);
|
||
|
Random rng = new Random();
|
||
|
for (int i = 0; i < RANDOM_ITERATIONS; ++i) {
|
||
|
double x = rng.nextDouble() * 100;
|
||
|
double y = rng.nextDouble() * 100;
|
||
|
assertEquals((x + y) * ConstantSlopeDEM.INTER_SAMPLE_DISTANCE, cDEM.elevationAt(pointForSampleIndex(x, y)), 1e-6);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
@Test
|
||
|
public void elevationAtStaysWithinBoundsOnRandomTerrain() {
|
||
|
int maxElevation = 1000;
|
||
|
DiscreteElevationModel dDEM = new RandomElevationDEM(EXT_13_13, maxElevation);
|
||
|
ContinuousElevationModel cDEM = new ContinuousElevationModel(dDEM);
|
||
|
Random rng = newRandom();
|
||
|
for (int i = 0; i < RANDOM_ITERATIONS; ++i) {
|
||
|
double x = rng.nextDouble() * dDEM.extent().iX().size();
|
||
|
double y = rng.nextDouble() * dDEM.extent().iY().size();
|
||
|
double e = cDEM.elevationAt(pointForSampleIndex(x, y));
|
||
|
assertTrue(0 <= e && e <= maxElevation);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
@Test
|
||
|
public void slopeAtReturnsCorrectInterpolatedSlope() {
|
||
|
DiscreteElevationModel dDEM = new ConstantSlopeDEM(EXT_100_100);
|
||
|
ContinuousElevationModel cDEM = new ContinuousElevationModel(dDEM);
|
||
|
Random rng = new Random();
|
||
|
double expectedSlope = Math.acos(1 / Math.sqrt(3));
|
||
|
for (int i = 0; i < RANDOM_ITERATIONS; ++i) {
|
||
|
double x = 5 + rng.nextDouble() * 90;
|
||
|
double y = 5 + rng.nextDouble() * 90;
|
||
|
assertEquals(expectedSlope, cDEM.slopeAt(pointForSampleIndex(x, y)), 1e-4);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
@Test
|
||
|
public void slopeAtStaysWithinBoundsOnRandomTerrain() {
|
||
|
int maxElevation = 1000;
|
||
|
DiscreteElevationModel dDEM = new RandomElevationDEM(EXT_13_13, maxElevation);
|
||
|
ContinuousElevationModel cDEM = new ContinuousElevationModel(dDEM);
|
||
|
Random rng = newRandom();
|
||
|
for (int i = 0; i < RANDOM_ITERATIONS; ++i) {
|
||
|
double x = rng.nextDouble() * dDEM.extent().iX().size();
|
||
|
double y = rng.nextDouble() * dDEM.extent().iY().size();
|
||
|
double e = toDegrees(cDEM.slopeAt(pointForSampleIndex(x, y)));
|
||
|
assertTrue(0 <= e && e < 90);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
private static GeoPoint pointForSampleIndex(double x, double y) {
|
||
|
return new GeoPoint(toRadians(x / 3600d), toRadians(y / 3600d));
|
||
|
}
|
||
|
}
|
||
|
|
||
|
class RandomElevationDEM implements DiscreteElevationModel {
|
||
|
private final Interval2D extent;
|
||
|
private final double[][] elevations;
|
||
|
|
||
|
public RandomElevationDEM(Interval2D extent, int maxElevation) {
|
||
|
this.extent = extent;
|
||
|
this.elevations = randomElevations(extent.iX().size(), extent.iY().size(), maxElevation);
|
||
|
}
|
||
|
|
||
|
private static double[][] randomElevations(int width, int height, int maxElevation) {
|
||
|
Random rng = newRandom();
|
||
|
double[][] es = new double[width][height];
|
||
|
for (int x = 0; x < width; ++x) {
|
||
|
for (int y = 0; y < height; ++y) {
|
||
|
es[x][y] = rng.nextInt(maxElevation + 1);
|
||
|
}
|
||
|
}
|
||
|
return es;
|
||
|
}
|
||
|
|
||
|
@Override
|
||
|
public Interval2D extent() {
|
||
|
return extent;
|
||
|
}
|
||
|
|
||
|
@Override
|
||
|
public double elevationSample(int x, int y) {
|
||
|
return elevations[x][y];
|
||
|
}
|
||
|
|
||
|
@Override
|
||
|
public void close() throws Exception { }
|
||
|
}
|
||
|
|
||
|
class ConstantSlopeDEM implements DiscreteElevationModel {
|
||
|
public final static double INTER_SAMPLE_DISTANCE =
|
||
|
2d * Math.PI * 6_371_000d / (3600d * 360d);
|
||
|
|
||
|
private final Interval2D extent;
|
||
|
|
||
|
public ConstantSlopeDEM(Interval2D extent) {
|
||
|
this.extent = extent;
|
||
|
}
|
||
|
|
||
|
@Override
|
||
|
public Interval2D extent() { return extent; }
|
||
|
|
||
|
@Override
|
||
|
public double elevationSample(int x, int y) {
|
||
|
return (x + y) * INTER_SAMPLE_DISTANCE;
|
||
|
}
|
||
|
|
||
|
@Override
|
||
|
public void close() throws Exception {}
|
||
|
}
|