GreatCircleDistance() public method

Computes the distance between this coordinate and another point on the earth. Uses spherical law of cosines formula, not Haversine.
public GreatCircleDistance ( Coordinate other ) : double
other Coordinate The other point
return double
コード例 #1
0
        // Calculate the distance between
        // Node 'stopPosition' and the segment p1 --> p2, where p1 -> p2 is a subset of a way.
        private double FindDistanceToSegment(Coordinate stopPosition, Coordinate p1, Coordinate p2, out Coordinate closest)
        {
            double dx = p2.Lon - p1.Lon;
            double dy = p2.Lat - p1.Lat;

            if ((dx == 0) && (dy == 0))
            {
                // It's a point not a line segment.
                closest = p1;
                dx      = stopPosition.Lon - p1.Lon;
                dy      = stopPosition.Lat - p1.Lat;

                //return Math.Sqrt(dx * dx + dy * dy);
                return(stopPosition.GreatCircleDistance(closest));
            }

            // Calculate the t that minimizes the distance.
            double t = ((stopPosition.Lon - p1.Lon) * dx + (stopPosition.Lat - p1.Lat) * dy) / (dx * dx + dy * dy);

            // See if this represents one of the segment's
            // end points or a point in the middle.
            if (t < 0)
            {
                closest = new Coordinate(p1.Lat, p1.Lon);
                dx      = stopPosition.Lon - p1.Lon;
                dy      = stopPosition.Lat - p1.Lat;
            }
            else if (t > 1)
            {
                closest = new Coordinate(p2.Lat, p2.Lon);
                dx      = stopPosition.Lon - p2.Lon;
                dy      = stopPosition.Lat - p2.Lat;
            }
            else
            {
                closest = new Coordinate(p1.Lat + t * dy, p1.Lon + t * dx);
                dx      = stopPosition.Lon - closest.Lon;
                dy      = stopPosition.Lat - closest.Lat;
            }

            // For linear geometry return Math.Sqrt(dx * dx + dy * dy);

            // For earth geography below
            return(stopPosition.GreatCircleDistance(closest));
        }
コード例 #2
0
        /// <summary>
        /// Test whether coordinate values are within a close enough distance to each other.
        /// </summary>
        /// <param name="v1"></param>
        /// <param name=""></param>
        /// <returns></returns>
        private bool CloseEnough(Coordinate c1, Coordinate c2)
        {
            // Some generating programs don't snap them together.

            double Epsilon = 5.0;   // Max allowable mismatch, in meters

            var distance = c1.GreatCircleDistance(c2);

            return(distance < Epsilon);
        }
コード例 #3
0
        /// <summary>
        /// Parse JSON serialized route coordinate array
        /// </summary>
        /// <param name="db"></param>
        /// <param name="route"></param>
        /// <param name="jsonShapes"></param>
        private void SaveNewRouteShape(TrolleyTrackerContext db, Route route, string jsonShapes)
        {
            JavaScriptSerializer jss = new JavaScriptSerializer();

            jss.RegisterConverters(new JavaScriptConverter[] { new DynamicJsonConverter() });

            dynamic shapeData = jss.Deserialize(jsonShapes, typeof(object)) as dynamic;

            Coordinate lastCoordinate = null;
            var        totalDistance  = 0.0;
            int        sequence       = 0;
            int        nodeCount      = shapeData.Length;

            for (int i = 0; i < nodeCount; i++)
            {
                var node = shapeData[i];
                var lon  = Convert.ToDouble(node.Lon);
                var lat  = Convert.ToDouble(node.Lat);

                var    thisCoordinate = new Coordinate(lat, lon);
                double distance       = 0.0;
                if (lastCoordinate != null)
                {
                    distance = thisCoordinate.GreatCircleDistance(lastCoordinate);
                }
                lastCoordinate = thisCoordinate;
                totalDistance += distance;

                // Add new point if not duplicated (some shape editors create duplicate nodes)
                if (distance > 0.0)
                {
                    var dbShape = new TrolleyTracker.Models.Shape();
                    dbShape.Lat              = lat;
                    dbShape.Lon              = lon;
                    dbShape.RouteID          = route.ID;
                    dbShape.Sequence         = sequence;
                    dbShape.DistanceTraveled = totalDistance;
                    sequence++;
                    db.Shapes.Add(dbShape);
                }
            }

            db.SaveChanges();
        }
コード例 #4
0
        private void FindNewStops(List <Stop> routeStops, ref List <Stop> newStops, ref List <Stop> oldStops)
        {
            double Epsilon = 20.0; // Max distance in meters for matching stop

            newStops = new List <Stop>();
            oldStops = new List <Stop>();

            List <Stop> dbStopsList = null;

            using (var db = new TrolleyTrackerContext())
            {
                dbStopsList = (from s in db.Stops
                               select s).ToList();
            }

            foreach (var testStop in routeStops)
            {
                var  testCoordinate = new Coordinate(testStop.Lat, testStop.Lon);
                bool match          = false;
                foreach (var dbStop in dbStopsList)
                {
                    var dbCoordinate = new Coordinate(dbStop.Lat, dbStop.Lon);
                    if (dbCoordinate.GreatCircleDistance(testCoordinate) < Epsilon)
                    {
                        // Stop already exists nearby
                        match = true;
                        break;
                    }
                }
                if (match)
                {
                    oldStops.Add(testStop);
                }
                else
                {
                    newStops.Add(testStop);
                }
            }
        }
コード例 #5
0
        public ActionResult Create(FormCollection collection)
        {
            try
            {
                Coordinate lastCoordinate = null;

                var strRouteID = collection.Get("RouteID");

                // Parse Geo-JSON formatted route coordinates
                var jsonShapes = collection.Get("JSONText");
                if (jsonShapes != null && strRouteID != null)
                {
                    int routeID = Convert.ToInt32(strRouteID);

                    using (var db = new TrolleyTracker.Models.TrolleyTrackerContext())
                    {
                        RemoveOldShape(routeID, db);

                        JavaScriptSerializer jss = new JavaScriptSerializer();
                        jss.RegisterConverters(new JavaScriptConverter[] { new DynamicJsonConverter() });

                        dynamic shapeData = jss.Deserialize(jsonShapes, typeof(object)) as dynamic;

                        var features = shapeData.features;
                        var geometryBlock = features[0];
                        var geometry = geometryBlock["geometry"];
                        var geoJSONtype = geometry["type"];
                        var coordinates = geometry["coordinates"];

                        int segmentCount = coordinates.Count;
                        if (geoJSONtype == "LineString") segmentCount = 1;
                        int sequence = 0;
                        double totalDistance = 0.0;
                        for (int seg = 0; seg < segmentCount; seg++)
                        {
                            var coordArray = coordinates[seg];
                            if (geoJSONtype == "LineString") coordArray = coordinates;
                            int nodeCount = coordArray.Count;
                            for (int i = 0; i < nodeCount; i++)
                            {
                                var node = coordArray[i];
                                var strLon = node[0];
                                var strLat = node[1];
                                var lon = Convert.ToDouble(strLon);
                                var lat = Convert.ToDouble(strLat);

                                var thisCoordinate = new Coordinate(0, lat, lon, null);
                                double distance = 0.0;
                                if (lastCoordinate != null)
                                {
                                    distance = thisCoordinate.GreatCircleDistance(lastCoordinate);
                                }
                                lastCoordinate = thisCoordinate;
                                totalDistance += distance;

                                var dbShape = new TrolleyTracker.Models.Shape();
                                dbShape.Lat = lat;
                                dbShape.Lon = lon;
                                dbShape.RouteID = routeID;
                                dbShape.Sequence = sequence;
                                dbShape.DistanceTraveled = totalDistance;
                                sequence++;
                                db.Shapes.Add(dbShape);
                            }

                        }
                        db.SaveChanges();

                        var assignStops = new AssignStopsToRoutes();
                        assignStops.UpdateStopsForRoute(db, routeID);
                    }

                }

                return RedirectToAction("Index");
            }
            catch
            {
                return View();
            }
        }
コード例 #6
0
        private static void UpdateStopTime(Trolley trolley)
        {
            UpdateStopList();

            // See if trolley has moved far enough to justify a full stop distance check
            var currentLocation = new Coordinate((double)trolley.CurrentLat, (double)trolley.CurrentLon);
            if (currentLocation.GreatCircleDistance(lastReportedLocation[trolley.Number]) > MinMoveDistance)
            {
                CheckForStopInRange(trolley, currentLocation);
                lastReportedLocation[trolley.Number] = currentLocation;
            }
        }
コード例 #7
0
        /// <summary>
        /// Check for stop proximity - try to minimize number of polled stops
        ///   - First preference is the previous stop
        ///    Then loop through all stops
        /// </summary>
        /// <param name="trolley"></param>
        /// <param name="currentLocation"></param>
        private static void CheckForStopInRange(Trolley trolley, Coordinate currentLocation)
        {
            //var lastStopID = -1;
            if (lastStopIDByTrolley.ContainsKey(trolley.Number) )
            {
                var stopID = lastStopIDByTrolley[trolley.Number];
                var stopSummary = stopSummaries[stopID];
                if (currentLocation.GreatCircleDistance(new Coordinate(stopSummary.Lat, stopSummary.Lon)) < StopRadiusCheck) {
                    // Still within stop zone
                    return;
                }
            }

            foreach(var stopID in stopSummaries.Keys)
            {
                var stopSummary = stopSummaries[stopID];
                if (currentLocation.GreatCircleDistance(new Coordinate(stopSummary.Lat, stopSummary.Lon)) < StopRadiusCheck)
                {
                    // Found new stop zone
                    if (stopSummary.LastTrolleyArrivalTime.ContainsKey(trolley.Number))
                    {
                        stopSummary.LastTrolleyArrivalTime[trolley.Number] = UTCToLocalTime.LocalTimeFromUTC(DateTime.UtcNow);
                    }
                    else
                    {
                        stopSummary.LastTrolleyArrivalTime.Add(trolley.Number, UTCToLocalTime.LocalTimeFromUTC(DateTime.UtcNow));
                    }
                    lastStopIDByTrolley.Add(trolley.Number, stopSummary.ID);
                    return;
                }

            }

            // Not currently in any stop zone
            if (lastStopIDByTrolley.ContainsKey(trolley.Number))
            {
                lastStopIDByTrolley.Remove(trolley.Number);
            }
        }
        public ActionResult Create(FormCollection collection)
        {
            try
            {
                Coordinate lastCoordinate = null;

                var strRouteID = collection.Get("RouteID");


                // Parse Geo-JSON formatted route coordinates
                var jsonShapes = collection.Get("JSONText");
                if (jsonShapes != null && strRouteID != null)
                {
                    int routeID = Convert.ToInt32(strRouteID);

                    using (var db = new TrolleyTracker.Models.TrolleyTrackerContext())
                    {
                        RemoveOldShape(routeID, db);

                        JavaScriptSerializer jss = new JavaScriptSerializer();
                        jss.RegisterConverters(new JavaScriptConverter[] { new DynamicJsonConverter() });

                        dynamic shapeData = jss.Deserialize(jsonShapes, typeof(object)) as dynamic;

                        var features      = shapeData.features;
                        var geometryBlock = features[0];
                        var geometry      = geometryBlock["geometry"];
                        var geoJSONtype   = geometry["type"];
                        var coordinates   = geometry["coordinates"];

                        int segmentCount = coordinates.Count;
                        if (geoJSONtype == "LineString")
                        {
                            segmentCount = 1;
                        }
                        int    sequence      = 0;
                        double totalDistance = 0.0;
                        for (int seg = 0; seg < segmentCount; seg++)
                        {
                            var coordArray = coordinates[seg];
                            if (geoJSONtype == "LineString")
                            {
                                coordArray = coordinates;
                            }
                            int nodeCount = coordArray.Count;
                            for (int i = 0; i < nodeCount; i++)
                            {
                                var node   = coordArray[i];
                                var strLon = node[0];
                                var strLat = node[1];
                                var lon    = Convert.ToDouble(strLon);
                                var lat    = Convert.ToDouble(strLat);

                                var    thisCoordinate = new Coordinate(lat, lon);
                                double distance       = 0.0;
                                if (lastCoordinate != null)
                                {
                                    distance = thisCoordinate.GreatCircleDistance(lastCoordinate);
                                }
                                lastCoordinate = thisCoordinate;
                                totalDistance += distance;

                                var dbShape = new TrolleyTracker.Models.Shape();
                                dbShape.Lat              = lat;
                                dbShape.Lon              = lon;
                                dbShape.RouteID          = routeID;
                                dbShape.Sequence         = sequence;
                                dbShape.DistanceTraveled = totalDistance;
                                sequence++;
                                db.Shapes.Add(dbShape);
                            }
                        }
                        db.SaveChanges();

                        var assignStops = new AssignStopsToRoutes();
                        assignStops.UpdateStopsForRoute(db, routeID);

                        var route = db.Routes.Find(routeID);
                        logger.Info($"Modified route shape of '{route.Description}' - '{route.LongName}'");
                    }
                }

                return(RedirectToAction("Index"));
            }
            catch (Exception ex)
            {
                ViewBag.Message = "Shape save exception";

                logger.Error(ex, "Exception saving route shape");
                ViewBag.RouteID = new SelectList(db.Routes, "ID", "ShortName");
                return(View());
            }
        }
        // Calculate the distance between
        // Node 'stopPosition' and the segment p1 --> p2, where p1 -> p2 is a subset of a way.
        private double FindDistanceToSegment(Coordinate stopPosition, Coordinate p1, Coordinate p2, out Coordinate closest)
        {
            double dx = p2.Lon - p1.Lon;
            double dy = p2.Lat - p1.Lat;
            if ((dx == 0) && (dy == 0))
            {
                // It's a point not a line segment.
                closest = p1;
                dx = stopPosition.Lon - p1.Lon;
                dy = stopPosition.Lat - p1.Lat;

                //return Math.Sqrt(dx * dx + dy * dy);
                return stopPosition.GreatCircleDistance(closest);
            }

            // Calculate the t that minimizes the distance.
            double t = ((stopPosition.Lon - p1.Lon) * dx + (stopPosition.Lat - p1.Lat) * dy) / (dx * dx + dy * dy);

            // See if this represents one of the segment's
            // end points or a point in the middle.
            if (t < 0)
            {
                closest = new Coordinate(p1.Lat, p1.Lon);
                dx = stopPosition.Lon - p1.Lon;
                dy = stopPosition.Lat - p1.Lat;
            }
            else if (t > 1)
            {
                closest = new Coordinate(p2.Lat, p2.Lon);
                dx = stopPosition.Lon - p2.Lon;
                dy = stopPosition.Lat - p2.Lat;
            }
            else
            {
                closest = new Coordinate(p1.Lat + t * dy, p1.Lon + t * dx);
                dx = stopPosition.Lon - closest.Lon;
                dy = stopPosition.Lat - closest.Lat;
            }

            // For linear geometry return Math.Sqrt(dx * dx + dy * dy);

            // For earth geography below
            return stopPosition.GreatCircleDistance(closest);
        }