From c6ab7f34e97952afd201f876e0f2dd28cb52794f Mon Sep 17 00:00:00 2001 From: snowy Date: Wed, 28 Aug 2024 22:07:43 +0800 Subject: [PATCH] =?UTF-8?q?:memo:=20litedoc=E6=96=B0=E5=A2=9E=E7=B1=BB?= =?UTF-8?q?=E7=BB=A7=E6=89=BF=E6=98=BE=E7=A4=BA=EF=BC=8C=E6=96=B0=E5=A2=9E?= =?UTF-8?q?=E5=8F=98=E9=87=8F=E8=87=AA=E5=8A=A8=E8=8E=B7=E5=8F=96=E6=B3=A8?= =?UTF-8?q?=E9=87=8A=EF=BC=8C=E6=96=B0=E5=A2=9E=E7=B1=BB=E6=96=B9=E6=B3=95?= =?UTF-8?q?=E5=92=8C=E5=87=BD=E6=95=B0=E7=9A=84=E5=8C=BA=E5=88=86=EF=BC=8C?= =?UTF-8?q?=E6=96=B0=E5=A2=9E=E9=AD=94=E6=9C=AF=E6=96=B9=E6=B3=95=E7=9A=84?= =?UTF-8?q?=E7=89=B9=E6=AE=8A=E5=B1=95=E7=A4=BA=E6=A8=A1=E5=BC=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/workflows/deploy-docs.yml | 6 +- docs/.vitepress/config/en.ts | 6 +- docs/.vitepress/config/index.ts | 6 +- docs/.vitepress/config/ja.ts | 14 + docs/.vitepress/config/zh.ts | 11 +- docs/.vitepress/config/zht.ts | 14 + docs/api/mp_math/angle.md | 130 ++-- docs/api/mp_math/const.md | 12 - docs/api/mp_math/equation.md | 51 +- docs/api/mp_math/line.md | 209 +++--- docs/api/mp_math/mp_math_typing.md | 60 +- docs/api/mp_math/plane.md | 246 ++++--- docs/api/mp_math/point.md | 57 +- docs/api/mp_math/segment.md | 31 +- docs/api/mp_math/utils.md | 88 ++- docs/api/mp_math/vector.md | 205 +++--- docs/api/presets/model/index.md | 13 +- docs/en/api/index.md | 3 + docs/en/api/mp_math/angle.md | 423 +++++++++++ docs/en/api/mp_math/const.md | 3 + docs/en/api/mp_math/equation.md | 162 ++++ docs/en/api/mp_math/index.md | 3 + docs/en/api/mp_math/line.md | 581 +++++++++++++++ docs/en/api/mp_math/mp_math_typing.md | 63 ++ docs/en/api/mp_math/plane.md | 592 +++++++++++++++ docs/en/api/mp_math/point.md | 186 +++++ docs/en/api/mp_math/segment.md | 34 + docs/en/api/mp_math/utils.md | 218 ++++++ docs/en/api/mp_math/vector.md | 690 ++++++++++++++++++ docs/en/api/particle/index.md | 3 + docs/en/api/presets/index.md | 3 + docs/en/api/presets/model/index.md | 47 ++ docs/guide/index.md | 1 + docs/index.md | 2 +- docs/ja/api/index.md | 3 + docs/ja/api/mp_math/angle.md | 423 +++++++++++ docs/ja/api/mp_math/const.md | 3 + docs/ja/api/mp_math/equation.md | 162 ++++ docs/ja/api/mp_math/index.md | 3 + docs/ja/api/mp_math/line.md | 581 +++++++++++++++ docs/ja/api/mp_math/mp_math_typing.md | 63 ++ docs/ja/api/mp_math/plane.md | 592 +++++++++++++++ docs/ja/api/mp_math/point.md | 186 +++++ docs/ja/api/mp_math/segment.md | 34 + docs/ja/api/mp_math/utils.md | 218 ++++++ docs/ja/api/mp_math/vector.md | 690 ++++++++++++++++++ docs/ja/api/particle/index.md | 3 + docs/ja/api/presets/index.md | 3 + docs/ja/api/presets/model/index.md | 47 ++ docs/zht/api/index.md | 3 + docs/zht/api/mp_math/angle.md | 423 +++++++++++ docs/zht/api/mp_math/const.md | 3 + docs/zht/api/mp_math/equation.md | 162 ++++ docs/zht/api/mp_math/index.md | 3 + docs/zht/api/mp_math/line.md | 581 +++++++++++++++ docs/zht/api/mp_math/mp_math_typing.md | 63 ++ docs/zht/api/mp_math/plane.md | 592 +++++++++++++++ docs/zht/api/mp_math/point.md | 186 +++++ docs/zht/api/mp_math/segment.md | 34 + docs/zht/api/mp_math/utils.md | 218 ++++++ docs/zht/api/mp_math/vector.md | 690 ++++++++++++++++++ docs/zht/api/particle/index.md | 3 + docs/zht/api/presets/index.md | 3 + docs/zht/api/presets/model/index.md | 47 ++ {liteyuki_autodoc => litedoc}/__init__.py | 0 {liteyuki_autodoc => litedoc}/__main__.py | 2 +- .../docstring/__init__.py | 0 .../docstring/docstring.py | 14 +- .../docstring/parser.py | 43 +- {liteyuki_autodoc => litedoc}/i18n.py | 18 +- {liteyuki_autodoc => litedoc}/output.py | 4 +- .../style/__init__.py | 0 .../style/markdown.py | 32 +- .../syntax/astparser.py | 135 +++- {liteyuki_autodoc => litedoc}/syntax/node.py | 89 ++- litedoc/translator.py | 47 ++ mbcp/mp_math/plane.py | 20 +- mbcp/mp_math/utils.py | 16 +- mbcp/mp_math/vector.py | 8 +- mkdoc.bat | 4 + pyproject.toml | 5 + tests/test_doc_translator.py | 16 + 82 files changed, 9965 insertions(+), 683 deletions(-) create mode 100644 docs/.vitepress/config/ja.ts create mode 100644 docs/.vitepress/config/zht.ts create mode 100644 docs/en/api/index.md create mode 100644 docs/en/api/mp_math/angle.md create mode 100644 docs/en/api/mp_math/const.md create mode 100644 docs/en/api/mp_math/equation.md create mode 100644 docs/en/api/mp_math/index.md create mode 100644 docs/en/api/mp_math/line.md create mode 100644 docs/en/api/mp_math/mp_math_typing.md create mode 100644 docs/en/api/mp_math/plane.md create mode 100644 docs/en/api/mp_math/point.md create mode 100644 docs/en/api/mp_math/segment.md create mode 100644 docs/en/api/mp_math/utils.md create mode 100644 docs/en/api/mp_math/vector.md create mode 100644 docs/en/api/particle/index.md create mode 100644 docs/en/api/presets/index.md create mode 100644 docs/en/api/presets/model/index.md create mode 100644 docs/guide/index.md create mode 100644 docs/ja/api/index.md create mode 100644 docs/ja/api/mp_math/angle.md create mode 100644 docs/ja/api/mp_math/const.md create mode 100644 docs/ja/api/mp_math/equation.md create mode 100644 docs/ja/api/mp_math/index.md create mode 100644 docs/ja/api/mp_math/line.md create mode 100644 docs/ja/api/mp_math/mp_math_typing.md create mode 100644 docs/ja/api/mp_math/plane.md create mode 100644 docs/ja/api/mp_math/point.md create mode 100644 docs/ja/api/mp_math/segment.md create mode 100644 docs/ja/api/mp_math/utils.md create mode 100644 docs/ja/api/mp_math/vector.md create mode 100644 docs/ja/api/particle/index.md create mode 100644 docs/ja/api/presets/index.md create mode 100644 docs/ja/api/presets/model/index.md create mode 100644 docs/zht/api/index.md create mode 100644 docs/zht/api/mp_math/angle.md create mode 100644 docs/zht/api/mp_math/const.md create mode 100644 docs/zht/api/mp_math/equation.md create mode 100644 docs/zht/api/mp_math/index.md create mode 100644 docs/zht/api/mp_math/line.md create mode 100644 docs/zht/api/mp_math/mp_math_typing.md create mode 100644 docs/zht/api/mp_math/plane.md create mode 100644 docs/zht/api/mp_math/point.md create mode 100644 docs/zht/api/mp_math/segment.md create mode 100644 docs/zht/api/mp_math/utils.md create mode 100644 docs/zht/api/mp_math/vector.md create mode 100644 docs/zht/api/particle/index.md create mode 100644 docs/zht/api/presets/index.md create mode 100644 docs/zht/api/presets/model/index.md rename {liteyuki_autodoc => litedoc}/__init__.py (100%) rename {liteyuki_autodoc => litedoc}/__main__.py (95%) rename {liteyuki_autodoc => litedoc}/docstring/__init__.py (100%) rename {liteyuki_autodoc => litedoc}/docstring/docstring.py (86%) rename {liteyuki_autodoc => litedoc}/docstring/parser.py (85%) rename {liteyuki_autodoc => litedoc}/i18n.py (86%) rename {liteyuki_autodoc => litedoc}/output.py (96%) rename {liteyuki_autodoc => litedoc}/style/__init__.py (100%) rename {liteyuki_autodoc => litedoc}/style/markdown.py (56%) rename {liteyuki_autodoc => litedoc}/syntax/astparser.py (62%) rename {liteyuki_autodoc => litedoc}/syntax/node.py (72%) create mode 100644 litedoc/translator.py create mode 100644 mkdoc.bat create mode 100644 tests/test_doc_translator.py diff --git a/.github/workflows/deploy-docs.yml b/.github/workflows/deploy-docs.yml index 5fa16da..50fcaa0 100644 --- a/.github/workflows/deploy-docs.yml +++ b/.github/workflows/deploy-docs.yml @@ -42,9 +42,9 @@ jobs: - name: Setup API markdown run: |- python -m pip install pydantic - 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 litedoc mbcp -o docs/api -l zh-Hans + python -m litedoc mbcp -o docs/en/api -l en + python -m litedoc mbcp -o docs/ja/api -l ja - name: 安装 pnpm uses: pnpm/action-setup@v2 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..4abf4a1 100644 --- a/docs/.vitepress/config/index.ts +++ b/docs/.vitepress/config/index.ts @@ -3,6 +3,8 @@ import {defineConfig} from "vitepress"; import {common} from './common' import {en} from './en' import {zh} from './zh' +import {zht} from './zht' +import {ja} from './ja' @@ -10,6 +12,8 @@ export default defineConfig({ ...common, locales:{ root: { label: "简体中文", ...zh }, - en: { label: "English", ...en } + en: { label: "English", ...en }, + ja: { label: "日本語", ...ja }, + zht: { label: "繁體中文", ...zht }, } }) \ 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/.vitepress/config/zht.ts b/docs/.vitepress/config/zht.ts new file mode 100644 index 0000000..c937048 --- /dev/null +++ b/docs/.vitepress/config/zht.ts @@ -0,0 +1,14 @@ +import {defineConfig} from 'vitepress' + +export const zht = defineConfig({ + + lang: "zh-Hant", + description: "一個用於Minecraft粒子計算和生成的軟體庫", + themeConfig: { + nav: [ + {text: '指引', link: '/guide/'}, + {text: 'API文檔', link: '/api/'}, + {text: '示範', link: '/demo/'}, + ], + }, +}) \ No newline at end of file diff --git a/docs/api/mp_math/angle.md b/docs/api/mp_math/angle.md index d5e1065..756d8f2 100644 --- a/docs/api/mp_math/angle.md +++ b/docs/api/mp_math/angle.md @@ -1,16 +1,14 @@ --- title: mbcp.mp_math.angle --- -### ***class*** `Angle` - -### ***class*** `AnyAngle` - -### *def* `__init__(self, value: float, is_radian: bool = False)` +### **class** `Angle` +### **class** `AnyAngle(Angle)` +### *method* `__init__(self, value: float, is_radian: bool = False)` 任意角度。 -参数: +**参数**: - value: 角度或弧度值 @@ -19,7 +17,7 @@ title: mbcp.mp_math.angle
-源码 + 源代码 ```python def __init__(self, value: float, is_radian: bool=False): @@ -37,19 +35,19 @@ def __init__(self, value: float, is_radian: bool=False):
### `@property` -### *def* `complementary(self) -> 'AnyAngle'` +### *method* `complementary(self) -> AnyAngle` 余角:两角的和为90°。 -返回: +**返回**: - 余角
-源码 + 源代码 ```python @property @@ -64,19 +62,19 @@ def complementary(self) -> 'AnyAngle':
### `@property` -### *def* `supplementary(self) -> 'AnyAngle'` +### *method* `supplementary(self) -> AnyAngle` 补角:两角的和为180°。 -返回: +**返回**: - 补角
-源码 + 源代码 ```python @property @@ -91,19 +89,19 @@ def supplementary(self) -> 'AnyAngle':
### `@property` -### *def* `degree(self) -> float` +### *method* `degree(self) -> float` 角度。 -返回: +**返回**: - 弧度
-源码 + 源代码 ```python @property @@ -118,19 +116,19 @@ def degree(self) -> float:
### `@property` -### *def* `minimum_positive(self) -> 'AnyAngle'` +### *method* `minimum_positive(self) -> AnyAngle` 最小正角。 -返回: +**返回**: - 最小正角度
-源码 + 源代码 ```python @property @@ -145,19 +143,19 @@ def minimum_positive(self) -> 'AnyAngle':
### `@property` -### *def* `maximum_negative(self) -> 'AnyAngle'` +### *method* `maximum_negative(self) -> AnyAngle` 最大负角。 -返回: +**返回**: - 最大负角度
-源码 + 源代码 ```python @property @@ -172,19 +170,19 @@ def maximum_negative(self) -> 'AnyAngle':
### `@property` -### *def* `sin(self) -> float` +### *method* `sin(self) -> float` 正弦值。 -返回: +**返回**: - 正弦值
-源码 + 源代码 ```python @property @@ -199,19 +197,19 @@ def sin(self) -> float:
### `@property` -### *def* `cos(self) -> float` +### *method* `cos(self) -> float` 余弦值。 -返回: +**返回**: - 余弦值
-源码 + 源代码 ```python @property @@ -226,19 +224,19 @@ def cos(self) -> float:
### `@property` -### *def* `tan(self) -> float` +### *method* `tan(self) -> float` 正切值。 -返回: +**返回**: - 正切值
-源码 + 源代码 ```python @property @@ -253,19 +251,19 @@ def tan(self) -> float:
### `@property` -### *def* `cot(self) -> float` +### *method* `cot(self) -> float` 余切值。 -返回: +**返回**: - 余切值
-源码 + 源代码 ```python @property @@ -280,19 +278,19 @@ def cot(self) -> float:
### `@property` -### *def* `sec(self) -> float` +### *method* `sec(self) -> float` 正割值。 -返回: +**返回**: - 正割值
-源码 + 源代码 ```python @property @@ -307,19 +305,19 @@ def sec(self) -> float:
### `@property` -### *def* `csc(self) -> float` +### *method* `csc(self) -> float` 余割值。 -返回: +**返回**: - 余割值
-源码 + 源代码 ```python @property @@ -333,11 +331,11 @@ def csc(self) -> float: ```
-### *def* `__add__(self, other: 'AnyAngle') -> 'AnyAngle'` +### *method* `self + other: AnyAngle => AnyAngle`
-源码 + 源代码 ```python def __add__(self, other: 'AnyAngle') -> 'AnyAngle': @@ -345,11 +343,11 @@ def __add__(self, other: 'AnyAngle') -> 'AnyAngle': ```
-### *def* `__eq__(self, other)` +### *method* `__eq__(self, other)`
-源码 + 源代码 ```python def __eq__(self, other): @@ -357,11 +355,11 @@ def __eq__(self, other): ```
-### *def* `__sub__(self, other: 'AnyAngle') -> 'AnyAngle'` +### *method* `self - other: AnyAngle => AnyAngle`
-源码 + 源代码 ```python def __sub__(self, other: 'AnyAngle') -> 'AnyAngle': @@ -369,11 +367,11 @@ def __sub__(self, other: 'AnyAngle') -> 'AnyAngle': ```
-### *def* `__mul__(self, other: float) -> 'AnyAngle'` +### *method* `self * other: float => AnyAngle`
-源码 + 源代码 ```python def __mul__(self, other: float) -> 'AnyAngle': @@ -381,36 +379,12 @@ def __mul__(self, other: float) -> 'AnyAngle': ```
-### *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'` +### *method* `self / other: float => AnyAngle`
-源码 + 源代码 ```python @overload @@ -420,11 +394,11 @@ def __truediv__(self, other: float) -> 'AnyAngle':
### `@overload` -### *def* `__truediv__(self, other: 'AnyAngle') -> float` +### *method* `self / other: AnyAngle => float`
-源码 + 源代码 ```python @overload @@ -433,11 +407,11 @@ def __truediv__(self, other: 'AnyAngle') -> float: ```
-### *def* `__truediv__(self, other)` +### *method* `self / other`
-源码 + 源代码 ```python def __truediv__(self, other): diff --git a/docs/api/mp_math/const.md b/docs/api/mp_math/const.md index 888edf3..a94898a 100644 --- a/docs/api/mp_math/const.md +++ b/docs/api/mp_math/const.md @@ -1,15 +1,3 @@ --- 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/api/mp_math/equation.md b/docs/api/mp_math/equation.md index e34924d..659a67a 100644 --- a/docs/api/mp_math/equation.md +++ b/docs/api/mp_math/equation.md @@ -1,12 +1,12 @@ --- title: mbcp.mp_math.equation --- -### *def* `get_partial_derivative_func(func: MultiVarsFunc = EPSILON) -> MultiVarsFunc` +### *func* `get_partial_derivative_func(func: MultiVarsFunc = EPSILON) -> MultiVarsFunc` 求N元函数一阶偏导函数。这玩意不太稳定,慎用。 -参数: +**参数**: - func: 函数 @@ -14,10 +14,18 @@ title: mbcp.mp_math.equation - epsilon: 偏移量 +**返回**: + +- 偏导函数 + +**引发**: + +- ValueError 无效变量类型 +
-源码 + 源代码 ```python def get_partial_derivative_func(func: MultiVarsFunc, var: int | tuple[int, ...], epsilon: Number=EPSILON) -> MultiVarsFunc: @@ -54,11 +62,11 @@ def get_partial_derivative_func(func: MultiVarsFunc, var: int | tuple[int, ...], ```
-### *def* `partial_derivative_func() -> Var` +### *func* `partial_derivative_func() -> Var`
-源码 + 源代码 ```python def partial_derivative_func(*args: Var) -> Var: @@ -70,11 +78,11 @@ def partial_derivative_func(*args: Var) -> Var: ```
-### *def* `high_order_partial_derivative_func() -> Var` +### *func* `high_order_partial_derivative_func() -> Var`
-源码 + 源代码 ```python def high_order_partial_derivative_func(*args: Var) -> Var: @@ -85,14 +93,13 @@ def high_order_partial_derivative_func(*args: Var) -> Var: ```
-### ***class*** `CurveEquation` - -### *def* `__init__(self, x_func: OneVarFunc, y_func: OneVarFunc, z_func: OneVarFunc)` +### **class** `CurveEquation` +### *method* `__init__(self, x_func: OneVarFunc, y_func: OneVarFunc, z_func: OneVarFunc)` 曲线方程。 -参数: +**参数**: - x_func: x函数 @@ -103,7 +110,7 @@ def high_order_partial_derivative_func(*args: Var) -> Var:
-源码 + 源代码 ```python def __init__(self, x_func: OneVarFunc, y_func: OneVarFunc, z_func: OneVarFunc): @@ -120,12 +127,12 @@ def __init__(self, x_func: OneVarFunc, y_func: OneVarFunc, z_func: OneVarFunc): ```
-### *def* `__call__(self) -> Point3 | tuple[Point3, ...]` +### *method* `__call__(self) -> Point3 | tuple[Point3, ...]` 计算曲线上的点。 -参数: +**参数**: - *t: @@ -134,7 +141,7 @@ def __init__(self, x_func: OneVarFunc, y_func: OneVarFunc, z_func: OneVarFunc):
-源码 + 源代码 ```python def __call__(self, *t: Var) -> Point3 | tuple[Point3, ...]: @@ -153,17 +160,3 @@ def __call__(self, *t: Var) -> Point3 | tuple[Point3, ...]: ```
-### *def* `__str__(self)` - - -
-源码 - -```python -def __str__(self): - return 'CurveEquation()' -``` -
- -### ***var*** `result_func = get_partial_derivative_func(result_func, v, epsilon)` - diff --git a/docs/api/mp_math/line.md b/docs/api/mp_math/line.md index d12dac8..e231f95 100644 --- a/docs/api/mp_math/line.md +++ b/docs/api/mp_math/line.md @@ -1,14 +1,13 @@ --- title: mbcp.mp_math.line --- -### ***class*** `Line3` - -### *def* `__init__(self, point: 'Point3', direction: 'Vector3')` +### **class** `Line3` +### *method* `__init__(self, point: Point3, direction: Vector3)` 三维空间中的直线。由一个点和一个方向向量确定。 -参数: +**参数**: - point: 直线上的一点 @@ -17,7 +16,7 @@ title: mbcp.mp_math.line
-源码 + 源代码 ```python def __init__(self, point: 'Point3', direction: 'Vector3'): @@ -32,21 +31,25 @@ def __init__(self, point: 'Point3', direction: 'Vector3'): ```
-### *def* `approx(self, other: 'Line3', epsilon: float = APPROX) -> bool` +### *method* `approx(self, other: Line3, epsilon: float = APPROX) -> bool` 判断两条直线是否近似相等。 -参数: +**参数**: - other: 另一条直线 - epsilon: 误差 +**返回**: + +- 是否近似相等 +
-源码 + 源代码 ```python def approx(self, other: 'Line3', epsilon: float=APPROX) -> bool: @@ -62,19 +65,27 @@ def approx(self, other: 'Line3', epsilon: float=APPROX) -> bool: ```
-### *def* `cal_angle(self, other: 'Line3') -> 'AnyAngle'` +### *method* `cal_angle(self, other: Line3) -> AnyAngle` 计算直线和直线之间的夹角。 -参数: +**参数**: - other: 另一条直线 +**返回**: + +- 夹角弧度 + +**引发**: + +- TypeError 不支持的类型 +
-源码 + 源代码 ```python def cal_angle(self, other: 'Line3') -> 'AnyAngle': @@ -91,19 +102,27 @@ def cal_angle(self, other: 'Line3') -> 'AnyAngle': ```
-### *def* `cal_distance(self, other: 'Line3 | Point3') -> float` +### *method* `cal_distance(self, other: Line3 | Point3) -> float` 计算直线和直线或点之间的距离。 -参数: +**参数**: - other: 平行直线或点 +**返回**: + +- 距离 + +**引发**: + +- TypeError 不支持的类型 +
-源码 + 源代码 ```python def cal_distance(self, other: 'Line3 | Point3') -> float: @@ -133,19 +152,29 @@ def cal_distance(self, other: 'Line3 | Point3') -> float: ```
-### *def* `cal_intersection(self, other: 'Line3') -> 'Point3'` +### *method* `cal_intersection(self, other: Line3) -> Point3` 计算两条直线的交点。 -参数: +**参数**: - other: 另一条直线 +**返回**: + +- 交点 + +**引发**: + +- ValueError 直线平行 + +- ValueError 直线不共面 +
-源码 + 源代码 ```python def cal_intersection(self, other: 'Line3') -> 'Point3': @@ -167,19 +196,23 @@ def cal_intersection(self, other: 'Line3') -> 'Point3': ```
-### *def* `cal_perpendicular(self, point: 'Point3') -> 'Line3'` +### *method* `cal_perpendicular(self, point: Point3) -> Line3` 计算直线经过指定点p的垂线。 -参数: +**参数**: - point: 指定点 +**返回**: + +- 垂线 +
-源码 + 源代码 ```python def cal_perpendicular(self, point: 'Point3') -> 'Line3': @@ -194,19 +227,23 @@ def cal_perpendicular(self, point: 'Point3') -> 'Line3': ```
-### *def* `get_point(self, t: RealNumber) -> 'Point3'` +### *method* `get_point(self, t: RealNumber) -> Point3` 获取直线上的点。同一条直线,但起始点和方向向量不同,则同一个t对应的点不同。 -参数: +**参数**: - t: 参数t +**返回**: + +- 点 +
-源码 + 源代码 ```python def get_point(self, t: RealNumber) -> 'Point3': @@ -221,19 +258,19 @@ def get_point(self, t: RealNumber) -> 'Point3': ```
-### *def* `get_parametric_equations(self) -> tuple[OneSingleVarFunc, OneSingleVarFunc, OneSingleVarFunc]` +### *method* `get_parametric_equations(self) -> tuple[OneSingleVarFunc, OneSingleVarFunc, OneSingleVarFunc]` 获取直线的参数方程。 -返回: +**返回**: - x(t), y(t), z(t)
-源码 + 源代码 ```python def get_parametric_equations(self) -> tuple[OneSingleVarFunc, OneSingleVarFunc, OneSingleVarFunc]: @@ -246,21 +283,25 @@ def get_parametric_equations(self) -> tuple[OneSingleVarFunc, OneSingleVarFunc, ```
-### *def* `is_approx_parallel(self, other: 'Line3', epsilon: float = 1e-06) -> bool` +### *method* `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: @@ -276,19 +317,23 @@ def is_approx_parallel(self, other: 'Line3', epsilon: float=1e-06) -> bool: ```
-### *def* `is_parallel(self, other: 'Line3') -> bool` +### *method* `is_parallel(self, other: Line3) -> bool` 判断两条直线是否平行。 -参数: +**参数**: - other: 另一条直线 +**返回**: + +- 是否平行 +
-源码 + 源代码 ```python def is_parallel(self, other: 'Line3') -> bool: @@ -303,19 +348,23 @@ def is_parallel(self, other: 'Line3') -> bool: ```
-### *def* `is_collinear(self, other: 'Line3') -> bool` +### *method* `is_collinear(self, other: Line3) -> bool` 判断两条直线是否共线。 -参数: +**参数**: - other: 另一条直线 +**返回**: + +- 是否共线 +
-源码 + 源代码 ```python def is_collinear(self, other: 'Line3') -> bool: @@ -330,19 +379,23 @@ def is_collinear(self, other: 'Line3') -> bool: ```
-### *def* `is_point_on(self, point: 'Point3') -> bool` +### *method* `is_point_on(self, point: Point3) -> bool` 判断点是否在直线上。 -参数: +**参数**: - point: 点 +**返回**: + +- 是否在直线上 +
-源码 + 源代码 ```python def is_point_on(self, point: 'Point3') -> bool: @@ -357,20 +410,24 @@ def is_point_on(self, point: 'Point3') -> bool: ```
-### *def* `is_coplanar(self, other: 'Line3') -> bool` +### *method* `is_coplanar(self, other: Line3) -> bool` 判断两条直线是否共面。 充要条件:两直线方向向量的叉乘与两直线上任意一点的向量的点积为0。 -参数: +**参数**: - other: 另一条直线 +**返回**: + +- 是否共面 +
-源码 + 源代码 ```python def is_coplanar(self, other: 'Line3') -> bool: @@ -386,7 +443,7 @@ def is_coplanar(self, other: 'Line3') -> bool: ```
-### *def* `simplify(self)` +### *method* `simplify(self)` 简化直线方程,等价相等。 @@ -397,7 +454,7 @@ def is_coplanar(self, other: 'Line3') -> bool:
-源码 + 源代码 ```python def simplify(self): @@ -418,21 +475,25 @@ def simplify(self):
### `@classmethod` -### *def* `from_two_points(cls, p1: 'Point3', p2: 'Point3') -> 'Line3'` +### *method* `from_two_points(cls, p1: Point3, p2: Point3) -> Line3` 工厂函数 由两点构造直线。 -参数: +**参数**: - p1: 点1 - p2: 点2 +**返回**: + +- 直线 +
-源码 + 源代码 ```python @classmethod @@ -450,19 +511,23 @@ def from_two_points(cls, p1: 'Point3', p2: 'Point3') -> 'Line3': ```
-### *def* `__and__(self, other: 'Line3') -> 'Line3 | Point3 | None'` +### *method* `__and__(self, other: Line3) -> Line3 | Point3 | None` 计算两条直线点集合的交集。重合线返回自身,平行线返回None,交线返回交点。 -参数: +**参数**: - other: 另一条直线 +**返回**: + +- 交点 +
-源码 + 源代码 ```python def __and__(self, other: 'Line3') -> 'Line3 | Point3 | None': @@ -482,21 +547,21 @@ def __and__(self, other: 'Line3') -> 'Line3 | Point3 | None': ```
-### *def* `__eq__(self, other) -> bool` +### *method* `__eq__(self, other) -> bool` 判断两条直线是否等价。 v1 // v2 ∧ (p1 - p2) // v1 -参数: +**参数**: - other:
-源码 + 源代码 ```python def __eq__(self, other) -> bool: @@ -514,43 +579,3 @@ def __eq__(self, other) -> bool: ```
-### *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/api/mp_math/mp_math_typing.md b/docs/api/mp_math/mp_math_typing.md index b166130..f55d036 100644 --- a/docs/api/mp_math/mp_math_typing.md +++ b/docs/api/mp_math/mp_math_typing.md @@ -1,37 +1,63 @@ --- title: mbcp.mp_math.mp_math_typing --- -### ***var*** `RealNumber: TypeAlias = int | float` +### ***var*** `RealNumber = int | float` -### ***var*** `Number: TypeAlias = RealNumber | complex` +- **类型**: `TypeAlias` -### ***var*** `SingleVar = TypeVar('SingleVar', bound=Number)` +### ***var*** `Number = RealNumber | complex` -### ***var*** `ArrayVar = TypeVar('ArrayVar', bound=Iterable[Number])` +- **类型**: `TypeAlias` -### ***var*** `Var: TypeAlias = SingleVar | ArrayVar` +### ***var*** `Var = SingleVar | ArrayVar` -### ***var*** `OneSingleVarFunc: TypeAlias = Callable[[SingleVar], SingleVar]` +- **类型**: `TypeAlias` -### ***var*** `OneArrayFunc: TypeAlias = Callable[[ArrayVar], ArrayVar]` +### ***var*** `OneSingleVarFunc = Callable[[SingleVar], SingleVar]` -### ***var*** `OneVarFunc: TypeAlias = OneSingleVarFunc | OneArrayFunc` +- **类型**: `TypeAlias` -### ***var*** `TwoSingleVarsFunc: TypeAlias = Callable[[SingleVar, SingleVar], SingleVar]` +### ***var*** `OneArrayFunc = Callable[[ArrayVar], ArrayVar]` -### ***var*** `TwoArraysFunc: TypeAlias = Callable[[ArrayVar, ArrayVar], ArrayVar]` +- **类型**: `TypeAlias` -### ***var*** `TwoVarsFunc: TypeAlias = TwoSingleVarsFunc | TwoArraysFunc` +### ***var*** `OneVarFunc = OneSingleVarFunc | OneArrayFunc` -### ***var*** `ThreeSingleVarsFunc: TypeAlias = Callable[[SingleVar, SingleVar, SingleVar], SingleVar]` +- **类型**: `TypeAlias` -### ***var*** `ThreeArraysFunc: TypeAlias = Callable[[ArrayVar, ArrayVar, ArrayVar], ArrayVar]` +### ***var*** `TwoSingleVarsFunc = Callable[[SingleVar, SingleVar], SingleVar]` -### ***var*** `ThreeVarsFunc: TypeAlias = ThreeSingleVarsFunc | ThreeArraysFunc` +- **类型**: `TypeAlias` -### ***var*** `MultiSingleVarsFunc: TypeAlias = Callable[..., SingleVar]` +### ***var*** `TwoArraysFunc = Callable[[ArrayVar, ArrayVar], ArrayVar]` -### ***var*** `MultiArraysFunc: TypeAlias = Callable[..., ArrayVar]` +- **类型**: `TypeAlias` -### ***var*** `MultiVarsFunc: TypeAlias = MultiSingleVarsFunc | MultiArraysFunc` +### ***var*** `TwoVarsFunc = TwoSingleVarsFunc | TwoArraysFunc` + +- **类型**: `TypeAlias` + +### ***var*** `ThreeSingleVarsFunc = Callable[[SingleVar, SingleVar, SingleVar], SingleVar]` + +- **类型**: `TypeAlias` + +### ***var*** `ThreeArraysFunc = Callable[[ArrayVar, ArrayVar, ArrayVar], ArrayVar]` + +- **类型**: `TypeAlias` + +### ***var*** `ThreeVarsFunc = ThreeSingleVarsFunc | ThreeArraysFunc` + +- **类型**: `TypeAlias` + +### ***var*** `MultiSingleVarsFunc = Callable[..., SingleVar]` + +- **类型**: `TypeAlias` + +### ***var*** `MultiArraysFunc = Callable[..., ArrayVar]` + +- **类型**: `TypeAlias` + +### ***var*** `MultiVarsFunc = MultiSingleVarsFunc | MultiArraysFunc` + +- **类型**: `TypeAlias` diff --git a/docs/api/mp_math/plane.md b/docs/api/mp_math/plane.md index e069db8..ac73d1e 100644 --- a/docs/api/mp_math/plane.md +++ b/docs/api/mp_math/plane.md @@ -1,37 +1,36 @@ --- title: mbcp.mp_math.plane --- -### ***class*** `Plane3` - -### *def* `__init__(self, a: float, b: float, c: float, d: float)` +### **class** `Plane3` +### *method* `__init__(self, a: float, b: float, c: float, d: float)` 平面方程:ax + by + cz + d = 0 -参数: +**参数**: -- a: +- a: x系数 -- b: +- b: y系数 -- c: +- c: z系数 -- d: +- d: 常数项
-源码 + 源代码 ```python def __init__(self, a: float, b: float, c: float, d: float): """ 平面方程:ax + by + cz + d = 0 Args: - a: - b: - c: - d: + a: x系数 + b: y系数 + c: z系数 + d: 常数项 """ self.a = a self.b = b @@ -40,31 +39,33 @@ def __init__(self, a: float, b: float, c: float, d: float): ```
-### *def* `approx(self, other: 'Plane3') -> bool` +### *method* `approx(self, other: Plane3) -> bool` 判断两个平面是否近似相等。 -参数: +**参数**: -- other: +- other: 另一个平面 + +**返回**: + +- 是否近似相等
-源码 + 源代码 ```python def approx(self, other: 'Plane3') -> bool: """ 判断两个平面是否近似相等。 Args: - other: - + 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) @@ -79,19 +80,27 @@ def approx(self, other: 'Plane3') -> bool: ```
-### *def* `cal_angle(self, other: 'Line3 | Plane3') -> 'AnyAngle'` +### *method* `cal_angle(self, other: Line3 | Plane3) -> AnyAngle` 计算平面与平面之间的夹角。 -参数: +**参数**: - other: 另一个平面 +**返回**: + +- 夹角弧度 + +**引发**: + +- TypeError 不支持的类型 +
-源码 + 源代码 ```python def cal_angle(self, other: 'Line3 | Plane3') -> 'AnyAngle': @@ -113,19 +122,27 @@ def cal_angle(self, other: 'Line3 | Plane3') -> 'AnyAngle': ```
-### *def* `cal_distance(self, other: 'Plane3 | Point3') -> float` +### *method* `cal_distance(self, other: Plane3 | Point3) -> float` 计算平面与平面或点之间的距离。 -参数: +**参数**: - other: 另一个平面或点 +**返回**: + +- 距离 + +**引发**: + +- TypeError 不支持的类型 +
-源码 + 源代码 ```python def cal_distance(self, other: 'Plane3 | Point3') -> float: @@ -147,28 +164,32 @@ def cal_distance(self, other: 'Plane3 | Point3') -> float: ```
-### *def* `cal_intersection_line3(self, other: 'Plane3') -> 'Line3'` +### *method* `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): @@ -191,19 +212,27 @@ def cal_intersection_line3(self, other: 'Plane3') -> 'Line3': ```
-### *def* `cal_intersection_point3(self, other: 'Line3') -> 'Point3'` +### *method* `cal_intersection_point3(self, other: Line3) -> Point3` 计算平面与直线的交点。 -参数: +**参数**: - other: 不与平面平行或在平面上的直线 +**返回**: + +- 交点 + +**引发**: + +- ValueError 平面与直线平行或重合 +
-源码 + 源代码 ```python def cal_intersection_point3(self, other: 'Line3') -> 'Point3': @@ -224,19 +253,23 @@ def cal_intersection_point3(self, other: 'Line3') -> 'Point3': ```
-### *def* `cal_parallel_plane3(self, point: 'Point3') -> 'Plane3'` +### *method* `cal_parallel_plane3(self, point: Point3) -> Plane3` 计算平行于该平面且过指定点的平面。 -参数: +**参数**: - point: 指定点 +**返回**: + +- 所求平面 +
-源码 + 源代码 ```python def cal_parallel_plane3(self, point: 'Point3') -> 'Plane3': @@ -245,25 +278,29 @@ 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` +### *method* `is_parallel(self, other: Plane3) -> bool` 判断两个平面是否平行。 -参数: +**参数**: - other: 另一个平面 +**返回**: + +- 是否平行 +
-源码 + 源代码 ```python def is_parallel(self, other: 'Plane3') -> bool: @@ -279,19 +316,19 @@ def is_parallel(self, other: 'Plane3') -> bool:
### `@property` -### *def* `normal(self) -> 'Vector3'` +### *method* `normal(self) -> Vector3` 平面的法向量。 -返回: +**返回**: - 法向量
-源码 + 源代码 ```python @property @@ -306,21 +343,25 @@ def normal(self) -> 'Vector3':
### `@classmethod` -### *def* `from_point_and_normal(cls, point: 'Point3', normal: 'Vector3') -> 'Plane3'` +### *method* `from_point_and_normal(cls, point: Point3, normal: Vector3) -> Plane3` 工厂函数 由点和法向量构造平面(点法式构造)。 -参数: +**参数**: - point: 平面上的一点 - normal: 法向量 +**返回**: + +- 平面 +
-源码 + 源代码 ```python @classmethod @@ -340,12 +381,12 @@ def from_point_and_normal(cls, point: 'Point3', normal: 'Vector3') -> 'Plane3':
### `@classmethod` -### *def* `from_three_points(cls, p1: 'Point3', p2: 'Point3', p3: 'Point3') -> 'Plane3'` +### *method* `from_three_points(cls, p1: Point3, p2: Point3, p3: Point3) -> Plane3` 工厂函数 由三点构造平面。 -参数: +**参数**: - p1: 点1 @@ -353,10 +394,14 @@ def from_point_and_normal(cls, point: 'Point3', normal: 'Vector3') -> 'Plane3': - p3: 点3 +**返回**: + +- 平面 +
-源码 + 源代码 ```python @classmethod @@ -378,21 +423,25 @@ def from_three_points(cls, p1: 'Point3', p2: 'Point3', p3: 'Point3') -> 'Plane3'
### `@classmethod` -### *def* `from_two_lines(cls, l1: 'Line3', l2: 'Line3') -> 'Plane3'` +### *method* `from_two_lines(cls, l1: Line3, l2: Line3) -> Plane3` 工厂函数 由两直线构造平面。 -参数: +**参数**: - l1: 直线1 - l2: 直线2 +**返回**: + +- 平面 +
-源码 + 源代码 ```python @classmethod @@ -414,21 +463,25 @@ def from_two_lines(cls, l1: 'Line3', l2: 'Line3') -> 'Plane3':
### `@classmethod` -### *def* `from_point_and_line(cls, point: 'Point3', line: 'Line3') -> 'Plane3'` +### *method* `from_point_and_line(cls, point: Point3, line: Line3) -> Plane3` 工厂函数 由点和直线构造平面。 -参数: +**参数**: - point: 面上一点 - line: 面上直线,不包含点 +**返回**: + +- 平面 +
-源码 + 源代码 ```python @classmethod @@ -445,45 +498,12 @@ def from_point_and_line(cls, point: 'Point3', line: 'Line3') -> 'Plane3': ```
-### *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'` +### *method* `__and__(self, other: Line3) -> Point3 | None`
-源码 + 源代码 ```python @overload @@ -493,11 +513,11 @@ def __and__(self, other: 'Line3') -> 'Point3 | None':
### `@overload` -### *def* `__and__(self, other: 'Plane3') -> 'Line3 | None'` +### *method* `__and__(self, other: Plane3) -> Line3 | None`
-源码 + 源代码 ```python @overload @@ -506,19 +526,23 @@ def __and__(self, other: 'Plane3') -> 'Line3 | None': ```
-### *def* `__and__(self, other)` +### *method* `__and__(self, other)` 取两平面的交集(人话:交线) -参数: +**参数**: - other: +**返回**: + +- 不平行平面的交线,平面平行返回None +
-源码 + 源代码 ```python def __and__(self, other): @@ -542,11 +566,11 @@ def __and__(self, other): ```
-### *def* `__eq__(self, other) -> bool` +### *method* `__eq__(self, other) -> bool`
-源码 + 源代码 ```python def __eq__(self, other) -> bool: @@ -554,11 +578,11 @@ def __eq__(self, other) -> bool: ```
-### *def* `__rand__(self, other: 'Line3') -> 'Point3'` +### *method* `__rand__(self, other: Line3) -> Point3`
-源码 + 源代码 ```python def __rand__(self, other: 'Line3') -> 'Point3': @@ -566,23 +590,3 @@ def __rand__(self, other: 'Line3') -> 'Point3': ```
-### ***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/api/mp_math/point.md b/docs/api/mp_math/point.md index abb2706..7f26c93 100644 --- a/docs/api/mp_math/point.md +++ b/docs/api/mp_math/point.md @@ -1,14 +1,13 @@ --- title: mbcp.mp_math.point --- -### ***class*** `Point3` - -### *def* `__init__(self, x: float, y: float, z: float)` +### **class** `Point3` +### *method* `__init__(self, x: float, y: float, z: float)` 笛卡尔坐标系中的点。 -参数: +**参数**: - x: x 坐标 @@ -19,7 +18,7 @@ title: mbcp.mp_math.point
-源码 + 源代码 ```python def __init__(self, x: float, y: float, z: float): @@ -36,21 +35,25 @@ def __init__(self, x: float, y: float, z: float): ```
-### *def* `approx(self, other: 'Point3', epsilon: float = APPROX) -> bool` +### *method* `approx(self, other: Point3, epsilon: float = APPROX) -> bool` 判断两个点是否近似相等。 -参数: +**参数**: - other: - epsilon: +**返回**: + +- 是否近似相等 +
-源码 + 源代码 ```python def approx(self, other: 'Point3', epsilon: float=APPROX) -> bool: @@ -67,24 +70,12 @@ def approx(self, other: 'Point3', epsilon: float=APPROX) -> bool: ```
-### *def* `__str__(self)` - - -
-源码 - -```python -def __str__(self): - return f'Point3({self.x}, {self.y}, {self.z})' -``` -
- ### `@overload` -### *def* `__add__(self, other: 'Vector3') -> 'Point3'` +### *method* `self + other: Vector3 => Point3`
-源码 + 源代码 ```python @overload @@ -94,11 +85,11 @@ def __add__(self, other: 'Vector3') -> 'Point3':
### `@overload` -### *def* `__add__(self, other: 'Point3') -> 'Point3'` +### *method* `self + other: Point3 => Point3`
-源码 + 源代码 ```python @overload @@ -107,20 +98,20 @@ def __add__(self, other: 'Point3') -> 'Point3': ```
-### *def* `__add__(self, other)` +### *method* `self + other` P + V -> P P + P -> P -参数: +**参数**: - other:
-源码 + 源代码 ```python def __add__(self, other): @@ -135,19 +126,19 @@ def __add__(self, other): ```
-### *def* `__eq__(self, other)` +### *method* `__eq__(self, other)` 判断两个点是否相等。 -参数: +**参数**: - other:
-源码 + 源代码 ```python def __eq__(self, other): @@ -161,21 +152,21 @@ def __eq__(self, other): ```
-### *def* `__sub__(self, other: 'Point3') -> 'Vector3'` +### *method* `self - other: Point3 => Vector3` P - P -> V P - V -> P 已在 :class:`Vector3` 中实现 -参数: +**参数**: - other:
-源码 + 源代码 ```python def __sub__(self, other: 'Point3') -> 'Vector3': diff --git a/docs/api/mp_math/segment.md b/docs/api/mp_math/segment.md index 0e39845..73e195b 100644 --- a/docs/api/mp_math/segment.md +++ b/docs/api/mp_math/segment.md @@ -1,9 +1,8 @@ --- title: mbcp.mp_math.segment --- -### ***class*** `Segment3` - -### *def* `__init__(self, p1: 'Point3', p2: 'Point3')` +### **class** `Segment3` +### *method* `__init__(self, p1: Point3, p2: Point3)` 三维空间中的线段。 @@ -13,7 +12,7 @@ title: mbcp.mp_math.segment
-源码 + 源代码 ```python def __init__(self, p1: 'Point3', p2: 'Point3'): @@ -33,27 +32,3 @@ def __init__(self, p1: 'Point3', p2: 'Point3'): ```
-### *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/api/mp_math/utils.md b/docs/api/mp_math/utils.md index 40ac31e..fbc0e0a 100644 --- a/docs/api/mp_math/utils.md +++ b/docs/api/mp_math/utils.md @@ -1,32 +1,36 @@ --- title: mbcp.mp_math.utils --- -### *def* `clamp() -> float` +### *func* `clamp() -> float` -区间截断函数。 +区间限定函数 -参数: +**参数**: -- x: +- x: 待限定的值 -- min_: +- min_: 最小值 -- max_: +- max_: 最大值 + +**返回**: + +- 限制后的值
-源码 + 源代码 ```python def clamp(x: float, min_: float, max_: float) -> float: """ - 区间截断函数。 + 区间限定函数 Args: - x: - min_: - max_: + x: 待限定的值 + min_: 最小值 + max_: 最大值 Returns: 限制后的值 @@ -35,33 +39,36 @@ def clamp(x: float, min_: float, max_: float) -> float: ```
-### *def* `approx(x: float = 0.0, y: float = APPROX) -> bool` +### *func* `approx(x: float = 0.0, y: float = APPROX) -> bool` 判断两个数是否近似相等。或包装一个实数,用于判断是否近似于0。 -参数: +**参数**: -- x: +- x: 数1 -- y: +- y: 数2 -- epsilon: +- epsilon: 误差 + +**返回**: + +- 是否近似相等
-源码 + 源代码 ```python def approx(x: float, y: float=0.0, epsilon: float=APPROX) -> bool: """ 判断两个数是否近似相等。或包装一个实数,用于判断是否近似于0。 Args: - x: - y: - epsilon: - + x: 数1 + y: 数2 + epsilon: 误差 Returns: 是否近似相等 """ @@ -69,21 +76,25 @@ def approx(x: float, y: float=0.0, epsilon: float=APPROX) -> bool: ```
-### *def* `sign(x: float = False) -> str` +### *func* `sign(x: float = False) -> str` 获取数的符号。 -参数: +**参数**: - x: 数 - only_neg: 是否只返回负数的符号 +**返回**: + +- 符号 + - "" +
-源码 + 源代码 ```python def sign(x: float, only_neg: bool=False) -> str: @@ -103,7 +114,7 @@ def sign(x: float, only_neg: bool=False) -> str: ```
-### *def* `sign_format(x: float = False) -> str` +### *func* `sign_format(x: float = False) -> str` 格式化符号数 @@ -111,16 +122,20 @@ def sign(x: float, only_neg: bool=False) -> str: 1 -> +1 0 -> "" -参数: +**参数**: - x: 数 - only_neg: 是否只返回负数的符号 +**返回**: + +- 符号 + - "" +
-源码 + 源代码 ```python def sign_format(x: float, only_neg: bool=False) -> str: @@ -143,13 +158,12 @@ def sign_format(x: float, only_neg: bool=False) -> str: ```
-### ***class*** `Approx` - -### *def* `__init__(self, value: RealNumber)` +### **class** `Approx` +### *method* `__init__(self, value: RealNumber)`
-源码 + 源代码 ```python def __init__(self, value: RealNumber): @@ -157,11 +171,11 @@ def __init__(self, value: RealNumber): ```
-### *def* `__eq__(self, other)` +### *method* `__eq__(self, other)`
-源码 + 源代码 ```python def __eq__(self, other): @@ -178,11 +192,11 @@ def __eq__(self, other): ```
-### *def* `raise_type_error(self, other)` +### *method* `raise_type_error(self, other)`
-源码 + 源代码 ```python def raise_type_error(self, other): @@ -190,11 +204,11 @@ def raise_type_error(self, other): ```
-### *def* `__ne__(self, other)` +### *method* `__ne__(self, other)`
-源码 + 源代码 ```python def __ne__(self, other): diff --git a/docs/api/mp_math/vector.md b/docs/api/mp_math/vector.md index cb8973c..dc88a09 100644 --- a/docs/api/mp_math/vector.md +++ b/docs/api/mp_math/vector.md @@ -1,14 +1,13 @@ --- title: mbcp.mp_math.vector --- -### ***class*** `Vector3` - -### *def* `__init__(self, x: float, y: float, z: float)` +### **class** `Vector3` +### *method* `__init__(self, x: float, y: float, z: float)` 3维向量 -参数: +**参数**: - x: x轴分量 @@ -19,7 +18,7 @@ title: mbcp.mp_math.vector
-源码 + 源代码 ```python def __init__(self, x: float, y: float, z: float): @@ -36,21 +35,25 @@ def __init__(self, x: float, y: float, z: float): ```
-### *def* `approx(self, other: 'Vector3', epsilon: float = APPROX) -> bool` +### *method* `approx(self, other: Vector3, epsilon: float = APPROX) -> bool` 判断两个向量是否近似相等。 -参数: +**参数**: - other: - epsilon: +**返回**: + +- 是否近似相等 +
-源码 + 源代码 ```python def approx(self, other: 'Vector3', epsilon: float=APPROX) -> bool: @@ -67,19 +70,23 @@ def approx(self, other: 'Vector3', epsilon: float=APPROX) -> bool: ```
-### *def* `cal_angle(self, other: 'Vector3') -> 'AnyAngle'` +### *method* `cal_angle(self, other: Vector3) -> AnyAngle` 计算两个向量之间的夹角。 -参数: +**参数**: - other: 另一个向量 +**返回**: + +- 夹角 +
-源码 + 源代码 ```python def cal_angle(self, other: 'Vector3') -> 'AnyAngle': @@ -94,7 +101,7 @@ def cal_angle(self, other: 'Vector3') -> 'AnyAngle': ```
-### *def* `cross(self, other: 'Vector3') -> 'Vector3'` +### *method* `cross(self, other: Vector3) -> Vector3` 向量积 叉乘:v1 cross v2 -> v3 @@ -103,10 +110,18 @@ def cal_angle(self, other: 'Vector3') -> 'AnyAngle': 其余结果的模为平行四边形的面积。 +**参数**: + +- other: + +**返回**: + +- 行列式的结果 +
-源码 + 源代码 ```python def cross(self, other: 'Vector3') -> 'Vector3': @@ -133,21 +148,25 @@ def cross(self, other: 'Vector3') -> 'Vector3': ```
-### *def* `is_approx_parallel(self, other: 'Vector3', epsilon: float = APPROX) -> bool` +### *method* `is_approx_parallel(self, other: Vector3, epsilon: float = APPROX) -> bool` 判断两个向量是否近似平行。 -参数: +**参数**: - other: 另一个向量 - epsilon: 允许的误差 +**返回**: + +- 是否近似平行 +
-源码 + 源代码 ```python def is_approx_parallel(self, other: 'Vector3', epsilon: float=APPROX) -> bool: @@ -163,19 +182,23 @@ def is_approx_parallel(self, other: 'Vector3', epsilon: float=APPROX) -> bool: ```
-### *def* `is_parallel(self, other: 'Vector3') -> bool` +### *method* `is_parallel(self, other: Vector3) -> bool` 判断两个向量是否平行。 -参数: +**参数**: - other: 另一个向量 +**返回**: + +- 是否平行 +
-源码 + 源代码 ```python def is_parallel(self, other: 'Vector3') -> bool: @@ -190,7 +213,7 @@ def is_parallel(self, other: 'Vector3') -> bool: ```
-### *def* `normalize(self)` +### *method* `normalize(self)` 将向量归一化。 @@ -200,7 +223,7 @@ def is_parallel(self, other: 'Vector3') -> bool:
-源码 + 源代码 ```python def normalize(self): @@ -217,7 +240,7 @@ def normalize(self):
### `@property` -### *def* `np_array(self) -> 'np.ndarray'` +### *method* `np_array(self) -> np.ndarray` @@ -225,7 +248,7 @@ def normalize(self):
-源码 + 源代码 ```python @property @@ -239,19 +262,19 @@ def np_array(self) -> 'np.ndarray':
### `@property` -### *def* `length(self) -> float` +### *method* `length(self) -> float` 向量的模。 -返回: +**返回**: - 模
-源码 + 源代码 ```python @property @@ -266,19 +289,19 @@ def length(self) -> float:
### `@property` -### *def* `unit(self) -> 'Vector3'` +### *method* `unit(self) -> Vector3` 获取该向量的单位向量。 -返回: +**返回**: - 单位向量
-源码 + 源代码 ```python @property @@ -292,11 +315,11 @@ def unit(self) -> 'Vector3': ```
-### *def* `__abs__(self)` +### *method* `__abs__(self)`
-源码 + 源代码 ```python def __abs__(self): @@ -305,11 +328,11 @@ def __abs__(self):
### `@overload` -### *def* `__add__(self, other: 'Vector3') -> 'Vector3'` +### *method* `self + other: Vector3 => Vector3`
-源码 + 源代码 ```python @overload @@ -319,11 +342,11 @@ def __add__(self, other: 'Vector3') -> 'Vector3':
### `@overload` -### *def* `__add__(self, other: 'Point3') -> 'Point3'` +### *method* `self + other: Point3 => Point3`
-源码 + 源代码 ```python @overload @@ -332,21 +355,21 @@ def __add__(self, other: 'Point3') -> 'Point3': ```
-### *def* `__add__(self, other)` +### *method* `self + other` V + P -> P V + V -> V -参数: +**参数**: - other:
-源码 + 源代码 ```python def __add__(self, other): @@ -368,19 +391,23 @@ def __add__(self, other): ```
-### *def* `__eq__(self, other)` +### *method* `__eq__(self, other)` 判断两个向量是否相等。 -参数: +**参数**: - other: +**返回**: + +- 是否相等 +
-源码 + 源代码 ```python def __eq__(self, other): @@ -395,7 +422,7 @@ def __eq__(self, other): ```
-### *def* `__radd__(self, other: 'Point3') -> 'Point3'` +### *method* `self + other: Point3 => Point3` P + V -> P @@ -407,7 +434,7 @@ P + V -> P
-源码 + 源代码 ```python def __radd__(self, other: 'Point3') -> 'Point3': @@ -423,11 +450,11 @@ def __radd__(self, other: 'Point3') -> 'Point3':
### `@overload` -### *def* `__sub__(self, other: 'Vector3') -> 'Vector3'` +### *method* `self - other: Vector3 => Vector3`
-源码 + 源代码 ```python @overload @@ -437,11 +464,11 @@ def __sub__(self, other: 'Vector3') -> 'Vector3':
### `@overload` -### *def* `__sub__(self, other: 'Point3') -> 'Point3'` +### *method* `self - other: Point3 => Point3`
-源码 + 源代码 ```python @overload @@ -450,21 +477,21 @@ def __sub__(self, other: 'Point3') -> 'Point3': ```
-### *def* `__sub__(self, other)` +### *method* `self - other` V - P -> P V - V -> V -参数: +**参数**: - other:
-源码 + 源代码 ```python def __sub__(self, other): @@ -485,19 +512,19 @@ def __sub__(self, other): ```
-### *def* `__rsub__(self, other: 'Point3')` +### *method* `self - other: Point3` P - V -> P -参数: +**参数**: - other:
-源码 + 源代码 ```python def __rsub__(self, other: 'Point3'): @@ -516,11 +543,11 @@ def __rsub__(self, other: 'Point3'):
### `@overload` -### *def* `__mul__(self, other: 'Vector3') -> 'Vector3'` +### *method* `self * other: Vector3 => Vector3`
-源码 + 源代码 ```python @overload @@ -530,11 +557,11 @@ def __mul__(self, other: 'Vector3') -> 'Vector3':
### `@overload` -### *def* `__mul__(self, other: RealNumber) -> 'Vector3'` +### *method* `self * other: RealNumber => Vector3`
-源码 + 源代码 ```python @overload @@ -543,19 +570,19 @@ def __mul__(self, other: RealNumber) -> 'Vector3': ```
-### *def* `__mul__(self, other: 'int | float | Vector3') -> 'Vector3'` +### *method* `self * other: int | float | Vector3 => Vector3` 数组运算 非点乘。点乘使用@,叉乘使用cross。 -参数: +**参数**: - other:
-源码 + 源代码 ```python def __mul__(self, other: 'int | float | Vector3') -> 'Vector3': @@ -575,11 +602,11 @@ def __mul__(self, other: 'int | float | Vector3') -> 'Vector3': ```
-### *def* `__rmul__(self, other: 'RealNumber') -> 'Vector3'` +### *method* `self * other: RealNumber => Vector3`
-源码 + 源代码 ```python def __rmul__(self, other: 'RealNumber') -> 'Vector3': @@ -587,19 +614,19 @@ def __rmul__(self, other: 'RealNumber') -> 'Vector3': ```
-### *def* `__matmul__(self, other: 'Vector3') -> 'RealNumber'` +### *method* `self @ other: Vector3 => RealNumber` 点乘。 -参数: +**参数**: - other:
-源码 + 源代码 ```python def __matmul__(self, other: 'Vector3') -> 'RealNumber': @@ -613,11 +640,11 @@ def __matmul__(self, other: 'Vector3') -> 'RealNumber': ```
-### *def* `__truediv__(self, other: RealNumber) -> 'Vector3'` +### *method* `self / other: RealNumber => Vector3`
-源码 + 源代码 ```python def __truediv__(self, other: RealNumber) -> 'Vector3': @@ -625,11 +652,11 @@ def __truediv__(self, other: RealNumber) -> 'Vector3': ```
-### *def* `__neg__(self)` +### *method* `- self`
-源码 + 源代码 ```python def __neg__(self): @@ -637,35 +664,27 @@ def __neg__(self): ```
-### *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)` +- **类型**: `Vector3` + +- **说明**: 零向量 + ### ***var*** `x_axis = Vector3(1, 0, 0)` +- **类型**: `Vector3` + +- **说明**: x轴单位向量 + ### ***var*** `y_axis = Vector3(0, 1, 0)` +- **类型**: `Vector3` + +- **说明**: y轴单位向量 + ### ***var*** `z_axis = Vector3(0, 0, 1)` +- **类型**: `Vector3` + +- **说明**: z轴单位向量 + diff --git a/docs/api/presets/model/index.md b/docs/api/presets/model/index.md index 53ad44e..ebbd889 100644 --- a/docs/api/presets/model/index.md +++ b/docs/api/presets/model/index.md @@ -1,24 +1,27 @@ --- title: mbcp.presets.model --- -### ***class*** `GeometricModels` - +### **class** `GeometricModels` ### `@staticmethod` -### *def* `sphere(radius: float, density: float)` +### *method* `sphere(radius: float, density: float)` 生成球体上的点集。 -参数: +**参数**: - radius: - density: +**返回**: + +- List[Point3]: 球体上的点集。 +
-源码 + 源代码 ```python @staticmethod 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..4058420 --- /dev/null +++ b/docs/en/api/mp_math/angle.md @@ -0,0 +1,423 @@ +--- +title: mbcp.mp_math.angle +--- +### **class** `Angle` +### **class** `AnyAngle(Angle)` +### *method* `__init__(self, value: float, is_radian: bool = False)` + + +任意角度。 + +**Arguments**: + +- 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` +### *method* `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` +### *method* `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` +### *method* `degree(self) -> float` + + +角度。 + +**Return**: + +- 弧度 + + + +
+ Source code + +```python +@property +def degree(self) -> float: + """ + 角度。 + Returns: + 弧度 + """ + return self.radian * 180 / PI +``` +
+ +### `@property` +### *method* `minimum_positive(self) -> AnyAngle` + + +最小正角。 + +**Return**: + +- 最小正角度 + + + +
+ Source code + +```python +@property +def minimum_positive(self) -> 'AnyAngle': + """ + 最小正角。 + Returns: + 最小正角度 + """ + return AnyAngle(self.radian % (2 * PI)) +``` +
+ +### `@property` +### *method* `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` +### *method* `sin(self) -> float` + + +正弦值。 + +**Return**: + +- 正弦值 + + + +
+ Source code + +```python +@property +def sin(self) -> float: + """ + 正弦值。 + Returns: + 正弦值 + """ + return math.sin(self.radian) +``` +
+ +### `@property` +### *method* `cos(self) -> float` + + +余弦值。 + +**Return**: + +- 余弦值 + + + +
+ Source code + +```python +@property +def cos(self) -> float: + """ + 余弦值。 + Returns: + 余弦值 + """ + return math.cos(self.radian) +``` +
+ +### `@property` +### *method* `tan(self) -> float` + + +正切值。 + +**Return**: + +- 正切值 + + + +
+ Source code + +```python +@property +def tan(self) -> float: + """ + 正切值。 + Returns: + 正切值 + """ + return math.tan(self.radian) +``` +
+ +### `@property` +### *method* `cot(self) -> float` + + +余切值。 + +**Return**: + +- 余切值 + + + +
+ Source code + +```python +@property +def cot(self) -> float: + """ + 余切值。 + Returns: + 余切值 + """ + return 1 / math.tan(self.radian) +``` +
+ +### `@property` +### *method* `sec(self) -> float` + + +正割值。 + +**Return**: + +- 正割值 + + + +
+ Source code + +```python +@property +def sec(self) -> float: + """ + 正割值。 + Returns: + 正割值 + """ + return 1 / math.cos(self.radian) +``` +
+ +### `@property` +### *method* `csc(self) -> float` + + +余割值。 + +**Return**: + +- 余割值 + + + +
+ Source code + +```python +@property +def csc(self) -> float: + """ + 余割值。 + Returns: + 余割值 + """ + return 1 / math.sin(self.radian) +``` +
+ +### *method* `self + other: AnyAngle => AnyAngle` + + +
+ Source code + +```python +def __add__(self, other: 'AnyAngle') -> 'AnyAngle': + return AnyAngle(self.radian + other.radian, is_radian=True) +``` +
+ +### *method* `__eq__(self, other)` + + +
+ Source code + +```python +def __eq__(self, other): + return approx(self.radian, other.radian) +``` +
+ +### *method* `self - other: AnyAngle => AnyAngle` + + +
+ Source code + +```python +def __sub__(self, other: 'AnyAngle') -> 'AnyAngle': + return AnyAngle(self.radian - other.radian, is_radian=True) +``` +
+ +### *method* `self * other: float => AnyAngle` + + +
+ Source code + +```python +def __mul__(self, other: float) -> 'AnyAngle': + return AnyAngle(self.radian * other, is_radian=True) +``` +
+ +### `@overload` +### *method* `self / other: float => AnyAngle` + + +
+ Source code + +```python +@overload +def __truediv__(self, other: float) -> 'AnyAngle': + ... +``` +
+ +### `@overload` +### *method* `self / other: AnyAngle => float` + + +
+ Source code + +```python +@overload +def __truediv__(self, other: 'AnyAngle') -> float: + ... +``` +
+ +### *method* `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..a94898a --- /dev/null +++ b/docs/en/api/mp_math/const.md @@ -0,0 +1,3 @@ +--- +title: mbcp.mp_math.const +--- diff --git a/docs/en/api/mp_math/equation.md b/docs/en/api/mp_math/equation.md new file mode 100644 index 0000000..0a63f52 --- /dev/null +++ b/docs/en/api/mp_math/equation.md @@ -0,0 +1,162 @@ +--- +title: mbcp.mp_math.equation +--- +### *func* `get_partial_derivative_func(func: MultiVarsFunc = EPSILON) -> MultiVarsFunc` + + +求N元函数一阶偏导函数。这玩意不太稳定,慎用。 + +**Arguments**: + +- 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') +``` +
+ +### *func* `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) +``` +
+ +### *func* `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` +### *method* `__init__(self, x_func: OneVarFunc, y_func: OneVarFunc, z_func: OneVarFunc)` + + +曲线方程。 + +**Arguments**: + +- 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 +``` +
+ +### *method* `__call__(self) -> Point3 | tuple[Point3, ...]` + + +计算曲线上的点。 + +**Arguments**: + +- *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))]) +``` +
+ 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..3267541 --- /dev/null +++ b/docs/en/api/mp_math/line.md @@ -0,0 +1,581 @@ +--- +title: mbcp.mp_math.line +--- +### **class** `Line3` +### *method* `__init__(self, point: Point3, direction: Vector3)` + + +三维空间中的直线。由一个点和一个方向向量确定。 + +**Arguments**: + +- point: 直线上的一点 + +- direction: 直线的方向向量 + + + +
+ Source code + +```python +def __init__(self, point: 'Point3', direction: 'Vector3'): + """ + 三维空间中的直线。由一个点和一个方向向量确定。 + Args: + point: 直线上的一点 + direction: 直线的方向向量 + """ + self.point = point + self.direction = direction +``` +
+ +### *method* `approx(self, other: Line3, epsilon: float = APPROX) -> bool` + + +判断两条直线是否近似相等。 + +**Arguments**: + +- 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) +``` +
+ +### *method* `cal_angle(self, other: Line3) -> AnyAngle` + + +计算直线和直线之间的夹角。 + +**Arguments**: + +- 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) +``` +
+ +### *method* `cal_distance(self, other: Line3 | Point3) -> float` + + +计算直线和直线或点之间的距离。 + +**Arguments**: + +- 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.') +``` +
+ +### *method* `cal_intersection(self, other: Line3) -> Point3` + + +计算两条直线的交点。 + +**Arguments**: + +- 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 +``` +
+ +### *method* `cal_perpendicular(self, point: Point3) -> Line3` + + +计算直线经过指定点p的垂线。 + +**Arguments**: + +- 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)) +``` +
+ +### *method* `get_point(self, t: RealNumber) -> Point3` + + +获取直线上的点。同一条直线,但起始点和方向向量不同,则同一个t对应的点不同。 + +**Arguments**: + +- t: 参数t + +**Return**: + +- 点 + + + +
+ Source code + +```python +def get_point(self, t: RealNumber) -> 'Point3': + """ + 获取直线上的点。同一条直线,但起始点和方向向量不同,则同一个t对应的点不同。 + Args: + t: 参数t + Returns: + 点 + """ + return self.point + t * self.direction +``` +
+ +### *method* `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) +``` +
+ +### *method* `is_approx_parallel(self, other: Line3, epsilon: float = 1e-06) -> bool` + + +判断两条直线是否近似平行。 + +**Arguments**: + +- 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) +``` +
+ +### *method* `is_parallel(self, other: Line3) -> bool` + + +判断两条直线是否平行。 + +**Arguments**: + +- other: 另一条直线 + +**Return**: + +- 是否平行 + + + +
+ Source code + +```python +def is_parallel(self, other: 'Line3') -> bool: + """ + 判断两条直线是否平行。 + Args: + other: 另一条直线 + Returns: + 是否平行 + """ + return self.direction.is_parallel(other.direction) +``` +
+ +### *method* `is_collinear(self, other: Line3) -> bool` + + +判断两条直线是否共线。 + +**Arguments**: + +- 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) +``` +
+ +### *method* `is_point_on(self, point: Point3) -> bool` + + +判断点是否在直线上。 + +**Arguments**: + +- point: 点 + +**Return**: + +- 是否在直线上 + + + +
+ Source code + +```python +def is_point_on(self, point: 'Point3') -> bool: + """ + 判断点是否在直线上。 + Args: + point: 点 + Returns: + 是否在直线上 + """ + return (point - self.point).is_parallel(self.direction) +``` +
+ +### *method* `is_coplanar(self, other: Line3) -> bool` + + +判断两条直线是否共面。 +充要条件:两直线方向向量的叉乘与两直线上任意一点的向量的点积为0。 + +**Arguments**: + +- 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 +``` +
+ +### *method* `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` +### *method* `from_two_points(cls, p1: Point3, p2: Point3) -> Line3` + + +工厂函数 由两点构造直线。 + +**Arguments**: + +- 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) +``` +
+ +### *method* `__and__(self, other: Line3) -> Line3 | Point3 | None` + + +计算两条直线点集合的交集。重合线返回自身,平行线返回None,交线返回交点。 + +**Arguments**: + +- 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) +``` +
+ +### *method* `__eq__(self, other) -> bool` + + +判断两条直线是否等价。 + +v1 // v2 ∧ (p1 - p2) // v1 + +**Arguments**: + +- 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) +``` +
+ 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..37d13e4 --- /dev/null +++ b/docs/en/api/mp_math/mp_math_typing.md @@ -0,0 +1,63 @@ +--- +title: mbcp.mp_math.mp_math_typing +--- +### ***var*** `RealNumber = int | float` + +- **Type**: `TypeAlias` + +### ***var*** `Number = RealNumber | complex` + +- **Type**: `TypeAlias` + +### ***var*** `Var = SingleVar | ArrayVar` + +- **Type**: `TypeAlias` + +### ***var*** `OneSingleVarFunc = Callable[[SingleVar], SingleVar]` + +- **Type**: `TypeAlias` + +### ***var*** `OneArrayFunc = Callable[[ArrayVar], ArrayVar]` + +- **Type**: `TypeAlias` + +### ***var*** `OneVarFunc = OneSingleVarFunc | OneArrayFunc` + +- **Type**: `TypeAlias` + +### ***var*** `TwoSingleVarsFunc = Callable[[SingleVar, SingleVar], SingleVar]` + +- **Type**: `TypeAlias` + +### ***var*** `TwoArraysFunc = Callable[[ArrayVar, ArrayVar], ArrayVar]` + +- **Type**: `TypeAlias` + +### ***var*** `TwoVarsFunc = TwoSingleVarsFunc | TwoArraysFunc` + +- **Type**: `TypeAlias` + +### ***var*** `ThreeSingleVarsFunc = Callable[[SingleVar, SingleVar, SingleVar], SingleVar]` + +- **Type**: `TypeAlias` + +### ***var*** `ThreeArraysFunc = Callable[[ArrayVar, ArrayVar, ArrayVar], ArrayVar]` + +- **Type**: `TypeAlias` + +### ***var*** `ThreeVarsFunc = ThreeSingleVarsFunc | ThreeArraysFunc` + +- **Type**: `TypeAlias` + +### ***var*** `MultiSingleVarsFunc = Callable[..., SingleVar]` + +- **Type**: `TypeAlias` + +### ***var*** `MultiArraysFunc = Callable[..., ArrayVar]` + +- **Type**: `TypeAlias` + +### ***var*** `MultiVarsFunc = MultiSingleVarsFunc | MultiArraysFunc` + +- **Type**: `TypeAlias` + diff --git a/docs/en/api/mp_math/plane.md b/docs/en/api/mp_math/plane.md new file mode 100644 index 0000000..fcdcb19 --- /dev/null +++ b/docs/en/api/mp_math/plane.md @@ -0,0 +1,592 @@ +--- +title: mbcp.mp_math.plane +--- +### **class** `Plane3` +### *method* `__init__(self, a: float, b: float, c: float, d: float)` + + +平面方程:ax + by + cz + d = 0 + +**Arguments**: + +- a: x系数 + +- b: y系数 + +- c: z系数 + +- d: 常数项 + + + +
+ Source code + +```python +def __init__(self, a: float, b: float, c: float, d: float): + """ + 平面方程:ax + by + cz + d = 0 + Args: + a: x系数 + b: y系数 + c: z系数 + d: 常数项 + """ + self.a = a + self.b = b + self.c = c + self.d = d +``` +
+ +### *method* `approx(self, other: Plane3) -> bool` + + +判断两个平面是否近似相等。 + +**Arguments**: + +- other: 另一个平面 + +**Return**: + +- 是否近似相等 + + + +
+ Source code + +```python +def approx(self, other: 'Plane3') -> bool: + """ + 判断两个平面是否近似相等。 + Args: + other: 另一个平面 + Returns: + 是否近似相等 + """ + 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 +``` +
+ +### *method* `cal_angle(self, other: Line3 | Plane3) -> AnyAngle` + + +计算平面与平面之间的夹角。 + +**Arguments**: + +- 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)}') +``` +
+ +### *method* `cal_distance(self, other: Plane3 | Point3) -> float` + + +计算平面与平面或点之间的距离。 + +**Arguments**: + +- 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)}') +``` +
+ +### *method* `cal_intersection_line3(self, other: Plane3) -> Line3` + + +计算两平面的交线。 + +**Arguments**: + +- 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) +``` +
+ +### *method* `cal_intersection_point3(self, other: Line3) -> Point3` + + +计算平面与直线的交点。 + +**Arguments**: + +- 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)) +``` +
+ +### *method* `cal_parallel_plane3(self, point: Point3) -> Plane3` + + +计算平行于该平面且过指定点的平面。 + +**Arguments**: + +- 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) +``` +
+ +### *method* `is_parallel(self, other: Plane3) -> bool` + + +判断两个平面是否平行。 + +**Arguments**: + +- other: 另一个平面 + +**Return**: + +- 是否平行 + + + +
+ Source code + +```python +def is_parallel(self, other: 'Plane3') -> bool: + """ + 判断两个平面是否平行。 + Args: + other: 另一个平面 + Returns: + 是否平行 + """ + return self.normal.is_parallel(other.normal) +``` +
+ +### `@property` +### *method* `normal(self) -> Vector3` + + +平面的法向量。 + +**Return**: + +- 法向量 + + + +
+ Source code + +```python +@property +def normal(self) -> 'Vector3': + """ + 平面的法向量。 + Returns: + 法向量 + """ + return Vector3(self.a, self.b, self.c) +``` +
+ +### `@classmethod` +### *method* `from_point_and_normal(cls, point: Point3, normal: Vector3) -> Plane3` + + +工厂函数 由点和法向量构造平面(点法式构造)。 + +**Arguments**: + +- 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` +### *method* `from_three_points(cls, p1: Point3, p2: Point3, p3: Point3) -> Plane3` + + +工厂函数 由三点构造平面。 + +**Arguments**: + +- 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` +### *method* `from_two_lines(cls, l1: Line3, l2: Line3) -> Plane3` + + +工厂函数 由两直线构造平面。 + +**Arguments**: + +- 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` +### *method* `from_point_and_line(cls, point: Point3, line: Line3) -> Plane3` + + +工厂函数 由点和直线构造平面。 + +**Arguments**: + +- 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) +``` +
+ +### `@overload` +### *method* `__and__(self, other: Line3) -> Point3 | None` + + +
+ Source code + +```python +@overload +def __and__(self, other: 'Line3') -> 'Point3 | None': + ... +``` +
+ +### `@overload` +### *method* `__and__(self, other: Plane3) -> Line3 | None` + + +
+ Source code + +```python +@overload +def __and__(self, other: 'Plane3') -> 'Line3 | None': + ... +``` +
+ +### *method* `__and__(self, other)` + + +取两平面的交集(人话:交线) + +**Arguments**: + +- 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)}'") +``` +
+ +### *method* `__eq__(self, other) -> bool` + + +
+ Source code + +```python +def __eq__(self, other) -> bool: + return self.approx(other) +``` +
+ +### *method* `__rand__(self, other: Line3) -> Point3` + + +
+ Source code + +```python +def __rand__(self, other: 'Line3') -> 'Point3': + return self.cal_intersection_point3(other) +``` +
+ diff --git a/docs/en/api/mp_math/point.md b/docs/en/api/mp_math/point.md new file mode 100644 index 0000000..7b5e6af --- /dev/null +++ b/docs/en/api/mp_math/point.md @@ -0,0 +1,186 @@ +--- +title: mbcp.mp_math.point +--- +### **class** `Point3` +### *method* `__init__(self, x: float, y: float, z: float)` + + +笛卡尔坐标系中的点。 + +**Arguments**: + +- 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 +``` +
+ +### *method* `approx(self, other: Point3, epsilon: float = APPROX) -> bool` + + +判断两个点是否近似相等。 + +**Arguments**: + +- 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]) +``` +
+ +### `@overload` +### *method* `self + other: Vector3 => Point3` + + +
+ Source code + +```python +@overload +def __add__(self, other: 'Vector3') -> 'Point3': + ... +``` +
+ +### `@overload` +### *method* `self + other: Point3 => Point3` + + +
+ Source code + +```python +@overload +def __add__(self, other: 'Point3') -> 'Point3': + ... +``` +
+ +### *method* `self + other` + + +P + V -> P +P + P -> P + +**Arguments**: + +- 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) +``` +
+ +### *method* `__eq__(self, other)` + + +判断两个点是否相等。 + +**Arguments**: + +- 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) +``` +
+ +### *method* `self - other: Point3 => Vector3` + + +P - P -> V + +P - V -> P 已在 :class:`Vector3` 中实现 + +**Arguments**: + +- 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..4fff8a2 --- /dev/null +++ b/docs/en/api/mp_math/segment.md @@ -0,0 +1,34 @@ +--- +title: mbcp.mp_math.segment +--- +### **class** `Segment3` +### *method* `__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) +``` +
+ diff --git a/docs/en/api/mp_math/utils.md b/docs/en/api/mp_math/utils.md new file mode 100644 index 0000000..d1cfdad --- /dev/null +++ b/docs/en/api/mp_math/utils.md @@ -0,0 +1,218 @@ +--- +title: mbcp.mp_math.utils +--- +### *func* `clamp() -> float` + + +区间限定函数 + +**Arguments**: + +- 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_) +``` +
+ +### *func* `approx(x: float = 0.0, y: float = APPROX) -> bool` + + +判断两个数是否近似相等。或包装一个实数,用于判断是否近似于0。 + +**Arguments**: + +- x: 数1 + +- y: 数2 + +- epsilon: 误差 + +**Return**: + +- 是否近似相等 + + + +
+ Source code + +```python +def approx(x: float, y: float=0.0, epsilon: float=APPROX) -> bool: + """ + 判断两个数是否近似相等。或包装一个实数,用于判断是否近似于0。 + Args: + x: 数1 + y: 数2 + epsilon: 误差 + Returns: + 是否近似相等 + """ + return abs(x - y) < epsilon +``` +
+ +### *func* `sign(x: float = False) -> str` + + +获取数的符号。 + +**Arguments**: + +- 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 '' +``` +
+ +### *func* `sign_format(x: float = False) -> str` + + +格式化符号数 +-1 -> -1 +1 -> +1 +0 -> "" + +**Arguments**: + +- 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` +### *method* `__init__(self, value: RealNumber)` + + +
+ Source code + +```python +def __init__(self, value: RealNumber): + self.value = value +``` +
+ +### *method* `__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) +``` +
+ +### *method* `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)}') +``` +
+ +### *method* `__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..083c669 --- /dev/null +++ b/docs/en/api/mp_math/vector.md @@ -0,0 +1,690 @@ +--- +title: mbcp.mp_math.vector +--- +### **class** `Vector3` +### *method* `__init__(self, x: float, y: float, z: float)` + + +3维向量 + +**Arguments**: + +- 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 +``` +
+ +### *method* `approx(self, other: Vector3, epsilon: float = APPROX) -> bool` + + +判断两个向量是否近似相等。 + +**Arguments**: + +- 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]) +``` +
+ +### *method* `cal_angle(self, other: Vector3) -> AnyAngle` + + +计算两个向量之间的夹角。 + +**Arguments**: + +- 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) +``` +
+ +### *method* `cross(self, other: Vector3) -> Vector3` + + +向量积 叉乘:v1 cross v2 -> v3 + +叉乘为0,则两向量平行。 +其余结果的模为平行四边形的面积。 + + +**Arguments**: + +- 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) +``` +
+ +### *method* `is_approx_parallel(self, other: Vector3, epsilon: float = APPROX) -> bool` + + +判断两个向量是否近似平行。 + +**Arguments**: + +- 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 +``` +
+ +### *method* `is_parallel(self, other: Vector3) -> bool` + + +判断两个向量是否平行。 + +**Arguments**: + +- other: 另一个向量 + +**Return**: + +- 是否平行 + + + +
+ Source code + +```python +def is_parallel(self, other: 'Vector3') -> bool: + """ + 判断两个向量是否平行。 + Args: + other: 另一个向量 + Returns: + 是否平行 + """ + return self.cross(other).approx(zero_vector3) +``` +
+ +### *method* `normalize(self)` + + +将向量归一化。 + +自体归一化,不返回值。 + + + +
+ Source code + +```python +def normalize(self): + """ + 将向量归一化。 + + 自体归一化,不返回值。 + """ + length = self.length + self.x /= length + self.y /= length + self.z /= length +``` +
+ +### `@property` +### *method* `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` +### *method* `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` +### *method* `unit(self) -> Vector3` + + +获取该向量的单位向量。 + +**Return**: + +- 单位向量 + + + +
+ Source code + +```python +@property +def unit(self) -> 'Vector3': + """ + 获取该向量的单位向量。 + Returns: + 单位向量 + """ + return self / self.length +``` +
+ +### *method* `__abs__(self)` + + +
+ Source code + +```python +def __abs__(self): + return self.length +``` +
+ +### `@overload` +### *method* `self + other: Vector3 => Vector3` + + +
+ Source code + +```python +@overload +def __add__(self, other: 'Vector3') -> 'Vector3': + ... +``` +
+ +### `@overload` +### *method* `self + other: Point3 => Point3` + + +
+ Source code + +```python +@overload +def __add__(self, other: 'Point3') -> 'Point3': + ... +``` +
+ +### *method* `self + other` + + +V + P -> P + +V + V -> V + +**Arguments**: + +- 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)}'") +``` +
+ +### *method* `__eq__(self, other)` + + +判断两个向量是否相等。 + +**Arguments**: + +- 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) +``` +
+ +### *method* `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` +### *method* `self - other: Vector3 => Vector3` + + +
+ Source code + +```python +@overload +def __sub__(self, other: 'Vector3') -> 'Vector3': + ... +``` +
+ +### `@overload` +### *method* `self - other: Point3 => Point3` + + +
+ Source code + +```python +@overload +def __sub__(self, other: 'Point3') -> 'Point3': + ... +``` +
+ +### *method* `self - other` + + +V - P -> P + +V - V -> V + +**Arguments**: + +- 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)}"') +``` +
+ +### *method* `self - other: Point3` + + +P - V -> P + +**Arguments**: + +- 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` +### *method* `self * other: Vector3 => Vector3` + + +
+ Source code + +```python +@overload +def __mul__(self, other: 'Vector3') -> 'Vector3': + ... +``` +
+ +### `@overload` +### *method* `self * other: RealNumber => Vector3` + + +
+ Source code + +```python +@overload +def __mul__(self, other: RealNumber) -> 'Vector3': + ... +``` +
+ +### *method* `self * other: int | float | Vector3 => Vector3` + + +数组运算 非点乘。点乘使用@,叉乘使用cross。 + +**Arguments**: + +- 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)}'") +``` +
+ +### *method* `self * other: RealNumber => Vector3` + + +
+ Source code + +```python +def __rmul__(self, other: 'RealNumber') -> 'Vector3': + return self.__mul__(other) +``` +
+ +### *method* `self @ other: Vector3 => RealNumber` + + +点乘。 + +**Arguments**: + +- 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 +``` +
+ +### *method* `self / other: RealNumber => Vector3` + + +
+ Source code + +```python +def __truediv__(self, other: RealNumber) -> 'Vector3': + return Vector3(self.x / other, self.y / other, self.z / other) +``` +
+ +### *method* `- self` + + +
+ Source code + +```python +def __neg__(self): + return Vector3(-self.x, -self.y, -self.z) +``` +
+ +### ***var*** `zero_vector3 = Vector3(0, 0, 0)` + +- **Type**: `Vector3` + +- **Description**: 零向量 + +### ***var*** `x_axis = Vector3(1, 0, 0)` + +- **Type**: `Vector3` + +- **Description**: x轴单位向量 + +### ***var*** `y_axis = Vector3(0, 1, 0)` + +- **Type**: `Vector3` + +- **Description**: y轴单位向量 + +### ***var*** `z_axis = Vector3(0, 0, 1)` + +- **Type**: `Vector3` + +- **Description**: z轴单位向量 + 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..5ef8faf --- /dev/null +++ b/docs/en/api/presets/model/index.md @@ -0,0 +1,47 @@ +--- +title: mbcp.presets.model +--- +### **class** `GeometricModels` +### `@staticmethod` +### *method* `sphere(radius: float, density: float)` + + +生成球体上的点集。 + +**Arguments**: + +- 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..545fe31 --- /dev/null +++ b/docs/ja/api/mp_math/angle.md @@ -0,0 +1,423 @@ +--- +title: mbcp.mp_math.angle +--- +### **class** `Angle` +### **class** `AnyAngle(Angle)` +### *method* `__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` +### *method* `complementary(self) -> AnyAngle` + + +余角:两角的和为90°。 + +**戻り値**: + +- 余角 + + + +
+ ソースコード + +```python +@property +def complementary(self) -> 'AnyAngle': + """ + 余角:两角的和为90°。 + Returns: + 余角 + """ + return AnyAngle(PI / 2 - self.minimum_positive.radian, is_radian=True) +``` +
+ +### `@property` +### *method* `supplementary(self) -> AnyAngle` + + +补角:两角的和为180°。 + +**戻り値**: + +- 补角 + + + +
+ ソースコード + +```python +@property +def supplementary(self) -> 'AnyAngle': + """ + 补角:两角的和为180°。 + Returns: + 补角 + """ + return AnyAngle(PI - self.minimum_positive.radian, is_radian=True) +``` +
+ +### `@property` +### *method* `degree(self) -> float` + + +角度。 + +**戻り値**: + +- 弧度 + + + +
+ ソースコード + +```python +@property +def degree(self) -> float: + """ + 角度。 + Returns: + 弧度 + """ + return self.radian * 180 / PI +``` +
+ +### `@property` +### *method* `minimum_positive(self) -> AnyAngle` + + +最小正角。 + +**戻り値**: + +- 最小正角度 + + + +
+ ソースコード + +```python +@property +def minimum_positive(self) -> 'AnyAngle': + """ + 最小正角。 + Returns: + 最小正角度 + """ + return AnyAngle(self.radian % (2 * PI)) +``` +
+ +### `@property` +### *method* `maximum_negative(self) -> AnyAngle` + + +最大负角。 + +**戻り値**: + +- 最大负角度 + + + +
+ ソースコード + +```python +@property +def maximum_negative(self) -> 'AnyAngle': + """ + 最大负角。 + Returns: + 最大负角度 + """ + return AnyAngle(-self.radian % (2 * PI), is_radian=True) +``` +
+ +### `@property` +### *method* `sin(self) -> float` + + +正弦值。 + +**戻り値**: + +- 正弦值 + + + +
+ ソースコード + +```python +@property +def sin(self) -> float: + """ + 正弦值。 + Returns: + 正弦值 + """ + return math.sin(self.radian) +``` +
+ +### `@property` +### *method* `cos(self) -> float` + + +余弦值。 + +**戻り値**: + +- 余弦值 + + + +
+ ソースコード + +```python +@property +def cos(self) -> float: + """ + 余弦值。 + Returns: + 余弦值 + """ + return math.cos(self.radian) +``` +
+ +### `@property` +### *method* `tan(self) -> float` + + +正切值。 + +**戻り値**: + +- 正切值 + + + +
+ ソースコード + +```python +@property +def tan(self) -> float: + """ + 正切值。 + Returns: + 正切值 + """ + return math.tan(self.radian) +``` +
+ +### `@property` +### *method* `cot(self) -> float` + + +余切值。 + +**戻り値**: + +- 余切值 + + + +
+ ソースコード + +```python +@property +def cot(self) -> float: + """ + 余切值。 + Returns: + 余切值 + """ + return 1 / math.tan(self.radian) +``` +
+ +### `@property` +### *method* `sec(self) -> float` + + +正割值。 + +**戻り値**: + +- 正割值 + + + +
+ ソースコード + +```python +@property +def sec(self) -> float: + """ + 正割值。 + Returns: + 正割值 + """ + return 1 / math.cos(self.radian) +``` +
+ +### `@property` +### *method* `csc(self) -> float` + + +余割值。 + +**戻り値**: + +- 余割值 + + + +
+ ソースコード + +```python +@property +def csc(self) -> float: + """ + 余割值。 + Returns: + 余割值 + """ + return 1 / math.sin(self.radian) +``` +
+ +### *method* `self + other: AnyAngle => AnyAngle` + + +
+ ソースコード + +```python +def __add__(self, other: 'AnyAngle') -> 'AnyAngle': + return AnyAngle(self.radian + other.radian, is_radian=True) +``` +
+ +### *method* `__eq__(self, other)` + + +
+ ソースコード + +```python +def __eq__(self, other): + return approx(self.radian, other.radian) +``` +
+ +### *method* `self - other: AnyAngle => AnyAngle` + + +
+ ソースコード + +```python +def __sub__(self, other: 'AnyAngle') -> 'AnyAngle': + return AnyAngle(self.radian - other.radian, is_radian=True) +``` +
+ +### *method* `self * other: float => AnyAngle` + + +
+ ソースコード + +```python +def __mul__(self, other: float) -> 'AnyAngle': + return AnyAngle(self.radian * other, is_radian=True) +``` +
+ +### `@overload` +### *method* `self / other: float => AnyAngle` + + +
+ ソースコード + +```python +@overload +def __truediv__(self, other: float) -> 'AnyAngle': + ... +``` +
+ +### `@overload` +### *method* `self / other: AnyAngle => float` + + +
+ ソースコード + +```python +@overload +def __truediv__(self, other: 'AnyAngle') -> float: + ... +``` +
+ +### *method* `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..a94898a --- /dev/null +++ b/docs/ja/api/mp_math/const.md @@ -0,0 +1,3 @@ +--- +title: mbcp.mp_math.const +--- diff --git a/docs/ja/api/mp_math/equation.md b/docs/ja/api/mp_math/equation.md new file mode 100644 index 0000000..af717d2 --- /dev/null +++ b/docs/ja/api/mp_math/equation.md @@ -0,0 +1,162 @@ +--- +title: mbcp.mp_math.equation +--- +### *func* `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') +``` +
+ +### *func* `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) +``` +
+ +### *func* `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` +### *method* `__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 +``` +
+ +### *method* `__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))]) +``` +
+ 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..15d1fd5 --- /dev/null +++ b/docs/ja/api/mp_math/line.md @@ -0,0 +1,581 @@ +--- +title: mbcp.mp_math.line +--- +### **class** `Line3` +### *method* `__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 +``` +
+ +### *method* `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) +``` +
+ +### *method* `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) +``` +
+ +### *method* `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.') +``` +
+ +### *method* `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 +``` +
+ +### *method* `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)) +``` +
+ +### *method* `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 +``` +
+ +### *method* `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) +``` +
+ +### *method* `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) +``` +
+ +### *method* `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) +``` +
+ +### *method* `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) +``` +
+ +### *method* `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) +``` +
+ +### *method* `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 +``` +
+ +### *method* `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` +### *method* `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) +``` +
+ +### *method* `__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) +``` +
+ +### *method* `__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) +``` +
+ 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..43ba76d --- /dev/null +++ b/docs/ja/api/mp_math/mp_math_typing.md @@ -0,0 +1,63 @@ +--- +title: mbcp.mp_math.mp_math_typing +--- +### ***var*** `RealNumber = int | float` + +- **タイプ**: `TypeAlias` + +### ***var*** `Number = RealNumber | complex` + +- **タイプ**: `TypeAlias` + +### ***var*** `Var = SingleVar | ArrayVar` + +- **タイプ**: `TypeAlias` + +### ***var*** `OneSingleVarFunc = Callable[[SingleVar], SingleVar]` + +- **タイプ**: `TypeAlias` + +### ***var*** `OneArrayFunc = Callable[[ArrayVar], ArrayVar]` + +- **タイプ**: `TypeAlias` + +### ***var*** `OneVarFunc = OneSingleVarFunc | OneArrayFunc` + +- **タイプ**: `TypeAlias` + +### ***var*** `TwoSingleVarsFunc = Callable[[SingleVar, SingleVar], SingleVar]` + +- **タイプ**: `TypeAlias` + +### ***var*** `TwoArraysFunc = Callable[[ArrayVar, ArrayVar], ArrayVar]` + +- **タイプ**: `TypeAlias` + +### ***var*** `TwoVarsFunc = TwoSingleVarsFunc | TwoArraysFunc` + +- **タイプ**: `TypeAlias` + +### ***var*** `ThreeSingleVarsFunc = Callable[[SingleVar, SingleVar, SingleVar], SingleVar]` + +- **タイプ**: `TypeAlias` + +### ***var*** `ThreeArraysFunc = Callable[[ArrayVar, ArrayVar, ArrayVar], ArrayVar]` + +- **タイプ**: `TypeAlias` + +### ***var*** `ThreeVarsFunc = ThreeSingleVarsFunc | ThreeArraysFunc` + +- **タイプ**: `TypeAlias` + +### ***var*** `MultiSingleVarsFunc = Callable[..., SingleVar]` + +- **タイプ**: `TypeAlias` + +### ***var*** `MultiArraysFunc = Callable[..., ArrayVar]` + +- **タイプ**: `TypeAlias` + +### ***var*** `MultiVarsFunc = MultiSingleVarsFunc | MultiArraysFunc` + +- **タイプ**: `TypeAlias` + diff --git a/docs/ja/api/mp_math/plane.md b/docs/ja/api/mp_math/plane.md new file mode 100644 index 0000000..adea50f --- /dev/null +++ b/docs/ja/api/mp_math/plane.md @@ -0,0 +1,592 @@ +--- +title: mbcp.mp_math.plane +--- +### **class** `Plane3` +### *method* `__init__(self, a: float, b: float, c: float, d: float)` + + +平面方程:ax + by + cz + d = 0 + +**引数**: + +- a: x系数 + +- b: y系数 + +- c: z系数 + +- d: 常数项 + + + +
+ ソースコード + +```python +def __init__(self, a: float, b: float, c: float, d: float): + """ + 平面方程:ax + by + cz + d = 0 + Args: + a: x系数 + b: y系数 + c: z系数 + d: 常数项 + """ + self.a = a + self.b = b + self.c = c + self.d = d +``` +
+ +### *method* `approx(self, other: Plane3) -> bool` + + +判断两个平面是否近似相等。 + +**引数**: + +- other: 另一个平面 + +**戻り値**: + +- 是否近似相等 + + + +
+ ソースコード + +```python +def approx(self, other: 'Plane3') -> bool: + """ + 判断两个平面是否近似相等。 + Args: + other: 另一个平面 + Returns: + 是否近似相等 + """ + 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 +``` +
+ +### *method* `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)}') +``` +
+ +### *method* `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)}') +``` +
+ +### *method* `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) +``` +
+ +### *method* `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)) +``` +
+ +### *method* `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) +``` +
+ +### *method* `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` +### *method* `normal(self) -> Vector3` + + +平面的法向量。 + +**戻り値**: + +- 法向量 + + + +
+ ソースコード + +```python +@property +def normal(self) -> 'Vector3': + """ + 平面的法向量。 + Returns: + 法向量 + """ + return Vector3(self.a, self.b, self.c) +``` +
+ +### `@classmethod` +### *method* `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` +### *method* `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` +### *method* `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` +### *method* `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) +``` +
+ +### `@overload` +### *method* `__and__(self, other: Line3) -> Point3 | None` + + +
+ ソースコード + +```python +@overload +def __and__(self, other: 'Line3') -> 'Point3 | None': + ... +``` +
+ +### `@overload` +### *method* `__and__(self, other: Plane3) -> Line3 | None` + + +
+ ソースコード + +```python +@overload +def __and__(self, other: 'Plane3') -> 'Line3 | None': + ... +``` +
+ +### *method* `__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)}'") +``` +
+ +### *method* `__eq__(self, other) -> bool` + + +
+ ソースコード + +```python +def __eq__(self, other) -> bool: + return self.approx(other) +``` +
+ +### *method* `__rand__(self, other: Line3) -> Point3` + + +
+ ソースコード + +```python +def __rand__(self, other: 'Line3') -> 'Point3': + return self.cal_intersection_point3(other) +``` +
+ diff --git a/docs/ja/api/mp_math/point.md b/docs/ja/api/mp_math/point.md new file mode 100644 index 0000000..d7f9460 --- /dev/null +++ b/docs/ja/api/mp_math/point.md @@ -0,0 +1,186 @@ +--- +title: mbcp.mp_math.point +--- +### **class** `Point3` +### *method* `__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 +``` +
+ +### *method* `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]) +``` +
+ +### `@overload` +### *method* `self + other: Vector3 => Point3` + + +
+ ソースコード + +```python +@overload +def __add__(self, other: 'Vector3') -> 'Point3': + ... +``` +
+ +### `@overload` +### *method* `self + other: Point3 => Point3` + + +
+ ソースコード + +```python +@overload +def __add__(self, other: 'Point3') -> 'Point3': + ... +``` +
+ +### *method* `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) +``` +
+ +### *method* `__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) +``` +
+ +### *method* `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..b4f7732 --- /dev/null +++ b/docs/ja/api/mp_math/segment.md @@ -0,0 +1,34 @@ +--- +title: mbcp.mp_math.segment +--- +### **class** `Segment3` +### *method* `__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) +``` +
+ diff --git a/docs/ja/api/mp_math/utils.md b/docs/ja/api/mp_math/utils.md new file mode 100644 index 0000000..41276a4 --- /dev/null +++ b/docs/ja/api/mp_math/utils.md @@ -0,0 +1,218 @@ +--- +title: mbcp.mp_math.utils +--- +### *func* `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_) +``` +
+ +### *func* `approx(x: float = 0.0, y: float = APPROX) -> bool` + + +判断两个数是否近似相等。或包装一个实数,用于判断是否近似于0。 + +**引数**: + +- x: 数1 + +- y: 数2 + +- epsilon: 误差 + +**戻り値**: + +- 是否近似相等 + + + +
+ ソースコード + +```python +def approx(x: float, y: float=0.0, epsilon: float=APPROX) -> bool: + """ + 判断两个数是否近似相等。或包装一个实数,用于判断是否近似于0。 + Args: + x: 数1 + y: 数2 + epsilon: 误差 + Returns: + 是否近似相等 + """ + return abs(x - y) < epsilon +``` +
+ +### *func* `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 '' +``` +
+ +### *func* `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` +### *method* `__init__(self, value: RealNumber)` + + +
+ ソースコード + +```python +def __init__(self, value: RealNumber): + self.value = value +``` +
+ +### *method* `__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) +``` +
+ +### *method* `raise_type_error(self, other)` + + +
+ ソースコード + +```python +def raise_type_error(self, other): + raise TypeError(f'Unsupported type: {type(self.value)} and {type(other)}') +``` +
+ +### *method* `__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..e3894d6 --- /dev/null +++ b/docs/ja/api/mp_math/vector.md @@ -0,0 +1,690 @@ +--- +title: mbcp.mp_math.vector +--- +### **class** `Vector3` +### *method* `__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 +``` +
+ +### *method* `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]) +``` +
+ +### *method* `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) +``` +
+ +### *method* `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) +``` +
+ +### *method* `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 +``` +
+ +### *method* `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) +``` +
+ +### *method* `normalize(self)` + + +将向量归一化。 + +自体归一化,不返回值。 + + + +
+ ソースコード + +```python +def normalize(self): + """ + 将向量归一化。 + + 自体归一化,不返回值。 + """ + length = self.length + self.x /= length + self.y /= length + self.z /= length +``` +
+ +### `@property` +### *method* `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` +### *method* `length(self) -> float` + + +向量的模。 + +**戻り値**: + +- 模 + + + +
+ ソースコード + +```python +@property +def length(self) -> float: + """ + 向量的模。 + Returns: + 模 + """ + return math.sqrt(self.x ** 2 + self.y ** 2 + self.z ** 2) +``` +
+ +### `@property` +### *method* `unit(self) -> Vector3` + + +获取该向量的单位向量。 + +**戻り値**: + +- 单位向量 + + + +
+ ソースコード + +```python +@property +def unit(self) -> 'Vector3': + """ + 获取该向量的单位向量。 + Returns: + 单位向量 + """ + return self / self.length +``` +
+ +### *method* `__abs__(self)` + + +
+ ソースコード + +```python +def __abs__(self): + return self.length +``` +
+ +### `@overload` +### *method* `self + other: Vector3 => Vector3` + + +
+ ソースコード + +```python +@overload +def __add__(self, other: 'Vector3') -> 'Vector3': + ... +``` +
+ +### `@overload` +### *method* `self + other: Point3 => Point3` + + +
+ ソースコード + +```python +@overload +def __add__(self, other: 'Point3') -> 'Point3': + ... +``` +
+ +### *method* `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)}'") +``` +
+ +### *method* `__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) +``` +
+ +### *method* `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` +### *method* `self - other: Vector3 => Vector3` + + +
+ ソースコード + +```python +@overload +def __sub__(self, other: 'Vector3') -> 'Vector3': + ... +``` +
+ +### `@overload` +### *method* `self - other: Point3 => Point3` + + +
+ ソースコード + +```python +@overload +def __sub__(self, other: 'Point3') -> 'Point3': + ... +``` +
+ +### *method* `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)}"') +``` +
+ +### *method* `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` +### *method* `self * other: Vector3 => Vector3` + + +
+ ソースコード + +```python +@overload +def __mul__(self, other: 'Vector3') -> 'Vector3': + ... +``` +
+ +### `@overload` +### *method* `self * other: RealNumber => Vector3` + + +
+ ソースコード + +```python +@overload +def __mul__(self, other: RealNumber) -> 'Vector3': + ... +``` +
+ +### *method* `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)}'") +``` +
+ +### *method* `self * other: RealNumber => Vector3` + + +
+ ソースコード + +```python +def __rmul__(self, other: 'RealNumber') -> 'Vector3': + return self.__mul__(other) +``` +
+ +### *method* `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 +``` +
+ +### *method* `self / other: RealNumber => Vector3` + + +
+ ソースコード + +```python +def __truediv__(self, other: RealNumber) -> 'Vector3': + return Vector3(self.x / other, self.y / other, self.z / other) +``` +
+ +### *method* `- self` + + +
+ ソースコード + +```python +def __neg__(self): + return Vector3(-self.x, -self.y, -self.z) +``` +
+ +### ***var*** `zero_vector3 = Vector3(0, 0, 0)` + +- **タイプ**: `Vector3` + +- **説明**: 零向量 + +### ***var*** `x_axis = Vector3(1, 0, 0)` + +- **タイプ**: `Vector3` + +- **説明**: x轴单位向量 + +### ***var*** `y_axis = Vector3(0, 1, 0)` + +- **タイプ**: `Vector3` + +- **説明**: y轴单位向量 + +### ***var*** `z_axis = Vector3(0, 0, 1)` + +- **タイプ**: `Vector3` + +- **説明**: z轴单位向量 + 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..364816d --- /dev/null +++ b/docs/ja/api/presets/model/index.md @@ -0,0 +1,47 @@ +--- +title: mbcp.presets.model +--- +### **class** `GeometricModels` +### `@staticmethod` +### *method* `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/zht/api/index.md b/docs/zht/api/index.md new file mode 100644 index 0000000..6d251e8 --- /dev/null +++ b/docs/zht/api/index.md @@ -0,0 +1,3 @@ +--- +title: mbcp +--- diff --git a/docs/zht/api/mp_math/angle.md b/docs/zht/api/mp_math/angle.md new file mode 100644 index 0000000..5265e64 --- /dev/null +++ b/docs/zht/api/mp_math/angle.md @@ -0,0 +1,423 @@ +--- +title: mbcp.mp_math.angle +--- +### **class** `Angle` +### **class** `AnyAngle(Angle)` +### *method* `__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` +### *method* `complementary(self) -> AnyAngle` + + +余角:两角的和为90°。 + +**返回**: + +- 余角 + + + +
+ 源碼 + +```python +@property +def complementary(self) -> 'AnyAngle': + """ + 余角:两角的和为90°。 + Returns: + 余角 + """ + return AnyAngle(PI / 2 - self.minimum_positive.radian, is_radian=True) +``` +
+ +### `@property` +### *method* `supplementary(self) -> AnyAngle` + + +补角:两角的和为180°。 + +**返回**: + +- 补角 + + + +
+ 源碼 + +```python +@property +def supplementary(self) -> 'AnyAngle': + """ + 补角:两角的和为180°。 + Returns: + 补角 + """ + return AnyAngle(PI - self.minimum_positive.radian, is_radian=True) +``` +
+ +### `@property` +### *method* `degree(self) -> float` + + +角度。 + +**返回**: + +- 弧度 + + + +
+ 源碼 + +```python +@property +def degree(self) -> float: + """ + 角度。 + Returns: + 弧度 + """ + return self.radian * 180 / PI +``` +
+ +### `@property` +### *method* `minimum_positive(self) -> AnyAngle` + + +最小正角。 + +**返回**: + +- 最小正角度 + + + +
+ 源碼 + +```python +@property +def minimum_positive(self) -> 'AnyAngle': + """ + 最小正角。 + Returns: + 最小正角度 + """ + return AnyAngle(self.radian % (2 * PI)) +``` +
+ +### `@property` +### *method* `maximum_negative(self) -> AnyAngle` + + +最大负角。 + +**返回**: + +- 最大负角度 + + + +
+ 源碼 + +```python +@property +def maximum_negative(self) -> 'AnyAngle': + """ + 最大负角。 + Returns: + 最大负角度 + """ + return AnyAngle(-self.radian % (2 * PI), is_radian=True) +``` +
+ +### `@property` +### *method* `sin(self) -> float` + + +正弦值。 + +**返回**: + +- 正弦值 + + + +
+ 源碼 + +```python +@property +def sin(self) -> float: + """ + 正弦值。 + Returns: + 正弦值 + """ + return math.sin(self.radian) +``` +
+ +### `@property` +### *method* `cos(self) -> float` + + +余弦值。 + +**返回**: + +- 余弦值 + + + +
+ 源碼 + +```python +@property +def cos(self) -> float: + """ + 余弦值。 + Returns: + 余弦值 + """ + return math.cos(self.radian) +``` +
+ +### `@property` +### *method* `tan(self) -> float` + + +正切值。 + +**返回**: + +- 正切值 + + + +
+ 源碼 + +```python +@property +def tan(self) -> float: + """ + 正切值。 + Returns: + 正切值 + """ + return math.tan(self.radian) +``` +
+ +### `@property` +### *method* `cot(self) -> float` + + +余切值。 + +**返回**: + +- 余切值 + + + +
+ 源碼 + +```python +@property +def cot(self) -> float: + """ + 余切值。 + Returns: + 余切值 + """ + return 1 / math.tan(self.radian) +``` +
+ +### `@property` +### *method* `sec(self) -> float` + + +正割值。 + +**返回**: + +- 正割值 + + + +
+ 源碼 + +```python +@property +def sec(self) -> float: + """ + 正割值。 + Returns: + 正割值 + """ + return 1 / math.cos(self.radian) +``` +
+ +### `@property` +### *method* `csc(self) -> float` + + +余割值。 + +**返回**: + +- 余割值 + + + +
+ 源碼 + +```python +@property +def csc(self) -> float: + """ + 余割值。 + Returns: + 余割值 + """ + return 1 / math.sin(self.radian) +``` +
+ +### *method* `self + other: AnyAngle => AnyAngle` + + +
+ 源碼 + +```python +def __add__(self, other: 'AnyAngle') -> 'AnyAngle': + return AnyAngle(self.radian + other.radian, is_radian=True) +``` +
+ +### *method* `__eq__(self, other)` + + +
+ 源碼 + +```python +def __eq__(self, other): + return approx(self.radian, other.radian) +``` +
+ +### *method* `self - other: AnyAngle => AnyAngle` + + +
+ 源碼 + +```python +def __sub__(self, other: 'AnyAngle') -> 'AnyAngle': + return AnyAngle(self.radian - other.radian, is_radian=True) +``` +
+ +### *method* `self * other: float => AnyAngle` + + +
+ 源碼 + +```python +def __mul__(self, other: float) -> 'AnyAngle': + return AnyAngle(self.radian * other, is_radian=True) +``` +
+ +### `@overload` +### *method* `self / other: float => AnyAngle` + + +
+ 源碼 + +```python +@overload +def __truediv__(self, other: float) -> 'AnyAngle': + ... +``` +
+ +### `@overload` +### *method* `self / other: AnyAngle => float` + + +
+ 源碼 + +```python +@overload +def __truediv__(self, other: 'AnyAngle') -> float: + ... +``` +
+ +### *method* `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/zht/api/mp_math/const.md b/docs/zht/api/mp_math/const.md new file mode 100644 index 0000000..a94898a --- /dev/null +++ b/docs/zht/api/mp_math/const.md @@ -0,0 +1,3 @@ +--- +title: mbcp.mp_math.const +--- diff --git a/docs/zht/api/mp_math/equation.md b/docs/zht/api/mp_math/equation.md new file mode 100644 index 0000000..f6abbb0 --- /dev/null +++ b/docs/zht/api/mp_math/equation.md @@ -0,0 +1,162 @@ +--- +title: mbcp.mp_math.equation +--- +### *func* `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') +``` +
+ +### *func* `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) +``` +
+ +### *func* `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` +### *method* `__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 +``` +
+ +### *method* `__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))]) +``` +
+ diff --git a/docs/zht/api/mp_math/index.md b/docs/zht/api/mp_math/index.md new file mode 100644 index 0000000..6e3261c --- /dev/null +++ b/docs/zht/api/mp_math/index.md @@ -0,0 +1,3 @@ +--- +title: mbcp.mp_math +--- diff --git a/docs/zht/api/mp_math/line.md b/docs/zht/api/mp_math/line.md new file mode 100644 index 0000000..b33e277 --- /dev/null +++ b/docs/zht/api/mp_math/line.md @@ -0,0 +1,581 @@ +--- +title: mbcp.mp_math.line +--- +### **class** `Line3` +### *method* `__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 +``` +
+ +### *method* `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) +``` +
+ +### *method* `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) +``` +
+ +### *method* `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.') +``` +
+ +### *method* `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 +``` +
+ +### *method* `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)) +``` +
+ +### *method* `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 +``` +
+ +### *method* `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) +``` +
+ +### *method* `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) +``` +
+ +### *method* `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) +``` +
+ +### *method* `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) +``` +
+ +### *method* `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) +``` +
+ +### *method* `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 +``` +
+ +### *method* `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` +### *method* `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) +``` +
+ +### *method* `__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) +``` +
+ +### *method* `__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) +``` +
+ diff --git a/docs/zht/api/mp_math/mp_math_typing.md b/docs/zht/api/mp_math/mp_math_typing.md new file mode 100644 index 0000000..73edd24 --- /dev/null +++ b/docs/zht/api/mp_math/mp_math_typing.md @@ -0,0 +1,63 @@ +--- +title: mbcp.mp_math.mp_math_typing +--- +### ***var*** `RealNumber = int | float` + +- **類型**: `TypeAlias` + +### ***var*** `Number = RealNumber | complex` + +- **類型**: `TypeAlias` + +### ***var*** `Var = SingleVar | ArrayVar` + +- **類型**: `TypeAlias` + +### ***var*** `OneSingleVarFunc = Callable[[SingleVar], SingleVar]` + +- **類型**: `TypeAlias` + +### ***var*** `OneArrayFunc = Callable[[ArrayVar], ArrayVar]` + +- **類型**: `TypeAlias` + +### ***var*** `OneVarFunc = OneSingleVarFunc | OneArrayFunc` + +- **類型**: `TypeAlias` + +### ***var*** `TwoSingleVarsFunc = Callable[[SingleVar, SingleVar], SingleVar]` + +- **類型**: `TypeAlias` + +### ***var*** `TwoArraysFunc = Callable[[ArrayVar, ArrayVar], ArrayVar]` + +- **類型**: `TypeAlias` + +### ***var*** `TwoVarsFunc = TwoSingleVarsFunc | TwoArraysFunc` + +- **類型**: `TypeAlias` + +### ***var*** `ThreeSingleVarsFunc = Callable[[SingleVar, SingleVar, SingleVar], SingleVar]` + +- **類型**: `TypeAlias` + +### ***var*** `ThreeArraysFunc = Callable[[ArrayVar, ArrayVar, ArrayVar], ArrayVar]` + +- **類型**: `TypeAlias` + +### ***var*** `ThreeVarsFunc = ThreeSingleVarsFunc | ThreeArraysFunc` + +- **類型**: `TypeAlias` + +### ***var*** `MultiSingleVarsFunc = Callable[..., SingleVar]` + +- **類型**: `TypeAlias` + +### ***var*** `MultiArraysFunc = Callable[..., ArrayVar]` + +- **類型**: `TypeAlias` + +### ***var*** `MultiVarsFunc = MultiSingleVarsFunc | MultiArraysFunc` + +- **類型**: `TypeAlias` + diff --git a/docs/zht/api/mp_math/plane.md b/docs/zht/api/mp_math/plane.md new file mode 100644 index 0000000..2145db9 --- /dev/null +++ b/docs/zht/api/mp_math/plane.md @@ -0,0 +1,592 @@ +--- +title: mbcp.mp_math.plane +--- +### **class** `Plane3` +### *method* `__init__(self, a: float, b: float, c: float, d: float)` + + +平面方程:ax + by + cz + d = 0 + +**變數説明**: + +- a: x系数 + +- b: y系数 + +- c: z系数 + +- d: 常数项 + + + +
+ 源碼 + +```python +def __init__(self, a: float, b: float, c: float, d: float): + """ + 平面方程:ax + by + cz + d = 0 + Args: + a: x系数 + b: y系数 + c: z系数 + d: 常数项 + """ + self.a = a + self.b = b + self.c = c + self.d = d +``` +
+ +### *method* `approx(self, other: Plane3) -> bool` + + +判断两个平面是否近似相等。 + +**變數説明**: + +- other: 另一个平面 + +**返回**: + +- 是否近似相等 + + + +
+ 源碼 + +```python +def approx(self, other: 'Plane3') -> bool: + """ + 判断两个平面是否近似相等。 + Args: + other: 另一个平面 + Returns: + 是否近似相等 + """ + 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 +``` +
+ +### *method* `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)}') +``` +
+ +### *method* `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)}') +``` +
+ +### *method* `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) +``` +
+ +### *method* `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)) +``` +
+ +### *method* `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) +``` +
+ +### *method* `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` +### *method* `normal(self) -> Vector3` + + +平面的法向量。 + +**返回**: + +- 法向量 + + + +
+ 源碼 + +```python +@property +def normal(self) -> 'Vector3': + """ + 平面的法向量。 + Returns: + 法向量 + """ + return Vector3(self.a, self.b, self.c) +``` +
+ +### `@classmethod` +### *method* `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` +### *method* `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` +### *method* `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` +### *method* `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) +``` +
+ +### `@overload` +### *method* `__and__(self, other: Line3) -> Point3 | None` + + +
+ 源碼 + +```python +@overload +def __and__(self, other: 'Line3') -> 'Point3 | None': + ... +``` +
+ +### `@overload` +### *method* `__and__(self, other: Plane3) -> Line3 | None` + + +
+ 源碼 + +```python +@overload +def __and__(self, other: 'Plane3') -> 'Line3 | None': + ... +``` +
+ +### *method* `__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)}'") +``` +
+ +### *method* `__eq__(self, other) -> bool` + + +
+ 源碼 + +```python +def __eq__(self, other) -> bool: + return self.approx(other) +``` +
+ +### *method* `__rand__(self, other: Line3) -> Point3` + + +
+ 源碼 + +```python +def __rand__(self, other: 'Line3') -> 'Point3': + return self.cal_intersection_point3(other) +``` +
+ diff --git a/docs/zht/api/mp_math/point.md b/docs/zht/api/mp_math/point.md new file mode 100644 index 0000000..2bb381d --- /dev/null +++ b/docs/zht/api/mp_math/point.md @@ -0,0 +1,186 @@ +--- +title: mbcp.mp_math.point +--- +### **class** `Point3` +### *method* `__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 +``` +
+ +### *method* `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]) +``` +
+ +### `@overload` +### *method* `self + other: Vector3 => Point3` + + +
+ 源碼 + +```python +@overload +def __add__(self, other: 'Vector3') -> 'Point3': + ... +``` +
+ +### `@overload` +### *method* `self + other: Point3 => Point3` + + +
+ 源碼 + +```python +@overload +def __add__(self, other: 'Point3') -> 'Point3': + ... +``` +
+ +### *method* `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) +``` +
+ +### *method* `__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) +``` +
+ +### *method* `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/zht/api/mp_math/segment.md b/docs/zht/api/mp_math/segment.md new file mode 100644 index 0000000..c032545 --- /dev/null +++ b/docs/zht/api/mp_math/segment.md @@ -0,0 +1,34 @@ +--- +title: mbcp.mp_math.segment +--- +### **class** `Segment3` +### *method* `__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) +``` +
+ diff --git a/docs/zht/api/mp_math/utils.md b/docs/zht/api/mp_math/utils.md new file mode 100644 index 0000000..96e6eb1 --- /dev/null +++ b/docs/zht/api/mp_math/utils.md @@ -0,0 +1,218 @@ +--- +title: mbcp.mp_math.utils +--- +### *func* `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_) +``` +
+ +### *func* `approx(x: float = 0.0, y: float = APPROX) -> bool` + + +判断两个数是否近似相等。或包装一个实数,用于判断是否近似于0。 + +**變數説明**: + +- x: 数1 + +- y: 数2 + +- epsilon: 误差 + +**返回**: + +- 是否近似相等 + + + +
+ 源碼 + +```python +def approx(x: float, y: float=0.0, epsilon: float=APPROX) -> bool: + """ + 判断两个数是否近似相等。或包装一个实数,用于判断是否近似于0。 + Args: + x: 数1 + y: 数2 + epsilon: 误差 + Returns: + 是否近似相等 + """ + return abs(x - y) < epsilon +``` +
+ +### *func* `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 '' +``` +
+ +### *func* `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` +### *method* `__init__(self, value: RealNumber)` + + +
+ 源碼 + +```python +def __init__(self, value: RealNumber): + self.value = value +``` +
+ +### *method* `__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) +``` +
+ +### *method* `raise_type_error(self, other)` + + +
+ 源碼 + +```python +def raise_type_error(self, other): + raise TypeError(f'Unsupported type: {type(self.value)} and {type(other)}') +``` +
+ +### *method* `__ne__(self, other)` + + +
+ 源碼 + +```python +def __ne__(self, other): + return not self.__eq__(other) +``` +
+ diff --git a/docs/zht/api/mp_math/vector.md b/docs/zht/api/mp_math/vector.md new file mode 100644 index 0000000..327dc51 --- /dev/null +++ b/docs/zht/api/mp_math/vector.md @@ -0,0 +1,690 @@ +--- +title: mbcp.mp_math.vector +--- +### **class** `Vector3` +### *method* `__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 +``` +
+ +### *method* `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]) +``` +
+ +### *method* `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) +``` +
+ +### *method* `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) +``` +
+ +### *method* `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 +``` +
+ +### *method* `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) +``` +
+ +### *method* `normalize(self)` + + +将向量归一化。 + +自体归一化,不返回值。 + + + +
+ 源碼 + +```python +def normalize(self): + """ + 将向量归一化。 + + 自体归一化,不返回值。 + """ + length = self.length + self.x /= length + self.y /= length + self.z /= length +``` +
+ +### `@property` +### *method* `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` +### *method* `length(self) -> float` + + +向量的模。 + +**返回**: + +- 模 + + + +
+ 源碼 + +```python +@property +def length(self) -> float: + """ + 向量的模。 + Returns: + 模 + """ + return math.sqrt(self.x ** 2 + self.y ** 2 + self.z ** 2) +``` +
+ +### `@property` +### *method* `unit(self) -> Vector3` + + +获取该向量的单位向量。 + +**返回**: + +- 单位向量 + + + +
+ 源碼 + +```python +@property +def unit(self) -> 'Vector3': + """ + 获取该向量的单位向量。 + Returns: + 单位向量 + """ + return self / self.length +``` +
+ +### *method* `__abs__(self)` + + +
+ 源碼 + +```python +def __abs__(self): + return self.length +``` +
+ +### `@overload` +### *method* `self + other: Vector3 => Vector3` + + +
+ 源碼 + +```python +@overload +def __add__(self, other: 'Vector3') -> 'Vector3': + ... +``` +
+ +### `@overload` +### *method* `self + other: Point3 => Point3` + + +
+ 源碼 + +```python +@overload +def __add__(self, other: 'Point3') -> 'Point3': + ... +``` +
+ +### *method* `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)}'") +``` +
+ +### *method* `__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) +``` +
+ +### *method* `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` +### *method* `self - other: Vector3 => Vector3` + + +
+ 源碼 + +```python +@overload +def __sub__(self, other: 'Vector3') -> 'Vector3': + ... +``` +
+ +### `@overload` +### *method* `self - other: Point3 => Point3` + + +
+ 源碼 + +```python +@overload +def __sub__(self, other: 'Point3') -> 'Point3': + ... +``` +
+ +### *method* `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)}"') +``` +
+ +### *method* `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` +### *method* `self * other: Vector3 => Vector3` + + +
+ 源碼 + +```python +@overload +def __mul__(self, other: 'Vector3') -> 'Vector3': + ... +``` +
+ +### `@overload` +### *method* `self * other: RealNumber => Vector3` + + +
+ 源碼 + +```python +@overload +def __mul__(self, other: RealNumber) -> 'Vector3': + ... +``` +
+ +### *method* `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)}'") +``` +
+ +### *method* `self * other: RealNumber => Vector3` + + +
+ 源碼 + +```python +def __rmul__(self, other: 'RealNumber') -> 'Vector3': + return self.__mul__(other) +``` +
+ +### *method* `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 +``` +
+ +### *method* `self / other: RealNumber => Vector3` + + +
+ 源碼 + +```python +def __truediv__(self, other: RealNumber) -> 'Vector3': + return Vector3(self.x / other, self.y / other, self.z / other) +``` +
+ +### *method* `- self` + + +
+ 源碼 + +```python +def __neg__(self): + return Vector3(-self.x, -self.y, -self.z) +``` +
+ +### ***var*** `zero_vector3 = Vector3(0, 0, 0)` + +- **類型**: `Vector3` + +- **説明**: 零向量 + +### ***var*** `x_axis = Vector3(1, 0, 0)` + +- **類型**: `Vector3` + +- **説明**: x轴单位向量 + +### ***var*** `y_axis = Vector3(0, 1, 0)` + +- **類型**: `Vector3` + +- **説明**: y轴单位向量 + +### ***var*** `z_axis = Vector3(0, 0, 1)` + +- **類型**: `Vector3` + +- **説明**: z轴单位向量 + diff --git a/docs/zht/api/particle/index.md b/docs/zht/api/particle/index.md new file mode 100644 index 0000000..4b514d5 --- /dev/null +++ b/docs/zht/api/particle/index.md @@ -0,0 +1,3 @@ +--- +title: mbcp.particle +--- diff --git a/docs/zht/api/presets/index.md b/docs/zht/api/presets/index.md new file mode 100644 index 0000000..472366f --- /dev/null +++ b/docs/zht/api/presets/index.md @@ -0,0 +1,3 @@ +--- +title: mbcp.presets +--- diff --git a/docs/zht/api/presets/model/index.md b/docs/zht/api/presets/model/index.md new file mode 100644 index 0000000..e0059b6 --- /dev/null +++ b/docs/zht/api/presets/model/index.md @@ -0,0 +1,47 @@ +--- +title: mbcp.presets.model +--- +### **class** `GeometricModels` +### `@staticmethod` +### *method* `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/__init__.py b/litedoc/__init__.py similarity index 100% rename from liteyuki_autodoc/__init__.py rename to litedoc/__init__.py diff --git a/liteyuki_autodoc/__main__.py b/litedoc/__main__.py similarity index 95% rename from liteyuki_autodoc/__main__.py rename to litedoc/__main__.py index dff40b1..3237c38 100644 --- a/liteyuki_autodoc/__main__.py +++ b/litedoc/__main__.py @@ -18,7 +18,7 @@ import argparse import os import sys -from liteyuki_autodoc.output import generate_from_module +from litedoc.output import generate_from_module def main(): diff --git a/liteyuki_autodoc/docstring/__init__.py b/litedoc/docstring/__init__.py similarity index 100% rename from liteyuki_autodoc/docstring/__init__.py rename to litedoc/docstring/__init__.py diff --git a/liteyuki_autodoc/docstring/docstring.py b/litedoc/docstring/docstring.py similarity index 86% rename from liteyuki_autodoc/docstring/docstring.py rename to litedoc/docstring/docstring.py index de17c8a..241a56f 100644 --- a/liteyuki_autodoc/docstring/docstring.py +++ b/litedoc/docstring/docstring.py @@ -12,7 +12,7 @@ from typing import Optional from pydantic import BaseModel, Field -from liteyuki_autodoc.i18n import get_text +from litedoc.i18n import get_text class Attr(BaseModel): @@ -126,24 +126,24 @@ class Docstring(BaseModel): # print(self.reduction()) # print(self.desc, self.return_) if self.args: - ret += PREFIX + f"{get_text(lang, 'docstring.args')}:\n\n" + ret += PREFIX + f"**{get_text(lang, 'docstring.args')}**:\n\n" for arg in self.args: ret += PREFIX + f"- {arg.name}: {arg.type} {arg.desc}\n\n" if self.attrs: - ret += PREFIX + f"{get_text(lang, 'docstring.attrs')}:\n\n" + ret += PREFIX + f"**{get_text(lang, 'docstring.attrs')}**:\n\n" for attr in self.attrs: ret += PREFIX + f"- {attr.name}: {attr.type} {attr.desc}\n\n" if self.return_ is not None: - ret += PREFIX + f"{get_text(lang, 'docstring.return')}:\n\n" + ret += PREFIX + f"**{get_text(lang, 'docstring.return')}**:\n\n" ret += PREFIX + f"- {self.return_.desc}\n\n" if self.raise_: - ret += PREFIX + f"{get_text(lang, 'docstring.raises')}:\n\n" + ret += PREFIX + f"**{get_text(lang, 'docstring.raises')}**:\n\n" for exception in self.raise_: ret += PREFIX + f"- {exception.name} {exception.desc}\n\n" if self.example: - ret += PREFIX + f"{get_text(lang, 'docstring.example')}:\n\n" + ret += PREFIX + f"**{get_text(lang, 'docstring.example')}**:\n\n" for example in self.example: - ret += PREFIX + f"- {example.desc}\n Input: {example.input}\n Output: {example.output}\n\n" + ret += PREFIX + f"- {example.desc}\n **{get_text(lang, 'docs.input')}**: {example.input}\n **{get_text(lang, 'docs.output')}**: {example.output}\n\n" return ret def __str__(self): diff --git a/liteyuki_autodoc/docstring/parser.py b/litedoc/docstring/parser.py similarity index 85% rename from liteyuki_autodoc/docstring/parser.py rename to litedoc/docstring/parser.py index 52e6b7c..24b7c20 100644 --- a/liteyuki_autodoc/docstring/parser.py +++ b/litedoc/docstring/parser.py @@ -3,7 +3,7 @@ Google docstring parser for Python. """ from typing import Optional -from liteyuki_autodoc.docstring.docstring import Docstring +from litedoc.docstring.docstring import Docstring class Parser: @@ -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/liteyuki_autodoc/i18n.py b/litedoc/i18n.py similarity index 86% rename from liteyuki_autodoc/i18n.py rename to litedoc/i18n.py index 3430a0a..c45aea5 100644 --- a/liteyuki_autodoc/i18n.py +++ b/litedoc/i18n.py @@ -9,7 +9,7 @@ NestedDict: TypeAlias = dict[str, 'str | NestedDict'] i18n_dict: dict[str, NestedDict] = { "en" : { "docstring": { - "args" : "Args", + "args" : "Arguments", "return" : "Return", "attribute": "Attribute", "raises" : "Raises", @@ -17,6 +17,8 @@ i18n_dict: dict[str, NestedDict] = { "yields" : "Yields", }, "src": "Source code", + "desc": "Description", + "type": "Type", }, "zh-Hans": { "docstring": { @@ -27,18 +29,22 @@ i18n_dict: dict[str, NestedDict] = { "example" : "示例", "yields" : "产出", }, - "src": "源码", + "src": "源代码", + "desc": "说明", + "type": "类型", }, "zh-Hant": { "docstring": { - "args" : "參數", + "args" : "變數説明", "return" : "返回", "attribute": "屬性", - "raises" : "引發", - "example" : "示例", + "raises" : "抛出", + "example" : "範例", "yields" : "產出", }, "src": "源碼", + "desc": "説明", + "type": "類型", }, "ja" : { "docstring": { @@ -50,6 +56,8 @@ i18n_dict: dict[str, NestedDict] = { "yields" : "生成", }, "src": "ソースコード", + "desc": "説明", + "type": "タイプ", }, } diff --git a/liteyuki_autodoc/output.py b/litedoc/output.py similarity index 96% rename from liteyuki_autodoc/output.py rename to litedoc/output.py index 0d9a2d5..ddf5750 100644 --- a/liteyuki_autodoc/output.py +++ b/litedoc/output.py @@ -10,8 +10,8 @@ Copyright (C) 2020-2024 LiteyukiStudio. All Rights Reserved """ import os.path -from liteyuki_autodoc.style.markdown import generate -from liteyuki_autodoc.syntax.astparser import AstParser +from litedoc.style.markdown import generate +from litedoc.syntax.astparser import AstParser def write_to_file(content: str, output: str) -> None: diff --git a/liteyuki_autodoc/style/__init__.py b/litedoc/style/__init__.py similarity index 100% rename from liteyuki_autodoc/style/__init__.py rename to litedoc/style/__init__.py diff --git a/liteyuki_autodoc/style/markdown.py b/litedoc/style/markdown.py similarity index 56% rename from liteyuki_autodoc/style/markdown.py rename to litedoc/style/markdown.py index 4f45d52..61ce035 100644 --- a/liteyuki_autodoc/style/markdown.py +++ b/litedoc/style/markdown.py @@ -10,9 +10,9 @@ Copyright (C) 2020-2024 LiteyukiStudio. All Rights Reserved """ from typing import Optional -from liteyuki_autodoc.syntax.astparser import AstParser -from liteyuki_autodoc.syntax.node import * -from liteyuki_autodoc.i18n import get_text +from litedoc.syntax.astparser import AstParser +from litedoc.syntax.node import * +from litedoc.i18n import get_text def generate(parser: AstParser, lang: str, frontmatter: Optional[dict] = None) -> str: @@ -36,24 +36,24 @@ def generate(parser: AstParser, lang: str, frontmatter: Optional[dict] = None) - # var > func > class + """遍历函数""" for func in parser.functions: + if func.name.startswith("_"): + continue md += func.markdown(lang) + """遍历类""" + for cls in parser.classes: - md += f"### ***class*** `{cls.name}`\n\n" - for mtd in cls.methods: - md += mtd.markdown(lang, 2, True) - - for attr in cls.attrs: - if attr.type == TypeHint.NO_TYPEHINT: - md += f"#### ***attr*** `{attr.name} = {attr.value}`\n\n" - else: - md += f"#### ***attr*** `{attr.name}: {attr.type} = {attr.value}`\n\n" + md += cls.markdown(lang) + """遍历变量""" for var in parser.variables: - if var.type == TypeHint.NO_TYPEHINT: - md += f"### ***var*** `{var.name} = {var.value}`\n\n" - else: - md += f"### ***var*** `{var.name}: {var.type} = {var.value}`\n\n" + md += f"### ***var*** `{var.name} = {var.value}`\n\n" + if var.type != TypeHint.NO_TYPEHINT: + md += f"- **{get_text(lang, 'type')}**: `{var.type}`\n\n" + + if var.docs is not None: + md += f"- **{get_text(lang, 'desc')}**: {var.docs}\n\n" return md diff --git a/liteyuki_autodoc/syntax/astparser.py b/litedoc/syntax/astparser.py similarity index 62% rename from liteyuki_autodoc/syntax/astparser.py rename to litedoc/syntax/astparser.py index ae3889b..3007ff1 100644 --- a/liteyuki_autodoc/syntax/astparser.py +++ b/litedoc/syntax/astparser.py @@ -9,11 +9,11 @@ Copyright (C) 2020-2024 LiteyukiStudio. All Rights Reserved @Software: PyCharm """ import ast +import inspect from .node import * from ..docstring.parser import parse - class AstParser: def __init__(self, code: str): self.code = code @@ -25,6 +25,51 @@ class AstParser: self.parse() + @staticmethod + def clear_quotes(s: str) -> str: + """ + 去除类型注解中的引号 + Args: + s: + Returns: + """ + return s.replace("'", "").replace('"', "") + + def get_line_content(self, lineno: int, ignore_index_out: bool = True) -> str: + """获取代码行内容 + Args: + lineno: 行号 + ignore_index_out: 是否忽略索引越界 + Returns: + 代码行内容 + """ + if ignore_index_out: + if lineno < 1 or lineno > len(self.code.split("\n")): + return "" + return self.code.split("\n")[lineno - 1] + + @staticmethod + def match_line_docs(linecontent: str) -> str: + """匹配行内注释 + Args: + linecontent: 行内容 + Returns: + 文档字符串 + """ + in_string = False + string_char = '' + for i, char in enumerate(linecontent): + if char in ('"', "'"): + if in_string: + if char == string_char: + in_string = False + else: + in_string = True + string_char = char + elif char == '#' and not in_string: + return linecontent[i + 1:].strip() + return "" + def parse(self): for node in ast.walk(self.tree): if isinstance(node, ast.ClassDef): @@ -47,21 +92,21 @@ class AstParser: posonlyargs=[ ArgNode( name=arg.arg, - type=ast.unparse(arg.annotation).strip() if arg.annotation else TypeHint.NO_TYPEHINT, + type=self.clear_quotes(ast.unparse(arg.annotation).strip()) if arg.annotation else TypeHint.NO_TYPEHINT, ) for arg in sub_node.args.posonlyargs ], args=[ ArgNode( name=arg.arg, - type=ast.unparse(arg.annotation).strip() if arg.annotation else TypeHint.NO_TYPEHINT, + type=self.clear_quotes(ast.unparse(arg.annotation).strip()) if arg.annotation else TypeHint.NO_TYPEHINT, ) for arg in sub_node.args.args ], kwonlyargs=[ ArgNode( name=arg.arg, - type=ast.unparse(arg.annotation).strip() if arg.annotation else TypeHint.NO_TYPEHINT, + type=self.clear_quotes(ast.unparse(arg.annotation).strip()) if arg.annotation else TypeHint.NO_TYPEHINT, ) for arg in sub_node.args.kwonlyargs ], @@ -77,26 +122,27 @@ class AstParser: ) for default in sub_node.args.defaults ], - return_=ast.unparse(sub_node.returns).strip() if sub_node.returns else TypeHint.NO_RETURN, + return_=self.clear_quotes(ast.unparse(sub_node.returns).strip()) if sub_node.returns else TypeHint.NO_RETURN, decorators=[ast.unparse(decorator).strip() for decorator in sub_node.decorator_list], is_async=isinstance(sub_node, ast.AsyncFunctionDef), - src=ast.unparse(sub_node).strip() + src=ast.unparse(sub_node).strip(), + is_classmethod=True )) - elif isinstance(sub_node, (ast.Assign, ast.AnnAssign)): - if isinstance(sub_node, ast.Assign): - class_node.attrs.append(AttrNode( - name=sub_node.targets[0].id, # type: ignore - type=TypeHint.NO_TYPEHINT, - value=ast.unparse(sub_node.value).strip() - )) - elif isinstance(sub_node, ast.AnnAssign): - class_node.attrs.append(AttrNode( - name=sub_node.target.id, - type=ast.unparse(sub_node.annotation).strip(), - value=ast.unparse(sub_node.value).strip() if sub_node.value else TypeHint.NO_DEFAULT - )) - else: - raise ValueError(f"Unsupported node type: {type(sub_node)}") + # elif isinstance(sub_node, (ast.Assign, ast.AnnAssign)): + # if isinstance(sub_node, ast.Assign): + # class_node.attrs.append(AttrNode( + # name=sub_node.targets[0].id, # type: ignore + # type=TypeHint.NO_TYPEHINT, + # value=ast.unparse(sub_node.value).strip() + # )) + # elif isinstance(sub_node, ast.AnnAssign): + # class_node.attrs.append(AttrNode( + # name=sub_node.target.id, + # type=ast.unparse(sub_node.annotation).strip(), + # value=ast.unparse(sub_node.value).strip() if sub_node.value else TypeHint.NO_DEFAULT + # )) + # else: + # raise ValueError(f"Unsupported node type: {type(sub_node)}") elif isinstance(node, (ast.FunctionDef, ast.AsyncFunctionDef)): # 仅打印模块级别的函数 @@ -109,21 +155,21 @@ class AstParser: posonlyargs=[ ArgNode( name=arg.arg, - type=ast.unparse(arg.annotation).strip() if arg.annotation else TypeHint.NO_TYPEHINT, + type=self.clear_quotes(ast.unparse(arg.annotation).strip()) if arg.annotation else TypeHint.NO_TYPEHINT, ) for arg in node.args.posonlyargs ], args=[ ArgNode( name=arg.arg, - type=ast.unparse(arg.annotation).strip() if arg.annotation else TypeHint.NO_TYPEHINT, + type=self.clear_quotes(ast.unparse(arg.annotation).strip()) if arg.annotation else TypeHint.NO_TYPEHINT, ) for arg, default in zip(node.args.args, node.args.defaults) ], kwonlyargs=[ ArgNode( name=arg.arg, - type=ast.unparse(arg.annotation).strip() if arg.annotation else TypeHint.NO_TYPEHINT, + type=self.clear_quotes(ast.unparse(arg.annotation).strip()) if arg.annotation else TypeHint.NO_TYPEHINT, ) for arg in node.args.kwonlyargs ], @@ -139,7 +185,7 @@ class AstParser: ) for default in node.args.defaults ], - return_=ast.unparse(node.returns).strip() if node.returns else TypeHint.NO_RETURN, + return_=self.clear_quotes(ast.unparse(node.returns).strip()) if node.returns else TypeHint.NO_RETURN, decorators=[ast.unparse(decorator).strip() for decorator in node.decorator_list], is_async=isinstance(node, ast.AsyncFunctionDef), src=ast.unparse(node).strip() @@ -147,23 +193,40 @@ class AstParser: elif isinstance(node, (ast.Assign, ast.AnnAssign)): if not self._is_module_level_variable2(node): - # print("变量不在模块级别", ast.unparse(node)) continue else: pass - if isinstance(node, ast.Assign): - for target in node.targets: - if isinstance(target, ast.Name): - self.variables.append(AssignNode( - name=target.id, - value=ast.unparse(node.value).strip(), - type=ast.unparse(node.annotation).strip() if isinstance(node, ast.AnnAssign) else TypeHint.NO_TYPEHINT - )) - elif isinstance(node, ast.AnnAssign): + lineno = node.lineno + prev_line = self.get_line_content(lineno - 1).strip() + curr_line = self.get_line_content(lineno).strip() + next_line = self.get_line_content(lineno + 1).strip() + + # 获取文档字符串,优先检测下行""" + if next_line.startswith('"""'): + docs = next_line[3:-3] + elif prev_line.startswith('"""'): + docs = prev_line[3:-3] + else: + curr_docs = self.match_line_docs(curr_line) + if curr_docs: + docs = curr_docs + else: + docs = None + + # if isinstance(node, ast.Assign): + # for target in node.targets: + # if isinstance(target, ast.Name): + # self.variables.append(AssignNode( + # name=target.id, + # value=ast.unparse(node.value).strip(), + # type=ast.unparse(node.annotation).strip() if isinstance(node, ast.AnnAssign) else TypeHint.NO_TYPEHINT + # )) + if isinstance(node, ast.AnnAssign): self.variables.append(AssignNode( name=node.target.id, value=ast.unparse(node.value).strip() if node.value else TypeHint.NO_DEFAULT, - type=ast.unparse(node.annotation).strip() + type=ast.unparse(node.annotation).strip(), + docs=docs )) def _is_module_level_function(self, node: ast.FunctionDef | ast.AsyncFunctionDef): diff --git a/liteyuki_autodoc/syntax/node.py b/litedoc/syntax/node.py similarity index 72% rename from liteyuki_autodoc/syntax/node.py rename to litedoc/syntax/node.py index 1a31919..d748928 100644 --- a/liteyuki_autodoc/syntax/node.py +++ b/litedoc/syntax/node.py @@ -13,8 +13,8 @@ from enum import Enum from pydantic import BaseModel, Field -from liteyuki_autodoc.docstring.docstring import Docstring -from liteyuki_autodoc.i18n import get_text +from litedoc.docstring.docstring import Docstring +from litedoc.i18n import get_text class TypeHint: @@ -37,6 +37,7 @@ class AssignNode(BaseModel): name: str type: str = "" value: str + docs: Optional[str] = "" class ArgNode(BaseModel): @@ -123,6 +124,22 @@ class FunctionNode(BaseModel): decorators: list[str] = [] src: str is_async: bool = False + is_classmethod: bool = False + + magic_methods: dict[str, str] = { + "__add__" : "+", + "__radd__" : "+", + "__sub__" : "-", + "__rsub__" : "-", + "__mul__" : "*", + "__rmul__" : "*", + "__matmul__" : "@", + "__rmatmul__": "@", + "__mod__" : "%", + "__truediv__": "/", + "__rtruediv__": "/", + "__neg__" : "-", + } # 魔术方法, 例如运算符 def is_private(self): """ @@ -140,12 +157,11 @@ class FunctionNode(BaseModel): """ return self.name.startswith("__") and self.name.endswith("__") - def markdown(self, lang: str, indent: int = 0, is_classmethod: bool = False) -> str: + def markdown(self, lang: str, indent: int = 0) -> str: """ Args: indent: int The number of spaces to indent the markdown. - is_classmethod: bool lang: str The language of the Returns: @@ -155,21 +171,20 @@ class FunctionNode(BaseModel): PREFIX = "" * indent # if is_classmethod: # PREFIX = "- #" + func_type = "func" if not self.is_classmethod else "method" md = "" - # 装饰器部分 if len(self.decorators) > 0: for decorator in self.decorators: md += PREFIX + f"### `@{decorator}`\n" if self.is_async: - md += PREFIX + "### *async def* " + md += PREFIX + f"### *async {func_type}* " else: - md += PREFIX + "### *def* " - - md += f"`{self.name}(" # code start + md += PREFIX + f"### *{func_type}* " + # code start # 配对位置参数和位置参数默认值,无默认值用TypeHint.NO_DEFAULT args: list[str] = [] # 可直接", ".join(args)得到位置参数部分 arg_i = 0 @@ -204,25 +219,33 @@ class FunctionNode(BaseModel): arg_text = f"{arg.name}" if arg.type != TypeHint.NO_TYPEHINT: arg_text += f": {arg.type}" - if kw_default.value != TypeHint.NO_DEFAULT: arg_text += f" = {kw_default.value}" args.append(arg_text) - md += ", ".join(args) + ")" - - if self.return_ != TypeHint.NO_RETURN: - md += f" -> {self.return_}" + """魔法方法""" + if self.name in self.magic_methods: + if len(args) == 2: + md += f"`{args[0]} {self.magic_methods[self.name]} {args[1]}" + elif len(args) == 1: + md += f"`{self.magic_methods[self.name]} {args[0]}" + if self.return_ != TypeHint.NO_RETURN: + md += f" => {self.return_}" + else: + md += f"`{self.name}(" # code start + md += ", ".join(args) + ")" + if self.return_ != TypeHint.NO_RETURN: + md += f" -> {self.return_}" md += "`\n\n" # code end """此处预留docstring""" if self.docs is not None: - md += f"\n{self.docs.markdown(lang, indent, is_classmethod)}\n" + md += f"\n{self.docs.markdown(lang, indent)}\n" else: pass # 源码展示 - md += PREFIX + f"\n
\n{get_text(lang, 'src')}\n\n```python\n{self.src}\n```\n
\n\n" + md += PREFIX + f"\n
\n {get_text(lang, 'src')} \n\n```python\n{self.src}\n```\n
\n\n" return md @@ -251,11 +274,41 @@ class ClassNode(BaseModel): The attributes of the class. methods: list[MethodNode] = [] The methods of the class. - inherit: list["ClassNode"] = [] + inherits: list["ClassNode"] = [] The classes that the class inherits from """ name: str docs: Optional[Docstring] = None attrs: list[AttrNode] = [] methods: list[FunctionNode] = [] - inherit: list["ClassNode"] = [] + inherits: list[str] = [] + + def markdown(self, lang: str) -> str: + """ + 返回类的markdown文档 + Args: + lang: str + The language of the + Returns: + markdown style document + """ + hidden_methods = [ + "__str__", + "__repr__", + ] + md = "" + md += f"### **class** `{self.name}" + if len(self.inherits) > 0: + md += f"({', '.join([cls for cls in self.inherits])})" + md += "`\n" + for method in self.methods: + if method.name in hidden_methods: + continue + md += method.markdown(lang, 2) + for attr in self.attrs: + if attr.type == TypeHint.NO_TYPEHINT: + md += f"#### ***attr*** `{attr.name} = {attr.value}`\n\n" + else: + md += f"#### ***attr*** `{attr.name}: {attr.type} = {attr.value}`\n\n" + + return md diff --git a/litedoc/translator.py b/litedoc/translator.py new file mode 100644 index 0000000..d9f93e0 --- /dev/null +++ b/litedoc/translator.py @@ -0,0 +1,47 @@ +# -*- coding: utf-8 -*- +""" +Copyright (C) 2020-2024 LiteyukiStudio. All Rights Reserved + +@Time : 2024/8/29 下午12:02 +@Author : snowykami +@Email : snowykami@outlook.com +@File : translator.py +@Software: PyCharm +""" +from typing import Optional + +from translate import Translator # type: ignore + +# 特殊映射语言 +i18n_lang2googletrans_lang = { + "zh-Hans": "zh-cn", + "zh-Hant": "zh-tw", + "en" : "en", +} + + +def get_google_lang(lang: str) -> str: + """ + Get google translate language + Args: + lang: language + Returns: + google translate language + """ + return i18n_lang2googletrans_lang.get(lang, lang) + + +def translate(text: str, lang: str, source_lang: str) -> str: + """ + Translate text to target language + Args: + source_lang: + text: text + lang: target language + Returns: + translated text + """ + if lang == source_lang: + return text + google_lang = get_google_lang(lang) + return Translator(to_lang=google_lang, from_lang=source_lang).translate(text) diff --git a/mbcp/mp_math/plane.py b/mbcp/mp_math/plane.py index 121d31e..992073a 100644 --- a/mbcp/mp_math/plane.py +++ b/mbcp/mp_math/plane.py @@ -22,10 +22,10 @@ class Plane3: """ 平面方程:ax + by + cz + d = 0 Args: - a: - b: - c: - d: + a: x系数 + b: y系数 + c: z系数 + d: 常数项 """ self.a = a self.b = b @@ -36,13 +36,10 @@ class Plane3: """ 判断两个平面是否近似相等。 Args: - other: - + 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) @@ -91,11 +88,11 @@ class Plane3: def cal_intersection_line3(self, other: 'Plane3') -> 'Line3': """ - 计算两平面的交线。该方法有问题,待修复。 + 计算两平面的交线。 Args: other: 另一个平面 Returns: - 交线 + 两平面的交线 Raises: """ if self.normal.is_parallel(other.normal): @@ -105,6 +102,7 @@ class Plane3: x, y, z = 0, 0, 0 # 依次判断条件假设x=0, y=0, 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]) @@ -146,7 +144,7 @@ class Plane3: Args: point: 指定点 Returns: - 平面 + 所求平面 """ return Plane3.from_point_and_normal(point, self.normal) diff --git a/mbcp/mp_math/utils.py b/mbcp/mp_math/utils.py index ae9f85a..630e926 100644 --- a/mbcp/mp_math/utils.py +++ b/mbcp/mp_math/utils.py @@ -22,11 +22,11 @@ if TYPE_CHECKING: def clamp(x: float, min_: float, max_: float) -> float: """ - 区间截断函数。 + 区间限定函数 Args: - x: - min_: - max_: + x: 待限定的值 + min_: 最小值 + max_: 最大值 Returns: 限制后的值 @@ -40,7 +40,6 @@ class Approx: 已实现对象 实数 Vector3 Point3 Plane3 Line3 """ - def __init__(self, value: RealNumber): self.value = value @@ -67,10 +66,9 @@ def approx(x: float, y: float = 0.0, epsilon: float = APPROX) -> bool: """ 判断两个数是否近似相等。或包装一个实数,用于判断是否近似于0。 Args: - x: - y: - epsilon: - + x: 数1 + y: 数2 + epsilon: 误差 Returns: 是否近似相等 """ diff --git a/mbcp/mp_math/vector.py b/mbcp/mp_math/vector.py index b82b732..cfc6df3 100644 --- a/mbcp/mp_math/vector.py +++ b/mbcp/mp_math/vector.py @@ -263,11 +263,11 @@ class Vector3: return f"Vector3({self.x}, {self.y}, {self.z})" -zero_vector3 = Vector3(0, 0, 0) +zero_vector3: Vector3 = Vector3(0, 0, 0) """零向量""" -x_axis = Vector3(1, 0, 0) +x_axis: Vector3 = Vector3(1, 0, 0) """x轴单位向量""" -y_axis = Vector3(0, 1, 0) +y_axis: Vector3 = Vector3(0, 1, 0) """y轴单位向量""" -z_axis = Vector3(0, 0, 1) +z_axis: Vector3 = Vector3(0, 0, 1) """z轴单位向量""" diff --git a/mkdoc.bat b/mkdoc.bat new file mode 100644 index 0000000..e31ccbe --- /dev/null +++ b/mkdoc.bat @@ -0,0 +1,4 @@ +python -m litedoc mbcp -o docs/api -l zh-Hans +python -m litedoc mbcp -o docs/en/api -l en +python -m litedoc mbcp -o docs/ja/api -l ja +python -m litedoc mbcp -o docs/zht/api -l zh-Hant \ No newline at end of file diff --git a/pyproject.toml b/pyproject.toml index ef3a892..07f6ef8 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -21,3 +21,8 @@ build-backend = "pdm.backend" [tool.pdm] distribution = true + +[tool.pdm.dev-dependencies] +dev = [ + "translate>=3.6.1", +] diff --git a/tests/test_doc_translator.py b/tests/test_doc_translator.py new file mode 100644 index 0000000..c647316 --- /dev/null +++ b/tests/test_doc_translator.py @@ -0,0 +1,16 @@ +# -*- coding: utf-8 -*- +""" +Copyright (C) 2020-2024 LiteyukiStudio. All Rights Reserved + +@Time : 2024/8/29 下午12:06 +@Author : snowykami +@Email : snowykami@outlook.com +@File : test_doc_translator.py +@Software: PyCharm +""" + +from litedoc.translator import translate + + +def test(): + print(translate("Hello, world!", "Chinese", "English"))