using System; using UnityEngine; namespace ProceduralToolkit { /// /// Representation of a 3D circle /// [Serializable] public struct Circle3 : IEquatable, IFormattable { public Vector3 center; public Vector3 normal; public float radius; /// /// Returns the perimeter of the circle /// public float perimeter => 2*Mathf.PI*radius; /// /// Returns the area of the circle /// public float area => Mathf.PI*radius*radius; public static Circle3 unitXY => new Circle3(Vector3.zero, Vector3.back, 1); public static Circle3 unitXZ => new Circle3(Vector3.zero, Vector3.up, 1); public static Circle3 unitYZ => new Circle3(Vector3.zero, Vector3.left, 1); public Circle3(float radius) : this(Vector3.zero, Vector3.back, radius) { } public Circle3(Vector3 center, float radius) : this(center, Vector3.back, radius) { } public Circle3(Vector3 center, Vector3 normal, float radius) { this.center = center; this.normal = normal; this.radius = radius; } /// /// Linearly interpolates between two circles /// public static Circle3 Lerp(Circle3 a, Circle3 b, float t) { t = Mathf.Clamp01(t); return new Circle3( center: a.center + (b.center - a.center)*t, normal: Vector3.LerpUnclamped(a.normal, b.normal, t), radius: a.radius + (b.radius - a.radius)*t); } /// /// Linearly interpolates between two circles without clamping the interpolant /// public static Circle3 LerpUnclamped(Circle3 a, Circle3 b, float t) { return new Circle3( center: a.center + (b.center - a.center)*t, normal: Vector3.LerpUnclamped(a.normal, b.normal, t), radius: a.radius + (b.radius - a.radius)*t); } public static explicit operator Sphere(Circle3 circle) { return new Sphere(circle.center, circle.radius); } public static explicit operator Circle2(Circle3 circle) { return new Circle2((Vector2) circle.center, circle.radius); } public static Circle3 operator +(Circle3 circle, Vector3 vector) { return new Circle3(circle.center + vector, circle.normal, circle.radius); } public static Circle3 operator -(Circle3 circle, Vector3 vector) { return new Circle3(circle.center - vector, circle.normal, circle.radius); } public static bool operator ==(Circle3 a, Circle3 b) { return a.center == b.center && a.normal == b.normal && a.radius == b.radius; } public static bool operator !=(Circle3 a, Circle3 b) { return !(a == b); } public override int GetHashCode() { return center.GetHashCode() ^ (normal.GetHashCode() << 2) ^ (radius.GetHashCode() >> 2); } public override bool Equals(object other) { return other is Circle3 && Equals((Circle3) other); } public bool Equals(Circle3 other) { return center.Equals(other.center) && normal.Equals(other.normal) && radius.Equals(other.radius); } public override string ToString() { return string.Format("Circle3(center: {0}, normal: {1}, radius: {2})", center, normal, radius); } public string ToString(string format) { return string.Format("Circle3(center: {0}, normal: {1}, radius: {2})", center.ToString(format), normal.ToString(format), radius.ToString(format)); } public string ToString(string format, IFormatProvider formatProvider) { return string.Format("Circle3(center: {0}, normal: {1}, radius: {2})", center.ToString(format, formatProvider), normal.ToString(format, formatProvider), radius.ToString(format, formatProvider)); } } }