content: package aima.gui.swing.applications.robotics.simple;
  
  import aima.core.robotics.impl.datatypes.Angle;
  import aima.core.robotics.impl.datatypes.AbstractRangeReading;
  import aima.core.util.Util;
  
  /**
   * A simple range reading that extends {@link AbstractRangeReading} by adding the range noise model.
   * 
   * @author Arno von Borries
   * @author Jan Phillip Kretzschmar
   * @author Andreas Walscheid
   *
   */
  public final class SimpleRangeReading extends AbstractRangeReading {
  
  	private static double RANGE_NOISE;
  	private static double BAD_DELTA;
  	private static double SENSOR_RANGE;
  	/**
  	 * Sets the noise model for all range readings.
  	 * @param value the noise of the model.
  	 */
  	public static void setRangeNoise(double value) {
  		RANGE_NOISE = value;
  	}
  	
  	/**
  	 * Sets the delta between two range readings, above which a weight of zero is calculated.
  	 * @param badDelta the worst acceptable delta.
  	 */
  	public static void setBadDelta(double badDelta) {
  		BAD_DELTA = badDelta;
  	}
  	
  	/**
  	 * Sets the sensor range that the virtual robot can measure at most.
  	 * @param sensorRange the range of the robot's sensor.
  	 */
  	public static void setSensorRange(double sensorRange) {
  		SENSOR_RANGE = sensorRange;
  	}
  	
  	/**
  	 * Constructor for a range reading that has a zero angle.
  	 * @param value the range reading.
  	 */
  	public SimpleRangeReading(double value) {
  		super(value);
  	}
  	
  	/**
  	 * Constructor for a range reading at a given angle.
  	 * @param value the range reading.
  	 * @param angle the angle of the range reading.
  	 */
  	public SimpleRangeReading(double value, Angle angle) {
  		super(value, angle);
  	}
  	
  	/**
  	 * Generates noise onto the range reading.
  	 * @return a new range reading with noise applied.
  	 */
  	public AbstractRangeReading addRangeNoise() {
  		if(Double.isInfinite(getValue())) return this;
  		final double adaptedRangeReading = Util.generateRandomDoubleBetween(getValue() - RANGE_NOISE, getValue() + RANGE_NOISE);
  		return new SimpleRangeReading(adaptedRangeReading,getAngle());
  	}
  
  	@Override
  	public double calculateWeight(AbstractRangeReading secondRange) {
  		final AbstractRangeReading firstRange = addRangeNoise();
  		if(firstRange.getValue() < 0 || secondRange.getValue() < 0) return 0;
  		if(Double.isInfinite(firstRange.getValue()) && Double.isInfinite(secondRange.getValue())) return 1;
  		final double firstRangeValue;
  		if(Double.isInfinite(firstRange.getValue()) || firstRange.getValue() > SENSOR_RANGE) firstRangeValue = SENSOR_RANGE;
  		else firstRangeValue = firstRange.getValue();
  		final double secondRangeValue;
  		if(Double.isInfinite(secondRange.getValue()) || secondRange.getValue() > SENSOR_RANGE) secondRangeValue = SENSOR_RANGE;
  		else secondRangeValue = secondRange.getValue();
  		final double delta = Math.abs(firstRangeValue - secondRangeValue);
  		if(delta > BAD_DELTA) return 0.0f;
  		return (float) (1.0d - delta / BAD_DELTA);
  	}
  }
  