| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152 | 
							- using System;
 
- using System.Collections.Generic;
 
- using o0.Geometry2D.Float;
 
- using Unity.VisualScripting;
 
- namespace ZIM
 
- {
 
-     // 屏幕识别使用,固定的顶点顺序: 左下,右下,左上,右上,严格遵守
 
-     public class OrdinalQuadrilateral : Geometry<OrdinalQuadrilateral>
 
-     {
 
-         public Vector A;
 
-         public Vector B;
 
-         public Vector C;
 
-         public Vector D;
 
-         public override int Count => 4;
 
-         public OrdinalQuadrilateral(Vector a, Vector b, Vector c, Vector d)
 
-         {
 
-             this.A = a;
 
-             this.B = b;
 
-             this.C = c;
 
-             this.D = d;
 
-         }
 
-         public OrdinalQuadrilateral(IEnumerable<Vector> enumable)
 
-         {
 
-             var e = enumable.GetEnumerator();
 
-             this.A = e.MoveNext() ? e.Current : default;
 
-             this.B = e.MoveNext() ? e.Current : default;
 
-             this.C = e.MoveNext() ? e.Current : default;
 
-             this.D = e.MoveNext() ? e.Current : default;
 
-         }
 
-         public static OrdinalQuadrilateral Identity { get; } = new OrdinalQuadrilateral(new Vector(0, 0), new Vector(1, 0), new Vector(0, 1), new Vector(1, 1));
 
-         /// <summary>四边形的质心(顶点平均值)</summary>
 
-         public Vector Centroid => new Vector(A.x + B.x + C.x + D.x, A.y + B.y + C.y + D.y) / 4f;
 
-         public override Vector this[int index]
 
-         {
 
-             get
 
-             {
 
-                 switch (index % Count)
 
-                 {
 
-                     default:
 
-                     case 0:
 
-                         return A;
 
-                     case 1:
 
-                         return B;
 
-                     case 2:
 
-                         return C;
 
-                     case 3:
 
-                         return D;
 
-                 }
 
-             }
 
-             set
 
-             {
 
-                 switch (index % Count)
 
-                 {
 
-                     default:
 
-                     case 0:
 
-                         A = value;
 
-                         break;
 
-                     case 1:
 
-                         B = value;
 
-                         break;
 
-                     case 2:
 
-                         C = value;
 
-                         break;
 
-                     case 3:
 
-                         D = value;
 
-                         break;
 
-                 }
 
-             }
 
-         }
 
-         public override string ToString()
 
-         {
 
-             return $"[{A}, {B}, {C}, {D}]";
 
-         }
 
-         // AABB包围盒,返回矩形左下角和右上角的坐标
 
-         public (Vector, Vector) AABBRect()
 
-         {
 
-             float minX = this[0].x;
 
-             float maxX = this[0].x;
 
-             float minY = this[0].y;
 
-             float maxY = this[0].y;
 
-             for (int i = 1; i < Count; i++)
 
-             {
 
-                 minX = Math.Min(minX, this[i].x);
 
-                 maxX = Math.Max(maxX, this[i].x);
 
-                 minY = Math.Min(minY, this[i].y);
 
-                 maxY = Math.Max(maxY, this[i].y);
 
-             }
 
-             return (new Vector(minX, minY), new Vector(maxX, maxY));
 
-         }
 
-         public Vector InterpolationFactors(Vector p)
 
-         {
 
-             float u, v;
 
-             float _a = (C.x - D.x + B.x - A.x) * (A.y - C.y) - (C.y - D.y + B.y - A.y) * (A.x - C.x);
 
-             float _b = (D.x - C.x) * (A.y - C.y) - (D.y - C.y) * (A.x - C.x) + (p.x - C.x) * (C.y - D.y + B.y - A.y) - (p.y - C.y) * (C.x - D.x + B.x - A.x);
 
-             float _c = (p.x - C.x) * (D.y - C.y) - (p.y - C.y) * (D.x - C.x);
 
-             if (_a < float.Epsilon)
 
-             {
 
-                 v = -_c / _b;
 
-             }
 
-             else
 
-             {
 
-                 float delta = _b * _b - 4 * _a * _c;
 
-                 if (delta < 0)
 
-                 {
 
-                     return default;
 
-                     throw new Exception("Delta is smaller than zero.");
 
-                 }
 
-                 float sqrtDelta = (float)Math.Sqrt(delta);
 
-                 v = (-_b + sqrtDelta) / (2 * _a);
 
-                 if (v < 0 || v > 1)
 
-                     v = (-_b - sqrtDelta) / (2 * _a);
 
-             }
 
-             u = ((p.x - C.x) - (A.x - C.x) * v) / ((D.x - C.x) + (C.x - D.x + B.x - A.x) * v);
 
-             return new Vector(u, 1 - v);
 
-         }
 
-         public static OrdinalQuadrilateral Fit(IEnumerable<Vector> pixels, Vector textureSize)
 
-         {
 
-             Vector[] vertex = new Vector[4] { new Vector(0, 0), new Vector(textureSize.x, 0), new Vector(textureSize.y, 0), textureSize };
 
-             Vector[] dir = new Vector[4] { new Vector(1, 1).Normalized, new Vector(-1, 1).Normalized, new Vector(1, -1).Normalized, new Vector(-1, -1).Normalized };
 
-             (float, Vector)[] min = new (float, Vector)[4] { (float.MaxValue, default), (float.MaxValue, default), (float.MaxValue, default), (float.MaxValue, default) };
 
-             foreach (var i in pixels)
 
-             {
 
-                 for (int j = 0; j < 4; j++)
 
-                 {
 
-                     var len = (i - vertex[j]).Dot(dir[j]);
 
-                     if (len < min[j].Item1)
 
-                         min[j] = (len, i);
 
-                 }
 
-             }
 
-             return new OrdinalQuadrilateral(min[0].Item2, min[1].Item2, min[2].Item2, min[3].Item2);
 
-         }
 
-     }
 
- }
 
 
  |