public static IList <IActivity> GetSimilarRoutes(IGPSRoute route, IList <IActivity> activities, System.Windows.Forms.ProgressBar progressBar) { IList <IActivity> results = null; try { if (progressBar == null) { progressBar = new System.Windows.Forms.ProgressBar(); } if (GetUniqueRoutes != null) { MethodInfo methodInfo = GetUniqueRoutes.GetMethod(findSimilarRouteSnippets); object resultFromURPlugIn = methodInfo.Invoke(route, new object[] { route, activities, progressBar }); results = (IList <IActivity>)resultFromURPlugIn; } } catch (Exception e) { // Log error? _uniqueRoutes = null; throw new Exception(string.Format(IntegrationUtility.OtherPluginExceptionText, UniquePlugin + ".dll", UniqueRoutesPluginName) + Environment.NewLine, e); } if (GetUniqueRoutes == null) { throw new Exception(string.Format(IntegrationUtility.OtherPluginExceptionText, UniquePlugin + ".dll", UniqueRoutesPluginName) + Environment.NewLine); } return(results); }
public GPSGrid(GPSGrid refGrid, IGPSRoute route, double BWidthFactor, double DistFactor, bool isDist) { m_Distance = DistFactor * Settings.Radius; m_Grid = new Dictionary<int, IDictionary<int, IList<int>>>(); m_Route = route; //Just copy the reference if (refGrid == null) { //Set grid size from aprox distance for reference //See Trails plugin, TrailsGPSLocation.getGPSBounds() m_latWidth = BWidthFactor * Settings.Radius / 110574 * 1.005F; m_lngWidth = BWidthFactor * Settings.Radius / 111132 / Math.Cos(m_Route[0].Value.LongitudeDegrees * Math.PI / 180); } else { m_latWidth = refGrid.m_latWidth; m_lngWidth = refGrid.m_lngWidth; } if (isDist) { m_Dist = m_Route.GetDistanceMetersTrack(); } else { m_Dist = null; } for (int i = 0; i < m_Route.Count; i++ ) { addGrid(i); } }
internal static void setCapacity(IGPSRoute t, int v) { #if ST_3_1_5314 if (t is ZoneFiveSoftware.Common.Data.GPS.GPSRoute2) { ((ZoneFiveSoftware.Common.Data.GPS.GPSRoute2)t).Capacity = v; } #endif }
public GlobalsatRoute(string name, IGPSRoute route) { this.Name = name; this.wpts = new List <GlobalsatWaypoint>(); foreach (ZoneFiveSoftware.Common.Data.ITimeValueEntry <IGPSPoint> g in route) { this.wpts.Add(new GlobalsatWaypoint("", 0, (short)g.Value.ElevationMeters, g.Value.LatitudeDegrees, g.Value.LongitudeDegrees)); } }
public static IList <IList <IGPSPoint> > GpsPoints(IGPSRoute gpsRoute, IValueRangeSeries <DateTime> selections) { IList <IList <IGPSPoint> > result = new List <IList <IGPSPoint> >(); if (selections != null && selections.Count > 0 && gpsRoute != null && gpsRoute.Count > 1) { //selection and gps points are sorted without overlap so traverse over gps points only once //(previous version had much more complicated version, that also accounted for pauses) int i = 0; foreach (IValueRange <DateTime> sel in selections) { IList <IGPSPoint> track = new List <IGPSPoint>(); //Use start/end "with priority", even if extra points are added. Care needed if returning GPSRoute DateTime t = DateTimeRangeSeries.Latest(sel.Lower, gpsRoute.StartTime); ITimeValueEntry <IGPSPoint> pt = gpsRoute.GetInterpolatedValue(t); if (pt != null) { track.Add(pt.Value); } while (i < gpsRoute.Count) { ITimeValueEntry <IGPSPoint> entry = gpsRoute[i]; DateTime time = gpsRoute.EntryDateTime(entry); i++; if (sel.Lower > time) { continue; } if (sel.Upper < time) { //Do not increase counter here, it could be needed i--; break; } track.Add(entry.Value); } t = DateTimeRangeSeries.Earliest(sel.Upper, gpsRoute.StartTime.AddSeconds(gpsRoute.TotalElapsedSeconds)); pt = gpsRoute.GetInterpolatedValue(t); if (pt != null) { track.Add(pt.Value); } result.Add(track); } } return(result); }
public static IList<IActivity> findSimilarRouteSnippets(IGPSRoute route, IList<IActivity> activities, System.Windows.Forms.ProgressBar progressBar) { return GpsRunningPlugin.Source.UniqueRoutes.findSimilarRoutes(route, activities, progressBar); }
public GPSGrid(GPSGrid refGrid, IGPSRoute route) : this(refGrid, route, 1, 1, false) { }
/// <summary> /// Used to generate the record properties of the supplied activity /// </summary> /// <param name="activity">The full activity for the record</param> /// <param name="category">The Record Category for this record</param> /// <param name="gpsTrack">The GPS route of the actual record</param> /// <param name="hrTrack">The HR track of the actual record</param> /// <param name="pwrTrack">The power track of the actual record</param> /// <param name="cadTrack">The cadence track of the actual record</param> public Record(IActivity activity, RecordCategory category, IGPSRoute gpsTrack, INumericTimeDataSeries hrTrack, INumericTimeDataSeries pwrTrack, INumericTimeDataSeries cadTrack, IDistanceDataTrack distTrack, INumericTimeDataSeries elevTrack, DateTime activityStartTime) { // Create new activity from template IActivity recActivity = (IActivity)Activator.CreateInstance(activity.GetType()); // HACK: Manually Clone 'activity' until a better way is found recActivity.Category = activity.Category; recActivity.DistanceMetersTrack = distTrack; recActivity.ElevationMetersTrack = elevTrack; recActivity.GPSRoute = gpsTrack; recActivity.HasStartTime = activity.HasStartTime; recActivity.HeartRatePerMinuteTrack = hrTrack; recActivity.Intensity = activity.Intensity; recActivity.Location = activity.Location; recActivity.Name = activity.Name; recActivity.PowerWattsTrack = pwrTrack; recActivity.CadencePerMinuteTrack = cadTrack; recActivity.Weather.Conditions = activity.Weather.Conditions; recActivity.Weather.CurentDirectionDegrees = activity.Weather.CurentDirectionDegrees; recActivity.Weather.CurentSpeedKilometersPerHour = activity.Weather.CurentSpeedKilometersPerHour; recActivity.Weather.HumidityPercent = activity.Weather.HumidityPercent; recActivity.Weather.TemperatureCelsius = activity.Weather.TemperatureCelsius; recActivity.Weather.WindDirectionDegrees = activity.Weather.WindDirectionDegrees; recActivity.Weather.WindSpeedKilometersPerHour = activity.Weather.WindSpeedKilometersPerHour; // Set the start time for the record activity recActivity.StartTime = activityStartTime; // Set up the activity info for pulling summary data ActivityInfo info = ActivityInfoCache.Instance.GetInfo(recActivity); // Set the record category this.category = category; // Max and Min elevation seen over the route float maxE = float.NegativeInfinity; float minE = float.PositiveInfinity; if (activity.GPSRoute != null && activity.GPSRoute.Count > 0) { GPSRoute startRoute = new GPSRoute(); for (int i = 0; i < activity.GPSRoute.Count; i++) { GPSPoint p = (GPSPoint)activity.GPSRoute[i].Value; if (p.ElevationMeters > maxE) { maxE = p.ElevationMeters; } if (p.ElevationMeters < minE) { minE = p.ElevationMeters; } if (gpsTrack.Count == 0) { break; } if (p.Equals((GPSPoint)gpsTrack[0].Value)) { break; } else { startRoute.Add(activity.GPSRoute.EntryDateTime(activity.GPSRoute[i]), p); } } startDistance = startRoute.TotalDistanceMeters; } else if (activity.ElevationMetersTrack != null) { for (int i = 0; i < activity.ElevationMetersTrack.Count; i++) { if (activity.ElevationMetersTrack[i].Value > maxE) { maxE = activity.ElevationMetersTrack[i].Value; } if (activity.ElevationMetersTrack[i].Value < maxE) { minE = activity.ElevationMetersTrack[i].Value; } } startDistance = 0; } this.maxElevation = maxE; this.minElevation = minE; this.trueStartDate = activity.StartTime; this.activity = recActivity; }
public static IDictionary<IActivity, IList<PointInfo[]>> findSimilarPoints(IGPSRoute refRoute, IList<IActivity> activities, System.Windows.Forms.ProgressBar progressBar) { return findSimilarPoints(refRoute, null, activities, progressBar); }
private static IList<IActivity> findSimilarRoutes(IGPSRoute refRoute, string refId, IList<IActivity> activities, bool activityCompare, System.Windows.Forms.ProgressBar progressBar) { if (progressBar == null) { progressBar = new System.Windows.Forms.ProgressBar(); } IList<IActivity> result = new List<IActivity>(); if (refRoute == null || refRoute.Count == 0) return result; if (activities == null) { activities = getBaseActivities(); } progressBar.Value = 0; progressBar.Minimum = 0; progressBar.Maximum = activities.Count; GPSGrid refGrid = new GPSGrid(null, refRoute); IDictionary<string, int> beginningPoints = new Dictionary<string, int>(); IDictionary<string, int> endPoints = new Dictionary<string, int>(); setBeginningAndEndPoints(refId, refRoute, activityCompare, beginningPoints, endPoints); if (!beginningPoints.ContainsKey(refId) || beginningPoints[refId] <= -1 || endPoints[refId] <= -1) { //The settings does not include any points return result; } foreach (IActivity otherActivity in activities) { if (otherActivity.GPSRoute != null && otherActivity.GPSRoute.Count > 0 && //Simple prune, eliminating routes not possibly common otherActivity.GPSRoute[0].Value.DistanceMetersToPoint(refRoute[0].Value) < otherActivity.GPSRoute.TotalDistanceMeters + refRoute.TotalDistanceMeters) { setBeginningAndEndPoints(otherActivity, activityCompare, beginningPoints, endPoints); //int noOfPoints = otherActivity.GPSRoute.Count; if (beginningPoints[otherActivity.ReferenceId] > -1 && endPoints[otherActivity.ReferenceId] > -1) { int pointsOutside = 0; bool inBand = true; int direction = 0; int prevMatch = -1; //IGPSBounds otherBounds = GPSBounds.FromGPSRoute(otherActivity.GPSRoute); GPSGrid otherGrid = new GPSGrid(refGrid, otherActivity); //Check if the reference route fits in the other activity for (int i = beginningPoints[refId]; i <= endPoints[refId]; i++) { IGPSPoint point = refRoute[i].Value; int closests = otherGrid.getClosePoint(point); if (closests < 0) { pointsOutside++; if (pointsOutside / ((double)refRoute.Count) > Settings.ErrorMargin) { inBand = false; break; } } else if (Settings.HasDirection) { int currMatch = closests;// grid.getCloseSinglePoint(point); if (currMatch > prevMatch) { direction++; } else if (currMatch < prevMatch) { direction--; } prevMatch = currMatch; ////Find direction. Works well when the routes are not overlapping and have similar length ////Use all matching points to get majority decision ////All matching points from grid.getAllClose would be better but is significantly slower //bool inOtherLowerHalf = i < otherActivity.GPSRoute.Count / 2; //bool inLowerHalf = closests < refRoute.Count / 2; //if ((inLowerHalf && inOtherLowerHalf) || // (!inLowerHalf && !inOtherLowerHalf)) // direction++; //else // direction--; } } //Check if the other activity matches the reference route //Only used when comparing activities if (inBand && activityCompare) { pointsOutside = 0; for (int i = beginningPoints[otherActivity.ReferenceId]; i <= endPoints[otherActivity.ReferenceId]; i++) { IGPSPoint point = otherActivity.GPSRoute[i].Value; int closests = refGrid.getClosePoint(point); if (closests < 0) { pointsOutside++; if (pointsOutside / ((double)otherActivity.GPSRoute.Count) > Settings.ErrorMargin) { inBand = false; break; } } } } if (inBand && direction >= 0) { result.Add(otherActivity); } } } progressBar.Increment(1); } return result; }
public static IList<IActivity> findSimilarRoutes(IGPSRoute refRoute, IList<IActivity> activities, bool activityCompare, System.Windows.Forms.ProgressBar progressBar) { return findSimilarRoutes(refRoute, "", activities, activityCompare, progressBar); }
private static void setBeginningAndEndPoints(string activity, IGPSRoute gpsroute, bool beginEndCheck, IDictionary<string, int> beginningPoints, IDictionary<string, int> endPoints) { double length = 0; //prune with some searches beginningPoints[activity] = 0; endPoints[activity] = gpsroute.Count - 1; if (beginEndCheck) { length = Settings.IgnoreBeginning + Settings.IgnoreEnd; if (length > gpsroute.TotalDistanceMeters) { //not used at all beginningPoints[activity] = -1; endPoints[activity] = -1; return; } if (length > 0) { //Note: As we normally cover few points, this is faster than activity.GPSRoute.GetDistanceMetersTrack() //(and the distance track must be scanned, there is no simple way to get the index for a distance) //If the algoritm to calc dist is changed, this should be changed too IGPSPoint previous; if (Settings.IgnoreBeginning > 0) { length = 0; previous = null; for (int i = 0; i < gpsroute.Count; i++) { if (length >= Settings.IgnoreBeginning) { beginningPoints[activity] = i; break; } IGPSPoint point = gpsroute[i].Value; if (previous != null) length += point.DistanceMetersToPoint(previous); previous = point; } } if (Settings.IgnoreEnd > 0) { length = 0; previous = null; for (int i = gpsroute.Count - 1; i >= 0; i--) { IGPSPoint current = gpsroute[i].Value; if (length >= Settings.IgnoreEnd) { endPoints[activity] = i; break; } if (previous != null) length += previous.DistanceMetersToPoint(current); previous = current; } } } } }
public static IList<IList<IGPSPoint>> GpsPoints(IGPSRoute gpsRoute, IValueRangeSeries<DateTime> selections) { IList<IList<IGPSPoint>> result = new List<IList<IGPSPoint>>(); if (selections != null && selections.Count > 0 && gpsRoute != null && gpsRoute.Count > 1) { //selection and gps points are sorted without overlap so traverse over gps points only once //(previous version had much more complicated version, that also accounted for pauses) int i = 0; foreach (IValueRange<DateTime> sel in selections) { IList<IGPSPoint> track = new List<IGPSPoint>(); //Use start/end "with priority", even if extra points are added. Care needed if returning GPSRoute DateTime t = DateTimeRangeSeries.Latest(sel.Lower, gpsRoute.StartTime); ITimeValueEntry<IGPSPoint> pt = gpsRoute.GetInterpolatedValue(t); if (pt != null) { track.Add(pt.Value); } while (i < gpsRoute.Count) { ITimeValueEntry<IGPSPoint> entry = gpsRoute[i]; DateTime time = gpsRoute.EntryDateTime(entry); i++; if (sel.Lower > time) { continue; } if (sel.Upper < time) { //Do not increase counter here, it could be needed i--; break; } track.Add(entry.Value); } t = DateTimeRangeSeries.Earliest(sel.Upper, gpsRoute.StartTime.AddSeconds(gpsRoute.TotalElapsedSeconds)); pt = gpsRoute.GetInterpolatedValue(t); if (pt != null) { track.Add(pt.Value); } result.Add(track); } } return result; }
static bool getRestLap(int index, IGPSRoute route, IActivityLaps laps) { bool restLap = false; if (laps != null && laps.Count > 1) { restLap = laps[laps.Count - 1].Rest; for (int i = 0; i < laps.Count - 1; i++) { //End time is starttime for next lap //Go from first to second last to find where it fits (default is last, no end time there) if (0 > route.EntryDateTime(route[index]).CompareTo(laps[i + 1].StartTime)) { //time was in previous lap restLap = laps[i].Rest; break; } } } return restLap; }
public static IDictionary<IActivity, IList<PointInfo[]>> findSimilarPoints(IGPSRoute refRoute, IActivityLaps refLaps, IList<IActivity> activities, System.Windows.Forms.ProgressBar progressBar) { GPSGrid refGrid = new GPSGrid(null, refRoute, 1F, 0.5F, true); IDictionary<IActivity, IList<PointInfo[]>> result = new Dictionary<IActivity, IList<PointInfo[]>>(); double cumulativeAverageDist = 0; int noCumAv = 0; if (activities != null) { if (progressBar != null) { progressBar.Value = 0; progressBar.Minimum = 0; progressBar.Maximum = activities.Count; } foreach (IActivity otherActivity in activities) { const int ExtraGridIndex = 2; const float MaxDistDiffFactor = 0.1F; double minDistStretch = Settings.Radius * 2; result.Add(otherActivity, new List<PointInfo[]>()); IDistanceDataTrack distTrack = otherActivity.GPSRoute.GetDistanceMetersTrack(); int lastMatch = -1; //index of previous match int startMatch = -1; IndexDiffDist lastMatchRef = null; IndexDiffDist startMatchRef = null; IndexDiffDist lastIndex = null; for (int i = 0; i < otherActivity.GPSRoute.Count; i++) { IList<IndexDiffDist> currIndex = new List<IndexDiffDist>(); IndexDiffDist closeIndex = null; //Closest to current point IndexDiffDist nextIndex = null; //The best match in this stretch bool isEnd = true; //This is the end of a stretch, unless a matching point is found currIndex = refGrid.getAllCloseStretch(otherActivity.GPSRoute[i].Value); if (currIndex.Count > 0) { int prio = int.MaxValue; foreach (IndexDiffDist IndDist in currIndex) { if (IndDist.Index > -1) { //Get the closest good enough point - used at start and could restart current stretch if (closeIndex == null || //Close match in distance (Math.Abs(IndDist.Dist - distTrack[i].Value) < 3 * Settings.Radius) || //Close to other matches (Math.Abs(IndDist.Dist - distTrack[i].Value - cumulativeAverageDist) < Math.Abs(closeIndex.Dist - distTrack[i].Value - cumulativeAverageDist))) { closeIndex = IndDist; } //next in relation to previous match if (lastMatch > -1 && lastIndex != null) { //Only check forward, i.e follow the same direction //Use a close enough stretch //This is the iffiest part of the algorithm matching stretches... if ((IndDist.low >= lastIndex.low && IndDist.low <= lastIndex.high || IndDist.Index >= lastIndex.low && IndDist.Index <= lastIndex.high) && IndDist.Index >= lastIndex.Index) { //The grid overlaps the old grid //The matching index may be lower then this is a restart (this or prev match should then be dropped) if ((prio > 0 && (nextIndex == null || IndDist.Diff < nextIndex.Diff) && IndDist.Index >= lastIndex.Index)) { nextIndex = IndDist; prio = 0; } else if (prio >= 0 && (IndDist.Index > lastIndex.Index && (nextIndex == null || nextIndex.Index <= lastIndex.Index))) { nextIndex = IndDist; prio = 0; } else if (IndDist.Index == lastIndex.Index && (nextIndex == null || nextIndex.Index < lastIndex.Index)) { nextIndex = IndDist; prio = 0; } else if (prio > 10) { nextIndex = IndDist; prio = 10; } else if (nextIndex == null) { nextIndex = IndDist; prio = 10; } //else - not better } else if (( IndDist.low >= lastIndex.low && IndDist.low <= lastIndex.high + ExtraGridIndex || IndDist.Index >= lastIndex.low && IndDist.Index <= lastIndex.high + ExtraGridIndex)) { //Grids are not overlapping, but adjacent points match forward if (prio > 20 && IndDist.Index > lastIndex.Index) { nextIndex = IndDist; prio = 20; } else if (prio >= 20) { nextIndex = IndDist; prio = 20; } } else if (( Math.Abs(IndDist.Dist / lastIndex.Dist - 1) < MaxDistDiffFactor) && (prio > 20)) { nextIndex = IndDist; prio = 30; } } } } //Update if close enough if (closeIndex != null) { //TODO: This algorithm needs to prio correct direction better //nextInd is best match for the stretch, but closeIndex could be better if (nextIndex == null || (!nextIndex.Equals(closeIndex)) && ( //back match - prefer closer lastIndex.Index > nextIndex.Index || prio > 10 && (minDistStretch < distTrack[i].Value - distTrack[startMatch].Value || (Math.Abs(nextIndex.Dist - distTrack[i].Value) > Settings.Radius) || (Math.Abs(nextIndex.Dist - distTrack[i].Value - cumulativeAverageDist) > Math.Abs(closeIndex.Dist - distTrack[i].Value - cumulativeAverageDist))))) { //switch to closeIndex and ignore nextIndex nextIndex = closeIndex; //start of new stretch - use best match to reference activity startMatch = i; lastIndex = closeIndex; startMatchRef = closeIndex; } else { //The stretch continues isEnd = false; cumulativeAverageDist += (lastIndex.Diff - distTrack[i].Value - cumulativeAverageDist) / ++noCumAv; } } } if (isEnd && lastMatch >= 0) { // end match PointInfo[] s = new PointInfo[2]; s[0] = new PointInfo(-i - 1); s[1] = new PointInfo(-lastMatchRef.Index - 1); result[otherActivity].Add(s); } if (nextIndex != null) { lastIndex = nextIndex; lastMatchRef = lastIndex; lastMatch = i; PointInfo[] s = new PointInfo[2]; s[0] = new PointInfo(i, distTrack[i].Value, otherActivity.GPSRoute[i].ElapsedSeconds, getRestLap(i, otherActivity), startMatch + " " + lastMatch + " " + startMatchRef + " " + lastMatchRef); s[1] = new PointInfo(lastIndex.Index, lastIndex.Dist, refRoute[lastIndex.Index].ElapsedSeconds, getRestLap(lastIndex.Index, refRoute, refLaps)); result[otherActivity].Add(s); } else { lastMatch = -1; } } //add end marker if needed if (lastMatch > -1) { PointInfo[] s = new PointInfo[2]; s[0] = new PointInfo(-otherActivity.GPSRoute.Count); s[1] = new PointInfo(-1); result[otherActivity].Add(s); } if (progressBar != null) { progressBar.Increment(1); } } } return result; }
//Get the data in a generic Globalsat format, to separate ST public static IList <GhPacketBase.Train> ToGlobTrack(GlobalsatProtocol device, IList <IActivity> activities) { IList <GhPacketBase.Train> result = new List <GhPacketBase.Train>(); foreach (IActivity activity in activities) { IGPSRoute gpsRoute = activity.GPSRoute; GhPacketBase.Train train = new GhPacketBase.Train(); train.StartTime = activity.StartTime; train.TotalTime = TimeSpan.FromSeconds(gpsRoute.TotalElapsedSeconds); train.TotalDistanceMeters = (Int32)Math.Round(gpsRoute.TotalDistanceMeters); train.LapCount = 1; train.TotalCalories = (Int16)activity.TotalCalories; if (train.MaximumSpeed == 0 && train.TotalTime.TotalSeconds >= 1) { //Better than 0(?) - Info() could be used train.MaximumSpeed = train.TotalDistanceMeters / train.TotalTime.TotalSeconds; } train.MaximumHeartRate = (byte)activity.MaximumHeartRatePerMinuteEntered; train.AverageHeartRate = (byte)activity.AverageHeartRatePerMinuteEntered; train.TotalAscend = (Int16)activity.TotalAscendMetersEntered; train.TotalDescend = (Int16)activity.TotalDescendMetersEntered; train.AverageCadence = (Int16)activity.AverageCadencePerMinuteEntered; train.MaximumCadence = (Int16)activity.MaximumCadencePerMinuteEntered; train.AveragePower = (Int16)activity.AveragePowerWattsEntered; train.MaximumPower = (Int16)activity.MaximumPowerWattsEntered; //Some protocols send laps in separate header //Use common code instead of overiding this method //Laps are not implemented when sending, one lap hardcoded for (int j = 0; j < gpsRoute.Count; j++) { IGPSPoint point = gpsRoute[j].Value; GhPacketBase.TrackPoint trackpoint = new GhPacketBase.TrackPoint(); trackpoint.Latitude = point.LatitudeDegrees; trackpoint.Longitude = point.LongitudeDegrees; trackpoint.Altitude = (Int32)point.ElevationMeters; if (j == 0) { trackpoint.IntervalTime = 0; } else { #if ST_2_1 int intTime = gpsRoute[j].ElapsedSeconds - gpsRoute[j - 1].ElapsedSeconds; #else uint intTime = gpsRoute[j].ElapsedSeconds - gpsRoute[j - 1].ElapsedSeconds; #endif float dist = gpsRoute[j].Value.DistanceMetersToPoint(gpsRoute[j - 1].Value); if (intTime > 0) { trackpoint.IntervalTime = intTime; trackpoint.Speed = dist / intTime; } else { //Time is not really used - could probably be empty //The alternative would be to drop the points trackpoint.IntervalTime = 1; } } train.TrackPoints.Add(trackpoint); } train.TrackPointCount = (short)train.TrackPoints.Count; result.Add(train); } return(result); }
public static IDictionary<IActivity, PointInfo[]> getCommonSpeed(IGPSRoute refRoute, IList<IActivity> activities, bool useActive) { IDictionary<IActivity, IList<PointInfo[]>> points = new Dictionary<IActivity, IList<PointInfo[]>>(); points = findSimilarPoints(refRoute, activities, null); return getCommonSpeed(points, activities, useActive, null); }