diff --git a/docs/.vitepress/config/en.ts b/docs/.vitepress/config/en.ts index b6b10e1..c8e5530 100644 --- a/docs/.vitepress/config/en.ts +++ b/docs/.vitepress/config/en.ts @@ -4,7 +4,11 @@ export const en = defineConfig({ lang: "en-US", description: "A library made for Minecraft particle generation", - themeConfig: { + nav: [ + {text: 'Get Start', link: '/guide'}, + {text: 'API Document', link: '/api/'}, + {text: 'Demo', link: '/demo/'}, + ], }, }) \ No newline at end of file diff --git a/docs/.vitepress/config/index.ts b/docs/.vitepress/config/index.ts index 0f14210..0262af8 100644 --- a/docs/.vitepress/config/index.ts +++ b/docs/.vitepress/config/index.ts @@ -3,6 +3,7 @@ import {defineConfig} from "vitepress"; import {common} from './common' import {en} from './en' import {zh} from './zh' +import {ja} from './ja' @@ -10,6 +11,7 @@ export default defineConfig({ ...common, locales:{ root: { label: "简体中文", ...zh }, - en: { label: "English", ...en } + en: { label: "English", ...en }, + ja: { label: "日本語", ...ja }, } }) \ No newline at end of file diff --git a/docs/.vitepress/config/ja.ts b/docs/.vitepress/config/ja.ts new file mode 100644 index 0000000..4cbd9e9 --- /dev/null +++ b/docs/.vitepress/config/ja.ts @@ -0,0 +1,14 @@ +import {defineConfig} from 'vitepress' + +export const ja = defineConfig({ + + lang: "ja-JP", + description: "Minecraftのパーティクル生成用のライブラリ", + themeConfig: { + nav: [ + {text: 'スタート', link: '/guide'}, + {text: 'APIドキュメント', link: '/api/'}, + {text: 'インスタンス', link: '/demo/'}, + ], + }, +}) \ No newline at end of file diff --git a/docs/.vitepress/config/zh.ts b/docs/.vitepress/config/zh.ts index 8c5003f..0068f3d 100644 --- a/docs/.vitepress/config/zh.ts +++ b/docs/.vitepress/config/zh.ts @@ -1,21 +1,14 @@ import {defineConfig} from 'vitepress' export const zh = defineConfig({ + lang: "zh-Hans", description: "一个用于Minecraft粒子计算和生成的库", - themeConfig: { nav: [ - {text: '快速开始', link: '/guide'}, + {text: '快速开始', link: '/guide/'}, {text: 'API文档', link: '/api/'}, {text: '实例', link: '/demo/'}, ], - // sidebar: { - // '/api/': { - // base: '/api/', - // items: [ - // ] - // } - // } }, }) \ No newline at end of file diff --git a/docs/api/mp_math/equation.md b/docs/api/mp_math/equation.md index e34924d..e3bb1c0 100644 --- a/docs/api/mp_math/equation.md +++ b/docs/api/mp_math/equation.md @@ -14,6 +14,14 @@ title: mbcp.mp_math.equation - epsilon: 偏移量 +返回: + +- 偏导函数 + +引发: + +- ValueError 无效变量类型 +
diff --git a/docs/api/mp_math/line.md b/docs/api/mp_math/line.md index d12dac8..353f91f 100644 --- a/docs/api/mp_math/line.md +++ b/docs/api/mp_math/line.md @@ -43,6 +43,10 @@ def __init__(self, point: 'Point3', direction: 'Vector3'): - epsilon: 误差 +返回: + +- 是否近似相等 +
@@ -71,6 +75,14 @@ def approx(self, other: 'Line3', epsilon: float=APPROX) -> bool: - other: 另一条直线 +返回: + +- 夹角弧度 + +引发: + +- TypeError 不支持的类型 +
@@ -100,6 +112,14 @@ def cal_angle(self, other: 'Line3') -> 'AnyAngle': - other: 平行直线或点 +返回: + +- 距离 + +引发: + +- TypeError 不支持的类型 +
@@ -142,6 +162,16 @@ def cal_distance(self, other: 'Line3 | Point3') -> float: - other: 另一条直线 +返回: + +- 交点 + +引发: + +- ValueError 直线平行 + +- ValueError 直线不共面 +
@@ -176,6 +206,10 @@ def cal_intersection(self, other: 'Line3') -> 'Point3': - point: 指定点 +返回: + +- 垂线 +
@@ -203,6 +237,10 @@ def cal_perpendicular(self, point: 'Point3') -> 'Line3': - t: 参数t +返回: + +- 点 +
@@ -257,6 +295,10 @@ def get_parametric_equations(self) -> tuple[OneSingleVarFunc, OneSingleVarFunc, - epsilon: 误差 +返回: + +- 是否近似平行 +
@@ -285,6 +327,10 @@ def is_approx_parallel(self, other: 'Line3', epsilon: float=1e-06) -> bool: - other: 另一条直线 +返回: + +- 是否平行 +
@@ -312,6 +358,10 @@ def is_parallel(self, other: 'Line3') -> bool: - other: 另一条直线 +返回: + +- 是否共线 +
@@ -339,6 +389,10 @@ def is_collinear(self, other: 'Line3') -> bool: - point: 点 +返回: + +- 是否在直线上 +
@@ -367,6 +421,10 @@ def is_point_on(self, point: 'Point3') -> bool: - other: 另一条直线 +返回: + +- 是否共面 +
@@ -429,6 +487,10 @@ def simplify(self): - p2: 点2 +返回: + +- 直线 +
@@ -459,6 +521,10 @@ def from_two_points(cls, p1: 'Point3', p2: 'Point3') -> 'Line3': - other: 另一条直线 +返回: + +- 交点 +
diff --git a/docs/api/mp_math/plane.md b/docs/api/mp_math/plane.md index e069db8..11e1785 100644 --- a/docs/api/mp_math/plane.md +++ b/docs/api/mp_math/plane.md @@ -49,6 +49,10 @@ def __init__(self, a: float, b: float, c: float, d: float): - other: +返回: + +- 是否近似相等 +
@@ -88,6 +92,14 @@ def approx(self, other: 'Plane3') -> bool: - other: 另一个平面 +返回: + +- 夹角弧度 + +引发: + +- TypeError 不支持的类型 +
@@ -122,6 +134,14 @@ def cal_angle(self, other: 'Line3 | Plane3') -> 'AnyAngle': - other: 另一个平面或点 +返回: + +- 距离 + +引发: + +- TypeError 不支持的类型 +
@@ -156,6 +176,10 @@ def cal_distance(self, other: 'Plane3 | Point3') -> float: - other: 另一个平面 +返回: + +- 交线 +
@@ -200,6 +224,14 @@ def cal_intersection_line3(self, other: 'Plane3') -> 'Line3': - other: 不与平面平行或在平面上的直线 +返回: + +- 交点 + +引发: + +- ValueError 平面与直线平行或重合 +
@@ -233,6 +265,10 @@ def cal_intersection_point3(self, other: 'Line3') -> 'Point3': - point: 指定点 +返回: + +- 平面 +
@@ -260,6 +296,10 @@ def cal_parallel_plane3(self, point: 'Point3') -> 'Plane3': - other: 另一个平面 +返回: + +- 是否平行 +
@@ -317,6 +357,10 @@ def normal(self) -> 'Vector3': - normal: 法向量 +返回: + +- 平面 +
@@ -353,6 +397,10 @@ def from_point_and_normal(cls, point: 'Point3', normal: 'Vector3') -> 'Plane3': - p3: 点3 +返回: + +- 平面 +
@@ -389,6 +437,10 @@ def from_three_points(cls, p1: 'Point3', p2: 'Point3', p3: 'Point3') -> 'Plane3' - l2: 直线2 +返回: + +- 平面 +
@@ -425,6 +477,10 @@ def from_two_lines(cls, l1: 'Line3', l2: 'Line3') -> 'Plane3': - line: 面上直线,不包含点 +返回: + +- 平面 +
@@ -515,6 +571,10 @@ def __and__(self, other: 'Plane3') -> 'Line3 | None': - other: +返回: + +- 不平行平面的交线,平面平行返回None +
diff --git a/docs/api/mp_math/point.md b/docs/api/mp_math/point.md index abb2706..85b7e91 100644 --- a/docs/api/mp_math/point.md +++ b/docs/api/mp_math/point.md @@ -47,6 +47,10 @@ def __init__(self, x: float, y: float, z: float): - epsilon: +返回: + +- 是否近似相等 +
diff --git a/docs/api/mp_math/utils.md b/docs/api/mp_math/utils.md index 40ac31e..96b4b6f 100644 --- a/docs/api/mp_math/utils.md +++ b/docs/api/mp_math/utils.md @@ -14,6 +14,10 @@ title: mbcp.mp_math.utils - max_: +返回: + +- 限制后的值 +
@@ -48,6 +52,10 @@ def clamp(x: float, min_: float, max_: float) -> float: - epsilon: +返回: + +- 是否近似相等 +
@@ -80,6 +88,10 @@ def approx(x: float, y: float=0.0, epsilon: float=APPROX) -> bool: - only_neg: 是否只返回负数的符号 +返回: + +- 符号 + - "" +
@@ -117,6 +129,10 @@ def sign(x: float, only_neg: bool=False) -> str: - only_neg: 是否只返回负数的符号 +返回: + +- 符号 + - "" +
diff --git a/docs/api/mp_math/vector.md b/docs/api/mp_math/vector.md index cb8973c..550b545 100644 --- a/docs/api/mp_math/vector.md +++ b/docs/api/mp_math/vector.md @@ -47,6 +47,10 @@ def __init__(self, x: float, y: float, z: float): - epsilon: +返回: + +- 是否近似相等 +
@@ -76,6 +80,10 @@ def approx(self, other: 'Vector3', epsilon: float=APPROX) -> bool: - other: 另一个向量 +返回: + +- 夹角 +
@@ -103,6 +111,14 @@ def cal_angle(self, other: 'Vector3') -> 'AnyAngle': 其余结果的模为平行四边形的面积。 +参数: + +- other: + +返回: + +- 行列式的结果 +
@@ -144,6 +160,10 @@ def cross(self, other: 'Vector3') -> 'Vector3': - epsilon: 允许的误差 +返回: + +- 是否近似平行 +
@@ -172,6 +192,10 @@ def is_approx_parallel(self, other: 'Vector3', epsilon: float=APPROX) -> bool: - other: 另一个向量 +返回: + +- 是否平行 +
@@ -377,6 +401,10 @@ def __add__(self, other): - other: +返回: + +- 是否相等 +
diff --git a/docs/api/presets/model/index.md b/docs/api/presets/model/index.md index 53ad44e..5d10b7d 100644 --- a/docs/api/presets/model/index.md +++ b/docs/api/presets/model/index.md @@ -15,6 +15,10 @@ title: mbcp.presets.model - density: +返回: + +- List[Point3]: 球体上的点集。 +
diff --git a/docs/en/api/index.md b/docs/en/api/index.md new file mode 100644 index 0000000..6d251e8 --- /dev/null +++ b/docs/en/api/index.md @@ -0,0 +1,3 @@ +--- +title: mbcp +--- diff --git a/docs/en/api/mp_math/angle.md b/docs/en/api/mp_math/angle.md new file mode 100644 index 0000000..3abc69b --- /dev/null +++ b/docs/en/api/mp_math/angle.md @@ -0,0 +1,449 @@ +--- +title: mbcp.mp_math.angle +--- +### ***class*** `Angle` + +### ***class*** `AnyAngle` + +### *def* `__init__(self, value: float, is_radian: bool = False)` + + +任意角度。 + +Args: + +- value: 角度或弧度值 + +- is_radian: 是否为弧度,默认为否 + + + +
+Source code + +```python +def __init__(self, value: float, is_radian: bool=False): + """ + 任意角度。 + Args: + value: 角度或弧度值 + is_radian: 是否为弧度,默认为否 + """ + if is_radian: + self.radian = value + else: + self.radian = value * PI / 180 +``` +
+ +### `@property` +### *def* `complementary(self) -> 'AnyAngle'` + + +余角:两角的和为90°。 + +Return: + +- 余角 + + + +
+Source code + +```python +@property +def complementary(self) -> 'AnyAngle': + """ + 余角:两角的和为90°。 + Returns: + 余角 + """ + return AnyAngle(PI / 2 - self.minimum_positive.radian, is_radian=True) +``` +
+ +### `@property` +### *def* `supplementary(self) -> 'AnyAngle'` + + +补角:两角的和为180°。 + +Return: + +- 补角 + + + +
+Source code + +```python +@property +def supplementary(self) -> 'AnyAngle': + """ + 补角:两角的和为180°。 + Returns: + 补角 + """ + return AnyAngle(PI - self.minimum_positive.radian, is_radian=True) +``` +
+ +### `@property` +### *def* `degree(self) -> float` + + +角度。 + +Return: + +- 弧度 + + + +
+Source code + +```python +@property +def degree(self) -> float: + """ + 角度。 + Returns: + 弧度 + """ + return self.radian * 180 / PI +``` +
+ +### `@property` +### *def* `minimum_positive(self) -> 'AnyAngle'` + + +最小正角。 + +Return: + +- 最小正角度 + + + +
+Source code + +```python +@property +def minimum_positive(self) -> 'AnyAngle': + """ + 最小正角。 + Returns: + 最小正角度 + """ + return AnyAngle(self.radian % (2 * PI)) +``` +
+ +### `@property` +### *def* `maximum_negative(self) -> 'AnyAngle'` + + +最大负角。 + +Return: + +- 最大负角度 + + + +
+Source code + +```python +@property +def maximum_negative(self) -> 'AnyAngle': + """ + 最大负角。 + Returns: + 最大负角度 + """ + return AnyAngle(-self.radian % (2 * PI), is_radian=True) +``` +
+ +### `@property` +### *def* `sin(self) -> float` + + +正弦值。 + +Return: + +- 正弦值 + + + +
+Source code + +```python +@property +def sin(self) -> float: + """ + 正弦值。 + Returns: + 正弦值 + """ + return math.sin(self.radian) +``` +
+ +### `@property` +### *def* `cos(self) -> float` + + +余弦值。 + +Return: + +- 余弦值 + + + +
+Source code + +```python +@property +def cos(self) -> float: + """ + 余弦值。 + Returns: + 余弦值 + """ + return math.cos(self.radian) +``` +
+ +### `@property` +### *def* `tan(self) -> float` + + +正切值。 + +Return: + +- 正切值 + + + +
+Source code + +```python +@property +def tan(self) -> float: + """ + 正切值。 + Returns: + 正切值 + """ + return math.tan(self.radian) +``` +
+ +### `@property` +### *def* `cot(self) -> float` + + +余切值。 + +Return: + +- 余切值 + + + +
+Source code + +```python +@property +def cot(self) -> float: + """ + 余切值。 + Returns: + 余切值 + """ + return 1 / math.tan(self.radian) +``` +
+ +### `@property` +### *def* `sec(self) -> float` + + +正割值。 + +Return: + +- 正割值 + + + +
+Source code + +```python +@property +def sec(self) -> float: + """ + 正割值。 + Returns: + 正割值 + """ + return 1 / math.cos(self.radian) +``` +
+ +### `@property` +### *def* `csc(self) -> float` + + +余割值。 + +Return: + +- 余割值 + + + +
+Source code + +```python +@property +def csc(self) -> float: + """ + 余割值。 + Returns: + 余割值 + """ + return 1 / math.sin(self.radian) +``` +
+ +### *def* `__add__(self, other: 'AnyAngle') -> 'AnyAngle'` + + +
+Source code + +```python +def __add__(self, other: 'AnyAngle') -> 'AnyAngle': + return AnyAngle(self.radian + other.radian, is_radian=True) +``` +
+ +### *def* `__eq__(self, other)` + + +
+Source code + +```python +def __eq__(self, other): + return approx(self.radian, other.radian) +``` +
+ +### *def* `__sub__(self, other: 'AnyAngle') -> 'AnyAngle'` + + +
+Source code + +```python +def __sub__(self, other: 'AnyAngle') -> 'AnyAngle': + return AnyAngle(self.radian - other.radian, is_radian=True) +``` +
+ +### *def* `__mul__(self, other: float) -> 'AnyAngle'` + + +
+Source code + +```python +def __mul__(self, other: float) -> 'AnyAngle': + return AnyAngle(self.radian * other, is_radian=True) +``` +
+ +### *def* `__repr__(self)` + + +
+Source code + +```python +def __repr__(self): + return f'AnyAngle({self.radian}, is_radian=True)' +``` +
+ +### *def* `__str__(self)` + + +
+Source code + +```python +def __str__(self): + return f'AnyAngle({self.degree}° or {self.radian} rad)' +``` +
+ +### `@overload` +### *def* `__truediv__(self, other: float) -> 'AnyAngle'` + + +
+Source code + +```python +@overload +def __truediv__(self, other: float) -> 'AnyAngle': + ... +``` +
+ +### `@overload` +### *def* `__truediv__(self, other: 'AnyAngle') -> float` + + +
+Source code + +```python +@overload +def __truediv__(self, other: 'AnyAngle') -> float: + ... +``` +
+ +### *def* `__truediv__(self, other)` + + +
+Source code + +```python +def __truediv__(self, other): + if isinstance(other, AnyAngle): + return self.radian / other.radian + return AnyAngle(self.radian / other, is_radian=True) +``` +
+ diff --git a/docs/en/api/mp_math/const.md b/docs/en/api/mp_math/const.md new file mode 100644 index 0000000..888edf3 --- /dev/null +++ b/docs/en/api/mp_math/const.md @@ -0,0 +1,15 @@ +--- +title: mbcp.mp_math.const +--- +### ***var*** `PI = math.pi` + +### ***var*** `E = math.e` + +### ***var*** `GOLDEN_RATIO = (1 + math.sqrt(5)) / 2` + +### ***var*** `GAMMA = 0.5772156649015329` + +### ***var*** `EPSILON = 0.0001` + +### ***var*** `APPROX = 0.001` + diff --git a/docs/en/api/mp_math/equation.md b/docs/en/api/mp_math/equation.md new file mode 100644 index 0000000..30462c2 --- /dev/null +++ b/docs/en/api/mp_math/equation.md @@ -0,0 +1,177 @@ +--- +title: mbcp.mp_math.equation +--- +### *def* `get_partial_derivative_func(func: MultiVarsFunc = EPSILON) -> MultiVarsFunc` + + +求N元函数一阶偏导函数。这玩意不太稳定,慎用。 + +Args: + +- func: 函数 + +- var: 变量位置,可为整数(一阶偏导)或整数元组(高阶偏导) + +- epsilon: 偏移量 + +Return: + +- 偏导函数 + +Raises: + +- ValueError 无效变量类型 + + + +
+Source code + +```python +def get_partial_derivative_func(func: MultiVarsFunc, var: int | tuple[int, ...], epsilon: Number=EPSILON) -> MultiVarsFunc: + """ + 求N元函数一阶偏导函数。这玩意不太稳定,慎用。 + Args: + func: 函数 + var: 变量位置,可为整数(一阶偏导)或整数元组(高阶偏导) + epsilon: 偏移量 + Returns: + 偏导函数 + Raises: + ValueError: 无效变量类型 + """ + if isinstance(var, int): + + def partial_derivative_func(*args: Var) -> Var: + args_list_plus = list(args) + args_list_plus[var] += epsilon + args_list_minus = list(args) + args_list_minus[var] -= epsilon + return (func(*args_list_plus) - func(*args_list_minus)) / (2 * epsilon) + return partial_derivative_func + elif isinstance(var, tuple): + + def high_order_partial_derivative_func(*args: Var) -> Var: + result_func = func + for v in var: + result_func = get_partial_derivative_func(result_func, v, epsilon) + return result_func(*args) + return high_order_partial_derivative_func + else: + raise ValueError('Invalid var type') +``` +
+ +### *def* `partial_derivative_func() -> Var` + + +
+Source code + +```python +def partial_derivative_func(*args: Var) -> Var: + args_list_plus = list(args) + args_list_plus[var] += epsilon + args_list_minus = list(args) + args_list_minus[var] -= epsilon + return (func(*args_list_plus) - func(*args_list_minus)) / (2 * epsilon) +``` +
+ +### *def* `high_order_partial_derivative_func() -> Var` + + +
+Source code + +```python +def high_order_partial_derivative_func(*args: Var) -> Var: + result_func = func + for v in var: + result_func = get_partial_derivative_func(result_func, v, epsilon) + return result_func(*args) +``` +
+ +### ***class*** `CurveEquation` + +### *def* `__init__(self, x_func: OneVarFunc, y_func: OneVarFunc, z_func: OneVarFunc)` + + +曲线方程。 + +Args: + +- x_func: x函数 + +- y_func: y函数 + +- z_func: z函数 + + + +
+Source code + +```python +def __init__(self, x_func: OneVarFunc, y_func: OneVarFunc, z_func: OneVarFunc): + """ + 曲线方程。 + Args: + x_func: x函数 + y_func: y函数 + z_func: z函数 + """ + self.x_func = x_func + self.y_func = y_func + self.z_func = z_func +``` +
+ +### *def* `__call__(self) -> Point3 | tuple[Point3, ...]` + + +计算曲线上的点。 + +Args: + +- *t: + +- 参数: + + + +
+Source code + +```python +def __call__(self, *t: Var) -> Point3 | tuple[Point3, ...]: + """ + 计算曲线上的点。 + Args: + *t: + 参数 + Returns: + + """ + if len(t) == 1: + return Point3(self.x_func(t[0]), self.y_func(t[0]), self.z_func(t[0])) + else: + return tuple([Point3(x, y, z) for x, y, z in zip(self.x_func(t), self.y_func(t), self.z_func(t))]) +``` +
+ +### *def* `__str__(self)` + + +
+Source code + +```python +def __str__(self): + return 'CurveEquation()' +``` +
+ +### ***var*** `result_func = get_partial_derivative_func(result_func, v, epsilon)` + diff --git a/docs/en/api/mp_math/index.md b/docs/en/api/mp_math/index.md new file mode 100644 index 0000000..6e3261c --- /dev/null +++ b/docs/en/api/mp_math/index.md @@ -0,0 +1,3 @@ +--- +title: mbcp.mp_math +--- diff --git a/docs/en/api/mp_math/line.md b/docs/en/api/mp_math/line.md new file mode 100644 index 0000000..40d0d57 --- /dev/null +++ b/docs/en/api/mp_math/line.md @@ -0,0 +1,622 @@ +--- +title: mbcp.mp_math.line +--- +### ***class*** `Line3` + +### *def* `__init__(self, point: 'Point3', direction: 'Vector3')` + + +三维空间中的直线。由一个点和一个方向向量确定。 + +Args: + +- point: 直线上的一点 + +- direction: 直线的方向向量 + + + +
+Source code + +```python +def __init__(self, point: 'Point3', direction: 'Vector3'): + """ + 三维空间中的直线。由一个点和一个方向向量确定。 + Args: + point: 直线上的一点 + direction: 直线的方向向量 + """ + self.point = point + self.direction = direction +``` +
+ +### *def* `approx(self, other: 'Line3', epsilon: float = APPROX) -> bool` + + +判断两条直线是否近似相等。 + +Args: + +- other: 另一条直线 + +- epsilon: 误差 + +Return: + +- 是否近似相等 + + + +
+Source code + +```python +def approx(self, other: 'Line3', epsilon: float=APPROX) -> bool: + """ + 判断两条直线是否近似相等。 + Args: + other: 另一条直线 + epsilon: 误差 + Returns: + 是否近似相等 + """ + return self.is_approx_parallel(other, epsilon) and (self.point - other.point).is_approx_parallel(self.direction, epsilon) +``` +
+ +### *def* `cal_angle(self, other: 'Line3') -> 'AnyAngle'` + + +计算直线和直线之间的夹角。 + +Args: + +- other: 另一条直线 + +Return: + +- 夹角弧度 + +Raises: + +- TypeError 不支持的类型 + + + +
+Source code + +```python +def cal_angle(self, other: 'Line3') -> 'AnyAngle': + """ + 计算直线和直线之间的夹角。 + Args: + other: 另一条直线 + Returns: + 夹角弧度 + Raises: + TypeError: 不支持的类型 + """ + return self.direction.cal_angle(other.direction) +``` +
+ +### *def* `cal_distance(self, other: 'Line3 | Point3') -> float` + + +计算直线和直线或点之间的距离。 + +Args: + +- other: 平行直线或点 + +Return: + +- 距离 + +Raises: + +- TypeError 不支持的类型 + + + +
+Source code + +```python +def cal_distance(self, other: 'Line3 | Point3') -> float: + """ + 计算直线和直线或点之间的距离。 + Args: + other: 平行直线或点 + + Returns: + 距离 + Raises: + TypeError: 不支持的类型 + """ + if isinstance(other, Line3): + if self == other: + return 0 + elif self.is_parallel(other): + return (other.point - self.point).cross(self.direction).length / self.direction.length + elif not self.is_coplanar(other): + return abs(self.direction.cross(other.direction) @ (self.point - other.point) / self.direction.cross(other.direction).length) + else: + return 0 + elif isinstance(other, Point3): + return (other - self.point).cross(self.direction).length / self.direction.length + else: + raise TypeError('Unsupported type.') +``` +
+ +### *def* `cal_intersection(self, other: 'Line3') -> 'Point3'` + + +计算两条直线的交点。 + +Args: + +- other: 另一条直线 + +Return: + +- 交点 + +Raises: + +- ValueError 直线平行 + +- ValueError 直线不共面 + + + +
+Source code + +```python +def cal_intersection(self, other: 'Line3') -> 'Point3': + """ + 计算两条直线的交点。 + Args: + other: 另一条直线 + Returns: + 交点 + Raises: + ValueError: 直线平行 + ValueError: 直线不共面 + """ + if self.is_parallel(other): + raise ValueError('Lines are parallel and do not intersect.') + if not self.is_coplanar(other): + raise ValueError('Lines are not coplanar and do not intersect.') + return self.point + self.direction.cross(other.direction) @ other.direction.cross(self.point - other.point) / self.direction.cross(other.direction).length ** 2 * self.direction +``` +
+ +### *def* `cal_perpendicular(self, point: 'Point3') -> 'Line3'` + + +计算直线经过指定点p的垂线。 + +Args: + +- point: 指定点 + +Return: + +- 垂线 + + + +
+Source code + +```python +def cal_perpendicular(self, point: 'Point3') -> 'Line3': + """ + 计算直线经过指定点p的垂线。 + Args: + point: 指定点 + Returns: + 垂线 + """ + return Line3(point, self.direction.cross(point - self.point)) +``` +
+ +### *def* `get_point(self, t: RealNumber) -> 'Point3'` + + +获取直线上的点。同一条直线,但起始点和方向向量不同,则同一个t对应的点不同。 + +Args: + +- t: 参数t + +Return: + +- 点 + + + +
+Source code + +```python +def get_point(self, t: RealNumber) -> 'Point3': + """ + 获取直线上的点。同一条直线,但起始点和方向向量不同,则同一个t对应的点不同。 + Args: + t: 参数t + Returns: + 点 + """ + return self.point + t * self.direction +``` +
+ +### *def* `get_parametric_equations(self) -> tuple[OneSingleVarFunc, OneSingleVarFunc, OneSingleVarFunc]` + + +获取直线的参数方程。 + +Return: + +- x(t), y(t), z(t) + + + +
+Source code + +```python +def get_parametric_equations(self) -> tuple[OneSingleVarFunc, OneSingleVarFunc, OneSingleVarFunc]: + """ + 获取直线的参数方程。 + Returns: + x(t), y(t), z(t) + """ + return (lambda t: self.point.x + self.direction.x * t, lambda t: self.point.y + self.direction.y * t, lambda t: self.point.z + self.direction.z * t) +``` +
+ +### *def* `is_approx_parallel(self, other: 'Line3', epsilon: float = 1e-06) -> bool` + + +判断两条直线是否近似平行。 + +Args: + +- other: 另一条直线 + +- epsilon: 误差 + +Return: + +- 是否近似平行 + + + +
+Source code + +```python +def is_approx_parallel(self, other: 'Line3', epsilon: float=1e-06) -> bool: + """ + 判断两条直线是否近似平行。 + Args: + other: 另一条直线 + epsilon: 误差 + Returns: + 是否近似平行 + """ + return self.direction.is_approx_parallel(other.direction, epsilon) +``` +
+ +### *def* `is_parallel(self, other: 'Line3') -> bool` + + +判断两条直线是否平行。 + +Args: + +- other: 另一条直线 + +Return: + +- 是否平行 + + + +
+Source code + +```python +def is_parallel(self, other: 'Line3') -> bool: + """ + 判断两条直线是否平行。 + Args: + other: 另一条直线 + Returns: + 是否平行 + """ + return self.direction.is_parallel(other.direction) +``` +
+ +### *def* `is_collinear(self, other: 'Line3') -> bool` + + +判断两条直线是否共线。 + +Args: + +- other: 另一条直线 + +Return: + +- 是否共线 + + + +
+Source code + +```python +def is_collinear(self, other: 'Line3') -> bool: + """ + 判断两条直线是否共线。 + Args: + other: 另一条直线 + Returns: + 是否共线 + """ + return self.is_parallel(other) and (self.point - other.point).is_parallel(self.direction) +``` +
+ +### *def* `is_point_on(self, point: 'Point3') -> bool` + + +判断点是否在直线上。 + +Args: + +- point: 点 + +Return: + +- 是否在直线上 + + + +
+Source code + +```python +def is_point_on(self, point: 'Point3') -> bool: + """ + 判断点是否在直线上。 + Args: + point: 点 + Returns: + 是否在直线上 + """ + return (point - self.point).is_parallel(self.direction) +``` +
+ +### *def* `is_coplanar(self, other: 'Line3') -> bool` + + +判断两条直线是否共面。 +充要条件:两直线方向向量的叉乘与两直线上任意一点的向量的点积为0。 + +Args: + +- other: 另一条直线 + +Return: + +- 是否共面 + + + +
+Source code + +```python +def is_coplanar(self, other: 'Line3') -> bool: + """ + 判断两条直线是否共面。 + 充要条件:两直线方向向量的叉乘与两直线上任意一点的向量的点积为0。 + Args: + other: 另一条直线 + Returns: + 是否共面 + """ + return self.direction.cross(other.direction) @ (self.point - other.point) == 0 +``` +
+ +### *def* `simplify(self)` + + +简化直线方程,等价相等。 +自体简化,不返回值。 + +按照可行性一次对x y z 化 0 处理,并对向量单位化 + + + +
+Source code + +```python +def simplify(self): + """ + 简化直线方程,等价相等。 + 自体简化,不返回值。 + + 按照可行性一次对x y z 化 0 处理,并对向量单位化 + """ + self.direction.normalize() + if self.direction.x == 0: + self.point.x = 0 + if self.direction.y == 0: + self.point.y = 0 + if self.direction.z == 0: + self.point.z = 0 +``` +
+ +### `@classmethod` +### *def* `from_two_points(cls, p1: 'Point3', p2: 'Point3') -> 'Line3'` + + +工厂函数 由两点构造直线。 + +Args: + +- p1: 点1 + +- p2: 点2 + +Return: + +- 直线 + + + +
+Source code + +```python +@classmethod +def from_two_points(cls, p1: 'Point3', p2: 'Point3') -> 'Line3': + """ + 工厂函数 由两点构造直线。 + Args: + p1: 点1 + p2: 点2 + Returns: + 直线 + """ + direction = p2 - p1 + return cls(p1, direction) +``` +
+ +### *def* `__and__(self, other: 'Line3') -> 'Line3 | Point3 | None'` + + +计算两条直线点集合的交集。重合线返回自身,平行线返回None,交线返回交点。 + +Args: + +- other: 另一条直线 + +Return: + +- 交点 + + + +
+Source code + +```python +def __and__(self, other: 'Line3') -> 'Line3 | Point3 | None': + """ + 计算两条直线点集合的交集。重合线返回自身,平行线返回None,交线返回交点。 + Args: + other: 另一条直线 + Returns: + 交点 + """ + if self.is_collinear(other): + return self + elif self.is_parallel(other) or not self.is_coplanar(other): + return None + else: + return self.cal_intersection(other) +``` +
+ +### *def* `__eq__(self, other) -> bool` + + +判断两条直线是否等价。 + +v1 // v2 ∧ (p1 - p2) // v1 + +Args: + +- other: + + + +
+Source code + +```python +def __eq__(self, other) -> bool: + """ + 判断两条直线是否等价。 + + v1 // v2 ∧ (p1 - p2) // v1 + Args: + other: + + Returns: + + """ + return self.direction.is_parallel(other.direction) and (self.point - other.point).is_parallel(self.direction) +``` +
+ +### *def* `__str__(self)` + + + + + + +
+Source code + +```python +def __str__(self): + """ + 返回点向式(x-x0) + Returns: + + """ + s = 'Line3: ' + if self.direction.x != 0: + s += f'(x{sign_format(-self.point.x)})/{self.direction.x}' + if self.direction.y != 0: + s += f' = (y{sign_format(-self.point.y)})/{self.direction.y}' + if self.direction.z != 0: + s += f' = (z{sign_format(-self.point.z)})/{self.direction.z}' + return s +``` +
+ +### *def* `__repr__(self)` + + +
+Source code + +```python +def __repr__(self): + return f'Line3({self.point}, {self.direction})' +``` +
+ diff --git a/docs/en/api/mp_math/mp_math_typing.md b/docs/en/api/mp_math/mp_math_typing.md new file mode 100644 index 0000000..b166130 --- /dev/null +++ b/docs/en/api/mp_math/mp_math_typing.md @@ -0,0 +1,37 @@ +--- +title: mbcp.mp_math.mp_math_typing +--- +### ***var*** `RealNumber: TypeAlias = int | float` + +### ***var*** `Number: TypeAlias = RealNumber | complex` + +### ***var*** `SingleVar = TypeVar('SingleVar', bound=Number)` + +### ***var*** `ArrayVar = TypeVar('ArrayVar', bound=Iterable[Number])` + +### ***var*** `Var: TypeAlias = SingleVar | ArrayVar` + +### ***var*** `OneSingleVarFunc: TypeAlias = Callable[[SingleVar], SingleVar]` + +### ***var*** `OneArrayFunc: TypeAlias = Callable[[ArrayVar], ArrayVar]` + +### ***var*** `OneVarFunc: TypeAlias = OneSingleVarFunc | OneArrayFunc` + +### ***var*** `TwoSingleVarsFunc: TypeAlias = Callable[[SingleVar, SingleVar], SingleVar]` + +### ***var*** `TwoArraysFunc: TypeAlias = Callable[[ArrayVar, ArrayVar], ArrayVar]` + +### ***var*** `TwoVarsFunc: TypeAlias = TwoSingleVarsFunc | TwoArraysFunc` + +### ***var*** `ThreeSingleVarsFunc: TypeAlias = Callable[[SingleVar, SingleVar, SingleVar], SingleVar]` + +### ***var*** `ThreeArraysFunc: TypeAlias = Callable[[ArrayVar, ArrayVar, ArrayVar], ArrayVar]` + +### ***var*** `ThreeVarsFunc: TypeAlias = ThreeSingleVarsFunc | ThreeArraysFunc` + +### ***var*** `MultiSingleVarsFunc: TypeAlias = Callable[..., SingleVar]` + +### ***var*** `MultiArraysFunc: TypeAlias = Callable[..., ArrayVar]` + +### ***var*** `MultiVarsFunc: TypeAlias = MultiSingleVarsFunc | MultiArraysFunc` + diff --git a/docs/en/api/mp_math/plane.md b/docs/en/api/mp_math/plane.md new file mode 100644 index 0000000..e5d5e82 --- /dev/null +++ b/docs/en/api/mp_math/plane.md @@ -0,0 +1,648 @@ +--- +title: mbcp.mp_math.plane +--- +### ***class*** `Plane3` + +### *def* `__init__(self, a: float, b: float, c: float, d: float)` + + +平面方程:ax + by + cz + d = 0 + +Args: + +- a: + +- b: + +- c: + +- d: + + + +
+Source code + +```python +def __init__(self, a: float, b: float, c: float, d: float): + """ + 平面方程:ax + by + cz + d = 0 + Args: + a: + b: + c: + d: + """ + self.a = a + self.b = b + self.c = c + self.d = d +``` +
+ +### *def* `approx(self, other: 'Plane3') -> bool` + + +判断两个平面是否近似相等。 + +Args: + +- other: + +Return: + +- 是否近似相等 + + + +
+Source code + +```python +def approx(self, other: 'Plane3') -> bool: + """ + 判断两个平面是否近似相等。 + Args: + other: + + Returns: + 是否近似相等 + """ + a = 3 + if self.a != 0: + k = other.a / self.a + return approx(other.b, self.b * k) and approx(other.c, self.c * k) and approx(other.d, self.d * k) + elif self.b != 0: + k = other.b / self.b + return approx(other.a, self.a * k) and approx(other.c, self.c * k) and approx(other.d, self.d * k) + elif self.c != 0: + k = other.c / self.c + return approx(other.a, self.a * k) and approx(other.b, self.b * k) and approx(other.d, self.d * k) + else: + return False +``` +
+ +### *def* `cal_angle(self, other: 'Line3 | Plane3') -> 'AnyAngle'` + + +计算平面与平面之间的夹角。 + +Args: + +- other: 另一个平面 + +Return: + +- 夹角弧度 + +Raises: + +- TypeError 不支持的类型 + + + +
+Source code + +```python +def cal_angle(self, other: 'Line3 | Plane3') -> 'AnyAngle': + """ + 计算平面与平面之间的夹角。 + Args: + other: 另一个平面 + Returns: + 夹角弧度 + Raises: + TypeError: 不支持的类型 + """ + if isinstance(other, Line3): + return self.normal.cal_angle(other.direction).complementary + elif isinstance(other, Plane3): + return AnyAngle(math.acos(self.normal @ other.normal / (self.normal.length * other.normal.length)), is_radian=True) + else: + raise TypeError(f'Unsupported type: {type(other)}') +``` +
+ +### *def* `cal_distance(self, other: 'Plane3 | Point3') -> float` + + +计算平面与平面或点之间的距离。 + +Args: + +- other: 另一个平面或点 + +Return: + +- 距离 + +Raises: + +- TypeError 不支持的类型 + + + +
+Source code + +```python +def cal_distance(self, other: 'Plane3 | Point3') -> float: + """ + 计算平面与平面或点之间的距离。 + Args: + other: 另一个平面或点 + Returns: + 距离 + Raises: + TypeError: 不支持的类型 + """ + if isinstance(other, Plane3): + return 0 + elif isinstance(other, Point3): + return abs(self.a * other.x + self.b * other.y + self.c * other.z + self.d) / (self.a ** 2 + self.b ** 2 + self.c ** 2) ** 0.5 + else: + raise TypeError(f'Unsupported type: {type(other)}') +``` +
+ +### *def* `cal_intersection_line3(self, other: 'Plane3') -> 'Line3'` + + +计算两平面的交线。该方法有问题,待修复。 + +Args: + +- other: 另一个平面 + +Return: + +- 交线 + + + +
+Source code + +```python +def cal_intersection_line3(self, other: 'Plane3') -> 'Line3': + """ + 计算两平面的交线。该方法有问题,待修复。 + Args: + other: 另一个平面 + Returns: + 交线 + Raises: + """ + if self.normal.is_parallel(other.normal): + raise ValueError('Planes are parallel and have no intersection.') + direction = self.normal.cross(other.normal) + x, y, z = (0, 0, 0) + if self.a != 0 and other.a != 0: + A = np.array([[self.b, self.c], [other.b, other.c]]) + B = np.array([-self.d, -other.d]) + y, z = np.linalg.solve(A, B) + elif self.b != 0 and other.b != 0: + A = np.array([[self.a, self.c], [other.a, other.c]]) + B = np.array([-self.d, -other.d]) + x, z = np.linalg.solve(A, B) + elif self.c != 0 and other.c != 0: + A = np.array([[self.a, self.b], [other.a, other.b]]) + B = np.array([-self.d, -other.d]) + x, y = np.linalg.solve(A, B) + return Line3(Point3(x, y, z), direction) +``` +
+ +### *def* `cal_intersection_point3(self, other: 'Line3') -> 'Point3'` + + +计算平面与直线的交点。 + +Args: + +- other: 不与平面平行或在平面上的直线 + +Return: + +- 交点 + +Raises: + +- ValueError 平面与直线平行或重合 + + + +
+Source code + +```python +def cal_intersection_point3(self, other: 'Line3') -> 'Point3': + """ + 计算平面与直线的交点。 + Args: + other: 不与平面平行或在平面上的直线 + Returns: + 交点 + Raises: + ValueError: 平面与直线平行或重合 + """ + if self.normal @ other.direction == 0: + raise ValueError('The plane and the line are parallel or coincident.') + x, y, z = other.get_parametric_equations() + t = -(self.a * other.point.x + self.b * other.point.y + self.c * other.point.z + self.d) / (self.a * other.direction.x + self.b * other.direction.y + self.c * other.direction.z) + return Point3(x(t), y(t), z(t)) +``` +
+ +### *def* `cal_parallel_plane3(self, point: 'Point3') -> 'Plane3'` + + +计算平行于该平面且过指定点的平面。 + +Args: + +- point: 指定点 + +Return: + +- 平面 + + + +
+Source code + +```python +def cal_parallel_plane3(self, point: 'Point3') -> 'Plane3': + """ + 计算平行于该平面且过指定点的平面。 + Args: + point: 指定点 + Returns: + 平面 + """ + return Plane3.from_point_and_normal(point, self.normal) +``` +
+ +### *def* `is_parallel(self, other: 'Plane3') -> bool` + + +判断两个平面是否平行。 + +Args: + +- other: 另一个平面 + +Return: + +- 是否平行 + + + +
+Source code + +```python +def is_parallel(self, other: 'Plane3') -> bool: + """ + 判断两个平面是否平行。 + Args: + other: 另一个平面 + Returns: + 是否平行 + """ + return self.normal.is_parallel(other.normal) +``` +
+ +### `@property` +### *def* `normal(self) -> 'Vector3'` + + +平面的法向量。 + +Return: + +- 法向量 + + + +
+Source code + +```python +@property +def normal(self) -> 'Vector3': + """ + 平面的法向量。 + Returns: + 法向量 + """ + return Vector3(self.a, self.b, self.c) +``` +
+ +### `@classmethod` +### *def* `from_point_and_normal(cls, point: 'Point3', normal: 'Vector3') -> 'Plane3'` + + +工厂函数 由点和法向量构造平面(点法式构造)。 + +Args: + +- point: 平面上的一点 + +- normal: 法向量 + +Return: + +- 平面 + + + +
+Source code + +```python +@classmethod +def from_point_and_normal(cls, point: 'Point3', normal: 'Vector3') -> 'Plane3': + """ + 工厂函数 由点和法向量构造平面(点法式构造)。 + Args: + point: 平面上的一点 + normal: 法向量 + Returns: + 平面 + """ + a, b, c = (normal.x, normal.y, normal.z) + d = -a * point.x - b * point.y - c * point.z + return cls(a, b, c, d) +``` +
+ +### `@classmethod` +### *def* `from_three_points(cls, p1: 'Point3', p2: 'Point3', p3: 'Point3') -> 'Plane3'` + + +工厂函数 由三点构造平面。 + +Args: + +- p1: 点1 + +- p2: 点2 + +- p3: 点3 + +Return: + +- 平面 + + + +
+Source code + +```python +@classmethod +def from_three_points(cls, p1: 'Point3', p2: 'Point3', p3: 'Point3') -> 'Plane3': + """ + 工厂函数 由三点构造平面。 + Args: + p1: 点1 + p2: 点2 + p3: 点3 + Returns: + 平面 + """ + v1 = p2 - p1 + v2 = p3 - p1 + normal = v1.cross(v2) + return cls.from_point_and_normal(p1, normal) +``` +
+ +### `@classmethod` +### *def* `from_two_lines(cls, l1: 'Line3', l2: 'Line3') -> 'Plane3'` + + +工厂函数 由两直线构造平面。 + +Args: + +- l1: 直线1 + +- l2: 直线2 + +Return: + +- 平面 + + + +
+Source code + +```python +@classmethod +def from_two_lines(cls, l1: 'Line3', l2: 'Line3') -> 'Plane3': + """ + 工厂函数 由两直线构造平面。 + Args: + l1: 直线1 + l2: 直线2 + Returns: + 平面 + """ + v1 = l1.direction + v2 = l2.point - l1.point + if v2 == zero_vector3: + v2 = l2.get_point(1) - l1.point + return cls.from_point_and_normal(l1.point, v1.cross(v2)) +``` +
+ +### `@classmethod` +### *def* `from_point_and_line(cls, point: 'Point3', line: 'Line3') -> 'Plane3'` + + +工厂函数 由点和直线构造平面。 + +Args: + +- point: 面上一点 + +- line: 面上直线,不包含点 + +Return: + +- 平面 + + + +
+Source code + +```python +@classmethod +def from_point_and_line(cls, point: 'Point3', line: 'Line3') -> 'Plane3': + """ + 工厂函数 由点和直线构造平面。 + Args: + point: 面上一点 + line: 面上直线,不包含点 + Returns: + 平面 + """ + return cls.from_point_and_normal(point, line.direction) +``` +
+ +### *def* `__repr__(self)` + + +
+Source code + +```python +def __repr__(self): + return f'Plane3({self.a}, {self.b}, {self.c}, {self.d})' +``` +
+ +### *def* `__str__(self)` + + +
+Source code + +```python +def __str__(self): + s = 'Plane3: ' + if self.a != 0: + s += f'{sign(self.a, only_neg=True)}{abs(self.a)}x' + if self.b != 0: + s += f' {sign(self.b)} {abs(self.b)}y' + if self.c != 0: + s += f' {sign(self.c)} {abs(self.c)}z' + if self.d != 0: + s += f' {sign(self.d)} {abs(self.d)}' + return s + ' = 0' +``` +
+ +### `@overload` +### *def* `__and__(self, other: 'Line3') -> 'Point3 | None'` + + +
+Source code + +```python +@overload +def __and__(self, other: 'Line3') -> 'Point3 | None': + ... +``` +
+ +### `@overload` +### *def* `__and__(self, other: 'Plane3') -> 'Line3 | None'` + + +
+Source code + +```python +@overload +def __and__(self, other: 'Plane3') -> 'Line3 | None': + ... +``` +
+ +### *def* `__and__(self, other)` + + +取两平面的交集(人话:交线) + +Args: + +- other: + +Return: + +- 不平行平面的交线,平面平行返回None + + + +
+Source code + +```python +def __and__(self, other): + """ + 取两平面的交集(人话:交线) + Args: + other: + Returns: + 不平行平面的交线,平面平行返回None + """ + if isinstance(other, Plane3): + if self.normal.is_parallel(other.normal): + return None + return self.cal_intersection_line3(other) + elif isinstance(other, Line3): + if self.normal @ other.direction == 0: + return None + return self.cal_intersection_point3(other) + else: + raise TypeError(f"unsupported operand type(s) for &: 'Plane3' and '{type(other)}'") +``` +
+ +### *def* `__eq__(self, other) -> bool` + + +
+Source code + +```python +def __eq__(self, other) -> bool: + return self.approx(other) +``` +
+ +### *def* `__rand__(self, other: 'Line3') -> 'Point3'` + + +
+Source code + +```python +def __rand__(self, other: 'Line3') -> 'Point3': + return self.cal_intersection_point3(other) +``` +
+ +### ***var*** `k = other.a / self.a` + +### ***var*** `A = np.array([[self.b, self.c], [other.b, other.c]])` + +### ***var*** `B = np.array([-self.d, -other.d])` + +### ***var*** `v2 = l2.get_point(1) - l1.point` + +### ***var*** `k = other.b / self.b` + +### ***var*** `A = np.array([[self.a, self.c], [other.a, other.c]])` + +### ***var*** `B = np.array([-self.d, -other.d])` + +### ***var*** `k = other.c / self.c` + +### ***var*** `A = np.array([[self.a, self.b], [other.a, other.b]])` + +### ***var*** `B = np.array([-self.d, -other.d])` + diff --git a/docs/en/api/mp_math/point.md b/docs/en/api/mp_math/point.md new file mode 100644 index 0000000..686cbfa --- /dev/null +++ b/docs/en/api/mp_math/point.md @@ -0,0 +1,199 @@ +--- +title: mbcp.mp_math.point +--- +### ***class*** `Point3` + +### *def* `__init__(self, x: float, y: float, z: float)` + + +笛卡尔坐标系中的点。 + +Args: + +- x: x 坐标 + +- y: y 坐标 + +- z: z 坐标 + + + +
+Source code + +```python +def __init__(self, x: float, y: float, z: float): + """ + 笛卡尔坐标系中的点。 + Args: + x: x 坐标 + y: y 坐标 + z: z 坐标 + """ + self.x = x + self.y = y + self.z = z +``` +
+ +### *def* `approx(self, other: 'Point3', epsilon: float = APPROX) -> bool` + + +判断两个点是否近似相等。 + +Args: + +- other: + +- epsilon: + +Return: + +- 是否近似相等 + + + +
+Source code + +```python +def approx(self, other: 'Point3', epsilon: float=APPROX) -> bool: + """ + 判断两个点是否近似相等。 + Args: + other: + epsilon: + + Returns: + 是否近似相等 + """ + return all([abs(self.x - other.x) < epsilon, abs(self.y - other.y) < epsilon, abs(self.z - other.z) < epsilon]) +``` +
+ +### *def* `__str__(self)` + + +
+Source code + +```python +def __str__(self): + return f'Point3({self.x}, {self.y}, {self.z})' +``` +
+ +### `@overload` +### *def* `__add__(self, other: 'Vector3') -> 'Point3'` + + +
+Source code + +```python +@overload +def __add__(self, other: 'Vector3') -> 'Point3': + ... +``` +
+ +### `@overload` +### *def* `__add__(self, other: 'Point3') -> 'Point3'` + + +
+Source code + +```python +@overload +def __add__(self, other: 'Point3') -> 'Point3': + ... +``` +
+ +### *def* `__add__(self, other)` + + +P + V -> P +P + P -> P + +Args: + +- other: + + + +
+Source code + +```python +def __add__(self, other): + """ + P + V -> P + P + P -> P + Args: + other: + Returns: + """ + return Point3(self.x + other.x, self.y + other.y, self.z + other.z) +``` +
+ +### *def* `__eq__(self, other)` + + +判断两个点是否相等。 + +Args: + +- other: + + + +
+Source code + +```python +def __eq__(self, other): + """ + 判断两个点是否相等。 + Args: + other: + Returns: + """ + return approx(self.x, other.x) and approx(self.y, other.y) and approx(self.z, other.z) +``` +
+ +### *def* `__sub__(self, other: 'Point3') -> 'Vector3'` + + +P - P -> V + +P - V -> P 已在 :class:`Vector3` 中实现 + +Args: + +- other: + + + +
+Source code + +```python +def __sub__(self, other: 'Point3') -> 'Vector3': + """ + P - P -> V + + P - V -> P 已在 :class:`Vector3` 中实现 + Args: + other: + Returns: + + """ + from .vector import Vector3 + return Vector3(self.x - other.x, self.y - other.y, self.z - other.z) +``` +
+ diff --git a/docs/en/api/mp_math/segment.md b/docs/en/api/mp_math/segment.md new file mode 100644 index 0000000..1dd8b85 --- /dev/null +++ b/docs/en/api/mp_math/segment.md @@ -0,0 +1,59 @@ +--- +title: mbcp.mp_math.segment +--- +### ***class*** `Segment3` + +### *def* `__init__(self, p1: 'Point3', p2: 'Point3')` + + +三维空间中的线段。 +:param p1: +:param p2: + + + +
+Source code + +```python +def __init__(self, p1: 'Point3', p2: 'Point3'): + """ + 三维空间中的线段。 + :param p1: + :param p2: + """ + self.p1 = p1 + self.p2 = p2 + '方向向量' + self.direction = self.p2 - self.p1 + '长度' + self.length = self.direction.length + '中心点' + self.midpoint = Point3((self.p1.x + self.p2.x) / 2, (self.p1.y + self.p2.y) / 2, (self.p1.z + self.p2.z) / 2) +``` +
+ +### *def* `__repr__(self)` + + +
+Source code + +```python +def __repr__(self): + return f'Segment3({self.p1}, {self.p2})' +``` +
+ +### *def* `__str__(self)` + + +
+Source code + +```python +def __str__(self): + return f'Segment3({self.p1} -> {self.p2})' +``` +
+ diff --git a/docs/en/api/mp_math/utils.md b/docs/en/api/mp_math/utils.md new file mode 100644 index 0000000..b31fd40 --- /dev/null +++ b/docs/en/api/mp_math/utils.md @@ -0,0 +1,220 @@ +--- +title: mbcp.mp_math.utils +--- +### *def* `clamp() -> float` + + +区间截断函数。 + +Args: + +- x: + +- min_: + +- max_: + +Return: + +- 限制后的值 + + + +
+Source code + +```python +def clamp(x: float, min_: float, max_: float) -> float: + """ + 区间截断函数。 + Args: + x: + min_: + max_: + + Returns: + 限制后的值 + """ + return max(min(x, max_), min_) +``` +
+ +### *def* `approx(x: float = 0.0, y: float = APPROX) -> bool` + + +判断两个数是否近似相等。或包装一个实数,用于判断是否近似于0。 + +Args: + +- x: + +- y: + +- epsilon: + +Return: + +- 是否近似相等 + + + +
+Source code + +```python +def approx(x: float, y: float=0.0, epsilon: float=APPROX) -> bool: + """ + 判断两个数是否近似相等。或包装一个实数,用于判断是否近似于0。 + Args: + x: + y: + epsilon: + + Returns: + 是否近似相等 + """ + return abs(x - y) < epsilon +``` +
+ +### *def* `sign(x: float = False) -> str` + + +获取数的符号。 + +Args: + +- x: 数 + +- only_neg: 是否只返回负数的符号 + +Return: + +- 符号 + - "" + + + +
+Source code + +```python +def sign(x: float, only_neg: bool=False) -> str: + """获取数的符号。 + Args: + x: 数 + only_neg: 是否只返回负数的符号 + Returns: + 符号 + - "" + """ + if x > 0: + return '+' if not only_neg else '' + elif x < 0: + return '-' + else: + return '' +``` +
+ +### *def* `sign_format(x: float = False) -> str` + + +格式化符号数 +-1 -> -1 +1 -> +1 +0 -> "" + +Args: + +- x: 数 + +- only_neg: 是否只返回负数的符号 + +Return: + +- 符号 + - "" + + + +
+Source code + +```python +def sign_format(x: float, only_neg: bool=False) -> str: + """格式化符号数 + -1 -> -1 + 1 -> +1 + 0 -> "" + Args: + x: 数 + only_neg: 是否只返回负数的符号 + Returns: + 符号 + - "" + """ + if x > 0: + return f'+{x}' if not only_neg else f'{x}' + elif x < 0: + return f'-{abs(x)}' + else: + return '' +``` +
+ +### ***class*** `Approx` + +### *def* `__init__(self, value: RealNumber)` + + +
+Source code + +```python +def __init__(self, value: RealNumber): + self.value = value +``` +
+ +### *def* `__eq__(self, other)` + + +
+Source code + +```python +def __eq__(self, other): + if isinstance(self.value, (float, int)): + if isinstance(other, (float, int)): + return abs(self.value - other) < APPROX + else: + self.raise_type_error(other) + elif isinstance(self.value, Vector3): + if isinstance(other, (Vector3, Point3, Plane3, Line3)): + return all([approx(self.value.x, other.x), approx(self.value.y, other.y), approx(self.value.z, other.z)]) + else: + self.raise_type_error(other) +``` +
+ +### *def* `raise_type_error(self, other)` + + +
+Source code + +```python +def raise_type_error(self, other): + raise TypeError(f'Unsupported type: {type(self.value)} and {type(other)}') +``` +
+ +### *def* `__ne__(self, other)` + + +
+Source code + +```python +def __ne__(self, other): + return not self.__eq__(other) +``` +
+ diff --git a/docs/en/api/mp_math/vector.md b/docs/en/api/mp_math/vector.md new file mode 100644 index 0000000..a04c352 --- /dev/null +++ b/docs/en/api/mp_math/vector.md @@ -0,0 +1,699 @@ +--- +title: mbcp.mp_math.vector +--- +### ***class*** `Vector3` + +### *def* `__init__(self, x: float, y: float, z: float)` + + +3维向量 + +Args: + +- x: x轴分量 + +- y: y轴分量 + +- z: z轴分量 + + + +
+Source code + +```python +def __init__(self, x: float, y: float, z: float): + """ + 3维向量 + Args: + x: x轴分量 + y: y轴分量 + z: z轴分量 + """ + self.x = x + self.y = y + self.z = z +``` +
+ +### *def* `approx(self, other: 'Vector3', epsilon: float = APPROX) -> bool` + + +判断两个向量是否近似相等。 + +Args: + +- other: + +- epsilon: + +Return: + +- 是否近似相等 + + + +
+Source code + +```python +def approx(self, other: 'Vector3', epsilon: float=APPROX) -> bool: + """ + 判断两个向量是否近似相等。 + Args: + other: + epsilon: + + Returns: + 是否近似相等 + """ + return all([abs(self.x - other.x) < epsilon, abs(self.y - other.y) < epsilon, abs(self.z - other.z) < epsilon]) +``` +
+ +### *def* `cal_angle(self, other: 'Vector3') -> 'AnyAngle'` + + +计算两个向量之间的夹角。 + +Args: + +- other: 另一个向量 + +Return: + +- 夹角 + + + +
+Source code + +```python +def cal_angle(self, other: 'Vector3') -> 'AnyAngle': + """ + 计算两个向量之间的夹角。 + Args: + other: 另一个向量 + Returns: + 夹角 + """ + return AnyAngle(math.acos(self @ other / (self.length * other.length)), is_radian=True) +``` +
+ +### *def* `cross(self, other: 'Vector3') -> 'Vector3'` + + +向量积 叉乘:v1 cross v2 -> v3 + +叉乘为0,则两向量平行。 +其余结果的模为平行四边形的面积。 + + +Args: + +- other: + +Return: + +- 行列式的结果 + + + +
+Source code + +```python +def cross(self, other: 'Vector3') -> 'Vector3': + """ + 向量积 叉乘:v1 cross v2 -> v3 + + 叉乘为0,则两向量平行。 + 其余结果的模为平行四边形的面积。 + + 返回如下行列式的结果: + + ``i j k`` + + ``x1 y1 z1`` + + ``x2 y2 z2`` + + Args: + other: + Returns: + 行列式的结果 + """ + 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* `is_approx_parallel(self, other: 'Vector3', epsilon: float = APPROX) -> bool` + + +判断两个向量是否近似平行。 + +Args: + +- other: 另一个向量 + +- epsilon: 允许的误差 + +Return: + +- 是否近似平行 + + + +
+Source code + +```python +def is_approx_parallel(self, other: 'Vector3', epsilon: float=APPROX) -> bool: + """ + 判断两个向量是否近似平行。 + Args: + other: 另一个向量 + epsilon: 允许的误差 + Returns: + 是否近似平行 + """ + return self.cross(other).length < epsilon +``` +
+ +### *def* `is_parallel(self, other: 'Vector3') -> bool` + + +判断两个向量是否平行。 + +Args: + +- other: 另一个向量 + +Return: + +- 是否平行 + + + +
+Source code + +```python +def is_parallel(self, other: 'Vector3') -> bool: + """ + 判断两个向量是否平行。 + Args: + other: 另一个向量 + Returns: + 是否平行 + """ + return self.cross(other).approx(zero_vector3) +``` +
+ +### *def* `normalize(self)` + + +将向量归一化。 + +自体归一化,不返回值。 + + + +
+Source code + +```python +def normalize(self): + """ + 将向量归一化。 + + 自体归一化,不返回值。 + """ + length = self.length + self.x /= length + self.y /= length + self.z /= length +``` +
+ +### `@property` +### *def* `np_array(self) -> 'np.ndarray'` + + + + + + +
+Source code + +```python +@property +def np_array(self) -> 'np.ndarray': + """ + 返回numpy数组 + Returns: + """ + return np.array([self.x, self.y, self.z]) +``` +
+ +### `@property` +### *def* `length(self) -> float` + + +向量的模。 + +Return: + +- 模 + + + +
+Source code + +```python +@property +def length(self) -> float: + """ + 向量的模。 + Returns: + 模 + """ + return math.sqrt(self.x ** 2 + self.y ** 2 + self.z ** 2) +``` +
+ +### `@property` +### *def* `unit(self) -> 'Vector3'` + + +获取该向量的单位向量。 + +Return: + +- 单位向量 + + + +
+Source code + +```python +@property +def unit(self) -> 'Vector3': + """ + 获取该向量的单位向量。 + Returns: + 单位向量 + """ + return self / self.length +``` +
+ +### *def* `__abs__(self)` + + +
+Source code + +```python +def __abs__(self): + return self.length +``` +
+ +### `@overload` +### *def* `__add__(self, other: 'Vector3') -> 'Vector3'` + + +
+Source code + +```python +@overload +def __add__(self, other: 'Vector3') -> 'Vector3': + ... +``` +
+ +### `@overload` +### *def* `__add__(self, other: 'Point3') -> 'Point3'` + + +
+Source code + +```python +@overload +def __add__(self, other: 'Point3') -> 'Point3': + ... +``` +
+ +### *def* `__add__(self, other)` + + +V + P -> P + +V + V -> V + +Args: + +- other: + + + +
+Source code + +```python +def __add__(self, other): + """ + V + P -> P + + V + V -> V + Args: + other: + Returns: + + """ + if isinstance(other, Vector3): + 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) + else: + raise TypeError(f"unsupported operand type(s) for +: 'Vector3' and '{type(other)}'") +``` +
+ +### *def* `__eq__(self, other)` + + +判断两个向量是否相等。 + +Args: + +- other: + +Return: + +- 是否相等 + + + +
+Source code + +```python +def __eq__(self, other): + """ + 判断两个向量是否相等。 + Args: + other: + Returns: + 是否相等 + """ + return approx(self.x, other.x) and approx(self.y, other.y) and approx(self.z, other.z) +``` +
+ +### *def* `__radd__(self, other: 'Point3') -> 'Point3'` + + +P + V -> P + +别去点那边实现了。 +:param other: +:return: + + + +
+Source code + +```python +def __radd__(self, other: 'Point3') -> 'Point3': + """ + P + V -> P + + 别去点那边实现了。 + :param other: + :return: + """ + return Point3(self.x + other.x, self.y + other.y, self.z + other.z) +``` +
+ +### `@overload` +### *def* `__sub__(self, other: 'Vector3') -> 'Vector3'` + + +
+Source code + +```python +@overload +def __sub__(self, other: 'Vector3') -> 'Vector3': + ... +``` +
+ +### `@overload` +### *def* `__sub__(self, other: 'Point3') -> 'Point3'` + + +
+Source code + +```python +@overload +def __sub__(self, other: 'Point3') -> 'Point3': + ... +``` +
+ +### *def* `__sub__(self, other)` + + +V - P -> P + +V - V -> V + +Args: + +- other: + + + +
+Source code + +```python +def __sub__(self, other): + """ + V - P -> P + + V - V -> V + Args: + other: + Returns: + """ + if isinstance(other, Vector3): + 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) + else: + raise TypeError(f'unsupported operand type(s) for -: "Vector3" and "{type(other)}"') +``` +
+ +### *def* `__rsub__(self, other: 'Point3')` + + +P - V -> P + +Args: + +- other: + + + +
+Source code + +```python +def __rsub__(self, other: 'Point3'): + """ + P - V -> P + Args: + other: + Returns: + + """ + if isinstance(other, Point3): + 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: 'Vector3') -> 'Vector3'` + + +
+Source code + +```python +@overload +def __mul__(self, other: 'Vector3') -> 'Vector3': + ... +``` +
+ +### `@overload` +### *def* `__mul__(self, other: RealNumber) -> 'Vector3'` + + +
+Source code + +```python +@overload +def __mul__(self, other: RealNumber) -> 'Vector3': + ... +``` +
+ +### *def* `__mul__(self, other: 'int | float | Vector3') -> 'Vector3'` + + +数组运算 非点乘。点乘使用@,叉乘使用cross。 + +Args: + +- other: + + + +
+Source code + +```python +def __mul__(self, other: 'int | float | Vector3') -> 'Vector3': + """ + 数组运算 非点乘。点乘使用@,叉乘使用cross。 + Args: + other: + + Returns: + """ + if isinstance(other, Vector3): + return Vector3(self.x * other.x, self.y * other.y, self.z * other.z) + elif isinstance(other, (float, int)): + return Vector3(self.x * other, self.y * other, self.z * other) + else: + raise TypeError(f"unsupported operand type(s) for *: 'Vector3' and '{type(other)}'") +``` +
+ +### *def* `__rmul__(self, other: 'RealNumber') -> 'Vector3'` + + +
+Source code + +```python +def __rmul__(self, other: 'RealNumber') -> 'Vector3': + return self.__mul__(other) +``` +
+ +### *def* `__matmul__(self, other: 'Vector3') -> 'RealNumber'` + + +点乘。 + +Args: + +- other: + + + +
+Source code + +```python +def __matmul__(self, other: 'Vector3') -> 'RealNumber': + """ + 点乘。 + Args: + other: + Returns: + """ + return self.x * other.x + self.y * other.y + self.z * other.z +``` +
+ +### *def* `__truediv__(self, other: RealNumber) -> 'Vector3'` + + +
+Source code + +```python +def __truediv__(self, other: RealNumber) -> 'Vector3': + return Vector3(self.x / other, self.y / other, self.z / other) +``` +
+ +### *def* `__neg__(self)` + + +
+Source code + +```python +def __neg__(self): + return Vector3(-self.x, -self.y, -self.z) +``` +
+ +### *def* `__repr__(self)` + + +
+Source code + +```python +def __repr__(self): + return f'Vector3({self.x}, {self.y}, {self.z})' +``` +
+ +### *def* `__str__(self)` + + +
+Source code + +```python +def __str__(self): + return f'Vector3({self.x}, {self.y}, {self.z})' +``` +
+ +### ***var*** `zero_vector3 = Vector3(0, 0, 0)` + +### ***var*** `x_axis = Vector3(1, 0, 0)` + +### ***var*** `y_axis = Vector3(0, 1, 0)` + +### ***var*** `z_axis = Vector3(0, 0, 1)` + diff --git a/docs/en/api/particle/index.md b/docs/en/api/particle/index.md new file mode 100644 index 0000000..4b514d5 --- /dev/null +++ b/docs/en/api/particle/index.md @@ -0,0 +1,3 @@ +--- +title: mbcp.particle +--- diff --git a/docs/en/api/presets/index.md b/docs/en/api/presets/index.md new file mode 100644 index 0000000..472366f --- /dev/null +++ b/docs/en/api/presets/index.md @@ -0,0 +1,3 @@ +--- +title: mbcp.presets +--- diff --git a/docs/en/api/presets/model/index.md b/docs/en/api/presets/model/index.md new file mode 100644 index 0000000..050500b --- /dev/null +++ b/docs/en/api/presets/model/index.md @@ -0,0 +1,48 @@ +--- +title: mbcp.presets.model +--- +### ***class*** `GeometricModels` + +### `@staticmethod` +### *def* `sphere(radius: float, density: float)` + + +生成球体上的点集。 + +Args: + +- radius: + +- density: + +Return: + +- List[Point3]: 球体上的点集。 + + + +
+Source code + +```python +@staticmethod +def sphere(radius: float, density: float): + """ + 生成球体上的点集。 + Args: + radius: + density: + Returns: + List[Point3]: 球体上的点集。 + """ + area = 4 * np.pi * radius ** 2 + num = int(area * density) + phi_list = np.arccos([clamp(-1 + (2.0 * _ - 1.0) / num, -1, 1) for _ in range(num)]) + theta_list = np.sqrt(num * np.pi) * phi_list + x_array = radius * np.sin(phi_list) * np.cos(theta_list) + y_array = radius * np.sin(phi_list) * np.sin(theta_list) + z_array = radius * np.cos(phi_list) + return [Point3(x_array[i], y_array[i], z_array[i]) for i in range(num)] +``` +
+ diff --git a/docs/guide/index.md b/docs/guide/index.md new file mode 100644 index 0000000..c888f8c --- /dev/null +++ b/docs/guide/index.md @@ -0,0 +1 @@ +# 开始不了一点 \ No newline at end of file diff --git a/docs/index.md b/docs/index.md index a2f37f2..b0ccbac 100644 --- a/docs/index.md +++ b/docs/index.md @@ -9,7 +9,7 @@ hero: actions: - theme: brand text: 快速开始 - link: md-ex + link: guide/ - theme: alt text: API文档 link: api/ diff --git a/docs/ja/api/index.md b/docs/ja/api/index.md new file mode 100644 index 0000000..6d251e8 --- /dev/null +++ b/docs/ja/api/index.md @@ -0,0 +1,3 @@ +--- +title: mbcp +--- diff --git a/docs/ja/api/mp_math/angle.md b/docs/ja/api/mp_math/angle.md new file mode 100644 index 0000000..10a0fae --- /dev/null +++ b/docs/ja/api/mp_math/angle.md @@ -0,0 +1,449 @@ +--- +title: mbcp.mp_math.angle +--- +### ***class*** `Angle` + +### ***class*** `AnyAngle` + +### *def* `__init__(self, value: float, is_radian: bool = False)` + + +任意角度。 + +引数: + +- value: 角度或弧度值 + +- is_radian: 是否为弧度,默认为否 + + + +
+ソースコード + +```python +def __init__(self, value: float, is_radian: bool=False): + """ + 任意角度。 + Args: + value: 角度或弧度值 + is_radian: 是否为弧度,默认为否 + """ + if is_radian: + self.radian = value + else: + self.radian = value * PI / 180 +``` +
+ +### `@property` +### *def* `complementary(self) -> 'AnyAngle'` + + +余角:两角的和为90°。 + +戻り値: + +- 余角 + + + +
+ソースコード + +```python +@property +def complementary(self) -> 'AnyAngle': + """ + 余角:两角的和为90°。 + Returns: + 余角 + """ + return AnyAngle(PI / 2 - self.minimum_positive.radian, is_radian=True) +``` +
+ +### `@property` +### *def* `supplementary(self) -> 'AnyAngle'` + + +补角:两角的和为180°。 + +戻り値: + +- 补角 + + + +
+ソースコード + +```python +@property +def supplementary(self) -> 'AnyAngle': + """ + 补角:两角的和为180°。 + Returns: + 补角 + """ + return AnyAngle(PI - self.minimum_positive.radian, is_radian=True) +``` +
+ +### `@property` +### *def* `degree(self) -> float` + + +角度。 + +戻り値: + +- 弧度 + + + +
+ソースコード + +```python +@property +def degree(self) -> float: + """ + 角度。 + Returns: + 弧度 + """ + return self.radian * 180 / PI +``` +
+ +### `@property` +### *def* `minimum_positive(self) -> 'AnyAngle'` + + +最小正角。 + +戻り値: + +- 最小正角度 + + + +
+ソースコード + +```python +@property +def minimum_positive(self) -> 'AnyAngle': + """ + 最小正角。 + Returns: + 最小正角度 + """ + return AnyAngle(self.radian % (2 * PI)) +``` +
+ +### `@property` +### *def* `maximum_negative(self) -> 'AnyAngle'` + + +最大负角。 + +戻り値: + +- 最大负角度 + + + +
+ソースコード + +```python +@property +def maximum_negative(self) -> 'AnyAngle': + """ + 最大负角。 + Returns: + 最大负角度 + """ + return AnyAngle(-self.radian % (2 * PI), is_radian=True) +``` +
+ +### `@property` +### *def* `sin(self) -> float` + + +正弦值。 + +戻り値: + +- 正弦值 + + + +
+ソースコード + +```python +@property +def sin(self) -> float: + """ + 正弦值。 + Returns: + 正弦值 + """ + return math.sin(self.radian) +``` +
+ +### `@property` +### *def* `cos(self) -> float` + + +余弦值。 + +戻り値: + +- 余弦值 + + + +
+ソースコード + +```python +@property +def cos(self) -> float: + """ + 余弦值。 + Returns: + 余弦值 + """ + return math.cos(self.radian) +``` +
+ +### `@property` +### *def* `tan(self) -> float` + + +正切值。 + +戻り値: + +- 正切值 + + + +
+ソースコード + +```python +@property +def tan(self) -> float: + """ + 正切值。 + Returns: + 正切值 + """ + return math.tan(self.radian) +``` +
+ +### `@property` +### *def* `cot(self) -> float` + + +余切值。 + +戻り値: + +- 余切值 + + + +
+ソースコード + +```python +@property +def cot(self) -> float: + """ + 余切值。 + Returns: + 余切值 + """ + return 1 / math.tan(self.radian) +``` +
+ +### `@property` +### *def* `sec(self) -> float` + + +正割值。 + +戻り値: + +- 正割值 + + + +
+ソースコード + +```python +@property +def sec(self) -> float: + """ + 正割值。 + Returns: + 正割值 + """ + return 1 / math.cos(self.radian) +``` +
+ +### `@property` +### *def* `csc(self) -> float` + + +余割值。 + +戻り値: + +- 余割值 + + + +
+ソースコード + +```python +@property +def csc(self) -> float: + """ + 余割值。 + Returns: + 余割值 + """ + return 1 / math.sin(self.radian) +``` +
+ +### *def* `__add__(self, other: 'AnyAngle') -> 'AnyAngle'` + + +
+ソースコード + +```python +def __add__(self, other: 'AnyAngle') -> 'AnyAngle': + return AnyAngle(self.radian + other.radian, is_radian=True) +``` +
+ +### *def* `__eq__(self, other)` + + +
+ソースコード + +```python +def __eq__(self, other): + return approx(self.radian, other.radian) +``` +
+ +### *def* `__sub__(self, other: 'AnyAngle') -> 'AnyAngle'` + + +
+ソースコード + +```python +def __sub__(self, other: 'AnyAngle') -> 'AnyAngle': + return AnyAngle(self.radian - other.radian, is_radian=True) +``` +
+ +### *def* `__mul__(self, other: float) -> 'AnyAngle'` + + +
+ソースコード + +```python +def __mul__(self, other: float) -> 'AnyAngle': + return AnyAngle(self.radian * other, is_radian=True) +``` +
+ +### *def* `__repr__(self)` + + +
+ソースコード + +```python +def __repr__(self): + return f'AnyAngle({self.radian}, is_radian=True)' +``` +
+ +### *def* `__str__(self)` + + +
+ソースコード + +```python +def __str__(self): + return f'AnyAngle({self.degree}° or {self.radian} rad)' +``` +
+ +### `@overload` +### *def* `__truediv__(self, other: float) -> 'AnyAngle'` + + +
+ソースコード + +```python +@overload +def __truediv__(self, other: float) -> 'AnyAngle': + ... +``` +
+ +### `@overload` +### *def* `__truediv__(self, other: 'AnyAngle') -> float` + + +
+ソースコード + +```python +@overload +def __truediv__(self, other: 'AnyAngle') -> float: + ... +``` +
+ +### *def* `__truediv__(self, other)` + + +
+ソースコード + +```python +def __truediv__(self, other): + if isinstance(other, AnyAngle): + return self.radian / other.radian + return AnyAngle(self.radian / other, is_radian=True) +``` +
+ diff --git a/docs/ja/api/mp_math/const.md b/docs/ja/api/mp_math/const.md new file mode 100644 index 0000000..888edf3 --- /dev/null +++ b/docs/ja/api/mp_math/const.md @@ -0,0 +1,15 @@ +--- +title: mbcp.mp_math.const +--- +### ***var*** `PI = math.pi` + +### ***var*** `E = math.e` + +### ***var*** `GOLDEN_RATIO = (1 + math.sqrt(5)) / 2` + +### ***var*** `GAMMA = 0.5772156649015329` + +### ***var*** `EPSILON = 0.0001` + +### ***var*** `APPROX = 0.001` + diff --git a/docs/ja/api/mp_math/equation.md b/docs/ja/api/mp_math/equation.md new file mode 100644 index 0000000..e7fe251 --- /dev/null +++ b/docs/ja/api/mp_math/equation.md @@ -0,0 +1,177 @@ +--- +title: mbcp.mp_math.equation +--- +### *def* `get_partial_derivative_func(func: MultiVarsFunc = EPSILON) -> MultiVarsFunc` + + +求N元函数一阶偏导函数。这玩意不太稳定,慎用。 + +引数: + +- func: 函数 + +- var: 变量位置,可为整数(一阶偏导)或整数元组(高阶偏导) + +- epsilon: 偏移量 + +戻り値: + +- 偏导函数 + +例外: + +- ValueError 无效变量类型 + + + +
+ソースコード + +```python +def get_partial_derivative_func(func: MultiVarsFunc, var: int | tuple[int, ...], epsilon: Number=EPSILON) -> MultiVarsFunc: + """ + 求N元函数一阶偏导函数。这玩意不太稳定,慎用。 + Args: + func: 函数 + var: 变量位置,可为整数(一阶偏导)或整数元组(高阶偏导) + epsilon: 偏移量 + Returns: + 偏导函数 + Raises: + ValueError: 无效变量类型 + """ + if isinstance(var, int): + + def partial_derivative_func(*args: Var) -> Var: + args_list_plus = list(args) + args_list_plus[var] += epsilon + args_list_minus = list(args) + args_list_minus[var] -= epsilon + return (func(*args_list_plus) - func(*args_list_minus)) / (2 * epsilon) + return partial_derivative_func + elif isinstance(var, tuple): + + def high_order_partial_derivative_func(*args: Var) -> Var: + result_func = func + for v in var: + result_func = get_partial_derivative_func(result_func, v, epsilon) + return result_func(*args) + return high_order_partial_derivative_func + else: + raise ValueError('Invalid var type') +``` +
+ +### *def* `partial_derivative_func() -> Var` + + +
+ソースコード + +```python +def partial_derivative_func(*args: Var) -> Var: + args_list_plus = list(args) + args_list_plus[var] += epsilon + args_list_minus = list(args) + args_list_minus[var] -= epsilon + return (func(*args_list_plus) - func(*args_list_minus)) / (2 * epsilon) +``` +
+ +### *def* `high_order_partial_derivative_func() -> Var` + + +
+ソースコード + +```python +def high_order_partial_derivative_func(*args: Var) -> Var: + result_func = func + for v in var: + result_func = get_partial_derivative_func(result_func, v, epsilon) + return result_func(*args) +``` +
+ +### ***class*** `CurveEquation` + +### *def* `__init__(self, x_func: OneVarFunc, y_func: OneVarFunc, z_func: OneVarFunc)` + + +曲线方程。 + +引数: + +- x_func: x函数 + +- y_func: y函数 + +- z_func: z函数 + + + +
+ソースコード + +```python +def __init__(self, x_func: OneVarFunc, y_func: OneVarFunc, z_func: OneVarFunc): + """ + 曲线方程。 + Args: + x_func: x函数 + y_func: y函数 + z_func: z函数 + """ + self.x_func = x_func + self.y_func = y_func + self.z_func = z_func +``` +
+ +### *def* `__call__(self) -> Point3 | tuple[Point3, ...]` + + +计算曲线上的点。 + +引数: + +- *t: + +- 参数: + + + +
+ソースコード + +```python +def __call__(self, *t: Var) -> Point3 | tuple[Point3, ...]: + """ + 计算曲线上的点。 + Args: + *t: + 参数 + Returns: + + """ + if len(t) == 1: + return Point3(self.x_func(t[0]), self.y_func(t[0]), self.z_func(t[0])) + else: + return tuple([Point3(x, y, z) for x, y, z in zip(self.x_func(t), self.y_func(t), self.z_func(t))]) +``` +
+ +### *def* `__str__(self)` + + +
+ソースコード + +```python +def __str__(self): + return 'CurveEquation()' +``` +
+ +### ***var*** `result_func = get_partial_derivative_func(result_func, v, epsilon)` + diff --git a/docs/ja/api/mp_math/index.md b/docs/ja/api/mp_math/index.md new file mode 100644 index 0000000..6e3261c --- /dev/null +++ b/docs/ja/api/mp_math/index.md @@ -0,0 +1,3 @@ +--- +title: mbcp.mp_math +--- diff --git a/docs/ja/api/mp_math/line.md b/docs/ja/api/mp_math/line.md new file mode 100644 index 0000000..58fb50b --- /dev/null +++ b/docs/ja/api/mp_math/line.md @@ -0,0 +1,622 @@ +--- +title: mbcp.mp_math.line +--- +### ***class*** `Line3` + +### *def* `__init__(self, point: 'Point3', direction: 'Vector3')` + + +三维空间中的直线。由一个点和一个方向向量确定。 + +引数: + +- point: 直线上的一点 + +- direction: 直线的方向向量 + + + +
+ソースコード + +```python +def __init__(self, point: 'Point3', direction: 'Vector3'): + """ + 三维空间中的直线。由一个点和一个方向向量确定。 + Args: + point: 直线上的一点 + direction: 直线的方向向量 + """ + self.point = point + self.direction = direction +``` +
+ +### *def* `approx(self, other: 'Line3', epsilon: float = APPROX) -> bool` + + +判断两条直线是否近似相等。 + +引数: + +- other: 另一条直线 + +- epsilon: 误差 + +戻り値: + +- 是否近似相等 + + + +
+ソースコード + +```python +def approx(self, other: 'Line3', epsilon: float=APPROX) -> bool: + """ + 判断两条直线是否近似相等。 + Args: + other: 另一条直线 + epsilon: 误差 + Returns: + 是否近似相等 + """ + return self.is_approx_parallel(other, epsilon) and (self.point - other.point).is_approx_parallel(self.direction, epsilon) +``` +
+ +### *def* `cal_angle(self, other: 'Line3') -> 'AnyAngle'` + + +计算直线和直线之间的夹角。 + +引数: + +- other: 另一条直线 + +戻り値: + +- 夹角弧度 + +例外: + +- TypeError 不支持的类型 + + + +
+ソースコード + +```python +def cal_angle(self, other: 'Line3') -> 'AnyAngle': + """ + 计算直线和直线之间的夹角。 + Args: + other: 另一条直线 + Returns: + 夹角弧度 + Raises: + TypeError: 不支持的类型 + """ + return self.direction.cal_angle(other.direction) +``` +
+ +### *def* `cal_distance(self, other: 'Line3 | Point3') -> float` + + +计算直线和直线或点之间的距离。 + +引数: + +- other: 平行直线或点 + +戻り値: + +- 距离 + +例外: + +- TypeError 不支持的类型 + + + +
+ソースコード + +```python +def cal_distance(self, other: 'Line3 | Point3') -> float: + """ + 计算直线和直线或点之间的距离。 + Args: + other: 平行直线或点 + + Returns: + 距离 + Raises: + TypeError: 不支持的类型 + """ + if isinstance(other, Line3): + if self == other: + return 0 + elif self.is_parallel(other): + return (other.point - self.point).cross(self.direction).length / self.direction.length + elif not self.is_coplanar(other): + return abs(self.direction.cross(other.direction) @ (self.point - other.point) / self.direction.cross(other.direction).length) + else: + return 0 + elif isinstance(other, Point3): + return (other - self.point).cross(self.direction).length / self.direction.length + else: + raise TypeError('Unsupported type.') +``` +
+ +### *def* `cal_intersection(self, other: 'Line3') -> 'Point3'` + + +计算两条直线的交点。 + +引数: + +- other: 另一条直线 + +戻り値: + +- 交点 + +例外: + +- ValueError 直线平行 + +- ValueError 直线不共面 + + + +
+ソースコード + +```python +def cal_intersection(self, other: 'Line3') -> 'Point3': + """ + 计算两条直线的交点。 + Args: + other: 另一条直线 + Returns: + 交点 + Raises: + ValueError: 直线平行 + ValueError: 直线不共面 + """ + if self.is_parallel(other): + raise ValueError('Lines are parallel and do not intersect.') + if not self.is_coplanar(other): + raise ValueError('Lines are not coplanar and do not intersect.') + return self.point + self.direction.cross(other.direction) @ other.direction.cross(self.point - other.point) / self.direction.cross(other.direction).length ** 2 * self.direction +``` +
+ +### *def* `cal_perpendicular(self, point: 'Point3') -> 'Line3'` + + +计算直线经过指定点p的垂线。 + +引数: + +- point: 指定点 + +戻り値: + +- 垂线 + + + +
+ソースコード + +```python +def cal_perpendicular(self, point: 'Point3') -> 'Line3': + """ + 计算直线经过指定点p的垂线。 + Args: + point: 指定点 + Returns: + 垂线 + """ + return Line3(point, self.direction.cross(point - self.point)) +``` +
+ +### *def* `get_point(self, t: RealNumber) -> 'Point3'` + + +获取直线上的点。同一条直线,但起始点和方向向量不同,则同一个t对应的点不同。 + +引数: + +- t: 参数t + +戻り値: + +- 点 + + + +
+ソースコード + +```python +def get_point(self, t: RealNumber) -> 'Point3': + """ + 获取直线上的点。同一条直线,但起始点和方向向量不同,则同一个t对应的点不同。 + Args: + t: 参数t + Returns: + 点 + """ + return self.point + t * self.direction +``` +
+ +### *def* `get_parametric_equations(self) -> tuple[OneSingleVarFunc, OneSingleVarFunc, OneSingleVarFunc]` + + +获取直线的参数方程。 + +戻り値: + +- x(t), y(t), z(t) + + + +
+ソースコード + +```python +def get_parametric_equations(self) -> tuple[OneSingleVarFunc, OneSingleVarFunc, OneSingleVarFunc]: + """ + 获取直线的参数方程。 + Returns: + x(t), y(t), z(t) + """ + return (lambda t: self.point.x + self.direction.x * t, lambda t: self.point.y + self.direction.y * t, lambda t: self.point.z + self.direction.z * t) +``` +
+ +### *def* `is_approx_parallel(self, other: 'Line3', epsilon: float = 1e-06) -> bool` + + +判断两条直线是否近似平行。 + +引数: + +- other: 另一条直线 + +- epsilon: 误差 + +戻り値: + +- 是否近似平行 + + + +
+ソースコード + +```python +def is_approx_parallel(self, other: 'Line3', epsilon: float=1e-06) -> bool: + """ + 判断两条直线是否近似平行。 + Args: + other: 另一条直线 + epsilon: 误差 + Returns: + 是否近似平行 + """ + return self.direction.is_approx_parallel(other.direction, epsilon) +``` +
+ +### *def* `is_parallel(self, other: 'Line3') -> bool` + + +判断两条直线是否平行。 + +引数: + +- other: 另一条直线 + +戻り値: + +- 是否平行 + + + +
+ソースコード + +```python +def is_parallel(self, other: 'Line3') -> bool: + """ + 判断两条直线是否平行。 + Args: + other: 另一条直线 + Returns: + 是否平行 + """ + return self.direction.is_parallel(other.direction) +``` +
+ +### *def* `is_collinear(self, other: 'Line3') -> bool` + + +判断两条直线是否共线。 + +引数: + +- other: 另一条直线 + +戻り値: + +- 是否共线 + + + +
+ソースコード + +```python +def is_collinear(self, other: 'Line3') -> bool: + """ + 判断两条直线是否共线。 + Args: + other: 另一条直线 + Returns: + 是否共线 + """ + return self.is_parallel(other) and (self.point - other.point).is_parallel(self.direction) +``` +
+ +### *def* `is_point_on(self, point: 'Point3') -> bool` + + +判断点是否在直线上。 + +引数: + +- point: 点 + +戻り値: + +- 是否在直线上 + + + +
+ソースコード + +```python +def is_point_on(self, point: 'Point3') -> bool: + """ + 判断点是否在直线上。 + Args: + point: 点 + Returns: + 是否在直线上 + """ + return (point - self.point).is_parallel(self.direction) +``` +
+ +### *def* `is_coplanar(self, other: 'Line3') -> bool` + + +判断两条直线是否共面。 +充要条件:两直线方向向量的叉乘与两直线上任意一点的向量的点积为0。 + +引数: + +- other: 另一条直线 + +戻り値: + +- 是否共面 + + + +
+ソースコード + +```python +def is_coplanar(self, other: 'Line3') -> bool: + """ + 判断两条直线是否共面。 + 充要条件:两直线方向向量的叉乘与两直线上任意一点的向量的点积为0。 + Args: + other: 另一条直线 + Returns: + 是否共面 + """ + return self.direction.cross(other.direction) @ (self.point - other.point) == 0 +``` +
+ +### *def* `simplify(self)` + + +简化直线方程,等价相等。 +自体简化,不返回值。 + +按照可行性一次对x y z 化 0 处理,并对向量单位化 + + + +
+ソースコード + +```python +def simplify(self): + """ + 简化直线方程,等价相等。 + 自体简化,不返回值。 + + 按照可行性一次对x y z 化 0 处理,并对向量单位化 + """ + self.direction.normalize() + if self.direction.x == 0: + self.point.x = 0 + if self.direction.y == 0: + self.point.y = 0 + if self.direction.z == 0: + self.point.z = 0 +``` +
+ +### `@classmethod` +### *def* `from_two_points(cls, p1: 'Point3', p2: 'Point3') -> 'Line3'` + + +工厂函数 由两点构造直线。 + +引数: + +- p1: 点1 + +- p2: 点2 + +戻り値: + +- 直线 + + + +
+ソースコード + +```python +@classmethod +def from_two_points(cls, p1: 'Point3', p2: 'Point3') -> 'Line3': + """ + 工厂函数 由两点构造直线。 + Args: + p1: 点1 + p2: 点2 + Returns: + 直线 + """ + direction = p2 - p1 + return cls(p1, direction) +``` +
+ +### *def* `__and__(self, other: 'Line3') -> 'Line3 | Point3 | None'` + + +计算两条直线点集合的交集。重合线返回自身,平行线返回None,交线返回交点。 + +引数: + +- other: 另一条直线 + +戻り値: + +- 交点 + + + +
+ソースコード + +```python +def __and__(self, other: 'Line3') -> 'Line3 | Point3 | None': + """ + 计算两条直线点集合的交集。重合线返回自身,平行线返回None,交线返回交点。 + Args: + other: 另一条直线 + Returns: + 交点 + """ + if self.is_collinear(other): + return self + elif self.is_parallel(other) or not self.is_coplanar(other): + return None + else: + return self.cal_intersection(other) +``` +
+ +### *def* `__eq__(self, other) -> bool` + + +判断两条直线是否等价。 + +v1 // v2 ∧ (p1 - p2) // v1 + +引数: + +- other: + + + +
+ソースコード + +```python +def __eq__(self, other) -> bool: + """ + 判断两条直线是否等价。 + + v1 // v2 ∧ (p1 - p2) // v1 + Args: + other: + + Returns: + + """ + return self.direction.is_parallel(other.direction) and (self.point - other.point).is_parallel(self.direction) +``` +
+ +### *def* `__str__(self)` + + + + + + +
+ソースコード + +```python +def __str__(self): + """ + 返回点向式(x-x0) + Returns: + + """ + s = 'Line3: ' + if self.direction.x != 0: + s += f'(x{sign_format(-self.point.x)})/{self.direction.x}' + if self.direction.y != 0: + s += f' = (y{sign_format(-self.point.y)})/{self.direction.y}' + if self.direction.z != 0: + s += f' = (z{sign_format(-self.point.z)})/{self.direction.z}' + return s +``` +
+ +### *def* `__repr__(self)` + + +
+ソースコード + +```python +def __repr__(self): + return f'Line3({self.point}, {self.direction})' +``` +
+ diff --git a/docs/ja/api/mp_math/mp_math_typing.md b/docs/ja/api/mp_math/mp_math_typing.md new file mode 100644 index 0000000..b166130 --- /dev/null +++ b/docs/ja/api/mp_math/mp_math_typing.md @@ -0,0 +1,37 @@ +--- +title: mbcp.mp_math.mp_math_typing +--- +### ***var*** `RealNumber: TypeAlias = int | float` + +### ***var*** `Number: TypeAlias = RealNumber | complex` + +### ***var*** `SingleVar = TypeVar('SingleVar', bound=Number)` + +### ***var*** `ArrayVar = TypeVar('ArrayVar', bound=Iterable[Number])` + +### ***var*** `Var: TypeAlias = SingleVar | ArrayVar` + +### ***var*** `OneSingleVarFunc: TypeAlias = Callable[[SingleVar], SingleVar]` + +### ***var*** `OneArrayFunc: TypeAlias = Callable[[ArrayVar], ArrayVar]` + +### ***var*** `OneVarFunc: TypeAlias = OneSingleVarFunc | OneArrayFunc` + +### ***var*** `TwoSingleVarsFunc: TypeAlias = Callable[[SingleVar, SingleVar], SingleVar]` + +### ***var*** `TwoArraysFunc: TypeAlias = Callable[[ArrayVar, ArrayVar], ArrayVar]` + +### ***var*** `TwoVarsFunc: TypeAlias = TwoSingleVarsFunc | TwoArraysFunc` + +### ***var*** `ThreeSingleVarsFunc: TypeAlias = Callable[[SingleVar, SingleVar, SingleVar], SingleVar]` + +### ***var*** `ThreeArraysFunc: TypeAlias = Callable[[ArrayVar, ArrayVar, ArrayVar], ArrayVar]` + +### ***var*** `ThreeVarsFunc: TypeAlias = ThreeSingleVarsFunc | ThreeArraysFunc` + +### ***var*** `MultiSingleVarsFunc: TypeAlias = Callable[..., SingleVar]` + +### ***var*** `MultiArraysFunc: TypeAlias = Callable[..., ArrayVar]` + +### ***var*** `MultiVarsFunc: TypeAlias = MultiSingleVarsFunc | MultiArraysFunc` + diff --git a/docs/ja/api/mp_math/plane.md b/docs/ja/api/mp_math/plane.md new file mode 100644 index 0000000..30425bf --- /dev/null +++ b/docs/ja/api/mp_math/plane.md @@ -0,0 +1,648 @@ +--- +title: mbcp.mp_math.plane +--- +### ***class*** `Plane3` + +### *def* `__init__(self, a: float, b: float, c: float, d: float)` + + +平面方程:ax + by + cz + d = 0 + +引数: + +- a: + +- b: + +- c: + +- d: + + + +
+ソースコード + +```python +def __init__(self, a: float, b: float, c: float, d: float): + """ + 平面方程:ax + by + cz + d = 0 + Args: + a: + b: + c: + d: + """ + self.a = a + self.b = b + self.c = c + self.d = d +``` +
+ +### *def* `approx(self, other: 'Plane3') -> bool` + + +判断两个平面是否近似相等。 + +引数: + +- other: + +戻り値: + +- 是否近似相等 + + + +
+ソースコード + +```python +def approx(self, other: 'Plane3') -> bool: + """ + 判断两个平面是否近似相等。 + Args: + other: + + Returns: + 是否近似相等 + """ + a = 3 + if self.a != 0: + k = other.a / self.a + return approx(other.b, self.b * k) and approx(other.c, self.c * k) and approx(other.d, self.d * k) + elif self.b != 0: + k = other.b / self.b + return approx(other.a, self.a * k) and approx(other.c, self.c * k) and approx(other.d, self.d * k) + elif self.c != 0: + k = other.c / self.c + return approx(other.a, self.a * k) and approx(other.b, self.b * k) and approx(other.d, self.d * k) + else: + return False +``` +
+ +### *def* `cal_angle(self, other: 'Line3 | Plane3') -> 'AnyAngle'` + + +计算平面与平面之间的夹角。 + +引数: + +- other: 另一个平面 + +戻り値: + +- 夹角弧度 + +例外: + +- TypeError 不支持的类型 + + + +
+ソースコード + +```python +def cal_angle(self, other: 'Line3 | Plane3') -> 'AnyAngle': + """ + 计算平面与平面之间的夹角。 + Args: + other: 另一个平面 + Returns: + 夹角弧度 + Raises: + TypeError: 不支持的类型 + """ + if isinstance(other, Line3): + return self.normal.cal_angle(other.direction).complementary + elif isinstance(other, Plane3): + return AnyAngle(math.acos(self.normal @ other.normal / (self.normal.length * other.normal.length)), is_radian=True) + else: + raise TypeError(f'Unsupported type: {type(other)}') +``` +
+ +### *def* `cal_distance(self, other: 'Plane3 | Point3') -> float` + + +计算平面与平面或点之间的距离。 + +引数: + +- other: 另一个平面或点 + +戻り値: + +- 距离 + +例外: + +- TypeError 不支持的类型 + + + +
+ソースコード + +```python +def cal_distance(self, other: 'Plane3 | Point3') -> float: + """ + 计算平面与平面或点之间的距离。 + Args: + other: 另一个平面或点 + Returns: + 距离 + Raises: + TypeError: 不支持的类型 + """ + if isinstance(other, Plane3): + return 0 + elif isinstance(other, Point3): + return abs(self.a * other.x + self.b * other.y + self.c * other.z + self.d) / (self.a ** 2 + self.b ** 2 + self.c ** 2) ** 0.5 + else: + raise TypeError(f'Unsupported type: {type(other)}') +``` +
+ +### *def* `cal_intersection_line3(self, other: 'Plane3') -> 'Line3'` + + +计算两平面的交线。该方法有问题,待修复。 + +引数: + +- other: 另一个平面 + +戻り値: + +- 交线 + + + +
+ソースコード + +```python +def cal_intersection_line3(self, other: 'Plane3') -> 'Line3': + """ + 计算两平面的交线。该方法有问题,待修复。 + Args: + other: 另一个平面 + Returns: + 交线 + Raises: + """ + if self.normal.is_parallel(other.normal): + raise ValueError('Planes are parallel and have no intersection.') + direction = self.normal.cross(other.normal) + x, y, z = (0, 0, 0) + if self.a != 0 and other.a != 0: + A = np.array([[self.b, self.c], [other.b, other.c]]) + B = np.array([-self.d, -other.d]) + y, z = np.linalg.solve(A, B) + elif self.b != 0 and other.b != 0: + A = np.array([[self.a, self.c], [other.a, other.c]]) + B = np.array([-self.d, -other.d]) + x, z = np.linalg.solve(A, B) + elif self.c != 0 and other.c != 0: + A = np.array([[self.a, self.b], [other.a, other.b]]) + B = np.array([-self.d, -other.d]) + x, y = np.linalg.solve(A, B) + return Line3(Point3(x, y, z), direction) +``` +
+ +### *def* `cal_intersection_point3(self, other: 'Line3') -> 'Point3'` + + +计算平面与直线的交点。 + +引数: + +- other: 不与平面平行或在平面上的直线 + +戻り値: + +- 交点 + +例外: + +- ValueError 平面与直线平行或重合 + + + +
+ソースコード + +```python +def cal_intersection_point3(self, other: 'Line3') -> 'Point3': + """ + 计算平面与直线的交点。 + Args: + other: 不与平面平行或在平面上的直线 + Returns: + 交点 + Raises: + ValueError: 平面与直线平行或重合 + """ + if self.normal @ other.direction == 0: + raise ValueError('The plane and the line are parallel or coincident.') + x, y, z = other.get_parametric_equations() + t = -(self.a * other.point.x + self.b * other.point.y + self.c * other.point.z + self.d) / (self.a * other.direction.x + self.b * other.direction.y + self.c * other.direction.z) + return Point3(x(t), y(t), z(t)) +``` +
+ +### *def* `cal_parallel_plane3(self, point: 'Point3') -> 'Plane3'` + + +计算平行于该平面且过指定点的平面。 + +引数: + +- point: 指定点 + +戻り値: + +- 平面 + + + +
+ソースコード + +```python +def cal_parallel_plane3(self, point: 'Point3') -> 'Plane3': + """ + 计算平行于该平面且过指定点的平面。 + Args: + point: 指定点 + Returns: + 平面 + """ + return Plane3.from_point_and_normal(point, self.normal) +``` +
+ +### *def* `is_parallel(self, other: 'Plane3') -> bool` + + +判断两个平面是否平行。 + +引数: + +- other: 另一个平面 + +戻り値: + +- 是否平行 + + + +
+ソースコード + +```python +def is_parallel(self, other: 'Plane3') -> bool: + """ + 判断两个平面是否平行。 + Args: + other: 另一个平面 + Returns: + 是否平行 + """ + return self.normal.is_parallel(other.normal) +``` +
+ +### `@property` +### *def* `normal(self) -> 'Vector3'` + + +平面的法向量。 + +戻り値: + +- 法向量 + + + +
+ソースコード + +```python +@property +def normal(self) -> 'Vector3': + """ + 平面的法向量。 + Returns: + 法向量 + """ + return Vector3(self.a, self.b, self.c) +``` +
+ +### `@classmethod` +### *def* `from_point_and_normal(cls, point: 'Point3', normal: 'Vector3') -> 'Plane3'` + + +工厂函数 由点和法向量构造平面(点法式构造)。 + +引数: + +- point: 平面上的一点 + +- normal: 法向量 + +戻り値: + +- 平面 + + + +
+ソースコード + +```python +@classmethod +def from_point_and_normal(cls, point: 'Point3', normal: 'Vector3') -> 'Plane3': + """ + 工厂函数 由点和法向量构造平面(点法式构造)。 + Args: + point: 平面上的一点 + normal: 法向量 + Returns: + 平面 + """ + a, b, c = (normal.x, normal.y, normal.z) + d = -a * point.x - b * point.y - c * point.z + return cls(a, b, c, d) +``` +
+ +### `@classmethod` +### *def* `from_three_points(cls, p1: 'Point3', p2: 'Point3', p3: 'Point3') -> 'Plane3'` + + +工厂函数 由三点构造平面。 + +引数: + +- p1: 点1 + +- p2: 点2 + +- p3: 点3 + +戻り値: + +- 平面 + + + +
+ソースコード + +```python +@classmethod +def from_three_points(cls, p1: 'Point3', p2: 'Point3', p3: 'Point3') -> 'Plane3': + """ + 工厂函数 由三点构造平面。 + Args: + p1: 点1 + p2: 点2 + p3: 点3 + Returns: + 平面 + """ + v1 = p2 - p1 + v2 = p3 - p1 + normal = v1.cross(v2) + return cls.from_point_and_normal(p1, normal) +``` +
+ +### `@classmethod` +### *def* `from_two_lines(cls, l1: 'Line3', l2: 'Line3') -> 'Plane3'` + + +工厂函数 由两直线构造平面。 + +引数: + +- l1: 直线1 + +- l2: 直线2 + +戻り値: + +- 平面 + + + +
+ソースコード + +```python +@classmethod +def from_two_lines(cls, l1: 'Line3', l2: 'Line3') -> 'Plane3': + """ + 工厂函数 由两直线构造平面。 + Args: + l1: 直线1 + l2: 直线2 + Returns: + 平面 + """ + v1 = l1.direction + v2 = l2.point - l1.point + if v2 == zero_vector3: + v2 = l2.get_point(1) - l1.point + return cls.from_point_and_normal(l1.point, v1.cross(v2)) +``` +
+ +### `@classmethod` +### *def* `from_point_and_line(cls, point: 'Point3', line: 'Line3') -> 'Plane3'` + + +工厂函数 由点和直线构造平面。 + +引数: + +- point: 面上一点 + +- line: 面上直线,不包含点 + +戻り値: + +- 平面 + + + +
+ソースコード + +```python +@classmethod +def from_point_and_line(cls, point: 'Point3', line: 'Line3') -> 'Plane3': + """ + 工厂函数 由点和直线构造平面。 + Args: + point: 面上一点 + line: 面上直线,不包含点 + Returns: + 平面 + """ + return cls.from_point_and_normal(point, line.direction) +``` +
+ +### *def* `__repr__(self)` + + +
+ソースコード + +```python +def __repr__(self): + return f'Plane3({self.a}, {self.b}, {self.c}, {self.d})' +``` +
+ +### *def* `__str__(self)` + + +
+ソースコード + +```python +def __str__(self): + s = 'Plane3: ' + if self.a != 0: + s += f'{sign(self.a, only_neg=True)}{abs(self.a)}x' + if self.b != 0: + s += f' {sign(self.b)} {abs(self.b)}y' + if self.c != 0: + s += f' {sign(self.c)} {abs(self.c)}z' + if self.d != 0: + s += f' {sign(self.d)} {abs(self.d)}' + return s + ' = 0' +``` +
+ +### `@overload` +### *def* `__and__(self, other: 'Line3') -> 'Point3 | None'` + + +
+ソースコード + +```python +@overload +def __and__(self, other: 'Line3') -> 'Point3 | None': + ... +``` +
+ +### `@overload` +### *def* `__and__(self, other: 'Plane3') -> 'Line3 | None'` + + +
+ソースコード + +```python +@overload +def __and__(self, other: 'Plane3') -> 'Line3 | None': + ... +``` +
+ +### *def* `__and__(self, other)` + + +取两平面的交集(人话:交线) + +引数: + +- other: + +戻り値: + +- 不平行平面的交线,平面平行返回None + + + +
+ソースコード + +```python +def __and__(self, other): + """ + 取两平面的交集(人话:交线) + Args: + other: + Returns: + 不平行平面的交线,平面平行返回None + """ + if isinstance(other, Plane3): + if self.normal.is_parallel(other.normal): + return None + return self.cal_intersection_line3(other) + elif isinstance(other, Line3): + if self.normal @ other.direction == 0: + return None + return self.cal_intersection_point3(other) + else: + raise TypeError(f"unsupported operand type(s) for &: 'Plane3' and '{type(other)}'") +``` +
+ +### *def* `__eq__(self, other) -> bool` + + +
+ソースコード + +```python +def __eq__(self, other) -> bool: + return self.approx(other) +``` +
+ +### *def* `__rand__(self, other: 'Line3') -> 'Point3'` + + +
+ソースコード + +```python +def __rand__(self, other: 'Line3') -> 'Point3': + return self.cal_intersection_point3(other) +``` +
+ +### ***var*** `k = other.a / self.a` + +### ***var*** `A = np.array([[self.b, self.c], [other.b, other.c]])` + +### ***var*** `B = np.array([-self.d, -other.d])` + +### ***var*** `v2 = l2.get_point(1) - l1.point` + +### ***var*** `k = other.b / self.b` + +### ***var*** `A = np.array([[self.a, self.c], [other.a, other.c]])` + +### ***var*** `B = np.array([-self.d, -other.d])` + +### ***var*** `k = other.c / self.c` + +### ***var*** `A = np.array([[self.a, self.b], [other.a, other.b]])` + +### ***var*** `B = np.array([-self.d, -other.d])` + diff --git a/docs/ja/api/mp_math/point.md b/docs/ja/api/mp_math/point.md new file mode 100644 index 0000000..679b537 --- /dev/null +++ b/docs/ja/api/mp_math/point.md @@ -0,0 +1,199 @@ +--- +title: mbcp.mp_math.point +--- +### ***class*** `Point3` + +### *def* `__init__(self, x: float, y: float, z: float)` + + +笛卡尔坐标系中的点。 + +引数: + +- x: x 坐标 + +- y: y 坐标 + +- z: z 坐标 + + + +
+ソースコード + +```python +def __init__(self, x: float, y: float, z: float): + """ + 笛卡尔坐标系中的点。 + Args: + x: x 坐标 + y: y 坐标 + z: z 坐标 + """ + self.x = x + self.y = y + self.z = z +``` +
+ +### *def* `approx(self, other: 'Point3', epsilon: float = APPROX) -> bool` + + +判断两个点是否近似相等。 + +引数: + +- other: + +- epsilon: + +戻り値: + +- 是否近似相等 + + + +
+ソースコード + +```python +def approx(self, other: 'Point3', epsilon: float=APPROX) -> bool: + """ + 判断两个点是否近似相等。 + Args: + other: + epsilon: + + Returns: + 是否近似相等 + """ + return all([abs(self.x - other.x) < epsilon, abs(self.y - other.y) < epsilon, abs(self.z - other.z) < epsilon]) +``` +
+ +### *def* `__str__(self)` + + +
+ソースコード + +```python +def __str__(self): + return f'Point3({self.x}, {self.y}, {self.z})' +``` +
+ +### `@overload` +### *def* `__add__(self, other: 'Vector3') -> 'Point3'` + + +
+ソースコード + +```python +@overload +def __add__(self, other: 'Vector3') -> 'Point3': + ... +``` +
+ +### `@overload` +### *def* `__add__(self, other: 'Point3') -> 'Point3'` + + +
+ソースコード + +```python +@overload +def __add__(self, other: 'Point3') -> 'Point3': + ... +``` +
+ +### *def* `__add__(self, other)` + + +P + V -> P +P + P -> P + +引数: + +- other: + + + +
+ソースコード + +```python +def __add__(self, other): + """ + P + V -> P + P + P -> P + Args: + other: + Returns: + """ + return Point3(self.x + other.x, self.y + other.y, self.z + other.z) +``` +
+ +### *def* `__eq__(self, other)` + + +判断两个点是否相等。 + +引数: + +- other: + + + +
+ソースコード + +```python +def __eq__(self, other): + """ + 判断两个点是否相等。 + Args: + other: + Returns: + """ + return approx(self.x, other.x) and approx(self.y, other.y) and approx(self.z, other.z) +``` +
+ +### *def* `__sub__(self, other: 'Point3') -> 'Vector3'` + + +P - P -> V + +P - V -> P 已在 :class:`Vector3` 中实现 + +引数: + +- other: + + + +
+ソースコード + +```python +def __sub__(self, other: 'Point3') -> 'Vector3': + """ + P - P -> V + + P - V -> P 已在 :class:`Vector3` 中实现 + Args: + other: + Returns: + + """ + from .vector import Vector3 + return Vector3(self.x - other.x, self.y - other.y, self.z - other.z) +``` +
+ diff --git a/docs/ja/api/mp_math/segment.md b/docs/ja/api/mp_math/segment.md new file mode 100644 index 0000000..62170c4 --- /dev/null +++ b/docs/ja/api/mp_math/segment.md @@ -0,0 +1,59 @@ +--- +title: mbcp.mp_math.segment +--- +### ***class*** `Segment3` + +### *def* `__init__(self, p1: 'Point3', p2: 'Point3')` + + +三维空间中的线段。 +:param p1: +:param p2: + + + +
+ソースコード + +```python +def __init__(self, p1: 'Point3', p2: 'Point3'): + """ + 三维空间中的线段。 + :param p1: + :param p2: + """ + self.p1 = p1 + self.p2 = p2 + '方向向量' + self.direction = self.p2 - self.p1 + '长度' + self.length = self.direction.length + '中心点' + self.midpoint = Point3((self.p1.x + self.p2.x) / 2, (self.p1.y + self.p2.y) / 2, (self.p1.z + self.p2.z) / 2) +``` +
+ +### *def* `__repr__(self)` + + +
+ソースコード + +```python +def __repr__(self): + return f'Segment3({self.p1}, {self.p2})' +``` +
+ +### *def* `__str__(self)` + + +
+ソースコード + +```python +def __str__(self): + return f'Segment3({self.p1} -> {self.p2})' +``` +
+ diff --git a/docs/ja/api/mp_math/utils.md b/docs/ja/api/mp_math/utils.md new file mode 100644 index 0000000..a97a5fa --- /dev/null +++ b/docs/ja/api/mp_math/utils.md @@ -0,0 +1,220 @@ +--- +title: mbcp.mp_math.utils +--- +### *def* `clamp() -> float` + + +区间截断函数。 + +引数: + +- x: + +- min_: + +- max_: + +戻り値: + +- 限制后的值 + + + +
+ソースコード + +```python +def clamp(x: float, min_: float, max_: float) -> float: + """ + 区间截断函数。 + Args: + x: + min_: + max_: + + Returns: + 限制后的值 + """ + return max(min(x, max_), min_) +``` +
+ +### *def* `approx(x: float = 0.0, y: float = APPROX) -> bool` + + +判断两个数是否近似相等。或包装一个实数,用于判断是否近似于0。 + +引数: + +- x: + +- y: + +- epsilon: + +戻り値: + +- 是否近似相等 + + + +
+ソースコード + +```python +def approx(x: float, y: float=0.0, epsilon: float=APPROX) -> bool: + """ + 判断两个数是否近似相等。或包装一个实数,用于判断是否近似于0。 + Args: + x: + y: + epsilon: + + Returns: + 是否近似相等 + """ + return abs(x - y) < epsilon +``` +
+ +### *def* `sign(x: float = False) -> str` + + +获取数的符号。 + +引数: + +- x: 数 + +- only_neg: 是否只返回负数的符号 + +戻り値: + +- 符号 + - "" + + + +
+ソースコード + +```python +def sign(x: float, only_neg: bool=False) -> str: + """获取数的符号。 + Args: + x: 数 + only_neg: 是否只返回负数的符号 + Returns: + 符号 + - "" + """ + if x > 0: + return '+' if not only_neg else '' + elif x < 0: + return '-' + else: + return '' +``` +
+ +### *def* `sign_format(x: float = False) -> str` + + +格式化符号数 +-1 -> -1 +1 -> +1 +0 -> "" + +引数: + +- x: 数 + +- only_neg: 是否只返回负数的符号 + +戻り値: + +- 符号 + - "" + + + +
+ソースコード + +```python +def sign_format(x: float, only_neg: bool=False) -> str: + """格式化符号数 + -1 -> -1 + 1 -> +1 + 0 -> "" + Args: + x: 数 + only_neg: 是否只返回负数的符号 + Returns: + 符号 + - "" + """ + if x > 0: + return f'+{x}' if not only_neg else f'{x}' + elif x < 0: + return f'-{abs(x)}' + else: + return '' +``` +
+ +### ***class*** `Approx` + +### *def* `__init__(self, value: RealNumber)` + + +
+ソースコード + +```python +def __init__(self, value: RealNumber): + self.value = value +``` +
+ +### *def* `__eq__(self, other)` + + +
+ソースコード + +```python +def __eq__(self, other): + if isinstance(self.value, (float, int)): + if isinstance(other, (float, int)): + return abs(self.value - other) < APPROX + else: + self.raise_type_error(other) + elif isinstance(self.value, Vector3): + if isinstance(other, (Vector3, Point3, Plane3, Line3)): + return all([approx(self.value.x, other.x), approx(self.value.y, other.y), approx(self.value.z, other.z)]) + else: + self.raise_type_error(other) +``` +
+ +### *def* `raise_type_error(self, other)` + + +
+ソースコード + +```python +def raise_type_error(self, other): + raise TypeError(f'Unsupported type: {type(self.value)} and {type(other)}') +``` +
+ +### *def* `__ne__(self, other)` + + +
+ソースコード + +```python +def __ne__(self, other): + return not self.__eq__(other) +``` +
+ diff --git a/docs/ja/api/mp_math/vector.md b/docs/ja/api/mp_math/vector.md new file mode 100644 index 0000000..5c5143b --- /dev/null +++ b/docs/ja/api/mp_math/vector.md @@ -0,0 +1,699 @@ +--- +title: mbcp.mp_math.vector +--- +### ***class*** `Vector3` + +### *def* `__init__(self, x: float, y: float, z: float)` + + +3维向量 + +引数: + +- x: x轴分量 + +- y: y轴分量 + +- z: z轴分量 + + + +
+ソースコード + +```python +def __init__(self, x: float, y: float, z: float): + """ + 3维向量 + Args: + x: x轴分量 + y: y轴分量 + z: z轴分量 + """ + self.x = x + self.y = y + self.z = z +``` +
+ +### *def* `approx(self, other: 'Vector3', epsilon: float = APPROX) -> bool` + + +判断两个向量是否近似相等。 + +引数: + +- other: + +- epsilon: + +戻り値: + +- 是否近似相等 + + + +
+ソースコード + +```python +def approx(self, other: 'Vector3', epsilon: float=APPROX) -> bool: + """ + 判断两个向量是否近似相等。 + Args: + other: + epsilon: + + Returns: + 是否近似相等 + """ + return all([abs(self.x - other.x) < epsilon, abs(self.y - other.y) < epsilon, abs(self.z - other.z) < epsilon]) +``` +
+ +### *def* `cal_angle(self, other: 'Vector3') -> 'AnyAngle'` + + +计算两个向量之间的夹角。 + +引数: + +- other: 另一个向量 + +戻り値: + +- 夹角 + + + +
+ソースコード + +```python +def cal_angle(self, other: 'Vector3') -> 'AnyAngle': + """ + 计算两个向量之间的夹角。 + Args: + other: 另一个向量 + Returns: + 夹角 + """ + return AnyAngle(math.acos(self @ other / (self.length * other.length)), is_radian=True) +``` +
+ +### *def* `cross(self, other: 'Vector3') -> 'Vector3'` + + +向量积 叉乘:v1 cross v2 -> v3 + +叉乘为0,则两向量平行。 +其余结果的模为平行四边形的面积。 + + +引数: + +- other: + +戻り値: + +- 行列式的结果 + + + +
+ソースコード + +```python +def cross(self, other: 'Vector3') -> 'Vector3': + """ + 向量积 叉乘:v1 cross v2 -> v3 + + 叉乘为0,则两向量平行。 + 其余结果的模为平行四边形的面积。 + + 返回如下行列式的结果: + + ``i j k`` + + ``x1 y1 z1`` + + ``x2 y2 z2`` + + Args: + other: + Returns: + 行列式的结果 + """ + 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* `is_approx_parallel(self, other: 'Vector3', epsilon: float = APPROX) -> bool` + + +判断两个向量是否近似平行。 + +引数: + +- other: 另一个向量 + +- epsilon: 允许的误差 + +戻り値: + +- 是否近似平行 + + + +
+ソースコード + +```python +def is_approx_parallel(self, other: 'Vector3', epsilon: float=APPROX) -> bool: + """ + 判断两个向量是否近似平行。 + Args: + other: 另一个向量 + epsilon: 允许的误差 + Returns: + 是否近似平行 + """ + return self.cross(other).length < epsilon +``` +
+ +### *def* `is_parallel(self, other: 'Vector3') -> bool` + + +判断两个向量是否平行。 + +引数: + +- other: 另一个向量 + +戻り値: + +- 是否平行 + + + +
+ソースコード + +```python +def is_parallel(self, other: 'Vector3') -> bool: + """ + 判断两个向量是否平行。 + Args: + other: 另一个向量 + Returns: + 是否平行 + """ + return self.cross(other).approx(zero_vector3) +``` +
+ +### *def* `normalize(self)` + + +将向量归一化。 + +自体归一化,不返回值。 + + + +
+ソースコード + +```python +def normalize(self): + """ + 将向量归一化。 + + 自体归一化,不返回值。 + """ + length = self.length + self.x /= length + self.y /= length + self.z /= length +``` +
+ +### `@property` +### *def* `np_array(self) -> 'np.ndarray'` + + + + + + +
+ソースコード + +```python +@property +def np_array(self) -> 'np.ndarray': + """ + 返回numpy数组 + Returns: + """ + return np.array([self.x, self.y, self.z]) +``` +
+ +### `@property` +### *def* `length(self) -> float` + + +向量的模。 + +戻り値: + +- 模 + + + +
+ソースコード + +```python +@property +def length(self) -> float: + """ + 向量的模。 + Returns: + 模 + """ + return math.sqrt(self.x ** 2 + self.y ** 2 + self.z ** 2) +``` +
+ +### `@property` +### *def* `unit(self) -> 'Vector3'` + + +获取该向量的单位向量。 + +戻り値: + +- 单位向量 + + + +
+ソースコード + +```python +@property +def unit(self) -> 'Vector3': + """ + 获取该向量的单位向量。 + Returns: + 单位向量 + """ + return self / self.length +``` +
+ +### *def* `__abs__(self)` + + +
+ソースコード + +```python +def __abs__(self): + return self.length +``` +
+ +### `@overload` +### *def* `__add__(self, other: 'Vector3') -> 'Vector3'` + + +
+ソースコード + +```python +@overload +def __add__(self, other: 'Vector3') -> 'Vector3': + ... +``` +
+ +### `@overload` +### *def* `__add__(self, other: 'Point3') -> 'Point3'` + + +
+ソースコード + +```python +@overload +def __add__(self, other: 'Point3') -> 'Point3': + ... +``` +
+ +### *def* `__add__(self, other)` + + +V + P -> P + +V + V -> V + +引数: + +- other: + + + +
+ソースコード + +```python +def __add__(self, other): + """ + V + P -> P + + V + V -> V + Args: + other: + Returns: + + """ + if isinstance(other, Vector3): + 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) + else: + raise TypeError(f"unsupported operand type(s) for +: 'Vector3' and '{type(other)}'") +``` +
+ +### *def* `__eq__(self, other)` + + +判断两个向量是否相等。 + +引数: + +- other: + +戻り値: + +- 是否相等 + + + +
+ソースコード + +```python +def __eq__(self, other): + """ + 判断两个向量是否相等。 + Args: + other: + Returns: + 是否相等 + """ + return approx(self.x, other.x) and approx(self.y, other.y) and approx(self.z, other.z) +``` +
+ +### *def* `__radd__(self, other: 'Point3') -> 'Point3'` + + +P + V -> P + +别去点那边实现了。 +:param other: +:return: + + + +
+ソースコード + +```python +def __radd__(self, other: 'Point3') -> 'Point3': + """ + P + V -> P + + 别去点那边实现了。 + :param other: + :return: + """ + return Point3(self.x + other.x, self.y + other.y, self.z + other.z) +``` +
+ +### `@overload` +### *def* `__sub__(self, other: 'Vector3') -> 'Vector3'` + + +
+ソースコード + +```python +@overload +def __sub__(self, other: 'Vector3') -> 'Vector3': + ... +``` +
+ +### `@overload` +### *def* `__sub__(self, other: 'Point3') -> 'Point3'` + + +
+ソースコード + +```python +@overload +def __sub__(self, other: 'Point3') -> 'Point3': + ... +``` +
+ +### *def* `__sub__(self, other)` + + +V - P -> P + +V - V -> V + +引数: + +- other: + + + +
+ソースコード + +```python +def __sub__(self, other): + """ + V - P -> P + + V - V -> V + Args: + other: + Returns: + """ + if isinstance(other, Vector3): + 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) + else: + raise TypeError(f'unsupported operand type(s) for -: "Vector3" and "{type(other)}"') +``` +
+ +### *def* `__rsub__(self, other: 'Point3')` + + +P - V -> P + +引数: + +- other: + + + +
+ソースコード + +```python +def __rsub__(self, other: 'Point3'): + """ + P - V -> P + Args: + other: + Returns: + + """ + if isinstance(other, Point3): + 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: 'Vector3') -> 'Vector3'` + + +
+ソースコード + +```python +@overload +def __mul__(self, other: 'Vector3') -> 'Vector3': + ... +``` +
+ +### `@overload` +### *def* `__mul__(self, other: RealNumber) -> 'Vector3'` + + +
+ソースコード + +```python +@overload +def __mul__(self, other: RealNumber) -> 'Vector3': + ... +``` +
+ +### *def* `__mul__(self, other: 'int | float | Vector3') -> 'Vector3'` + + +数组运算 非点乘。点乘使用@,叉乘使用cross。 + +引数: + +- other: + + + +
+ソースコード + +```python +def __mul__(self, other: 'int | float | Vector3') -> 'Vector3': + """ + 数组运算 非点乘。点乘使用@,叉乘使用cross。 + Args: + other: + + Returns: + """ + if isinstance(other, Vector3): + return Vector3(self.x * other.x, self.y * other.y, self.z * other.z) + elif isinstance(other, (float, int)): + return Vector3(self.x * other, self.y * other, self.z * other) + else: + raise TypeError(f"unsupported operand type(s) for *: 'Vector3' and '{type(other)}'") +``` +
+ +### *def* `__rmul__(self, other: 'RealNumber') -> 'Vector3'` + + +
+ソースコード + +```python +def __rmul__(self, other: 'RealNumber') -> 'Vector3': + return self.__mul__(other) +``` +
+ +### *def* `__matmul__(self, other: 'Vector3') -> 'RealNumber'` + + +点乘。 + +引数: + +- other: + + + +
+ソースコード + +```python +def __matmul__(self, other: 'Vector3') -> 'RealNumber': + """ + 点乘。 + Args: + other: + Returns: + """ + return self.x * other.x + self.y * other.y + self.z * other.z +``` +
+ +### *def* `__truediv__(self, other: RealNumber) -> 'Vector3'` + + +
+ソースコード + +```python +def __truediv__(self, other: RealNumber) -> 'Vector3': + return Vector3(self.x / other, self.y / other, self.z / other) +``` +
+ +### *def* `__neg__(self)` + + +
+ソースコード + +```python +def __neg__(self): + return Vector3(-self.x, -self.y, -self.z) +``` +
+ +### *def* `__repr__(self)` + + +
+ソースコード + +```python +def __repr__(self): + return f'Vector3({self.x}, {self.y}, {self.z})' +``` +
+ +### *def* `__str__(self)` + + +
+ソースコード + +```python +def __str__(self): + return f'Vector3({self.x}, {self.y}, {self.z})' +``` +
+ +### ***var*** `zero_vector3 = Vector3(0, 0, 0)` + +### ***var*** `x_axis = Vector3(1, 0, 0)` + +### ***var*** `y_axis = Vector3(0, 1, 0)` + +### ***var*** `z_axis = Vector3(0, 0, 1)` + diff --git a/docs/ja/api/particle/index.md b/docs/ja/api/particle/index.md new file mode 100644 index 0000000..4b514d5 --- /dev/null +++ b/docs/ja/api/particle/index.md @@ -0,0 +1,3 @@ +--- +title: mbcp.particle +--- diff --git a/docs/ja/api/presets/index.md b/docs/ja/api/presets/index.md new file mode 100644 index 0000000..472366f --- /dev/null +++ b/docs/ja/api/presets/index.md @@ -0,0 +1,3 @@ +--- +title: mbcp.presets +--- diff --git a/docs/ja/api/presets/model/index.md b/docs/ja/api/presets/model/index.md new file mode 100644 index 0000000..82b4f79 --- /dev/null +++ b/docs/ja/api/presets/model/index.md @@ -0,0 +1,48 @@ +--- +title: mbcp.presets.model +--- +### ***class*** `GeometricModels` + +### `@staticmethod` +### *def* `sphere(radius: float, density: float)` + + +生成球体上的点集。 + +引数: + +- radius: + +- density: + +戻り値: + +- List[Point3]: 球体上的点集。 + + + +
+ソースコード + +```python +@staticmethod +def sphere(radius: float, density: float): + """ + 生成球体上的点集。 + Args: + radius: + density: + Returns: + List[Point3]: 球体上的点集。 + """ + area = 4 * np.pi * radius ** 2 + num = int(area * density) + phi_list = np.arccos([clamp(-1 + (2.0 * _ - 1.0) / num, -1, 1) for _ in range(num)]) + theta_list = np.sqrt(num * np.pi) * phi_list + x_array = radius * np.sin(phi_list) * np.cos(theta_list) + y_array = radius * np.sin(phi_list) * np.sin(theta_list) + z_array = radius * np.cos(phi_list) + return [Point3(x_array[i], y_array[i], z_array[i]) for i in range(num)] +``` +
+ diff --git a/docs/zh-Hant/api/index.md b/docs/zh-Hant/api/index.md new file mode 100644 index 0000000..6d251e8 --- /dev/null +++ b/docs/zh-Hant/api/index.md @@ -0,0 +1,3 @@ +--- +title: mbcp +--- diff --git a/docs/zh-Hant/api/mp_math/angle.md b/docs/zh-Hant/api/mp_math/angle.md new file mode 100644 index 0000000..9539679 --- /dev/null +++ b/docs/zh-Hant/api/mp_math/angle.md @@ -0,0 +1,449 @@ +--- +title: mbcp.mp_math.angle +--- +### ***class*** `Angle` + +### ***class*** `AnyAngle` + +### *def* `__init__(self, value: float, is_radian: bool = False)` + + +任意角度。 + +參數: + +- value: 角度或弧度值 + +- is_radian: 是否为弧度,默认为否 + + + +
+源碼 + +```python +def __init__(self, value: float, is_radian: bool=False): + """ + 任意角度。 + Args: + value: 角度或弧度值 + is_radian: 是否为弧度,默认为否 + """ + if is_radian: + self.radian = value + else: + self.radian = value * PI / 180 +``` +
+ +### `@property` +### *def* `complementary(self) -> 'AnyAngle'` + + +余角:两角的和为90°。 + +返回: + +- 余角 + + + +
+源碼 + +```python +@property +def complementary(self) -> 'AnyAngle': + """ + 余角:两角的和为90°。 + Returns: + 余角 + """ + return AnyAngle(PI / 2 - self.minimum_positive.radian, is_radian=True) +``` +
+ +### `@property` +### *def* `supplementary(self) -> 'AnyAngle'` + + +补角:两角的和为180°。 + +返回: + +- 补角 + + + +
+源碼 + +```python +@property +def supplementary(self) -> 'AnyAngle': + """ + 补角:两角的和为180°。 + Returns: + 补角 + """ + return AnyAngle(PI - self.minimum_positive.radian, is_radian=True) +``` +
+ +### `@property` +### *def* `degree(self) -> float` + + +角度。 + +返回: + +- 弧度 + + + +
+源碼 + +```python +@property +def degree(self) -> float: + """ + 角度。 + Returns: + 弧度 + """ + return self.radian * 180 / PI +``` +
+ +### `@property` +### *def* `minimum_positive(self) -> 'AnyAngle'` + + +最小正角。 + +返回: + +- 最小正角度 + + + +
+源碼 + +```python +@property +def minimum_positive(self) -> 'AnyAngle': + """ + 最小正角。 + Returns: + 最小正角度 + """ + return AnyAngle(self.radian % (2 * PI)) +``` +
+ +### `@property` +### *def* `maximum_negative(self) -> 'AnyAngle'` + + +最大负角。 + +返回: + +- 最大负角度 + + + +
+源碼 + +```python +@property +def maximum_negative(self) -> 'AnyAngle': + """ + 最大负角。 + Returns: + 最大负角度 + """ + return AnyAngle(-self.radian % (2 * PI), is_radian=True) +``` +
+ +### `@property` +### *def* `sin(self) -> float` + + +正弦值。 + +返回: + +- 正弦值 + + + +
+源碼 + +```python +@property +def sin(self) -> float: + """ + 正弦值。 + Returns: + 正弦值 + """ + return math.sin(self.radian) +``` +
+ +### `@property` +### *def* `cos(self) -> float` + + +余弦值。 + +返回: + +- 余弦值 + + + +
+源碼 + +```python +@property +def cos(self) -> float: + """ + 余弦值。 + Returns: + 余弦值 + """ + return math.cos(self.radian) +``` +
+ +### `@property` +### *def* `tan(self) -> float` + + +正切值。 + +返回: + +- 正切值 + + + +
+源碼 + +```python +@property +def tan(self) -> float: + """ + 正切值。 + Returns: + 正切值 + """ + return math.tan(self.radian) +``` +
+ +### `@property` +### *def* `cot(self) -> float` + + +余切值。 + +返回: + +- 余切值 + + + +
+源碼 + +```python +@property +def cot(self) -> float: + """ + 余切值。 + Returns: + 余切值 + """ + return 1 / math.tan(self.radian) +``` +
+ +### `@property` +### *def* `sec(self) -> float` + + +正割值。 + +返回: + +- 正割值 + + + +
+源碼 + +```python +@property +def sec(self) -> float: + """ + 正割值。 + Returns: + 正割值 + """ + return 1 / math.cos(self.radian) +``` +
+ +### `@property` +### *def* `csc(self) -> float` + + +余割值。 + +返回: + +- 余割值 + + + +
+源碼 + +```python +@property +def csc(self) -> float: + """ + 余割值。 + Returns: + 余割值 + """ + return 1 / math.sin(self.radian) +``` +
+ +### *def* `__add__(self, other: 'AnyAngle') -> 'AnyAngle'` + + +
+源碼 + +```python +def __add__(self, other: 'AnyAngle') -> 'AnyAngle': + return AnyAngle(self.radian + other.radian, is_radian=True) +``` +
+ +### *def* `__eq__(self, other)` + + +
+源碼 + +```python +def __eq__(self, other): + return approx(self.radian, other.radian) +``` +
+ +### *def* `__sub__(self, other: 'AnyAngle') -> 'AnyAngle'` + + +
+源碼 + +```python +def __sub__(self, other: 'AnyAngle') -> 'AnyAngle': + return AnyAngle(self.radian - other.radian, is_radian=True) +``` +
+ +### *def* `__mul__(self, other: float) -> 'AnyAngle'` + + +
+源碼 + +```python +def __mul__(self, other: float) -> 'AnyAngle': + return AnyAngle(self.radian * other, is_radian=True) +``` +
+ +### *def* `__repr__(self)` + + +
+源碼 + +```python +def __repr__(self): + return f'AnyAngle({self.radian}, is_radian=True)' +``` +
+ +### *def* `__str__(self)` + + +
+源碼 + +```python +def __str__(self): + return f'AnyAngle({self.degree}° or {self.radian} rad)' +``` +
+ +### `@overload` +### *def* `__truediv__(self, other: float) -> 'AnyAngle'` + + +
+源碼 + +```python +@overload +def __truediv__(self, other: float) -> 'AnyAngle': + ... +``` +
+ +### `@overload` +### *def* `__truediv__(self, other: 'AnyAngle') -> float` + + +
+源碼 + +```python +@overload +def __truediv__(self, other: 'AnyAngle') -> float: + ... +``` +
+ +### *def* `__truediv__(self, other)` + + +
+源碼 + +```python +def __truediv__(self, other): + if isinstance(other, AnyAngle): + return self.radian / other.radian + return AnyAngle(self.radian / other, is_radian=True) +``` +
+ diff --git a/docs/zh-Hant/api/mp_math/const.md b/docs/zh-Hant/api/mp_math/const.md new file mode 100644 index 0000000..888edf3 --- /dev/null +++ b/docs/zh-Hant/api/mp_math/const.md @@ -0,0 +1,15 @@ +--- +title: mbcp.mp_math.const +--- +### ***var*** `PI = math.pi` + +### ***var*** `E = math.e` + +### ***var*** `GOLDEN_RATIO = (1 + math.sqrt(5)) / 2` + +### ***var*** `GAMMA = 0.5772156649015329` + +### ***var*** `EPSILON = 0.0001` + +### ***var*** `APPROX = 0.001` + diff --git a/docs/zh-Hant/api/mp_math/equation.md b/docs/zh-Hant/api/mp_math/equation.md new file mode 100644 index 0000000..8a2a0a4 --- /dev/null +++ b/docs/zh-Hant/api/mp_math/equation.md @@ -0,0 +1,177 @@ +--- +title: mbcp.mp_math.equation +--- +### *def* `get_partial_derivative_func(func: MultiVarsFunc = EPSILON) -> MultiVarsFunc` + + +求N元函数一阶偏导函数。这玩意不太稳定,慎用。 + +參數: + +- func: 函数 + +- var: 变量位置,可为整数(一阶偏导)或整数元组(高阶偏导) + +- epsilon: 偏移量 + +返回: + +- 偏导函数 + +引發: + +- ValueError 无效变量类型 + + + +
+源碼 + +```python +def get_partial_derivative_func(func: MultiVarsFunc, var: int | tuple[int, ...], epsilon: Number=EPSILON) -> MultiVarsFunc: + """ + 求N元函数一阶偏导函数。这玩意不太稳定,慎用。 + Args: + func: 函数 + var: 变量位置,可为整数(一阶偏导)或整数元组(高阶偏导) + epsilon: 偏移量 + Returns: + 偏导函数 + Raises: + ValueError: 无效变量类型 + """ + if isinstance(var, int): + + def partial_derivative_func(*args: Var) -> Var: + args_list_plus = list(args) + args_list_plus[var] += epsilon + args_list_minus = list(args) + args_list_minus[var] -= epsilon + return (func(*args_list_plus) - func(*args_list_minus)) / (2 * epsilon) + return partial_derivative_func + elif isinstance(var, tuple): + + def high_order_partial_derivative_func(*args: Var) -> Var: + result_func = func + for v in var: + result_func = get_partial_derivative_func(result_func, v, epsilon) + return result_func(*args) + return high_order_partial_derivative_func + else: + raise ValueError('Invalid var type') +``` +
+ +### *def* `partial_derivative_func() -> Var` + + +
+源碼 + +```python +def partial_derivative_func(*args: Var) -> Var: + args_list_plus = list(args) + args_list_plus[var] += epsilon + args_list_minus = list(args) + args_list_minus[var] -= epsilon + return (func(*args_list_plus) - func(*args_list_minus)) / (2 * epsilon) +``` +
+ +### *def* `high_order_partial_derivative_func() -> Var` + + +
+源碼 + +```python +def high_order_partial_derivative_func(*args: Var) -> Var: + result_func = func + for v in var: + result_func = get_partial_derivative_func(result_func, v, epsilon) + return result_func(*args) +``` +
+ +### ***class*** `CurveEquation` + +### *def* `__init__(self, x_func: OneVarFunc, y_func: OneVarFunc, z_func: OneVarFunc)` + + +曲线方程。 + +參數: + +- x_func: x函数 + +- y_func: y函数 + +- z_func: z函数 + + + +
+源碼 + +```python +def __init__(self, x_func: OneVarFunc, y_func: OneVarFunc, z_func: OneVarFunc): + """ + 曲线方程。 + Args: + x_func: x函数 + y_func: y函数 + z_func: z函数 + """ + self.x_func = x_func + self.y_func = y_func + self.z_func = z_func +``` +
+ +### *def* `__call__(self) -> Point3 | tuple[Point3, ...]` + + +计算曲线上的点。 + +參數: + +- *t: + +- 参数: + + + +
+源碼 + +```python +def __call__(self, *t: Var) -> Point3 | tuple[Point3, ...]: + """ + 计算曲线上的点。 + Args: + *t: + 参数 + Returns: + + """ + if len(t) == 1: + return Point3(self.x_func(t[0]), self.y_func(t[0]), self.z_func(t[0])) + else: + return tuple([Point3(x, y, z) for x, y, z in zip(self.x_func(t), self.y_func(t), self.z_func(t))]) +``` +
+ +### *def* `__str__(self)` + + +
+源碼 + +```python +def __str__(self): + return 'CurveEquation()' +``` +
+ +### ***var*** `result_func = get_partial_derivative_func(result_func, v, epsilon)` + diff --git a/docs/zh-Hant/api/mp_math/index.md b/docs/zh-Hant/api/mp_math/index.md new file mode 100644 index 0000000..6e3261c --- /dev/null +++ b/docs/zh-Hant/api/mp_math/index.md @@ -0,0 +1,3 @@ +--- +title: mbcp.mp_math +--- diff --git a/docs/zh-Hant/api/mp_math/line.md b/docs/zh-Hant/api/mp_math/line.md new file mode 100644 index 0000000..305e4d5 --- /dev/null +++ b/docs/zh-Hant/api/mp_math/line.md @@ -0,0 +1,622 @@ +--- +title: mbcp.mp_math.line +--- +### ***class*** `Line3` + +### *def* `__init__(self, point: 'Point3', direction: 'Vector3')` + + +三维空间中的直线。由一个点和一个方向向量确定。 + +參數: + +- point: 直线上的一点 + +- direction: 直线的方向向量 + + + +
+源碼 + +```python +def __init__(self, point: 'Point3', direction: 'Vector3'): + """ + 三维空间中的直线。由一个点和一个方向向量确定。 + Args: + point: 直线上的一点 + direction: 直线的方向向量 + """ + self.point = point + self.direction = direction +``` +
+ +### *def* `approx(self, other: 'Line3', epsilon: float = APPROX) -> bool` + + +判断两条直线是否近似相等。 + +參數: + +- other: 另一条直线 + +- epsilon: 误差 + +返回: + +- 是否近似相等 + + + +
+源碼 + +```python +def approx(self, other: 'Line3', epsilon: float=APPROX) -> bool: + """ + 判断两条直线是否近似相等。 + Args: + other: 另一条直线 + epsilon: 误差 + Returns: + 是否近似相等 + """ + return self.is_approx_parallel(other, epsilon) and (self.point - other.point).is_approx_parallel(self.direction, epsilon) +``` +
+ +### *def* `cal_angle(self, other: 'Line3') -> 'AnyAngle'` + + +计算直线和直线之间的夹角。 + +參數: + +- other: 另一条直线 + +返回: + +- 夹角弧度 + +引發: + +- TypeError 不支持的类型 + + + +
+源碼 + +```python +def cal_angle(self, other: 'Line3') -> 'AnyAngle': + """ + 计算直线和直线之间的夹角。 + Args: + other: 另一条直线 + Returns: + 夹角弧度 + Raises: + TypeError: 不支持的类型 + """ + return self.direction.cal_angle(other.direction) +``` +
+ +### *def* `cal_distance(self, other: 'Line3 | Point3') -> float` + + +计算直线和直线或点之间的距离。 + +參數: + +- other: 平行直线或点 + +返回: + +- 距离 + +引發: + +- TypeError 不支持的类型 + + + +
+源碼 + +```python +def cal_distance(self, other: 'Line3 | Point3') -> float: + """ + 计算直线和直线或点之间的距离。 + Args: + other: 平行直线或点 + + Returns: + 距离 + Raises: + TypeError: 不支持的类型 + """ + if isinstance(other, Line3): + if self == other: + return 0 + elif self.is_parallel(other): + return (other.point - self.point).cross(self.direction).length / self.direction.length + elif not self.is_coplanar(other): + return abs(self.direction.cross(other.direction) @ (self.point - other.point) / self.direction.cross(other.direction).length) + else: + return 0 + elif isinstance(other, Point3): + return (other - self.point).cross(self.direction).length / self.direction.length + else: + raise TypeError('Unsupported type.') +``` +
+ +### *def* `cal_intersection(self, other: 'Line3') -> 'Point3'` + + +计算两条直线的交点。 + +參數: + +- other: 另一条直线 + +返回: + +- 交点 + +引發: + +- ValueError 直线平行 + +- ValueError 直线不共面 + + + +
+源碼 + +```python +def cal_intersection(self, other: 'Line3') -> 'Point3': + """ + 计算两条直线的交点。 + Args: + other: 另一条直线 + Returns: + 交点 + Raises: + ValueError: 直线平行 + ValueError: 直线不共面 + """ + if self.is_parallel(other): + raise ValueError('Lines are parallel and do not intersect.') + if not self.is_coplanar(other): + raise ValueError('Lines are not coplanar and do not intersect.') + return self.point + self.direction.cross(other.direction) @ other.direction.cross(self.point - other.point) / self.direction.cross(other.direction).length ** 2 * self.direction +``` +
+ +### *def* `cal_perpendicular(self, point: 'Point3') -> 'Line3'` + + +计算直线经过指定点p的垂线。 + +參數: + +- point: 指定点 + +返回: + +- 垂线 + + + +
+源碼 + +```python +def cal_perpendicular(self, point: 'Point3') -> 'Line3': + """ + 计算直线经过指定点p的垂线。 + Args: + point: 指定点 + Returns: + 垂线 + """ + return Line3(point, self.direction.cross(point - self.point)) +``` +
+ +### *def* `get_point(self, t: RealNumber) -> 'Point3'` + + +获取直线上的点。同一条直线,但起始点和方向向量不同,则同一个t对应的点不同。 + +參數: + +- t: 参数t + +返回: + +- 点 + + + +
+源碼 + +```python +def get_point(self, t: RealNumber) -> 'Point3': + """ + 获取直线上的点。同一条直线,但起始点和方向向量不同,则同一个t对应的点不同。 + Args: + t: 参数t + Returns: + 点 + """ + return self.point + t * self.direction +``` +
+ +### *def* `get_parametric_equations(self) -> tuple[OneSingleVarFunc, OneSingleVarFunc, OneSingleVarFunc]` + + +获取直线的参数方程。 + +返回: + +- x(t), y(t), z(t) + + + +
+源碼 + +```python +def get_parametric_equations(self) -> tuple[OneSingleVarFunc, OneSingleVarFunc, OneSingleVarFunc]: + """ + 获取直线的参数方程。 + Returns: + x(t), y(t), z(t) + """ + return (lambda t: self.point.x + self.direction.x * t, lambda t: self.point.y + self.direction.y * t, lambda t: self.point.z + self.direction.z * t) +``` +
+ +### *def* `is_approx_parallel(self, other: 'Line3', epsilon: float = 1e-06) -> bool` + + +判断两条直线是否近似平行。 + +參數: + +- other: 另一条直线 + +- epsilon: 误差 + +返回: + +- 是否近似平行 + + + +
+源碼 + +```python +def is_approx_parallel(self, other: 'Line3', epsilon: float=1e-06) -> bool: + """ + 判断两条直线是否近似平行。 + Args: + other: 另一条直线 + epsilon: 误差 + Returns: + 是否近似平行 + """ + return self.direction.is_approx_parallel(other.direction, epsilon) +``` +
+ +### *def* `is_parallel(self, other: 'Line3') -> bool` + + +判断两条直线是否平行。 + +參數: + +- other: 另一条直线 + +返回: + +- 是否平行 + + + +
+源碼 + +```python +def is_parallel(self, other: 'Line3') -> bool: + """ + 判断两条直线是否平行。 + Args: + other: 另一条直线 + Returns: + 是否平行 + """ + return self.direction.is_parallel(other.direction) +``` +
+ +### *def* `is_collinear(self, other: 'Line3') -> bool` + + +判断两条直线是否共线。 + +參數: + +- other: 另一条直线 + +返回: + +- 是否共线 + + + +
+源碼 + +```python +def is_collinear(self, other: 'Line3') -> bool: + """ + 判断两条直线是否共线。 + Args: + other: 另一条直线 + Returns: + 是否共线 + """ + return self.is_parallel(other) and (self.point - other.point).is_parallel(self.direction) +``` +
+ +### *def* `is_point_on(self, point: 'Point3') -> bool` + + +判断点是否在直线上。 + +參數: + +- point: 点 + +返回: + +- 是否在直线上 + + + +
+源碼 + +```python +def is_point_on(self, point: 'Point3') -> bool: + """ + 判断点是否在直线上。 + Args: + point: 点 + Returns: + 是否在直线上 + """ + return (point - self.point).is_parallel(self.direction) +``` +
+ +### *def* `is_coplanar(self, other: 'Line3') -> bool` + + +判断两条直线是否共面。 +充要条件:两直线方向向量的叉乘与两直线上任意一点的向量的点积为0。 + +參數: + +- other: 另一条直线 + +返回: + +- 是否共面 + + + +
+源碼 + +```python +def is_coplanar(self, other: 'Line3') -> bool: + """ + 判断两条直线是否共面。 + 充要条件:两直线方向向量的叉乘与两直线上任意一点的向量的点积为0。 + Args: + other: 另一条直线 + Returns: + 是否共面 + """ + return self.direction.cross(other.direction) @ (self.point - other.point) == 0 +``` +
+ +### *def* `simplify(self)` + + +简化直线方程,等价相等。 +自体简化,不返回值。 + +按照可行性一次对x y z 化 0 处理,并对向量单位化 + + + +
+源碼 + +```python +def simplify(self): + """ + 简化直线方程,等价相等。 + 自体简化,不返回值。 + + 按照可行性一次对x y z 化 0 处理,并对向量单位化 + """ + self.direction.normalize() + if self.direction.x == 0: + self.point.x = 0 + if self.direction.y == 0: + self.point.y = 0 + if self.direction.z == 0: + self.point.z = 0 +``` +
+ +### `@classmethod` +### *def* `from_two_points(cls, p1: 'Point3', p2: 'Point3') -> 'Line3'` + + +工厂函数 由两点构造直线。 + +參數: + +- p1: 点1 + +- p2: 点2 + +返回: + +- 直线 + + + +
+源碼 + +```python +@classmethod +def from_two_points(cls, p1: 'Point3', p2: 'Point3') -> 'Line3': + """ + 工厂函数 由两点构造直线。 + Args: + p1: 点1 + p2: 点2 + Returns: + 直线 + """ + direction = p2 - p1 + return cls(p1, direction) +``` +
+ +### *def* `__and__(self, other: 'Line3') -> 'Line3 | Point3 | None'` + + +计算两条直线点集合的交集。重合线返回自身,平行线返回None,交线返回交点。 + +參數: + +- other: 另一条直线 + +返回: + +- 交点 + + + +
+源碼 + +```python +def __and__(self, other: 'Line3') -> 'Line3 | Point3 | None': + """ + 计算两条直线点集合的交集。重合线返回自身,平行线返回None,交线返回交点。 + Args: + other: 另一条直线 + Returns: + 交点 + """ + if self.is_collinear(other): + return self + elif self.is_parallel(other) or not self.is_coplanar(other): + return None + else: + return self.cal_intersection(other) +``` +
+ +### *def* `__eq__(self, other) -> bool` + + +判断两条直线是否等价。 + +v1 // v2 ∧ (p1 - p2) // v1 + +參數: + +- other: + + + +
+源碼 + +```python +def __eq__(self, other) -> bool: + """ + 判断两条直线是否等价。 + + v1 // v2 ∧ (p1 - p2) // v1 + Args: + other: + + Returns: + + """ + return self.direction.is_parallel(other.direction) and (self.point - other.point).is_parallel(self.direction) +``` +
+ +### *def* `__str__(self)` + + + + + + +
+源碼 + +```python +def __str__(self): + """ + 返回点向式(x-x0) + Returns: + + """ + s = 'Line3: ' + if self.direction.x != 0: + s += f'(x{sign_format(-self.point.x)})/{self.direction.x}' + if self.direction.y != 0: + s += f' = (y{sign_format(-self.point.y)})/{self.direction.y}' + if self.direction.z != 0: + s += f' = (z{sign_format(-self.point.z)})/{self.direction.z}' + return s +``` +
+ +### *def* `__repr__(self)` + + +
+源碼 + +```python +def __repr__(self): + return f'Line3({self.point}, {self.direction})' +``` +
+ diff --git a/docs/zh-Hant/api/mp_math/mp_math_typing.md b/docs/zh-Hant/api/mp_math/mp_math_typing.md new file mode 100644 index 0000000..b166130 --- /dev/null +++ b/docs/zh-Hant/api/mp_math/mp_math_typing.md @@ -0,0 +1,37 @@ +--- +title: mbcp.mp_math.mp_math_typing +--- +### ***var*** `RealNumber: TypeAlias = int | float` + +### ***var*** `Number: TypeAlias = RealNumber | complex` + +### ***var*** `SingleVar = TypeVar('SingleVar', bound=Number)` + +### ***var*** `ArrayVar = TypeVar('ArrayVar', bound=Iterable[Number])` + +### ***var*** `Var: TypeAlias = SingleVar | ArrayVar` + +### ***var*** `OneSingleVarFunc: TypeAlias = Callable[[SingleVar], SingleVar]` + +### ***var*** `OneArrayFunc: TypeAlias = Callable[[ArrayVar], ArrayVar]` + +### ***var*** `OneVarFunc: TypeAlias = OneSingleVarFunc | OneArrayFunc` + +### ***var*** `TwoSingleVarsFunc: TypeAlias = Callable[[SingleVar, SingleVar], SingleVar]` + +### ***var*** `TwoArraysFunc: TypeAlias = Callable[[ArrayVar, ArrayVar], ArrayVar]` + +### ***var*** `TwoVarsFunc: TypeAlias = TwoSingleVarsFunc | TwoArraysFunc` + +### ***var*** `ThreeSingleVarsFunc: TypeAlias = Callable[[SingleVar, SingleVar, SingleVar], SingleVar]` + +### ***var*** `ThreeArraysFunc: TypeAlias = Callable[[ArrayVar, ArrayVar, ArrayVar], ArrayVar]` + +### ***var*** `ThreeVarsFunc: TypeAlias = ThreeSingleVarsFunc | ThreeArraysFunc` + +### ***var*** `MultiSingleVarsFunc: TypeAlias = Callable[..., SingleVar]` + +### ***var*** `MultiArraysFunc: TypeAlias = Callable[..., ArrayVar]` + +### ***var*** `MultiVarsFunc: TypeAlias = MultiSingleVarsFunc | MultiArraysFunc` + diff --git a/docs/zh-Hant/api/mp_math/plane.md b/docs/zh-Hant/api/mp_math/plane.md new file mode 100644 index 0000000..f19cc6d --- /dev/null +++ b/docs/zh-Hant/api/mp_math/plane.md @@ -0,0 +1,648 @@ +--- +title: mbcp.mp_math.plane +--- +### ***class*** `Plane3` + +### *def* `__init__(self, a: float, b: float, c: float, d: float)` + + +平面方程:ax + by + cz + d = 0 + +參數: + +- a: + +- b: + +- c: + +- d: + + + +
+源碼 + +```python +def __init__(self, a: float, b: float, c: float, d: float): + """ + 平面方程:ax + by + cz + d = 0 + Args: + a: + b: + c: + d: + """ + self.a = a + self.b = b + self.c = c + self.d = d +``` +
+ +### *def* `approx(self, other: 'Plane3') -> bool` + + +判断两个平面是否近似相等。 + +參數: + +- other: + +返回: + +- 是否近似相等 + + + +
+源碼 + +```python +def approx(self, other: 'Plane3') -> bool: + """ + 判断两个平面是否近似相等。 + Args: + other: + + Returns: + 是否近似相等 + """ + a = 3 + if self.a != 0: + k = other.a / self.a + return approx(other.b, self.b * k) and approx(other.c, self.c * k) and approx(other.d, self.d * k) + elif self.b != 0: + k = other.b / self.b + return approx(other.a, self.a * k) and approx(other.c, self.c * k) and approx(other.d, self.d * k) + elif self.c != 0: + k = other.c / self.c + return approx(other.a, self.a * k) and approx(other.b, self.b * k) and approx(other.d, self.d * k) + else: + return False +``` +
+ +### *def* `cal_angle(self, other: 'Line3 | Plane3') -> 'AnyAngle'` + + +计算平面与平面之间的夹角。 + +參數: + +- other: 另一个平面 + +返回: + +- 夹角弧度 + +引發: + +- TypeError 不支持的类型 + + + +
+源碼 + +```python +def cal_angle(self, other: 'Line3 | Plane3') -> 'AnyAngle': + """ + 计算平面与平面之间的夹角。 + Args: + other: 另一个平面 + Returns: + 夹角弧度 + Raises: + TypeError: 不支持的类型 + """ + if isinstance(other, Line3): + return self.normal.cal_angle(other.direction).complementary + elif isinstance(other, Plane3): + return AnyAngle(math.acos(self.normal @ other.normal / (self.normal.length * other.normal.length)), is_radian=True) + else: + raise TypeError(f'Unsupported type: {type(other)}') +``` +
+ +### *def* `cal_distance(self, other: 'Plane3 | Point3') -> float` + + +计算平面与平面或点之间的距离。 + +參數: + +- other: 另一个平面或点 + +返回: + +- 距离 + +引發: + +- TypeError 不支持的类型 + + + +
+源碼 + +```python +def cal_distance(self, other: 'Plane3 | Point3') -> float: + """ + 计算平面与平面或点之间的距离。 + Args: + other: 另一个平面或点 + Returns: + 距离 + Raises: + TypeError: 不支持的类型 + """ + if isinstance(other, Plane3): + return 0 + elif isinstance(other, Point3): + return abs(self.a * other.x + self.b * other.y + self.c * other.z + self.d) / (self.a ** 2 + self.b ** 2 + self.c ** 2) ** 0.5 + else: + raise TypeError(f'Unsupported type: {type(other)}') +``` +
+ +### *def* `cal_intersection_line3(self, other: 'Plane3') -> 'Line3'` + + +计算两平面的交线。该方法有问题,待修复。 + +參數: + +- other: 另一个平面 + +返回: + +- 交线 + + + +
+源碼 + +```python +def cal_intersection_line3(self, other: 'Plane3') -> 'Line3': + """ + 计算两平面的交线。该方法有问题,待修复。 + Args: + other: 另一个平面 + Returns: + 交线 + Raises: + """ + if self.normal.is_parallel(other.normal): + raise ValueError('Planes are parallel and have no intersection.') + direction = self.normal.cross(other.normal) + x, y, z = (0, 0, 0) + if self.a != 0 and other.a != 0: + A = np.array([[self.b, self.c], [other.b, other.c]]) + B = np.array([-self.d, -other.d]) + y, z = np.linalg.solve(A, B) + elif self.b != 0 and other.b != 0: + A = np.array([[self.a, self.c], [other.a, other.c]]) + B = np.array([-self.d, -other.d]) + x, z = np.linalg.solve(A, B) + elif self.c != 0 and other.c != 0: + A = np.array([[self.a, self.b], [other.a, other.b]]) + B = np.array([-self.d, -other.d]) + x, y = np.linalg.solve(A, B) + return Line3(Point3(x, y, z), direction) +``` +
+ +### *def* `cal_intersection_point3(self, other: 'Line3') -> 'Point3'` + + +计算平面与直线的交点。 + +參數: + +- other: 不与平面平行或在平面上的直线 + +返回: + +- 交点 + +引發: + +- ValueError 平面与直线平行或重合 + + + +
+源碼 + +```python +def cal_intersection_point3(self, other: 'Line3') -> 'Point3': + """ + 计算平面与直线的交点。 + Args: + other: 不与平面平行或在平面上的直线 + Returns: + 交点 + Raises: + ValueError: 平面与直线平行或重合 + """ + if self.normal @ other.direction == 0: + raise ValueError('The plane and the line are parallel or coincident.') + x, y, z = other.get_parametric_equations() + t = -(self.a * other.point.x + self.b * other.point.y + self.c * other.point.z + self.d) / (self.a * other.direction.x + self.b * other.direction.y + self.c * other.direction.z) + return Point3(x(t), y(t), z(t)) +``` +
+ +### *def* `cal_parallel_plane3(self, point: 'Point3') -> 'Plane3'` + + +计算平行于该平面且过指定点的平面。 + +參數: + +- point: 指定点 + +返回: + +- 平面 + + + +
+源碼 + +```python +def cal_parallel_plane3(self, point: 'Point3') -> 'Plane3': + """ + 计算平行于该平面且过指定点的平面。 + Args: + point: 指定点 + Returns: + 平面 + """ + return Plane3.from_point_and_normal(point, self.normal) +``` +
+ +### *def* `is_parallel(self, other: 'Plane3') -> bool` + + +判断两个平面是否平行。 + +參數: + +- other: 另一个平面 + +返回: + +- 是否平行 + + + +
+源碼 + +```python +def is_parallel(self, other: 'Plane3') -> bool: + """ + 判断两个平面是否平行。 + Args: + other: 另一个平面 + Returns: + 是否平行 + """ + return self.normal.is_parallel(other.normal) +``` +
+ +### `@property` +### *def* `normal(self) -> 'Vector3'` + + +平面的法向量。 + +返回: + +- 法向量 + + + +
+源碼 + +```python +@property +def normal(self) -> 'Vector3': + """ + 平面的法向量。 + Returns: + 法向量 + """ + return Vector3(self.a, self.b, self.c) +``` +
+ +### `@classmethod` +### *def* `from_point_and_normal(cls, point: 'Point3', normal: 'Vector3') -> 'Plane3'` + + +工厂函数 由点和法向量构造平面(点法式构造)。 + +參數: + +- point: 平面上的一点 + +- normal: 法向量 + +返回: + +- 平面 + + + +
+源碼 + +```python +@classmethod +def from_point_and_normal(cls, point: 'Point3', normal: 'Vector3') -> 'Plane3': + """ + 工厂函数 由点和法向量构造平面(点法式构造)。 + Args: + point: 平面上的一点 + normal: 法向量 + Returns: + 平面 + """ + a, b, c = (normal.x, normal.y, normal.z) + d = -a * point.x - b * point.y - c * point.z + return cls(a, b, c, d) +``` +
+ +### `@classmethod` +### *def* `from_three_points(cls, p1: 'Point3', p2: 'Point3', p3: 'Point3') -> 'Plane3'` + + +工厂函数 由三点构造平面。 + +參數: + +- p1: 点1 + +- p2: 点2 + +- p3: 点3 + +返回: + +- 平面 + + + +
+源碼 + +```python +@classmethod +def from_three_points(cls, p1: 'Point3', p2: 'Point3', p3: 'Point3') -> 'Plane3': + """ + 工厂函数 由三点构造平面。 + Args: + p1: 点1 + p2: 点2 + p3: 点3 + Returns: + 平面 + """ + v1 = p2 - p1 + v2 = p3 - p1 + normal = v1.cross(v2) + return cls.from_point_and_normal(p1, normal) +``` +
+ +### `@classmethod` +### *def* `from_two_lines(cls, l1: 'Line3', l2: 'Line3') -> 'Plane3'` + + +工厂函数 由两直线构造平面。 + +參數: + +- l1: 直线1 + +- l2: 直线2 + +返回: + +- 平面 + + + +
+源碼 + +```python +@classmethod +def from_two_lines(cls, l1: 'Line3', l2: 'Line3') -> 'Plane3': + """ + 工厂函数 由两直线构造平面。 + Args: + l1: 直线1 + l2: 直线2 + Returns: + 平面 + """ + v1 = l1.direction + v2 = l2.point - l1.point + if v2 == zero_vector3: + v2 = l2.get_point(1) - l1.point + return cls.from_point_and_normal(l1.point, v1.cross(v2)) +``` +
+ +### `@classmethod` +### *def* `from_point_and_line(cls, point: 'Point3', line: 'Line3') -> 'Plane3'` + + +工厂函数 由点和直线构造平面。 + +參數: + +- point: 面上一点 + +- line: 面上直线,不包含点 + +返回: + +- 平面 + + + +
+源碼 + +```python +@classmethod +def from_point_and_line(cls, point: 'Point3', line: 'Line3') -> 'Plane3': + """ + 工厂函数 由点和直线构造平面。 + Args: + point: 面上一点 + line: 面上直线,不包含点 + Returns: + 平面 + """ + return cls.from_point_and_normal(point, line.direction) +``` +
+ +### *def* `__repr__(self)` + + +
+源碼 + +```python +def __repr__(self): + return f'Plane3({self.a}, {self.b}, {self.c}, {self.d})' +``` +
+ +### *def* `__str__(self)` + + +
+源碼 + +```python +def __str__(self): + s = 'Plane3: ' + if self.a != 0: + s += f'{sign(self.a, only_neg=True)}{abs(self.a)}x' + if self.b != 0: + s += f' {sign(self.b)} {abs(self.b)}y' + if self.c != 0: + s += f' {sign(self.c)} {abs(self.c)}z' + if self.d != 0: + s += f' {sign(self.d)} {abs(self.d)}' + return s + ' = 0' +``` +
+ +### `@overload` +### *def* `__and__(self, other: 'Line3') -> 'Point3 | None'` + + +
+源碼 + +```python +@overload +def __and__(self, other: 'Line3') -> 'Point3 | None': + ... +``` +
+ +### `@overload` +### *def* `__and__(self, other: 'Plane3') -> 'Line3 | None'` + + +
+源碼 + +```python +@overload +def __and__(self, other: 'Plane3') -> 'Line3 | None': + ... +``` +
+ +### *def* `__and__(self, other)` + + +取两平面的交集(人话:交线) + +參數: + +- other: + +返回: + +- 不平行平面的交线,平面平行返回None + + + +
+源碼 + +```python +def __and__(self, other): + """ + 取两平面的交集(人话:交线) + Args: + other: + Returns: + 不平行平面的交线,平面平行返回None + """ + if isinstance(other, Plane3): + if self.normal.is_parallel(other.normal): + return None + return self.cal_intersection_line3(other) + elif isinstance(other, Line3): + if self.normal @ other.direction == 0: + return None + return self.cal_intersection_point3(other) + else: + raise TypeError(f"unsupported operand type(s) for &: 'Plane3' and '{type(other)}'") +``` +
+ +### *def* `__eq__(self, other) -> bool` + + +
+源碼 + +```python +def __eq__(self, other) -> bool: + return self.approx(other) +``` +
+ +### *def* `__rand__(self, other: 'Line3') -> 'Point3'` + + +
+源碼 + +```python +def __rand__(self, other: 'Line3') -> 'Point3': + return self.cal_intersection_point3(other) +``` +
+ +### ***var*** `k = other.a / self.a` + +### ***var*** `A = np.array([[self.b, self.c], [other.b, other.c]])` + +### ***var*** `B = np.array([-self.d, -other.d])` + +### ***var*** `v2 = l2.get_point(1) - l1.point` + +### ***var*** `k = other.b / self.b` + +### ***var*** `A = np.array([[self.a, self.c], [other.a, other.c]])` + +### ***var*** `B = np.array([-self.d, -other.d])` + +### ***var*** `k = other.c / self.c` + +### ***var*** `A = np.array([[self.a, self.b], [other.a, other.b]])` + +### ***var*** `B = np.array([-self.d, -other.d])` + diff --git a/docs/zh-Hant/api/mp_math/point.md b/docs/zh-Hant/api/mp_math/point.md new file mode 100644 index 0000000..f8b52e8 --- /dev/null +++ b/docs/zh-Hant/api/mp_math/point.md @@ -0,0 +1,199 @@ +--- +title: mbcp.mp_math.point +--- +### ***class*** `Point3` + +### *def* `__init__(self, x: float, y: float, z: float)` + + +笛卡尔坐标系中的点。 + +參數: + +- x: x 坐标 + +- y: y 坐标 + +- z: z 坐标 + + + +
+源碼 + +```python +def __init__(self, x: float, y: float, z: float): + """ + 笛卡尔坐标系中的点。 + Args: + x: x 坐标 + y: y 坐标 + z: z 坐标 + """ + self.x = x + self.y = y + self.z = z +``` +
+ +### *def* `approx(self, other: 'Point3', epsilon: float = APPROX) -> bool` + + +判断两个点是否近似相等。 + +參數: + +- other: + +- epsilon: + +返回: + +- 是否近似相等 + + + +
+源碼 + +```python +def approx(self, other: 'Point3', epsilon: float=APPROX) -> bool: + """ + 判断两个点是否近似相等。 + Args: + other: + epsilon: + + Returns: + 是否近似相等 + """ + return all([abs(self.x - other.x) < epsilon, abs(self.y - other.y) < epsilon, abs(self.z - other.z) < epsilon]) +``` +
+ +### *def* `__str__(self)` + + +
+源碼 + +```python +def __str__(self): + return f'Point3({self.x}, {self.y}, {self.z})' +``` +
+ +### `@overload` +### *def* `__add__(self, other: 'Vector3') -> 'Point3'` + + +
+源碼 + +```python +@overload +def __add__(self, other: 'Vector3') -> 'Point3': + ... +``` +
+ +### `@overload` +### *def* `__add__(self, other: 'Point3') -> 'Point3'` + + +
+源碼 + +```python +@overload +def __add__(self, other: 'Point3') -> 'Point3': + ... +``` +
+ +### *def* `__add__(self, other)` + + +P + V -> P +P + P -> P + +參數: + +- other: + + + +
+源碼 + +```python +def __add__(self, other): + """ + P + V -> P + P + P -> P + Args: + other: + Returns: + """ + return Point3(self.x + other.x, self.y + other.y, self.z + other.z) +``` +
+ +### *def* `__eq__(self, other)` + + +判断两个点是否相等。 + +參數: + +- other: + + + +
+源碼 + +```python +def __eq__(self, other): + """ + 判断两个点是否相等。 + Args: + other: + Returns: + """ + return approx(self.x, other.x) and approx(self.y, other.y) and approx(self.z, other.z) +``` +
+ +### *def* `__sub__(self, other: 'Point3') -> 'Vector3'` + + +P - P -> V + +P - V -> P 已在 :class:`Vector3` 中实现 + +參數: + +- other: + + + +
+源碼 + +```python +def __sub__(self, other: 'Point3') -> 'Vector3': + """ + P - P -> V + + P - V -> P 已在 :class:`Vector3` 中实现 + Args: + other: + Returns: + + """ + from .vector import Vector3 + return Vector3(self.x - other.x, self.y - other.y, self.z - other.z) +``` +
+ diff --git a/docs/zh-Hant/api/mp_math/segment.md b/docs/zh-Hant/api/mp_math/segment.md new file mode 100644 index 0000000..54a2eae --- /dev/null +++ b/docs/zh-Hant/api/mp_math/segment.md @@ -0,0 +1,59 @@ +--- +title: mbcp.mp_math.segment +--- +### ***class*** `Segment3` + +### *def* `__init__(self, p1: 'Point3', p2: 'Point3')` + + +三维空间中的线段。 +:param p1: +:param p2: + + + +
+源碼 + +```python +def __init__(self, p1: 'Point3', p2: 'Point3'): + """ + 三维空间中的线段。 + :param p1: + :param p2: + """ + self.p1 = p1 + self.p2 = p2 + '方向向量' + self.direction = self.p2 - self.p1 + '长度' + self.length = self.direction.length + '中心点' + self.midpoint = Point3((self.p1.x + self.p2.x) / 2, (self.p1.y + self.p2.y) / 2, (self.p1.z + self.p2.z) / 2) +``` +
+ +### *def* `__repr__(self)` + + +
+源碼 + +```python +def __repr__(self): + return f'Segment3({self.p1}, {self.p2})' +``` +
+ +### *def* `__str__(self)` + + +
+源碼 + +```python +def __str__(self): + return f'Segment3({self.p1} -> {self.p2})' +``` +
+ diff --git a/docs/zh-Hant/api/mp_math/utils.md b/docs/zh-Hant/api/mp_math/utils.md new file mode 100644 index 0000000..57bb639 --- /dev/null +++ b/docs/zh-Hant/api/mp_math/utils.md @@ -0,0 +1,220 @@ +--- +title: mbcp.mp_math.utils +--- +### *def* `clamp() -> float` + + +区间截断函数。 + +參數: + +- x: + +- min_: + +- max_: + +返回: + +- 限制后的值 + + + +
+源碼 + +```python +def clamp(x: float, min_: float, max_: float) -> float: + """ + 区间截断函数。 + Args: + x: + min_: + max_: + + Returns: + 限制后的值 + """ + return max(min(x, max_), min_) +``` +
+ +### *def* `approx(x: float = 0.0, y: float = APPROX) -> bool` + + +判断两个数是否近似相等。或包装一个实数,用于判断是否近似于0。 + +參數: + +- x: + +- y: + +- epsilon: + +返回: + +- 是否近似相等 + + + +
+源碼 + +```python +def approx(x: float, y: float=0.0, epsilon: float=APPROX) -> bool: + """ + 判断两个数是否近似相等。或包装一个实数,用于判断是否近似于0。 + Args: + x: + y: + epsilon: + + Returns: + 是否近似相等 + """ + return abs(x - y) < epsilon +``` +
+ +### *def* `sign(x: float = False) -> str` + + +获取数的符号。 + +參數: + +- x: 数 + +- only_neg: 是否只返回负数的符号 + +返回: + +- 符号 + - "" + + + +
+源碼 + +```python +def sign(x: float, only_neg: bool=False) -> str: + """获取数的符号。 + Args: + x: 数 + only_neg: 是否只返回负数的符号 + Returns: + 符号 + - "" + """ + if x > 0: + return '+' if not only_neg else '' + elif x < 0: + return '-' + else: + return '' +``` +
+ +### *def* `sign_format(x: float = False) -> str` + + +格式化符号数 +-1 -> -1 +1 -> +1 +0 -> "" + +參數: + +- x: 数 + +- only_neg: 是否只返回负数的符号 + +返回: + +- 符号 + - "" + + + +
+源碼 + +```python +def sign_format(x: float, only_neg: bool=False) -> str: + """格式化符号数 + -1 -> -1 + 1 -> +1 + 0 -> "" + Args: + x: 数 + only_neg: 是否只返回负数的符号 + Returns: + 符号 + - "" + """ + if x > 0: + return f'+{x}' if not only_neg else f'{x}' + elif x < 0: + return f'-{abs(x)}' + else: + return '' +``` +
+ +### ***class*** `Approx` + +### *def* `__init__(self, value: RealNumber)` + + +
+源碼 + +```python +def __init__(self, value: RealNumber): + self.value = value +``` +
+ +### *def* `__eq__(self, other)` + + +
+源碼 + +```python +def __eq__(self, other): + if isinstance(self.value, (float, int)): + if isinstance(other, (float, int)): + return abs(self.value - other) < APPROX + else: + self.raise_type_error(other) + elif isinstance(self.value, Vector3): + if isinstance(other, (Vector3, Point3, Plane3, Line3)): + return all([approx(self.value.x, other.x), approx(self.value.y, other.y), approx(self.value.z, other.z)]) + else: + self.raise_type_error(other) +``` +
+ +### *def* `raise_type_error(self, other)` + + +
+源碼 + +```python +def raise_type_error(self, other): + raise TypeError(f'Unsupported type: {type(self.value)} and {type(other)}') +``` +
+ +### *def* `__ne__(self, other)` + + +
+源碼 + +```python +def __ne__(self, other): + return not self.__eq__(other) +``` +
+ diff --git a/docs/zh-Hant/api/mp_math/vector.md b/docs/zh-Hant/api/mp_math/vector.md new file mode 100644 index 0000000..c496b5c --- /dev/null +++ b/docs/zh-Hant/api/mp_math/vector.md @@ -0,0 +1,699 @@ +--- +title: mbcp.mp_math.vector +--- +### ***class*** `Vector3` + +### *def* `__init__(self, x: float, y: float, z: float)` + + +3维向量 + +參數: + +- x: x轴分量 + +- y: y轴分量 + +- z: z轴分量 + + + +
+源碼 + +```python +def __init__(self, x: float, y: float, z: float): + """ + 3维向量 + Args: + x: x轴分量 + y: y轴分量 + z: z轴分量 + """ + self.x = x + self.y = y + self.z = z +``` +
+ +### *def* `approx(self, other: 'Vector3', epsilon: float = APPROX) -> bool` + + +判断两个向量是否近似相等。 + +參數: + +- other: + +- epsilon: + +返回: + +- 是否近似相等 + + + +
+源碼 + +```python +def approx(self, other: 'Vector3', epsilon: float=APPROX) -> bool: + """ + 判断两个向量是否近似相等。 + Args: + other: + epsilon: + + Returns: + 是否近似相等 + """ + return all([abs(self.x - other.x) < epsilon, abs(self.y - other.y) < epsilon, abs(self.z - other.z) < epsilon]) +``` +
+ +### *def* `cal_angle(self, other: 'Vector3') -> 'AnyAngle'` + + +计算两个向量之间的夹角。 + +參數: + +- other: 另一个向量 + +返回: + +- 夹角 + + + +
+源碼 + +```python +def cal_angle(self, other: 'Vector3') -> 'AnyAngle': + """ + 计算两个向量之间的夹角。 + Args: + other: 另一个向量 + Returns: + 夹角 + """ + return AnyAngle(math.acos(self @ other / (self.length * other.length)), is_radian=True) +``` +
+ +### *def* `cross(self, other: 'Vector3') -> 'Vector3'` + + +向量积 叉乘:v1 cross v2 -> v3 + +叉乘为0,则两向量平行。 +其余结果的模为平行四边形的面积。 + + +參數: + +- other: + +返回: + +- 行列式的结果 + + + +
+源碼 + +```python +def cross(self, other: 'Vector3') -> 'Vector3': + """ + 向量积 叉乘:v1 cross v2 -> v3 + + 叉乘为0,则两向量平行。 + 其余结果的模为平行四边形的面积。 + + 返回如下行列式的结果: + + ``i j k`` + + ``x1 y1 z1`` + + ``x2 y2 z2`` + + Args: + other: + Returns: + 行列式的结果 + """ + 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* `is_approx_parallel(self, other: 'Vector3', epsilon: float = APPROX) -> bool` + + +判断两个向量是否近似平行。 + +參數: + +- other: 另一个向量 + +- epsilon: 允许的误差 + +返回: + +- 是否近似平行 + + + +
+源碼 + +```python +def is_approx_parallel(self, other: 'Vector3', epsilon: float=APPROX) -> bool: + """ + 判断两个向量是否近似平行。 + Args: + other: 另一个向量 + epsilon: 允许的误差 + Returns: + 是否近似平行 + """ + return self.cross(other).length < epsilon +``` +
+ +### *def* `is_parallel(self, other: 'Vector3') -> bool` + + +判断两个向量是否平行。 + +參數: + +- other: 另一个向量 + +返回: + +- 是否平行 + + + +
+源碼 + +```python +def is_parallel(self, other: 'Vector3') -> bool: + """ + 判断两个向量是否平行。 + Args: + other: 另一个向量 + Returns: + 是否平行 + """ + return self.cross(other).approx(zero_vector3) +``` +
+ +### *def* `normalize(self)` + + +将向量归一化。 + +自体归一化,不返回值。 + + + +
+源碼 + +```python +def normalize(self): + """ + 将向量归一化。 + + 自体归一化,不返回值。 + """ + length = self.length + self.x /= length + self.y /= length + self.z /= length +``` +
+ +### `@property` +### *def* `np_array(self) -> 'np.ndarray'` + + + + + + +
+源碼 + +```python +@property +def np_array(self) -> 'np.ndarray': + """ + 返回numpy数组 + Returns: + """ + return np.array([self.x, self.y, self.z]) +``` +
+ +### `@property` +### *def* `length(self) -> float` + + +向量的模。 + +返回: + +- 模 + + + +
+源碼 + +```python +@property +def length(self) -> float: + """ + 向量的模。 + Returns: + 模 + """ + return math.sqrt(self.x ** 2 + self.y ** 2 + self.z ** 2) +``` +
+ +### `@property` +### *def* `unit(self) -> 'Vector3'` + + +获取该向量的单位向量。 + +返回: + +- 单位向量 + + + +
+源碼 + +```python +@property +def unit(self) -> 'Vector3': + """ + 获取该向量的单位向量。 + Returns: + 单位向量 + """ + return self / self.length +``` +
+ +### *def* `__abs__(self)` + + +
+源碼 + +```python +def __abs__(self): + return self.length +``` +
+ +### `@overload` +### *def* `__add__(self, other: 'Vector3') -> 'Vector3'` + + +
+源碼 + +```python +@overload +def __add__(self, other: 'Vector3') -> 'Vector3': + ... +``` +
+ +### `@overload` +### *def* `__add__(self, other: 'Point3') -> 'Point3'` + + +
+源碼 + +```python +@overload +def __add__(self, other: 'Point3') -> 'Point3': + ... +``` +
+ +### *def* `__add__(self, other)` + + +V + P -> P + +V + V -> V + +參數: + +- other: + + + +
+源碼 + +```python +def __add__(self, other): + """ + V + P -> P + + V + V -> V + Args: + other: + Returns: + + """ + if isinstance(other, Vector3): + 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) + else: + raise TypeError(f"unsupported operand type(s) for +: 'Vector3' and '{type(other)}'") +``` +
+ +### *def* `__eq__(self, other)` + + +判断两个向量是否相等。 + +參數: + +- other: + +返回: + +- 是否相等 + + + +
+源碼 + +```python +def __eq__(self, other): + """ + 判断两个向量是否相等。 + Args: + other: + Returns: + 是否相等 + """ + return approx(self.x, other.x) and approx(self.y, other.y) and approx(self.z, other.z) +``` +
+ +### *def* `__radd__(self, other: 'Point3') -> 'Point3'` + + +P + V -> P + +别去点那边实现了。 +:param other: +:return: + + + +
+源碼 + +```python +def __radd__(self, other: 'Point3') -> 'Point3': + """ + P + V -> P + + 别去点那边实现了。 + :param other: + :return: + """ + return Point3(self.x + other.x, self.y + other.y, self.z + other.z) +``` +
+ +### `@overload` +### *def* `__sub__(self, other: 'Vector3') -> 'Vector3'` + + +
+源碼 + +```python +@overload +def __sub__(self, other: 'Vector3') -> 'Vector3': + ... +``` +
+ +### `@overload` +### *def* `__sub__(self, other: 'Point3') -> 'Point3'` + + +
+源碼 + +```python +@overload +def __sub__(self, other: 'Point3') -> 'Point3': + ... +``` +
+ +### *def* `__sub__(self, other)` + + +V - P -> P + +V - V -> V + +參數: + +- other: + + + +
+源碼 + +```python +def __sub__(self, other): + """ + V - P -> P + + V - V -> V + Args: + other: + Returns: + """ + if isinstance(other, Vector3): + 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) + else: + raise TypeError(f'unsupported operand type(s) for -: "Vector3" and "{type(other)}"') +``` +
+ +### *def* `__rsub__(self, other: 'Point3')` + + +P - V -> P + +參數: + +- other: + + + +
+源碼 + +```python +def __rsub__(self, other: 'Point3'): + """ + P - V -> P + Args: + other: + Returns: + + """ + if isinstance(other, Point3): + 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: 'Vector3') -> 'Vector3'` + + +
+源碼 + +```python +@overload +def __mul__(self, other: 'Vector3') -> 'Vector3': + ... +``` +
+ +### `@overload` +### *def* `__mul__(self, other: RealNumber) -> 'Vector3'` + + +
+源碼 + +```python +@overload +def __mul__(self, other: RealNumber) -> 'Vector3': + ... +``` +
+ +### *def* `__mul__(self, other: 'int | float | Vector3') -> 'Vector3'` + + +数组运算 非点乘。点乘使用@,叉乘使用cross。 + +參數: + +- other: + + + +
+源碼 + +```python +def __mul__(self, other: 'int | float | Vector3') -> 'Vector3': + """ + 数组运算 非点乘。点乘使用@,叉乘使用cross。 + Args: + other: + + Returns: + """ + if isinstance(other, Vector3): + return Vector3(self.x * other.x, self.y * other.y, self.z * other.z) + elif isinstance(other, (float, int)): + return Vector3(self.x * other, self.y * other, self.z * other) + else: + raise TypeError(f"unsupported operand type(s) for *: 'Vector3' and '{type(other)}'") +``` +
+ +### *def* `__rmul__(self, other: 'RealNumber') -> 'Vector3'` + + +
+源碼 + +```python +def __rmul__(self, other: 'RealNumber') -> 'Vector3': + return self.__mul__(other) +``` +
+ +### *def* `__matmul__(self, other: 'Vector3') -> 'RealNumber'` + + +点乘。 + +參數: + +- other: + + + +
+源碼 + +```python +def __matmul__(self, other: 'Vector3') -> 'RealNumber': + """ + 点乘。 + Args: + other: + Returns: + """ + return self.x * other.x + self.y * other.y + self.z * other.z +``` +
+ +### *def* `__truediv__(self, other: RealNumber) -> 'Vector3'` + + +
+源碼 + +```python +def __truediv__(self, other: RealNumber) -> 'Vector3': + return Vector3(self.x / other, self.y / other, self.z / other) +``` +
+ +### *def* `__neg__(self)` + + +
+源碼 + +```python +def __neg__(self): + return Vector3(-self.x, -self.y, -self.z) +``` +
+ +### *def* `__repr__(self)` + + +
+源碼 + +```python +def __repr__(self): + return f'Vector3({self.x}, {self.y}, {self.z})' +``` +
+ +### *def* `__str__(self)` + + +
+源碼 + +```python +def __str__(self): + return f'Vector3({self.x}, {self.y}, {self.z})' +``` +
+ +### ***var*** `zero_vector3 = Vector3(0, 0, 0)` + +### ***var*** `x_axis = Vector3(1, 0, 0)` + +### ***var*** `y_axis = Vector3(0, 1, 0)` + +### ***var*** `z_axis = Vector3(0, 0, 1)` + diff --git a/docs/zh-Hant/api/particle/index.md b/docs/zh-Hant/api/particle/index.md new file mode 100644 index 0000000..4b514d5 --- /dev/null +++ b/docs/zh-Hant/api/particle/index.md @@ -0,0 +1,3 @@ +--- +title: mbcp.particle +--- diff --git a/docs/zh-Hant/api/presets/index.md b/docs/zh-Hant/api/presets/index.md new file mode 100644 index 0000000..472366f --- /dev/null +++ b/docs/zh-Hant/api/presets/index.md @@ -0,0 +1,3 @@ +--- +title: mbcp.presets +--- diff --git a/docs/zh-Hant/api/presets/model/index.md b/docs/zh-Hant/api/presets/model/index.md new file mode 100644 index 0000000..123e021 --- /dev/null +++ b/docs/zh-Hant/api/presets/model/index.md @@ -0,0 +1,48 @@ +--- +title: mbcp.presets.model +--- +### ***class*** `GeometricModels` + +### `@staticmethod` +### *def* `sphere(radius: float, density: float)` + + +生成球体上的点集。 + +參數: + +- radius: + +- density: + +返回: + +- List[Point3]: 球体上的点集。 + + + +
+源碼 + +```python +@staticmethod +def sphere(radius: float, density: float): + """ + 生成球体上的点集。 + Args: + radius: + density: + Returns: + List[Point3]: 球体上的点集。 + """ + area = 4 * np.pi * radius ** 2 + num = int(area * density) + phi_list = np.arccos([clamp(-1 + (2.0 * _ - 1.0) / num, -1, 1) for _ in range(num)]) + theta_list = np.sqrt(num * np.pi) * phi_list + x_array = radius * np.sin(phi_list) * np.cos(theta_list) + y_array = radius * np.sin(phi_list) * np.sin(theta_list) + z_array = radius * np.cos(phi_list) + return [Point3(x_array[i], y_array[i], z_array[i]) for i in range(num)] +``` +
+ diff --git a/liteyuki_autodoc/docstring/parser.py b/liteyuki_autodoc/docstring/parser.py index 52e6b7c..df7096d 100644 --- a/liteyuki_autodoc/docstring/parser.py +++ b/liteyuki_autodoc/docstring/parser.py @@ -52,10 +52,30 @@ class GoogleDocstringParser(Parser): self.docstring = Docstring() + def read_line(self, move: bool = True) -> str: + """ + 每次读取一行 + Args: + move: 是否移动指针 + Returns: + """ + if self.lineno >= len(self.lines): + return "" + line = self.lines[self.lineno] + if move: + self.lineno += 1 + return line + def match_token(self) -> Optional[str]: + """ + 解析下一行的token + Returns: + + """ for token in self._tokens: - if self.lines[self.lineno][self.char:].startswith(token): - self.char += len(token) + line = self.read_line(move=False) + if line.strip().startswith(token): + self.lineno += 1 return self._tokens[token] return None @@ -115,17 +135,12 @@ class GoogleDocstringParser(Parser): 在一个子解析器中,解析下一行,直到缩进小于等于当前行的缩进 Returns: """ - while (self.lineno + 1) < len(self.lines): - line = self.lines[self.lineno + 1] - if line.startswith(" " * self.indent): - line = line[self.indent:] - self.lineno += 1 - return line - else: - self.lineno += 1 - return None - self.lineno += 1 - return None + line = self.read_line(move=False) + if line.startswith(" " * self.indent): + self.lineno += 1 + return line[self.indent:] + else: + return None def parse(self) -> Docstring: """ diff --git a/mkdoc.bat b/mkdoc.bat new file mode 100644 index 0000000..a658d57 --- /dev/null +++ b/mkdoc.bat @@ -0,0 +1,4 @@ +python -m liteyuki_autodoc mbcp -o docs/api -l zh-Hans +python -m liteyuki_autodoc mbcp -o docs/en/api -l en +python -m liteyuki_autodoc mbcp -o docs/ja/api -l ja +python -m liteyuki_autodoc mbcp -o docs/zh-Hant/api -l zh-Hant \ No newline at end of file