Disabled external gits

This commit is contained in:
2022-04-07 18:43:21 +02:00
parent 182267a8cb
commit 88cb3426ad
1067 changed files with 102374 additions and 6 deletions

View File

@@ -0,0 +1,167 @@
package ch.epfl.alpano;
import static ch.epfl.alpano.Azimuth.canonicalize;
import static ch.epfl.alpano.Azimuth.fromMath;
import static ch.epfl.alpano.Azimuth.isCanonical;
import static ch.epfl.alpano.Azimuth.toMath;
import static ch.epfl.alpano.Azimuth.toOctantString;
import static ch.epfl.test.TestRandomizer.RANDOM_ITERATIONS;
import static ch.epfl.test.TestRandomizer.newRandom;
import static java.lang.Math.PI;
import static java.lang.Math.floorMod;
import static java.lang.Math.nextDown;
import static java.lang.Math.round;
import static java.lang.Math.scalb;
import static java.lang.Math.toDegrees;
import static java.lang.Math.toRadians;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Random;
import org.junit.Test;
public class AzimuthTest {
@Test
public void isCanonicalIsTrueFor0() {
assertTrue(isCanonical(0));
}
@Test
public void isCanonicalIsFalseFor0Pred() {
assertFalse(isCanonical(nextDown(0)));
}
@Test
public void isCanonicalIsTrueFor2PiPred() {
assertTrue(isCanonical(nextDown(scalb(PI, 1))));
}
@Test
public void isCanonicalIsFalseFor2Pi() {
assertFalse(isCanonical(scalb(PI, 1)));
}
@Test
public void isCanonicalIsTrueForRandomCanonicalAzimuths() {
Random rng = newRandom();
for (int i = 0; i < RANDOM_ITERATIONS; ++i)
assertTrue(isCanonical(rng.nextDouble() * scalb(PI, 1)));
}
@Test
public void canonicalizeCorrectlyCanonicalizesRoundedRandomAngles() {
Random rng = newRandom();
for (int i = 0; i < RANDOM_ITERATIONS; ++i) {
int aDeg = rng.nextInt(10_000) - 5_000;
double aRad = toRadians(aDeg);
double canonicalARad = canonicalize(aRad);
assertTrue(0 <= canonicalARad && canonicalARad < scalb(PI, 1));
int canonicalADeg = (int)round(toDegrees(canonicalARad));
if (canonicalADeg == 360)
canonicalADeg = 0;
assertEquals(floorMod(aDeg, 360), canonicalADeg);
}
}
@Test
public void toMathCorrectlyHandles0() {
assertEquals(0d, toMath(0d), 0d);
}
@Test
public void fromMathCorrectlyHandles0() {
assertEquals(0d, fromMath(0d), 0d);
}
@Test
public void toMathWorksForKnownValues() {
int[] vs = new int[] {
0, 0,
1,359,
2,358,
358,2,
359,1,
90, 270,
180, 180,
179,181,
181,179,
270, 90
};
for (int i = 0; i < vs.length; i += 2) {
double a = toMath(toRadians(vs[i]));
assertEquals(toRadians(vs[i+1]), a, 1e-10);
}
}
@Test
public void fromMathWorksForKnownValues() {
int[] vs = new int[] {
0, 0,
1,359,
2,358,
358,2,
359,1,
90, 270,
180, 180,
179,181,
181,179,
270, 90
};
for (int i = 0; i < vs.length; i += 2) {
double a = fromMath(toRadians(vs[i]));
assertEquals(toRadians(vs[i+1]), a, 1e-10);
}
}
@Test
public void toMathAndFromMathAreInverseForRandomValues() {
Random rng = newRandom();
for (int i = 0; i < RANDOM_ITERATIONS; ++i) {
double a = rng.nextDouble() * scalb(PI, 1);
double a2 = fromMath(toMath(a));
assertEquals(a, a2, 1e-10);
double a3 = toMath(fromMath(a));
assertEquals(a, a3, 1e-10);
}
}
@Test(expected = java.lang.IllegalArgumentException.class)
public void toMathThrowsFor2Pi() {
toMath(scalb(PI, 1));
}
@Test(expected = java.lang.IllegalArgumentException.class)
public void fromMathThrowsFor2Pi() {
fromMath(scalb(PI, 1));
}
@Test(expected = IllegalArgumentException.class)
public void toOctantStringThrowsForNonCanonicalAzimuth() {
toOctantString(-1, null, null, null, null);
}
@Test
public void toOctantStringCorrectlyCyclesThroughValues() {
String n = "north", e = "east", s = "south", w = "west";
ArrayList<String> expected = new ArrayList<>();
expected.addAll(Collections.nCopies(45, n));
expected.addAll(Collections.nCopies(45, n+e));
expected.addAll(Collections.nCopies(45, e));
expected.addAll(Collections.nCopies(45, s+e));
expected.addAll(Collections.nCopies(45, s));
expected.addAll(Collections.nCopies(45, s+w));
expected.addAll(Collections.nCopies(45, w));
expected.addAll(Collections.nCopies(45, n+w));
for (int aDeg = 0; aDeg < 360; ++aDeg) {
double aRad = toRadians(floorMod(aDeg - 22, 360));
String os = toOctantString(aRad, n, e, s, w);
assertEquals(expected.get(aDeg), os);
}
}
}

View File

@@ -0,0 +1,37 @@
package ch.epfl.alpano;
import static ch.epfl.test.TestRandomizer.RANDOM_ITERATIONS;
import static ch.epfl.test.TestRandomizer.newRandom;
import static java.lang.Math.PI;
import static java.lang.Math.scalb;
import static org.junit.Assert.assertEquals;
import java.util.Random;
import org.junit.Test;
public class DistanceTest {
private static double EARTH_CIRCUMFERENCE = 40_030_174; // rounded to nearest integer
@Test
public void toRadiansAndToMetersAreInverseForRandomValues() {
Random rng = newRandom();
for (int i = 0; i < RANDOM_ITERATIONS; ++i) {
double dRad = rng.nextDouble() * scalb(PI, 1);
double dRad2 = Distance.toRadians(Distance.toMeters(dRad));
assertEquals(dRad, dRad2, 1e-10);
}
}
@Test
public void toMetersIsCorrectForKnownValues() {
assertEquals(0, Distance.toMeters(0), 0);
assertEquals(EARTH_CIRCUMFERENCE, Distance.toMeters(scalb(PI, 1)), 0.5);
}
@Test
public void toRadiansIsCorrectForKnownValues() {
assertEquals(0, Distance.toRadians(0), 0);
assertEquals(scalb(PI, 1), Distance.toRadians(EARTH_CIRCUMFERENCE), 1e-5);
}
}

View File

@@ -0,0 +1,71 @@
package ch.epfl.alpano;
import java.io.File;
import javax.imageio.ImageIO;
import ch.epfl.alpano.dem.ContinuousElevationModel;
import ch.epfl.alpano.dem.DiscreteElevationModel;
import ch.epfl.alpano.dem.HgtDiscreteElevationModel;
import static java.lang.Math.max;
import static java.lang.Math.min;
import static java.lang.Math.toRadians;
import java.awt.image.BufferedImage;
final class DrawPanorama {
final static File HGT_FILE = new File("HGT"+File.separatorChar+"N46E007.hgt");
final static int IMAGE_WIDTH = 500;
final static int IMAGE_HEIGHT = 200;
final static double ORIGIN_LON = toRadians(7.65);
final static double ORIGIN_LAT = toRadians(46.73);
final static int ELEVATION = 600;
final static double CENTER_AZIMUTH = toRadians(180);
final static double HORIZONTAL_FOV = toRadians(60);
final static int MAX_DISTANCE = 100_000;
final static PanoramaParameters PARAMS =
new PanoramaParameters(new GeoPoint(ORIGIN_LON,
ORIGIN_LAT),
ELEVATION,
CENTER_AZIMUTH,
HORIZONTAL_FOV,
MAX_DISTANCE,
IMAGE_WIDTH,
IMAGE_HEIGHT);
public static void main(String[] as) throws Exception {
try (DiscreteElevationModel dDEM =
new HgtDiscreteElevationModel(HGT_FILE)) {
ContinuousElevationModel cDEM =
new ContinuousElevationModel(dDEM);
Panorama p = new PanoramaComputer(cDEM)
.computePanorama(PARAMS);
BufferedImage i =
new BufferedImage(IMAGE_WIDTH,
IMAGE_HEIGHT,
BufferedImage.TYPE_INT_RGB);
for (int x = 0; x < IMAGE_WIDTH; ++x) {
for (int y = 0; y < IMAGE_HEIGHT; ++y) {
float d = p.distanceAt(x, y);
int c = (d == Float.POSITIVE_INFINITY)
? 0x87_CE_EB
: gray((d - 2_000) / 15_000);
i.setRGB(x, y, c);
}
}
ImageIO.write(i, "png", new File("tests/ch/epfl/alpano/niesen.png"));
}
}
private static int gray(double v) {
double clampedV = max(0, min(v, 1));
int gray = (int) (255.9999 * clampedV);
return (gray << 16) | (gray << 8) | gray;
}
}

View File

@@ -0,0 +1,66 @@
package ch.epfl.alpano;
import java.io.File;
import javax.imageio.ImageIO;
import ch.epfl.alpano.dem.ContinuousElevationModel;
import ch.epfl.alpano.dem.DiscreteElevationModel;
import ch.epfl.alpano.dem.HgtDiscreteElevationModel;
import ch.epfl.alpano.gui.ChannelPainter;
import ch.epfl.alpano.gui.ImagePainter;
import ch.epfl.alpano.gui.PanoramaRenderer;
import javafx.embed.swing.SwingFXUtils;
import javafx.scene.image.Image;
import static java.lang.Math.toRadians;
final class DrawPanoramaNew {
final static File HGT_FILE = new File("HGT"+File.separatorChar+"N46E007.hgt");
final static int IMAGE_WIDTH = 2_500;
final static int IMAGE_HEIGHT = 800;
final static double ORIGIN_LON = toRadians(7.65);
final static double ORIGIN_LAT = toRadians(46.73);
final static int ELEVATION = 600;
final static double CENTER_AZIMUTH = toRadians(180);
final static double HORIZONTAL_FOV = toRadians(110);
final static int MAX_DISTANCE = 100_000;
final static PanoramaParameters PARAMS =
new PanoramaParameters(new GeoPoint(ORIGIN_LON,
ORIGIN_LAT),
ELEVATION,
CENTER_AZIMUTH,
HORIZONTAL_FOV,
MAX_DISTANCE,
IMAGE_WIDTH,
IMAGE_HEIGHT);
public static void main(String[] as) throws Exception {
try (DiscreteElevationModel dDEM =
new HgtDiscreteElevationModel(HGT_FILE)) {
ContinuousElevationModel cDEM =
new ContinuousElevationModel(dDEM);
Panorama p = new PanoramaComputer(cDEM)
.computePanorama(PARAMS);
ChannelPainter d = p::distanceAt;
ChannelPainter sl = p::slopeAt;
ChannelPainter h = d.div(100000).cycling().mul(360);
ChannelPainter s = d.div(200000).clamped().inverted();
ChannelPainter b = sl.mul(2).div(Math.PI).inverted().mul(0.7).add(0.3);
ChannelPainter o =
d.map(dist -> dist == Float.POSITIVE_INFINITY ? 0 : 1);
ImagePainter l = ImagePainter.hsb(h, s, b, o);
Image i = PanoramaRenderer.renderPanorama(p, l);
ImageIO.write(SwingFXUtils.fromFXImage(i, null),
"png",
new File("tests/ch/epfl/alpano/niesen-profile.png"));
}
}
}

View File

@@ -0,0 +1,63 @@
package ch.epfl.alpano;
import java.io.File;
import java.util.Locale;
import javax.imageio.ImageIO;
import ch.epfl.alpano.dem.ContinuousElevationModel;
import ch.epfl.alpano.dem.DiscreteElevationModel;
import ch.epfl.alpano.dem.HgtDiscreteElevationModel;
import ch.epfl.alpano.gui.ChannelPainter;
import ch.epfl.alpano.gui.ImagePainter;
import ch.epfl.alpano.gui.PanoramaRenderer;
import ch.epfl.alpano.gui.PanoramaUserParameters;
import javafx.embed.swing.SwingFXUtils;
import javafx.scene.image.Image;
import ch.epfl.alpano.gui.PredefinedPanoramas;
final class DrawPanoramaNew2 {
public static void main(String[] as) throws Exception {
PanoramaUserParameters pano = PredefinedPanoramas.JURA_ALPS.get();
ContinuousElevationModel cDEM =generatePredefinedCDEM("./HGT/");
Panorama p = new PanoramaComputer(cDEM)
.computePanorama(pano.panoramaComputeParameters());
ChannelPainter d = p::distanceAt;
ChannelPainter sl = p::slopeAt;
ChannelPainter h = d.div(100000).cycling().mul(360);
ChannelPainter s = d.div(200000).clamped().inverted();
ChannelPainter b = sl.mul(2).div(Math.PI).inverted().mul(0.7).add(0.3);
ChannelPainter o =
d.map(dist -> dist == Float.POSITIVE_INFINITY ? 0 : 1);
ImagePainter l = ImagePainter.hsb(h, s, b, o);
Image i = PanoramaRenderer.renderPanorama(p, l);
ImageIO.write(SwingFXUtils.fromFXImage(i, null),
"png",
new File("tests/ch/epfl/alpano/niesen-profile.png"));
}
private static final ContinuousElevationModel generatePredefinedCDEM(String path){
DiscreteElevationModel DEM1=null;
DiscreteElevationModel DEM2=null;
File file;
for(int i=6;i<=11;++i){
for(int j=45;j<=47;++j){
file = new File(String.format((Locale) null, path+"N%02dE%03d.hgt",j,i));
if(DEM1==null)
DEM1 = new HgtDiscreteElevationModel(file);
DEM1 = new HgtDiscreteElevationModel(file).union(DEM1);
}
if(DEM2==null)
DEM2=DEM1;
DEM2=DEM1.union(DEM2);
DEM1=null;
}
return new ContinuousElevationModel(DEM2);
}
}

View File

@@ -0,0 +1,68 @@
package ch.epfl.alpano;
import static org.junit.Assert.*;
import org.junit.Test;
public class GeoPointTest {
@Test(expected = IllegalArgumentException.class)
public void constructorLimitTest1(){
new GeoPoint(0, 2*Math.PI);
}
@Test(expected = IllegalArgumentException.class)
public void constructorLimitTest2(){
new GeoPoint(2*Math.PI, 2*Math.PI);
}
@Test(expected = IllegalArgumentException.class)
public void constructorLimitTest3(){
new GeoPoint(2*Math.PI, 0);
}
@Test
public void distanceToTest1(){
GeoPoint london = new GeoPoint(Math.toRadians(6.631), Math.toRadians(46.521));
GeoPoint moscow = new GeoPoint( Math.toRadians(37.623), Math.toRadians(55.753));
assertEquals(2367000, london.distanceTo(moscow), 1000);//1km imprecision
assertEquals(0,london.azimuthTo(london),0);
}
@Test
public void distanceToTest2(){
GeoPoint epfl = new GeoPoint(Math.toRadians(6.56730), Math.toRadians(46.51781));
GeoPoint eiler = new GeoPoint( Math.toRadians(8.00537), Math.toRadians(46.57756));
assertEquals(110294, epfl.distanceTo(eiler), 150);//150M imprecision
}
@Test
public void distanceToTest3(){
GeoPoint p1 = new GeoPoint(Math.PI,Math.PI/2.0);
GeoPoint p2 = new GeoPoint(Math.PI,Math.PI/2.0);
GeoPoint p3 = new GeoPoint(0,Math.PI/2.0);
GeoPoint p4 = new GeoPoint(Math.PI/10.0,Math.PI/2.0);
assertEquals(p3.distanceTo(p4), p4.distanceTo(p3), 10);
assertEquals(p2.distanceTo(p1), p1.distanceTo(p2), 10);
assertEquals(p3.distanceTo(p4), p1.distanceTo(p2), 10);
}
@Test
public void distanceToTest4(){
GeoPoint p1 = new GeoPoint(Math.PI/2.0,Math.PI/2.0);
GeoPoint p2 = new GeoPoint(-Math.PI/2.0,Math.PI/2.0);
GeoPoint p3 = new GeoPoint(-Math.PI/2.0,Math.PI/2.0);
GeoPoint p4 = new GeoPoint(Math.PI/10.0,Math.PI/2.0);
assertEquals(p3.distanceTo(p4), p4.distanceTo(p3), 10);
assertEquals(p2.distanceTo(p1), p1.distanceTo(p2), 10);
assertEquals(p3.distanceTo(p4), p1.distanceTo(p2), 10);
}
@Test
public void toStringTest(){
GeoPoint g = new GeoPoint(Math.toRadians(-7.6543), Math.toRadians(54.3210));
assertEquals("(-7.6543,54.3210)", g.toString());
}
}

View File

@@ -0,0 +1,31 @@
package ch.epfl.alpano;
import static java.lang.Math.toDegrees;
import static java.lang.Math.toRadians;
import static org.junit.Assert.assertEquals;
import org.junit.Test;
public class GeoPointTestP {
private static GeoPoint CORNAVIN = new GeoPoint(toRadians(6.14308), toRadians(46.21023));
private static GeoPoint M1_EPFL = new GeoPoint(toRadians(6.56599), toRadians(46.52224));
private static GeoPoint FEDERAL_PALACE = new GeoPoint(toRadians(7.44428), toRadians(46.94652));
private static GeoPoint SAENTIS = new GeoPoint(toRadians(9.34324), toRadians(47.24942));
private static GeoPoint MONTE_TAMARO = new GeoPoint(toRadians(8.86598), toRadians(46.10386));
@Test
public void distanceToWorksOnKnownPoints() {
assertEquals(226_000, M1_EPFL.distanceTo(SAENTIS), 10);
assertEquals( 81_890, M1_EPFL.distanceTo(FEDERAL_PALACE), 10);
assertEquals(143_560, FEDERAL_PALACE.distanceTo(MONTE_TAMARO), 10);
assertEquals(269_870, SAENTIS.distanceTo(CORNAVIN), 10);
}
@Test
public void azimuthToWorksOnKnownPoints() {
assertEquals( 68.03, toDegrees(M1_EPFL.azimuthTo(SAENTIS)), 0.01);
assertEquals( 54.50, toDegrees(M1_EPFL.azimuthTo(FEDERAL_PALACE)), 0.01);
assertEquals(130.23, toDegrees(FEDERAL_PALACE.azimuthTo(MONTE_TAMARO)), 0.01);
assertEquals(245.82, toDegrees(SAENTIS.azimuthTo(CORNAVIN)), 0.01);
}
}

View File

@@ -0,0 +1,257 @@
package ch.epfl.alpano;
import static ch.epfl.test.TestRandomizer.RANDOM_ITERATIONS;
import static ch.epfl.test.TestRandomizer.newRandom;
import static org.junit.Assert.*;
import java.util.Random;
import org.junit.Test;
public class Interval1DTest {
@Test(expected = IllegalArgumentException.class)
public void testRandomIncludedFromAndToFails() {
Random rng = newRandom();
int a,b;
for (int i = 0; i < RANDOM_ITERATIONS; ++i){
a = rng.nextInt();
b = rng.nextInt();
if(a>b){
new Interval1D(a,b);
}
}
}
@Test
public void testRandomIncludedFromAndTo() {
Random rng = newRandom();
Interval1D interval;
int a,b;
for (int i = 0; i < RANDOM_ITERATIONS; ++i){
a = rng.nextInt();
b = rng.nextInt();
if(a<=b){
interval = new Interval1D(a,b);
assertEquals(interval.includedFrom(),a,0);
assertEquals(interval.includedTo(),b,0);
assertEquals(interval.size(),(b-a+1),0);
}
}
}
@Test
public void testLimitsIncludedFromAndTo() {
Interval1D interval = new Interval1D(0,0);
assertEquals(interval.includedFrom(),0,0);
assertEquals(interval.includedTo(),0,0);
assertEquals(interval.size(),1,0);
}
@Test
public void testContainsTrue() {
Random rng = newRandom();
Interval1D interval;
int a,b,m;
for (int i = 0; i < RANDOM_ITERATIONS; ++i){
a = rng.nextInt(500);
b = rng.nextInt(500);
if(a<=b){
m = (b+a)/2;
interval = new Interval1D(a,b);
assertTrue(interval.contains(m));
}
}
}
@Test
public void testContainsFails() {
Random rng = newRandom();
Interval1D interval;
int a,b,c;
for (int i = 0; i < RANDOM_ITERATIONS; ++i){
a = rng.nextInt(500);
b = rng.nextInt(500);
c = rng.nextInt(500);
if(a<=b && (c<a ||c>b)){
interval = new Interval1D(a,b);
assertFalse(interval.contains(c));
}
}
}
@Test
public void testSizeOfIntersectionWith() {
Interval1D interval1;
Interval1D interval2;
int num[] = {
1,1,0,2,1,
1,2,1,5,2,
1,4,0,2,2,
1,4,0,1,1,
2,4,0,1,0
};
for (int i = 0; i < num.length; i += 5) {
interval1 = new Interval1D(num[i],num[i+1]);
interval2 = new Interval1D(num[i+2],num[i+3]);
assertEquals(interval1.sizeOfIntersectionWith(interval2), interval2.sizeOfIntersectionWith(interval1));
assertEquals(interval1.sizeOfIntersectionWith(interval2), num[i+4], 0);
}
}
@Test
public void testBoundingUnion() {
Interval1D interval1;
Interval1D interval2;
Interval1D interval3;
int num[] = {
1,1,0,2,0,2,
1,1,1,1,1,1,
0,0,0,0,0,0,
0,0,1,1,0,1,
0,1,0,1,0,1,
0,5,1,1,0,5,
0,4,1,5,0,5,
1,5,0,4,0,5,
1,4,0,5,0,5,
0,0,9,9,0,9
};
for (int i = 0; i < num.length; i += 6) {
interval1 = new Interval1D(num[i],num[i+1]);
interval2 = new Interval1D(num[i+2],num[i+3]);
interval3 = new Interval1D(num[i+4],num[i+5]);
assertTrue(interval1.boundingUnion(interval2).equals(interval3));
}
}
@Test
public void testIsUnionableWithTrue() {
Interval1D interval1;
Interval1D interval2;
int num[] = {
1,1,0,2,
1,2,1,5,
1,4,0,2,
1,4,0,1,
2,4,0,2,
0,0,0,1,
0,5,5,5,
0,1,1,1,
-1,1,0,2
};
for (int i = 0; i < num.length; i += 4) {
interval1 = new Interval1D(num[i],num[i+1]);
interval2 = new Interval1D(num[i+2],num[i+3]);
assertEquals(interval1.isUnionableWith(interval2), interval2.isUnionableWith(interval1));
assertTrue(interval1.isUnionableWith(interval2));
}
}
@Test
public void testIsUnionableWithFalse() {
Interval1D interval1;
Interval1D interval2;
int num[] = {
0,0,2,2,
0,0,2,3,
0,0,4,4,
0,4,6,8,
2,2,0,0,
};
for (int i = 0; i < num.length; i += 4) {
interval1 = new Interval1D(num[i],num[i+1]);
interval2 = new Interval1D(num[i+2],num[i+3]);
assertEquals(interval1.isUnionableWith(interval2), interval2.isUnionableWith(interval1));
assertFalse(interval1.isUnionableWith(interval2));
}
}
@Test
public void testUnion() {
Interval1D interval1;
Interval1D interval2;
String str;
int num[] = {
1,1,0,2,0,2,
1,1,1,1,1,1,
0,0,0,0,0,0,
0,1,0,1,0,1,
0,1,0,1,0,1,
0,5,1,1,0,5,
0,4,1,5,0,5,
1,5,0,4,0,5,
1,4,0,5,0,5,
};
for (int i = 0; i < num.length; i += 6) {
interval1 = new Interval1D(num[i],num[i+1]);
interval2 = new Interval1D(num[i+2],num[i+3]);
str =("["+num[i+4]+".."+num[i+5]+"]");
assertEquals(str,interval1.union(interval2).toString());
}
}
@Test(expected = IllegalArgumentException.class)
public void testUnionFails() {
Interval1D interval1 = new Interval1D(0,0);
Interval1D interval2 = new Interval1D(2,2);
interval1.union(interval2);
}
@Test
public void testEqualsObjectTrue() {
Random rng = newRandom();
Interval1D interval1;
Interval1D interval2;
int a,b;
for (int i = 0; i < RANDOM_ITERATIONS; ++i){
a = rng.nextInt(500);
b = rng.nextInt(500);
if(a<=b){
interval1 = new Interval1D(a,b);
interval2 = new Interval1D(a,b);
assertTrue(interval1.equals(interval2));
assertEquals(interval1.equals(interval2), interval2.equals(interval1));
}
}
}
@Test
public void testEqualsObjectFalse() {
Random rng = newRandom();
Interval1D interval1;
String str = "";
int a,b;
for (int i = 0; i < RANDOM_ITERATIONS; ++i){
a = rng.nextInt(500);
b = rng.nextInt(500);
if(a<=b){
interval1 = new Interval1D(a,b);
assertFalse(interval1.equals(str));
assertEquals(interval1.equals(str), str.equals(interval1));
}
}
}
@Test
public void testToString() {
Random rng = newRandom();
Interval1D interval1;
int a,b;
for (int i = 0; i < RANDOM_ITERATIONS; ++i){
a = rng.nextInt(500);
b = rng.nextInt(500);
if(a<=b){
interval1 = new Interval1D(a,b);
assertEquals(interval1.toString(),"["+a+".."+b+"]");
}
}
}
}

View File

@@ -0,0 +1,161 @@
package ch.epfl.alpano;
import static ch.epfl.test.ObjectTest.hashCodeIsCompatibleWithEquals;
import static ch.epfl.test.TestRandomizer.RANDOM_ITERATIONS;
import static ch.epfl.test.TestRandomizer.newRandom;
import static java.lang.Math.ceil;
import static java.lang.Math.max;
import static java.lang.Math.min;
import static java.lang.Math.sqrt;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import java.util.Random;
import org.junit.Test;
public class Interval1DTestP {
private static Interval1D i_0_9() { return new Interval1D(0, 9); }
private static Interval1D i_0_2() { return new Interval1D(0, 2); }
private static Interval1D i_3_5() { return new Interval1D(3, 5); }
private static Interval1D i_4_6() { return new Interval1D(4, 6); }
private static Interval1D i_6_9() { return new Interval1D(6, 9); }
@Test(expected = IllegalArgumentException.class)
public void constructorFailsForInvalidBounds() {
new Interval1D(1, 0);
}
@Test
public void constructorWorksForSingletonInterval() {
new Interval1D(10, 10);
}
@Test
public void containsIsTrueOnlyForTheIntervalsElements() {
int sqrtIt = (int)ceil(sqrt(RANDOM_ITERATIONS));
Random rng = newRandom();
for (int i = 0; i < sqrtIt; ++i) {
int a = rng.nextInt(200) - 100;
int b = a + rng.nextInt(50);
Interval1D interval = new Interval1D(a, b);
for (int j = 0; j < sqrtIt; ++j) {
int v = rng.nextInt(200) - 100;
assertEquals(a <= v && v <= b, interval.contains(v));
}
}
}
@Test
public void containsWorksAtTheLimit() {
Random rng = newRandom();
for (int i = 0; i < RANDOM_ITERATIONS; ++i) {
int max = rng.nextInt(2000);
int a = rng.nextInt(max) - 1000;
int b = max - 1000;
Interval1D interval = new Interval1D(a, b);
assertFalse(interval.contains(a - 1));
assertTrue(interval.contains(a));
assertTrue(interval.contains(b));
assertFalse(interval.contains(b + 1));
}
}
@Test
public void sizeWorksOnKnownIntervals() {
assertEquals(10, i_0_9().size());
assertEquals(3, i_0_2().size());
assertEquals(3, i_3_5().size());
assertEquals(3, i_4_6().size());
assertEquals(4, i_6_9().size());
}
@Test
public void sizeOfIntersectionWorksOnNonIntersectingIntervals() {
assertEquals(0, i_0_2().sizeOfIntersectionWith(i_3_5()));
assertEquals(0, i_0_2().sizeOfIntersectionWith(i_4_6()));
assertEquals(0, i_0_2().sizeOfIntersectionWith(i_6_9()));
}
@Test
public void sizeOfIntersectionWorksOnIntersectingIntervals() {
assertEquals(3, i_0_2().sizeOfIntersectionWith(i_0_9()));
assertEquals(3, i_0_9().sizeOfIntersectionWith(i_0_2()));
assertEquals(1, i_4_6().sizeOfIntersectionWith(i_6_9()));
}
@Test
public void boundingUnionWorksOnKnownIntervals() {
assertEquals(0, i_0_2().boundingUnion(i_6_9()).includedFrom());
assertEquals(9, i_0_2().boundingUnion(i_6_9()).includedTo());
assertEquals(0, i_6_9().boundingUnion(i_0_2()).includedFrom());
assertEquals(9, i_6_9().boundingUnion(i_0_2()).includedTo());
assertEquals(0, i_0_9().boundingUnion(i_0_9()).includedFrom());
assertEquals(9, i_0_9().boundingUnion(i_0_9()).includedTo());
}
@Test
public void isUnionableWithWorksOnKnownIntervals() {
// Intersecting intervals
assertTrue(i_0_9().isUnionableWith(i_0_9()));
assertTrue(i_0_9().isUnionableWith(i_3_5()));
assertTrue(i_3_5().isUnionableWith(i_3_5()));
assertTrue(i_3_5().isUnionableWith(i_0_9()));
assertTrue(i_3_5().isUnionableWith(i_4_6()));
assertTrue(i_4_6().isUnionableWith(i_4_6()));
assertTrue(i_4_6().isUnionableWith(i_3_5()));
// Contiguous intervals
assertTrue(i_3_5().isUnionableWith(i_6_9()));
assertTrue(i_6_9().isUnionableWith(i_3_5()));
}
@Test(expected = IllegalArgumentException.class)
public void unionFailsOnNonUnionableIntervals() {
i_0_2().union(i_6_9());
}
@Test
public void unionWorksWhenOneIntervalContainsTheOther() {
assertEquals(i_0_9(), i_0_9().union(i_3_5()));
assertEquals(i_0_9(), i_3_5().union(i_0_9()));
}
@Test
public void unionWorksWithASingleInterval() {
assertEquals(i_3_5(), i_3_5().union(i_3_5()).union(i_3_5()));
}
@Test
public void unionWorksWhenOneIntervalIsContiguousWithTheOther() {
Interval1D i = i_0_2().union(i_6_9().union(i_3_5()));
assertEquals(i_0_9(), i);
}
@Test
public void equalsIsStructural() {
Random rng = newRandom();
for (int i = 0; i < RANDOM_ITERATIONS; ++i) {
int a = rng.nextInt(), b = rng.nextInt();
Interval1D int1 = new Interval1D(min(a, b), max(a, b));
Interval1D int2 = new Interval1D(min(a, b), max(a, b));
Interval1D int3 = new Interval1D(min(a, b) + 1, max(a, b) + 1);
assertTrue(int1.equals(int2));
assertFalse(int1.equals(int3));
}
}
@Test
public void hashCodeAndEqualsAreCompatible() {
Random rng = newRandom();
for (int i = 0; i < RANDOM_ITERATIONS; ++i) {
int a = rng.nextInt(), b = rng.nextInt();
int c = rng.nextInt(), d = rng.nextInt();
Interval1D int1 = new Interval1D(min(a, b), max(a, b));
Interval1D int2 = new Interval1D(min(c, d), max(c, d));
Interval1D int3 = new Interval1D(min(c, d), max(c, d));
assertTrue(hashCodeIsCompatibleWithEquals(int1, int2));
assertTrue(hashCodeIsCompatibleWithEquals(int2, int3));
}
}
}

View File

@@ -0,0 +1,227 @@
package ch.epfl.alpano;
import static org.junit.Assert.*;
import java.util.HashMap;
import org.junit.Test;
public class Interval2DTest {
@Test(expected= NullPointerException.class)
public void testInterval2D() {
new Interval2D(null, null);
}
@Test
public void testContains() {
HashMap<int[][], int[]> testValues = new HashMap<int[][], int[]>();
testValues.put(new int[][] { {0,4}, {0,4} }, new int[] {2,4});
testValues.put(new int[][] { {0,0}, {0,0} }, new int[] {0,0});
for (int[][] values : testValues.keySet()){
assertEquals ( true ,
new Interval2D(
new Interval1D(values[0][0], values[0][1]),
new Interval1D(values[1][0], values[1][1])).contains(testValues.get(values)[0],
testValues.get(values)[1])
);
}
testValues = new HashMap<int[][], int[]>();
testValues.put(new int[][] { {0,4}, {0,4} }, new int[] {-1,-1});
testValues.put(new int[][] { {0,0}, {0,0} }, new int[] {0,1});
for (int[][] values : testValues.keySet()){
assertEquals ( false,
new Interval2D(
new Interval1D(values[0][0], values[0][1]),
new Interval1D(values[1][0], values[1][1])).contains(testValues.get(values)[0],
testValues.get(values)[1])
);
}
}
@Test
public void testSize() {
HashMap<int[][], Integer> testValues = new HashMap<int[][], Integer>();
testValues.put(new int[][] { {0,4}, {0,4} }, 25);
testValues.put(new int[][] { {0,0}, {0,0} }, 1);
for (int[][] values : testValues.keySet()){
assertEquals ( (int)testValues.get(values),
new Interval2D(
new Interval1D(values[0][0], values[0][1]),
new Interval1D(values[1][0], values[1][1])).size()
);
}
}
@Test
public void testSizeOfIntersectionWith() {
HashMap<int[][][], Integer> testValues = new HashMap<int[][][], Integer>();
testValues.put( new int[][][] { {{0,5}, {0,5}} , {{4,6},{4,6}} } , 4);
testValues.put( new int[][][] { {{0,0}, {0,0}} , {{-40,40},{-40,40}} } , 1);
testValues.put( new int[][][] { {{0,5}, {0,5}} , {{10,15},{10,15}} } , 0);
for (int[][][] values : testValues.keySet()){
assertEquals ( (int)testValues.get(values),
new Interval2D(
new Interval1D(values[0][0][0], values[0][0][1]),
new Interval1D(values[0][1][0], values[0][1][1])).sizeOfIntersectionWith(
new Interval2D(
new Interval1D(values[1][0][0], values[1][0][1]),
new Interval1D(values[1][1][0], values[1][1][1])))
);
};
}
@Test
public void testBoundingUnion() {
HashMap<int[][][], int[][]> testValues = new HashMap<int[][][], int[][]>();
testValues.put( new int[][][] {{{0,5}, {0,5}} , {{4,6},{4,6}} } , new int[][] {{0,6},{0,6}} );
testValues.put( new int[][][] {{{0,0}, {0,0}} , {{4,6},{4,6}} } , new int[][] {{0,6},{0,6}} );
for (int[][][] values : testValues.keySet()){
assertEquals (true,
new Interval2D(
new Interval1D(values[0][0][0], values[0][0][1]),
new Interval1D(values[0][1][0], values[0][1][1])).boundingUnion(
new Interval2D(
new Interval1D(values[1][0][0], values[1][0][1]),
new Interval1D(values[1][1][0], values[1][1][1]))).equals(
new Interval2D(
new Interval1D(testValues.get(values)[0][0], testValues.get(values)[0][1]),
new Interval1D(testValues.get(values)[1][0], testValues.get(values)[1][1]))
));
};
}
@Test
public void testIsUnionableWith() {
HashMap<int[][][], Boolean> testValues = new HashMap<int[][][], Boolean>();
testValues.put( new int[][][] {{{0,5}, {0,5}} , {{4,6},{4,6}} } ,false);
testValues.put( new int[][][] {{{0,0}, {0,0}} , {{1,6},{1,6}} } , false );
for (int[][][] values : testValues.keySet()){
assertEquals ( true,
testValues.get(values) == new Interval2D(
new Interval1D(values[0][0][0], values[0][0][1]),
new Interval1D(values[0][1][0], values[0][1][1])).isUnionableWith(
new Interval2D(
new Interval1D(values[1][0][0], values[1][0][1]),
new Interval1D(values[1][1][0], values[1][1][1]))));
};
}
@Test(expected = IllegalArgumentException.class)
public void testUnion() {
HashMap<int[][][], int[][]> testValues = new HashMap<int[][][], int[][]>();
testValues.put( new int[][][] {{{0,5}, {0,5}} , {{4,6},{4,6}} } , new int[][] {{4,5},{4,5}} );
testValues.put( new int[][][] {{{-100,-100}, {0,0}} , {{0,0},{100,100}} } , new int[][] {{0,0},{0,0}} );
testValues.put( new int[][][] {{{-100,100}, {0,0}} , {{0,0},{-100,100}} } , new int[][] {{0,0},{0,0}} );
for (int[][][] values : testValues.keySet()){
assertEquals (false,
new Interval2D(
new Interval1D(values[0][0][0], values[0][0][1]),
new Interval1D(values[0][1][0], values[0][1][1])).union(
new Interval2D(
new Interval1D(values[1][0][0], values[1][0][1]),
new Interval1D(values[1][1][0], values[1][1][1]))).equals(
new Interval2D(
new Interval1D(testValues.get(values)[0][0], testValues.get(values)[0][1]),
new Interval1D(testValues.get(values)[1][0], testValues.get(values)[1][1]))
));
};
new Interval2D(
new Interval1D(0, 0),
new Interval1D(0, 0)).union(
new Interval2D(
new Interval1D(1, 1),
new Interval1D(1, 1)));
}
@Test
public void testEqualsObject() {
HashMap<int[][][], Boolean> testValues = new HashMap<int[][][], Boolean>();
testValues.put( new int[][][] {{{0,5}, {0,5}} , {{0,5},{0,5}} } ,true );
testValues.put( new int[][][] {{{0,5}, {0,5}} , {{0,5},{0,6}} } , false );
for (int[][][] values : testValues.keySet()){
assertEquals ( testValues.get(values) , new Interval2D(
new Interval1D(values[0][0][0], values[0][0][1]),
new Interval1D(values[0][1][0], values[0][1][1])).equals(
new Interval2D(
new Interval1D(values[1][0][0], values[1][0][1]),
new Interval1D(values[1][1][0], values[1][1][1]))) );
};
}
@Test
public void testToString() {
HashMap<int[][], String> testValues = new HashMap<int[][], String>();
testValues.put(new int[][] { {0,4}, {0,4} }, "[0..4]x[0..4]");
for (int[][] values : testValues.keySet()){
assertEquals (testValues.get(values),
new Interval2D(
new Interval1D(values[0][0], values[0][1]),
new Interval1D(values[1][0], values[1][1])).toString()
);
}
}
}

View File

@@ -0,0 +1,209 @@
package ch.epfl.alpano;
import static ch.epfl.test.ObjectTest.hashCodeIsCompatibleWithEquals;
import static ch.epfl.test.TestRandomizer.RANDOM_ITERATIONS;
import static ch.epfl.test.TestRandomizer.newRandom;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import java.util.Random;
import org.junit.Test;
public class Interval2DTestP {
private static Interval2D newInterval2D(int x1, int x2, int y1, int y2) {
return new Interval2D(new Interval1D(x1, x2), new Interval1D(y1, y2));
}
private static Interval2D i_0_10_0_10() {
return newInterval2D(0, 10, 0, 10);
}
private static Interval2D i_0_9_0_11() {
return newInterval2D(0, 9, 0, 11);
}
private static Interval2D i_0_10_11_20() {
return newInterval2D(0, 10, 11, 20);
}
private static Interval2D i_0_10_0_20() {
return newInterval2D(0, 10, 0, 20);
}
private static Interval2D i_11_20_0_10() {
return newInterval2D(11, 20, 0, 10);
}
private static Interval2D i_0_20_0_10() {
return newInterval2D(0, 20, 0, 10);
}
private static Interval2D i_2_2_2_2() {
return newInterval2D(2, 2, 2, 2);
}
@Test(expected = NullPointerException.class)
public void constructorFailsOnInvalidInterval() {
new Interval2D(null, null);
}
@Test
public void containsWorksOnKnownIntervals() {
Interval2D i = i_2_2_2_2();
for (int x = 1; x <= 3; ++x) {
for (int y = 1; y <= 3; ++y) {
assertEquals(x == 2 && y == 2, i.contains(x, y));
}
}
}
@Test
public void sizeWorksOnKnownIntervals() {
assertEquals(1, i_2_2_2_2().size());
assertEquals(21 * 11, i_0_20_0_10().size());
assertEquals(10 * 11, i_11_20_0_10().size());
}
@Test
public void sizeOfIntersectionWorksOnNonIntersectingIntervals() {
assertEquals(0, i_2_2_2_2().sizeOfIntersectionWith(i_11_20_0_10()));
assertEquals(0, i_11_20_0_10().sizeOfIntersectionWith(i_2_2_2_2()));
}
@Test
public void sizeOfIntersectionWorksOnIntersectingIntervals() {
assertEquals(1, i_2_2_2_2().sizeOfIntersectionWith(i_2_2_2_2()));
assertEquals(21 * 11, i_0_20_0_10().sizeOfIntersectionWith(i_0_20_0_10()));
assertEquals(1, i_2_2_2_2().sizeOfIntersectionWith(i_0_20_0_10()));
assertEquals(1, i_0_20_0_10().sizeOfIntersectionWith(i_2_2_2_2()));
assertEquals(10 * 11, i_0_10_0_10().sizeOfIntersectionWith(i_0_9_0_11()));
}
@Test
public void boudingUnionWorksOnKnownIntervals() {
assertEquals(i_2_2_2_2(), i_2_2_2_2().boundingUnion(i_2_2_2_2()));
Interval2D i1 = i_0_10_0_10().boundingUnion(i_0_9_0_11());
assertEquals(0, i1.iX().includedFrom());
assertEquals(10, i1.iX().includedTo());
assertEquals(0, i1.iY().includedFrom());
assertEquals(11, i1.iY().includedTo());
Interval2D i2 = i_2_2_2_2().boundingUnion(i_11_20_0_10());
assertEquals(2, i2.iX().includedFrom());
assertEquals(20, i2.iX().includedTo());
assertEquals(0, i2.iY().includedFrom());
assertEquals(10, i2.iY().includedTo());
}
@Test
public void isUnionableWorksOnKnownUnionableIntervals() {
assertTrue(i_0_10_0_10().isUnionableWith(i_0_10_0_10()));
assertTrue(i_0_10_0_10().isUnionableWith(i_0_10_11_20()));
assertTrue(i_0_10_11_20().isUnionableWith(i_0_10_0_10()));
assertTrue(i_0_10_0_10().isUnionableWith(i_11_20_0_10()));
assertTrue(i_11_20_0_10().isUnionableWith(i_0_10_0_10()));
assertTrue(i_0_10_0_10().isUnionableWith(i_2_2_2_2()));
assertTrue(i_2_2_2_2().isUnionableWith(i_0_10_0_10()));
}
@Test
public void isUnionableWorksOnKnownNonUnionableIntervals() {
assertFalse(i_2_2_2_2().isUnionableWith(i_11_20_0_10()));
assertFalse(i_11_20_0_10().isUnionableWith(i_2_2_2_2()));
assertFalse(i_0_9_0_11().isUnionableWith(i_0_10_0_10()));
assertFalse(i_0_10_0_10().isUnionableWith(i_0_9_0_11()));
}
@Test
public void isUnionableWithIsReflexive() {
Random rng = newRandom();
for (int i = 0; i < RANDOM_ITERATIONS; ++i) {
Interval2D interval = nextInterval(rng, 500, 1000);
assertTrue(interval.isUnionableWith(interval));
}
}
@Test
public void isUnionableWithIsSymmetric() {
Random rng = newRandom();
for (int i = 0; i < RANDOM_ITERATIONS; ++i) {
Interval2D i1 = nextInterval(rng, 5, 10);
Interval2D i2 = nextInterval(rng, 5, 10);
assertTrue(! i1.isUnionableWith(i2) || i2.isUnionableWith(i1));
}
}
@Test(expected = IllegalArgumentException.class)
public void unionFailsOnNonUnionableIntervals() {
i_2_2_2_2().union(i_11_20_0_10());
}
@Test
public void unionWorksOnASingleInterval() {
assertEquals(i_0_10_0_10(), i_0_10_0_10().union(i_0_10_0_10().union(i_0_10_0_10())));
}
@Test
public void unionWorksOnKnownIntervals() {
assertEquals(i_0_10_0_10(), i_0_10_0_10().union(i_2_2_2_2()));
assertEquals(i_0_10_0_10(), i_2_2_2_2().union(i_0_10_0_10()));
assertEquals(i_0_10_0_20(), i_0_10_0_10().union(i_0_10_11_20()));
assertEquals(i_0_10_0_20(), i_0_10_11_20().union(i_0_10_0_10()));
assertEquals(i_0_20_0_10(), i_0_10_0_10().union(i_11_20_0_10()));
assertEquals(i_0_20_0_10(), i_11_20_0_10().union(i_0_10_0_10()));
}
@Test
public void unionIsCommutative() {
Random rng = newRandom();
for (int i = 0; i < RANDOM_ITERATIONS; ++i) {
Interval2D i1 = nextInterval(rng, 5, 10);
Interval2D i2 = nextInterval(rng, 5, 10);
if (i1.isUnionableWith(i2))
assertEquals(i1.union(i2), i2.union(i1));
}
}
@Test
public void equalsIsStructural() {
Random rng = newRandom();
for (int i = 0; i < RANDOM_ITERATIONS; ++i) {
int x1 = rng.nextInt(1000) - 500;
int x2 = x1 + rng.nextInt(1000);
int y1 = rng.nextInt(1000) - 500;
int y2 = y1 + rng.nextInt(1000);
Interval2D int1 = newInterval2D(x1, x2, y1, y2);
Interval2D int2 = newInterval2D(x1, x2, y1, y2);
Interval2D int3 = newInterval2D(x1, x2, y1, y2 + 1);
assertTrue(int1.equals(int2));
assertTrue(int2.equals(int1));
assertFalse(int1.equals(int3));
assertFalse(int3.equals(int1));
}
}
@Test
public void hashCodeAndEqualsAreCompatible() {
Random rng = newRandom();
for (int i = 0; i < RANDOM_ITERATIONS; ++i) {
int a = rng.nextInt(1000) - 500, b = a + rng.nextInt(20);
int c = rng.nextInt(1000) - 500, d = c + rng.nextInt(20);
Interval2D i1 = newInterval2D(a, b, c, d);
Interval2D i1b = newInterval2D(a, b, c, d);
Interval2D i2 = newInterval2D(a, b, c, d + 1);
assertTrue(hashCodeIsCompatibleWithEquals(i1, i1b));
assertTrue(hashCodeIsCompatibleWithEquals(i1, i2));
}
}
private Interval2D nextInterval(Random rng, int maxOffset, int maxSize) {
int offsetX = rng.nextInt(maxOffset), offsetY = rng.nextInt(maxOffset);
int sizeX = rng.nextInt(maxSize), sizeY = rng.nextInt(maxSize);
return newInterval2D(-offsetX, sizeX - offsetX, -offsetY, sizeY - offsetY);
}
}

View File

@@ -0,0 +1,217 @@
package ch.epfl.alpano;
import static ch.epfl.alpano.Math2.angularDistance;
import static ch.epfl.alpano.Math2.bilerp;
import static ch.epfl.alpano.Math2.firstIntervalContainingRoot;
import static ch.epfl.alpano.Math2.floorMod;
import static ch.epfl.alpano.Math2.haversin;
import static ch.epfl.alpano.Math2.improveRoot;
import static ch.epfl.alpano.Math2.lerp;
import static ch.epfl.alpano.Math2.sq;
import static ch.epfl.test.TestRandomizer.RANDOM_ITERATIONS;
import static ch.epfl.test.TestRandomizer.newRandom;
import static java.lang.Math.PI;
import static java.lang.Math.cos;
import static java.lang.Math.floor;
import static java.lang.Math.max;
import static java.lang.Math.min;
import static java.lang.Math.sin;
import static java.lang.Math.toRadians;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
import java.util.Random;
import java.util.function.DoubleUnaryOperator;
import org.junit.Test;
public class Math2Test {
@Test
public void sqSquaresRandomValues() {
Random rng = newRandom();
for (int i = 0; i < RANDOM_ITERATIONS; ++i) {
double x = rng.nextDouble() * 1_000d - 500d;
assertEquals(x * x, sq(x), 1e-10);
}
}
@Test
public void floorModWorksOnRandomValues() {
Random rng = newRandom();
for (int i = 0; i < RANDOM_ITERATIONS; ++i) {
double n = rng.nextDouble() * 1_000d - 500d;
double d = 0;
while (d == 0)
d = rng.nextDouble() * 1_000d - 500d;
double q = (int)floor(n / d);
double r = floorMod(n, d);
assertEquals(n, q * d + r, 1e-10);
}
}
@Test
public void haversinWorksOnRandomAngles() {
Random rng = newRandom();
for (int i = 0; i < RANDOM_ITERATIONS; ++i) {
double a = nextAngle(rng);
double h = (1d - cos(a)) / 2d;
assertEquals(h, haversin(a), 1e-10);
}
}
@Test
public void angularDistanceWorksOnKnownAngles() {
double data[] = {
0, 45, 45,
45, 0, -45,
0, 179, 179,
0, 181, -179,
181, 359, 178,
181, 2, -179
};
for (int i = 0; i < data.length; i += 3) {
double a1 = toRadians(data[i]);
double a2 = toRadians(data[i + 1]);
double expectedD = toRadians(data[i + 2]);
assertEquals(expectedD, angularDistance(a1, a2), 1e-10);
}
}
@Test
public void angularDistanceIsInExpectedRange() {
Random rng = newRandom();
for (int i = 0; i < RANDOM_ITERATIONS; ++i) {
double a1 = nextAngle(rng);
double a2 = nextAngle(rng);
double d = angularDistance(a1, a2);
assertTrue(-PI <= d && d < PI);
}
}
@Test
public void angularDistanceIsSymmetric() {
Random rng = newRandom();
for (int i = 0; i < RANDOM_ITERATIONS; ++i) {
double a1 = nextAngle(rng);
double a2 = nextAngle(rng);
assertEquals(0, angularDistance(a1, a2) + angularDistance(a2, a1), 1e-10);
}
}
@Test
public void lerpIsFirstValueAtStart() {
Random rng = newRandom();
for (int i = 0; i < RANDOM_ITERATIONS; ++i) {
double v1 = (rng.nextDouble() - 0.5) * 1000d;
double v2 = (rng.nextDouble() - 0.5) * 1000d;
assertEquals(v1, lerp(v1, v2, 0), 1e-10);
}
}
@Test
public void lerpIsAverageValueAtMiddle() {
Random rng = newRandom();
for (int i = 0; i < RANDOM_ITERATIONS; ++i) {
double v1 = (rng.nextDouble() - 0.5) * 1000d;
double v2 = (rng.nextDouble() - 0.5) * 1000d;
assertEquals((v1 + v2) / 2d, lerp(v1, v2, 0.5), 1e-10);
}
}
@Test
public void lerpIsSecondValueAtEnd() {
Random rng = newRandom();
for (int i = 0; i < RANDOM_ITERATIONS; ++i) {
double v1 = (rng.nextDouble() - 0.5) * 1000d;
double v2 = (rng.nextDouble() - 0.5) * 1000d;
assertEquals(v2, lerp(v1, v2, 1), 1e-10);
}
}
@Test
public void lerpIsInExpectedRange() {
Random rng = newRandom();
for (int i = 0; i < RANDOM_ITERATIONS; ++i) {
double v1 = (rng.nextDouble() - 0.5) * 1000d;
double v2 = (rng.nextDouble() - 0.5) * 1000d;
double p = rng.nextDouble();
double v = lerp(v1, v2, p);
assertTrue(min(v1, v2) <= v && v <= max(v1, v2));
}
}
@Test
public void bilerpIsInExpectedRange() {
Random rng = newRandom();
for (int i = 0; i < RANDOM_ITERATIONS; ++i) {
double v1 = (rng.nextDouble() - 0.5) * 1000d;
double v2 = (rng.nextDouble() - 0.5) * 1000d;
double v3 = (rng.nextDouble() - 0.5) * 1000d;
double v4 = (rng.nextDouble() - 0.5) * 1000d;
double x = rng.nextDouble(), y = rng.nextDouble();
double v = bilerp(v1, v2, v3, v4, x, y);
assertTrue(min(min(v1, v2), min(v3, v4)) <= v
&& v <= max(max(v1, v2), max(v3, v4)));
}
}
@Test
public void bilerpIsCorrectInCorners() {
Random rng = newRandom();
for (int i = 0; i < RANDOM_ITERATIONS; ++i) {
double v0 = rng.nextDouble(), v1 = rng.nextDouble();
double v2 = rng.nextDouble(), v3 = rng.nextDouble();
assertEquals(v0, bilerp(v0, v1, v2, v3, 0, 0), 1e-10);
assertEquals(v1, bilerp(v1, v1, v2, v3, 1, 0), 1e-10);
assertEquals(v2, bilerp(v2, v1, v2, v3, 0, 1), 1e-10);
assertEquals(v3, bilerp(v3, v1, v2, v3, 1, 1), 1e-10);
}
}
@Test
public void bilerpLerpsAlongSides() {
Random rng = newRandom();
for (int i = 0; i < RANDOM_ITERATIONS; ++i) {
double v0 = rng.nextDouble(), v1 = rng.nextDouble();
double v2 = rng.nextDouble(), v3 = rng.nextDouble();
assertEquals((v0 + v1)/2d, bilerp(v0, v1, v2, v3, 0.5, 0), 1e-10);
assertEquals((v0 + v2)/2d, bilerp(v0, v1, v2, v3, 0, 0.5), 1e-10);
assertEquals((v2 + v3)/2d, bilerp(v0, v1, v2, v3, 0.5, 1), 1e-10);
assertEquals((v1 + v3)/2d, bilerp(v0, v1, v2, v3, 1, 0.5), 1e-10);
}
}
@Test
public void firstIntervalContainingRootWorksOnSin() {
double i1 = firstIntervalContainingRoot(new Sin(), -1d, 1d, 0.1 + 1e-11);
assertEquals(-0.1, i1, 1e-10);
double i2 = firstIntervalContainingRoot(new Sin(), 1, 4, 1);
assertEquals(3, i2, 0);
}
@Test(expected = IllegalArgumentException.class)
public void improveRootFailsWhenIntervalDoesNotContainRoot() {
improveRoot(new Sin(), 1, 2, 1e-10);
}
@Test
public void improveRootWorksOnSin() {
double pi = improveRoot(new Sin(), 3.1, 3.2, 1e-10);
assertEquals(PI, pi, 1e-10);
double mPi = improveRoot(new Sin(), -4, -3.1, 1e-10);
assertEquals(-PI, mPi, 1e-10);
}
private static double nextAngle(Random rng) {
return rng.nextDouble() * 2d * PI;
}
}
class Sin implements DoubleUnaryOperator {
@Override
public double applyAsDouble(double x) {
return sin(x);
}
}

View File

@@ -0,0 +1,45 @@
package ch.epfl.alpano;
import static org.junit.Assert.*;
import org.junit.Test;
import ch.epfl.alpano.dem.ContinuousElevationModel;
import ch.epfl.alpano.dem.ElevationProfile;
public class PanoramaCompTest {
@Test(expected = NullPointerException.class)
public void throwsNullPointerUponConstruction(){
new PanoramaComputer(null);
}
@Test
public void givesTrivialZero(){
double zero =PanoramaComputer.rayToGroundDistance(
new ElevationProfile( new ContinuousElevationModel(new TestDemForPanoramaComp(new Interval2D(new Interval1D(-100, 100),
new Interval1D(-100, 100)))),
new GeoPoint(0,0),2.5,100), 0.0, 0.0).applyAsDouble(
1);
assertEquals(0, zero,0.01);
}
@Test(expected = IllegalArgumentException.class)
public void throwsIllegalArgumentExceptionOnNegValues(){
double zero =PanoramaComputer.rayToGroundDistance(
new ElevationProfile( new ContinuousElevationModel(new TestDemForPanoramaComp(new Interval2D(new Interval1D(-100, 100),
new Interval1D(-100, 100)))),
new GeoPoint(0,0),0,100), 0.0, 1.0).applyAsDouble(
-50);
assertEquals(0, zero,0);
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,95 @@
package ch.epfl.alpano;
import static org.junit.Assert.*;
import org.junit.Test;
public class PanoramaParametersTest {
private GeoPoint vp = new GeoPoint(Math.toRadians(6.8087),Math.toRadians(47.0085));
private PanoramaParameters pp = new PanoramaParameters(vp, 1380, Math.toRadians(162),
Math.toRadians(27), 300, 2500, 800);
@Test
public void testAzimuthForX() {
assertEquals(pp.azimuthForX(1),Math.toRadians(148.5108043217287),0.000001);
}
@Test
public void testXForAzimuth() {
assertEquals(pp.xForAzimuth(pp.azimuthForX(1)),1,0.000000001);
}
@Test(expected = IllegalArgumentException.class)
public void testXForAzimuthFails() {
pp.xForAzimuth(Math.toRadians(27-81.5));
}
@Test
public void testAltitudeForY() {
assertEquals(pp.altitudeForY(0),Math.toRadians(4.316326530612245),0.00000001);
}
@Test
public void testYForAltitude() {
assertEquals(pp.yForAltitude(pp.altitudeForY(1)),1,0.000000001);
}
@Test
public void testIsValidSampleIndexFails1() {
assertEquals(pp.isValidSampleIndex(2500, 800),false);
}
@Test
public void testIsValidSampleIndexFails2() {
assertEquals(pp.isValidSampleIndex(-1, -1),false);
}
@Test
public void testLinearSampleIndexSucces() {
assertEquals(pp.linearSampleIndex(0, 0),0);
assertEquals(pp.linearSampleIndex(2500-1, 800-1),(2500*800)-1);
}
@Test
public void testObserverPosition() {
assertEquals(pp.observerPosition(),vp);
}
@Test
public void testObserverElevation() {
assertEquals(pp.observerElevation(),1380,0);
}
@Test
public void testCenterAzimuth() {
assertEquals(pp.centerAzimuth(),Math.toRadians(162),0.00000001);
}
@Test
public void testHorizontalFieldOfView() {
assertEquals(pp.horizontalFieldOfView(),Math.toRadians(27),0.0000001);
}
@Test
public void testVerticalFieldOfView() {
assertEquals(pp.verticalFieldOfView(),Math.toRadians(8.63265306122),0.000000001);
}
@Test
public void testMaxDistance() {
assertEquals(pp.maxDistance(),300,0);
}
@Test
public void testWidth() {
assertEquals(pp.width(),2500,0);
}
@Test
public void testHeight() {
assertEquals(pp.height(),800,0);
}
}

View File

@@ -0,0 +1,167 @@
package ch.epfl.alpano;
import static ch.epfl.test.TestRandomizer.RANDOM_ITERATIONS;
import static ch.epfl.test.TestRandomizer.newRandom;
import static java.lang.Math.PI;
import static java.lang.Math.floorMod;
import static java.lang.Math.nextUp;
import static java.lang.Math.toRadians;
import static org.junit.Assert.assertEquals;
import java.util.Random;
import org.junit.Test;
public class PanoramaParametersTestP {
// Default (and valid) arguments for constructor
private static GeoPoint O_POS() { return new GeoPoint(toRadians(4), toRadians(4)); }
private static int O_EL = 1000;
private static double C_AZ = toRadians(180);
private static double H_FOV = toRadians(60);
private static int MAX_D = 1000;
private static int W = 100, H = 100;
@Test(expected = NullPointerException.class)
public void constructorFailsWithNullObserverPosition() {
new PanoramaParameters(null, O_EL, C_AZ, H_FOV, MAX_D, W, H);
}
@Test(expected = IllegalArgumentException.class)
public void constructorFailsWithNonCanonicalAzimuth() {
new PanoramaParameters(O_POS(), O_EL, 42d, H_FOV, MAX_D, W, H);
}
@Test(expected = IllegalArgumentException.class)
public void constructorFailsWithZeroFieldOfView() {
new PanoramaParameters(O_POS(), O_EL, C_AZ, 0, MAX_D, W, H);
}
@Test(expected = IllegalArgumentException.class)
public void constructorFailsWithTooLargeOfView() {
new PanoramaParameters(O_POS(), O_EL, C_AZ, nextUp(2d * PI), MAX_D, W, H);
}
@Test(expected = IllegalArgumentException.class)
public void constructorFailsWithZeroWidth() {
new PanoramaParameters(O_POS(), O_EL, C_AZ, H_FOV, MAX_D, 0, H);
}
@Test(expected = IllegalArgumentException.class)
public void constructorFailsWithZeroHeight() {
new PanoramaParameters(O_POS(), O_EL, C_AZ, H_FOV, MAX_D, W, 0);
}
@Test(expected = IllegalArgumentException.class)
public void constructorFailsWithZeroMaxDistance() {
new PanoramaParameters(O_POS(), O_EL, C_AZ, H_FOV, 0, W, H);
}
@Test
public void verticalFieldOfViewIsCorrect() {
PanoramaParameters p =
new PanoramaParameters(O_POS(), O_EL, C_AZ, toRadians(60), MAX_D, 601, 201);
assertEquals(p.verticalFieldOfView(), toRadians(20), 1e-10);
}
@Test(expected = IllegalArgumentException.class)
public void azimuthForXFailsForNegativeX() {
PanoramaParameters p =
new PanoramaParameters(O_POS(), O_EL, C_AZ, H_FOV, MAX_D, W, H);
p.azimuthForX(-1);
}
@Test(expected = IllegalArgumentException.class)
public void azimuthForXFailsForTooBigX() {
PanoramaParameters p =
new PanoramaParameters(O_POS(), O_EL, C_AZ, H_FOV, MAX_D, W, H);
p.azimuthForX(W + 1);
}
@Test
public void azimuthForXWorksForFullCircle() {
int centralAzDeg = 90;
PanoramaParameters p =
new PanoramaParameters(O_POS(), O_EL, toRadians(centralAzDeg), Math2.PI2, MAX_D, 361, 201);
for (int azDeg = 0; azDeg < 360; ++azDeg) {
double expectedAz = toRadians(floorMod(azDeg - centralAzDeg, 360));
double actualAz = p.azimuthForX(azDeg);
assertEquals(expectedAz, actualAz, 1e-10);
}
}
@Test(expected = IllegalArgumentException.class)
public void xForAzimuthFailsForTooSmallAzimuth() {
PanoramaParameters p =
new PanoramaParameters(O_POS(), O_EL, toRadians(10), toRadians(40), MAX_D, W, H);
p.xForAzimuth(toRadians(349.99));
}
@Test(expected = IllegalArgumentException.class)
public void xForAzimuthFailsForTooBigAzimuth() {
PanoramaParameters p =
new PanoramaParameters(O_POS(), O_EL, toRadians(10), toRadians(40), MAX_D, W, H);
p.xForAzimuth(toRadians(50.01));
}
@Test(expected = IllegalArgumentException.class)
public void altitudeForYFailsForNegativeY() {
PanoramaParameters p =
new PanoramaParameters(O_POS(), O_EL, C_AZ, H_FOV, MAX_D, W, H);
p.altitudeForY(-1);
}
@Test(expected = IllegalArgumentException.class)
public void altitueForYFailsForTooBigY() {
PanoramaParameters p =
new PanoramaParameters(O_POS(), O_EL, C_AZ, H_FOV, MAX_D, W, H);
p.altitudeForY(H + 1);
}
@Test
public void altitudeForYWorks() {
int height = 201;
PanoramaParameters p =
new PanoramaParameters(O_POS(), O_EL, C_AZ, toRadians(60), MAX_D, 601, height);
double halfVerticalFOV = toRadians(20) / 2d;
double delta = toRadians(0.1);
for (int y = 0; y < height; ++y) {
assertEquals(halfVerticalFOV - y * delta, p.altitudeForY(y), 1e-9);
}
}
@Test(expected = IllegalArgumentException.class)
public void yForAltitudeFailsForTooSmallAltitude() {
PanoramaParameters p =
new PanoramaParameters(O_POS(), O_EL, C_AZ, toRadians(60), MAX_D, 601, 201);
p.yForAltitude(toRadians(-10.01));
}
@Test(expected = IllegalArgumentException.class)
public void yForAltitudeFailsForTooBigAltitude() {
PanoramaParameters p =
new PanoramaParameters(O_POS(), O_EL, C_AZ, toRadians(60), MAX_D, 601, 201);
p.yForAltitude(toRadians(10.01));
}
@Test
public void azimuthForXAndXForAzimuthAreInverse() {
PanoramaParameters p =
new PanoramaParameters(O_POS(), O_EL, C_AZ, toRadians(60), MAX_D, 601, 201);
Random rng = newRandom();
for (int i = 0; i < RANDOM_ITERATIONS; ++i) {
int x = 1 + rng.nextInt(600);
assertEquals(x, p.xForAzimuth(p.azimuthForX(x)), 1e-10);
}
}
@Test
public void altitudeForYAndYForAltitudeAreInverse() {
PanoramaParameters p =
new PanoramaParameters(O_POS(), O_EL, C_AZ, toRadians(60), MAX_D, 601, 201);
Random rng = newRandom();
for (int i = 0; i < RANDOM_ITERATIONS; ++i) {
int x = 1 + rng.nextInt(200);
assertEquals(x, p.yForAltitude(p.altitudeForY(x)), 1e-10);
}
}
}

View File

@@ -0,0 +1,104 @@
package ch.epfl.alpano;
import static ch.epfl.test.TestRandomizer.newRandom;
import static java.lang.Math.toRadians;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertSame;
import java.util.Random;
import org.junit.Test;
public class PanoramaTestP{
private static PanoramaParameters PARAMS() {
return new PanoramaParameters(
new GeoPoint(toRadians(46), toRadians(6)),
1000,
toRadians(180),
toRadians(60),
100_000,
9,
7);
}
@Test(expected = NullPointerException.class)
public void builderFailsWithNullParameters() {
new Panorama.Builder(null);
}
@Test
public void builderConstructorCorrectlyInitializesSamples() {
Panorama p = new Panorama.Builder(PARAMS()).build();
assertEquals(Float.POSITIVE_INFINITY, p.distanceAt(0, 0), 0);
assertEquals(0, p.longitudeAt(0, 0), 0);
assertEquals(0, p.latitudeAt(0, 0), 0);
assertEquals(0, p.elevationAt(0, 0), 0);
assertEquals(0, p.slopeAt(0, 0), 0);
}
@Test(expected = IndexOutOfBoundsException.class)
public void setDistanceAtFailsWithInvalidIndex() {
Panorama.Builder b = new Panorama.Builder(PARAMS());
b.setDistanceAt(10, 0, 1);
}
@Test
public void setLongitudeAtReturnsThis() {
Panorama.Builder b = new Panorama.Builder(PARAMS());
assertSame(b, b.setLongitudeAt(0, 0, 1));
}
@Test(expected = IllegalStateException.class)
public void setSlopeAtFailsAfterBuild() {
Panorama.Builder b = new Panorama.Builder(PARAMS());
b.build();
b.setSlopeAt(0, 0, 0);
}
@Test(expected = IllegalStateException.class)
public void buildFailsAfterBuild() {
Panorama.Builder b = new Panorama.Builder(PARAMS());
b.build();
b.build();
}
@Test
public void parametersReturnsParameters() {
PanoramaParameters ps = PARAMS();
Panorama p = new Panorama.Builder(ps).build();
assertSame(ps, p.parameters());
}
@Test
public void builderSettersWork() {
PanoramaParameters ps = PARAMS();
float[] values = new float[ps.width() * ps.height()];
Random rng = newRandom();
for (int i = 0; i < values.length; ++i)
values[i] = rng.nextFloat() + 0.5f;
Panorama.Builder b = new Panorama.Builder(ps);
for (int x = 0; x < ps.width(); ++x) {
for (int y = 0; y < ps.height(); ++y) {
float v = values[y + x * ps.height()];
b.setDistanceAt(x, y, v)
.setElevationAt(x, y, v)
.setLatitudeAt(x, y, v)
.setLongitudeAt(x, y, v)
.setSlopeAt(x, y, v);
}
}
Panorama p = b.build();
for (int x = 0; x < ps.width(); ++x) {
for (int y = 0; y < ps.height(); ++y) {
float v = values[y + x * ps.height()];
assertEquals(v, p.distanceAt(x, y), 0);
assertEquals(v, p.elevationAt(x, y), 0);
assertEquals(v, p.latitudeAt(x, y), 0);
assertEquals(v, p.longitudeAt(x, y), 0);
assertEquals(v, p.slopeAt(x, y), 0);
}
}
}
}

View File

@@ -0,0 +1,47 @@
package ch.epfl.alpano;
import static ch.epfl.alpano.Preconditions.*;
import org.junit.Test;
public class PreconditionsTest {
////////// checkArgument (1 argument)
@Test
public void checkArgument1SucceedsForTrue() {
checkArgument(true);
}
@Test(expected = IllegalArgumentException.class)
public void checkArgument1ThrowsForFalse() {
checkArgument(false);
}
////////// checkArgument (2 arguments)
@Test
public void checkArgument2SucceedsForTrue() {
checkArgument(true, "");
}
@Test(expected = IllegalArgumentException.class)
public void checkArgument2ThrowsForFalse() {
checkArgument(false, "");
}
////////// checkNonNul (1 arguments)
@Test
public void checkNonNulSuccess() {
checkNonNul(1, "");
}
@Test(expected = NullPointerException.class)
public void checkNonNulThrowsForZero() {
checkNonNul(0, "");
}
////////// checkNonNul (1 arguments)
}

View File

@@ -0,0 +1,26 @@
package ch.epfl.alpano;
import ch.epfl.alpano.dem.DiscreteElevationModel;
public class TestDemForPanoramaComp implements DiscreteElevationModel {
private final Interval2D extent;
public TestDemForPanoramaComp(Interval2D extent) {
this.extent = extent;
}
@Override
public void close() throws Exception { }
@Override
public Interval2D extent() { return extent; }
@Override
public double elevationSample(int x, int y) {
return x*x-y*y;
}
}

View File

@@ -0,0 +1,117 @@
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.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.Interval1D;
import ch.epfl.alpano.Interval2D;
public class CompositeDiscreteElevationModelTest {
private final static Interval2D ext1 = new Interval2D(
new Interval1D(-100_000, 100_000),
new Interval1D(0, 100_000));
private final static Interval2D ext2 = new Interval2D(
new Interval1D(-100_000, 100_000),
new Interval1D(100_001, 200_000));
private final static Interval2D ext12 = new Interval2D(
new Interval1D(-100_000, 100_000),
new Interval1D(0, 200_000));
private final static Interval2D ext3 = new Interval2D(
new Interval1D(0, 99_999),
new Interval1D(0, 100_001));
@Test
public void samplesPerRadiansHasCorrectValue() {
assertEquals(206264.80624709636, DiscreteElevationModel.SAMPLES_PER_RADIAN, 1e-8);
}
@Test
public void sampleIndexWorksOnRandomValues() {
Random rng = newRandom();
for (int i = 0; i < RANDOM_ITERATIONS; ++i) {
int arcSeconds = rng.nextInt(2_000_000) - 1_000_000;
double angle = toRadians(arcSeconds / 3_600d);
assertEquals(arcSeconds, DiscreteElevationModel.sampleIndex(angle), 1e-5);
}
}
@SuppressWarnings("resource")
@Test(expected = IllegalArgumentException.class)
public void unionFailsIfExtentsNotUnionable() {
ConstantElevationDEM dem1 = new ConstantElevationDEM(ext1, 0);
ConstantElevationDEM dem2 = new ConstantElevationDEM(ext3, 0);
dem1.union(dem2);
}
@SuppressWarnings("resource")
@Test
public void extentOfUnionIsUnionOfExtent() {
ConstantElevationDEM dem1 = new ConstantElevationDEM(ext1, 0);
ConstantElevationDEM dem2 = new ConstantElevationDEM(ext2, 0);
DiscreteElevationModel dem12 = dem1.union(dem2);
assertEquals(ext12, dem12.extent());
}
@SuppressWarnings("resource")
@Test(expected = IllegalArgumentException.class)
public void elevationSampleFailsWhenOutsideOfExtent() {
ConstantElevationDEM dem1 = new ConstantElevationDEM(ext1, 0);
ConstantElevationDEM dem2 = new ConstantElevationDEM(ext2, 0);
DiscreteElevationModel dem12 = dem1.union(dem2);
dem12.elevationSample(0, 200_001);
}
@SuppressWarnings("resource")
@Test
public void elevationSampleWorksOnBothSubDEMs() {
ConstantElevationDEM dem1 = new ConstantElevationDEM(ext1, 1);
ConstantElevationDEM dem2 = new ConstantElevationDEM(ext2, 2);
DiscreteElevationModel dem12 = dem1.union(dem2);
assertEquals(1, dem12.elevationSample(-100_000, 0), 0);
assertEquals(1, dem12.elevationSample(100_000, 0), 0);
assertEquals(1, dem12.elevationSample(100_000, 100_000), 0);
assertEquals(1, dem12.elevationSample(-100_000, 100_000), 0);
assertEquals(2, dem12.elevationSample(-100_000, 100_001), 0);
assertEquals(2, dem12.elevationSample(100_000, 100_001), 0);
assertEquals(2, dem12.elevationSample(100_000, 200_000), 0);
assertEquals(2, dem12.elevationSample(-100_000, 200_000), 0);
}
@SuppressWarnings("resource")
@Test
public void closeClosesBothSubDEMs() throws Exception {
ConstantElevationDEM dem1 = new ConstantElevationDEM(ext1, 0);
ConstantElevationDEM dem2 = new ConstantElevationDEM(ext2, 0);
DiscreteElevationModel dem12 = dem1.union(dem2);
dem12.close();
assertTrue(dem1.isClosed);
assertTrue(dem2.isClosed);
}
}
class ConstantElevationDEM implements DiscreteElevationModel {
private final Interval2D extent;
private final double elevation;
boolean isClosed = false;
public ConstantElevationDEM(Interval2D extent, double elevation) {
this.extent = extent;
this.elevation = elevation;
}
@Override
public void close() throws Exception { isClosed = true; }
@Override
public Interval2D extent() { return extent; }
@Override
public double elevationSample(int x, int y) { return elevation; }
}

View File

@@ -0,0 +1,170 @@
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 {}
}

View File

@@ -0,0 +1,70 @@
package ch.epfl.alpano.dem;
import static java.lang.Math.toRadians;
import java.awt.image.BufferedImage;
import java.io.File;
import java.util.ArrayList;
import java.util.Arrays;
import javax.imageio.ImageIO;
import ch.epfl.alpano.GeoPoint;
final class DrawElevationProfile {
final static File HGT_FILE = new File("HGT"+File.separatorChar+"N46E006.hgt");
final static double MAX_ELEVATION = 1_500;
final static int LENGTH = 111_000;
final static double AZIMUTH = toRadians(27.97);
final static double LONGITUDE = toRadians(6.15432);
final static double LATITUDE = toRadians(46.20562);
final static int WIDTH = 800, HEIGHT = 100;
public static void main(String[] as) throws Exception {
DiscreteElevationModel dDEM =
new HgtDiscreteElevationModel(HGT_FILE);
ContinuousElevationModel cDEM =
new ContinuousElevationModel(dDEM);
GeoPoint o =
new GeoPoint(LONGITUDE, LATITUDE);
ElevationProfile p1 =
new ElevationProfile(cDEM, o, AZIMUTH, (int)(LENGTH/3));
GeoPoint gP1 = p1.positionAt((int)LENGTH/3);
ElevationProfile p2 =
new ElevationProfile(cDEM, p1.positionAt((int)LENGTH/3), AZIMUTH+toRadians(6.0),2*((int)LENGTH/3));
GeoPoint gP2 = p2.positionAt(2*((int)LENGTH/3));
ElevationProfile p3 = new ElevationProfile (cDEM,p2.positionAt(2*((int)LENGTH/3)), AZIMUTH, LENGTH);
ArrayList<GeoPoint> trekkingSpots = new ArrayList<GeoPoint>(Arrays.asList(o,gP1,gP2));
ArrayList<ElevationProfile> profiles= new ArrayList<ElevationProfile>();
for (int index = 0; index < trekkingSpots.size()-1; index++){
GeoPoint current= trekkingSpots.get(index);
GeoPoint next = trekkingSpots.get(index+1);
ElevationProfile evP= new ElevationProfile(cDEM, current,current.azimuthTo(next), current.distanceTo(next));
profiles.add(evP);
}
CompositElevationProfile p = new CompositElevationProfile(profiles);
int BLACK = 0x00_00_00, WHITE = 0xFF_FF_FF;
BufferedImage i =
new BufferedImage(WIDTH, HEIGHT, BufferedImage.TYPE_INT_RGB);
for (int x = 0; x < WIDTH; ++x) {
double pX = x * (double) LENGTH / (WIDTH - 1);
double pY = p.elevationAt(pX);
int yL = (int)((pY / MAX_ELEVATION) * (HEIGHT - 1));
for (int y = 0; y < HEIGHT; ++y) {
int color = y < yL ? BLACK : WHITE;
i.setRGB(x, HEIGHT - 1 - y, color);
}
}
dDEM.close();
ImageIO.write(i, "png", new File("tests/ch/epfl/alpano/dem/profile.png"));
}
}

View File

@@ -0,0 +1,83 @@
package ch.epfl.alpano.dem;
import static java.lang.Math.max;
import static java.lang.Math.min;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import javax.imageio.ImageIO;
import ch.epfl.alpano.GeoPoint;
import static java.lang.Math.toRadians;
final class DrawHgtDEM {
final static File HGT_FILE = new File("HGT"+File.separatorChar+"N46E006.hgt");
final static double ORIGIN_LON = toRadians(6.25);
final static double ORIGIN_LAT = toRadians(46.25);
final static double WIDTH = toRadians(0.5);
final static int IMAGE_SIZE = 300;
final static double MIN_ELEVATION = 200;
final static double MAX_ELEVATION = 1_500;
public static void main(String[] as) throws Exception {
DiscreteElevationModel dDEM =
new HgtDiscreteElevationModel(HGT_FILE);
ContinuousElevationModel cDEM =
new ContinuousElevationModel(dDEM);
double step = WIDTH / (IMAGE_SIZE - 1);
BufferedImage i = new BufferedImage(IMAGE_SIZE,
IMAGE_SIZE,
BufferedImage.TYPE_INT_RGB);
for (int x = 0; x < IMAGE_SIZE; ++x) {
double lon = ORIGIN_LON + x * step;
for (int y = 0; y < IMAGE_SIZE; ++y) {
double lat = ORIGIN_LAT + y * step;
GeoPoint p = new GeoPoint(lon, lat);
double el =
(cDEM.elevationAt(p) - MIN_ELEVATION)
/ (MAX_ELEVATION - MIN_ELEVATION);
i.setRGB(x, IMAGE_SIZE - 1 - y, gray(el));
}
}
dDEM.close();
ImageIO.write(i, "png", new File("tests/ch/epfl/alpano/dem/dem.png"));
}
public static void drawDem(ContinuousElevationModel cDem){
double step = WIDTH / (IMAGE_SIZE - 1);
BufferedImage i = new BufferedImage(IMAGE_SIZE,
IMAGE_SIZE,
BufferedImage.TYPE_INT_RGB);
for (int x = 0; x < IMAGE_SIZE; ++x) {
double lon = ORIGIN_LON + x * step;
for (int y = 0; y < IMAGE_SIZE; ++y) {
double lat = ORIGIN_LAT + y * step;
GeoPoint p = new GeoPoint(lon, lat);
double el =
(cDem.elevationAt(p) - MIN_ELEVATION)
/ (MAX_ELEVATION - MIN_ELEVATION);
i.setRGB(x, IMAGE_SIZE - 1 - y, gray(el));
}
}
try {
ImageIO.write(i, "png", new File("tests/ch/epfl/alpano/dem/dem.png"));
} catch (IOException e) {
e.printStackTrace();
}
}
private static int gray(double v) {
double clampedV = max(0, min(v, 1));
int gray = (int) (255.9999 * clampedV);
return (gray << 16) | (gray << 8) | gray;
}
}

View File

@@ -0,0 +1,50 @@
package ch.epfl.alpano.dem;
import static java.lang.Math.max;
import static java.lang.Math.min;
import java.awt.image.BufferedImage;
import java.io.File;
import javax.imageio.ImageIO;
import ch.epfl.alpano.GeoPoint;
import static java.lang.Math.toRadians;
final class DrawHgtDEM2 {
final static double ORIGIN_LON = toRadians(6.0);
final static double ORIGIN_LAT = toRadians(45.0);
final static double WIDTH = toRadians(0.1);
final static int IMAGE_SIZE = 1200;
final static double MIN_ELEVATION = 00;
final static double MAX_ELEVATION = 500;
public static void main(String[] as) throws Exception {
DiscreteElevationModel dDEM = new HgtDiscreteElevationModel(null);
ContinuousElevationModel cDEM =
new ContinuousElevationModel(dDEM);
double step = WIDTH / (IMAGE_SIZE - 1);
BufferedImage i = new BufferedImage(IMAGE_SIZE,
IMAGE_SIZE, BufferedImage.TYPE_INT_RGB);
for (int x = 0; x < IMAGE_SIZE; ++x) {
double lon = ORIGIN_LON + x * step;
for (int y = 0; y < IMAGE_SIZE; ++y) {
double lat = ORIGIN_LAT + y * step;
GeoPoint p = new GeoPoint(lon, lat);
double el =
(cDEM.elevationAt(p) - MIN_ELEVATION)
/ (MAX_ELEVATION - MIN_ELEVATION);
i.setRGB(x, IMAGE_SIZE - 1 - y, gray(el));
}
}
dDEM.close();
ImageIO.write(i, "png", new File("tests/ch/epfl/alpano/dem/dem2.png"));
}
private static int gray(double v) {
double clampedV = max(0, min(v, 1));
int gray = (int) (255.9999 * clampedV);
return (gray << 16) | (gray << 8) | gray;
}
}

View File

@@ -0,0 +1,49 @@
package ch.epfl.alpano.dem;
import static java.lang.Math.toRadians;
import static org.junit.Assert.*;
import java.io.File;
import org.junit.Test;
import ch.epfl.alpano.GeoPoint;
public class ElevationProfileTest {
final static File HGT_FILE = new File("HGT"+File.separatorChar+"N46E006.hgt");
final static double AZIMUTH = toRadians(45.0);
final static double LONGITUDE = toRadians(6.0);
final static double LATITUDE = toRadians(46.0);
final static int LENGTH = 111_000;
@Test
public void testElevationProfile() {
DiscreteElevationModel dDEM =
new HgtDiscreteElevationModel(HGT_FILE);
ContinuousElevationModel cDEM =
new ContinuousElevationModel(dDEM);
GeoPoint o =
new GeoPoint(LONGITUDE, LATITUDE);
ElevationProfile p =
new ElevationProfile(cDEM, o, AZIMUTH, LENGTH);
assertEquals(toRadians(6.09385),p.positionAt(10240).longitude(),0.00001);
assertEquals(toRadians(46.06508),p.positionAt(10240).latitude(),0.00001);
}
/*
@Test
public void testElevationAt() {
fail("Not yet implemented");
}
@Test
public void testPositionAt() {
fail("Not yet implemented");
}
@Test
public void testSlopeAt() {
fail("Not yet implemented");
}
*/
}

View File

@@ -0,0 +1,134 @@
package ch.epfl.alpano.dem;
import static java.lang.Math.PI;
import static java.lang.Math.toRadians;
import static org.junit.Assert.assertEquals;
import org.junit.Test;
import ch.epfl.alpano.GeoPoint;
import ch.epfl.alpano.Interval1D;
import ch.epfl.alpano.Interval2D;
public class ElevationProfileTestP {
@Test(expected = NullPointerException.class)
public void constructorFailsWhenElevationModelIsNull() {
new ElevationProfile(null, new GeoPoint(0,0), 0, 100);
}
@Test(expected = NullPointerException.class)
public void constructorFailsWhenOriginIsNull() {
new ElevationProfile(newConstantSlopeDEM(), null, 0, 100);
}
@Test(expected = IllegalArgumentException.class)
public void constructorFailsWhenAzimuthIsNotCanonical() {
new ElevationProfile(newConstantSlopeDEM(), new GeoPoint(0,0), 6.3, 100);
}
@Test(expected = IllegalArgumentException.class)
public void constructorFailsWhenLengthIsZero() {
new ElevationProfile(newConstantSlopeDEM(), new GeoPoint(0,0), 0, 0);
}
@Test(expected = IllegalArgumentException.class)
public void elevationAtFailsWhenXIsTooBig() {
ElevationProfile p = new ElevationProfile(newConstantSlopeDEM(), new GeoPoint(0,0), 0, 100);
p.elevationAt(101);
}
@Test
public void elevationAtWorksOnConstantSlopeDEMGoingNorth() {
ElevationProfile p = new ElevationProfile(newConstantSlopeDEM(), new GeoPoint(0,0), 0, 100_000);
for (int i = 0; i < 100; ++i) {
double x = 100d * i;
assertEquals(x, p.elevationAt(x), 1e-5);
}
}
@Test
public void elevationAtWorksOnConstantSlopeDEMGoingSouth() {
ElevationProfile p = new ElevationProfile(newConstantSlopeDEM(), new GeoPoint(0,0), PI, 100_000);
for (int i = 0; i < 100; ++i) {
double x = 100d * i;
assertEquals(-x, p.elevationAt(x), 1e-5);
}
}
@Test
public void elevationAtWorksOnConstantSlopeDEMGoingEast() {
ElevationProfile p = new ElevationProfile(newConstantSlopeDEM(), new GeoPoint(0,0), PI/2d, 100_000);
for (int i = 0; i < 100; ++i) {
double x = 100d * i;
assertEquals(x, p.elevationAt(x), 1e-5);
}
}
@Test
public void elevationAtWorksOnConstantSlopeDEMGoingWest() {
ElevationProfile p = new ElevationProfile(newConstantSlopeDEM(), new GeoPoint(0,0), 3d*PI/2d, 100_000);
for (int i = 0; i < 100; ++i) {
double x = 100d * i;
assertEquals(-x, p.elevationAt(x), 1e-5);
}
}
@Test(expected = IllegalArgumentException.class)
public void positionAtFailsWhenXIsTooBig() {
ElevationProfile p = new ElevationProfile(newConstantSlopeDEM(), new GeoPoint(0,0), 0, 100);
p.positionAt(101);
}
@Test
public void positionAtProducesConstantLongitudeWhenGoingNorth() {
double lon = toRadians(3);
ElevationProfile p = new ElevationProfile(newConstantSlopeDEM(), new GeoPoint(lon,toRadians(40)), 0, 100_000);
for (int i = 0; i < 100; ++i) {
double x = 500d * i;
assertEquals(lon, p.positionAt(x).longitude(), 1e-5);
}
}
@Test
public void positionAtProducesConstantLongitudeWhenGoingSouth() {
double lon = toRadians(3);
ElevationProfile p = new ElevationProfile(newConstantSlopeDEM(), new GeoPoint(lon,toRadians(40)), PI, 100_000);
for (int i = 0; i < 100; ++i) {
double x = 500d * i;
assertEquals(lon, p.positionAt(x).longitude(), 1e-5);
}
}
@Test
public void positionAtProducesConstantLatitudeWhenGoingEast() {
double lat = toRadians(40);
ElevationProfile p = new ElevationProfile(newConstantSlopeDEM(), new GeoPoint(toRadians(3),lat), PI/2d, 100_000);
for (int i = 0; i < 100; ++i) {
double x = 500d * i;
assertEquals(lat, p.positionAt(x).latitude(), 1e-4);
}
}
@Test
public void positionAtProducesConstantLatitudeWhenGoingWest() {
double lat = toRadians(40);
ElevationProfile p = new ElevationProfile(newConstantSlopeDEM(), new GeoPoint(toRadians(3),lat), 3d*PI/2d, 100_000);
for (int i = 0; i < 100; ++i) {
double x = 500d * i;
assertEquals(lat, p.positionAt(x).latitude(), 1e-4);
}
}
@Test(expected = IllegalArgumentException.class)
public void slopeAtFailsWhenXIsNegative() {
ElevationProfile p = new ElevationProfile(newConstantSlopeDEM(), new GeoPoint(0,0), 0, 100);
p.positionAt(-1);
}
private static ContinuousElevationModel newConstantSlopeDEM() {
Interval2D extent = new Interval2D(
new Interval1D(-10_000, 10_000),
new Interval1D(-10_000, 10_000));
return new ContinuousElevationModel(new ConstantSlopeDEM(extent));
}
}

View File

@@ -0,0 +1,77 @@
package ch.epfl.alpano.dem;
import static org.junit.Assert.*;
import static ch.epfl.alpano.Preconditions.checkArgument;
import java.io.File;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import org.junit.Test;
public class HgtDiscreteElevationModelTest {
@Test
public void testHgtDiscreteElevationModel() {
String[] files = {"N45E006.hgt","N45E007.hgt","N45E008.hgt","N45E009.hgt",
"N45E010.hgt","N45E011.hgt","N46E006.hgt","N46E007.hgt",
"N46E008.hgt","N46E009.hgt","N46E010.hgt","N46E011.hgt",
"N47E006.hgt","N47E007.hgt","N47E008.hgt","N47E009.hgt",
"N47E010.hgt","N47E011.hgt","N00E000.hgt","S89W120"};
File file;
for(String txt: files){
file = new File("HGT"+File.separatorChar+txt);
if(file.exists())
new HgtDiscreteElevationModel(file);
}
assertTrue(true);
}
@Test(expected=IllegalArgumentException.class)
public void testHgtDiscreteElevationModelFails() {
String[] files = {"N45E180.hgt","N45E007.hgt",};
File file;
for(String txt: files){
file = new File("HGT"+File.separatorChar+txt);
new HgtDiscreteElevationModel(file);
}
}
@Test
public void checkFileNameSuccess() {
assertTrue(checkFileName("S00E000.hgt")!=null);
assertTrue(checkFileName("N00E000.hgt")!=null);
assertTrue(checkFileName("S00W129.hgt")!=null);
assertTrue(checkFileName("N00W000.hgt")!=null);
assertTrue(checkFileName("S69E139.hgt")!=null);
assertTrue(checkFileName("S90W180.hgt")!=null);
assertTrue(checkFileName("N90E180.hgt")!=null);
assertTrue(checkFileName("S90W180.hgt")!=null);
}
@Test(expected=IllegalArgumentException.class)
public void checkFileNameFails() {
checkFileName("E46E006.hgt");
checkFileName("N4gE006.hgt");
checkFileName("N46E0g6.hgt");
checkFileName("N46E006lhgt");
checkFileName("N46E006.hGT");
checkFileName("N4gE006.hgt");
checkFileName("N46E0g6.hgt");
checkFileName("N46E006phgt");
checkFileName("Q99E006.hGT");
}
private static final Matcher checkFileName(String txt){
final Pattern P = Pattern.compile("([NS])(\\d{2})([EW])(\\d{3})\\.hgt");
Matcher m = P.matcher(txt);
checkArgument((txt.length()==11 && m.find()));
int lat = Integer.parseInt(m.group(2));
int lon = Integer.parseInt(m.group(4));
checkArgument(!(lat>90 || lon>180 ));
return m;
}
}

View File

@@ -0,0 +1,154 @@
package ch.epfl.alpano.dem;
import static java.nio.file.StandardCopyOption.REPLACE_EXISTING;
import static java.nio.file.StandardOpenOption.CREATE_NEW;
import static java.nio.file.StandardOpenOption.READ;
import static java.nio.file.StandardOpenOption.WRITE;
import static org.junit.Assert.assertEquals;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.nio.ShortBuffer;
import java.nio.channels.FileChannel;
import java.nio.channels.FileChannel.MapMode;
import java.nio.file.FileVisitResult;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.SimpleFileVisitor;
import java.nio.file.attribute.BasicFileAttributes;
import org.junit.AfterClass;
import org.junit.BeforeClass;
import org.junit.Test;
import ch.epfl.alpano.Interval1D;
import ch.epfl.alpano.Interval2D;
public class HgtDiscreteElevationModelTestP {
private final static long HGT_FILE_SIZE = 3601L * 3601L * 2L;
private static Path FAKE_HGT_DIR, FAKE_HGT_FILE;
@BeforeClass
public static void createFakeHgtFiles() throws IOException {
Path fakeHgtDir = Files.createTempDirectory("hgt");
Path fakeHgtFile = fakeHgtDir.resolve("empty.hgt");
try (FileChannel c = FileChannel.open(fakeHgtFile, CREATE_NEW, READ, WRITE)) {
// make sure the empty hgt file has the right size
c.map(MapMode.READ_WRITE, 0, HGT_FILE_SIZE).asShortBuffer();
}
FAKE_HGT_FILE = fakeHgtFile;
FAKE_HGT_DIR = fakeHgtDir;
}
@AfterClass
public static void deleteFakeHgtFiles() throws IOException {
Files.walkFileTree(FAKE_HGT_DIR, new SimpleFileVisitor<Path>() {
@Override
public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException {
Files.delete(file);
return FileVisitResult.CONTINUE;
}
@Override
public FileVisitResult postVisitDirectory(Path dir, IOException exc) throws IOException {
if (exc != null)
throw exc;
Files.delete(dir);
return FileVisitResult.CONTINUE;
}
});
}
@Test(expected = IllegalArgumentException.class)
public void constructorFailsWithTooShortName() throws Exception {
createHgtDemWithFileNamed("N47E010.hg");
}
@Test(expected = IllegalArgumentException.class)
public void constructorFailsWithInvalidLatitudeLetter() throws Exception {
createHgtDemWithFileNamed("N4xE010.hgt");
}
@Test(expected = IllegalArgumentException.class)
public void constructorFailsWithInvalidLongitudeLetter() throws Exception {
createHgtDemWithFileNamed("N47x010.hgt");
}
@Test(expected = IllegalArgumentException.class)
public void constructorFailsWithInexistantFile() throws Exception {
Path p = FAKE_HGT_DIR.resolve("N40E010.hgt");
try (DiscreteElevationModel d = new HgtDiscreteElevationModel(p.toFile())) {}
}
@Test(expected = IllegalArgumentException.class)
public void constructorFailsWithEmptyFile() throws Exception {
File f = FAKE_HGT_DIR.resolve("N41E010.hgt").toFile();
try (FileOutputStream s = new FileOutputStream(f)) {
s.write(0);
}
try (DiscreteElevationModel d = new HgtDiscreteElevationModel(f)) {}
}
@Test
public void constructorWorksInEcuador() throws Exception {
createHgtDemWithFileNamed("S03W078.hgt");
}
@Test
public void extentMatchesFileName() throws Exception {
int[] lons = new int[] { 1, 7 };
int[] lats = new int[] { 1, 47 };
for (int lon: lons) {
for (int lat: lats) {
Interval2D expectedExtent = new Interval2D(
new Interval1D(lon * 3600, (lon + 1) * 3600),
new Interval1D(lat * 3600, (lat + 1) * 3600));
String hgtFileName = String.format("N%02dE%03d.hgt", lat, lon);
Path p = copyEmptyHgtFileAs(hgtFileName);
try (HgtDiscreteElevationModel dem = new HgtDiscreteElevationModel(p.toFile())) {
assertEquals(expectedExtent, dem.extent());
}
}
}
}
@Test(expected = IllegalArgumentException.class)
public void elevationSampleFailsForIndexNotInExtent() throws Exception {
String hgtFileName = "N02E002.hgt";
Path p = copyEmptyHgtFileAs(hgtFileName);
try (HgtDiscreteElevationModel dem = new HgtDiscreteElevationModel(p.toFile())) {
dem.elevationSample(10, 10);
}
}
@Test
public void elevationSampleIsCorrectInFourCorners() throws Exception {
Path p = FAKE_HGT_DIR.resolve("N01E001.hgt");
try (FileChannel c = FileChannel.open(p, CREATE_NEW, READ, WRITE)) {
ShortBuffer b = c.map(MapMode.READ_WRITE, 0, HGT_FILE_SIZE).asShortBuffer();
b.put(0, (short)1);
b.put(3600, (short) 2);
b.put(3601 * 3600, (short) 3);
b.put(3601 * 3601 - 1, (short) 4);
}
try (HgtDiscreteElevationModel dem = new HgtDiscreteElevationModel(p.toFile())) {
assertEquals(0, dem.elevationSample(4000, 4000), 1e-10);
assertEquals(1, dem.elevationSample(3600, 7200), 1e-10);
assertEquals(2, dem.elevationSample(7200, 7200), 1e-10);
assertEquals(3, dem.elevationSample(3600, 3600), 1e-10);
assertEquals(4, dem.elevationSample(7200, 3600), 1e-10);
}
}
private static void createHgtDemWithFileNamed(String hgtFileName) throws Exception {
Path p = copyEmptyHgtFileAs(hgtFileName);
try (DiscreteElevationModel d = new HgtDiscreteElevationModel(p.toFile())) {}
}
private static Path copyEmptyHgtFileAs(String hgtFileName) throws IOException {
return Files.copy(FAKE_HGT_FILE, FAKE_HGT_DIR.resolve(hgtFileName), REPLACE_EXISTING);
}
}

View File

@@ -0,0 +1,26 @@
package ch.epfl.alpano.dem;
import java.io.File;
import java.io.IOException;
import java.io.FileInputStream;
import java.nio.ShortBuffer;
import java.nio.channels.FileChannel.MapMode;
public class MemMapExample {
public static void main(String[] args)
throws IOException {
File f = new File("HGT"+File.separatorChar+"N46E007.hgt");
long l = f.length();
try (FileInputStream s = new FileInputStream(f)) {
ShortBuffer b = s.getChannel()
.map(MapMode.READ_ONLY, 0, l)
.asShortBuffer();
for (int i = 0; i <= 5; ++i)
System.out.println(b.get(i));
System.out.println("-----------------");
for (int i = 12967195; i < 12967201; ++i)
System.out.println(b.get(i));
}
}
}

View File

@@ -0,0 +1,57 @@
package ch.epfl.alpano.dem;
import static java.awt.image.BufferedImage.TYPE_INT_RGB;
import static java.lang.Math.*;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import ch.epfl.alpano.*;
import javax.imageio.ImageIO;
public final class TestWavyDEM {
@SuppressWarnings("resource")
public static void main(String[] args)
throws IOException {
DiscreteElevationModel dDEM1 =
new WavyDEM(new Interval2D(new Interval1D(0, 50),
new Interval1D(0, 100)));
DiscreteElevationModel dDEM2 =
new WavyDEM(new Interval2D(new Interval1D(50, 100),
new Interval1D(0, 100)));
DiscreteElevationModel dDEM =
dDEM1.union(dDEM2);
ContinuousElevationModel cDEM =
new ContinuousElevationModel(dDEM);
int size = 300;
double scale = (100d / 3600d) / (size - 1);
BufferedImage elI =
new BufferedImage(size, size, TYPE_INT_RGB);
BufferedImage slI =
new BufferedImage(size, size, TYPE_INT_RGB);
for (int x = 0; x < size; ++x) {
for (int y = 0; y < size; ++y) {
GeoPoint p = new GeoPoint(toRadians(x * scale),
toRadians(y * scale));
double el = cDEM.elevationAt(p);
elI.setRGB(x, y, gray(el / 1000d));
double sl = cDEM.slopeAt(p);
slI.setRGB(x, y, gray(sl / (PI / 2d)));
}
}
ImageIO.write(elI, "png", new File("tests/ch/epfl/alpano/dem/elevation.png"));
ImageIO.write(slI, "png", new File("tests/ch/epfl/alpano/dem/slope.png"));
}
private static int gray(double v) {
double clampedV = max(0, min(v, 1));
int gray = (int) (255.9999 * clampedV);
return (gray << 16) | (gray << 8) | gray;
}
}

View File

@@ -0,0 +1,28 @@
package ch.epfl.alpano.dem;
import ch.epfl.alpano.Interval2D;
import static java.lang.Math.PI;
import static java.lang.Math.sin;
import static java.lang.Math.cos;
final class WavyDEM implements DiscreteElevationModel {
private final static double PERIOD = 100, HEIGHT = 1000;
private final Interval2D extent;
public WavyDEM(Interval2D extent) {
this.extent = extent;
}
@Override
public void close() throws Exception { }
@Override
public Interval2D extent() { return extent; }
@Override
public double elevationSample(int x, int y) {
double x1 = PI * 2d * x / PERIOD;
double y1 = PI * 2d * y / PERIOD;
return (1 + sin(x1) * cos(y1)) / 2d * HEIGHT;
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 56 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 951 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 30 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 56 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 446 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 252 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 800 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 29 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 354 KiB

View File

@@ -0,0 +1,31 @@
package ch.epfl.alpano.gui;
import static ch.epfl.alpano.gui.PredefinedPanoramas.*;
import ch.epfl.alpano.gui.PanoramaParametersBean;
import javafx.application.Application;
import javafx.application.Platform;
import javafx.beans.property.ObjectProperty;
import javafx.stage.Stage;
public final class BeansUse extends Application {
public static void main(String[] args) {
launch(args);
}
@Override
public void start(Stage primaryStage) throws Exception {
PanoramaParametersBean bean =
new PanoramaParametersBean(NIESEN.get());
ObjectProperty<Integer> prop =
bean.ObserverLatitudeProperty();
prop.addListener((o, oV, nV) ->
System.out.printf(" %d -> %d (%s)%n", oV, nV, o));
System.out.println("set to 1");
prop.set(1);
System.out.println("set to 2");
prop.set(2);
Platform.exit();
}
}

View File

@@ -0,0 +1,28 @@
package ch.epfl.alpano.gui;
import static org.junit.Assert.*;
import org.junit.Test;
public class FixedPointStringConverterTest {
@Test
public void testFixedPointStringConverter() {
//fail("Not yet implemented");
}
@Test
public void testFromStringString() {
FixedPointStringConverter f = new FixedPointStringConverter(4);
assertEquals(123457, (int)f.fromString("12.3456789"));
FixedPointStringConverter f1 = new FixedPointStringConverter(2);
assertEquals("1011", f1.toString(101100));
}
@Test
public void testToStringInteger() {
FixedPointStringConverter f = new FixedPointStringConverter(1);
assertEquals("67.8", f.toString(678));
}
}

View File

@@ -0,0 +1,28 @@
package ch.epfl.alpano.gui;
import static org.junit.Assert.*;
import org.junit.Test;
public class LabeledListStringConverterTest {
@Test
public void testLabeledListStringConverter() {
}
@Test
public void testFromStringString() {
LabeledListStringConverter c = new LabeledListStringConverter("none","2x","4x");
System.out.println(c.fromString("2x"));
//assertEquals(1,c.fromString("2x"));
}
@Test
public void testToStringInteger() {
LabeledListStringConverter c = new LabeledListStringConverter("none","2x","4x");
assertEquals("none",c.toString(0));
}
}

View File

@@ -0,0 +1,50 @@
package ch.epfl.alpano.gui;
import java.io.File;
import java.io.IOException;
import java.util.List;
import org.junit.Test;
import ch.epfl.alpano.dem.ContinuousElevationModel;
import ch.epfl.alpano.dem.HgtDiscreteElevationModel;
import ch.epfl.alpano.summit.GazetteerParser;
import ch.epfl.alpano.summit.Summit;
import javafx.scene.Node;
import javafx.scene.text.Text;
public class LabelizerTest {
@Test
public void testLabels() {
try {
List<Summit> listOfSummit = GazetteerParser.readSummitsFrom(new File("HGT/alps.txt"));
HgtDiscreteElevationModel dDem = new HgtDiscreteElevationModel(new File ("HGT/N46E007.hgt"));
ContinuousElevationModel cDem = new ContinuousElevationModel(dDem);
Labelizer l = new Labelizer(cDem, listOfSummit);
List<Node> n= l.labels(PredefinedPanoramas.NIESEN.get().panoramaComputeParameters());
int count =0;
for (Node node : n){
System.out.println(node);
if (node instanceof Text){
++count;
//System.out.println("node");
System.out.println(node.toString());
}
}
System.out.println(count);
} catch (IOException e) {
e.printStackTrace();
}
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.1 KiB

View File

@@ -0,0 +1,41 @@
package ch.epfl.alpano.sigcheck;
import ch.epfl.alpano.GeoPoint;
import ch.epfl.alpano.Interval1D;
import ch.epfl.alpano.Interval2D;
final class SignatureChecks_02 {
private SignatureChecks_02() {}
String checkGeoPoint() {
double lon = 0, lat = 0;
GeoPoint p = new GeoPoint(lon, lat);
lon += p.longitude() + p.latitude();
double d = p.distanceTo(p);
double a = p.azimuthTo(p);
return String.valueOf(d) + a;
}
String checkInterval1D() {
int a = 0;
Interval1D i = new Interval1D(a, a);
a = i.includedFrom() + i.includedTo() + i.size() + i.sizeOfIntersectionWith(i);
boolean b = i.contains(a)
| i.isUnionableWith(i);
i = i.union(i.boundingUnion(i));
return i.toString() + b;
}
String checkInterval2D() {
int a = 0;
Interval1D i1 = null;
Interval2D i2 = new Interval2D(i1, i1);
i1 = i2.iX();
i1 = i2.iY();
a = i2.size() + i2.sizeOfIntersectionWith(i2);
boolean b = i2.contains(a, a)
| i2.isUnionableWith(i2);
i2 = i2.union(i2.boundingUnion(i2));
return i2.toString() + b;
}
}

View File

@@ -0,0 +1,29 @@
package ch.epfl.alpano.sigcheck;
import ch.epfl.alpano.GeoPoint;
import ch.epfl.alpano.Interval2D;
import ch.epfl.alpano.dem.ContinuousElevationModel;
import ch.epfl.alpano.dem.DiscreteElevationModel;
final class SignatureChecks_03 {
private SignatureChecks_03() {}
String checkDiscElevationModel(DiscreteElevationModel d) throws Exception {
double a = DiscreteElevationModel.SAMPLES_PER_DEGREE * DiscreteElevationModel.SAMPLES_PER_RADIAN;
a = DiscreteElevationModel.sampleIndex(a);
Interval2D e = d.extent();
int v = 0;
a = d.elevationSample(v, v);
d = d.union(d);
d.close();
return d.toString() + e;
}
String checkContElevationModel() {
DiscreteElevationModel md = null;
ContinuousElevationModel m = new ContinuousElevationModel(md);
GeoPoint p = null;
double e = m.elevationAt(p) + m.slopeAt(p);
return String.valueOf(e);
}
}

View File

@@ -0,0 +1,30 @@
package ch.epfl.alpano.sigcheck;
import java.io.File;
import ch.epfl.alpano.GeoPoint;
import ch.epfl.alpano.dem.ContinuousElevationModel;
import ch.epfl.alpano.dem.DiscreteElevationModel;
import ch.epfl.alpano.dem.ElevationProfile;
import ch.epfl.alpano.dem.HgtDiscreteElevationModel;
final class SignatureChecks_04 {
private SignatureChecks_04() {}
void checkHgtDiscreteElevationModel() {
File f = null;
DiscreteElevationModel m = new HgtDiscreteElevationModel(f);
System.out.println(m);
}
void checkElevationProfile() {
ContinuousElevationModel dem = null;
GeoPoint o = null;
double d = 0;
ElevationProfile p = new ElevationProfile(dem, o, d, d);
d = p.elevationAt(d);
o = p.positionAt(d);
d = p.slopeAt(d);
}
}

View File

@@ -0,0 +1,46 @@
package ch.epfl.alpano.sigcheck;
import java.io.File;
import java.io.IOException;
import java.util.List;
import ch.epfl.alpano.GeoPoint;
import ch.epfl.alpano.PanoramaParameters;
import ch.epfl.alpano.summit.GazetteerParser;
import ch.epfl.alpano.summit.Summit;
final class SignatureChecks_05 {
private SignatureChecks_05() {}
void checkSummit() {
GeoPoint p = null;
int e = 0;
Summit s = new Summit("", p, e);
p = s.position();
e = s.elevation();
System.out.println(s.name());
}
void checkGazetteerParser() throws IOException {
File f = null;
List<Summit> s = GazetteerParser.readSummitsFrom(f);
System.out.println(s);
}
void checkPanoramaParameters() {
GeoPoint p = null;
int i = 0;
double d = 0d;
PanoramaParameters pp = new PanoramaParameters(p, i, d, d, i, i, i);
p = pp.observerPosition();
i = pp.observerElevation();
d = pp.centerAzimuth();
d = pp.horizontalFieldOfView();
d = pp.verticalFieldOfView();
i = pp.width();
i = pp.height();
i = pp.maxDistance();
d = pp.xForAzimuth(pp.azimuthForX(d));
d = pp.yForAltitude(pp.altitudeForY(d));
}
}

View File

@@ -0,0 +1,49 @@
package ch.epfl.alpano.sigcheck;
import java.util.function.DoubleUnaryOperator;
import ch.epfl.alpano.Panorama;
import ch.epfl.alpano.PanoramaComputer;
import ch.epfl.alpano.PanoramaParameters;
import ch.epfl.alpano.dem.ContinuousElevationModel;
import ch.epfl.alpano.dem.ElevationProfile;
final class SignatureChecks_06 {
private SignatureChecks_06() {}
void checkPanorama(Panorama p) {
PanoramaParameters pp = p.parameters();
int x = 0;
float d = p.distanceAt(x, x);
d = p.distanceAt(x, x, d);
d = p.longitudeAt(x, x);
d = p.latitudeAt(x, x);
d = p.elevationAt(x, x);
d = p.slopeAt(x, x);
checkPanoramaBuilder(pp);
}
void checkPanoramaBuilder(PanoramaParameters pp) {
Panorama.Builder b = new Panorama.Builder(pp);
int x = 0;
float d = 0;
b.setDistanceAt(x, x, d);
b.setLongitudeAt(x, x, d);
b.setLatitudeAt(x, x, d);
b.setElevationAt(x, x, d);
b.setSlopeAt(x, x, d);
Panorama p = b.build();
checkPanorama(p);
}
void checkPanoramaComputer(PanoramaParameters pp) {
ContinuousElevationModel d = null;
PanoramaComputer pc = new PanoramaComputer(d);
Panorama p = pc.computePanorama(pp);
checkPanorama(p);
double y = 0;
ElevationProfile pr = null;
DoubleUnaryOperator o = PanoramaComputer.rayToGroundDistance(pr, y, y);
System.out.println(o);
}
}

View File

@@ -0,0 +1,12 @@
package ch.epfl.alpano.sigcheck;
import ch.epfl.alpano.gui.Alpano;
final class SignatureChecks_11 {
private SignatureChecks_11() {}
void checkAlpano() {
String[] args = null;
Alpano.main(args);
}
}

View File

@@ -0,0 +1,136 @@
package ch.epfl.alpano.summit;
import static ch.epfl.alpano.summit.GazetteerParser.readSummitsFrom;
import static java.lang.Math.toDegrees;
import static java.lang.Math.toRadians;
import static java.nio.charset.StandardCharsets.US_ASCII;
import static org.junit.Assert.assertEquals;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.nio.file.Files;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Comparator;
import java.util.Iterator;
import java.util.List;
import org.junit.Test;
import ch.epfl.alpano.GeoPoint;
public class GazetteerParserTest {
@Test(expected = IOException.class)
public void parserFailsOnNonExistantFile() throws IOException {
readSummitsFrom(new File("/ /d:/ééé"));
}
@Test(expected = IOException.class)
public void parserFailsOnGarbageLine() throws IOException {
readSummitsFrom(tempFileWithLines("blabla"));
}
@Test(expected = IOException.class)
public void parserFailsOnInvalidLongitude() throws IOException {
String l = " 7:25:1x 45:08:25 1325 R0 E07 BA MONTE CURT";
readSummitsFrom(tempFileWithLines(l));
}
@Test(expected = IOException.class)
public void parserFailsOnInvalidLatitude() throws IOException {
String l = " 7:25:12 45:08:2_ 1325 R0 E07 BA MONTE CURT";
readSummitsFrom(tempFileWithLines(l));
}
@Test(expected = IOException.class)
public void parserFailsOnInvalidElevation() throws IOException {
String l = " 7:25:12 45:08:25 leet R0 E07 BA MONTE CURT";
readSummitsFrom(tempFileWithLines(l));
}
@Test(expected = UnsupportedOperationException.class)
public void summitListIsUnmodifiable() throws IOException {
String l = " 7:01:02 46:32:56 2002 H1 B01 D7 LE MOLESON";
readSummitsFrom(tempFileWithLines(l)).clear();
}
@Test
public void parserWorksOnValidFile() throws IOException {
List<Summit> summits = Arrays.asList(
new Summit("A MONT UN", hmsPoint(7, 30, 00, 15, 16, 17), 30),
new Summit("B MONT ZWEI", hmsPoint(6, 12, 34, 1, 23, 45), 10),
new Summit("C MONTE TRE", hmsPoint(1, 33, 33, 15, 66, 66), 1000),
new Summit("D MONT AU NOM TRES LONG", hmsPoint(5, 00, 00, 5, 00, 00), 8000));
String[] formattedSummits = new String[summits.size()];
int i = 0;
for (Summit s: summits)
formattedSummits[i++] = formatSummit(s);
File f = tempFileWithLines(formattedSummits);
List<Summit> readSummits = new ArrayList<>(readSummitsFrom(f));
assertEquals(summits.size(), readSummits.size());
readSummits.sort(Comparator.comparing(Summit::name));
Iterator<Summit> expectedIt = summits.iterator();
Iterator<Summit> actualIt = readSummits.iterator();
while (expectedIt.hasNext()) {
Summit expected = expectedIt.next();
Summit actual = actualIt.next();
assertEquals(expected.name(), actual.name());
assertEquals(expected.elevation(), actual.elevation());
assertEquals(
expected.position().longitude(),
actual.position().longitude(),
toRadians(1d / 3600d));
assertEquals(
expected.position().latitude(),
actual.position().latitude(),
toRadians(1d / 3600d));
}
}
private String formatSummit(Summit s) {
double lon = s.position().longitude();
double lat = s.position().latitude();
return String.format("%3d:%02d:%02d %2d:%02d:%02d %5d R0 E07 BA %s",
h(lon), m(lon), s(lon), h(lat), m(lat), s(lat), s.elevation(), s.name());
}
private static GeoPoint hmsPoint(
int hLon, int mLon, int sLon,
int hLat, int mLat, int sLat) {
return new GeoPoint(hmsToRad(hLon, mLon, sLon), hmsToRad(hLat, mLat, sLat));
}
private static double hmsToRad(int h, int m, int s) {
return toRadians(h + (m / 60d) + (s / 3600d));
}
private static int h(double d) {
return (int)toDegrees(d);
}
private static int m(double d) {
return (int)(toDegrees(d) * 60d) % 60;
}
private static int s(double d) {
return (int)(toDegrees(d) * 3600d) % 60;
}
private static File tempFileWithLines(String... lines) throws IOException {
File f = Files.createTempFile("summits", ".txt").toFile();
f.deleteOnExit();
try (BufferedWriter b = new BufferedWriter(
new OutputStreamWriter(
new FileOutputStream(f), US_ASCII))) {
for (String l: lines) {
b.write(l);
b.newLine();
}
}
return f;
}
}

View File

@@ -0,0 +1,136 @@
package ch.epfl.alpano.summit;
import static ch.epfl.alpano.summit.GazetteerParser.readSummitsFrom;
import static java.lang.Math.toDegrees;
import static java.lang.Math.toRadians;
import static java.nio.charset.StandardCharsets.US_ASCII;
import static org.junit.Assert.assertEquals;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.nio.file.Files;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Comparator;
import java.util.Iterator;
import java.util.List;
import org.junit.Test;
import ch.epfl.alpano.GeoPoint;
public class GazetterParserTestP {
@Test(expected = IOException.class)
public void parserFailsOnNonExistantFile() throws IOException {
readSummitsFrom(new File("/ /d:/ééé"));
}
@Test(expected = IOException.class)
public void parserFailsOnGarbageLine() throws IOException {
readSummitsFrom(tempFileWithLines("blabla"));
}
@Test(expected = IOException.class)
public void parserFailsOnInvalidLongitude() throws IOException {
String l = " 7:25:1x 45:08:25 1325 R0 E07 BA MONTE CURT";
readSummitsFrom(tempFileWithLines(l));
}
@Test(expected = IOException.class)
public void parserFailsOnInvalidLatitude() throws IOException {
String l = " 7:25:12 45:08:2_ 1325 R0 E07 BA MONTE CURT";
readSummitsFrom(tempFileWithLines(l));
}
@Test(expected = IOException.class)
public void parserFailsOnInvalidElevation() throws IOException {
String l = " 7:25:12 45:08:25 leet R0 E07 BA MONTE CURT";
readSummitsFrom(tempFileWithLines(l));
}
@Test(expected = UnsupportedOperationException.class)
public void summitListIsUnmodifiable() throws IOException {
String l = " 7:01:02 46:32:56 2002 H1 B01 D7 LE MOLESON";
readSummitsFrom(tempFileWithLines(l)).clear();
}
@Test
public void parserWorksOnValidFile() throws IOException {
List<Summit> summits = Arrays.asList(
new Summit("A MONT UN", hmsPoint(7, 30, 00, 15, 16, 17), 30),
new Summit("B MONT ZWEI", hmsPoint(6, 12, 34, 1, 23, 45), 10),
new Summit("C MONTE TRE", hmsPoint(1, 33, 33, 15, 66, 66), 1000),
new Summit("D MONT AU NOM TRES LONG", hmsPoint(5, 00, 00, 5, 00, 00), 8000));
String[] formattedSummits = new String[summits.size()];
int i = 0;
for (Summit s: summits)
formattedSummits[i++] = formatSummit(s);
File f = tempFileWithLines(formattedSummits);
List<Summit> readSummits = new ArrayList<>(readSummitsFrom(f));
assertEquals(summits.size(), readSummits.size());
readSummits.sort(Comparator.comparing(Summit::name));
Iterator<Summit> expectedIt = summits.iterator();
Iterator<Summit> actualIt = readSummits.iterator();
while (expectedIt.hasNext()) {
Summit expected = expectedIt.next();
Summit actual = actualIt.next();
assertEquals(expected.name(), actual.name());
assertEquals(expected.elevation(), actual.elevation());
assertEquals(
expected.position().longitude(),
actual.position().longitude(),
toRadians(1d / 3600d));
assertEquals(
expected.position().latitude(),
actual.position().latitude(),
toRadians(1d / 3600d));
}
}
private String formatSummit(Summit s) {
double lon = s.position().longitude();
double lat = s.position().latitude();
return String.format("%3d:%02d:%02d %2d:%02d:%02d %5d R0 E07 BA %s",
h(lon), m(lon), s(lon), h(lat), m(lat), s(lat), s.elevation(), s.name());
}
private static GeoPoint hmsPoint(
int hLon, int mLon, int sLon,
int hLat, int mLat, int sLat) {
return new GeoPoint(hmsToRad(hLon, mLon, sLon), hmsToRad(hLat, mLat, sLat));
}
private static double hmsToRad(int h, int m, int s) {
return toRadians(h + (m / 60d) + (s / 3600d));
}
private static int h(double d) {
return (int)toDegrees(d);
}
private static int m(double d) {
return (int)(toDegrees(d) * 60d) % 60;
}
private static int s(double d) {
return (int)(toDegrees(d) * 3600d) % 60;
}
private static File tempFileWithLines(String... lines) throws IOException {
File f = Files.createTempFile("summits", ".txt").toFile();
f.deleteOnExit();
try (BufferedWriter b = new BufferedWriter(
new OutputStreamWriter(
new FileOutputStream(f), US_ASCII))) {
for (String l: lines) {
b.write(l);
b.newLine();
}
}
return f;
}
}

View File

@@ -0,0 +1,41 @@
package ch.epfl.alpano.summit;
import static java.lang.Math.toRadians;
import static org.junit.Assert.assertEquals;
import org.junit.Test;
import ch.epfl.alpano.GeoPoint;
public class SummitTestP {
@Test(expected = NullPointerException.class)
public void constructorFailsWithNullName() {
new Summit(null, new GeoPoint(0, 0), 1);
}
@Test(expected = NullPointerException.class)
public void constructorFailsWithNullPosition() {
new Summit("sommet", null, 1);
}
@Test
public void nameReturnsName() {
String n = "sommet";
Summit s = new Summit(n, new GeoPoint(0,0), 1);
assertEquals(n, s.name());
}
@Test
public void positionReturnsPosition() {
GeoPoint p = new GeoPoint(toRadians(3), toRadians(5));
Summit s = new Summit("sommet", p, 1);
assertEquals(p, s.position());
}
@Test
public void elevationReturnsElevation() {
int e = 1234;
Summit s = new Summit("sommet", new GeoPoint(0, 0), e);
assertEquals(e, s.elevation());
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 78 KiB

View File

@@ -0,0 +1,7 @@
package ch.epfl.test;
public interface ObjectTest {
public static boolean hashCodeIsCompatibleWithEquals(Object o1, Object o2) {
return ! o1.equals(o2) || o1.hashCode() == o2.hashCode();
}
}

View File

@@ -0,0 +1,14 @@
package ch.epfl.test;
import java.util.Random;
public interface TestRandomizer {
// Fix random seed to guarantee reproducibility.
public final static long SEED = 2017;
public final static int RANDOM_ITERATIONS = 500;
public static Random newRandom() {
return new Random(SEED);
}
}