Example #1
0
        public static Expression <Func <T, double> > CalculateDistanceFrom <T>(double originLatitude, double originLongitude, string latitudePropertyName, string longitudePropertyName, DistanceUnit distanceUnit)
        {
            var earthsRadiusConstantExpression = Expression.Constant(GeoCalculator.GetRadius(distanceUnit));
            var inputExpression           = Expression.Parameter(typeof(T), "x");
            var originLatitudeExpression  = Expression.Constant(originLatitude);
            var originLongitudeExpression = Expression.Constant(originLongitude);

            var destinationLatitudeExpression  = Expression.Convert(Expression.Property(inputExpression, latitudePropertyName), typeof(double));
            var destinationLongitudeExpression = Expression.Convert(Expression.Property(inputExpression, longitudePropertyName), typeof(double));

            if (originLatitude < -90 || originLatitude > 90 || originLongitude < -180 || originLongitude > 180)
            {
                return(Expression.Lambda <Func <T, double> >(Expression.Constant(-1.0), inputExpression));
            }

            return(Expression.Lambda <Func <T, double> >(
                       Expression.Multiply(
                           earthsRadiusConstantExpression,
                           Expression.Multiply(
                               Expression.Constant(2.0),
                               Expression.Call(_asin,
                                               // MIN isn't supported in SQL
                                               // Tested all (4B+) combinations of valid Lat/Long and calculation was never greater than 1
                                               //Expression.Call(_min,
                                               //    Expression.Constant(1.0),
                                               Expression.Call(_sqrt,
                                                               Expression.Add(
                                                                   Expression.Call(_pow,
                                                                                   Expression.Call(_sin,
                                                                                                   Expression.Divide(
                                                                                                       originLatitudeExpression.DiffRadiansExpression(destinationLatitudeExpression),
                                                                                                       Expression.Constant(2.0)
                                                                                                       )
                                                                                                   ),
                                                                                   Expression.Constant(2.0)
                                                                                   ),
                                                                   Expression.Multiply(
                                                                       Expression.Call(_cos, originLatitudeExpression.ToRadiansExpression()),
                                                                       Expression.Multiply(
                                                                           Expression.Call(_cos, destinationLatitudeExpression.ToRadiansExpression()),
                                                                           Expression.Call(_pow,
                                                                                           Expression.Call(_sin,
                                                                                                           Expression.Divide(
                                                                                                               originLongitudeExpression.DiffRadiansExpression(destinationLongitudeExpression),
                                                                                                               Expression.Constant(2.0)
                                                                                                               )
                                                                                                           ),
                                                                                           Expression.Constant(2.0)
                                                                                           )
                                                                           )
                                                                       )
                                                                   )
                                                               )
                                               //)
                                               )
                               )
                           ),
                       inputExpression));
        }