using UnityEngine;
using System.Collections.Generic;
using System.Linq;
namespace UnityEngine.ProBuilder
{
///
/// Internal bounds class.
///
sealed class Bounds2D
{
public Vector2 center = Vector2.zero;
[SerializeField] Vector2 m_Size = Vector2.zero;
[SerializeField] Vector2 m_Extents = Vector2.zero;
public Vector2 size
{
get { return m_Size; }
set
{
m_Size = value;
m_Extents.x = m_Size.x * .5f;
m_Extents.y = m_Size.y * .5f;
}
}
public Vector2 extents
{
get { return m_Extents; }
}
///
/// Returns an array of Vector2[] points for each corner, in the order right to left, top to bottom.
///
public Vector2[] corners
{
get
{
return new Vector2[] {
new Vector2(center.x - extents.x, center.y + extents.y),
new Vector2(center.x + extents.x, center.y + extents.y),
new Vector2(center.x - extents.x, center.y - extents.y),
new Vector2(center.x + extents.x, center.y - extents.y)
};
}
}
public Bounds2D()
{}
public Bounds2D(Vector2 center, Vector2 size)
{
this.center = center;
this.size = size;
}
///
/// Create bounds from a set of 2d points.
///
///
public Bounds2D(IList points)
{
SetWithPoints(points);
}
///
/// Create bounds from a set of 2d points.
///
///
///
public Bounds2D(IList points, IList indexes)
{
SetWithPoints(points, indexes);
}
///
/// Create bounds from a set of 3d points cast to 2d.
///
///
///
internal Bounds2D(Vector3[] points, Edge[] edges)
{
float xMin = 0f,
xMax = 0f,
yMin = 0f,
yMax = 0f;
if (points.Length > 0 && edges.Length > 0)
{
xMin = points[edges[0].a].x;
yMin = points[edges[0].a].y;
xMax = xMin;
yMax = yMin;
for (int i = 0; i < edges.Length; i++)
{
xMin = Mathf.Min(xMin, points[edges[i].a].x);
xMin = Mathf.Min(xMin, points[edges[i].b].x);
yMin = Mathf.Min(yMin, points[edges[i].a].y);
yMin = Mathf.Min(yMin, points[edges[i].b].y);
xMax = Mathf.Max(xMax, points[edges[i].a].x);
xMax = Mathf.Max(xMax, points[edges[i].b].x);
yMax = Mathf.Max(yMax, points[edges[i].a].y);
yMax = Mathf.Max(yMax, points[edges[i].b].y);
}
}
this.center = new Vector2((xMin + xMax) / 2f, (yMin + yMax) / 2f);
this.size = new Vector3(xMax - xMin, yMax - yMin);
}
public Bounds2D(Vector2[] points, int length)
{
float xMin = 0f,
xMax = 0f,
yMin = 0f,
yMax = 0f;
if (points.Length > 0)
{
xMin = points[0].x;
yMin = points[0].y;
xMax = xMin;
yMax = yMin;
for (int i = 1; i < length; i++)
{
xMin = Mathf.Min(xMin, points[i].x);
yMin = Mathf.Min(yMin, points[i].y);
xMax = Mathf.Max(xMax, points[i].x);
yMax = Mathf.Max(yMax, points[i].y);
}
}
this.center = new Vector2((xMin + xMax) / 2f, (yMin + yMax) / 2f);
this.size = new Vector3(xMax - xMin, yMax - yMin);
}
///
/// Returns true if the point is contained within the bounds. False otherwise.
///
///
///
public bool ContainsPoint(Vector2 point)
{
return !(point.x > center.x + extents.x ||
point.x < center.x - extents.x ||
point.y > center.y + extents.y ||
point.y < center.y - extents.y);
}
///
/// Returns true if any part of the line segment is contained within this bounding box.
///
///
///
///
public bool IntersectsLineSegment(Vector2 lineStart, Vector2 lineEnd)
{
if (ContainsPoint(lineStart) || ContainsPoint(lineEnd))
{
return true;
}
else
{
Vector2[] aabb = corners;
return (Math.GetLineSegmentIntersect(aabb[0], aabb[1], lineStart, lineEnd) ||
Math.GetLineSegmentIntersect(aabb[1], aabb[3], lineStart, lineEnd) ||
Math.GetLineSegmentIntersect(aabb[3], aabb[2], lineStart, lineEnd) ||
Math.GetLineSegmentIntersect(aabb[2], aabb[0], lineStart, lineEnd));
}
}
///
/// Returns true if bounds overlap.
///
///
///
public bool Intersects(Bounds2D bounds)
{
Vector2 dist = this.center - bounds.center;
Vector2 size = this.size + bounds.size;
return Mathf.Abs(dist.x) * 2f < size.x &&
Mathf.Abs(dist.y) * 2f < size.y;
}
///
/// Check if this rect is intersected by another.
///
///
/// True if bounds overlaps rect.
public bool Intersects(Rect rect)
{
Vector2 dist = this.center - rect.center;
Vector2 size = this.size + rect.size;
return Mathf.Abs(dist.x) * 2f < size.x &&
Mathf.Abs(dist.y) * 2f < size.y;
}
///
/// Set this bounds center and size to encapsulate points.
///
///
public void SetWithPoints(IList points)
{
float xMin = 0f,
xMax = 0f,
yMin = 0f,
yMax = 0f;
int len = points.Count;
if (len > 0)
{
xMin = points[0].x;
yMin = points[0].y;
xMax = xMin;
yMax = yMin;
for (int i = 1; i < len; i++)
{
float x = points[i].x;
float y = points[i].y;
if (x < xMin) xMin = x;
if (x > xMax) xMax = x;
if (y < yMin) yMin = y;
if (y > yMax) yMax = y;
}
}
center.x = (xMin + xMax) / 2f;
center.y = (yMin + yMax) / 2f;
m_Size.x = xMax - xMin;
m_Size.y = yMax - yMin;
m_Extents.x = m_Size.x * .5f;
m_Extents.y = m_Size.y * .5f;
}
///
/// Set this bounds center and size to encapsulate points.
///
///
///
public void SetWithPoints(IList points, IList indexes)
{
float xMin = 0f,
xMax = 0f,
yMin = 0f,
yMax = 0f;
if (points.Count > 0 && indexes.Count > 0)
{
xMin = points[indexes[0]].x;
yMin = points[indexes[0]].y;
xMax = xMin;
yMax = yMin;
for (int i = 1; i < indexes.Count; i++)
{
float x = points[indexes[i]].x;
float y = points[indexes[i]].y;
if (x < xMin) xMin = x;
if (x > xMax) xMax = x;
if (y < yMin) yMin = y;
if (y > yMax) yMax = y;
}
}
center.x = (xMin + xMax) / 2f;
center.y = (yMin + yMax) / 2f;
m_Size.x = xMax - xMin;
m_Size.y = yMax - yMin;
m_Extents.x = m_Size.x * .5f;
m_Extents.y = m_Size.y * .5f;
}
///
/// Returns the center of the bounding box of points. Optional parameter @length limits the bounds calculations
/// to only the points up to length in array.
///
///
///
///
public static Vector2 Center(IList points)
{
float xMin = 0f,
xMax = 0f,
yMin = 0f,
yMax = 0f;
int size = points.Count;
xMin = points[0].x;
yMin = points[0].y;
xMax = xMin;
yMax = yMin;
for (int i = 1; i < size; i++)
{
float x = points[i].x;
float y = points[i].y;
if (x < xMin) xMin = x;
if (x > xMax) xMax = x;
if (y < yMin) yMin = y;
if (y > yMax) yMax = y;
}
return new Vector2((xMin + xMax) / 2f, (yMin + yMax) / 2f);
}
public static Vector2 Center(IList points, IList indexes)
{
float xMin = 0f,
xMax = 0f,
yMin = 0f,
yMax = 0f;
int size = indexes.Count;
xMin = points[indexes[0]].x;
yMin = points[indexes[0]].y;
xMax = xMin;
yMax = yMin;
for (int i = 1; i < size; i++)
{
float x = points[indexes[i]].x;
float y = points[indexes[i]].y;
if (x < xMin) xMin = x;
if (x > xMax) xMax = x;
if (y < yMin) yMin = y;
if (y > yMax) yMax = y;
}
return new Vector2((xMin + xMax) / 2f, (yMin + yMax) / 2f);
}
public static Vector2 Size(IList points, IList indexes)
{
float xMin = 0f,
xMax = 0f,
yMin = 0f,
yMax = 0f;
int size = indexes.Count;
xMin = points[indexes[0]].x;
yMin = points[indexes[0]].y;
xMax = xMin;
yMax = yMin;
for (int i = 1; i < size; i++)
{
float x = points[indexes[i]].x;
float y = points[indexes[i]].y;
if (x < xMin) xMin = x;
if (x > xMax) xMax = x;
if (y < yMin) yMin = y;
if (y > yMax) yMax = y;
}
return new Vector2(xMax - xMin, yMax - yMin);
}
internal static Vector2 Center(IList points, IEnumerable indexes)
{
float xMin = 0f,
xMax = 0f,
yMin = 0f,
yMax = 0f;
var first = indexes.First();
xMin = points[first].x;
yMin = points[first].y;
xMax = xMin;
yMax = yMin;
foreach(var index in indexes)
{
float x = points[index].x;
float y = points[index].y;
if (x < xMin) xMin = x;
if (x > xMax) xMax = x;
if (y < yMin) yMin = y;
if (y > yMax) yMax = y;
}
return new Vector2((xMin + xMax) / 2f, (yMin + yMax) / 2f);
}
public override string ToString()
{
return "[cen: " + center + " size: " + size + "]";
}
}
}