// calculates the distance from start to the point projected onto the line private double getDistanceAlongLine(GpxPoint point) { double distanceA = 1000 * GpxParser.gpsToGpx(startingPoint).GetDistanceFrom(point); // distances to start point double cos_phi = getCosPhi(point); return(cos_phi * distanceA); }
// calculates cos(phi) where phi is the angle between the line and a line from the start point to the current point private double getCosPhi(GpxPoint point) { // distances to start/end point double distanceA = 1000 * GpxParser.gpsToGpx(startingPoint).GetDistanceFrom(point); double distanceB = 1000 * GpxParser.gpsToGpx(endPoint).GetDistanceFrom(point); // using cosine theorem; phi is the angle between the line and a line from the start point to the current point double cos_phi = (lineLength * lineLength + distanceA * distanceA - distanceB * distanceB) / (2 * lineLength * distanceA); if (cos_phi > 1) // prevents errors due to rounding { return(1); } else if (cos_phi < -1) { return(-1); } else { return(cos_phi); } }
public CalculationResult calculate() { CalculationResult result; lineLength = 1000 * GpxParser.gpsToGpx(startingPoint).GetDistanceFrom(GpxParser.gpsToGpx(endPoint)); // length of the line // calculate deviations List <double> deviations = new List <double>(); List <double> distancesAlongLine = new List <double>(); foreach (GpxPoint point in gpxData) { deviations.Add(getDeviation(point)); distancesAlongLine.Add(getDistanceAlongLine(point)); } // calculate metrics result.deviations = deviations; result.awgDeviation = getAwgDeviation(deviations); result.awgSquareDeviation = getAwgSquareDeviation(deviations); result.area = getArea(deviations, distancesAlongLine); result.areaNorm = result.area / lineLength; result.over10 = percentageOverThreshold(deviations, 10); result.over25 = percentageOverThreshold(deviations, 25); result.over50 = percentageOverThreshold(deviations, 50); result.over80 = percentageOverThreshold(deviations, 80); result.over120 = percentageOverThreshold(deviations, 120); result.numOver10 = numberOverThreshold(deviations, 10); result.numOver25 = numberOverThreshold(deviations, 25); result.numOver50 = numberOverThreshold(deviations, 50); result.numOver80 = numberOverThreshold(deviations, 80); result.numOver120 = numberOverThreshold(deviations, 120); result.maxDeviation = getMaximumDeviation(deviations); // create histogram data result.histogramData = getHistogramData(deviations); return(result); }
// calculates the deviation of a point to the line private double getDeviation(GpxPoint point) { double distanceA = 1000 * GpxParser.gpsToGpx(startingPoint).GetDistanceFrom(point); // distances to start point double cos_phi = getCosPhi(point); double sin_phi = System.Math.Sqrt(1 - cos_phi * cos_phi); // deviation is the heigth of the triangle double deviation = sin_phi * distanceA; // if point is left of the line, deviation is negativ double deltaLong = endPoint.Longitude - startingPoint.Longitude; double deltaLat = endPoint.Latitude - startingPoint.Latitude; double slope = deltaLat / deltaLong; if (slope * (point.Longitude - startingPoint.Longitude) < point.Latitude - startingPoint.Latitude) { deviation *= -1; } if (startingPoint.Longitude > endPoint.Longitude) // the direction you walk the line changes left/right { deviation *= -1; } return(deviation); }