Skip to content

Commit

Permalink
Fix an issue where the KOMs would not be rendered correctly on the el…
Browse files Browse the repository at this point in the history
…evation profile
  • Loading branch information
sandermvanvliet committed Jul 12, 2023
1 parent 4a8f55e commit e9e0d96
Show file tree
Hide file tree
Showing 4 changed files with 334 additions and 38 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,8 @@ internal class CalculatedElevationProfile
public ImmutableList<int> ElevationLines { get; }
public ImmutableArray<TrackPoint> Points { get; }

private CalculatedElevationProfile(
IEnumerable<ElevationGroup> elevationGroups,
private CalculatedElevationProfile(IEnumerable<ElevationGroup> elevationGroups,
List<TrackPoint> trackPoints,
double minAltitude,
double maxAltitude,
double totalDistance)
Expand All @@ -33,7 +33,7 @@ internal class CalculatedElevationProfile
AltitudeDelta = minAltitude < 0 ? -minAltitude + maxAltitude : maxAltitude;
ElevationGroups = elevationGroups.ToImmutableList();
ElevationLines = CalculateElevationLines();
Points = ElevationGroups.SelectMany(eg => eg.Points).ToImmutableArray();
Points = trackPoints.ToImmutableArray();// ElevationGroups.SelectMany(eg => eg.Points).ToImmutableArray();
}

private ImmutableList<int> CalculateElevationLines()
Expand Down Expand Up @@ -79,6 +79,7 @@ private ImmutableList<int> CalculateElevationLines()

private static CalculatedElevationProfile Empty => new(
new List<ElevationGroup>(),
new List<TrackPoint>(),
0,
0,
0
Expand Down Expand Up @@ -162,6 +163,7 @@ internal static CalculatedElevationProfile From(PlannedRoute? route, List<Segmen

var elevationGroups = new List<ElevationGroup>();
ElevationGroup? currentGroup = null;
var overallIndex = 0;

foreach (var point in routePoints)
{
Expand All @@ -176,7 +178,7 @@ internal static CalculatedElevationProfile From(PlannedRoute? route, List<Segmen
DistanceFromLast = distanceFromLast,
DistanceOnSegment = distanceOnRoute,
Segment = point.Segment, // Copy
Index = point.Index // Copy
Index = overallIndex++ // Recalculate this
};

var grade = previousPoint == null
Expand Down Expand Up @@ -214,8 +216,9 @@ internal static CalculatedElevationProfile From(PlannedRoute? route, List<Segmen

return new CalculatedElevationProfile(
elevationGroups,
minAltitude,
maxAltitude,
trackPoints,
minAltitude,
maxAltitude,
trackPoints[^1].DistanceOnSegment /* we can cheat here as we've already calculated it above */);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ public class ElevationProfileLayeredRenderOperation: ICustomDrawOperation
SkiaPaints.ElevationProfileGradeEightPaint,
SkiaPaints.ElevationProfileGradeTenPaint
};
private IEnumerable<Segment>? _climbMarkersOnRoute;
private List<(Segment Climb, TrackPoint Start, TrackPoint Finish)> _climbMarkersOnRoute;
private readonly SKPaint _finishLinePaint;
private readonly SKPaint _circlePaint;
private readonly SKPaint _finishCirclePaint;
Expand Down Expand Up @@ -79,10 +79,84 @@ public ElevationProfileLayeredRenderOperation()
set
{
_route = value;
_elevationProfile = CalculatedElevationProfile.From(_route, Segments);
_renderParameters = RenderParameters.From(RenderMode, Bounds, _elevationProfile, RiderPosition, Markers);
_elevationProfile.CalculatePathsForElevationGroups(_renderParameters);

if (_route != null && Markers != null && Segments != null)
{
_elevationProfile = CalculatedElevationProfile.From(_route, Segments);
_renderParameters =
RenderParameters.From(RenderMode, Bounds, _elevationProfile, RiderPosition, Markers);
_elevationProfile.CalculatePathsForElevationGroups(_renderParameters);

_climbMarkersOnRoute = CalculateClimbMarkers(_route, Markers.Where(m => m.Type == SegmentType.Climb).ToList(), Segments);
}
else
{
// Reset everything
_elevationProfile = null;
_renderParameters = null;
_climbMarkersOnRoute = new List<(Segment Climb, TrackPoint Start, TrackPoint Finish)>();
}
}
}

public static List<(Segment Climb, TrackPoint Start, TrackPoint Finish)> CalculateClimbMarkers(PlannedRoute plannedRoute, List<Segment> markers, List<Segment> segments)
{
var elevationProfile = CalculatedElevationProfile.From(plannedRoute, segments);

var result = new List<(Segment Climb, TrackPoint Start, TrackPoint Finish)>();
Segment? currentClimb = null;
TrackPoint? start = null;

var index = 0;
while (index < elevationProfile.Points.Length)
{
var point = elevationProfile.Points[index];

if (currentClimb == null)
{
var climb = markers.SingleOrDefault(m => m.A.IsCloseTo(point));

if (climb != null)
{
currentClimb = climb;
start = point;
}
else
{
index++;
continue;
}
}

while (index < elevationProfile.Points.Length)
{
var nextPoint = elevationProfile.Points[index];
// Check if this point is still on the climb
if (currentClimb.Contains(nextPoint))
{
index++;
continue;
}

// Check if the last point was close to the end of the segment
if (currentClimb.B.IsCloseTo(elevationProfile.Points[index - 1]))
{
// Yup, add this climb
result.Add((
currentClimb,
start,
finish: elevationProfile.Points[index - 1]
));
}

currentClimb = null;
start = null;

break;
}
}

return result;
}

public Rect Bounds
Expand Down Expand Up @@ -231,7 +305,7 @@ private void RenderElevationLines(SKCanvas canvas, RenderParameters renderParame
List<Segment>? markers,
CalculatedElevationProfile elevationProfile)
{
if (markers == null || !markers.Any())
if (_climbMarkersOnRoute == null)
{
return;
}
Expand All @@ -242,37 +316,13 @@ private void RenderElevationLines(SKCanvas canvas, RenderParameters renderParame

// Because we flipped, we also need to translate
canvas.Translate(renderParameters.TranslateX, -renderParameters.PlotHeight);

var climbMarkersOnRoute = _climbMarkersOnRoute;

if (climbMarkersOnRoute == null)
foreach (var climbMarker in _climbMarkersOnRoute)
{
var climbMarkers = markers.Where(m => m.Type == SegmentType.Climb).ToList();

_climbMarkersOnRoute = climbMarkersOnRoute = elevationProfile
.Points
.Select(point => new
{
Point = point,
Marker = climbMarkers.FirstOrDefault(m => m.Contains(point))
})
.Where(x => x.Marker != null)
.GroupBy(x => x.Marker!.Id, x => x.Marker!, (_, values) => values.First())
.ToList();
DrawStartMarker(canvas, climbMarker.Start, renderParameters);
DrawFinishFlag(canvas, climbMarker.Finish, renderParameters);
}

foreach (var climbMarker in climbMarkersOnRoute)
{
var closestA = elevationProfile.GetClosestPointOnRoute(climbMarker.A);
var closestB = elevationProfile.GetClosestPointOnRoute(climbMarker.B);

if (closestA != null && closestB != null && closestA.DistanceOnSegment < closestB.DistanceOnSegment)
{
DrawStartMarker(canvas, closestA, renderParameters);
DrawFinishFlag(canvas, closestB, renderParameters);
}
}

// Back to normal
canvas.Restore();
}
Expand Down
5 changes: 5 additions & 0 deletions src/RoadCaptain/Segment.cs
Original file line number Diff line number Diff line change
Expand Up @@ -377,5 +377,10 @@ public bool Contains(TrackPoint position, out TrackPoint? match)

return false;
}

public override string ToString()
{
return $"segment {Id}";
}
}
}
Loading

0 comments on commit e9e0d96

Please sign in to comment.