public void TestDistance() { Vector p1 = new Vector(0, 0); Vector p2 = new Vector(3, 4); Assert.IsTrue(p1.Distance(p2) == 5, "Distance calc 1 failed"); Assert.IsTrue(p1.Distance2(p2) == 25, "Distance2 calc 1 failed"); Assert.IsTrue(new Vector(1, 1).Closest(p1, new Vector(2, 0)) == new Vector(1, 0), "Closest point 1 failed."); //Same test for point that is already on the line Assert.IsTrue(new Vector(1, 0).Closest(p1, new Vector(2, 0)) == new Vector(1, 0), "Closest point 3 failed."); }
public void TestEquality() { Vector p1 = new Vector(0, 0); Vector p2 = new Vector(1, 0); Vector p3 = new Vector(0, 0); Assert.IsTrue(p1 == p3, "Equality test to same coordinates failed."); Assert.IsFalse(p1 == p2, "Equality test for 2 different points failed"); Assert.IsFalse(p1 != p3, "Inequality test to same point failed."); Assert.IsTrue(p1 != p2, "Inequality test for 2 different points failed"); }
public void TestMath() { Vector p1 = new Vector(0, 0); Vector p2 = new Vector(1, -1); Assert.IsTrue(p1 + p2 == new Vector(1, -1), "Vector addition 1 failed."); Assert.IsTrue(p1 - p2 == new Vector(-1, 1), "Vector subtraction 1 failed."); Assert.IsTrue(p2 * 3 == new Vector(3, -3), "Vector multiplication 1 failed."); Assert.IsTrue(new Vector(2, 3).Dot(new Vector(3, 2)) == 12, "Dot 1 failed"); Assert.IsTrue(new Vector(2, 3).PerpDot(new Vector(3, 2)) == -5, "PerpDot 1 failed"); //Perp dot on same line Assert.IsTrue(new Vector(2, 3).PerpDot(new Vector(4, 6)) == 0, "PerpDot 3 failed"); }
public void TestAngleDetection() { //Calculates angle to a point in each cardinal direction var tests = new List<KeyValuePair<Vector, double>>(); tests.Add(new KeyValuePair<Vector, double>(new Vector(1, 0), 0d)); tests.Add(new KeyValuePair<Vector, double>(new Vector(1, 1), Math.PI / 4)); tests.Add(new KeyValuePair<Vector, double>(new Vector(0, 1), Math.PI / 2)); tests.Add(new KeyValuePair<Vector, double>(new Vector(-1, 1), 3 * Math.PI / 4)); tests.Add(new KeyValuePair<Vector, double>(new Vector(-1, 0), Math.PI)); tests.Add(new KeyValuePair<Vector, double>(new Vector(-1, -1), -3 * Math.PI / 4)); tests.Add(new KeyValuePair<Vector, double>(new Vector(0, -1), -Math.PI / 2)); tests.Add(new KeyValuePair<Vector, double>(new Vector(1, -1), -Math.PI / 4)); string format = "AngleTo fails on {0}. Expected {1}, got {2}"; Vector origin = new Vector(0, 0); foreach (var test in tests) { double angle = origin.AngleTo(test.Key); Assert.IsTrue(angle == test.Value, string.Format(format, test.Value, test.Key, angle)); } }
public void TestAngleProjection() { //Test GetPointAt in all 8 cardinal directions. Origin assumed to be in top-left var tests = new List<KeyValuePair<double, Vector>>(); tests.Add(new KeyValuePair<double, Vector>(0d, new Vector(1, 0))); tests.Add(new KeyValuePair<double, Vector>(Math.PI / 4, new Vector(1, -1))); tests.Add(new KeyValuePair<double, Vector>(Math.PI / 2, new Vector(0, -1))); tests.Add(new KeyValuePair<double, Vector>(3 * Math.PI / 4, new Vector(-1, -1))); tests.Add(new KeyValuePair<double, Vector>(Math.PI, new Vector(-1, 0))); tests.Add(new KeyValuePair<double, Vector>(-3 * Math.PI / 4, new Vector(-1, 1))); tests.Add(new KeyValuePair<double, Vector>(-Math.PI / 2, new Vector(0, 1))); tests.Add(new KeyValuePair<double, Vector>(-Math.PI / 4, new Vector(1, 1))); string format = "GetPointAt fails on {0}. Expected {1}, got {2}"; Vector origin = new Vector(0, 0); foreach (var pair in tests) { double hypotenuse = origin.Distance(pair.Value); Vector point = origin.GetPointAt(hypotenuse, pair.Key); Assert.IsTrue(point == pair.Value, string.Format(format, pair.Key, pair.Value, point)); } }
/// <summary> /// Perpendicular dot product (determinant) of the vector. /// Positive if the point lies counterclockwise to the vector, negative /// if clockwise, and 0 if it lies on the same line. /// </summary> public double PerpDot(Vector other) { return -Y * other.X + X * other.Y; }
/// <summary> /// Dot product of this vector and the other /// </summary> public double Dot(Vector other) { return X * other.X + Y * other.Y; }
/// <summary> /// Angle from this point to another. Assumes Origin (0,0) is top-left /// </summary> public double AngleTo(Vector other) { return Math.Atan2(other.Y - Y, other.X - X); }
/// <summary> /// Distance squared to the other point (faster than Euclidean calc) /// </summary> /// <param name="t"></param> /// <param name="other"></param> /// <returns></returns> public double Distance2(Vector other) { return (other.X - X) * (other.X - X) + (other.Y - Y) * (other.Y - Y); }
/// <summary> /// Euclidean distance from this point to the other /// </summary> public double Distance(Vector other) { return Math.Sqrt((other.X - X) * (other.X - X) + (other.Y - Y) * (other.Y - Y)); }
public Vector(Vector other) { X = other.X; Y = other.Y; }
/// <summary> /// On the line described by the 2 other points, return the point closest to this one. /// </summary> public Vector Closest(Vector a, Vector b) { double da = b.Y - a.Y; double db = a.X - b.X; double c1 = db * a.X + db * a.Y; double c2 = -db * this.X + da * this.Y; double det = da * da + db * db; double cx = 0; double cy = 0; if (det != 0) { cx = (da * c1 - db * c2) / det; cy = (da * c2 + db * c1) / det; } else { // The point is already on the line cx = this.X; cy = this.Y; } return new Vector(cx, cy); }
public Point(Vector other) { X = (int)(other.X); Y = (int)(other.Y); }