using System; namespace InkCanvasForClassX.Libraries { /// /// 提供了對平面向量的坐標運算 /// public class Vector { private double _x = 0; private double _y = 0; public Vector(double x = 0, double y = 0) { _x = x; _y = y; } public double X { get => _x; set => _x = value; } public double Y { get => _y; set => _y = value; } /// /// 將該向量改變為其相反向量 /// public Vector Negate() { _x = -_x; _y = -_y; return this; } /// /// 提供一個Vector,返回該Vector的相反向量 /// public static Vector NegateVector(Vector vec) { return new Vector(-vec.X, -vec.Y); } /// /// Csharp中的Math.Hypot實現 /// private static double Hypot(params double[] values) { double sum = 0; foreach (var value in values) { sum += Math.Pow(value, 2); } return Math.Sqrt(sum); } /// /// 獲取該向量的長度 /// public double Length => Vector.Hypot(_x,_y); /// /// 獲取該向量的未開平方的長度 /// public double LengthSquared => _x * _x + _y * _y; /// /// 將該向量和另一個向量相加 /// public Vector Add(Vector vec) { _x = _x + vec.X; _y = _y + vec.Y; return this; } /// /// 提供兩個Vector,返回相加後的Vector /// public static Vector AddVectors(Vector vec1, Vector vec2) { return new Vector(vec1.X + vec2.X, vec1.Y + vec2.Y); } /// /// 將該向量減去另一個向量 /// public Vector Subtract(Vector vec) { _x = _x - vec.X; _y = _y - vec.Y; return this; } /// /// 提供兩個Vector,返回-後的Vector /// public static Vector SubtractVectors(Vector vec1, Vector vec2) { return new Vector(vec1.X - vec2.X, vec1.Y - vec2.Y); } /// /// 將該向量除以一個數值 /// public Vector DivideBy(double n) { _x = _x / n; _y = _y / n; return this; } /// /// 提供兩個Vector,返回/後的Vector /// public static Vector DivideByVector(Vector vec, double n) { return new Vector(vec.X / n, vec.Y / n); } /// /// 將該向量乘以一個數值 /// public Vector Multiply(double n) { _x = _x * n; _y = _y * n; return this; } /// /// 提供兩個Vector,返回*後的Vector /// public static Vector MultiplyVector(Vector vec, double n) { return new Vector(vec.X * n, vec.Y * n); } /// /// 將該向量垂直旋轉 /// public Vector PerpendicularRotation() { var _t = _x; _x = _y; _y = - _t; return this; } /// /// 提供Vector,返回垂直旋轉後的Vector /// public static Vector PerpendicularRotationVector(Vector vec) { return new Vector(vec.Y, - vec.X); } /// /// 提供兩個Vector,返回兩個Vector點乘後的数值 /// public static double DotVectors(Vector vec1, Vector vec2) { return vec1.X * vec2.X + vec1.Y * vec2.Y; } /// /// 判斷該向量和另外一個向量是否相等 /// public bool IsEqual(Vector vec) { return Math.Abs(_x - vec.X) < 0.01 && Math.Abs(_y - vec.Y) < 0.01; } /// /// 獲取該向量和另一個向量的平方距離 /// public double DistLengthSquared(Vector vec) { var subVec = Vector.SubtractVectors(this, vec); return subVec.LengthSquared; } /// /// 獲取一個向量和另一個向量的平方距離 /// public static double DistLengthSquaredVectors(Vector vec1, Vector vec2) { var subVec = Vector.SubtractVectors(vec1, vec2); return subVec.LengthSquared; } /// /// 獲取該向量和另一個向量的距離 /// public double DistLength(Vector vec) { return Vector.Hypot(this._y - vec.Y, this._x - vec.X); } /// /// 獲取一個向量和另一個向量的距離 /// public static double DistLengthVectors(Vector vec1, Vector vec2) { return Vector.Hypot(vec1.Y - vec2.Y, vec1.X - vec2.X); } /// /// 將該向量修改為其中間向量 /// public Vector Med(Vector vec) { var addVec = new Vector(_x, _y).Add(vec); addVec.Multiply(0.5); _x = addVec.X; _y = addVec.Y; return this; } /// /// 獲取一個向量和另一個向量的中間向量 /// public static Vector MedVectors(Vector vec1, Vector vec2) { var addVec = Vector.AddVectors(vec1, vec2); return addVec.Multiply(0.5); } /// /// 將該向量圍繞另一個向量旋轉r弧度 /// public Vector Rotate(Vector vec, double r) { var sin = Math.Sin(r); var cos = Math.Cos(r); var px = _x - vec.X; var py = _y - vec.Y; var nx = px * cos - py * sin; var ny = px * sin + py * cos; _x = nx + vec.X; _y = ny + vec.Y; return this; } /// /// 將一個向量圍繞另一個向量旋轉r弧度 /// public static Vector RotateVectors(Vector vec1, Vector vec2, double r) { var sin = Math.Sin(r); var cos = Math.Cos(r); var px = vec1.X - vec2.X; var py = vec1.Y - vec2.Y; var nx = px * cos - py * sin; var ny = px * sin + py * cos; return new Vector(nx + vec2.X, ny + vec2.Y); } /// /// 將該向量與另一個向量插值 /// public Vector Interpolate(Vector vec, double t) { Add(SubtractVectors(vec, this).Multiply(t)); return this; } /// /// 將一個向量與另一個向量插值 /// public static Vector InterpolateVectors(Vector vec1, Vector vec2, double t) { return AddVectors(vec1, SubtractVectors(vec2, vec1).Multiply(t)); } /// /// 將該向量投影在向量的方向上,並附加距離 /// public Vector Project(Vector vec, double c) { Add(vec.Multiply(c)); return this; } /// /// 將投影在向量的方向上,並附加距離 /// public static Vector ProjectVectors(Vector vec1, Vector vec2, double c) { return AddVectors(vec1, MultiplyVector(vec2,c)); } /// /// 取得單位向量 /// public Vector Unit() { return DivideByVector(this, Length); } /// /// 取得單位向量 /// public static Vector UnitVector(Vector vec) { return DivideByVector(vec, vec.Length); } } }