Disabled external gits
@@ -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; }
 | 
			
		||||
}
 | 
			
		||||
@@ -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 {}
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										70
									
								
								Alpano/tests/ch/epfl/alpano/dem/DrawElevationProfile.java
									
									
									
									
									
										Normal 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"));
 | 
			
		||||
  }
 | 
			
		||||
  
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										83
									
								
								Alpano/tests/ch/epfl/alpano/dem/DrawHgtDEM.java
									
									
									
									
									
										Normal 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;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										50
									
								
								Alpano/tests/ch/epfl/alpano/dem/DrawHgtDEM2.java
									
									
									
									
									
										Normal 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;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										49
									
								
								Alpano/tests/ch/epfl/alpano/dem/ElevationProfileTest.java
									
									
									
									
									
										Normal 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");
 | 
			
		||||
    }
 | 
			
		||||
     */
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										134
									
								
								Alpano/tests/ch/epfl/alpano/dem/ElevationProfileTestP.java
									
									
									
									
									
										Normal 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));
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -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;
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
@@ -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);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										26
									
								
								Alpano/tests/ch/epfl/alpano/dem/MemMapExample.java
									
									
									
									
									
										Normal 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));
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										57
									
								
								Alpano/tests/ch/epfl/alpano/dem/TestWavyDEM.java
									
									
									
									
									
										Normal 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;
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										28
									
								
								Alpano/tests/ch/epfl/alpano/dem/WavyDEM.java
									
									
									
									
									
										Normal 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;
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										
											BIN
										
									
								
								Alpano/tests/ch/epfl/alpano/dem/dem.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						| 
		 After Width: | Height: | Size: 56 KiB  | 
							
								
								
									
										
											BIN
										
									
								
								Alpano/tests/ch/epfl/alpano/dem/dem2.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						| 
		 After Width: | Height: | Size: 951 KiB  | 
							
								
								
									
										
											BIN
										
									
								
								Alpano/tests/ch/epfl/alpano/dem/elevation.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						| 
		 After Width: | Height: | Size: 30 KiB  | 
							
								
								
									
										
											BIN
										
									
								
								Alpano/tests/ch/epfl/alpano/dem/mapView.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						| 
		 After Width: | Height: | Size: 56 KiB  | 
							
								
								
									
										
											BIN
										
									
								
								Alpano/tests/ch/epfl/alpano/dem/mapzen.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						| 
		 After Width: | Height: | Size: 446 KiB  | 
							
								
								
									
										
											BIN
										
									
								
								Alpano/tests/ch/epfl/alpano/dem/mapzenSlope.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						| 
		 After Width: | Height: | Size: 252 KiB  | 
							
								
								
									
										
											BIN
										
									
								
								Alpano/tests/ch/epfl/alpano/dem/profile.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						| 
		 After Width: | Height: | Size: 800 B  | 
							
								
								
									
										
											BIN
										
									
								
								Alpano/tests/ch/epfl/alpano/dem/slope.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						| 
		 After Width: | Height: | Size: 29 KiB  | 
							
								
								
									
										
											BIN
										
									
								
								Alpano/tests/ch/epfl/alpano/dem/testImage.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						| 
		 After Width: | Height: | Size: 354 KiB  |