parent
61449b407c
commit
b7c7fba169
@ -1,228 +0,0 @@
|
||||
import pygame
|
||||
import math
|
||||
|
||||
class Vector2D:
|
||||
def __init__(self, x: float = 0, y: float = 0):
|
||||
self._vector = pygame.Vector2(x, y)
|
||||
|
||||
@property
|
||||
def x(self) -> float:
|
||||
return self._vector.x
|
||||
|
||||
@x.setter
|
||||
def x(self, value: float):
|
||||
self._vector.x = value
|
||||
|
||||
@property
|
||||
def y(self) -> float:
|
||||
return self._vector.y
|
||||
|
||||
@y.setter
|
||||
def y(self, value: float):
|
||||
self._vector.y = value
|
||||
|
||||
def __add__(self, other):
|
||||
if isinstance(other, Vector2D):
|
||||
return Vector2D(self.x + other.x, self.y + other.y)
|
||||
else:
|
||||
result = self._vector + other._vector
|
||||
return Vector2D(result.x, result.y)
|
||||
|
||||
def __sub__(self, other):
|
||||
if isinstance(other, Vector2D):
|
||||
return Vector2D(self.x - other.x, self.y - other.y)
|
||||
else:
|
||||
result = self._vector - other._vector
|
||||
return Vector2D(result.x, result.y)
|
||||
|
||||
def __mul__(self, scalar):
|
||||
if isinstance(scalar, Vector2D):
|
||||
return Vector2D(self.x * scalar.x, self.y * scalar.y)
|
||||
else:
|
||||
result = self._vector * scalar
|
||||
return Vector2D(result.x, result.y)
|
||||
|
||||
def __truediv__(self, other):
|
||||
if isinstance(other, Vector2D):
|
||||
return Vector2D(self.x / other.x, self.y / other.y)
|
||||
else:
|
||||
result = self._vector / other
|
||||
return Vector2D(result.x, result.y)
|
||||
|
||||
def length(self):
|
||||
return self._vector.length()
|
||||
|
||||
def normalize(self):
|
||||
result = self._vector.normalize()
|
||||
return Vector2D(result.x, result.y)
|
||||
|
||||
def dot(self, other):
|
||||
if isinstance(other, Vector2D):
|
||||
return self._vector.dot(other._vector)
|
||||
else:
|
||||
return self._vector.dot(other)
|
||||
|
||||
class Transform2D:
|
||||
IDENTITY = None
|
||||
FLIP_X = None
|
||||
FLIP_Y = None
|
||||
|
||||
def __init__(self, position: Vector2D = None, rotation: float = 0.0,
|
||||
scale: Vector2D = None):
|
||||
"""
|
||||
初始化变换矩阵
|
||||
|
||||
Args:
|
||||
position: 位置向量
|
||||
rotation: 旋转角度(弧度)
|
||||
scale: 缩放向量
|
||||
"""
|
||||
if position is None:
|
||||
position = Vector2D(0, 0)
|
||||
if scale is None:
|
||||
scale = Vector2D(1.0, 1.0)
|
||||
|
||||
self._set_transform(position, rotation, scale)
|
||||
|
||||
def _set_transform(self, position: Vector2D, rotation: float, scale: Vector2D):
|
||||
"""
|
||||
根据位置、旋转和缩放设置变换矩阵
|
||||
"""
|
||||
cos = math.cos(rotation)
|
||||
sin = math.sin(rotation)
|
||||
|
||||
# 设置基向量(旋转和缩放的组合)
|
||||
self.x = Vector2D(cos * scale.x, sin * scale.x)
|
||||
self.y = Vector2D(-sin * scale.y, cos * scale.y)
|
||||
|
||||
# 设置原点(平移)
|
||||
self.origin = position
|
||||
|
||||
@property
|
||||
def position(self) -> Vector2D:
|
||||
"""获取位置"""
|
||||
return self.origin
|
||||
|
||||
@position.setter
|
||||
def position(self, value: Vector2D):
|
||||
"""设置位置"""
|
||||
self.origin = value
|
||||
|
||||
@property
|
||||
def scale(self) -> Vector2D:
|
||||
"""获取缩放"""
|
||||
# 计算基向量的长度来得到缩放因子
|
||||
scale_x = math.sqrt(self.x.x * self.x.x + self.x.y * self.x.y)
|
||||
scale_y = math.sqrt(self.y.x * self.y.x + self.y.y * self.y.y)
|
||||
return Vector2D(scale_x, scale_y)
|
||||
|
||||
@scale.setter
|
||||
def scale(self, value: Vector2D):
|
||||
"""设置缩放"""
|
||||
current_scale = self.scale
|
||||
if current_scale.x != 0 and current_scale.y != 0:
|
||||
# 调整基向量以适应新的缩放
|
||||
scale_ratio_x = value.x / current_scale.x
|
||||
scale_ratio_y = value.y / current_scale.y
|
||||
self.x = Vector2D(self.x.x * scale_ratio_x, self.x.y * scale_ratio_x)
|
||||
self.y = Vector2D(self.y.x * scale_ratio_y, self.y.y * scale_ratio_y)
|
||||
|
||||
@property
|
||||
def rotation(self) -> float:
|
||||
"""获取旋转角度"""
|
||||
return math.atan2(self.x.y, self.x.x)
|
||||
|
||||
@rotation.setter
|
||||
def rotation(self, value: float):
|
||||
"""设置旋转角度"""
|
||||
current_scale = self.scale
|
||||
cos = math.cos(value)
|
||||
sin = math.sin(value)
|
||||
|
||||
self.x = Vector2D(cos * current_scale.x, sin * current_scale.x)
|
||||
self.y = Vector2D(-sin * current_scale.y, cos * current_scale.y)
|
||||
|
||||
def transform_point(self, point: Vector2D) -> Vector2D:
|
||||
"""
|
||||
应用变换到点
|
||||
|
||||
Args:
|
||||
point: 要变换的点
|
||||
|
||||
Returns:
|
||||
变换后的点
|
||||
"""
|
||||
# 应用线性变换然后加上平移
|
||||
x = self.x * point.x
|
||||
y = self.y * point.y
|
||||
return self.origin + x + y
|
||||
|
||||
def multiply(self, other: 'Transform2D') -> 'Transform2D':
|
||||
"""
|
||||
将另一个变换应用到当前变换
|
||||
|
||||
Args:
|
||||
other: 要应用的变换
|
||||
|
||||
Returns:
|
||||
新的变换对象
|
||||
"""
|
||||
# 组合两个变换矩阵
|
||||
new_x = Vector2D(
|
||||
self.x.x * other.x.x + self.y.x * other.x.y,
|
||||
self.x.y * other.x.x + self.y.y * other.x.y
|
||||
)
|
||||
new_y = Vector2D(
|
||||
self.x.x * other.y.x + self.y.x * other.y.y,
|
||||
self.x.y * other.y.x + self.y.y * other.y.y
|
||||
)
|
||||
new_origin = self.transform_point(other.origin)
|
||||
|
||||
result = Transform2D()
|
||||
result.x = new_x
|
||||
result.y = new_y
|
||||
result.origin = new_origin
|
||||
return result
|
||||
|
||||
def inverse(self) -> 'Transform2D':
|
||||
"""
|
||||
计算逆变换
|
||||
|
||||
Returns:
|
||||
逆变换
|
||||
"""
|
||||
# 计算2x2矩阵的行列式
|
||||
det = self.x.x * self.y.y - self.x.y * self.y.x
|
||||
|
||||
if abs(det) < 1e-10:
|
||||
raise ValueError("Transform is not invertible")
|
||||
|
||||
inv_det = 1.0 / det
|
||||
|
||||
# 计算逆矩阵的基向量
|
||||
inv_x = Vector2D(
|
||||
self.y.y * inv_det,
|
||||
-self.x.y * inv_det
|
||||
)
|
||||
inv_y = Vector2D(
|
||||
-self.y.x * inv_det,
|
||||
self.x.x * inv_det
|
||||
)
|
||||
|
||||
# 计算逆矩阵的原点
|
||||
origin_dot = self.origin.x * inv_x.x + self.origin.y * inv_x.y
|
||||
origin_dot2 = self.origin.x * inv_y.x + self.origin.y * inv_y.y
|
||||
inv_origin = Vector2D(-origin_dot, -origin_dot2)
|
||||
|
||||
result = Transform2D()
|
||||
result.x = inv_x
|
||||
result.y = inv_y
|
||||
result.origin = inv_origin
|
||||
return result
|
||||
|
||||
|
||||
# 初始化预定义常量
|
||||
Transform2D.IDENTITY = Transform2D()
|
||||
Transform2D.FLIP_X = Transform2D(scale=Vector2D(-1, 1))
|
||||
Transform2D.FLIP_Y = Transform2D(scale=Vector2D(1, -1))
|
||||
|
||||
Loading…
Reference in new issue