@@ -1,54 +1,69 @@
|
||||
import 'dart:math' as math;
|
||||
|
||||
/// A robust, immutable 2D coordinate.
|
||||
/// A lightweight, immutable 2D Vector/Coordinate system.
|
||||
class Coordinate2D implements Comparable<Coordinate2D> {
|
||||
final double x;
|
||||
final double y;
|
||||
|
||||
const Coordinate2D(this.x, this.y);
|
||||
|
||||
/// Factory for a (0,0) coordinate.
|
||||
static const Coordinate2D zero = Coordinate2D(0.0, 0.0);
|
||||
|
||||
// --- Core Logic ---
|
||||
|
||||
/// Returns the Euclidean distance between this and [other].
|
||||
/// Uses the formula: $$d = \sqrt{(x_2 - x_1)^2 + (y_2 - y_1)^2}$$
|
||||
double distanceTo(Coordinate2D other) {
|
||||
final dx = x - other.x;
|
||||
final dy = y - other.y;
|
||||
return math.sqrt(dx * dx + dy * dy);
|
||||
/// Returns the angle in radians between this coordinate and [other].
|
||||
/// Useful for "Look At" logic or determining steering direction.
|
||||
/// Result is between -pi and pi.
|
||||
double angleTo(Coordinate2D other) {
|
||||
return math.atan2(other.y - y, other.x - x);
|
||||
}
|
||||
|
||||
/// True if both ordinates are finite (not NaN or Infinity).
|
||||
bool get isValid => x.isFinite && y.isFinite;
|
||||
/// Rotates the coordinate around (0,0) by [radians].
|
||||
Coordinate2D rotate(double radians) {
|
||||
final cos = math.cos(radians);
|
||||
final sin = math.sin(radians);
|
||||
return Coordinate2D(
|
||||
(x * cos) - (y * sin),
|
||||
(x * sin) + (y * cos),
|
||||
);
|
||||
}
|
||||
|
||||
/// Linear Interpolation: Slides between this and [target] by [t] (0.0 to 1.0).
|
||||
/// Perfect for smooth camera follows or "lerping" an object to a new spot.
|
||||
Coordinate2D lerp(Coordinate2D target, double t) {
|
||||
return Coordinate2D(
|
||||
x + (target.x - x) * t,
|
||||
y + (target.y - y) * t,
|
||||
);
|
||||
}
|
||||
|
||||
double get magnitude => math.sqrt(x * x + y * y);
|
||||
|
||||
Coordinate2D get normalized {
|
||||
final m = magnitude;
|
||||
if (m == 0) return const Coordinate2D(0, 0);
|
||||
return Coordinate2D(x / m, y / m);
|
||||
}
|
||||
|
||||
double dot(Coordinate2D other) => (x * other.x) + (y * other.y);
|
||||
|
||||
double distanceTo(Coordinate2D other) => (this - other).magnitude;
|
||||
|
||||
Coordinate2D operator +(Coordinate2D other) =>
|
||||
Coordinate2D(x + other.x, y + other.y);
|
||||
Coordinate2D operator -(Coordinate2D other) =>
|
||||
Coordinate2D(x - other.x, y - other.y);
|
||||
Coordinate2D operator *(double factor) =>
|
||||
Coordinate2D(x * factor, y * factor);
|
||||
Coordinate2D operator /(double divisor) =>
|
||||
Coordinate2D(x / divisor, y / divisor);
|
||||
Coordinate2D operator *(double n) => Coordinate2D(x * n, y * n);
|
||||
Coordinate2D operator /(double n) => Coordinate2D(x / n, y / n);
|
||||
|
||||
@override
|
||||
bool operator ==(Object other) =>
|
||||
identical(this, other) ||
|
||||
other is Coordinate2D &&
|
||||
runtimeType == other.runtimeType &&
|
||||
x == other.x &&
|
||||
y == other.y;
|
||||
other is Coordinate2D && x == other.x && y == other.y;
|
||||
|
||||
@override
|
||||
int get hashCode => Object.hash(x, y);
|
||||
|
||||
@override
|
||||
int compareTo(Coordinate2D other) {
|
||||
if (x != other.x) return x.compareTo(other.x);
|
||||
return y.compareTo(other.y);
|
||||
}
|
||||
int compareTo(Coordinate2D other) =>
|
||||
x != other.x ? x.compareTo(other.x) : y.compareTo(other.y);
|
||||
|
||||
@override
|
||||
String toString() => 'Coordinate($x, $y)';
|
||||
String toString() => 'Coordinate2D($x, $y)';
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user