Search code examples
google-mapsmathroutescomparisoncoordinates

How to tell the direction of the given points


I am coming up or am looking for an equation to this trivial problem:

Well it's more about knowing the direction in which the user is going based on the users geo location.

As you can see below the User's first coordinates are in point x after a minute or two the user's coordinates changed and is now at point y

Given the User's coordinates x and y , the Intersection point A and Point B how do I come up with a formula that would tell me if the user is in the right lane (going from point B to point A) or is in the left lane (going from point A to point B).

see image


Solution

  • Assuming this is just coordinate based, and does NOT need to take into consideration the road or path the points are on, use the dot product. Create segments from points and dot product of two segments is positive if segments are aligned (point is same direction with less than 90 degrees) and negative if segments point in opposite directions.

    If problem needs to consider the road or path, then the below will not work, because road/path may at times curve back and be moving away from destination, so correct direction on the road/path would temporarily be increasing distance to destination (as the crow flies). As your question is worded it SOUNDS like you want to be able to tell, from a single user position X and Y values which lane of a defined road they are in. If you think about it, that is simply not possible without knowing the exact geometry of the road/path itself. If it is curved at all, it becomes impossible to determine. Think about it. For ANY given position on the ground, you could bend the road one way or the other to cause that spot to be in either lane...

    But with TWO positions, that represent movement in time, and the assumption that they are moving forward in whatever lane they are in, you CAN determine whether that motion is more towards Point A or towards Point B.

    Technically, dot product of two vectors A and B
    A dot B = |A| x |B| x Cos(Angle between them))

    So, and AGAIN, this is assuming you don't need to take into consideration the shape or curvature of the road, you just make two directed segments, one from B to A, and another from one user position to a subsequent user position (representing his/her motion during some finite time interval), and take the dot product of these two segments. If it's positive, he's moving towards A, if negative, hes moving towards B.

    (this code is simplified)

    public struct Point
    {
        public double X { get; set; }
        public double Y { get; set; }
    
        private Point(double xValue, double yValue)
        { X = xValue; Y = yValue; }
        public static Point Make(double x, double y)
        { return new Point(x, y); }
    }
    
    
    public class Segment
    {
        public Point StartPoint { get; set; }
        public Point EndPoint { get; set; }
    
        #region ctor / factories
        protected Segment(Point startPoint, Point endPoint)
            : base(startPoint, (endPoint.Y - startPoint.Y) /
                                (endPoint.X - startPoint.X))
        {
           StartPoint = startPoint;
           EndPoint = endPoint;
        }
        public static new Segment Make(Point startPoint, Point endPoint)
        {
            if (startPoint == endPoint)
                throw new Exception(
                    "You must use two different points to define a segment.");
            return new Segment(startPoint, endPoint);
        }
        public static new Segment Make(double ax, double ay, double px, double py)
        { return Make(Point.Make(ax, ay), Point.Make(px, py)); }
    
        public static Segment NullSegment { get { return new Segment(); } }
        #endregion ctor / factories
    
        public double Length
        {
            get
            {
                return Math.Sqrt(
                    Math.Pow(EndPoint.Y - StartPoint.Y, 2) +
                    Math.Pow(EndPoint.X - StartPoint.X, 2));
            }
        }
    
        public double DotProduct(Segment seg, bool normalize = false)
        {
            double
                dAx = EndPoint.X - StartPoint.X,
                dAy = EndPoint.Y - StartPoint.Y,
                dBx = seg.EndPoint.X - seg.StartPoint.X,
                dBy = seg.EndPoint.Y - seg.StartPoint.Y;
    
            var dP = dAx * dBx + dAy * dBy;
    
            return normalize? dP / Length / seg.Length : dP;
        }
    }