content: package tim.prune.data;
  
  /**
   * Abstract class to hold static calculation functions
   * for gradient (like glide slope)
   */
  public abstract class GradientCalculator
  {
  	/**
  	 * Calculate the gradient value of the track at the specified index
  	 * @param inTrack track object
  	 * @param inIndex index of point to calculate gradient for
  	 * @param inValue object in which to place result of calculation
  	 */
  	public static void calculateGradient(Track inTrack, int inIndex, SpeedValue inValue)
  	{
  		if (inValue != null)
  		{
  			inValue.setInvalid();
  		}
  		if (inTrack == null || inIndex < 0 || inValue == null)
  		{
  			System.err.println("Cannot calculate gradient for index " + inIndex);
  			return;
  		}
  
  		// If no altitude or it's a waypoint then no gradient either
  		DataPoint point = inTrack.getPoint(inIndex);
  		if (point == null || !point.hasAltitude() || point.isWaypoint()) {
  			return;
  		}
  
  		// If the point has horizontal and vertical speeds already then just use those
  		if (point.hasHSpeed() && point.hasVSpeed()) {
  			inValue.setValue(point.getVSpeed().getValueInMetresPerSec() / point.getHSpeed().getValueInMetresPerSec());
  		}
  		else if (!point.getSegmentStart())
  		{
  			// Use the previous track point and the next track point
  			DataPoint p = inTrack.getPreviousTrackPoint(inIndex-1);
  			DataPoint q = inTrack.getNextTrackPoint(inIndex+1);
  			if (p != null && q != null && !q.getSegmentStart()
  				&& p.hasAltitude() && q.hasAltitude())
  			{
  				final double horizRads = DataPoint.calculateRadiansBetween(p, point) +
  					DataPoint.calculateRadiansBetween(point, q);
  				final double horizDist = Distance.convertRadiansToDistance(horizRads, UnitSetLibrary.UNITS_METRES);
  				final double heightDiff = q.getAltitude().getMetricValue() - p.getAltitude().getMetricValue();
  				// Get gradient in radians
  				final double gradient = Math.atan2(heightDiff, horizDist);
  				inValue.setValue(gradient);
  			}
  		}
  		// otherwise, just leave value as invalid
  	}
  }
  