孙广东 2017.10.22
http://blog.csdn.NET/u010019717
1、判断 一个点是否在 与坐标平行的矩形内
public struct AAB2 {
public Vector2 Min;
public Vector2 Max;
public static AAB2 CreateAAB2(Transform point0, Transform point1)
{
// Creates aab from two unsorted points, if you know min and max use constructor
return CreateFromTwoPoints(point0.position, point1.position);
}
public static AAB2 CreateFromTwoPoints(Vector2 point0, Vector2 point1)
{
AAB2 aab;
if (point0.x < point1.x)
{
aab.Min.x = point0.x;
aab.Max.x = point1.x;
}
else
{
aab.Min.x = point1.x;
aab.Max.x = point0.x;
}
if (point0.y < point1.y)
{
aab.Min.y = point0.y;
aab.Max.y = point1.y;
return aab;
}
aab.Min.y = point1.y;
aab.Max.y = point0.y;
return aab;
}
public bool Contains(ref Vector2 point)
{
if (point.x < this.Min.x)
{
return false;
}
if (point.x > this.Max.x)
{
return false;
}
if (point.y < this.Min.y)
{
return false;
}
if (point.y > this.Max.y)
{
return false;
}
return true;
}
public void CalcVertices(out Vector2 vertex0, out Vector2 vertex1, out Vector2 vertex2, out Vector2 vertex3)
{
vertex0 = this.Min;
vertex1 = new Vector2(this.Max.x, this.Min.y);
vertex2 = this.Max;
vertex3 = new Vector2(this.Min.x, this.Max.y);
}
}
[ExecuteInEditMode]
public class Test_ContPoint2AAB2 : MonoBehaviour
{
public Transform Point;
public Transform Box_Point0, Box_Point1;
private const float _pointRadius = .11f;
private void OnDrawGizmos()
{
Vector2 point = Point.position;
AAB2 box = AAB2.CreateAAB2(Box_Point0, Box_Point1);
bool cont = box.Contains(ref point);
FiguresColor();
DrawAAB(ref box);
if (cont) ResultsColor();
DrawPoint(point);
LogInfo(cont);
}
protected void DrawPoint(Vector2 position)
{
Gizmos.DrawSphere(position, _pointRadius);
}
protected void ResultsColor()
{
Gizmos.color = Color.blue;
}
protected void FiguresColor()
{
Gizmos.color = Color.gray;
}
protected void LogInfo(object value)
{
Debug.Log(value);
}
protected void DrawAAB(ref AAB2 box)
{
Vector2 v0, v1, v2, v3;
box.CalcVertices(out v0, out v1, out v2, out v3);
Gizmos.DrawLine(v0, v1);
Gizmos.DrawLine(v1, v2);
Gizmos.DrawLine(v2, v3);
Gizmos.DrawLine(v3, v0);
}
}
2、 判断是否在矩形内
矩形就是 Box 对象决定, 自己是原点, 旋转决定了两个轴 , Scale决定了 宽高!
[ExecuteInEditMode]
public class Test_ContPoint2Box2 : MonoBehaviour
{
public Transform Point;
public Transform Box;
private const float _pointRadius = .11f;
private void OnDrawGizmos()
{
Vector2 point = Point.position;
Box2 box = Box2.CreateBox2(Box);
bool cont = box.Contains(ref point);
FiguresColor();
DrawBox(ref box);
if (cont) ResultsColor();
DrawPoint(point);
LogInfo(cont);
}
protected void DrawPoint(Vector2 position)
{
Gizmos.DrawSphere(position, _pointRadius);
}
protected void ResultsColor()
{
Gizmos.color = Color.blue;
}
protected void FiguresColor()
{
Gizmos.color = Color.gray;
}
protected void LogInfo(object value)
{
Debug.Log(value);
}
protected void DrawBox(ref Box2 box)
{
Vector2 v0, v1, v2, v3;
box.CalcVertices(out v0, out v1, out v2, out v3);
Gizmos.DrawLine(v0, v1);
Gizmos.DrawLine(v1, v2);
Gizmos.DrawLine(v2, v3);
Gizmos.DrawLine(v3, v0);
}
}
public struct Box2 {
public Vector2 Center;
public Vector2 Axis0;
public Vector2 Axis1;
public Vector2 Extents;
public Box2(Vector2 center, Vector2 axis0, Vector2 axis1, Vector2 extents)
{
this.Center = center;
this.Axis0 = axis0;
this.Axis1 = axis1;
this.Extents = extents;
}
public static Box2 CreateBox2(Transform box)
{
return new Box2(box.position, box.right, box.up, box.localScale);
}
public bool Contains(ref Vector2 point)
{
Vector2 vector;
vector.x = point.x - this.Center.x;
vector.y = point.y - this.Center.y;
float num = vector.Dot(ref this.Axis0);
if (num < -this.Extents.x)
{
return false;
}
if (num > this.Extents.x)
{
return false;
}
num = vector.Dot(ref this.Axis1);
if (num < -this.Extents.y)
{
return false;
}
if (num > this.Extents.y)
{
return false;
}
return true;
}
public void CalcVertices(out Vector2 vertex0, out Vector2 vertex1, out Vector2 vertex2, out Vector2 vertex3)
{
Vector2 vector = (Vector2)(this.Axis0 * this.Extents.x);
Vector2 vector2 = (Vector2)(this.Axis1 * this.Extents.y);
vertex0 = (this.Center - vector) - vector2;
vertex1 = (this.Center + vector) - vector2;
vertex2 = (this.Center + vector) + vector2;
vertex3 = (this.Center - vector) + vector2;
}
}
public static class Vector2ex
{
public static float Dot(this Vector2 vector, ref Vector2 value)
{
return ((vector.x * value.x) + (vector.y * value.y));
}
}
3、 判断一个点是否在园内部
[ExecuteInEditMode]
public class Test_ContPoint2Circle2 : MonoBehaviour
{
public Transform Point;
public Transform Circle;
private const float _pointRadius = .11f;
private void OnDrawGizmos()
{
Vector2 point = Point.position;
Circle2 circle = Circle2.CreateCircle2(Circle);
bool cont = circle.Contains(ref point);
FiguresColor();
DrawCircle(ref circle);
if (cont) ResultsColor();
DrawPoint(point);
LogInfo(cont);
}
protected void DrawPoint(Vector2 position)
{
Gizmos.DrawSphere(position, _pointRadius);
}
protected void ResultsColor()
{
Gizmos.color = Color.blue;
}
protected void FiguresColor()
{
Gizmos.color = Color.gray;
}
protected void LogInfo(object value)
{
Debug.Log(value);
}
protected void DrawCircle(ref Circle2 circle)
{
int count = 40;
float delta = 2f * Mathf.PI / count;
Vector3 prev = circle.Eval(0);
for (int i = 1; i <= count; ++i)
{
Vector3 curr = circle.Eval(i * delta);
Gizmos.DrawLine(prev, curr);
prev = curr;
}
}
}
public struct Circle2
{
public Vector2 Center;
public float Radius;
public Circle2(Vector2 center, float radius)
{
this.Center = center;
this.Radius = radius;
}
public bool Contains(ref Vector2 point)
{
Vector2 vector = point - this.Center;
return (vector.SqrMagnitude() <= (this.Radius * this.Radius));
}
public Vector2 Eval(float t)
{
return new Vector2(this.Center.x + (this.Radius * Mathf.Cos(t)), this.Center.y + (this.Radius * Mathf.Sin(t)));
}
public static Circle2 CreateCircle2(Transform circle)
{
return new Circle2(circle.position, circle.localScale.x);
}
}
4、 三角形内
[ExecuteInEditMode]
public class Test_ContPoint2Triangle2 : MonoBehaviour
{
public Transform Point;
public Transform V0, V1, V2;
private const float _pointRadius = .11f;
private void OnDrawGizmos()
{
Vector2 point = Point.position;
Triangle2 triangle = Triangle2.CreateTriangle2(V0, V1, V2);
Orientations orientation = triangle.CalcOrientation();
if (orientation == Orientations.CCW)
{
bool cont = triangle.Contains(ref point);
bool cont1 = triangle.ContainsCCW(ref point); // 如果你知道三角形方向(顶点顺序方向),就用这个
FiguresColor();
DrawTriangle(ref triangle);
if (cont) ResultsColor();
DrawPoint(point);
LogInfo("Orientation: " + orientation + " Contained: " + cont);
if (cont != cont1)
Debug.LogError("cont != cont1");
}
else if (orientation == Orientations.CW)
{
bool cont = triangle.Contains(ref point);
bool cont1 = triangle.ContainsCW(ref point); // 如果你知道三角形方向(顶点顺序方向),就用这个
FiguresColor();
DrawTriangle(ref triangle);
if (cont) ResultsColor();
DrawPoint(point);
LogInfo("Orientation: " + orientation + " Contained: " + cont);
if (cont != cont1)
Debug.LogError("cont != cont1");
}
else // Degenerate
{
Debug.LogError("Triangle is degenerate");
}
}
void DrawTriangle(ref Triangle2 triangle)
{
Gizmos.DrawLine(triangle.V0, triangle.V1);
Gizmos.DrawLine(triangle.V1, triangle.V2);
Gizmos.DrawLine(triangle.V2, triangle.V0);
}
protected void DrawPoint(Vector2 position)
{
Gizmos.DrawSphere(position, _pointRadius);
}
protected void ResultsColor()
{
Gizmos.color = Color.blue;
}
protected void FiguresColor()
{
Gizmos.color = Color.gray;
}
protected void LogInfo(object value)
{
Debug.Log(value);
}
}
public enum Orientations
{
CW,
CCW,
None
}
public struct Triangle2 {
public Vector2 V0;
public Vector2 V1;
public Vector2 V2;
public static Triangle2 CreateTriangle2(Transform v0, Transform v1, Transform v2)
{
return new Triangle2(v0.position, v1.position, v2.position);
}
public Triangle2(Vector2 v0, Vector2 v1, Vector2 v2)
{
this.V0 = v0;
this.V1 = v1;
this.V2 = v2;
}
public Orientations CalcOrientation(float threshold = 1E-05f)
{
float num = this.CalcDeterminant();
if (num > threshold)
{
return Orientations.CCW;
}
if (num < -threshold)
{
return Orientations.CW;
}
return Orientations.None;
}
public float CalcDeterminant()
{
return ((((((this.V1.x * this.V2.y) + (this.V0.x * this.V1.y)) + (this.V2.x * this.V0.y)) - (this.V1.x * this.V0.y)) - (this.V2.x * this.V1.y)) - (this.V0.x * this.V2.y));
}
public bool Contains(ref Vector2 point)
{
bool flag = (((point.x - this.V1.x) * (this.V0.y - this.V1.y)) - ((point.y - this.V1.y) * (this.V0.x - this.V1.x))) < 0f;
bool flag2 = (((point.x - this.V2.x) * (this.V1.y - this.V2.y)) - ((point.y - this.V2.y) * (this.V1.x - this.V2.x))) < 0f;
if (flag != flag2)
{
return false;
}
bool flag3 = (((point.x - this.V0.x) * (this.V2.y - this.V0.y)) - ((point.y - this.V0.y) * (this.V2.x - this.V0.x))) < 0f;
return (flag2 == flag3);
}
/// <summary>
/// 当已经知道 三个顶点的顺序是逆时针方向的时候使用
/// </summary>
/// <param name="point"></param>
/// <returns></returns>
public bool ContainsCCW(ref Vector2 point)
{
if ((((point.x - this.V0.x) * (this.V1.y - this.V0.y)) - ((point.y - this.V0.y) * (this.V1.x - this.V0.x))) > 0f)
{
return false;
}
if ((((point.x - this.V1.x) * (this.V2.y - this.V1.y)) - ((point.y - this.V1.y) * (this.V2.x - this.V1.x))) > 0f)
{
return false;
}
if ((((point.x - this.V2.x) * (this.V0.y - this.V2.y)) - ((point.y - this.V2.y) * (this.V0.x - this.V2.x))) > 0f)
{
return false;
}
return true;
}
/// <summary>
/// 当已经知道 三个顶点的顺序是顺时针方向的时候使用
/// </summary>
/// <param name="point"></param>
/// <returns></returns>
public bool ContainsCW(ref Vector2 point)
{
if ((((point.x - this.V0.x) * (this.V1.y - this.V0.y)) - ((point.y - this.V0.y) * (this.V1.x - this.V0.x))) < 0f)
{
return false;
}
if ((((point.x - this.V1.x) * (this.V2.y - this.V1.y)) - ((point.y - this.V1.y) * (this.V2.x - this.V1.x))) < 0f)
{
return false;
}
if ((((point.x - this.V2.x) * (this.V0.y - this.V2.y)) - ((point.y - this.V2.y) * (this.V0.x - this.V2.x))) < 0f)
{
return false;
}
return true;
}
}
5、 凸多边形内
public class Test_ContPoint2ConvexPolygon2 : MonoBehaviour {
public Transform Point;
public Transform[] ConvexPolygon;
private const float _pointRadius = .11f;
private void OnDrawGizmos()
{
Vector2 point = Point.position;
Polygon2 convexPolygon = Polygon2.CreatePolygon2(ConvexPolygon);
Orientations orientation;
// 判断是凸状的不?
bool convex = convexPolygon.IsConvex(out orientation);
if (convex)
{
bool cont;
if (orientation == Orientations.CCW)
{
cont = convexPolygon.ContainsConvexCCW(ref point);
//cont = convexPolygon.ContainsConvexQuadCCW(point); // 如果你知道 方向(顶点顺序方向),就用这个
}
else // CW
{
cont = convexPolygon.ContainsConvexCW(ref point);
//cont = convexPolygon.ContainsConvexQuadCW(point);
}
FiguresColor();
DrawPolygon(convexPolygon);
if (cont) ResultsColor();
DrawPoint(point);
LogInfo("Orientation: " + orientation + " Contained: " + cont);
}
else
{
FiguresColor();
DrawPolygon(convexPolygon);
DrawPoint(point);
Debug.LogError("polygon is non-convex");
}
}
protected void DrawPolygon(Polygon2 polygon)
{
for (int i0 = 0, i1 = polygon.VertexCount - 1; i0 < polygon.VertexCount; i1 = i0, ++i0)
{
Gizmos.DrawLine(polygon[i0], polygon[i1]);
}
}
protected void DrawPoint(Vector2 position)
{
Gizmos.DrawSphere(position, _pointRadius);
}
protected void ResultsColor()
{
Gizmos.color = Color.blue;
}
protected void FiguresColor()
{
Gizmos.color = Color.gray;
}
protected void LogInfo(object value)
{
Debug.Log(value);
}
}
public struct Edge2
{
public Vector2 Point0;
public Vector2 Point1;
public Vector2 Direction;
public Vector2 Normal;
public float Length;
}
public static class Vector3ex
{
public static Vector2 ToVector2XY(this Vector3 vector)
{
return new Vector2(vector.x, vector.y);
}
}
public struct Polygon2 {
private Edge2[] _edges;
private Vector2[] _vertices;
public Polygon2(int vertexCount)
{
this._vertices = new Vector2[vertexCount];
this._edges = new Edge2[vertexCount];
}
public Vector2 this[int vertexIndex]
{
get
{
return this._vertices[vertexIndex];
}
set
{
this._vertices[vertexIndex] = value;
}
}
public int VertexCount
{
get
{
return this._vertices.Length;
}
}
public static Polygon2 CreatePolygon2(Transform[] polygon)
{
Polygon2 result = new Polygon2(polygon.Length);
for (int i = 0; i < polygon.Length; ++i)
{
result[i] = polygon[i].position.ToVector2XY();
}
result.UpdateEdges();
return result;
}
public void UpdateEdges()
{
int length = this._vertices.Length;
int index = length - 1;
for (int i = 0; i < length; i++)
{
Vector2 vector = (this._edges[index].Point1 = this._vertices[i]) - (this._edges[index].Point0 = this._vertices[index]);
this._edges[index].Length = Vector2ex.Normalize(ref vector, 1E-05f);
this._edges[index].Direction = vector;
this._edges[index].Normal = vector.Perp();
index = i;
}
}
/// <summary>
/// 判断当前是不是 凸 状的
/// </summary>
/// <param name="orientation"></param>
/// <param name="threshold"></param>
/// <returns></returns>
public bool IsConvex(out Orientations orientation, float threshold = 1E-05f)
{
orientation = Orientations.None;
int length = this._edges.Length;
int num2 = 0;
int index = length - 1;
for (int i = 0; i < length; i++)
{
Vector2 vector = -this._edges[index].Direction;
Vector2 direction = this._edges[i].Direction;
float num5 = vector.DotPerp(ref direction);
int num6 = ((num5 < -threshold) || (num5 > threshold)) ? ((num5 > 0f) ? 1 : -1) : 0;
if (num6 != 0)
{
if (num2 != 0)
{
if (((num2 > 0) && (num6 < 0)) || ((num2 < 0) && (num6 > 0)))
{
return false;
}
}
else
{
num2 += num6;
}
}
index = i;
}
orientation = (num2 == 0) ? Orientations.None : ((num2 > 0) ? Orientations.CW : Orientations.CCW);
return (orientation != Orientations.None);
}
public bool ContainsConvexCCW(ref Vector2 point)
{
return this.SubContainsPointCCW(ref point, 0, 0);
}
public bool ContainsConvexCW(ref Vector2 point)
{
return this.SubContainsPointCW(ref point, 0, 0);
}
private bool SubContainsPointCCW(ref Vector2 p, int i0, int i1)
{
float num2;
float num3;
float num4;
float num5;
int num7;
int length = this._vertices.Length;
int num6 = i1 - i0;
if ((num6 == 1) || ((num6 < 0) && ((num6 + length) == 1)))
{
num2 = this._vertices[i1].y - this._vertices[i0].y;
num3 = this._vertices[i0].x - this._vertices[i1].x;
num4 = p.x - this._vertices[i0].x;
num5 = p.y - this._vertices[i0].y;
return (((num2 * num4) + (num3 * num5)) <= 0f);
}
if (i0 < i1)
{
num7 = (i0 + i1) >> 1;
}
else
{
num7 = ((i0 + i1) + length) >> 1;
if (num7 >= length)
{
num7 -= length;
}
}
num2 = this._vertices[num7].y - this._vertices[i0].y;
num3 = this._vertices[i0].x - this._vertices[num7].x;
num4 = p.x - this._vertices[i0].x;
num5 = p.y - this._vertices[i0].y;
if (((num2 * num4) + (num3 * num5)) > 0f)
{
return this.SubContainsPointCCW(ref p, i0, num7);
}
return this.SubContainsPointCCW(ref p, num7, i1);
}
private bool SubContainsPointCW(ref Vector2 p, int i0, int i1)
{
float num2;
float num3;
float num4;
float num5;
int num7;
int length = this._vertices.Length;
int num6 = i1 - i0;
if ((num6 == 1) || ((num6 < 0) && ((num6 + length) == 1)))
{
num2 = this._vertices[i1].y - this._vertices[i0].y;
num3 = this._vertices[i0].x - this._vertices[i1].x;
num4 = p.x - this._vertices[i0].x;
num5 = p.y - this._vertices[i0].y;
return (((num2 * num4) + (num3 * num5)) >= 0f);
}
if (i0 < i1)
{
num7 = (i0 + i1) >> 1;
}
else
{
num7 = ((i0 + i1) + length) >> 1;
if (num7 >= length)
{
num7 -= length;
}
}
num2 = this._vertices[num7].y - this._vertices[i0].y;
num3 = this._vertices[i0].x - this._vertices[num7].x;
num4 = p.x - this._vertices[i0].x;
num5 = p.y - this._vertices[i0].y;
if (((num2 * num4) + (num3 * num5)) < 0f)
{
return this.SubContainsPointCW(ref p, i0, num7);
}
return this.SubContainsPointCW(ref p, num7, i1);
}
}
public static class Vector2ex
{
public static float Dot(this Vector2 vector, ref Vector2 value)
{
return ((vector.x * value.x) + (vector.y * value.y));
}
public static float Normalize(ref Vector2 vector, float epsilon = 1E-05f)
{
float num = Mathf.Sqrt((vector.x * vector.x) + (vector.y * vector.y));
if (num >= epsilon)
{
float num2 = 1f / num;
vector.x *= num2;
vector.y *= num2;
return num;
}
vector.x = 0f;
vector.y = 0f;
return 0f;
}
public static float DotPerp(this Vector2 vector, ref Vector2 value)
{
return ((vector.x * value.y) - (vector.y * value.x));
}
public static Vector2 Perp(this Vector2 vector)
{
return new Vector2(vector.y, -vector.x);
}
}
6、 直接判断是否在多边形内。 凹多边形内 (其实不管是凹还是凸了)
public struct Edge2
{
public Vector2 Point0;
public Vector2 Point1;
public Vector2 Direction;
public Vector2 Normal;
public float Length;
}
public static class Vector3ex
{
public static Vector2 ToVector2XY(this Vector3 vector)
{
return new Vector2(vector.x, vector.y);
}
}
public struct Polygon2 {
private Edge2[] _edges;
private Vector2[] _vertices;
public Polygon2(int vertexCount)
{
this._vertices = new Vector2[vertexCount];
this._edges = new Edge2[vertexCount];
}
public Vector2 this[int vertexIndex]
{
get
{
return this._vertices[vertexIndex];
}
set
{
this._vertices[vertexIndex] = value;
}
}
public int VertexCount
{
get
{
return this._vertices.Length;
}
}
public static Polygon2 CreatePolygon2(Transform[] polygon)
{
Polygon2 result = new Polygon2(polygon.Length);
for (int i = 0; i < polygon.Length; ++i)
{
result[i] = polygon[i].position.ToVector2XY();
}
result.UpdateEdges();
return result;
}
public void UpdateEdges()
{
int length = this._vertices.Length;
int index = length - 1;
for (int i = 0; i < length; i++)
{
Vector2 vector = (this._edges[index].Point1 = this._vertices[i]) - (this._edges[index].Point0 = this._vertices[index]);
this._edges[index].Length = Vector2ex.Normalize(ref vector, 1E-05f);
this._edges[index].Direction = vector;
this._edges[index].Normal = vector.Perp();
index = i;
}
}
public bool ContainsSimple(ref Vector2 point)
{
bool flag = false;
int length = this._vertices.Length;
int index = 0;
int num3 = length - 1;
while (index < length)
{
float num4;
float num5;
Vector2 vector = this._vertices[index];
Vector2 vector2 = this._vertices[num3];
if (point.y < vector2.y)
{
if (vector.y <= point.y)
{
num5 = (point.y - vector.y) * (vector2.x - vector.x);
num4 = (point.x - vector.x) * (vector2.y - vector.y);
if (num5 > num4)
{
flag = !flag;
}
}
}
else if (point.y < vector.y)
{
num5 = (point.y - vector.y) * (vector2.x - vector.x);
num4 = (point.x - vector.x) * (vector2.y - vector.y);
if (num5 < num4)
{
flag = !flag;
}
}
num3 = index;
index++;
}
return flag;
}
}
[ExecuteInEditMode]
public class Test_ContPoint2Polygon2 : MonoBehaviour
{
public Transform Point;
public Transform[] Polygon;
private const float _pointRadius = .11f;
private void OnDrawGizmos()
{
Vector2 point = Point.position;
Polygon2 polygon = Polygon2.CreatePolygon2(Polygon);
bool cont = polygon.ContainsSimple(ref point);
FiguresColor();
DrawPolygon(polygon);
if (cont) ResultsColor();
DrawPoint(point);
LogInfo(cont);
}
protected void DrawPolygon(Polygon2 polygon)
{
for (int i0 = 0, i1 = polygon.VertexCount - 1; i0 < polygon.VertexCount; i1 = i0, ++i0)
{
Gizmos.DrawLine(polygon[i0], polygon[i1]);
}
}
protected void DrawPoint(Vector2 position)
{
Gizmos.DrawSphere(position, _pointRadius);
}
protected void ResultsColor()
{
Gizmos.color = Color.blue;
}
protected void FiguresColor()
{
Gizmos.color = Color.gray;
}
protected void LogInfo(object value)
{
Debug.Log(value);
}
}
public static class Vector2ex
{
public static float Normalize(ref Vector2 vector, float epsilon = 1E-05f)
{
float num = Mathf.Sqrt((vector.x * vector.x) + (vector.y * vector.y));
if (num >= epsilon)
{
float num2 = 1f / num;
vector.x *= num2;
vector.y *= num2;
return num;
}
vector.x = 0f;
vector.y = 0f;
return 0f;
}
public static Vector2 Perp(this Vector2 vector)
{
return new Vector2(vector.y, -vector.x);
}
}