mirror of
https://github.com/snowykami/mbcp.git
synced 2024-11-22 14:17:38 +08:00
⚡ add some mathematical method for object Line3
This commit is contained in:
parent
de5bfa3843
commit
24d8b4980d
88
mbcp/mp_math/line.py
Normal file
88
mbcp/mp_math/line.py
Normal file
@ -0,0 +1,88 @@
|
|||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
"""
|
||||||
|
Copyright (C) 2020-2024 LiteyukiStudio. All Rights Reserved
|
||||||
|
|
||||||
|
@Time : 2024/8/6 下午12:57
|
||||||
|
@Author : snowykami
|
||||||
|
@Email : snowykami@outlook.com
|
||||||
|
@File : line.py
|
||||||
|
@Software: PyCharm
|
||||||
|
"""
|
||||||
|
from typing import overload, TYPE_CHECKING
|
||||||
|
|
||||||
|
if TYPE_CHECKING:
|
||||||
|
from .point import Point3
|
||||||
|
|
||||||
|
|
||||||
|
class Line3:
|
||||||
|
def __init__(self, a: float, b: float, c: float, d: float):
|
||||||
|
"""
|
||||||
|
三维空间中的直线。
|
||||||
|
:param a:
|
||||||
|
:param b:
|
||||||
|
:param c:
|
||||||
|
:param d:
|
||||||
|
"""
|
||||||
|
self.a = a
|
||||||
|
self.b = b
|
||||||
|
self.c = c
|
||||||
|
self.d = d
|
||||||
|
|
||||||
|
def __str__(self):
|
||||||
|
return f"Line3({self.a}, {self.b}, {self.c}, {self.d})"
|
||||||
|
|
||||||
|
def get_perpendicular(self, point: "Point3") -> "Line3":
|
||||||
|
"""
|
||||||
|
获取直线经过指定点p的垂线。
|
||||||
|
:param point: 指定点p,直线外的点
|
||||||
|
:return: 垂直于self且过点p的直线
|
||||||
|
"""
|
||||||
|
a = -self.b
|
||||||
|
b = self.a
|
||||||
|
c = 0
|
||||||
|
d = -(a * point.x + b * point.y + self.c * point.z)
|
||||||
|
return Line3(a, b, c, d)
|
||||||
|
|
||||||
|
def get_intersection(self, line: "Line3") -> "Point3":
|
||||||
|
"""
|
||||||
|
获取两条直线的交点。
|
||||||
|
: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.")
|
||||||
|
|
||||||
|
if self.is_collinear(line):
|
||||||
|
raise ValueError("Lines are collinear and do not have a single intersection point.")
|
||||||
|
|
||||||
|
if not self.is_coplanar(line):
|
||||||
|
raise ValueError("Lines are not coplanar and do not intersect.")
|
||||||
|
|
||||||
|
a1, b1, c1, d1 = self.a, self.b, self.c, self.d
|
||||||
|
a2, b2, c2, d2 = line.a, line.b, line.c, line.d
|
||||||
|
|
||||||
|
t = (b1 * (c2 * d1 - c1 * d2) - b2 * (c1 * d1 - c2 * d2)) / (b1 * c2 - b2 * c1)
|
||||||
|
|
||||||
|
x = self.a * t + self.b * (-d1 / self.b)
|
||||||
|
y = -self.b * t + self.a * (d1 / self.a)
|
||||||
|
z = 0
|
||||||
|
|
||||||
|
return Point3(x, y, z)
|
||||||
|
|
||||||
|
def is_parallel(self, line: "Line3") -> bool:
|
||||||
|
# 直线平行的条件是它们的法向量成比例
|
||||||
|
return self.a * line.b == self.b * line.a and self.c * line.b == self.d * line.a
|
||||||
|
|
||||||
|
def is_collinear(self, line: "Line3") -> bool:
|
||||||
|
# 直线共线的条件是它们的法向量成比例且常数项也成比例
|
||||||
|
return self.is_parallel(line) and (self.d * line.b - self.b * line.d) / (self.a * line.b - self.b * line.a) == 0
|
||||||
|
|
||||||
|
def is_coplanar(self, line: "Line3") -> bool:
|
||||||
|
# 两条直线共面的条件是它们的方向向量和法向量的叉乘为零向量
|
||||||
|
direction1 = (-self.c, 0, self.a)
|
||||||
|
direction2 = (line.c, -line.b, 0)
|
||||||
|
cross_product = direction1[0] * direction2[1] - direction1[1] * direction2[0]
|
||||||
|
return cross_product == 0
|
@ -1,7 +1,7 @@
|
|||||||
from typing import overload, TYPE_CHECKING
|
from typing import overload, TYPE_CHECKING
|
||||||
|
|
||||||
if TYPE_CHECKING:
|
if TYPE_CHECKING: # type: ignore
|
||||||
from mcpe.mp_math.vector import Vector3
|
from .vector import Vector3
|
||||||
|
|
||||||
|
|
||||||
class Point3:
|
class Point3:
|
0
mbcp/mp_math/py.typed
Normal file
0
mbcp/mp_math/py.typed
Normal file
@ -1,7 +1,7 @@
|
|||||||
from typing import overload, TYPE_CHECKING
|
from typing import overload, TYPE_CHECKING
|
||||||
|
|
||||||
if TYPE_CHECKING:
|
if TYPE_CHECKING: # type: ignore
|
||||||
from mcpe.mp_math.point import Point3
|
from .point import Point3
|
||||||
|
|
||||||
|
|
||||||
class Vector3:
|
class Vector3:
|
||||||
@ -47,6 +47,12 @@ class Vector3:
|
|||||||
...
|
...
|
||||||
|
|
||||||
def __sub__(self, other):
|
def __sub__(self, other):
|
||||||
|
"""
|
||||||
|
V - P -> P
|
||||||
|
V - V -> V
|
||||||
|
:param other:
|
||||||
|
: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):
|
||||||
@ -55,9 +61,13 @@ class Vector3:
|
|||||||
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 __rsub__(self, other: Point3):
|
def __rsub__(self, other: Point3):
|
||||||
|
"""
|
||||||
|
P - V -> P
|
||||||
|
:param other:
|
||||||
|
:return:
|
||||||
|
"""
|
||||||
|
|
||||||
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)
|
||||||
elif isinstance(other, Vector3):
|
|
||||||
return Vector3(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'")
|
@ -1,66 +0,0 @@
|
|||||||
# -*- coding: utf-8 -*-
|
|
||||||
"""
|
|
||||||
Copyright (C) 2020-2024 LiteyukiStudio. All Rights Reserved
|
|
||||||
|
|
||||||
@Time : 2024/8/6 下午12:57
|
|
||||||
@Author : snowykami
|
|
||||||
@Email : snowykami@outlook.com
|
|
||||||
@File : line.py
|
|
||||||
@Software: PyCharm
|
|
||||||
"""
|
|
||||||
from typing import overload, TYPE_CHECKING
|
|
||||||
|
|
||||||
if TYPE_CHECKING:
|
|
||||||
from mcpe.mp_math.point import Point3
|
|
||||||
from mcpe.mp_math.vector import Vector3
|
|
||||||
|
|
||||||
|
|
||||||
class Line3:
|
|
||||||
def __init__(self, a: float, b: float, c: float, d:float):
|
|
||||||
"""
|
|
||||||
三维空间中的直线。
|
|
||||||
:param a:
|
|
||||||
:param b:
|
|
||||||
:param c:
|
|
||||||
:param d:
|
|
||||||
"""
|
|
||||||
self.a = a
|
|
||||||
self.b = b
|
|
||||||
self.c = c
|
|
||||||
self.d = d
|
|
||||||
|
|
||||||
def __str__(self):
|
|
||||||
return f"Line3({self.a}, {self.b}, {self.c}, {self.d})"
|
|
||||||
|
|
||||||
def get_perpendicular(self, p: "Point3") -> "Line3":
|
|
||||||
"""
|
|
||||||
获取直线经过指定点p的垂线。
|
|
||||||
:param p: 指定点p,直线外的点
|
|
||||||
:return: 垂直于self且过点p的直线
|
|
||||||
"""
|
|
||||||
a = -self.b
|
|
||||||
b = self.a
|
|
||||||
c = 0
|
|
||||||
d = -(a * p.x + b * p.y + self.c * p.z)
|
|
||||||
return Line3(a, b, c, d)
|
|
||||||
|
|
||||||
def get_intersection(self, l: "Line3") -> "Point3":
|
|
||||||
"""
|
|
||||||
获取两空间直线的交点。
|
|
||||||
:param l: 另一条直线,不平行于self,不共线,且共面
|
|
||||||
:return: 交点
|
|
||||||
"""
|
|
||||||
# 平行检测
|
|
||||||
if ...:
|
|
||||||
...
|
|
||||||
# 共线检测
|
|
||||||
if ...:
|
|
||||||
...
|
|
||||||
# 不共线检测
|
|
||||||
if ...:
|
|
||||||
...
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue
Block a user