/* * Author: Cedric Holzl - Mohamed Khadri * Sciper: 257844 - 261203 */ package ch.epfl.alpano; import static ch.epfl.alpano.Preconditions.checkBounds; import java.util.Arrays; /** * Panorama data holder computed using PanoramaComputer class using given * panorama parameters * * @see PanoramaComputer * @see PanoramaParameters * @see Panorama.Builder */ public final class Panorama { private final float[] distance; private final float[] longitude; private final float[] latitude; private final float[] altitude; private final float[] slope; private final PanoramaParameters parameters; /** * Panorama constructor * * @param parameters * : the PanoramaParameters * @param distance * : float table containing the distances * @param longitude * : float table containing the longitudes * @param latitude * : float table containing the latitudes * @param altitude * : float table containing the altitudes * @param slope * : float table containing the slopes */ private Panorama(PanoramaParameters parameters, float[] distance, float[] longitude, float[] latitude, float[] altitude, float[] slope) { this.distance = distance; this.longitude = longitude; this.latitude = latitude; this.altitude = altitude; this.slope = slope; this.parameters = parameters; } /** * Returns the parameters of the panorama * * @return the PanoramaParameters of the panorama */ public PanoramaParameters parameters() { return this.parameters; } /** * Returns the distance given a certain index x,y * * @param x * horizontal index * @param y * : vertical index * @return the distance given x,y * @throws IndexOutOfBoundsException * if x or y are out of bounds */ public float distanceAt(int x, int y) { checkBounds(parameters().isValidSampleIndex(x, y)); return this.distance[parameters().linearSampleIndex(x, y)]; } /** * Returns the distance given a certain index x,y * * @param x * horizontal index * @param y * : vertical index * @param d * : the default distance * @return the distance given x,y or the default distance if x or y are out * of bounds */ public float distanceAt(int x, int y, float d) { if (parameters().isValidSampleIndex(x, y)) return this.distance[parameters().linearSampleIndex(x, y)]; else return d; } /** * Returns the latitude given a certain index x,y * * @param x * horizontal index * @param y * : vertical index * @return the latitude given x,y * @throws IndexOutOfBoundsException * if x or y are out of bounds */ public float latitudeAt(int x, int y) { checkBounds(parameters().isValidSampleIndex(x, y)); return this.latitude[parameters().linearSampleIndex(x, y)]; } /** * Returns the longitude given a certain index x,y * * @param x * horizontal index * @param y * : vertical index * @return the longitude given x,y * @throws IndexOutOfBoundsException * if x or y are out of bounds */ public float longitudeAt(int x, int y) { checkBounds(parameters().isValidSampleIndex(x, y)); return this.longitude[parameters().linearSampleIndex(x, y)]; } /** * Returns the altitude given a certain index x,y * * @param x * horizontal index * @param y * : vertical index * @return the altitude given x,y * @throws IndexOutOfBoundsException * if x or y are out of bounds */ public float elevationAt(int x, int y) { checkBounds(parameters().isValidSampleIndex(x, y)); return this.altitude[parameters().linearSampleIndex(x, y)]; } /** * Returns the slope given a certain index x,y * * @param x * horizontal index * @param y * : vertical index * @return the slope given x,y * @throws IndexOutOfBoundsException * if x or y are out of bounds */ public float slopeAt(int x, int y) { checkBounds(parameters().isValidSampleIndex(x, y)); return this.slope[parameters().linearSampleIndex(x, y)]; } /** * Panorama Builder: * * Gathers data for a Panorama and builds it. * * @see Panorama * @see PanoramaComputer */ public final static class Builder { private float[] distance; private float[] longitude; private float[] latitude; private float[] altitude; private float[] slope; private final PanoramaParameters parameters; /** * Constructor of a panorama builder * * @param pp * : the panorama parameters * @throws NullPointerException * if the PanoramaParameters object is null */ public Builder(PanoramaParameters pp) { this.parameters = pp; int size = pp.width() * pp.height(); this.distance = new float[size]; this.longitude = new float[size]; this.latitude = new float[size]; this.altitude = new float[size]; this.slope = new float[size]; Arrays.fill(distance, Float.POSITIVE_INFINITY); } /** * Enters the distance into the table at a given index * * @param x * : horizontal index * @param y * : vertical index * @param distance * : the value to enter in the table * @return the builder (itself) * @throws IllegalStateException * if the Panorama has already been created * @throws IndexOutOfBoundsException * if x or y are out of bounds * @see checkBuilder */ public Builder setDistanceAt(int x, int y, float distance) { checkBuilder(); checkBounds(this.parameters.isValidSampleIndex(x, y)); this.distance[this.parameters.linearSampleIndex(x, y)] = distance; return this; } /** * Enters the longitude into the table at a given index * * @param x * : horizontal index * @param y * : vertical index * @param longitude * : the value to enter in the table * @return the builder (itself) * @throws IllegalStateException * if the panorama has already been created * @throws IndexOutOfBoundsException * if x or y are out of bounds * @see checkBuilder */ public Builder setLongitudeAt(int x, int y, float longitude) { checkBuilder(); checkBounds(this.parameters.isValidSampleIndex(x, y)); this.longitude[this.parameters.linearSampleIndex(x, y)] = longitude; return this; } /** * Enters the latitude into the table at a given index * * @param x * : horizontal index * @param y * : vertical index * @param latitude * : the value to enter in the table * @return the builder (itself) * @throws IllegalStateException * if the panorama has already been created * @throws IndexOutOfBoundsException * if x or y are out of bounds * @see checkBuilder */ public Builder setLatitudeAt(int x, int y, float latitude) { checkBuilder(); checkBounds(this.parameters.isValidSampleIndex(x, y)); this.latitude[this.parameters.linearSampleIndex(x, y)] = latitude; return this; } /** * Enters the altitude into the table at a given index * * @param x * : horizontal index * @param y * : vertical index * @param elevation * : the value to enter in the table * @return the builder (itself) * @throws IllegalStateException * if the panorama has already been created * @throws IndexOutOfBoundsException * if x or y are out of bounds * @see checkBuilder */ public Builder setElevationAt(int x, int y, float elevation) { checkBuilder(); checkBounds(this.parameters.isValidSampleIndex(x, y)); this.altitude[this.parameters.linearSampleIndex(x, y)] = elevation; return this; } /** * Enters the slope into the table at a given index * * @param x * : horizontal index * @param y * : vertical index * @param slope * : the value to enter in the table * @return the builder (itself) * @throws IllegalStateException * if the panorama has already been created * @throws IndexOutOfBoundsException * if x or y are out of bounds * @see checkBuilder */ public Builder setSlopeAt(int x, int y, float slope) { checkBuilder(); checkBounds(this.parameters.isValidSampleIndex(x, y)); this.slope[this.parameters.linearSampleIndex(x, y)] = slope; return this; } /** * Creates and returns the panorama * * @return the panorama * @throws IllegalStateException * if the panorama has already been created * @see checkBuilder */ public Panorama build() { checkBuilder(); Panorama p = new Panorama(parameters, distance, longitude, latitude, altitude, slope); this.distance = null; this.longitude = null; this.latitude = null; this.altitude = null; this.slope = null; return p; } /** * Checks if the panorama has already been built * * @throws IllegalStateException * if the panorama has already been created */ private void checkBuilder() { if (!(distance != null && longitude != null && latitude != null && altitude != null && slope != null)) throw new IllegalStateException(); } } }