using System; using System.Collections.Generic; using UnityEngine; namespace ProceduralToolkit { /// /// Representation of a 2D line segment /// [Serializable] public struct Segment2 : IEquatable, IFormattable { public Vector2 a; public Vector2 b; /// /// Returns the normalized direction of the segment /// public Vector2 direction => (b - a).normalized; /// /// Returns the length of the segment /// public float length => (b - a).magnitude; /// /// Returns the center of the segment /// public Vector2 center => GetPoint(0.5f); /// /// Returns the axis-aligned bounding box of the segment /// public Rect aabb { get { Vector2 min = Vector2.Min(a, b); Vector2 max = Vector2.Max(a, b); return Rect.MinMaxRect(min.x, min.y, max.x, max.y); } } public Segment2(Vector2 a, Vector2 b) { this.a = a; this.b = b; } /// /// Access the a or b component using [0] or [1] respectively /// public Vector2 this[int index] { get { switch (index) { case 0: return a; case 1: return b; default: throw new IndexOutOfRangeException("Invalid Segment2 index!"); } } set { switch (index) { case 0: a = value; break; case 1: b = value; break; default: throw new IndexOutOfRangeException("Invalid Segment2 index!"); } } } /// /// Returns a point on the segment at the given normalized position /// /// Normalized position public Vector2 GetPoint(float position) { return Geometry.PointOnSegment2(a, b, position); } /// /// Returns a list of evenly distributed points on the segment /// /// Number of points public List GetPoints(int count) { return Geometry.PointsOnSegment2(a, b, count); } /// /// Linearly interpolates between two segments /// public static Segment2 Lerp(Segment2 a, Segment2 b, float t) { t = Mathf.Clamp01(t); return new Segment2(a.a + (b.a - a.a)*t, a.b + (b.b - a.b)*t); } /// /// Linearly interpolates between two segments without clamping the interpolant /// public static Segment2 LerpUnclamped(Segment2 a, Segment2 b, float t) { return new Segment2(a.a + (b.a - a.a)*t, a.b + (b.b - a.b)*t); } #region Casting operators public static explicit operator Line2(Segment2 segment) { return new Line2(segment.a, (segment.b - segment.a).normalized); } public static explicit operator Ray2D(Segment2 segment) { return new Ray2D(segment.a, (segment.b - segment.a).normalized); } public static explicit operator Segment3(Segment2 segment) { return new Segment3((Vector3) segment.a, (Vector3) segment.b); } #endregion Casting operators public static Segment2 operator +(Segment2 segment, Vector2 vector) { return new Segment2(segment.a + vector, segment.b + vector); } public static Segment2 operator -(Segment2 segment, Vector2 vector) { return new Segment2(segment.a - vector, segment.b - vector); } public static bool operator ==(Segment2 a, Segment2 b) { return a.a == b.a && a.b == b.b; } public static bool operator !=(Segment2 a, Segment2 b) { return !(a == b); } public override int GetHashCode() { return a.GetHashCode() ^ (b.GetHashCode() << 2); } public override bool Equals(object other) { return other is Segment2 && Equals((Segment2) other); } public bool Equals(Segment2 other) { return a.Equals(other.a) && b.Equals(other.b); } public override string ToString() { return string.Format("Segment2(a: {0}, b: {1})", a, b); } public string ToString(string format) { return string.Format("Segment2(a: {0}, b: {1})", a.ToString(format), b.ToString(format)); } public string ToString(string format, IFormatProvider formatProvider) { return string.Format("Segment2(a: {0}, b: {1})", a.ToString(format, formatProvider), b.ToString(format, formatProvider)); } } }