| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135 |
- using System;
- using System.Collections;
- using System.Collections.Generic;
- using UnityEngine;
- namespace ZIM.Unity
- {
- public class UnityQuadrilateral
- {
- Vector2 a, b, c, d; // 左下,右下,左上,右上
- public UnityQuadrilateral(Vector2 a, Vector2 b, Vector2 c, Vector2 d)
- {
- this.a = a;
- this.b = b;
- this.c = c;
- this.d = d;
- }
- public Vector2 this[int index]
- {
- get
- {
- switch (index)
- {
- case 0: return this.a;
- case 1: return this.b;
- case 2: return this.c;
- case 3: return this.d;
- default: return default;
- }
- }
- }
- public bool IsInScreen(Vector2 size)
- {
- if (a.x < b.x && a.y < c.y && b.y < d.y && c.x < d.x && a.x > 0 && a.y > 0 &&
- b.x < size.x && b.y > 0 && c.x > 0 && c.y < size.y && d.x < size.x && d.y < size.y)
- return true;
- return false;
- }
- public override string ToString()
- {
- return $"{a}, {b}, {c}, {d}";
- }
- public Vector2 InterpolationFactors(Vector2 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 = Mathf.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 Vector2(u, 1 - v);
- }
- public static UnityQuadrilateral Fit(IEnumerable<Vector2> pixels, Vector2 textureSize)
- {
- Vector2[] vertex = new Vector2[4] { new Vector2(0, 0), new Vector2(textureSize.x, 0), new Vector2(textureSize.y, 0), textureSize };
- Vector2[] dir = new Vector2[4] { new Vector2(1, 1).normalized, new Vector2(-1, 1).normalized, new Vector2(1, -1).normalized, new Vector2(-1, -1).normalized };
- (float, Vector2)[] min = new (float, Vector2)[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 = Vector2.Dot(i - vertex[j], dir[j]);
- if (len < min[j].Item1)
- min[j] = (len, i);
- }
- }
- return new UnityQuadrilateral(min[0].Item2, min[1].Item2, min[2].Item2, min[3].Item2);
- //float minX = 0, minY = 0;
- //float maxX = textureSize.x, maxY = textureSize.y;
- //foreach (Vector2 p in pixels)
- //{
- // minX = Math.Min(minX, p.x);
- // minY = Math.Min(minY, p.y);
- // maxX = Math.Max(maxX, p.x);
- // maxY = Math.Max(maxY, p.y);
- //}
- //Vector2[] vertices = new Vector2[4];
- //vertices[0] = new Vector2(minX, minY); // 左下角
- //vertices[1] = new Vector2(maxX, minY); // 右下角
- //vertices[2] = new Vector2(minX, maxY); // 左上角
- //vertices[3] = new Vector2(maxX, maxY); // 右上角
- //for (int i = 0; i < 4; i++)
- //{
- // float minDistance = float.MaxValue;
- // Vector2 closestPoint = default;
- // foreach (var j in pixels)
- // {
- // float distance = (vertices[i] - j).magnitude;
- // if (distance < minDistance)
- // {
- // minDistance = distance;
- // closestPoint = j;
- // }
- // }
- // vertices[i] = closestPoint;
- //}
- //return new Quadrilateral(vertices[0], vertices[1], vertices[2], vertices[3]);
- }
- }
- }
|