public double Calculate(GeometryToMeasure.Point from, GeometryToMeasure.Point to, int fractionDigits = -1)
        {
            if (from == null || to == null)
            {
                return(double.NaN);
            }

            var dx = from.X - to.X;
            var dy = from.Y - to.Y;

            var d        = Math.Pow(dx, 2) + Math.Pow(dy, 2);
            var distance = Math.Sqrt(d);

            if (fractionDigits != -1)
            {
                distance = Math.Round(distance, fractionDigits);
            }

            return(distance);
        }
        public DominantRouteResolverCommand(IList <GeometryToMeasure.ResponseLocation> locations, GeometryToMeasure.Point point, int suggestCount)
        {
            Caculator       = new PythagoreanDistance();
            Point           = point;
            SuggestCount    = suggestCount;
            RequestContract = new Concurrencies.RequestContract
            {
                Locations = new Concurrencies.RequestLocation[locations.Count]
            };
            RouteMap = new Dictionary <string, GeometryToMeasure.ResponseLocation>(locations.Count);

            for (var i = 0; i < locations.Count; i++)
            {
                var item = locations[i];
                RouteMap[item.RouteId] = item;

                RequestContract.Locations[i] = new Concurrencies.RequestLocation
                {
                    FromMeasure = item.Measure,
                    ToMeasure   = item.Measure,
                    RouteId     = item.RouteId
                };
            }
        }
Example #3
0
        public async Task <HttpResponseMessage> ReverseMilePost(double?x, double?y,
                                                                [FromUri] ReverseMilepostOptions options)
        {
            var log         = Log.ForContext <GeocodeController>();
            var specificLog = log.ForContext("request-id", $"{x},{y}");

            specificLog.Warning("geocode(reverse-milepost): {x},{y}, with {@options}", x, y, options);

            #region validation

            var errors = "";
            if (!x.HasValue)
            {
                errors = "X is empty.";
            }

            if (!y.HasValue)
            {
                errors += "Y is emtpy";
            }

            if (errors.Length > 0)
            {
                return(Request.CreateResponse(HttpStatusCode.BadRequest,
                                              new ResultContainer <ReverseGeocodeResult>
                {
                    Status = (int)HttpStatusCode.BadRequest,
                    Message = errors
                }));
            }

            #endregion

            var baseUrl = "https://maps.udot.utah.gov/randh/rest/services/ALRS/MapServer/exts/LRSServer/networkLayers/0/";

            var point           = new GeometryToMeasure.Point(x.Value, y.Value);
            var requestContract = new GeometryToMeasure.RequestContract
            {
                Locations = new[] {
                    new GeometryToMeasure.RequestLocation {
                        Geometry = point
                    }
                },
                OutSr     = options.WkId,
                InSr      = options.WkId,
                Tolerance = options.Buffer
            };

            var requestUri = $"{baseUrl}geometryToMeasure{requestContract.QueryString}";

            HttpResponseMessage httpResponse;

            try
            {
                httpResponse = await App.HttpClient.GetAsync(requestUri);
            }
            catch (AggregateException ex)
            {
                specificLog.Fatal(ex, "geocode(reverse - milepost): aggregate exception");

                return(Request.CreateResponse(HttpStatusCode.InternalServerError,
                                              new ResultContainer
                {
                    Status = (int)HttpStatusCode.InternalServerError,
                    Message = "I'm sorry, it seems as though the request had issues."
                })
                       .AddTypeHeader(typeof(ResultContainer <ReverseMilepostResult>)));
            }

            try
            {
                httpResponse.EnsureSuccessStatusCode();
            }
            catch (Exception ex)
            {
                specificLog.Fatal(ex, "geocode(reverse-milepost): general exception");

                return(Request.CreateResponse(HttpStatusCode.InternalServerError,
                                              new ResultContainer
                {
                    Status = (int)HttpStatusCode.InternalServerError,
                    Message = "I'm sorry, we were unable to communicate with the UDOT service."
                })
                       .AddTypeHeader(typeof(ResultContainer <ReverseMilepostResult>)));
            }

            GeometryToMeasure.ResponseContract response;

            try
            {
                response = await httpResponse.Content.ReadAsAsync <GeometryToMeasure.ResponseContract>(new[]
                {
                    new TextPlainResponseFormatter()
                });
            }
            catch (Exception ex)
            {
                specificLog.Fatal(ex, "geocode(reverse-milepost): error reading result");

                return(Request.CreateResponse(HttpStatusCode.InternalServerError,
                                              new ResultContainer
                {
                    Status = (int)HttpStatusCode.InternalServerError,
                    Message = "I'm sorry, we were unable to read the result."
                })
                       .AddTypeHeader(typeof(ResultContainer <ReverseMilepostResult>)));
            }

            if (!response.IsSuccessful)
            {
                return(Request.CreateResponse(HttpStatusCode.BadRequest,
                                              new ResultContainer
                {
                    Status = (int)HttpStatusCode.BadRequest,
                    Message = "Your request was invalid. Check that your coordinates and spatial reference match."
                })
                       .AddTypeHeader(typeof(ResultContainer <ReverseMilepostResult>)));
            }

            if (response.Locations?.Length != 1)
            {
                // this should not happen
                specificLog.Warning("geocode(reverse-milepost): multiple locations found");
            }

            var location = response.Locations[0];

            if (location.Status != GeometryToMeasure.Status.esriLocatingOK)
            {
                if (location.Status != GeometryToMeasure.Status.esriLocatingMultipleLocation)
                {
                    return(Request.CreateResponse(HttpStatusCode.NotFound,
                                                  new ResultContainer
                    {
                        Message = "No milepost was found within your buffer radius.",
                        Status = (int)HttpStatusCode.NotFound
                    })
                           .AddTypeHeader(typeof(ResultContainer <ReverseMilepostResult>)));
                }

                // concurrency
                var primaryRoutes = FilterPrimaryRoutes(location.Results, options.IncludeRampSystems == 1);

                if (primaryRoutes.Count < 1)
                {
                    return(Request.CreateResponse(HttpStatusCode.NotFound,
                                                  new ResultContainer
                    {
                        Message = "No milepost was found within your buffer radius.",
                        Status = (int)HttpStatusCode.NotFound
                    })
                           .AddTypeHeader(typeof(ResultContainer <ReverseMilepostResult>)));
                }

                var dominantRoutes = await CommandExecutor.ExecuteCommandAsync(
                    new DominantRouteResolverCommand(primaryRoutes, point, options.SuggestCount));

                return(Request.CreateResponse(HttpStatusCode.OK, new ResultContainer <ReverseMilepostResult>
                {
                    Status = (int)HttpStatusCode.OK,
                    Result = dominantRoutes
                })
                       .AddTypeHeader(typeof(ResultContainer <ReverseMilepostResult>))
                       .AddCache());
            }

            var routes = FilterPrimaryRoutes(location.Results, options.IncludeRampSystems == 1);

            if (routes.Count < 1)
            {
                return(Request.CreateResponse(HttpStatusCode.NotFound, new ResultContainer <ReverseMilepostResult>
                {
                    Message = "No milepost was found within your buffer radius.",
                    Status = (int)HttpStatusCode.NotFound
                }));
            }

            location = routes[0];

            return(Request.CreateResponse(HttpStatusCode.OK, new ResultContainer <ReverseMilepostResult>
            {
                Result = new ReverseMilepostResult
                {
                    Route = location.RouteId,
                    OffsetMeters = 0,
                    Milepost = location.Measure,
                    Dominant = true,
                    Candidates = Array.Empty <ReverseMilepostResult>()
                },
                Status = (int)HttpStatusCode.OK
            }));
        }