protected override Task ProcessInternal()

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);
        }