/// <summary> /// Interpolate the simultion data to a specified interval using a linear interpolation. /// </summary> /// <param name="simulatedTrain">The list of the simulated train details.</param> /// <param name="trackGeometry">The list of Track geometry data to align the train location.</param> /// <param name="startKm">Starting kilometreage for the interpolation.</param> /// <param name="endKm">End kilometerage for the interpolation.</param> /// <param name="interval">interpolation interval, specified in metres.</param> /// <returns>List of interpolated values for the simulation.</returns> public List <InterpolatedTrain> interpolateSimulationData(List <simulatedTrain> simulatedTrain, List <trackGeometry> trackGeometry) { /* Placeholders for the interpolated distance markers. */ double previousKm = 0; double currentKm = 0; /* Place holder to calaculte the time for each interpolated value. */ DateTime simTime = new DateTime(); double time = 0; double days, hours, minutes, seconds; /* Flag to indicate when to collect the next time value. */ bool timeChange = true; /* Additional loop and TSR details. */ int geometryIdx = 0; bool loop = false; bool TSR = false; double TSRspeed = 0; /* Index values for the interpolation parameters */ int index0 = -1; int index1 = -1; /* Interplation parameters. */ double interpolatedSpeed = 0; double X0, X1, Y0, Y1; List <InterpolatedTrain> simulatedInterpolation = new List <InterpolatedTrain>(); if (simulatedTrain[1].singleLineKm - simulatedTrain[0].singleLineKm > 0) // Increasing Km { /* Set the start of the interpolation. */ currentKm = Settings.startKm; while (currentKm < Settings.endKm) { /* Find the closest kilometerage markers either side of the current interpoaltion point. */ index0 = findClosestLowerKm(currentKm, simulatedTrain); index1 = findClosestGreaterKm(currentKm, simulatedTrain); /* If a valid index is found, extract the existing journey parameters and interpolate. */ if (index0 >= 0 && index1 >= 0) { X0 = simulatedTrain[index0].singleLineKm; X1 = simulatedTrain[index1].singleLineKm; Y0 = simulatedTrain[index0].velocity; Y1 = simulatedTrain[index1].velocity; if (timeChange) { time = simulatedTrain[index0].time; days = (time / secPerDay); hours = (days - Math.Truncate(days)) * hoursPerDay; minutes = (hours - Math.Truncate(hours)) * minutesPerHour; seconds = (minutes - Math.Truncate(minutes)) * secPerMinute; simTime = new DateTime(2000, 1, (int)days + 1, (int)hours, (int)minutes, (int)seconds); timeChange = false; } /* Perform linear interpolation. */ interpolatedSpeed = linear(currentKm, X0, X1, Y0, Y1); /* Interpolate the time. */ simTime = simTime.AddHours(calculateTimeInterval(previousKm, currentKm, interpolatedSpeed)); } else { /* Boundary conditions for interpolating the data prior to and beyond the existing journey points. */ time = 0; interpolatedSpeed = 0; } /* Determine if we need to extract the time from the data or interpolate it. */ if (index1 >= 0) { if (currentKm >= simulatedTrain[index1].singleLineKm) { timeChange = true; } } geometryIdx = trackGeometry[0].findClosestTrackGeometryPoint(trackGeometry, currentKm); if (geometryIdx >= 0) { /* Check if there is a loop at this location. */ loop = trackGeometry[geometryIdx].isLoopHere; /* Check if there is a TSR at this location. */ TSR = trackGeometry[geometryIdx].isTSRHere; TSRspeed = trackGeometry[geometryIdx].temporarySpeedRestriction; } /* Create the interpolated data object and add it to the list. */ InterpolatedTrain item = new InterpolatedTrain("Simulated Train", "Simulated Loco", simTime, currentKm, interpolatedSpeed, loop, TSR, TSRspeed); simulatedInterpolation.Add(item); /* Create a copy of the current km marker and increment. */ previousKm = currentKm; currentKm = currentKm + Settings.interval / 1000; } } else // Decreasing km. { /* Set the start of the interpolation. */ currentKm = Settings.endKm; while (currentKm > Settings.startKm) { /* Find the closest kilometerage markers either side of the current interpoaltion point. */ index0 = findClosestLowerKm(currentKm, simulatedTrain); index1 = findClosestGreaterKm(currentKm, simulatedTrain); /* If a valid index is found, extract the existing journey parameters and interpolate. */ if (index0 >= 0 && index1 >= 0) { X0 = simulatedTrain[index0].singleLineKm; X1 = simulatedTrain[index1].singleLineKm; Y0 = simulatedTrain[index0].velocity; Y1 = simulatedTrain[index1].velocity; if (timeChange) { time = simulatedTrain[index0].time; days = (time / secPerDay); hours = (days - Math.Truncate(days)) * hoursPerDay; minutes = (hours - Math.Truncate(hours)) * minutesPerHour; seconds = (minutes - Math.Truncate(minutes)) * secPerMinute; simTime = new DateTime(2000, 1, (int)days + 1, (int)hours, (int)minutes, (int)seconds); timeChange = false; } /* Perform linear interpolation. */ interpolatedSpeed = linear(currentKm, X0, X1, Y0, Y1); /* Interpolate the time. */ simTime = simTime.AddHours(calculateTimeInterval(previousKm, currentKm, interpolatedSpeed)); } else { /* Boundary conditions for interpolating the data prior to and beyond the existing journey points. */ time = 0; interpolatedSpeed = 0; } /* Determine if we need to extract the time from the data or interpolate it. */ if (index0 >= 0) { if (currentKm <= simulatedTrain[index0].singleLineKm) { timeChange = true; } } geometryIdx = trackGeometry[0].findClosestTrackGeometryPoint(trackGeometry, currentKm); if (geometryIdx >= 0) { /* Check if there is a loop at this location. */ loop = trackGeometry[geometryIdx].isLoopHere; /* Check if there is a TSR at this location. */ TSR = trackGeometry[geometryIdx].isTSRHere; TSRspeed = trackGeometry[geometryIdx].temporarySpeedRestriction; } /* Create the interpolated data object and add it to the list. */ InterpolatedTrain item = new InterpolatedTrain("Simualted Train", "Simulated Loco", simTime, currentKm, interpolatedSpeed, loop, TSR, TSRspeed); simulatedInterpolation.Add(item); /* Create a copy of the current km marker and increment. */ previousKm = currentKm; currentKm = currentKm - Settings.interval / 1000; } } return(simulatedInterpolation); }
/// <summary> /// Interpolate the train speed to a specified interval using a linear interpolation. /// </summary> /// <param name="trains">List of train objects containing the parameters for each train journey.</param> /// <param name="trackGeometry">The list of Track geometry data to align the train location.</param> /// <param name="startKm">Starting kilometreage for the interpolation.</param> /// <param name="endKm">End kilometerage for the interpolation.</param> /// <param name="interval">interpolation interval, specified in metres.</param> /// <returns>List of train objects with interpolated values at the specified interval.</returns> public List <Train> interpolateTrainData(List <Train> trains, List <trackGeometry> trackGeometry) { /* Placeholders for the interpolated distance markers. */ double previousKm = 0; double currentKm = 0; /* Place holder to calaculte the time for each interpolated value. */ DateTime time = new DateTime(); /* Flag to indicate when to collect the next time value. */ bool timeChange = true; /* Additional loop and TSR details. */ int geometryIdx = 0; bool loop = false; bool TSR = false; double TSRspeed = 0; /* Index values for the interpolation parameters */ int index0 = -1; int index1 = -1; /* Interplation parameters. */ double interpolatedSpeed = 0; double X0, X1, Y0, Y1; /* Create a new list of trains for the journies interpolated values. */ List <Train> newTrainList = new List <Train>(); /* Create a journey list to store the existing journey details. */ List <TrainDetails> journey = new List <TrainDetails>(); /* Cycle through each train to interpolate between points. */ for (int trainIdx = 0; trainIdx < trains.Count(); trainIdx++) { /* Create a new journey list of interpolated values. */ List <InterpolatedTrain> interpolatedTrainList = new List <InterpolatedTrain>(); journey = trains[trainIdx].TrainJourney; if (journey[0].trainDirection == direction.increasing) { /* Set the start of the interpolation. */ currentKm = Settings.startKm; while (currentKm < Settings.endKm) { /* Find the closest kilometerage markers either side of the current interpoaltion point. */ index0 = findClosestLowerKm(currentKm, journey); index1 = findClosestGreaterKm(currentKm, journey); /* If a valid index is found, extract the existing journey parameters and interpolate. */ if (index0 >= 0 && index1 >= 0) { X0 = journey[index0].geometryKm; X1 = journey[index1].geometryKm; Y0 = journey[index0].speed; Y1 = journey[index1].speed; if (timeChange) { time = journey[index0].NotificationDateTime; timeChange = false; } /* Perform linear interpolation. */ interpolatedSpeed = linear(currentKm, X0, X1, Y0, Y1); /* Interpolate the time. */ time = time.AddHours(calculateTimeInterval(previousKm, currentKm, interpolatedSpeed)); } else { /* Boundary conditions for interpolating the data prior to and beyond the existing journey points. */ time = new DateTime(2000, 1, 1); interpolatedSpeed = 0; } /* Determine if we need to extract the time from the data or interpolate it. */ if (index1 >= 0) { if (currentKm >= journey[index1].geometryKm) { timeChange = true; } } geometryIdx = trackGeometry[0].findClosestTrackGeometryPoint(trackGeometry, currentKm); if (geometryIdx >= 0) { /* Check if there is a loop at this location. */ loop = trackGeometry[geometryIdx].isLoopHere; /* Check if there is a TSR at this location. */ TSR = trackGeometry[geometryIdx].isTSRHere; TSRspeed = trackGeometry[geometryIdx].temporarySpeedRestriction; } /* Create the interpolated data object and add it to the list. */ InterpolatedTrain item = new InterpolatedTrain(trains[trainIdx].TrainJourney[0].TrainID, trains[trainIdx].TrainJourney[0].LocoID, time, currentKm, interpolatedSpeed, loop, TSR, TSRspeed); interpolatedTrainList.Add(item); /* Create a copy of the current km marker and increment. */ previousKm = currentKm; currentKm = currentKm + Settings.interval / 1000; } } else if (journey[0].trainDirection == direction.decreasing) { /* Set the start of the interpolation. */ currentKm = Settings.endKm; while (currentKm > Settings.startKm) { /* Find the closest kilometerage markers either side of the current interpoaltion point. */ index0 = findClosestLowerKm(currentKm, journey); index1 = findClosestGreaterKm(currentKm, journey); /* If a valid index is found, extract the existing journey parameters and interpolate. */ if (index0 >= 0 && index1 >= 0) { X0 = journey[index0].geometryKm; X1 = journey[index1].geometryKm; Y0 = journey[index0].speed; Y1 = journey[index1].speed; if (timeChange) { time = journey[index0].NotificationDateTime; timeChange = false; } /* Perform linear interpolation. */ interpolatedSpeed = linear(currentKm, X0, X1, Y0, Y1); /* Interpolate the time. */ time = time.AddHours(calculateTimeInterval(previousKm, currentKm, interpolatedSpeed)); } else { /* Boundary conditions for interpolating the data prior to and beyond the existing journey points. */ time = new DateTime(2000, 1, 1); interpolatedSpeed = 0; } /* Determine if we need to extract the time from the data or interpolate it. */ if (index0 >= 0) { if (currentKm <= journey[index0].geometryKm) { timeChange = true; } } geometryIdx = trackGeometry[0].findClosestTrackGeometryPoint(trackGeometry, currentKm); if (geometryIdx >= 0) { /* Check if there is a loop at this location. */ loop = trackGeometry[geometryIdx].isLoopHere; /* Check if there is a TSR at this location. */ TSR = trackGeometry[geometryIdx].isTSRHere; TSRspeed = trackGeometry[geometryIdx].temporarySpeedRestriction; } /* Create the interpolated data object and add it to the list. */ InterpolatedTrain item = new InterpolatedTrain(trains[trainIdx].TrainJourney[0].TrainID, trains[trainIdx].TrainJourney[0].LocoID, time, currentKm, interpolatedSpeed, loop, TSR, TSRspeed); interpolatedTrainList.Add(item); /* Create a copy of the current km marker and increment. */ previousKm = currentKm; currentKm = currentKm - Settings.interval / 1000; } } else { /* The train direction is not defined. */ } /* Add the interpolated list to the list of new train objects. */ Train trainItem = new Train(interpolatedTrainList, journey[0].trainDirection); newTrainList.Add(trainItem); } /* Return the completed interpolated train data. */ return(newTrainList); }