// angle ABC
        public static double InteriorAngle(Coordinate2 <double> a, Coordinate2 <double> b, Coordinate2 <double> c)
        {
            double da = AngleBetween(b, a);
            double db = AngleBetween(b, c);

            return(Math.Abs(db - da));
        }
        private static Coordinate2 <double> MeanNearest(Coordinate2 <double> p1, Coordinate2 <double> p2, Coordinate2 <double> q1, Coordinate2 <double> q2)
        {
            Coordinate2 <double> mean = new Coordinate2 <double>((p1.X + p2.X + q1.X + q2.X) * 0.25, (p1.Y + p2.Y + q1.Y + q2.Y) * 0.25);

            Coordinate2 <double> intPt = p1;
            double bestDist            = CoordinatePair2Utils.Length(mean.X, mean.Y, intPt.X, intPt.Y);
            double curDist             = CoordinatePair2Utils.Length(mean.X, mean.Y, p2.X, p2.Y);

            if (curDist < bestDist)
            {
                bestDist = curDist;
                intPt    = p2;
            }
            curDist = CoordinatePair2Utils.Length(mean.X, mean.Y, q1.X, q1.Y);
            if (curDist < bestDist)
            {
                bestDist = curDist;
                intPt    = q1;
            }
            curDist = CoordinatePair2Utils.Length(mean.X, mean.Y, q2.X, q2.Y);
            if (curDist < bestDist)
            {
                //bestDist = curDist;
                //intPt = q2;
                return(q2);
            }
            return(intPt);
        }
        /**
         * Normalize the supplied coordinates to
         * so that the midpoint of their intersection envelope
         * lies at the origin.
         *
         * @param n00
         * @param n01
         * @param n10
         * @param n11
         * @param normPt
         */
        public static void NormalizeToEnvCentre(Coordinate2 <double> n00, Coordinate2 <double> n01, Coordinate2 <double> n10, Coordinate2 <double> n11, Coordinate2 <double> normPt)
        {
            double minX0 = n00.X < n01.X ? n00.X : n01.X;
            double minY0 = n00.Y < n01.Y ? n00.Y : n01.Y;
            double maxX0 = n00.X > n01.X ? n00.X : n01.X;
            double maxY0 = n00.Y > n01.Y ? n00.Y : n01.Y;

            double minX1 = n10.X < n11.X ? n10.X : n11.X;
            double minY1 = n10.Y < n11.Y ? n10.Y : n11.Y;
            double maxX1 = n10.X > n11.X ? n10.X : n11.X;
            double maxY1 = n10.Y > n11.Y ? n10.Y : n11.Y;

            double intMinX = minX0 > minX1 ? minX0 : minX1;
            double intMaxX = maxX0 < maxX1 ? maxX0 : maxX1;
            double intMinY = minY0 > minY1 ? minY0 : minY1;
            double intMaxY = maxY0 < maxY1 ? maxY0 : maxY1;

            double intMidX = (intMinX + intMaxX) / 2.0;
            double intMidY = (intMinY + intMaxY) / 2.0;

            normPt.X = intMidX;
            normPt.Y = intMidY;

            n00.X -= normPt.X;
            n00.Y -= normPt.Y;

            n01.X -= normPt.X;
            n01.Y -= normPt.Y;

            n10.X -= normPt.X;
            n10.Y -= normPt.Y;

            n11.X -= normPt.X;
            n11.Y -= normPt.Y;
        }
        /// <summary>
        /// Test the envelope defined by p1-p2 for intersection with the envelope defined by q1-q2
        /// </summary>
        internal static bool EnvelopesIntersect(Coordinate2 <double> p1, Coordinate2 <double> p2, Coordinate2 <double> q1, Coordinate2 <double> q2)
        {
            double minp = p1.X < p2.X ? p1.X : p2.X;
            double maxq = q1.X > q2.X ? q1.X : q2.X;

            if (minp > maxq)
            {
                return(false);
            }

            double minq = q1.X < q2.X ? q1.X : q2.X;
            double maxp = p1.X > p2.X ? p1.X : p2.X;

            if (maxp < minq)
            {
                return(false);
            }

            maxq = q1.Y > q2.Y ? q1.Y : q2.Y;
            minp = p1.Y < p2.Y ? p1.Y : p2.Y;

            if (minp > maxq)
            {
                return(false);
            }

            minq = q1.Y < q2.Y ? q1.Y : q2.Y;
            maxp = p1.Y > p2.Y ? p1.Y : p2.Y;

            if (maxp < minq)
            {
                return(false);
            }
            return(true);
        }
        /// <summary>
        /// Test the envelope defined by p1-p2 for intersection with the envelope defined by q1-q2
        /// </summary>
        /// <param name="p1"></param>
        /// <param name="p2"></param>
        /// <param name="q1"></param>
        /// <param name="q2"></param>
        /// <returns></returns>
        public static bool EnvelopesIntersect(Coordinate2 <double> p1, Coordinate2 <double> p2, Coordinate2 <double> q1, Coordinate2 <double> q2)
        {
            double minq = Math.Min(q1.X, q2.X);
            double maxq = Math.Max(q1.X, q2.X);
            double minp = Math.Min(p1.X, p2.X);
            double maxp = Math.Max(p1.X, p2.X);

            if (minp > maxq)
            {
                return(false);
            }
            if (maxp < minq)
            {
                return(false);
            }

            minq = Math.Min(q1.Y, q2.Y);
            maxq = Math.Max(q1.Y, q2.Y);
            minp = Math.Min(p1.Y, p2.Y);
            maxp = Math.Max(p1.Y, p2.Y);

            if (minp > maxq)
            {
                return(false);
            }
            if (maxp < minq)
            {
                return(false);
            }
            return(true);
        }
        // angle ABC
        public static double AngleBetween(Coordinate2 <double> a, Coordinate2 <double> b, Coordinate2 <double> c)
        {
            double a1 = AngleBetween(b, a);
            double a2 = AngleBetween(b, c);

            return(AngleUtils.Diff(a1, a2));
        }
        public static Envelope2 <T> EnvelopeFor <T>(Envelope2 <T> env, Coordinate2 <T> p)
            where T : IEquatable <T>, IComparable <T>
        {
            if (env == null || p == null)
            {
                return(null);
            }
            T minX = env.MinX;
            T maxX = env.MaxX;
            T minY = env.MinY;
            T maxY = env.MaxY;

            if (minX.CompareTo(p.X) > 0)
            {
                minX = p.X;
            }
            else if (maxX.CompareTo(p.X) < 0)
            {
                maxX = p.X;
            }
            if (minY.CompareTo(p.Y) > 0)
            {
                minY = p.Y;
            }
            else if (maxY.CompareTo(p.Y) < 0)
            {
                maxY = p.Y;
            }
            return(new Envelope2 <T>(minX, minY, maxX, maxY));
        }
        public static double Length(Coordinate2 <double> start, Coordinate2 <double> end)
        {
            double dx = end.X - start.X;
            double dy = end.Y - start.Y;

            return(Math.Sqrt(dx * dx + dy * dy));
        }
        //removes duplicated points in a chain of points - only adjacent duplicates are removed
        public static Coordinate2 <T>[] RemoveAdjacentDups <T>(IEnumerable <Coordinate2 <T> > chain, bool isRing)
            where T : IEquatable <T>, IComparable <T>
        {
            if (chain == null)
            {
                return(null);
            }
            Coordinate2 <T>         prev = null;
            List <Coordinate2 <T> > tmp  = new List <Coordinate2 <T> >();

            foreach (Coordinate2 <T> curPt in chain)
            {
                if (curPt == null)
                {
                    continue;
                }
                if (curPt.Equals(prev))
                {
                    continue; //dup
                }
                prev = curPt;
                tmp.Add(curPt);
            }
            if (isRing && tmp.Count > 1)
            {
                if (tmp[0].Equals(tmp[tmp.Count - 1])) //start and end are dup on a ring
                {
                    tmp.RemoveAt(tmp.Count - 1);       //get rid of the last item
                }
            }
            return(tmp.ToArray());
        }
Example #10
0
        public static Envelope2 <T> EnvelopeFor <T>(Coordinate2 <T> a, Coordinate2 <T> b)
            where T : IEquatable <T>, IComparable <T>
        {
            if (a == null || b == null)
            {
                return(null);
            }
            T minX = a.X;
            T maxX = a.X;
            T minY = a.Y;
            T maxY = a.Y;

            if (minX.CompareTo(b.X) > 0)
            {
                minX = b.X;
            }
            else if (maxX.CompareTo(b.X) < 0)
            {
                maxX = b.X;
            }
            if (minY.CompareTo(b.Y) > 0)
            {
                minY = b.Y;
            }
            else if (maxY.CompareTo(b.Y) < 0)
            {
                maxY = b.Y;
            }
            return(new Envelope2 <T>(minX, minY, maxX, maxY));
        }
Example #11
0
        public static double Distance(Coordinate2 <double> a, Coordinate2 <double> b)
        {
            double dX = b.X - a.X;
            double dY = b.Y - a.Y;

            return(Math.Sqrt(dX * dX + dY * dY));
        }
Example #12
0
 public LineIntersectionResult(Coordinate2 <T> basePoint, Coordinate2 <T> finalPoint)
 {
     if (basePoint == null)
     {
         if (finalPoint == null)
         {
             this.IntersectionType = LineIntersectionType.NoIntersection;
             this.BasePoint        = null;
             this.FinalPoint       = null;
         }
         else
         {
             this.IntersectionType = LineIntersectionType.PointIntersection;
             this.BasePoint        = finalPoint;
             this.FinalPoint       = null;
         }
     }
     else if (finalPoint == null)
     {
         this.IntersectionType = LineIntersectionType.PointIntersection;
         this.BasePoint        = basePoint;
         this.FinalPoint       = null;
     }
     else
     {
         this.IntersectionType = LineIntersectionType.CollinearIntersection;
         this.BasePoint        = basePoint;
         this.FinalPoint       = finalPoint;
     }
 }
Example #13
0
 public static bool PointsEqual(Coordinate2 <double> pt1, Coordinate2 <double> pt2)
 {
     if (MathUtils.AlmostEqual(pt1.X, pt2.X) && MathUtils.AlmostEqual(pt1.Y, pt2.Y))
     {
         return(true);
     }
     return(false);
 }
Example #14
0
 public bool Equals(Coordinate2 <T> other)
 {
     if (other == null)
     {
         return(false);
     }
     return(this.X.Equals(other.X) && this.Y.Equals(other.Y));
 }
Example #15
0
 public Coordinate2(Coordinate2 <T> other)
 {
     if (other == null)
     {
         throw new ArgumentNullException();
     }
     this.X = other.X;
     this.Y = other.Y;
 }
Example #16
0
 public CoordinatePair2(CoordinatePair2 <T> other)
 {
     if (other == null)
     {
         throw new ArgumentNullException();
     }
     this.Start = new Coordinate2 <T>(other.Start);
     this.End   = new Coordinate2 <T>(other.End);
 }
Example #17
0
 public CoordinatePair2(Coordinate2 <T> start, Coordinate2 <T> end)
 {
     if (start == null || end == null)
     {
         throw new ArgumentNullException();
     }
     this.Start = start;
     this.End   = end;
 }
Example #18
0
        // angle ABC
        public static bool IsObtuse(Coordinate2 <double> a, Coordinate2 <double> b, Coordinate2 <double> c)
        {
            double dx0 = a.X - b.X;
            double dy0 = a.Y - b.Y;
            double dx1 = c.X - b.X;
            double dy1 = c.Y - b.Y;
            double dp  = dx0 * dx1 + dy0 * dy1;

            return(dp < 0);
        }
Example #19
0
        // angle ABC
        public static double AngleBetweenCircular(Coordinate2 <double> a, Coordinate2 <double> b, Coordinate2 <double> c)
        {
            double da = AngleBetween(b, c) - AngleBetween(b, a);

            if (da < 0)
            {
                return(da + Constants.TwoPi);
            }
            return(da);
        }
Example #20
0
        public int CompareTo(Coordinate2 <T> other)
        {
            int dx = this.X.CompareTo(other.X);

            if (dx == 0)
            {
                return(this.Y.CompareTo(other.Y));
            }
            return(dx);
        }
 public static LineIntersectionType ComputeIntersectionType(Coordinate2 <double> p1, Coordinate2 <double> p2, Coordinate2 <double> p)
 {
     // do between check first, since it is faster than the orientation test
     if (PointInEnvelope(p1, p2, p))
     {
         if ((OrientationIndex(p1, p2, p) == 0) && (OrientationIndex(p2, p1, p) == 0))
         {
             return(LineIntersectionType.PointIntersection);
         }
     }
     return(LineIntersectionType.NoIntersection);
 }
 public static int OrientationIndex(Coordinate2 <double> p1, Coordinate2 <double> p2, Coordinate2 <double> q)
 {
     // travelling along p1->p2, turn counter clockwise to get to q return 1,
     // travelling along p1->p2, turn clockwise to get to q return -1,
     // p1, p2 and q are colinear return 0.
     //double dx1 = p2.X - p1.X;
     //double dy1 = p2.Y - p1.Y;
     //double dx2 = q.X - p2.X;
     //double dy2 = q.Y - p2.Y;
     //return AngleUtils.DeterminantSign(dx1, dy1, dx2, dy2);
     return(AngleUtils.DeterminantSign(p2.X - p1.X, p2.Y - p1.Y, q.X - p2.X, q.Y - p2.Y));
 }
Example #23
0
 public LineIntersectionResult(Coordinate2 <T> intersectionPoint)
 {
     if (intersectionPoint != null)
     {
         this.IntersectionType = LineIntersectionType.PointIntersection;
     }
     else
     {
         this.IntersectionType = LineIntersectionType.NoIntersection;
     }
     this.BasePoint  = intersectionPoint;
     this.FinalPoint = null;
 }
Example #24
0
        // angle ABC
        public static double AngleBetweenOriented(Coordinate2 <double> a, Coordinate2 <double> b, Coordinate2 <double> c)
        {
            double a1 = AngleBetween(b, a);
            double a2 = AngleBetween(b, c);
            double da = a2 - a1;

            if (da <= Constants.NPi)
            {
                return(da + Constants.TwoPi);
            }
            if (da > Math.PI)
            {
                return(da - Constants.TwoPi);
            }
            return(da);
        }
Example #25
0
        //Orientation of q with respect to line segment from p1->p2
        public static Orientation Orient(Coordinate2 <double> p1, Coordinate2 <double> p2, Coordinate2 <double> q)
        {
            double dx1  = p2.X - p1.X;
            double dy1  = p2.Y - p1.Y;
            double dx2  = q.X - p2.X;
            double dy2  = q.Y - p2.Y;
            int    sign = AngleUtils.DeterminantSign(dx1, dy1, dx2, dy2);

            if (sign < 0)
            {
                return(Orientation.Clockwise);
            }
            else if (sign > 0)
            {
                return(Orientation.Counterclockwise);
            }
            return(Orientation.Collinear);
        }
        public static double Distance(Coordinate2 <double> p1, Coordinate2 <double> p2, Coordinate2 <double> q)
        {
            if (p1.Equals(p2))
            {
                return(Coordinate2Utils.Distance(p1, q));
            }
            double r = ((q.X - p1.X) * (p2.X - p1.X) + (q.Y - p1.Y) * (p2.Y - p1.Y)) / ((p2.X - p1.X) * (p2.X - p1.X) + (p2.Y - p1.Y) * (p2.Y - p1.Y));

            if (r <= 0.0d)
            {
                return(Coordinate2Utils.Distance(q, p1));
            }
            if (r >= 1.0d)
            {
                return(Coordinate2Utils.Distance(q, p2));
            }

            double s = ((p1.Y - q.Y) * (p2.X - p1.X) - (p1.X - q.X) * (p2.Y - p1.Y)) / ((p2.X - p1.X) * (p2.X - p1.X) + (p2.Y - p1.Y) * (p2.Y - p1.Y));

            return(Math.Abs(s) * Math.Sqrt(((p2.X - p1.X) * (p2.X - p1.X) + (p2.Y - p1.Y) * (p2.Y - p1.Y))));
        }
        public static Coordinate2 <double> NearestPoint(Coordinate2 <double> p0, Coordinate2 <double> p1, Coordinate2 <double> q)
        {
            if (p0.Equals(p1))
            {
                return(p0);
            }

            double s1 = (p1.Y - p0.Y) * (q.Y - p0.Y) + (p1.X - p0.X) * (q.X - p0.X);
            double s2 = (p1.Y - p0.Y) * (q.Y - p1.Y) + (p1.X - p0.X) * (q.X - p1.X);

            if (s1 * s2 <= 0)
            {
                double lam = (p0.Y - p1.Y) * (p0.Y - p1.Y) + (p0.X - p1.X) * (p0.X - p1.X); //dotproduct of p0-p1
                lam = ((q.Y - p0.Y) * (p0.Y - p1.Y) + (q.X - p0.X) * (p0.X - p1.X)) / lam;
                return(new Coordinate2 <double>(p0.X + lam * (p0.X - p1.X), p0.Y + lam * (p0.Y - p1.Y)));
            }
            else
            {
                return((s1 > 0) ? p1 : p0);
            }
        }
Example #28
0
        public static Envelope2 <T> EnvelopeFor <T>(IEnumerable <Coordinate2 <T> > points)
            where T : IEquatable <T>, IComparable <T>
        {
            if (points == null)
            {
                return(null);
            }
            IEnumerator <Coordinate2 <T> > en = points.GetEnumerator();

            if (en.MoveNext())
            {
                Coordinate2 <T> cur = en.Current;
                T minX = cur.X;
                T maxX = cur.X;
                T minY = cur.Y;
                T maxY = cur.Y;
                while (en.MoveNext())
                {
                    cur = en.Current;
                    if (minX.CompareTo(cur.X) > 0)
                    {
                        minX = cur.X;
                    }
                    else if (maxX.CompareTo(cur.X) < 0)
                    {
                        maxX = cur.X;
                    }
                    if (minY.CompareTo(cur.Y) > 0)
                    {
                        minY = cur.Y;
                    }
                    else if (maxY.CompareTo(cur.Y) < 0)
                    {
                        maxY = cur.Y;
                    }
                }
                return(new Envelope2 <T>(minX, minY, maxX, maxY));
            }
            return(null);
        }
        public static Coordinate2 <double> Bisector(Coordinate2 <double> p1, Coordinate2 <double> p2)
        {
            double dX  = p2.X - p1.X;
            double dY  = p2.Y - p1.Y;
            double l1X = p1.X + (dX * 0.5);
            double l1Y = p1.Y + (dY * 0.5);
            double l2X = p1.X - dY + (dX * 0.5);
            double l2Y = p1.Y + dX + (dY * 0.5);

            double w = l1X * l2Y - l2X * l1Y;

            if (w == 0)
            {
                w = double.Epsilon;
            }
            else if (double.IsInfinity(w) || double.IsNaN(w))
            {
                if (double.IsPositiveInfinity(w))
                {
                    w = double.MaxValue;
                }
                else if (double.IsNegativeInfinity(w))
                {
                    w = double.MinValue;
                }
                else
                {
                    w = double.Epsilon;
                }
            }

            dX = (l1Y - l2Y) / w;
            dY = (l2X - l1X) / w;

            return(new Coordinate2 <double>(dX, dY));
        }
Example #30
0
        private static Coordinate2 <double> MeanNearest(Coordinate2 <double> p1, Coordinate2 <double> p2, Coordinate2 <double> q1, Coordinate2 <double> q2)
        {
            Coordinate2 <double> mean = new Coordinate2 <double>(p1.X, p1.Y);

            mean.X += p2.X;
            mean.Y += p2.Y;
            mean.X += q1.X;
            mean.Y += q1.Y;
            mean.X += q2.X;
            mean.Y += q2.Y;
            mean.X *= 0.25;
            mean.Y *= 0.25;

            Coordinate2 <double> intPt = p1;
            double bestDist            = MathUtils.Distance(mean.X, mean.Y, intPt.X, intPt.Y);
            double curDist             = MathUtils.Distance(mean.X, mean.Y, p2.X, p2.Y);

            if (curDist < bestDist)
            {
                bestDist = curDist;
                intPt    = p2;
            }
            curDist = MathUtils.Distance(mean.X, mean.Y, q1.X, q1.Y);
            if (curDist < bestDist)
            {
                bestDist = curDist;
                intPt    = q1;
            }
            curDist = MathUtils.Distance(mean.X, mean.Y, q2.X, q2.Y);
            if (curDist < bestDist)
            {
                bestDist = curDist;
                intPt    = q2;
            }
            return(intPt);
        }