350 lines
11 KiB
Java
Raw Normal View History

2022-04-07 18:43:21 +02:00
/*
* 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();
}
}
}