in Backend/src/Trackable.TripDetection/Modules/ClusteredStopDetectorModule.cs [79:185]
protected override Task<TripDetectionContext> ProcessInternal(TripDetectionContext input)
{
var tripSegments = new List<TripSegmentBase>();
foreach (var segment in input.TripSegments)
{
if (!segment.IsMovingSegment)
{
tripSegments.Add(segment);
continue;
}
var currentStopCluster = new StoppedSegment();
var currentMovingCluster = new MovingSegment();
State previousState = State.Stopped;
State currentState = State.Unknown;
var points = segment.Points;
currentStopCluster.Points.Add(points.First());
// Loop over points and extract segments
for (var i = 1; i < points.Count - 1; i++)
{
var previousTrackingPoint = points[i - 1];
var currentTrackingPoint = points[i];
var nextTrackingPoint = points[i + 1];
double cumulativeAngle = 0;
for (int j = i - this.arcWindowSize /2 ; j <= i + this.arcWindowSize / 2; j++)
{
if (j >= 0 && j < points.Count)
{
cumulativeAngle += MathUtils.AngleBetweenPoints(points[j], points[i]);
}
}
cumulativeAngle /= this.arcWindowSize;
double calculatedSpeed = MathUtils.AverageSpeed(previousTrackingPoint, currentTrackingPoint, nextTrackingPoint);
currentState = (calculatedSpeed <= this.maximumDwellSpeed && cumulativeAngle > this.minimumAngleDifference)
? State.Stopped : State.Moving;
if (currentState == State.Moving)
{
currentMovingCluster.Points.Add(currentTrackingPoint);
if (previousState == State.Stopped)
{
if (currentStopCluster.GetDurationInSeconds() < this.minimumDwellTime)
{
tripSegments.Add(new MovingSegment(currentStopCluster.Points));
}
else
{
currentStopCluster.Points.Add(currentTrackingPoint);
tripSegments.Add(currentStopCluster);
}
currentStopCluster = new StoppedSegment();
}
}
if (currentState == State.Stopped)
{
currentStopCluster.Points.Add(currentTrackingPoint);
if (previousState == State.Moving)
{
currentMovingCluster.Points.Add(currentTrackingPoint);
tripSegments.Add(currentMovingCluster);
currentMovingCluster = new MovingSegment();
}
}
previousState = currentState;
}
// Add the last segment to the list of segments including the last
// unprocessed point
if (currentStopCluster.Points.Any())
{
currentStopCluster
.Points
.Add(points[points.Count - 1]);
tripSegments.Add(currentStopCluster);
}
else if (currentMovingCluster.Points.Any())
{
currentMovingCluster
.Points
.Add(points[points.Count - 1]);
tripSegments.Add(currentMovingCluster);
}
}
input.TripSegments = tripSegments;
return Task.FromResult(input);
}