// 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()); }
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)); }
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)); }
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; } }
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); }
public bool Equals(Coordinate2 <T> other) { if (other == null) { return(false); } return(this.X.Equals(other.X) && this.Y.Equals(other.Y)); }
public Coordinate2(Coordinate2 <T> other) { if (other == null) { throw new ArgumentNullException(); } this.X = other.X; this.Y = other.Y; }
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); }
public CoordinatePair2(Coordinate2 <T> start, Coordinate2 <T> end) { if (start == null || end == null) { throw new ArgumentNullException(); } this.Start = start; this.End = end; }
// 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); }
// 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); }
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)); }
public LineIntersectionResult(Coordinate2 <T> intersectionPoint) { if (intersectionPoint != null) { this.IntersectionType = LineIntersectionType.PointIntersection; } else { this.IntersectionType = LineIntersectionType.NoIntersection; } this.BasePoint = intersectionPoint; this.FinalPoint = null; }
// 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); }
//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); } }
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)); }
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); }