mirror of
https://github.com/snowykami/mbcp.git
synced 2024-11-22 06:07:37 +08:00
⚡ add some mathematical method for object Segment3
This commit is contained in:
parent
b4d5da5fc3
commit
edc6a5ddaf
@ -8,10 +8,10 @@ Copyright (C) 2020-2024 LiteyukiStudio. All Rights Reserved
|
||||
@File : line.py
|
||||
@Software: PyCharm
|
||||
"""
|
||||
from typing import overload, TYPE_CHECKING
|
||||
from typing import TYPE_CHECKING
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from .point import Point3
|
||||
from .point import Point3 # type: ignore
|
||||
|
||||
|
||||
class Line3:
|
||||
@ -49,8 +49,6 @@ class Line3:
|
||||
:param line:
|
||||
:return:
|
||||
"""
|
||||
normal1 = (self.b, -self.a, 0)
|
||||
normal2 = (-line.b, line.a, 0)
|
||||
|
||||
if self.is_parallel(line):
|
||||
raise ValueError("Lines are parallel and do not intersect.")
|
||||
|
@ -1,7 +1,7 @@
|
||||
from typing import overload, TYPE_CHECKING
|
||||
from typing import TYPE_CHECKING, overload
|
||||
|
||||
if TYPE_CHECKING: # type: ignore
|
||||
from .vector import Vector3
|
||||
if TYPE_CHECKING:
|
||||
from .vector import Vector3 # type: ignore
|
||||
|
||||
|
||||
class Point3:
|
||||
@ -19,5 +19,37 @@ class Point3:
|
||||
def __str__(self):
|
||||
return f"Point3({self.x}, {self.y}, {self.z})"
|
||||
|
||||
@overload
|
||||
def __add__(self, other: "Vector3") -> "Point3":
|
||||
...
|
||||
|
||||
@overload
|
||||
def __add__(self, other: "Point3") -> "Point3":
|
||||
...
|
||||
|
||||
def __add__(self, other):
|
||||
"""
|
||||
P + V -> P
|
||||
P + P -> P
|
||||
:param other:
|
||||
:return:
|
||||
"""
|
||||
return Point3(self.x + other.x, self.y + other.y, self.z + other.z)
|
||||
|
||||
def __sub__(self, other: "Point3") -> "Vector3":
|
||||
"""
|
||||
P - P -> V
|
||||
|
||||
P - V -> P 已在 :class:`Vector3` 中实现
|
||||
:param other:
|
||||
:return:
|
||||
"""
|
||||
return Vector3(self.x - other.x, self.y - other.y, self.z - other.z)
|
||||
|
||||
def __truediv__(self, other: float) -> "Point3":
|
||||
"""
|
||||
P / n -> P
|
||||
:param other:
|
||||
:return:
|
||||
"""
|
||||
return Point3(self.x / other, self.y / other, self.z / other)
|
||||
|
@ -0,0 +1,2 @@
|
||||
# py.typed
|
||||
partial
|
90
mbcp/mp_math/segment.py
Normal file
90
mbcp/mp_math/segment.py
Normal file
@ -0,0 +1,90 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
"""
|
||||
Copyright (C) 2020-2024 LiteyukiStudio. All Rights Reserved
|
||||
|
||||
@Time : 2024/8/7 上午12:42
|
||||
@Author : snowykami
|
||||
@Email : snowykami@outlook.com
|
||||
@File : segment.py
|
||||
@Software: PyCharm
|
||||
"""
|
||||
|
||||
from typing import TYPE_CHECKING
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from .point import Point3 # type: ignore
|
||||
from .vector import Vector3 # type: ignore
|
||||
|
||||
|
||||
class Segment3:
|
||||
def __init__(self, start: "Point3", end: "Point3"):
|
||||
"""
|
||||
三维空间中的线段。
|
||||
:param start:
|
||||
:param end:
|
||||
"""
|
||||
self._start = start
|
||||
self._end = end
|
||||
|
||||
"""方向向量"""
|
||||
self._direction = self._end - self._start
|
||||
"""长度"""
|
||||
self._length = self._direction.length
|
||||
"""中心点"""
|
||||
self._midpoint = (self._start + self._end) / 2
|
||||
|
||||
def __str__(self):
|
||||
return f"Segment3({self._start}, {self._end})"
|
||||
|
||||
def _unset_properties(self):
|
||||
self._length = None
|
||||
self._direction = None
|
||||
self._midpoint = None
|
||||
|
||||
@property
|
||||
def start(self) -> "Point3":
|
||||
return self._start
|
||||
|
||||
@start.setter
|
||||
def start(self, value: "Point3"):
|
||||
self._start = value
|
||||
self._unset_properties()
|
||||
|
||||
@property
|
||||
def end(self) -> "Point3":
|
||||
return self._end
|
||||
|
||||
@end.setter
|
||||
def end(self, value: "Point3"):
|
||||
self._end = value
|
||||
self._unset_properties()
|
||||
|
||||
@property
|
||||
def length(self) -> float:
|
||||
"""
|
||||
线段的长度。
|
||||
:return:
|
||||
"""
|
||||
if self._length is None:
|
||||
self._length = (self._end - self._start).length
|
||||
return self._length
|
||||
|
||||
@property
|
||||
def direction(self) -> "Vector3":
|
||||
"""
|
||||
线段的方向向量。
|
||||
:return:
|
||||
"""
|
||||
if self._direction is None:
|
||||
self._direction = self._end - self._start
|
||||
return self._direction
|
||||
|
||||
@property
|
||||
def midpoint(self) -> "Point3":
|
||||
"""
|
||||
线段的中点。
|
||||
:return:
|
||||
"""
|
||||
if self._midpoint is None:
|
||||
self._midpoint = (self._start + self._end) / 2
|
||||
return self._midpoint
|
@ -1,7 +1,7 @@
|
||||
from typing import overload, TYPE_CHECKING
|
||||
|
||||
if TYPE_CHECKING: # type: ignore
|
||||
from .point import Point3
|
||||
if TYPE_CHECKING:
|
||||
from .point import Point3 # type: ignore
|
||||
|
||||
|
||||
class Vector3:
|
||||
@ -12,12 +12,65 @@ class Vector3:
|
||||
:param y:
|
||||
:param z:
|
||||
"""
|
||||
self.x = x
|
||||
self.y = y
|
||||
self.z = z
|
||||
self._x = x
|
||||
self._y = y
|
||||
self._z = z
|
||||
self._length = (x ** 2 + y ** 2 + z ** 2) ** 0.5
|
||||
self._normalized = self / self._length
|
||||
|
||||
def __str__(self):
|
||||
return f"Vector3({self.x}, {self.y}, {self.z})"
|
||||
return f"Vector3({self._x}, {self._y}, {self._z})"
|
||||
|
||||
def _unset_properties(self):
|
||||
self._length = None
|
||||
self._normalized = None
|
||||
|
||||
@property
|
||||
def x(self):
|
||||
return self._x
|
||||
|
||||
@x.setter
|
||||
def x(self, value):
|
||||
self._x = value
|
||||
self._unset_properties()
|
||||
|
||||
@property
|
||||
def y(self):
|
||||
return self._y
|
||||
|
||||
@y.setter
|
||||
def y(self, value):
|
||||
self._y = value
|
||||
self._unset_properties()
|
||||
|
||||
@property
|
||||
def z(self):
|
||||
return self._z
|
||||
|
||||
@z.setter
|
||||
def z(self, value):
|
||||
self._z = value
|
||||
self._unset_properties()
|
||||
|
||||
@property
|
||||
def length(self) -> float:
|
||||
"""
|
||||
向量的模。
|
||||
:return:
|
||||
"""
|
||||
if self._length is None:
|
||||
self._length = (self._x ** 2 + self._y ** 2 + self._z ** 2) ** 0.5
|
||||
return self._length
|
||||
|
||||
@property
|
||||
def normalized(self) -> 'Vector3':
|
||||
"""
|
||||
返回该向量的单位向量。
|
||||
:return:
|
||||
"""
|
||||
if self._normalized is None:
|
||||
self._normalized = self / self.length
|
||||
return self._normalized
|
||||
|
||||
@overload
|
||||
def __add__(self, other: 'Vector3') -> 'Vector3':
|
||||
@ -29,14 +82,14 @@ class Vector3:
|
||||
|
||||
def __add__(self, other):
|
||||
if isinstance(other, Vector3):
|
||||
return Vector3(self.x + other.x, self.y + other.y, self.z + other.z)
|
||||
return Vector3(self._x + other._x, self._y + other._y, self._z + other._z)
|
||||
elif isinstance(other, Point3):
|
||||
return Point3(self.x + other.x, self.y + other.y, self.z + other.z)
|
||||
return Point3(self._x + other.x, self._y + other.y, self._z + other.z)
|
||||
else:
|
||||
raise TypeError(f"unsupported operand type(s) for +: 'Vector3' and '{type(other)}'")
|
||||
|
||||
def __radd__(self, other: 'Point3') -> 'Point3':
|
||||
return Point3(self.x + other.x, self.y + other.y, self.z + other.z)
|
||||
return Point3(self._x + other.x, self._y + other.y, self._z + other.z)
|
||||
|
||||
@overload
|
||||
def __sub__(self, other: 'Vector3') -> 'Vector3':
|
||||
@ -54,9 +107,9 @@ class Vector3:
|
||||
:return:
|
||||
"""
|
||||
if isinstance(other, Vector3):
|
||||
return Vector3(self.x - other.x, self.y - other.y, self.z - other.z)
|
||||
return Vector3(self._x - other._x, self._y - other._y, self._z - other._z)
|
||||
elif isinstance(other, Point3):
|
||||
return Point3(self.x - other.x, self.y - other.y, self.z - other.z)
|
||||
return Point3(self._x - other.x, self._y - other.y, self._z - other.z)
|
||||
else:
|
||||
raise TypeError(f"unsupported operand type(s) for -: 'Vector3' and '{type(other)}'")
|
||||
|
||||
@ -68,6 +121,48 @@ class Vector3:
|
||||
"""
|
||||
|
||||
if isinstance(other, Point3):
|
||||
return Point3(other.x - self.x, other.y - self.y, other.z - self.z)
|
||||
return Point3(other.x - self._x, other.y - self._y, other.z - self._z)
|
||||
else:
|
||||
raise TypeError(f"unsupported operand type(s) for -: '{type(other)}' and 'Vector3'")
|
||||
|
||||
@overload
|
||||
def __mul__(self, other: float) -> 'Vector3':
|
||||
...
|
||||
|
||||
@overload
|
||||
def __mul__(self, other: 'Vector3') -> float:
|
||||
...
|
||||
|
||||
def __mul__(self, other):
|
||||
"""
|
||||
乘法。包括点乘和数乘。
|
||||
:param other:
|
||||
:return:
|
||||
"""
|
||||
if isinstance(other, (int, float)):
|
||||
return Vector3(self._x * other, self._y * other, self._z * other)
|
||||
elif isinstance(other, Vector3):
|
||||
return self._x * other._x + self._y * other._y + self._z * other._z
|
||||
else:
|
||||
raise TypeError(f"unsupported operand type(s) for *: 'Vector3' and '{type(other)}'")
|
||||
|
||||
def __rmul__(self, other: float) -> 'Vector3':
|
||||
"""
|
||||
右乘。
|
||||
:param other:
|
||||
:return:
|
||||
"""
|
||||
return Vector3(self._x * other, self._y * other, self._z * other)
|
||||
|
||||
def __matmul__(self, other: 'Vector3') -> 'Vector3':
|
||||
"""
|
||||
叉乘。
|
||||
:param other: 另一个向量
|
||||
:return: 叉乘结果向量
|
||||
"""
|
||||
return Vector3(self._y * other._z - self._z * other._y,
|
||||
self._z * other._x - self._x * other._z,
|
||||
self._x * other._y - self._y * other._x)
|
||||
|
||||
def __truediv__(self, other: float) -> 'Vector3':
|
||||
return Vector3(self._x / other, self._y / other, self._z / other)
|
||||
|
2
mbcp/py.typed
Normal file
2
mbcp/py.typed
Normal file
@ -0,0 +1,2 @@
|
||||
# py.typed
|
||||
partial
|
@ -8,15 +8,15 @@ Copyright (C) 2020-2024 LiteyukiStudio. All Rights Reserved
|
||||
@File : test_vector.py
|
||||
@Software: PyCharm
|
||||
"""
|
||||
from mcpe.mp_math.vector import Vector3
|
||||
from mcpe.mp_math.point import Point3
|
||||
from mbcp.mp_math.vector import Vector3
|
||||
from mbcp.mp_math.point import Point3
|
||||
|
||||
|
||||
def test_v():
|
||||
v1 = Vector3(1, 2, 3)
|
||||
v2 = Vector3(4, 5, 6)
|
||||
v3 = v1 + v2
|
||||
assert v3.x == 5
|
||||
assert v3.y == 7
|
||||
assert v3.z == 9
|
||||
assert v3._x == 5
|
||||
assert v3._y == 7
|
||||
assert v3._z == 9
|
||||
print("test_v 1111passed")
|
||||
|
Loading…
Reference in New Issue
Block a user