Exemplo n.º 1
0
        /// <summary>
        /// Calculate the intersection point of two line segments
        /// adapted to C# from http://rbrundritt.wordpress.com/2008/10/20/approximate-points-of-intersection-of-two-line-segments/
        /// </summary>
        /// <returns>Null if there is no intersection. Otherwise the point of intersection.</returns>
        public static IGeoLocation SimplePolylineIntersection(IGeoLocation latlong1, IGeoLocation latlong2, IGeoLocation latlong3, IGeoLocation latlong4)
        {
            //Line segment 1 (p1, p2)
            var a1 = latlong2.Latitude - latlong1.Latitude;
            var b1 = latlong1.Longitude - latlong2.Longitude;
            var c1 = a1 * latlong1.Longitude + b1 * latlong1.Latitude;

            //Line segment 2 (p3,  p4)
            var a2 = latlong4.Latitude - latlong3.Latitude;
            var b2 = latlong3.Longitude - latlong4.Longitude;
            var c2 = a2 * latlong3.Longitude + b2 * latlong3.Latitude;

            var determinate = a1 * b2 - a2 * b1;

            IGeoLocation intersection;
            if (determinate != 0)
            {
                var x = (b2 * c1 - b1 * c2) / determinate;
                var y = (a1 * c2 - a2 * c1) / determinate;

                var intersect = new GeoLocation(y, x);

                if (InBoundedBox(latlong1, latlong2, intersect) && InBoundedBox(latlong3, latlong4, intersect))
                    intersection = intersect;
                else
                    intersection = null;
            }
            else //lines are parallel
                intersection = null;

            return intersection;
        }
Exemplo n.º 2
0
        /// <summary>
        /// Stores employee trackpoints.
        /// Used by the mobile phone application.
        /// NOTE: TrackPoints CollectedTimeStamp should be in UTC.
        /// </summary>
        /// <param name="roleId">Current roleId </param>
        /// <param name="trackPoints">The list of TrackPoints being passed from an Employee's device</param>
        /// <returns>An Http response to the device signaling that the TrackPoint was successfully created</returns>
        public void Post(Guid roleId, TrackPoint[] trackPoints)
        {
            if (!trackPoints.Any() || !trackPoints.First().RouteId.HasValue)
                throw Request.BadRequest();

            var routeId = trackPoints.First().RouteId.Value;

            var currentUserAccount = CoreEntitiesContainer.CurrentUserAccount();
            var currentBusinessAccount = CoreEntitiesContainer.Owner(roleId, new[] { RoleType.Administrator, RoleType.Regular, RoleType.Mobile }).FirstOrDefault();

            //Return an Unauthorized Status Code if
            //a) there is no UserAccount
            //b) the user does not have access to the route (currentBusinessAccount == null)
            if (currentUserAccount == null || currentBusinessAccount == null)
                throw Request.NotAuthorized();

            var employee = CoreEntitiesContainer.Employees.FirstOrDefault(e => e.LinkedUserAccount.Id == currentUserAccount.Id
                                                                                && e.EmployerId == currentBusinessAccount.Id);
            if (employee == null)
                throw Request.NotFound("Employee");

            //order the new track points by their TimeStamps
            //remove inaccurate trackpoints
            var orderedModelTrackPoints = trackPoints.Where(tp => tp.Accuracy < 50).OrderBy(tp => tp.CollectedTimeStamp).ToArray();

            var latestTrackPoint = orderedModelTrackPoints.LastOrDefault();

            //if there was a previous point today, check the latest point is not erroneous
            if (employee.LastTimeStamp.HasValue && DateTime.UtcNow.Subtract(employee.LastTimeStamp.Value) < TimeSpan.FromDays(1))
            {
                var previous = new GeoLocation(employee.LastLatitude.Value, employee.LastLongitude.Value);
                latestTrackPoint = orderedModelTrackPoints.LastOrDefault(t => !Erroneous(t, previous, t.CollectedTimeStamp.Subtract(employee.LastTimeStamp.Value)));

                //set the heading based on the previous point
                if (latestTrackPoint != null)
                    latestTrackPoint.Heading = (int)GeoLocationTools.Bearing(previous, latestTrackPoint);
            }

            if (latestTrackPoint != null)
            {
                //Save the latest (most current) TrackPoint to the database
                employee.LastCompassDirection = latestTrackPoint.Heading;
                employee.LastLatitude = (double?)latestTrackPoint.Latitude;
                employee.LastLongitude = (double?)latestTrackPoint.Longitude;
                employee.LastSource = latestTrackPoint.Source;
                employee.LastSpeed = (double?)latestTrackPoint.Speed;
                employee.LastTimeStamp = latestTrackPoint.CollectedTimeStamp;
                employee.LastAccuracy = latestTrackPoint.Accuracy;
            }

            //Push TrackPoints to Azure as long as either
            //the LastPushToAzureTimeStamp is null
            //the LastPushToAzureTimeStamp difference from the TrackPoint is > TimeBetweenPushesToAzure
            var lastPushToAzureTimeStamp = employee.LastPushToAzureTimeStamp;

            //send the TrackPoints to azure, that are seperated by TimeBetweenPushesToAzure (in seconds)
            foreach (var trackPoint in orderedModelTrackPoints)
            {
                if (lastPushToAzureTimeStamp.HasValue && (trackPoint.CollectedTimeStamp - lastPushToAzureTimeStamp) < TimeSpan.FromSeconds(UpdateConstants.SecondsBetweenHistoricalTrackPoints))
                    continue;

                if (trackPoint.Id == Guid.Empty)
                    trackPoint.Id = Guid.NewGuid();

                PushTrackPointToAzure(currentBusinessAccount, trackPoint, employee, routeId);

                lastPushToAzureTimeStamp = trackPoint.CollectedTimeStamp;
            }

            employee.LastPushToAzureTimeStamp = lastPushToAzureTimeStamp;

            //Save all the changes that have been made in the Database
            SaveWithRetry();
        }