diff --git a/content/api.json b/content/api.json index c76677e..47a9b37 100644 --- a/content/api.json +++ b/content/api.json @@ -39,8 +39,7 @@ "crates/sim/apsis-scenario/src", "crates/sim/apsis-event/src", "crates/sim/apsis-output/src", - "crates/sim/apsis-sim/src", - "crates/apsis-rs/src" + "crates/sim/apsis-sim/src" ], "crates": [ { @@ -8735,12 +8734,6 @@ "associated": true } ] - }, - { - "name": "apsis-rs", - "layer": null, - "summary": "ApsisRS: computational kernels for commercial spaceflight and satellite internet systems. The workspace is organized into dependency-ordered layers: ```text foundation -> physics -> orbit -> rf -> network -> ops -> sim ``` Dependencies flow in one direction only. A layer may use the layers to its left but never the layers to its right. This crate is the public facade named `apsis-rs`. Downstream projects depend on it directly and enable the feature that matches the layers they need. Each feature re-exports the crates of one layer and pulls in the features of the layers below it. For example, the `orbit` feature enables `physics` and re-exports [`apsis_orbit`], [`apsis_tle`], [`apsis_sgp4`], [`apsis_kepler`], and [`apsis_ephemeris`]. The `full` feature enables every layer, including `sim`. Because `sim` aggregates all other layers and is only needed by simulation workloads, projects that do not run simulations can enable `ops` instead, which enables every layer except `sim`.", - "items": [] } ] } diff --git a/content/api.zh.json b/content/api.zh.json index 566109e..62e9550 100644 --- a/content/api.zh.json +++ b/content/api.zh.json @@ -54,57 +54,57 @@ "Mat3": "按列主序存储的三阶矩阵。\n\n字段名遵循 `m<行><列>` 约定,因此 `m01` 是第一行第二列的元。字段按列主序列出,[`Mat3::from_columns`] 与 [`Mat3::column`] 也使用同一顺序。", "Mat3::ZERO": "零矩阵。", "Mat3::IDENTITY": "单位矩阵。", - "Mat3::from_rows": "按行主序由九个元创建矩阵。\n\n参数按行分组:先是 `row0`,然后是 `row1`,最后是 `row2`。", - "Mat3::from_columns": "由三个列矢量创建矩阵。", - "Mat3::from_diagonal": "由对角元矢量创建对角矩阵。", - "Mat3::from_quat": "由单位四元数创建旋转矩阵。\n\n假定四元数长度为 1。非单位四元数会产生带缩放的矩阵,[`Mat3::is_rotation`] 会拒绝该结果。", - "Mat3::from_axis_angle": "创建绕单位轴 `axis` 旋转 `angle` 弧度的旋转矩阵。\n\n当轴的长度为零或非有限时返回 `None`。", + "Mat3::from_rows": "由九个元素按行优先顺序创建一个矩阵。\n\n参数按行分组:先是 `row0`,然后是 `row1`,最后是 `row2`。", + "Mat3::from_columns": "由三个列向量创建一个矩阵。", + "Mat3::from_diagonal": "由对角元素的向量创建一个对角矩阵。", + "Mat3::from_quat": "由单位四元数创建一个旋转矩阵。\n\n假定该四元数长度为 1。非单位四元数会产生一个带缩放的矩阵,……", + "Mat3::from_axis_angle": "创建绕单位轴 `axis` 旋转 `angle` 弧度的旋转矩阵。\n\n当该轴长度为零或非有限时返回 `None`。", "Mat3::from_rotation_x": "创建绕第一轴旋转 `angle` 弧度的旋转矩阵。", "Mat3::from_rotation_y": "创建绕第二轴旋转 `angle` 弧度的旋转矩阵。", "Mat3::from_rotation_z": "创建绕第三轴旋转 `angle` 弧度的旋转矩阵。", - "Mat3::get": "返回第 `row` 行第 `column` 列的元。\n\n当任一下标超出 `0..=2` 时返回 `None`。", - "Mat3::column": "返回第 `index` 列。\n\n当 `index` 超出 `0..=2` 时返回 `None`。", - "Mat3::row": "返回第 `index` 行。\n\n当 `index` 超出 `0..=2` 时返回 `None`。", + "Mat3::get": "返回第 `row` 行第 `column` 列的元素。\n\n当任一索引落在 `0..=2` 之外时返回 `None`。", + "Mat3::column": "返回第 `index` 列。\n\n当 `index` 落在 `0..=2` 之外时返回 `None`。", + "Mat3::row": "返回第 `index` 行。\n\n当 `index` 落在 `0..=2` 之外时返回 `None`。", "Mat3::transpose": "返回转置。", - "Mat3::trace": "返回对角元之和。", + "Mat3::trace": "返回对角元素之和。", "Mat3::determinant": "返回行列式。", - "Mat3::is_rotation": "当本矩阵在 `tolerance` 内是旋转时返回 `true`。\n\n矩阵是旋转当且仅当它是正交的且行列式为 1。该检查逐元比较 `M^T M` 与单位矩阵,再比较行列式与 1。", - "Mat3::is_finite": "当九个元都是有限值时返回 `true`。", + "Mat3::is_rotation": "当该矩阵在 `tolerance` 范围内是一个旋转时返回 `true`。\n\n当矩阵正交且行列式为一时,它是一个旋转。该检查……", + "Mat3::is_finite": "当九个元素都有限时返回 `true`。", "Quat": "四元数 `w + xi + yj + zk`。\n\n旋转矢量的方法假定四元数长度为 1。乘法与加法不作此假定,因为任意四元数运算在该假定之外仍有定义。用 [`Quat::normalize`] 施加单位长度,用 [`Quat::is_normalized`] 检查它。\n\n绕单位轴 `u` 旋转角度 `theta` 的旋转为 `w = cos(theta / 2)`,`(x, y, z) = u * sin(theta / 2)`。复合约定与矩阵乘法相同:`(a * b)` 作用于矢量时先施加 `b`,再施加 `a`。", "Quat::IDENTITY": "单位旋转。", - "Quat::new": "由四个分量创建四元数。", - "Quat::from_mat3": "由旋转矩阵 `m` 创建四元数。\n\n算法选取最大的对角元作为除数,使平方根对任意输入旋转都良态。当 `m` 不是旋转矩阵时——即在 `1e-9` 容差内不正交或行列式不为 1——返回 `None`。", - "Quat::vector": "返回矢量部分 `(x, y, z)`。", - "Quat::norm_squared": "返回本四元数长度的平方。", - "Quat::norm": "返回本四元数的长度。", - "Quat::normalize": "返回缩放至单位长度的本四元数。\n\n当长度为零或非有限时返回 `None`。", - "Quat::conjugate": "返回共轭 `w - xi - yj - zk`。\n\n对单位四元数而言这就是逆旋转。", + "Quat::new": "由四个分量创建一个四元数。", + "Quat::from_mat3": "由旋转矩阵 `m` 创建一个四元数。\n\n该算法挑选对角线上最大的元素作除数,从而使平方根保持良态……", + "Quat::vector": "返回向量部分 `(x, y, z)`。", + "Quat::norm_squared": "返回这个四元数长度的平方。", + "Quat::norm": "返回这个四元数的长度。", + "Quat::normalize": "返回缩放到单位长度的这个四元数。\n\n当长度为零或非有限时返回 `None`。", + "Quat::conjugate": "返回共轭 `w - xi - yj - zk`。\n\n对单位四元数它就是逆旋转。", "Quat::inverse": "返回逆旋转。\n\n当长度为零或非有限时返回 `None`。", - "Quat::dot": "返回 `self` 与 `rhs` 的点积,二者都视为四分量矢量。", - "Quat::rotate": "用本旋转旋转 `v`。\n\n假定本四元数长度为 1。旋转按 `v + 2 * cross(vector, cross(vector, v) + w * v)` 计算,避免两次构造四元数乘积矩阵。", - "Quat::angle": "返回旋转角,单位为弧度,位于 `[0, pi]`。\n\n假定本四元数长度为 1。", - "Quat::axis": "返回作为单位矢量的旋转轴。\n\n对单位旋转返回 `None`,因为此时没有定义轴。假定本四元数长度为 1。", - "Quat::lerp": "返回从 `self` 到 `rhs` 的线性插值。\n\n这是弦插值,因此结果不是单位四元数,角速度也不恒定。需要中间旋转均匀时请使用 [`Quat::slerp`]。", - "Quat::slerp": "返回从 `self` 到 `rhs` 的球面线性插值。\n\n取两条弧中较短的一条,因此结果沿保持角度最小的路径。当输入近乎平行时退化为 [`Quat::lerp`],否则分母中的正弦会损失精度。", - "Quat::is_normalized": "当长度在 `1e-9` 容差内为 1 时返回 `true`。", - "Quat::quarter_turn_x": "返回绕第一轴四分之一圈的旋转。", - "Quat::half_turn_z": "返回绕第三轴半圈的旋转。", + "Quat::dot": "返回 `self` 与 `rhs` 的点积,把两者都当作四维向量。", + "Quat::rotate": "用这个旋转旋转 `v`。\n\n假定该四元数长度为 1。旋转按 `v + 2 * cross(vector, cross(vector, v) + w * v)` 计算,……", + "Quat::angle": "返回以弧度计的旋转角,落在 `[0, pi]`。\n\n假定该四元数长度为 1。", + "Quat::axis": "以单位向量返回旋转轴。\n\n对单位旋转返回 `None`,因为那里没有定义旋转轴。假定该四元数长度为 1,……", + "Quat::lerp": "返回从 `self` 到 `rhs` 的线性插值。\n\n这是弦插值,因此结果不是单位四元数,角速度也……", + "Quat::slerp": "返回从 `self` 到 `rhs` 的球面线性插值。\n\n取两段弧中较短的一段,因此结果沿着旋转所……", + "Quat::is_normalized": "当长度在 `1e-9` 的容差内为一时返回 `true`。", + "Quat::quarter_turn_x": "返回绕第一轴四分之一周的旋转。", + "Quat::half_turn_z": "返回绕第三轴半周的旋转。", "Vec3": "三分量列矢量。\n\n分量名为 `x`、`y`、`z`。此处不赋予它们含义;参考系由使用该矢量的 crate 定义。", - "Vec3::ZERO": "零矢量。", - "Vec3::X": "沿第一轴的单位矢量。", - "Vec3::Y": "沿第二轴的单位矢量。", - "Vec3::Z": "沿第三轴的单位矢量。", - "Vec3::new": "由三个分量创建矢量。", - "Vec3::splat": "创建三个分量都等于 `value` 的矢量。", - "Vec3::x": "返回第一个分量。", - "Vec3::y": "返回第二个分量。", - "Vec3::z": "返回第三个分量。", - "Vec3::get": "返回由 `index` 选中的分量,其中 `0`、`1`、`2` 分别选中 `x`、`y`、`z`。\n\n下标超出 `0..=2` 时返回 `None`。", - "Vec3::cross": "返回叉积 `self x rhs`。\n\n结果与两个输入都垂直并遵循右手定则,因此 `Vec3::X.cross(Vec3::Y)` 等于 `Vec3::Z`。", + "Vec3::ZERO": "零向量。", + "Vec3::X": "沿第一轴的单位向量。", + "Vec3::Y": "沿第二轴的单位向量。", + "Vec3::Z": "沿第三轴的单位向量。", + "Vec3::new": "由三个分量创建一个向量。", + "Vec3::splat": "创建一个三个分量都等于 `value` 的向量。", + "Vec3::x": "返回第一分量。", + "Vec3::y": "返回第二分量。", + "Vec3::z": "返回第三分量。", + "Vec3::get": "返回由 `index` 选出的分量,其中 `0`、`1`、`2` 分别对应 `x`、`y`、`z`。\n\n当索引落在 `0..=2` 之外时返回 `None`……", + "Vec3::cross": "返回叉积 `self x rhs`。\n\n结果同时垂直于两个输入并遵循右手定则,因此 `Vec3::X.cross(Vec3::Y)` 等于……", "Vec3::distance": "返回 `self` 与 `rhs` 之间的欧氏距离。", "Vec3::distance_squared": "返回 `self` 与 `rhs` 之间欧氏距离的平方。", - "Vec3::angle_between": "返回 `self` 与 `rhs` 之间的夹角,单位为弧度。\n\n结果位于 `[0, pi]`。当任一矢量长度为零或非有限,或任一分量非有限时返回 `None`。", - "Vec3::abs": "返回各分量取绝对值后的矢量。", + "Vec3::angle_between": "以弧度返回 `self` 与 `rhs` 之间的夹角。\n\n结果落在 `[0, pi]`。当任一向量长度为零或非有限时返回 `None`……", + "Vec3::abs": "返回一个向量,其每个分量都被替换为其绝对值。", "Vec3::max_component": "返回最大的分量。", "Vec3::min_component": "返回最小的分量。", "Radians": "以弧度表示的角度。", @@ -177,45 +177,45 @@ "Eci::to_ecef": "在给定地球自转角下,把本惯性系位置转换到地固系。", "Ecef::to_eci": "在给定地球自转角下,把本地固系位置转换到惯性系。", "Ecef::to_geodetic": "把本地固系位置转换为给定椭球面上的纬度、经度与高。\n\n当位置位于极轴上时返回 `None`,因为此时经度无定义。", - "Geodetic::new": "由纬度、经度与高创建大地坐标位置。", + "Geodetic::new": "由纬度、经度和高度创建一个大地位置。\n\n纬度与经度以弧度为单位,高度以米为单位。", "Geodetic::latitude": "以弧度返回大地纬度。", - "Geodetic::longitude": "以弧度返回经度,向东为正。", - "Geodetic::height": "以米返回椭球面以上的高。", - "Geodetic::ellipsoidal": "返回底层的大地坐标位置。", - "Geodetic::to_ecef": "把本位置转换到 WGS 84 椭球上的地固系。\n\n这是常见情形。需要其他椭球时请使用 [`Geodetic::to_ecef_on`]。", - "Geodetic::to_ecef_on": "把本位置转换到给定椭球上的地固系。", + "Geodetic::longitude": "以弧度返回经度,以东为正。", + "Geodetic::height": "以米返回该椭球之上的高度。", + "Geodetic::ellipsoidal": "返回底层的椭球位置。", + "Geodetic::to_ecef": "在 WGS 84 椭球上把这个位置转换为地固系。\n\n这是常见情形。换用其他椭球时请用 [`Geodetic::to_ecef_on`]。", + "Geodetic::to_ecef_on": "在给定椭球上把这个位置转换为地固系。", "Geodetic": "大地坐标位置:椭球面上的纬度、经度与高。\n\n纬度与经度单位为弧度,高单位为米。纬度是大地纬度,即椭球法线与赤道面之间的夹角,位于 `[-pi/2, pi/2]`。经度自本初子午线向东量取。高是沿椭球法线的距离,椭球面之外为正。", "Ellipsoid": "双轴参考椭球:绕短半轴的旋转椭圆。\n\n形状由两个数确定。本 crate 存储长半轴与扁率倒数,即标准中 WGS 84 椭球的两个定义参数。其余所有量都是导出的,因此不存在参数之间互相矛盾的风险。\n\n长度单位为米,角度单位为弧度。", - "Ellipsoid::new": "由长半轴与扁率倒数创建椭球。\n\n长度单位为米。扁率倒数必须为正且有限;无穷大描述球体。", - "Ellipsoid::semi_major_axis": "以米返回长半轴。", - "Ellipsoid::inverse_flattening": "返回扁率倒数。", - "Ellipsoid::flattening": "返回扁率。\n\n对球体该值为零。", - "Ellipsoid::semi_minor_axis": "以米返回短半轴。", - "Ellipsoid::eccentricity_squared": "返回第一偏心率平方,即 `[0, 1)` 内的无量纲数。\n\n对扁率 `f`,它是 `2f - f^2`。", - "Ellipsoid::eccentricity": "返回第一偏心率,即 `[0, 1)` 内的无量纲数。", - "Ellipsoid::second_eccentricity_squared": "返回第二偏心率平方,无量纲。\n\n它是 `e^2 / (1 - e^2)`,出现在把大地坐标转换为直角坐标的闭式中。", - "Ellipsoid::polar_radius_of_curvature": "以米返回极曲率半径。\n\n这是极点处子午圈内的曲率半径,等于 `a / sqrt(1 - e^2)`。", - "Ellipsoid::prime_vertical_radius": "以米返回给定大地纬度处的卯酉圈曲率半径。\n\n这是沿椭球法线从表面到自转轴的距离,从赤道处的长半轴增至极点处的 [`Ellipsoid::polar_radius_of_curvature`]。\n\n纬度单位为弧度。", - "Ellipsoid::meridian_radius": "以米返回给定大地纬度处的子午圈曲率半径。\n\n纬度单位为弧度。", + "Ellipsoid::new": "由半长轴和倒数扁率创建一个椭球。\n\n长度以米为单位。倒数扁率必须为正且有限;取无穷大则描述一个球。", + "Ellipsoid::semi_major_axis": "以米返回半长轴。", + "Ellipsoid::inverse_flattening": "返回倒数扁率。", + "Ellipsoid::flattening": "返回扁率。\n\n对球体为零。", + "Ellipsoid::semi_minor_axis": "以米返回半短轴。", + "Ellipsoid::eccentricity_squared": "返回第一偏心率平方,一个落在 `[0, 1)` 的无量纲数。\n\n对扁率 `f` 它等于 `2f - f^2`。", + "Ellipsoid::eccentricity": "返回第一偏心率,一个落在 `[0, 1)` 的无量纲数。", + "Ellipsoid::second_eccentricity_squared": "返回第二偏心率平方,一个无量纲数。\n\n它等于 `e^2 / (1 - e^2)`,出现在把大地位置转换为直角坐标的闭式解中。", + "Ellipsoid::polar_radius_of_curvature": "以米返回极曲率半径。\n\n这是子午圈内在极点处的曲率半径,等于 `a / sqrt(1 - e^2)`。", + "Ellipsoid::prime_vertical_radius": "以米返回给定大地纬度处卯酉圈内的曲率半径。\n\n这是沿椭球法线量得的、从地表到极轴的距离;它从赤道处的半长轴增长到极点处的 [`Ellipsoid::polar_radius_of_curvature`]。\n\n纬度以弧度为单位。", + "Ellipsoid::meridian_radius": "以米返回给定大地纬度处子午圈内的曲率半径。\n\n纬度以弧度为单位。", "Ellipsoid::geocentric_latitude": "以弧度返回与给定大地纬度对应的地心纬度。\n\n地心纬度自赤道面量到矢径,而大地纬度量到椭球法线。离开赤道与两极时,地心纬度是两者中较小的那个。", "WGS84": "WGS 84 参考椭球。\n\n两个定义参数是长半轴 `a = 6 378 137 m` 与扁率倒数 `1 / f = 298.257 223 563`。\n\n来源:NIMA TR8350.2,第三版,2000。", "WGS84_GRAVITATIONAL_PARAMETER": "WGS 84 的地球引力参数,单位为立方米每二次方秒。\n\n它放在这里而不是 `apsis-core`,是为了让使用该椭球的调用方能配上相应的引力场。该值为 `3.986 004 418e14 m^3/s^2`。", - "Geodetic::to_cartesian": "把本大地坐标位置转换为给定椭球上的地固系直角坐标。\n\n该系的第三轴沿椭球短半轴穿过北极,第一轴穿过赤道与本初子午线的交点,第二轴构成右手系。结果单位为米。\n\n闭式为\n\n```text\nN = a / sqrt(1 - e^2 sin^2(lat))\nx = (N + h) cos(lat) cos(lon)\ny = (N + h) cos(lat) sin(lon)\nz = (N (1 - e^2) + h) sin(lat)\n```\n\n其中 `N` 是卯酉圈曲率半径。该形式处处精确,包括两极,因为两处的余弦因子为零。", - "Geodetic::is_valid": "当每个字段都是有限值且纬度与经度在各自范围内时返回 `true`。", + "Geodetic::to_cartesian": "把这个大地位置转换为给定椭球上的地固直角坐标。\n\n该坐标系的第三轴沿穿过北极的椭球短轴,第一轴穿过赤道与本初子午线的交点,第二轴凑成右手系。结果以米为单位。\n\n闭式解为\n\n```text\nN = a / sqrt(1 - e^2 sin^2(lat))\nx = (N + h) cos(lat) cos(lon)\ny = (N + h) cos(lat) sin(lon)\nz = (N (1 - e^2) + h) sin(lat)\n```\n\n其中 `N` 是卯酉圈曲率半径。这个形式处处精确,包括在极点处——那里余弦因子为零。", + "Geodetic::is_valid": "当每个字段都有限、且纬度与经度都在各自范围内时返回 `true`。", "cartesian_from_geodetic": "把大地坐标位置转换为地固系直角坐标。\n\n坐标系定义与闭式见 [`Geodetic::to_cartesian`]。", "geodetic_from_cartesian": "把地固系直角坐标转换为大地坐标位置。\n\n纬度与高由 Bowring 方法求得:闭式求解子午线方程,再用若干固定点迭代修正结果。对从椭球面以下到地球静止轨道半径的位置,迭代收敛到远优于一微米。\n\n当位置非有限,或位于极轴上以致经度无定义时返回 `None`。", "ERA_J2000_TURNS": "J2000.0 历元处的地球自转角,单位为圈。\n\n按该角的定义,历元值为零:国际天文学联合会把地球自转角定义为自 J2000.0 起 UT1 天数的线性函数,因此历元处的常数项属于该定义的另一部分。", "ERA_RATE_TURNS_PER_DAY": "地球自转角的变化率,单位为圈每 UT1 日。\n\n该值为 `1.002 737 811 911 354 6`,即每天 `360.985 612 288 088` 度。它超过每天一圈,因为地球在一个恒星日内转一圈,而恒星日短于太阳日。", "ut1_days_from_j2000": "自 J2000.0 历元到给定 UT1 尺度儒略日的天数。\n\nJ2000.0 历元是儒略日 2451545.0,即 2000-01-01 的正午。", "EarthRotationAngle": "给定时刻的地球自转角。\n\n该角是自天体中间原点绕天极量到地球中间原点的旋转。在实践中它就是惯性系与地固系之间的夹角。\n\n该角不归约到一圈之内,因此即使区间超过一天,两个角之差仍有意义。", - "EarthRotationAngle::from_turns": "由圈值创建角度。", - "EarthRotationAngle::from_radians": "由弧度值创建角度。", - "EarthRotationAngle::from_ut1_julian_date": "返回 UT1 尺度上给定儒略日处的角度。", - "EarthRotationAngle::from_ut1_days": "返回自 J2000.0 历元起给定 UT1 天数处的角度。\n\n表达式是线性的:`theta = 0.779 057 273 2640 + 1.002 737 909 350 795 * d`,其中 `d` 是区间天数。常数项 `0.779 057` 圈是历元时刻的角,约 280.46 度。", - "EarthRotationAngle::turns": "以圈返回该角。\n\n该值不归约到 `[0, 1)`。", - "EarthRotationAngle::turns_positive": "以圈返回该角,归约到 `[0, 1)`。", - "EarthRotationAngle::radians": "以弧度返回该角。\n\n该值不归约到 `[0, 2 pi)`。", - "EarthRotationAngle::radians_positive": "以弧度返回该角,归约到 `[0, 2 pi)`。", + "EarthRotationAngle::from_turns": "由以周为单位的值创建一个角度。", + "EarthRotationAngle::from_radians": "由以弧度为单位的值创建一个角度。", + "EarthRotationAngle::from_ut1_julian_date": "返回 UT1 尺度上某个儒略日对应的角度。", + "EarthRotationAngle::from_ut1_days": "返回自 J2000.0 历元以来若干 UT1 日数对应的角度。\n\n该表达式是线性的:`theta = 0.779 057 273 2640 + 1.002 737 909 350 795 * d`,其中 `d` 是以日计的间隔。常数项 `0.779 057` 周就是历元本身的角度,约为 280.46 度。\n\n来源:IERS Conventions (2010),公式 8.32。", + "EarthRotationAngle::turns": "以周返回该角度。\n\n该值未被化归到 `[0, 1)`。", + "EarthRotationAngle::turns_positive": "以周返回该角度,化归到 `[0, 1)`。", + "EarthRotationAngle::radians": "以弧度返回该角度。\n\n该值未被化归到 `[0, 2 pi)`。", + "EarthRotationAngle::radians_positive": "以弧度返回该角度,化归到 `[0, 2 pi)`。", "rotation_eci_to_ecef": "返回把惯性系矢量映射到地固系的旋转。\n\n该旋转是绕第三轴按地球自转角顺时针转动。把它作用于惯性系矢量得到地固系矢量,因此固定在惯性空间的矢量会随着地球在其下方转动而获得一个负向旋转。", "rotation_ecef_to_eci": "返回把地固系矢量映射到惯性系的旋转。\n\n这是 [`rotation_eci_to_ecef`] 的转置,对旋转矩阵而言也就是它的逆。", "mean_anomaly_moon": "以弧度返回月球的平近点角。\n\n这是 IERS 2003 表达式中的 Delaunay 参数 `l`。", @@ -243,9 +243,9 @@ "ComplementaryTerm": "春分点方程补充项的一项。\n\n八个乘数作用于参数 `l`、`l'`、`F`、`D`、`Om`、金星的平黄经、地球的平黄经与总累积岁差。", "PlanetaryTerm": "行星章动级数的一项。\n\n十三个乘数按 `l`、`F`、`D`、`Om`、水星至天王星、海王星与总累积岁差的顺序作用于行星参数。", "Nutation": "以弧度表示的黄经章动与交角章动。", - "Nutation::new": "由两个角创建章动。", - "Nutation::longitude_arcseconds": "以角秒返回黄经章动。", - "Nutation::obliquity_arcseconds": "以角秒返回交角章动。", + "Nutation::new": "由两个角度创建一个章动。", + "Nutation::longitude_arcseconds": "以角秒返回经度方向的章动。", + "Nutation::obliquity_arcseconds": "以角秒返回黄经交角方向的章动。", "Nutation::plus": "返回两个章动之和。", "nutation_2000a": "返回给定时刻的黄经章动与交角章动。\n\n时间是以地球时尺度表示的、自 J2000.0 起的儒略世纪数。这是 IAU 2000A 模型,包含完整的日月与行星级数。", "nutation_2000a_with_2006_adjustment": "返回施加 IAU 2006 岁差调整后的章动。\n\nIAU 2000A 模型建立在 IAU 1976 岁差之上,而 IAU 2006 岁差改变了岁差量的表示,因此需要一个小调整以保持两个模型相互一致。", @@ -265,10 +265,10 @@ "equation_of_the_equinoxes_complementary_terms": "返回春分点方程的补充项。\n\n春分点方程除了黄经章动在真赤道上的投影之外,还有一组补充项,这部分由该函数给出。", "equation_of_the_equinoxes": "返回给定时刻的春分点方程。\n\n春分点方程是沿真赤道量取的真春分点与平春分点之差。它就把平恒星时转换为视恒星时的那个量。", "PolarMotion": "地球的极移,以两个角与相应旋转表示。\n\n极移是自转轴在地球内部的运动。国际地球自转与参考系统服务每日测量并发布它。它小于 0.5 角秒,约合地面 15 米,对大多数用途可忽略;本工作区保留它,以便需要时能够施加。", - "PolarMotion::NONE": "零极移,即在无法获得已发布数值时所用的近似。\n\n忽略极移带来的误差小于十分之一角秒,远低于这些内核所针对的定位精度。", - "PolarMotion::new": "由三个角创建极移。", - "PolarMotion::is_valid": "当各角可用时返回 `true`。", - "PolarMotion::matrix": "返回极移的旋转矩阵。\n\n该旋转先绕第三轴旋转定位角,再绕第二轴旋转负的 `x` 位移,最后绕第一轴旋转 `y` 位移。", + "PolarMotion::NONE": "零极移,它是在拿不到公布值时所用的近似。\n\n略去极移带来的误差小于十分之一角秒,远低于章动,但高于现代变换的精度。", + "PolarMotion::new": "由三个角度创建一个极移。", + "PolarMotion::is_valid": "当这些角度可用时返回 `true`。", + "PolarMotion::matrix": "返回该极移的旋转矩阵。\n\n该旋转先绕第三轴按定位量转,再绕第二轴按 `x` 位移的相反数转,最后绕第一轴按 `y` 位移的相反数转。所用的符号与参考实现一致,它们把地球参考系对齐到天极。\n\n来源:按 `eraPom00` 的实现方式,它把每次旋转依次复合到累加器的左侧。", "intermediate_to_terrestrial_matrix": "返回给定时刻的中间系到地固系矩阵。\n\n中间系是当日真赤道真春分点,地固系是该时刻的地固系。两者之差是地球自转与极移。", "greenwich_apparent_sidereal_time": "返回给定 UT1 与 TT 儒略日的格林尼治视恒星时。\n\n它是平恒星时加上春分点方程,因此是真春分点的时角。", "greenwich_mean_sidereal_time": "返回给定 UT1 与 TT 儒略日的格林尼治平恒星时。\n\n该关系是地球自转角加上赤经中的累积岁差,后者即平春分点相对天体中间原点的旋转量。", @@ -291,10 +291,10 @@ "ElementError::detail": "返回附在本错误上的详情文本,若有。", "PropagationErrorKind": "传播失败的类别。", "PropagationError": "初始化或传播卫星时的失败。", - "PropagationError::new": "由给定类别创建错误。", - "PropagationError::with_detail": "附上导致失败的数值的描述。", - "PropagationError::kind": "返回本失败的类别。", - "PropagationError::detail": "返回附在本错误上的详情文本,若有。", + "PropagationError::new": "以给定类别创建一个错误。", + "PropagationError::with_detail": "附上对导致失败的值的描述。", + "PropagationError::kind": "返回这次失败的类别。", + "PropagationError::detail": "返回附在这个错误上的细节文本,若有。", "Elements": "以传播器所用单位表示的卫星元素。\n\n角度单位为弧度,平均运动单位为弧度每分钟。辅助函数把 [`TwoLineElement`] 转换为这种形式。", "Elements::from_tle": "把已解析的元素集转换为传播器所用的单位。\n\n历元取为元素集中原样书写的 UTC 约化儒略日。元素集历元是一个 UTC 日历时刻,但传播器把它当作均匀的时间原点,这正是理论拟合时所用的约定。先把它转换为均匀尺度会因闰秒偏移而使历元移动约 33 秒,而该移动会传入深空分支的日月级数。", "Elements::unkozai_mean_motion": "施加 Kozai 到 Brouwer 平均运动的改正。\n\n元素集中的平均运动是 Kozai 平均运动,理论在使用前必须把它转换为 Brouwer 平均运动。这里以求值所用的形式写作不动点迭代,因为 `a` 通过开普勒第三定律依赖于 `n0`。对元素集中出现的每一条轨道,迭代都从改正前的平均运动出发在若干步内收敛。\n\n来源:Vallado 等,*Revisiting Spacetrack Report #3*,AIAA 2006-6753,2006。", @@ -303,22 +303,22 @@ "GravityModel": "引力模型:传播器使用的地球常数。", "GravityModel::WGS72": "WGS 72 引力模型。\n\n这是 SGP4 理论所拟合的模型,也是与标准元素集匹配的模型。", "GravityModel::WGS84": "WGS 84 引力模型。\n\n仅在元素集是针对 WGS 84 拟合时使用。", - "GravityModel::reciprocal_sqrt_mu": "返回引力参数平方根的倒数,单位为秒每千米的二分之三次方。", - "GravityModel::sqrt_mu": "返回引力参数的平方根,单位为千米的二分之三次方每秒。", - "GravityModel::xke": "返回 `xke`,即开普勒常数,单位为 `er^1.5 / min`。\n\n传播器以分钟与地球半径为单位工作,因此引力参数按\n\n```text\nxke = 60 / sqrt(radius^3 / mu)\n```\n\n换算,即半径为一个地球半径的圆轨道的角速率,单位为弧度每分钟。", - "GravityModel::tumin": "以分钟返回 `xke` 的倒数。\n\n这是模型的时间单位:参考圆轨道的周期除以二π。", - "GravityModel::j3_over_j2": "返回 `j3 / j2`,它在理论中作为一个比值出现。", - "GravityModel::x2o3": "返回 `2 * xke^2`,该项出现在平均运动改正中。", + "GravityModel::reciprocal_sqrt_mu": "返回引力参数平方根的倒数,单位为秒每千米的分之三次方。", + "GravityModel::sqrt_mu": "返回引力参数的平方根,单位为千米的分之三次方每秒。", + "GravityModel::xke": "返回 `xke`,即开普勒常数,单位为 `er^1.5 / min`。\n\n传播器以分钟和地球半径为单位工作,因此引力参数按\n\n```text\nxke = 60 / sqrt(radius^3 / mu)\n```\n\n换算,它是一个地球半径半径的圆轨道每分钟的角速率,单位为弧度每分钟。", + "GravityModel::tumin": "返回 `xke` 的倒数,单位为分钟。\n\n这是模型的时间单位:参考圆轨道的周期除以二 pi。", + "GravityModel::j3_over_j2": "返回 `j3 / j2`,它在理论中以单一比值出现。", + "GravityModel::x2o3": "返回 `2 * xke^2`,它是平均运动修正中出现的一项。", "Satellite": "已准备好传播的卫星。\n\n用 [`Satellite::from_element`] 构造,然后对每个关注的时刻调用 [`Satellite::propagate_minutes`] 或 [`Satellite::propagate_at`]。初始化工作——包括平均运动改正与每个只依赖元素的系数——在构造时完成一次。", - "Satellite::from_element": "由已解析的元素集初始化卫星。\n\n当平均元素不描述模型可传播的轨道时返回 `None`,例如偏心率大于等于一。需要知道原因的调用方应使用 [`Satellite::try_from_element`]。", - "Satellite::try_from_element": "由已解析的元素集初始化卫星。\n\n当元素被拒绝时,返回描述哪个元素不可传播的错误。", - "Satellite::try_from_elements": "由已是模型单位的平均元素初始化卫星。", - "Satellite::epoch_mjd": "以 TAI 尺度上的约化儒略日返回元素的历元。", - "Satellite::is_deep_space": "当适用深空分支时返回 `true`。", - "Satellite::minutes_since_epoch": "返回自元素集历元到给定时刻的分钟数。\n\n该时刻以 TAI 尺度上的约化儒略日给出,与 [`Satellite::epoch_mjd`] 同尺度。", - "Satellite::propagate_at": "返回卫星在给定时刻的状态。\n\n该时刻是 TAI 尺度上的约化儒略日。", - "Satellite::propagate_minutes": "返回卫星在距元素集历元若干分钟处的状态。\n\n负值表示向后传播。结果位于真赤道平春分点坐标系,位置单位为千米、速度单位为千米每秒。\n\n当传播得到的半径低于一个地球半径时返回 [`PropagationErrorKind::Decayed`](crate::PropagationErrorKind::Decayed),模型把该情况视为卫星已再入。", - "Satellite::xke": "返回模型的 Kepler 常数,单位为弧度每分钟每地球半径的二分之三次方。", + "Satellite::from_element": "由解析出的元素集初始化一颗卫星。\n\n当平均根数不描述模型能够传播的轨道时返回 `None`,例如偏心率大于或等于一。需要知道具体原因的调用者请用 [`Satellite::try_from_element`]。", + "Satellite::try_from_element": "由解析出的元素集初始化一颗卫星。\n\n当这些根数被拒绝时,返回一个说明是哪个根数无法传播的错误。", + "Satellite::try_from_elements": "由已经处于模型单位下的平均根数初始化一颗卫星。", + "Satellite::epoch_mjd": "以 TAI 尺度返回根数的历元所对应的简化儒略日。", + "Satellite::is_deep_space": "当深空分支适用时返回 `true`。", + "Satellite::minutes_since_epoch": "返回从元素集历元到给定时刻的分钟数。\n\n该时刻以 TAI 尺度的简化儒略日给出,与 [`Satellite::epoch_mjd`] 是同一尺度。", + "Satellite::propagate_at": "返回卫星在给定时刻的状态。\n\n该时刻是 TAI 尺度的简化儒略日。", + "Satellite::propagate_minutes": "返回卫星在自元素集历元起若干分钟后的状态。\n\n负值表示向前传播。结果位于真赤道平赤道坐标系,位置以千米为单位,速度以千米每秒为单位。\n\n当传播后的半径低于一个地球半径时返回 [`PropagationErrorKind::Decayed`](crate::PropagationErrorKind::Decayed),模型把这视为卫星已经再入。", + "Satellite::xke": "返回模型的开普勒常数,单位为每地球半径之分之三次方每分钟弧度。", "State": "卫星在真赤道平春分点坐标系中的位置与速度。\n\n位置单位为千米,速度单位为千米每秒。该系是模型定义的坐标系:第一轴指向平春分点,第三轴沿真赤道极轴,第二轴构成右手系。", "State::altitude_radius": "以千米返回距地心的距离。", "State::speed": "以千米每秒返回相对地心的速率。", @@ -332,19 +332,19 @@ "KeplerianElements": "轨道的六个开普勒元素。\n\n形状与大小由半长轴与偏心率给出,朝向由倾角、升交点赤经与近地点幅角给出,沿轨道的位置由真近点角给出。\n\n角度单位为弧度,半长轴单位为千米。轨道是椭圆,因此偏心率必须小于一。", "KeplerianElements::State": "卫星在元素所参考惯性系中的位置与速度。\n\n位置单位为千米,速度单位为千米每秒。该系的第一轴指向参考方向,第三轴沿轨道法线,第二轴构成右手系。", "KeplerianElements::is_valid": "当元素描述椭圆轨道时返回 `true`。", - "KeplerianElements::semi_latus_rectum": "以千米返回半通径。\n\n这是 `a (1 - e^2)`,即从焦点到轨道的距离,沿垂直长轴方向量取。", - "KeplerianElements::semi_minor_axis": "以千米返回短半轴。", - "KeplerianElements::perigee_radius": "以千米返回近地点半径。\n\n这是距焦点的最近距离,`a (1 - e)`。", - "KeplerianElements::apogee_radius": "以千米返回远地点半径。\n\n这是距焦点的最远点,`a (1 + e)`。", + "KeplerianElements::semi_latus_rectum": "以千米返回半通径。\n\n它等于 `a (1 - e^2)`,即垂直于长轴量得的从焦点到轨道的距离。", + "KeplerianElements::semi_minor_axis": "以千米返回半短轴。", + "KeplerianElements::perigee_radius": "以千米返回近地点半径。\n\n这是对焦点的最近距离 `a (1 - e)`。", + "KeplerianElements::apogee_radius": "以千米返回远地点半径。\n\n这是离焦点最远的点 `a (1 + e)`。", "KeplerianElements::period": "以秒返回轨道周期。\n\n这是开普勒第三定律,`T = 2 pi sqrt(a^3 / mu)`。", "KeplerianElements::eccentric_anomaly": "返回与真近点角对应的偏近点角。", "KeplerianElements::mean_anomaly": "返回与真近点角对应的平近点角。", - "KeplerianElements::to_state": "把本元素转换为位置与速度。\n\n当元素不构成有效椭圆轨道时返回 `None`。\n\n转换先把卫星置于近焦点坐标系,其第一轴指向近地点、第三轴沿轨道法线,\n\n```text\nr = p / (1 + e cos nu)\nx = r cos nu, y = r sin nu, z = 0\nvx = -sqrt(mu / p) sin nu\nvy = sqrt(mu / p) (e + cos nu)\n```\n\n再按近地点幅角、倾角与升交点赤经依次旋转。", - "KeplerianElements::from_state": "返回给定位置与速度对应的元素。\n\n当状态非有限、半径为零,或轨道不是椭圆时返回 `None`。该转换假定轨道是束缚的,因此抛物线与双曲线状态会被拒绝,而不是以大于等于一的偏心率返回。", - "KeplerianElements::with_true_anomaly": "返回具有不同真近点角的本元素副本。", - "KeplerianElements::with_mean_anomaly": "返回处于给定平近点角的本元素副本。\n\n真近点角由平近点角经开普勒方程恢复。", - "KeplerianElements::to_mean_anomaly": "返回平近点角,即沿轨道的时间线性度量。\n\n该值与 [`KeplerianElements::mean_anomaly`] 相同,命名是为了与 [`KeplerianElements::with_mean_anomaly`] 对称。", - "KeplerianElements::perifocal_to_inertial": "返回自近焦点系到惯性系的旋转。\n\n该旋转是三次初等旋转之积:先绕第三轴旋转近地点幅角,再绕第一轴旋转倾角,最后绕第三轴旋转升交点赤经。", + "KeplerianElements::to_state": "把这些根数转换为位置与速度。\n\n当这些根数不是有效的椭圆轨道时返回 `None`。\n\n该转换把卫星放在近焦点坐标系中,其中第一轴指向近地点,第三轴沿轨道法线,\n\n```text\nr = p / (1 + e cos nu)\nx = r cos nu, y = r sin nu, z = 0\nvx = -sqrt(mu / p) sin nu\nvy = sqrt(mu / p) (e + cos nu)\n```\n\n然后依次按近地点幅角、倾角和升交点赤经旋转。", + "KeplerianElements::from_state": "返回给定位置与速度对应的根数。\n\n当状态量非有限、半径为零、或轨道不是椭圆时返回 `None`。该转换假定轨道是束缚的,因此抛物线或双曲线状态会被拒绝,而不是返回一个偏心率大于或等于一的结果。", + "KeplerianElements::with_true_anomaly": "返回这些根数的一份副本,其中真近点角不同。", + "KeplerianElements::with_mean_anomaly": "返回处于给定平近点角的这些根数副本。\n\n真近点角由平近点角经开普勒方程解出。", + "KeplerianElements::to_mean_anomaly": "返回平近点角,它是沿轨道的线性时间量度。\n\n这与 [`KeplerianElements::mean_anomaly`] 是同一个值,此处命名是为了与 [`KeplerianElements::with_mean_anomaly`] 对称。", + "KeplerianElements::perifocal_to_inertial": "返回从近焦点坐标系到惯性系的旋转。\n\n该旋转是三个基本旋转之积:先绕第三轴转近地点幅角,再绕第一轴转倾角,最后绕第三轴转升交点赤经。", "GravityParameter": "中心天体的引力参数,单位为立方千米每二次方秒。\n\n提供两个值是因为工作区同时支持两种引力模型,正确的选择是与轨道元素来源相匹配的那个。对由两行元素集导出的元素,应使用 SGP4 理论所拟合的 WGS 72 值。", "GravityParameter::WGS72": "WGS 72 引力参数,`398 600.8 km^3/s^2`。", "GravityParameter::WGS84": "WGS 84 引力参数,`398 600.5 km^3/s^2`。", @@ -459,6 +459,81 @@ "State::with_true_anomaly": "返回具有不同真近点角的本元素副本。", "State::with_mean_anomaly": "返回处于给定平近点角的本元素副本。\n\n真近点角由平近点角经开普勒方程恢复。", "State::to_mean_anomaly": "返回平近点角,即沿轨道的时间线性度量。\n\n该值与 [`KeplerianElements::mean_anomaly`] 相同,命名是为了与 [`KeplerianElements::with_mean_anomaly`] 对称。", - "State::perifocal_to_inertial": "返回自近焦点系到惯性系的旋转。\n\n该旋转是三次初等旋转之积:先绕第三轴旋转近地点幅角,再绕第一轴旋转倾角,最后绕第三轴旋转升交点赤经。" + "State::perifocal_to_inertial": "返回自近焦点系到惯性系的旋转。\n\n该旋转是三次初等旋转之积:先绕第三轴旋转近地点幅角,再绕第一轴旋转倾角,最后绕第三轴旋转升交点赤经。", + "apsis-core::new": "以给定的类别创建一个不带消息的错误。", + "apsis-core::with_message": "以给定的类别和消息创建一个错误。\n\n消息应当描述这一次失败的具体原因。它是给读日志的人看的,不是用来做匹配的。", + "apsis-core::with_source": "以给定的类别和一个来源错误创建一个错误。", + "apsis-core::with_context": "为这个错误附上一条消息,替换已有的消息。", + "apsis-core::caused_by": "附上一个来源错误,替换已有的来源。", + "apsis-core::kind": "返回这个错误的类别。", + "apsis-core::message": "返回附在这个错误上的消息,若有。", + "apsis-units::new": "以弧度值创建一个角度。", + "apsis-units::value": "以弧度返回这个角度。", + "apsis-units::to_degrees": "把这个角度转换为度。", + "apsis-units::wrap": "返回折叠到半开区间 `[-pi, pi)` 的这个角度。\n\n折叠使用 [`f64::rem_euclid`](f64::rem_euclid),因此对负值与很大的值结果都有定义。", + "apsis-units::to_radians": "把这个角度转换为弧度。", + "apsis-units::period": "返回与这个频率对应的周期,单位为秒。\n\n频率为零时返回 `f64::INFINITY`,这正是周期无穷大的正确极限。", + "apsis-units::to_kilometers": "把这个长度转换为千米。", + "apsis-units::to_meters": "把这个长度转换为米。", + "apsis-units::from_celsius": "以摄氏温度值创建一个温度。\n\n使用摄氏温标定义的精确偏移量。", + "apsis-units::to_celsius": "把这个温度转换为摄氏度。", + "apsis-leap::effective_mjd": "返回生效时刻的简化儒略日。\n\n闰秒在 UTC 的 00:00:00 生效,因此生效时刻就是给定日历日的起点。", + "apsis-tle::as_char": "返回元素集中所用的字符。", + "apsis-tle::new": "以给定的类别、行号和列区间创建一个错误。\n\n行号从 1 开始。列区间是从 1 开始、含两端的区间,指明读取失败时所在的字段。", + "apsis-tle::with_detail": "附上对出错文本的描述。", + "apsis-tle::kind": "返回这次失败的类别。", + "apsis-tle::line": "返回失败所在行的一基行号。", + "apsis-tle::columns": "返回失败的一基含两端列区间,若有。", + "apsis-tle::detail": "返回附在这个错误上的细节文本,若有。", + "apsis-tle::Result": "一个 [`Result`](core::result::Result),其错误类型为 [`ElementError`]。", + "apsis-time::new": "由各字段创建一个日历日期。", + "apsis-time::from_ymd": "在给定日期的起点创建一个日历日期。", + "apsis-time::seconds_of_day": "返回自当日零点起经过的秒数。", + "apsis-time::is_valid": "当各字段构成一个在前推格里高利历中存在的日期时返回 `true`。", + "apsis-time::is_leap_year": "当 `year` 在前推格里高利历中是闰年时返回 `true`。", + "apsis-time::days_in_month": "返回给定年份中给定月份的天数。\n\n`month` 落在 `1..=12` 之外时返回零。", + "apsis-time::ymd_from_mjd": "把简化儒略日转换为日历日期。\n\n小数部分被忽略,因此结果是包含该时刻的那一日历日。", + "apsis-time::seconds_of_day_from_mjd": "只保留 MJD 的小数部分,作为自午夜起的秒数。\n\n对任何有限输入,结果都落在 `[0, 86400)` 内。", + "apsis-time::J2000": "时刻 2000-01-01T12:00:00 TT,它定义了 J2000.0 历元。\n\n该值在 TT 尺度上是 `2451545.0`,再回退到 TAI。", + "apsis-time::from_tai_mjd": "由 TAI 尺度上的简化儒略日创建一个历元。", + "apsis-time::from_mjd": "由给定尺度上的简化儒略日创建一个历元。\n\n当该时刻无法在所请求的尺度上表示时返回 `None`。1972 年之前的 UTC 即属此情形,用于从 UTC 转换的闰秒表不适用于那段范围。", + "apsis-time::from_calendar": "由日历日期创建一个历元,并按给定尺度解释它。\n\n当各字段不构成有效日期,或该时刻无法在所请求的尺度上表示时返回 `None`。", + "apsis-time::tai_mjd": "以 TAI 尺度返回该时刻的简化儒略日。", + "apsis-time::mjd": "以给定尺度返回该时刻的简化儒略日。\n\n当该时刻早于 1972 年而请求的是 UTC 尺度时返回 `None`,因为闰秒表不覆盖那段范围。", + "apsis-time::calendar": "以给定尺度返回该时刻的日历日期。\n\n当该时刻的尺度转换不可用时返回 `None`;参见 [`Epoch::mjd`]。", + "apsis-time::seconds_until": "返回从 `self` 到 `other` 的带符号秒数。\n\n`other` 更晚时结果为正。由于两个历元都以均匀的 TAI 尺度存储,这个差是精确的,且与创建任一历元所用的尺度无关。", + "apsis-time::add_seconds": "返回平移了 `seconds` 的历元。\n\n平移量以均匀 TAI 尺度上的 SI 秒计,因此该时刻恰好前进这么多经过时间。这里只提供这一种平移:以 UTC 时钟计量的平移在区间跨越插入的闰秒时会不同,而 UTC 时钟在这种时刻上并没有单一良定义的数值。需要对 UTC 尺度做日历运算的调用者应当转换到 [`Calendar`]、调整后再转换回来。", + "apsis-time::is_finite": "当存储的简化儒略日为有限值时返回 `true`。", + "apsis-time::is_uniform": "当该尺度以均匀速率运行时返回 `true`。\n\n这里的 UTC 是唯一不均匀的尺度,因为闰秒会使它的一些分钟长达 61 秒。", + "apsis-time::name": "返回该尺度的短名,例如 `TAI` 或 `UTC`。", + "Inertial::new": "由以米为单位的向量创建一个惯性系位置。", + "Inertial::vector": "以米返回该位置。", + "Inertial::to_ecef": "在给定的地球自转角处,把这个惯性系位置转换为地固系。", + "Inertial::to_eci": "在给定的地球自转角处,把这个地固系位置转换为惯性系。", + "Inertial::to_geodetic": "把这个地固系位置转换为给定椭球之上的纬度、经度与高度。\n\n当该位置位于极轴上时返回 `None`,因为那里没有定义经度。", + "apsis-geodesy::new": "由纬度、经度和高度创建一个大地位置。", + "apsis-kepler::is_valid": "当这些根数描述一条椭圆轨道时返回 `true`。", + "apsis-kepler::period": "以秒返回轨道周期。\n\n这是开普勒第三定律 `T = 2 pi sqrt(a^3 / mu)`。", + "apsis-kepler::eccentric_anomaly": "返回与真近点角对应的偏近点角。", + "apsis-kepler::mean_anomaly": "返回与真近点角对应的平近点角。", + "apsis-kepler::WGS72": "WGS 72 引力参数 `398 600.8 km^3/s^2`。", + "apsis-kepler::value": "以立方千米每二次方秒返回该值。", + "apsis-kepler::sqrt": "返回该参数的平方根,单位为千米的三分之二次方每秒。", + "Series::at": "返回某个以儒略世纪计的时刻对应的五个参数。", + "apsis-sgp4::propagate_minutes_at": "按顺序把一颗卫星传播到自其历元起的一组分钟处。\n\n这是顺序形式,供对照使用,也用于较小的列表——那种情况下启动线程的代价超过工作本身。", + "apsis-sgp4::propagate_minutes_at_parallel": "跨多个线程把一颗卫星传播到自其历元起的一组分钟处。\n\n结果与 [`propagate_minutes_at`] 逐元素、且以相同顺序一致。模型报告卫星衰减的那一分钟给出 `None`,与顺序形式相同;线程不会在第一个这样的分钟处停下,因为调用者通常需要整条轨迹,会自行判断衰减意味着什么。\n\n传播是确定性的,只取决于这些分钟,因此结果与工作如何切分无关。\n\n收益取决于列表中工作量的大小,因为启动线程有固定开销,短列表无法收回这份开销。以一分钟步长算,一天是一千四百个状态,收益很小;一个月是四万三千个,能快好几倍。有许多短轨道的调用者更适合下面按卫星的形式,它一次接收整个列表。", + "apsis-sgp4::propagate_at": "按顺序把多颗卫星传播到同一时刻。\n\n按卫星的工作是彼此独立的,因此一个星座在某一时刻的状态是天然的批处理。卫星只被读取,因此它们以引用形式在各线程间共享。", + "apsis-sgp4::propagate_at_parallel": "跨多个线程把多颗卫星传播到同一时刻。\n\n结果与 [`propagate_at`] 逐元素、且以相同顺序一致。\n\n这是覆盖性计算想要的形式:它在一次调用中持有整个星座,于是线程为所有卫星只启动一次,而不是每颗卫星一次,即便只有几百颗的星座也能获益。", + "apsis-sgp4::from_tle": "把解析出的元素集转换为传播器所用的单位。\n\n历元取元素集中原样写下的 UTC 简化儒略日。元素集历元是一个 UTC 日历时刻,但传播器把它当作均匀的时间原点,这是该理论拟合时所依据的约定。先把它换算到均匀尺度会把历元平移一个闰秒偏移量,约为 33 秒,而这一平移会传播进深空分支的太阳与月球级数中。", + "apsis-sgp4::unkozai_mean_motion": "施加从 Kozai 平均运动到 Brouwer 平均运动的修正。\n\n元素集中的平均运动是 Kozai 平均运动,理论必须先把它换算成 Brouwer 平均运动。其关系为\n\n```text\nn0 = n / (1 + 1.5 k2 (3 cos^2 i - 1) / (a^2 sqrt(1 - e^2)) / a^2)\n```\n\n此处写成不动点迭代的形式,因为 `a` 通过开普勒第三定律依赖于 `n0`。对元素集中出现的每一条轨道,该迭代从未修正的平均运动出发,几步之内即收敛。\n\n施加从 Kozai 平均运动到 Brouwer 平均运动的修正。\n\n元素集中的平均运动是 Kozai 平均运动,理论必须先把它换算成 Brouwer 平均运动。以 `no` 表示元素集中的值、`xke` 表示开普勒常数,参考实现的求值为\n\n```text\nak = (xke / no)^(2/3)\nd1 = 0.75 j2 (3 cos^2 i - 1) / (sqrt(1 - e^2) (1 - e^2))\ndel = d1 / ak^2\nadel = ak (1 - del^2 - del (1/3 + 134 del^2 / 81))\ndel = d1 / adel^2\nn0 = no / (1 + del)\n```\n\n第二次求值 `del` 用的是 `adel` 而非 `ak`,这正是该修正与修正后平均运动所隐含的半长轴保持一致的原因。\n\n来源:Vallado 等,*Revisiting Spacetrack Report #3*,AIAA 2006-6753,2006。", + "apsis-sgp4::validate": "在初始化之前校验平均根数。\n\n当轨道无法传播时返回错误,例如偏心率不构成闭合轨道,或平均运动不为正。", + "GravityModel::is_deep_space": "当这些根数描述一条深空轨道时返回 `true`。\n\n判据是轨道周期,它由平均运动推出。", + "apsis-sgp4::WGS72": "WGS 72 重力模型。\n\n这是 SGP4 理论拟合所采用的模型,也是与标准元素集相匹配的那个。", + "Satellite::altitude_radius": "返回到地心的距离,单位为千米。", + "Satellite::speed": "返回相对地心的速率,单位为千米每秒。", + "apsis-math::thread_count": "一项工作应当使用的线程数。\n\n这是标准库报告的机器并行度,至少为一。它是……", + "apsis-math::threads_for": "对 `len` 个元素做循环时应当运行的线程数。\n\n比线程数还短的循环会让大多数线程无事可做,而……", + "apsis-math::for_each_index": "对一个范围的每个索引运行一次闭包,分散到多个线程。\n\n该范围被切成每个线程一段连续区间,每个线程……", + "apsis-math::map_index": "收集一个范围中每个索引对应的值,分散到多个线程。\n\n这就是常见情形下的 [`for_each_index`],此时结果……" } } diff --git a/frontend/src/pages/Api.svelte b/frontend/src/pages/Api.svelte index e4d214e..5a935a9 100644 --- a/frontend/src/pages/Api.svelte +++ b/frontend/src/pages/Api.svelte @@ -142,9 +142,18 @@ })) .filter((layer) => layer.crates.length > 0); const placed = new Set(declared.map((layer) => layer.id)); - const rest = current.crates.filter((krate) => !placed.has(krate.layer)); + // A crate that belongs to no layer is the workspace facade, which only + // re-exports what the crates of the layers already define. It is shown + // nowhere: a listing of it would repeat every item of the layers under a + // second name, and it is not a subject a reader is looking for. + const rest = current.crates.filter( + (krate) => krate.layer !== '' && !placed.has(krate.layer), + ); return rest.length > 0 - ? [...grouped, { id: '', title: { zh: '其他', en: 'Others' }, summary: { zh: '', en: '' }, crates: rest }] + ? [ + ...grouped, + { id: '', title: { zh: '其他', en: 'Others' }, summary: { zh: '', en: '' }, crates: rest }, + ] : grouped; }); diff --git a/scripts/extract_api.py b/scripts/extract_api.py index 4180d5b..a668163 100755 --- a/scripts/extract_api.py +++ b/scripts/extract_api.py @@ -267,6 +267,12 @@ def main(): if not os.path.isdir(os.path.join(workspace, directory)): sys.stderr.write("skipping %s: no such directory\n" % directory) continue + if layer is None: + # The facade sits directly in `crates` and re-exports every layer. + # It defines nothing of its own, so listing it would repeat every + # item of the layers under a second name without adding anything. + sys.stderr.write("skipping %s: the workspace facade\n" % name) + continue entry = collect_crate(workspace, name, directory) entry["layer"] = layer crates.append(entry) diff --git a/src/docs/api.rs b/src/docs/api.rs index ba88e30..8370705 100644 --- a/src/docs/api.rs +++ b/src/docs/api.rs @@ -183,7 +183,25 @@ fn translated(table: Option<&Value>, key: &str) -> Option { /// Several types have an associated `new`, so the qualified key is the one /// that disambiguates them; the bare key is kept as a fallback for a /// translation that is the same for every owner. -fn item_translation(item_texts: Option<&Value>, owner: Option<&str>, name: &str) -> Option { +/// Returns the Chinese text of an item. +/// +/// Three keys are tried, most specific first. A name such as `new` is used +/// by many crates and several of them mean different things by it, so a +/// translation filed under the name alone would be shown against the wrong +/// documentation. The crate qualified key names one item exactly. The owner +/// qualified key names a method of one type, which separates two items of +/// the same crate that share a name, such as the `new` of two types. The +/// bare key is the last resort and is only correct for a name that one crate +/// uses for one thing. +fn item_translation( + item_texts: Option<&Value>, + krate: &str, + owner: Option<&str>, + name: &str, +) -> Option { + if let Some(text) = translated(item_texts, &format!("{krate}::{name}")) { + return Some(text); + } if let Some(owner) = owner { if let Some(text) = translated(item_texts, &format!("{owner}::{name}")) { return Some(text); @@ -233,7 +251,12 @@ fn parse_crate( .iter() .enumerate() .filter_map(|(index, item)| { - parse_item(item, item_texts, owner_of(raw_items, index).as_deref()) + parse_item( + item, + item_texts, + &name, + owner_of(raw_items, index).as_deref(), + ) }) .collect(); let summary_zh = translated(crate_texts, &name); @@ -247,7 +270,12 @@ fn parse_crate( } /// Parses one item. -fn parse_item(value: &Value, item_texts: Option<&Value>, owner: Option<&str>) -> Option { +fn parse_item( + value: &Value, + item_texts: Option<&Value>, + krate: &str, + owner: Option<&str>, +) -> Option { let name = value.get("name")?.as_str()?.to_string(); let kind = value.get("kind")?.as_str()?.to_string(); let signature = value @@ -264,7 +292,7 @@ fn parse_item(value: &Value, item_texts: Option<&Value>, owner: Option<&str>) -> .get("associated") .and_then(Value::as_bool) .unwrap_or(false); - let doc_zh = item_translation(item_texts, owner, &name); + let doc_zh = item_translation(item_texts, krate, owner, &name); Some(ApiItem { kind, name, @@ -312,4 +340,41 @@ mod tests { assert!(parse("not json").is_empty()); assert!(parse("{}").is_empty()); } + + #[test] + fn a_translation_filed_under_the_crate_beats_the_bare_name() { + // `new` means something different in each crate, so a translation + // filed under the name alone would be shown against the wrong + // documentation. + let item = r#"{"kind":"fn","name":"new","doc":"English.", + "signature":"pub fn new()"}"#; + let texts = r#"{ + "new":"裸译。", + "apsis-core::new":"属于 apsis-core 的译文。"}"#; + let parsed = parse_item( + &crate::json::parse(item).expect("an item"), + Some(&crate::json::parse(texts).expect("the translations")), + "apsis-core", + None, + ) + .expect("an item"); + assert_eq!(parsed.doc_zh.as_deref(), Some("属于 apsis-core 的译文。")); + } + + #[test] + fn a_translation_filed_under_the_owner_separates_two_items_of_one_crate() { + // Two types of one crate each have a `new`; the owner tells them + // apart. + let item = r#"{"kind":"fn","name":"new","doc":"English.", + "signature":"pub fn new()"}"#; + let texts = r#"{"Inertial::new":"惯性系的新建。"}"#; + let parsed = parse_item( + &crate::json::parse(item).expect("an item"), + Some(&crate::json::parse(texts).expect("the translations")), + "apsis-coord", + Some("Inertial"), + ) + .expect("an item"); + assert_eq!(parsed.doc_zh.as_deref(), Some("惯性系的新建。")); + } }