diff options
author | chai <215380520@qq.com> | 2024-06-03 10:15:45 +0800 |
---|---|---|
committer | chai <215380520@qq.com> | 2024-06-03 10:15:45 +0800 |
commit | acea7b2e728787a0d83bbf83c8c1f042d2c32e7e (patch) | |
tree | 0bfec05c1ca2d71be2c337bcd110a0421f19318b /Plugins/MonoGame.Extended/source/MonoGame.Extended/Shapes/Polygon.cs | |
parent | 88febcb02bf127d961c6471d9e846c0e1315f5c3 (diff) |
+ plugins project
Diffstat (limited to 'Plugins/MonoGame.Extended/source/MonoGame.Extended/Shapes/Polygon.cs')
-rw-r--r-- | Plugins/MonoGame.Extended/source/MonoGame.Extended/Shapes/Polygon.cs | 179 |
1 files changed, 179 insertions, 0 deletions
diff --git a/Plugins/MonoGame.Extended/source/MonoGame.Extended/Shapes/Polygon.cs b/Plugins/MonoGame.Extended/source/MonoGame.Extended/Shapes/Polygon.cs new file mode 100644 index 0000000..841ce2b --- /dev/null +++ b/Plugins/MonoGame.Extended/source/MonoGame.Extended/Shapes/Polygon.cs @@ -0,0 +1,179 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using Microsoft.Xna.Framework; + +namespace MonoGame.Extended.Shapes +{ + public class Polygon : IEquatable<Polygon> + { + public Polygon(IEnumerable<Vector2> vertices) + { + _localVertices = vertices.ToArray(); + _transformedVertices = _localVertices; + _offset = Vector2.Zero; + _rotation = 0; + _scale = Vector2.One; + _isDirty = false; + } + + private readonly Vector2[] _localVertices; + private Vector2[] _transformedVertices; + private Vector2 _offset; + private float _rotation; + private Vector2 _scale; + private bool _isDirty; + + public Vector2[] Vertices + { + get + { + if (_isDirty) + { + _transformedVertices = GetTransformedVertices(); + _isDirty = false; + } + + return _transformedVertices; + } + } + + public float Left + { + get { return Vertices.Min(v => v.X); } + } + + public float Right + { + get { return Vertices.Max(v => v.X); } + } + + public float Top + { + get { return Vertices.Min(v => v.Y); } + } + + public float Bottom + { + get { return Vertices.Max(v => v.Y); } + } + + public void Offset(Vector2 amount) + { + _offset += amount; + _isDirty = true; + } + + public void Rotate(float amount) + { + _rotation += amount; + _isDirty = true; + } + + public void Scale(Vector2 amount) + { + _scale += amount; + _isDirty = true; + } + + private Vector2[] GetTransformedVertices() + { + var newVertices = new Vector2[_localVertices.Length]; + var isScaled = _scale != Vector2.One; + + for (var i = 0; i < _localVertices.Length; i++) + { + var p = _localVertices[i]; + + if (isScaled) + p *= _scale; + + // ReSharper disable once CompareOfFloatsByEqualityOperator + if (_rotation != 0) + { + var cos = (float) Math.Cos(_rotation); + var sin = (float) Math.Sin(_rotation); + p = new Vector2(cos*p.X - sin*p.Y, sin*p.X + cos*p.Y); + } + + newVertices[i] = p + _offset; + } + + return newVertices; + } + + public Polygon TransformedCopy(Vector2 offset, float rotation, Vector2 scale) + { + var polygon = new Polygon(_localVertices); + polygon.Offset(offset); + polygon.Rotate(rotation); + polygon.Scale(scale - Vector2.One); + return new Polygon(polygon.Vertices); + } + + public RectangleF BoundingRectangle + { + get + { + var minX = Left; + var minY = Top; + var maxX = Right; + var maxY = Bottom; + return new RectangleF(minX, minY, maxX - minX, maxY - minY); + } + } + + public bool Contains(Vector2 point) + { + return Contains(point.X, point.Y); + } + + public bool Contains(float x, float y) + { + var intersects = 0; + var vertices = Vertices; + + for (var i = 0; i < vertices.Length; i++) + { + var x1 = vertices[i].X; + var y1 = vertices[i].Y; + var x2 = vertices[(i + 1)%vertices.Length].X; + var y2 = vertices[(i + 1)%vertices.Length].Y; + + if ((((y1 <= y) && (y < y2)) || ((y2 <= y) && (y < y1))) && (x < (x2 - x1)/(y2 - y1)*(y - y1) + x1)) + intersects++; + } + + return (intersects & 1) == 1; + } + + public static bool operator ==(Polygon a, Polygon b) + { + return a.Equals(b); + } + + public static bool operator !=(Polygon a, Polygon b) + { + return !(a == b); + } + + public override bool Equals(object obj) + { + if (ReferenceEquals(null, obj)) return false; + return obj is Polygon && Equals((Polygon) obj); + } + + public bool Equals(Polygon other) + { + return Vertices.SequenceEqual(other.Vertices); + } + + public override int GetHashCode() + { + unchecked + { + return Vertices.Aggregate(27, (current, v) => current + 13*current + v.GetHashCode()); + } + } + } +}
\ No newline at end of file |