Exemple #1
0
        public void LongPolylineRectWithinDistanceSanityTest2()
        {
            List <GeoCoordinates> points = new List <GeoCoordinates>();

            for (int i = 0; i < 1000; ++i)
            {
                // Points stretch from (0,0) to (9.99, 9.99)
                points.Add(new GeoCoordinates(i / 100.0, i / 100.0));
            }

            GeoPolyline pl = new GeoPolyline(points);

            // Rect is in upper left corner of the square (0,0),(10,0),(10,10),(0,10)
            // and has side length 4. It should be sqrt(2) units away from line.
            Rect r = new Rect
            {
                xMin = 0,
                xMax = 4,
                yMin = 6,
                yMax = 10
            };

            Assert.False(pl.RectWithinDistance(r, 1.3));
            Assert.True(pl.RectWithinDistance(r, 1.5));
        }
Exemple #2
0
        public void SinglePointPolylineRectWithinDistanceIsCircleTest()
        {
            GeoPolyline pl = new GeoPolyline(new GeoCoordinates(0, 0));

            Rect r = new Rect
            {
                xMin = 1,
                xMax = 2,
                yMin = 1,
                yMax = 2
            };

            Assert.False(pl.RectWithinDistance(r, 1.1));
            Assert.True(pl.RectWithinDistance(r, 1.5));
        }
Exemple #3
0
        public void LongPolylineRectWithinDistanceSanityTest1()
        {
            List <GeoCoordinates> points = new List <GeoCoordinates>();

            for (int i = 0; i < 1000; ++i)
            {
                // Points stretch from lng=0 to lng=9.99
                points.Add(new GeoCoordinates(0, i / 100.0));
            }

            GeoPolyline pl = new GeoPolyline(points);

            // Rect 1 unit above line.
            Rect r = new Rect
            {
                xMin = 0,
                xMax = 10,
                yMin = 1,
                yMax = 2
            };

            Assert.False(pl.RectWithinDistance(r, 0.9));
            Assert.True(pl.RectWithinDistance(r, 1.1));
        }
        GetRide(UserRideOffer offer,
                ConcurrentGeoQuadtree <MatchableRideRequest> origins,
                ConcurrentGeoQuadtree <MatchableRideRequest> destinations)
        {
            RouteInfo driverRoute = await GetRoute(offer);

            var originsTask      = GetElementsInsideAsync(origins, NearRoute);
            var destinationsTask = GetElementsInsideAsync(destinations, NearRoute);

            // Only consider passengers whose origins and destinations are near
            // the driver's route.
            var potentialPassengers = new HashSet <MatchableRideRequest>(
                from element in await originsTask
                select element.Data);

            potentialPassengers.IntersectWith(
                from element in await destinationsTask
                select element.Data);

            // Find a passenger going in the same direction as the driver such that
            // picking up the passenger does not put the driver too far out of their way.
            foreach (var passenger in potentialPassengers.Where(GoingInDriversDirection))
            {
                RouteInfo routeWithPassenger = await GetRouteWithPassenger(offer, passenger);

                // Reject route if it's too far out of the way according to
                // the driver's settings.
                if (driverRoute.drivingTime.HasValue && routeWithPassenger.drivingTime.HasValue)
                {
                    TimeSpan originalTime = driverRoute.drivingTime.Value;
                    TimeSpan newTime      = routeWithPassenger.drivingTime.Value;
                    TimeSpan maxTime      = originalTime + TimeSpan.FromMinutes(offer.RideOffer.MaxTimeOutOfWay);

                    if (newTime > maxTime)
                    {
                        // Output debug info for demos.
                        Program.LogError($"Matched {offer.User.UserInfo.UserId} with {passenger.Request.User.UserInfo.UserId}" +
                                         " but resulting route was too long." +
                                         $" Original trip duration: {originalTime.Minutes} mins." +
                                         $" Matched trip duration: {newTime.Minutes} mins." +
                                         $" Driver's max time out of way: {offer.RideOffer.MaxTimeOutOfWay} mins.");
                        continue;
                    }
                }

                return(RideWithPassenger(offer, passenger));
            }

            return(EmptyRide(offer, driverRoute));


            /// <summary>
            /// Tests whether any point in the rect is close enough to <see cref="route"/>.
            /// </summary>
            bool NearRoute(Rect rect)
            {
                // Ignore passengers more than approximately 1km of the route.
                // TODO Take large max-time-out-of-way values into account when choosing max-dist-out-of-way.
                double maxDistMeters  = 1000;
                double maxDistDegrees = offer.RideOffer.Trip.Source.DegreesUpperBound(maxDistMeters);

                GeoPolyline route = driverRoute.overviewPolyline;

                return(route.RectWithinDistance(rect, maxDistDegrees));
            }

            /// <summary>
            /// Tests whether this passenger is going in the same direction as the driver.
            /// </summary>
            bool GoingInDriversDirection(MatchableRideRequest request)
            {
                var driverDest = offer.RideOffer.Trip.Destination;
                var driverOrig = offer.RideOffer.Trip.Source;
                var driverSeg  = new GeoSegment(driverOrig, driverDest);

                var passDest = request.Request.RideRequest.Trip.Destination;
                var passOrig = request.Request.RideRequest.Trip.Source;
                var passSeg  = new GeoSegment(passOrig, passDest);

                // Use GeoSegments so that this works near prime meridian.
                var passDiff   = passSeg.Point2Representative - passSeg.Point1Representative;
                var driverDiff = driverSeg.Point2Representative - driverSeg.Point1Representative;

                // Compute the dot product of the vectors. This is a pretty rough
                // estimate and doesn't take into account the Earth's curvature.
                return(passDiff.Dot(driverDiff) > 0);
            }
        }