protected override void Calculate() { var cachedProperty = GetFromCache(); if (cachedProperty != null) { value = cachedProperty.Value; return; } var currentLongLat = Session.Route.GetLocationFromParameterizedLocation(End); var lastPL = new ParameterizedLocation(End); ParameterizedLocation thisPL; ParameterizedLocation thresholdPL; double lastNodeDistance = 0; double thisNodeDistance = 0; while (true) { thisPL = Session.Route.GetNextPLNode(lastPL, ParameterizedLocation.Direction.Backward); if (thisPL == null || Session.Route.IsFirstPLInSegment(thisPL) || thisPL < Start) { break; } var longLat = Session.Route.GetLocationFromParameterizedLocation(thisPL); thisNodeDistance = LinearAlgebraUtil.DistancePointToPointLongLat(longLat, currentLongLat); if (thisNodeDistance > DistanceThreshold) { break; } lastPL = thisPL; lastNodeDistance = thisNodeDistance; } if (thisPL == null) { thisPL = new ParameterizedLocation(Start.SegmentIndex, 0); } if (Session.Route.IsFirstPLInSegment(thisPL)) { thresholdPL = thisPL; } else if (thisPL < Start) { thresholdPL = new ParameterizedLocation(Start); } else { var t = thisNodeDistance - lastNodeDistance == 0 ? 1 : (DistanceThreshold - lastNodeDistance) / (thisNodeDistance - lastNodeDistance); thresholdPL = new ParameterizedLocation(thisPL.SegmentIndex, lastPL.Value - t * (lastPL.Value - thisPL.Value)); } value = Session.Route.GetTimeFromParameterizedLocation(End) - Session.Route.GetTimeFromParameterizedLocation(thresholdPL); AddToCache(); }
protected override void Calculate() { var cachedProperty = GetFromCache(); if (cachedProperty != null) { value = cachedProperty.Value; return; } var routeLength = (double)new RouteDistance(Session, Start, End, RetrieveExternalProperty).Value; var altitudeDifference = (double?)new AltitudeDifference(Session, Start, End, RetrieveExternalProperty).Value; if (altitudeDifference.HasValue) { value = LinearAlgebraUtil.ToDegrees(Math.Atan2(altitudeDifference.Value, routeLength)); } else { value = null; } AddToCache(); }
protected override void Calculate() { var cachedProperty = GetFromCache(); if (cachedProperty != null) { value = cachedProperty.Value; return; } double sum = 0; var spanStartTime = Session.Route.GetTimeFromParameterizedLocation(Start); var spanEndTime = Session.Route.GetTimeFromParameterizedLocation(End); int lapIndex = 0; // examine each lap until end time while (Session.Route.LapTimes[lapIndex] < spanEndTime && lapIndex < Session.Route.LapTimes.Count - 1) { var thisLapStartPL = Session.Route.GetParameterizedLocationFromTime(Session.Route.LapTimes[lapIndex]); var thisLapEndPL = Session.Route.GetParameterizedLocationFromTime(Session.Route.LapTimes[lapIndex + 1]); ParameterizedLocation startPL = null; // span starts somewhere in this lap? if (spanStartTime >= Session.Route.LapTimes[lapIndex] && spanStartTime < Session.Route.LapTimes[lapIndex + 1]) { startPL = Start; } // span starts before this lap? else if (spanStartTime < Session.Route.LapTimes[lapIndex]) { startPL = thisLapStartPL; } ParameterizedLocation endPL = null; // span ends somewhere in this lap? if (spanEndTime >= Session.Route.LapTimes[lapIndex] && spanEndTime < Session.Route.LapTimes[lapIndex + 1]) { endPL = End; } // span ends after this lap? else if (spanEndTime >= Session.Route.LapTimes[lapIndex + 1]) { endPL = thisLapEndPL; } if (startPL != null && endPL != null) { // this lap contains some of the desired distance to be measured for (var i = startPL.SegmentIndex; i <= endPL.SegmentIndex; i++) { var thisSegmentStartPL = new ParameterizedLocation(i, 0); var thisSegmentEndPL = new ParameterizedLocation(i, Session.Route.Segments[i].Waypoints.Count - 1); if (thisSegmentStartPL < startPL) { thisSegmentStartPL = startPL; } if (thisSegmentEndPL > endPL) { thisSegmentEndPL = endPL; } var thisLapStartLocation = Session.Route.GetLocationFromParameterizedLocation(thisLapStartPL); var thisLapEndLocation = Session.Route.GetLocationFromParameterizedLocation(thisLapEndPL); var projectionOrigin = thisLapStartLocation / 2 + thisLapEndLocation / 2; var startLocationPoint = Session.Route.GetLocationFromParameterizedLocation(startPL).Project(projectionOrigin); var endLocationPoint = Session.Route.GetLocationFromParameterizedLocation(endPL).Project(projectionOrigin); var thisLapStartLocationPoint = thisLapStartLocation.Project(projectionOrigin); var thisLapEndLocationPoint = thisLapEndLocation.Project(projectionOrigin); double t0; double t1; // get start and end point parameterized lcoations (t0 and t1) on straight line LinearAlgebraUtil.ClosestDistancePointToLine(startLocationPoint, thisLapStartLocationPoint, thisLapEndLocationPoint, out t0); LinearAlgebraUtil.ClosestDistancePointToLine(endLocationPoint, thisLapStartLocationPoint, thisLapEndLocationPoint, out t1); t0 = Math.Max(0, Math.Min(1, t0)); t1 = Math.Max(0, Math.Min(1, t1)); sum += (t1 - t0) * LinearAlgebraUtil.DistancePointToPointLongLat(thisLapStartLocation, thisLapEndLocation); } } lapIndex++; } value = sum; AddToCache(); }