mirror of
https://github.com/snowykami/mbcp.git
synced 2024-11-22 14:17:38 +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
|
@File : line.py
|
||||||
@Software: PyCharm
|
@Software: PyCharm
|
||||||
"""
|
"""
|
||||||
from typing import overload, TYPE_CHECKING
|
from typing import TYPE_CHECKING
|
||||||
|
|
||||||
if TYPE_CHECKING:
|
if TYPE_CHECKING:
|
||||||
from .point import Point3
|
from .point import Point3 # type: ignore
|
||||||
|
|
||||||
|
|
||||||
class Line3:
|
class Line3:
|
||||||
@ -49,8 +49,6 @@ class Line3:
|
|||||||
:param line:
|
:param line:
|
||||||
:return:
|
:return:
|
||||||
"""
|
"""
|
||||||
normal1 = (self.b, -self.a, 0)
|
|
||||||
normal2 = (-line.b, line.a, 0)
|
|
||||||
|
|
||||||
if self.is_parallel(line):
|
if self.is_parallel(line):
|
||||||
raise ValueError("Lines are parallel and do not intersect.")
|
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
|
if TYPE_CHECKING:
|
||||||
from .vector import Vector3
|
from .vector import Vector3 # type: ignore
|
||||||
|
|
||||||
|
|
||||||
class Point3:
|
class Point3:
|
||||||
@ -19,5 +19,37 @@ class Point3:
|
|||||||
def __str__(self):
|
def __str__(self):
|
||||||
return f"Point3({self.x}, {self.y}, {self.z})"
|
return f"Point3({self.x}, {self.y}, {self.z})"
|
||||||
|
|
||||||
|
@overload
|
||||||
def __add__(self, other: "Vector3") -> "Point3":
|
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)
|
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
|
from typing import overload, TYPE_CHECKING
|
||||||
|
|
||||||
if TYPE_CHECKING: # type: ignore
|
if TYPE_CHECKING:
|
||||||
from .point import Point3
|
from .point import Point3 # type: ignore
|
||||||
|
|
||||||
|
|
||||||
class Vector3:
|
class Vector3:
|
||||||
@ -12,12 +12,65 @@ class Vector3:
|
|||||||
:param y:
|
:param y:
|
||||||
:param z:
|
:param z:
|
||||||
"""
|
"""
|
||||||
self.x = x
|
self._x = x
|
||||||
self.y = y
|
self._y = y
|
||||||
self.z = z
|
self._z = z
|
||||||
|
self._length = (x ** 2 + y ** 2 + z ** 2) ** 0.5
|
||||||
|
self._normalized = self / self._length
|
||||||
|
|
||||||
def __str__(self):
|
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
|
@overload
|
||||||
def __add__(self, other: 'Vector3') -> 'Vector3':
|
def __add__(self, other: 'Vector3') -> 'Vector3':
|
||||||
@ -29,14 +82,14 @@ class Vector3:
|
|||||||
|
|
||||||
def __add__(self, other):
|
def __add__(self, other):
|
||||||
if isinstance(other, Vector3):
|
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):
|
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:
|
else:
|
||||||
raise TypeError(f"unsupported operand type(s) for +: 'Vector3' and '{type(other)}'")
|
raise TypeError(f"unsupported operand type(s) for +: 'Vector3' and '{type(other)}'")
|
||||||
|
|
||||||
def __radd__(self, other: 'Point3') -> 'Point3':
|
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
|
@overload
|
||||||
def __sub__(self, other: 'Vector3') -> 'Vector3':
|
def __sub__(self, other: 'Vector3') -> 'Vector3':
|
||||||
@ -54,9 +107,9 @@ class Vector3:
|
|||||||
:return:
|
:return:
|
||||||
"""
|
"""
|
||||||
if isinstance(other, Vector3):
|
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):
|
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:
|
else:
|
||||||
raise TypeError(f"unsupported operand type(s) for -: 'Vector3' and '{type(other)}'")
|
raise TypeError(f"unsupported operand type(s) for -: 'Vector3' and '{type(other)}'")
|
||||||
|
|
||||||
@ -68,6 +121,48 @@ class Vector3:
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
if isinstance(other, Point3):
|
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:
|
else:
|
||||||
raise TypeError(f"unsupported operand type(s) for -: '{type(other)}' and 'Vector3'")
|
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
|
@File : test_vector.py
|
||||||
@Software: PyCharm
|
@Software: PyCharm
|
||||||
"""
|
"""
|
||||||
from mcpe.mp_math.vector import Vector3
|
from mbcp.mp_math.vector import Vector3
|
||||||
from mcpe.mp_math.point import Point3
|
from mbcp.mp_math.point import Point3
|
||||||
|
|
||||||
|
|
||||||
def test_v():
|
def test_v():
|
||||||
v1 = Vector3(1, 2, 3)
|
v1 = Vector3(1, 2, 3)
|
||||||
v2 = Vector3(4, 5, 6)
|
v2 = Vector3(4, 5, 6)
|
||||||
v3 = v1 + v2
|
v3 = v1 + v2
|
||||||
assert v3.x == 5
|
assert v3._x == 5
|
||||||
assert v3.y == 7
|
assert v3._y == 7
|
||||||
assert v3.z == 9
|
assert v3._z == 9
|
||||||
print("test_v 1111passed")
|
print("test_v 1111passed")
|
||||||
|
Loading…
Reference in New Issue
Block a user