+
+ /**
+ * Create waypoints for the halfway markers
+ */
+ private void createHalfwayWaypoints()
+ {
+ // Calculate the details of the whole track so we can see what to halve
+ final int numPoints = _app.getTrackInfo().getTrack().getNumPoints();
+ RangeStats totalStats = new RangeStats();
+ DataPoint currPoint = null;
+ for (int i=0; i<numPoints; i++)
+ {
+ currPoint = _app.getTrackInfo().getTrack().getPoint(i);
+ totalStats.addPoint(currPoint);
+ }
+ // Calculate total moving distance of track
+ final double totalDist = totalStats.getMovingDistanceKilometres();
+ // If the track has altitudes, also calculate total climb and total descent
+ final double totalClimb = totalStats.getMovingAltitudeRange().getClimb(UnitSetLibrary.UNITS_METRES);
+ final double totalDescent = totalStats.getMovingAltitudeRange().getDescent(UnitSetLibrary.UNITS_METRES);
+
+ final double halfDistance = totalDist / 2.0;
+ final double halfClimb = totalClimb / 2.0;
+ final double halfDescent = totalDescent / 2.0;
+
+ // Now loop through points again, looking for the halfway points
+ RangeStats partialStats = new RangeStats();
+ DataPoint prevPoint = null;
+ boolean createdDistance = false, createdClimb = false, createdDescent = false;
+ double prevDistance = 0.0, prevClimb = 0.0, prevDescent = 0.0;
+ for (int i=0; i<numPoints; i++)
+ {
+ currPoint = _app.getTrackInfo().getTrack().getPoint(i);
+ partialStats.addPoint(currPoint);
+ if (!currPoint.isWaypoint())
+ {
+ // distance
+ if (!createdDistance && totalDist > 0.0)
+ {
+ final double currDist = partialStats.getMovingDistanceKilometres();
+ createdDistance = processHalfValue(prevPoint, prevDistance, halfDistance,
+ currPoint, currDist, HalfwayType.HALF_DISTANCE);
+ prevDistance = currDist;
+ }
+ // climb
+ if (!createdClimb && totalClimb > 0.0)
+ {
+ final double currClimb = partialStats.getMovingAltitudeRange().getClimb(UnitSetLibrary.UNITS_METRES);
+ createdClimb = processHalfValue(prevPoint, prevClimb, halfClimb,
+ currPoint, currClimb, HalfwayType.HALF_CLIMB);
+ prevClimb = currClimb;
+ }
+ // descent
+ if (!createdDescent && totalDescent > 0.0)
+ {
+ final double currDescent = partialStats.getMovingAltitudeRange().getDescent(UnitSetLibrary.UNITS_METRES);
+ createdDescent = processHalfValue(prevPoint, prevDescent, halfDescent,
+ currPoint, currDescent, HalfwayType.HALF_DESCENT);
+ prevDescent = currDescent;
+ }
+
+ prevPoint = currPoint;
+ }
+ }
+ }
+
+ /**
+ * Consider a pair of points in the track to see if a new halfway marker should be inserted between them
+ * @param inPrevPoint previous point
+ * @param inPrevValue value of function at this previous point
+ * @param inTargetValue target halfway value
+ * @param inCurrPoint current point
+ * @param inCurrValue value of function at this current point
+ * @param inType type of halfway point
+ */
+ private boolean processHalfValue(DataPoint inPrevPoint, double inPrevValue, double inTargetValue,
+ DataPoint inCurrPoint, double inCurrValue, HalfwayType inType)
+ {
+ if (inPrevValue <= inTargetValue && inCurrValue >= inTargetValue)
+ {
+ // Calculate position of limit between the two points
+ final double valueBeforeBreak = inTargetValue - inPrevValue;
+ final double valueAfterBreak = inCurrValue - inTargetValue;
+ final double fractionFromPrev = valueBeforeBreak / (valueBeforeBreak + valueAfterBreak);
+ DataPoint marker = DataPoint.interpolate(inPrevPoint, inCurrPoint, fractionFromPrev);
+ marker.setFieldValue(Field.WAYPT_NAME, createHalfwayName(inType), false);
+ _pointsToAdd.add(marker);
+ return true;
+ }
+ return false;
+ }
+
+ /**
+ * Create the name of the halfway point according to type
+ * @param inType type of point
+ */
+ private String createHalfwayName(HalfwayType inType)
+ {
+ String typeString = null;
+ switch (inType)
+ {
+ case HALF_DISTANCE:
+ typeString = "distance";
+ break;
+ case HALF_CLIMB:
+ typeString = "climb";
+ break;
+ case HALF_DESCENT:
+ typeString = "descent";
+ break;
+ }
+ if (typeString != null)
+ {
+ return I18nManager.getText("dialog.markers.half." + typeString);
+ }
+ return "half";
+ }