docs: extend the bilingual sweep into routing, topology, access and rf

A translation table for the sentences that recur across the error types
and the simple accessors let the same wording be applied everywhere at
once, which both keeps the Chinese consistent and covers a hundred and
twenty-nine sites in a single pass. Routing, topology, access and the radio
frequency crates are now part of the sweep.
This commit is contained in:
ApsisRS contributors 2026-10-02 01:10:40 +08:00
parent 500f9775db
commit 2f62d2522b
47 changed files with 312 additions and 2 deletions

View File

@ -43,22 +43,30 @@ pub struct AccessError {
impl AccessError {
/// Creates an error with the given category.
///
/// 用给定类别创建一个错误。
pub fn new(kind: AccessErrorKind) -> Self {
Self { kind, detail: None }
}
/// Attaches a description of the values that caused the failure.
///
/// 附加对该失败所涉数值的说明。
pub fn with_detail(mut self, detail: impl Into<String>) -> Self {
self.detail = Some(detail.into());
self
}
/// Returns the category of this failure.
///
/// 返回该失败的类别。
pub fn kind(&self) -> AccessErrorKind {
self.kind
}
/// Returns the detail text attached to this error, if any.
///
/// 返回附加在该错误上的说明文本,若有。
pub fn detail(&self) -> Option<&str> {
self.detail.as_deref()
}

View File

@ -14,6 +14,8 @@ use apsis_math::Vec3;
#[derive(Debug, Clone, Copy, PartialEq)]
pub struct OrbitSample {
/// The time of the sample, in seconds from the caller's origin.
///
/// 样本时刻,单位为自调用方原点起的秒数。
pub seconds: f64,
/// The satellite position in the Earth-fixed frame, in kilometers.
pub position_ecef_km: Vec3,

View File

@ -59,6 +59,8 @@ impl ConstellationError {
/// Creates an error with the given category.
///
/// 用给定类别创建一个错误。
///
/// 用给定类别创建一个错误。
pub fn new(kind: ConstellationErrorKind) -> Self {
Self { kind, detail: None }
}
@ -66,6 +68,8 @@ impl ConstellationError {
/// Attaches a description of the values that caused the failure.
///
/// 附加对该失败所涉数值的说明。
///
/// 附加对该失败所涉数值的说明。
pub fn with_detail(mut self, detail: impl Into<String>) -> Self {
self.detail = Some(detail.into());
self
@ -74,12 +78,16 @@ impl ConstellationError {
/// Returns the category of this failure.
///
/// 返回该失败的类别。
///
/// 返回该失败的类别。
pub fn kind(&self) -> ConstellationErrorKind {
self.kind
}
/// Returns the detail text attached to this error, if any.
///
/// 返回附加在该错误上的说明文本,若有。
///
/// 返回附加在该错误上的说明文本,若无则返回 `None`。
pub fn detail(&self) -> Option<&str> {
self.detail.as_deref()

View File

@ -73,6 +73,8 @@ impl Footprint {
/// the elevation mask.
///
/// Returns `None` when the geometry is not usable.
///
/// 几何不可用时返回 `None`。
pub fn footprint_central_angle(
satellite_radius: f64,
body_radius: f64,
@ -89,6 +91,8 @@ pub fn footprint_central_angle(
/// Returns the footprint for a satellite and an elevation mask.
///
/// Returns `None` when the geometry is not usable.
///
/// 几何不可用时返回 `None`。
pub fn footprint(
satellite_radius: f64,
body_radius: f64,
@ -105,6 +109,8 @@ pub fn footprint(
/// This is a free function form of [`Footprint::area`].
///
/// Returns `None` when the geometry is not usable.
///
/// 几何不可用时返回 `None`。
pub fn footprint_area(satellite_radius: f64, body_radius: f64, elevation_mask: f64) -> Option<f64> {
Some(footprint(satellite_radius, body_radius, elevation_mask)?.area())
}
@ -112,6 +118,8 @@ pub fn footprint_area(satellite_radius: f64, body_radius: f64, elevation_mask: f
/// Returns the fraction of the Earth's surface covered by a footprint.
///
/// Returns `None` when the geometry is not usable.
///
/// 几何不可用时返回 `None`。
pub fn footprint_fraction(
satellite_radius: f64,
body_radius: f64,
@ -167,6 +175,8 @@ pub fn point_in_footprint(
/// footprint is known and the mask it corresponds to is wanted.
///
/// Returns `None` when the geometry is not usable.
///
/// 几何不可用时返回 `None`。
pub fn footprint_edge_elevation(satellite_radius: f64, footprint: &Footprint) -> Option<f64> {
elevation_from_central_angle(
satellite_radius,

View File

@ -57,6 +57,8 @@ pub fn nadir_angle(satellite_radius: f64, body_radius: f64, elevation: f64) -> O
/// body radius.
///
/// Returns `None` when the geometry is not usable.
///
/// 几何不可用时返回 `None`。
pub fn earth_central_angle(satellite_radius: f64, body_radius: f64, elevation: f64) -> Option<f64> {
let nadir = nadir_angle(satellite_radius, body_radius, elevation)?;
// Rounding can leave a small negative value at the zenith, where the
@ -86,6 +88,8 @@ pub fn earth_central_angle(satellite_radius: f64, body_radius: f64, elevation: f
/// even though the range there is simply the altitude.
///
/// Returns `None` when the geometry is not usable.
///
/// 几何不可用时返回 `None`。
pub fn slant_range(satellite_radius: f64, body_radius: f64, elevation: f64) -> Option<f64> {
let central = earth_central_angle(satellite_radius, body_radius, elevation)?;
if !central.is_finite() || central < 0.0 {

View File

@ -233,6 +233,8 @@ pub fn visible_from_geodetic(
/// is used only for its radius.
///
/// Returns `None` when the geometry is not usable.
///
/// 几何不可用时返回 `None`。
pub fn central_angle_to_station(
satellite_ecef_km: Vec3,
ground: &GroundPoint,

View File

@ -147,6 +147,8 @@ fn validate(policy: &HandoverPolicy, candidates: &[Candidate]) -> Result<(), Han
/// quality by more than the margin.
///
/// Returns an error when the candidates or the policy are not usable.
///
/// 候选或策略不可用时返回错误。
pub fn decide(
policy: &HandoverPolicy,
current: Option<usize>,
@ -166,6 +168,8 @@ pub fn decide(
/// prevents.
///
/// Returns an error when the candidates or the policy are not usable.
///
/// 候选或策略不可用时返回错误。
pub fn decide_with_history(
policy: &HandoverPolicy,
current: Option<usize>,

View File

@ -37,22 +37,30 @@ pub struct HandoverError {
impl HandoverError {
/// Creates an error with the given category.
///
/// 用给定类别创建一个错误。
pub fn new(kind: HandoverErrorKind) -> Self {
Self { kind, detail: None }
}
/// Attaches a description of the values that caused the failure.
///
/// 附加对该失败所涉数值的说明。
pub fn with_detail(mut self, detail: impl Into<String>) -> Self {
self.detail = Some(detail.into());
self
}
/// Returns the category of this failure.
///
/// 返回该失败的类别。
pub fn kind(&self) -> HandoverErrorKind {
self.kind
}
/// Returns the detail text attached to this error, if any.
///
/// 返回附加在该错误上的说明文本,若有。
pub fn detail(&self) -> Option<&str> {
self.detail.as_deref()
}

View File

@ -210,6 +210,8 @@ impl HandoverTracker {
/// tracker having recorded it.
///
/// Returns an error when the candidates or the policy are not usable.
///
/// 候选或策略不可用时返回错误。
pub fn step(
&mut self,
seconds: f64,

View File

@ -16,11 +16,17 @@ use core::cmp::Ordering;
use std::collections::BinaryHeap;
/// A heap entry holding a node and its tentative distance.
///
/// 堆中的一项,保存某个节点及其暂定距离。
#[derive(Debug, Clone, Copy, PartialEq)]
struct Candidate {
/// The tentative distance from the source.
///
/// 自源点出发的暂定距离。
distance: f64,
/// The node index.
///
/// 节点下标。
node: usize,
}
@ -32,6 +38,8 @@ impl Ord for Candidate {
// the greatest element, which is what the maximum heap needs. Equal
// distances are ordered by node index so that the sequence of
// relaxations is reproducible.
// 反转距离比较,使最小距离成为最大元素,这正是最大堆所需。距离
// 相等时按节点下标排序,使松弛的次序可复现。
other
.distance
.partial_cmp(&self.distance)
@ -48,6 +56,8 @@ impl PartialOrd for Candidate {
/// The result of a single source shortest path computation.
///
/// 单源最短路计算的结果。
///
/// The distances are to every node reachable from the source, and the
/// predecessor map records the edge by which each node was reached. Both are
/// what a routing table needs, and a single computation fills a whole row of
@ -55,16 +65,24 @@ impl PartialOrd for Candidate {
#[derive(Debug, Clone, PartialEq)]
pub struct PathTree {
/// The source node.
///
/// 源节点。
pub source: usize,
/// The distance to each node, or infinity when it is unreachable.
///
/// 到各节点的距离;不可达时为无穷。
pub distances: Vec<f64>,
/// The predecessor of each node on the shortest path, if any.
///
/// 各节点在最短路上的前驱,若有。
pub predecessors: Vec<Option<usize>>,
}
impl PathTree {
/// Returns the distance to a node.
///
/// 返回到某节点的距离。
///
/// Returns `None` when the node index is out of range or the node is
/// unreachable.
pub fn distance(&self, node: usize) -> Option<f64> {
@ -73,11 +91,17 @@ impl PathTree {
}
/// Returns `true` when the node is reachable from the source.
///
/// 当该节点自源点可达时返回 `true`。
pub fn is_reachable(&self, node: usize) -> bool {
self.distance(node).is_some()
}
/// Returns the number of reachable nodes, including the source itself.
///
/// 返回可达节点的数量,含源点自身。
///
/// 返回可达节点的数量,含源点自身。
pub fn reachable_count(&self) -> usize {
self.distances
.iter()
@ -87,6 +111,8 @@ impl PathTree {
/// Reconstructs the route to a node.
///
/// 重建到某节点的路由。
///
/// Returns an error when the node is out of range or unreachable.
pub fn route_to(&self, destination: usize, topology: &Topology) -> Result<Route, RoutingError> {
if destination >= self.distances.len() {
@ -99,6 +125,7 @@ impl PathTree {
}
// Walk the predecessor chain back to the source, then reverse it.
// 沿前驱链回溯到源点,然后反转。
let mut nodes = vec![destination];
let mut current = destination;
while current != self.source {
@ -129,6 +156,10 @@ impl PathTree {
///
/// Returns an error when the source node is out of range.
///
/// 计算自一个源点到每个可达节点的最短距离。
///
/// 源节点超出取值范围时返回错误。
///
/// Source: Dijkstra, E. W., *A note on two problems in connexion with
/// graphs*, Numerische Mathematik 1, 1959.
pub fn shortest_paths_from(topology: &Topology, source: usize) -> Result<PathTree, RoutingError> {
@ -150,6 +181,7 @@ pub fn shortest_paths_from(topology: &Topology, source: usize) -> Result<PathTre
while let Some(Candidate { distance, node }) = heap.pop() {
// A stale entry: the node already has a shorter distance.
// 过时项:该节点已有更短的距离。
if settled[node] {
continue;
}
@ -175,7 +207,7 @@ pub fn shortest_paths_from(topology: &Topology, source: usize) -> Result<PathTre
})
}
/// Returns the shortest route between two nodes.
/// 返回两节点之间的最短路由。
///
/// Returns an error when either node is out of range, when they are the
/// same node, or when no route exists.
@ -261,7 +293,7 @@ pub fn route_over_series(
.has_edge(edge.from, edge.to)
});
if present_everywhere {
// The link was checked above, so a failure here would mean the
// 链路已在上方校验,故此处的失败意味着
// reference topology contradicts itself.
let _ = intersection.add_edge(edge.from, edge.to, edge.cost);
}

View File

@ -3,18 +3,30 @@
use core::fmt;
/// The category of a routing error.
///
/// 路由错误的类别。
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
#[non_exhaustive]
pub enum RoutingErrorKind {
/// A node index is outside the range of the graph.
///
/// 节点下标超出该图的取值范围。
NoSuchNode,
/// No route exists between the two nodes.
///
/// 两节点之间不存在路由。
NoRoute,
/// The two endpoints are the same node.
///
/// 两个端点是同一节点。
SameEndpoint,
/// The interval is empty or not ordered.
///
/// 区间为空或次序不对。
InvalidInterval,
/// The topology series does not cover the requested interval.
///
/// 拓扑序列未覆盖所请求的区间。
SeriesTooShort,
}
@ -32,6 +44,8 @@ impl fmt::Display for RoutingErrorKind {
}
/// A failure while routing.
///
/// 路由时发生的失败。
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct RoutingError {
kind: RoutingErrorKind,
@ -40,22 +54,38 @@ pub struct RoutingError {
impl RoutingError {
/// Creates an error with the given category.
///
/// 用给定类别创建一个错误。
///
/// 用给定类别创建一个错误。
pub fn new(kind: RoutingErrorKind) -> Self {
Self { kind, detail: None }
}
/// Attaches a description of the values that caused the failure.
///
/// 附加对该失败所涉数值的说明。
///
/// 附加对该失败所涉数值的说明。
pub fn with_detail(mut self, detail: impl Into<String>) -> Self {
self.detail = Some(detail.into());
self
}
/// Returns the category of this failure.
///
/// 返回该失败的类别。
///
/// 返回该失败的类别。
pub fn kind(&self) -> RoutingErrorKind {
self.kind
}
/// Returns the detail text attached to this error, if any.
///
/// 返回附加在该错误上的说明文本,若有。
///
/// 返回附加在该错误上的说明文本,若有。
pub fn detail(&self) -> Option<&str> {
self.detail.as_deref()
}

View File

@ -46,22 +46,30 @@ pub struct TopologyError {
impl TopologyError {
/// Creates an error with the given category.
///
/// 用给定类别创建一个错误。
pub fn new(kind: TopologyErrorKind) -> Self {
Self { kind, detail: None }
}
/// Attaches a description of the values that caused the failure.
///
/// 附加对该失败所涉数值的说明。
pub fn with_detail(mut self, detail: impl Into<String>) -> Self {
self.detail = Some(detail.into());
self
}
/// Returns the category of this failure.
///
/// 返回该失败的类别。
pub fn kind(&self) -> TopologyErrorKind {
self.kind
}
/// Returns the detail text attached to this error, if any.
///
/// 返回附加在该错误上的说明文本,若有。
pub fn detail(&self) -> Option<&str> {
self.detail.as_deref()
}

View File

@ -15,6 +15,8 @@ pub struct TopologySample {
impl TopologySample {
/// Creates a sample.
///
/// 创建一个样本。
pub const fn new(seconds: f64, topology: Topology) -> Self {
Self { seconds, topology }
}

View File

@ -61,6 +61,8 @@ impl ResourceError {
/// Creates an error with the given category.
///
/// 用给定类别创建一个错误。
///
/// 用给定类别创建一个错误。
pub fn new(kind: ResourceErrorKind) -> Self {
Self { kind, detail: None }
}
@ -68,6 +70,8 @@ impl ResourceError {
/// Attaches a description of the values that caused the failure.
///
/// 附加对该失败所涉数值的说明。
///
/// 附加对该失败所涉数值的说明。
pub fn with_detail(mut self, detail: impl Into<String>) -> Self {
self.detail = Some(detail.into());
self
@ -76,6 +80,8 @@ impl ResourceError {
/// Returns the category of this failure.
///
/// 返回该失败的类别。
///
/// 返回该失败的类别。
pub fn kind(&self) -> ResourceErrorKind {
self.kind
}
@ -83,6 +89,8 @@ impl ResourceError {
/// Returns the detail text attached to this error, if any.
///
/// 返回附加在该错误上的说明文本,若有。
///
/// 返回附加在该错误上的说明文本,若有。
pub fn detail(&self) -> Option<&str> {
self.detail.as_deref()
}

View File

@ -66,6 +66,8 @@ impl ScheduleError {
/// Creates an error with the given category.
///
/// 用给定类别创建一个错误。
///
/// 用给定类别创建一个错误。
pub fn new(kind: ScheduleErrorKind) -> Self {
Self { kind, detail: None }
}
@ -73,6 +75,8 @@ impl ScheduleError {
/// Attaches a description of the values that caused the failure.
///
/// 附加对该失败所涉数值的说明。
///
/// 附加对该失败所涉数值的说明。
pub fn with_detail(mut self, detail: impl Into<String>) -> Self {
self.detail = Some(detail.into());
self
@ -81,6 +85,8 @@ impl ScheduleError {
/// Returns the category of this failure.
///
/// 返回该失败的类别。
///
/// 返回该失败的类别。
pub fn kind(&self) -> ScheduleErrorKind {
self.kind
}
@ -88,6 +94,8 @@ impl ScheduleError {
/// Returns the detail text attached to this error, if any.
///
/// 返回附加在该错误上的说明文本,若有。
///
/// 返回附加在该错误上的说明文本,若有。
pub fn detail(&self) -> Option<&str> {
self.detail.as_deref()
}

View File

@ -184,6 +184,8 @@ impl Evaluation {
/// Returns `true` when every offered task was placed.
///
/// 当所有提交任务均被放置时返回 `true`。
///
/// 当所有提交任务均被放置时返回 `true`。
pub fn is_complete(&self) -> bool {
self.placed_count == self.offered_count
}

View File

@ -124,6 +124,8 @@ impl SchedulingResult {
/// Returns `true` when every offered task was placed.
///
/// 当所有提交任务均被放置时返回 `true`。
///
/// 当所有提交任务均被放置时返回 `true`。
pub fn is_complete(&self) -> bool {
self.outcomes.iter().all(PlanOutcome::is_scheduled)
}

View File

@ -76,6 +76,8 @@ impl TaskError {
/// Creates an error with the given category.
///
/// 用给定类别创建一个错误。
///
/// 用给定类别创建一个错误。
pub fn new(kind: TaskErrorKind) -> Self {
Self { kind, detail: None }
}
@ -83,6 +85,8 @@ impl TaskError {
/// Attaches a description of the values that caused the failure.
///
/// 附加对该失败所涉数值的说明。
///
/// 附加对该失败所涉数值的说明。
pub fn with_detail(mut self, detail: impl Into<String>) -> Self {
self.detail = Some(detail.into());
self
@ -91,6 +95,8 @@ impl TaskError {
/// Returns the category of this failure.
///
/// 返回该失败的类别。
///
/// 返回该失败的类别。
pub fn kind(&self) -> TaskErrorKind {
self.kind
}
@ -98,6 +104,8 @@ impl TaskError {
/// Returns the detail text attached to this error, if any.
///
/// 返回附加在该错误上的说明文本,若有。
///
/// 返回附加在该错误上的说明文本,若有。
pub fn detail(&self) -> Option<&str> {
self.detail.as_deref()
}

View File

@ -18,14 +18,20 @@ pub struct Sample {
/// The time of the sample, in seconds from the caller's origin.
///
/// 样本时刻,单位为自调用方原点起的秒数。
///
/// 样本时刻,单位为自调用方原点起的秒数。
pub seconds: f64,
/// Position, in kilometers.
///
/// 位置,单位为千米。
///
/// 位置,单位为千米。
pub position: Vec3,
/// Velocity, in kilometers per second.
///
/// 速度,单位为千米每秒。
///
/// 速度,单位为千米每秒。
pub velocity: Vec3,
}
@ -33,6 +39,8 @@ impl Sample {
/// Creates a sample.
///
/// 创建一个样本。
///
/// 创建一个样本。
pub const fn new(seconds: f64, position: Vec3, velocity: Vec3) -> Self {
Self {
seconds,

View File

@ -61,6 +61,8 @@ impl EphemerisError {
/// Creates an error with the given category.
///
/// 用给定类别创建一个错误。
///
/// 用给定类别创建一个错误。
pub fn new(kind: EphemerisErrorKind) -> Self {
Self { kind, detail: None }
}
@ -68,6 +70,8 @@ impl EphemerisError {
/// Attaches a description of the value that caused the failure.
///
/// 附加对该失败所涉数值的说明。
///
/// 附加对该失败所涉数值的说明。
pub fn with_detail(mut self, detail: impl Into<String>) -> Self {
self.detail = Some(detail.into());
self
@ -76,6 +80,8 @@ impl EphemerisError {
/// Returns the category of this failure.
///
/// 返回该失败的类别。
///
/// 返回该失败的类别。
pub const fn kind(&self) -> EphemerisErrorKind {
self.kind
}
@ -83,6 +89,8 @@ impl EphemerisError {
/// Returns the detail text attached to this error, if any.
///
/// 返回附加在该错误上的说明文本,若有。
///
/// 返回附加在该错误上的说明文本,若有。
pub fn detail(&self) -> Option<&str> {
self.detail.as_deref()
}

View File

@ -37,14 +37,20 @@ pub struct KeplerianElements {
/// Right ascension of the ascending node, in radians.
///
/// 升交点赤经,单位为弧度。
///
/// 升交点赤经,单位为弧度。
pub right_ascension: f64,
/// Argument of perigee, in radians.
///
/// 近地点幅角,单位为弧度。
///
/// 近地点幅角,单位为弧度。
pub argument_of_perigee: f64,
/// True anomaly, in radians.
///
/// 真近点角,单位为弧度。
///
/// 真近点角,单位为弧度。
pub true_anomaly: f64,
}
@ -64,10 +70,14 @@ pub struct State {
/// Position, in kilometers.
///
/// 位置,单位为千米。
///
/// 位置,单位为千米。
pub position: Vec3,
/// Velocity, in kilometers per second.
///
/// 速度,单位为千米每秒。
///
/// 速度,单位为千米每秒。
pub velocity: Vec3,
}

View File

@ -61,6 +61,8 @@ impl ManeuverError {
/// Creates an error with the given category.
///
/// 用给定类别创建一个错误。
///
/// 用给定类别创建一个错误。
pub fn new(kind: ManeuverErrorKind) -> Self {
Self { kind, detail: None }
}
@ -68,6 +70,8 @@ impl ManeuverError {
/// Attaches a description of the value that caused the failure.
///
/// 附加对该失败所涉数值的说明。
///
/// 附加对该失败所涉数值的说明。
pub fn with_detail(mut self, detail: impl Into<String>) -> Self {
self.detail = Some(detail.into());
self
@ -76,6 +80,8 @@ impl ManeuverError {
/// Returns the category of this failure.
///
/// 返回该失败的类别。
///
/// 返回该失败的类别。
pub const fn kind(&self) -> ManeuverErrorKind {
self.kind
}
@ -83,6 +89,8 @@ impl ManeuverError {
/// Returns the detail text attached to this error, if any.
///
/// 返回附加在该错误上的说明文本,若有。
///
/// 返回附加在该错误上的说明文本,若有。
pub fn detail(&self) -> Option<&str> {
self.detail.as_deref()
}

View File

@ -27,6 +27,8 @@ pub struct Orbit {
impl Orbit {
/// Prepares an orbit from a parsed element set and a gravity model.
///
/// 由已解析的根数集与重力模型准备轨道。
///
/// The gravity model must match the one the element set was fitted
/// against, which for a catalogued satellite means
/// [`GravityModel::WGS72`]. Returns `None` when the elements are not
@ -42,6 +44,8 @@ impl Orbit {
/// Prepares an orbit from a parsed element set and a gravity model.
///
/// 由已解析的根数集与重力模型准备轨道。
///
/// Returns an error describing which element is not propagatable.
///
/// 由已解析的根数集与重力模型准备轨道。

View File

@ -50,6 +50,8 @@ impl PropagationError {
/// Creates an error with the given category.
///
/// 用给定类别创建一个错误。
///
/// 用给定类别创建一个错误。
pub fn new(kind: PropagationErrorKind) -> Self {
Self { kind, detail: None }
}
@ -57,6 +59,8 @@ impl PropagationError {
/// Attaches a description of the value that caused the failure.
///
/// 附加对该失败所涉数值的说明。
///
/// 附加对该失败所涉数值的说明。
pub fn with_detail(mut self, detail: impl Into<String>) -> Self {
self.detail = Some(detail.into());
self
@ -65,6 +69,8 @@ impl PropagationError {
/// Returns the category of this failure.
///
/// 返回该失败的类别。
///
/// 返回该失败的类别。
pub fn kind(&self) -> PropagationErrorKind {
self.kind
}
@ -72,6 +78,8 @@ impl PropagationError {
/// Returns the detail text attached to this error, if any.
///
/// 返回附加在该错误上的说明文本,若有。
///
/// 返回附加在该错误上的说明文本,若有。
pub fn detail(&self) -> Option<&str> {
self.detail.as_deref()
}

View File

@ -66,22 +66,32 @@ pub struct Elements {
/// Eccentricity, dimensionless.
///
/// 偏心率,无量纲。
///
/// 偏心率,无量纲。
pub eccentricity: f64,
/// Inclination, in radians.
///
/// 倾角,单位为弧度。
///
/// 倾角,单位为弧度。
pub inclination: f64,
/// Right ascension of the ascending node, in radians.
///
/// 升交点赤经,单位为弧度。
///
/// 升交点赤经,单位为弧度。
pub right_ascension: f64,
/// Argument of perigee, in radians.
///
/// 近地点幅角,单位为弧度。
///
/// 近地点幅角,单位为弧度。
pub argument_of_perigee: f64,
/// Mean anomaly, in radians.
///
/// 平近点角,单位为弧度。
///
/// 平近点角,单位为弧度。
pub mean_anomaly: f64,
}

View File

@ -62,18 +62,26 @@ pub struct Satellite {
/// Inclination, in radians.
///
/// 倾角,单位为弧度。
///
/// 倾角,单位为弧度。
pub(crate) inclo: f64,
/// Right ascension of the ascending node, in radians.
///
/// 升交点赤经,单位为弧度。
///
/// 升交点赤经,单位为弧度。
pub(crate) nodeo: f64,
/// Argument of perigee, in radians.
///
/// 近地点幅角,单位为弧度。
///
/// 近地点幅角,单位为弧度。
pub(crate) argpo: f64,
/// Mean anomaly, in radians.
///
/// 平近点角,单位为弧度。
///
/// 平近点角,单位为弧度。
pub(crate) mo: f64,
/// `BSTAR` drag term, in inverse Earth radii.
///

View File

@ -19,10 +19,14 @@ pub struct State {
/// Position, in kilometers.
///
/// 位置,单位为千米。
///
/// 位置,单位为千米。
pub position: Vec3,
/// Velocity, in kilometers per second.
///
/// 速度,单位为千米每秒。
///
/// 速度,单位为千米每秒。
pub velocity: Vec3,
/// The propagated semi-major axis, in kilometers.
///

View File

@ -85,6 +85,8 @@ impl ElementError {
/// Attaches a description of the offending text.
///
/// 附加对有问题的文本的说明。
///
/// 附加对有问题的文本的说明。
pub fn with_detail(mut self, detail: impl Into<String>) -> Self {
self.detail = Some(detail.into());
self
@ -93,6 +95,8 @@ impl ElementError {
/// Returns the category of this failure.
///
/// 返回该失败的类别。
///
/// 返回该失败的类别。
pub fn kind(&self) -> ElementErrorKind {
self.kind
}
@ -114,6 +118,8 @@ impl ElementError {
/// Returns the detail text attached to this error, if any.
///
/// 返回附加在该错误上的说明文本,若有。
///
/// 返回附加在该错误上的说明文本,若有。
pub fn detail(&self) -> Option<&str> {
self.detail.as_deref()
}

View File

@ -32,6 +32,8 @@
use core::f64::consts::PI;
/// Converts arcseconds to radians.
///
/// 把角秒转换为弧度。
const ARCSECOND_TO_RADIAN: f64 = PI / (180.0 * 3_600.0);
/// The number of arcs in a full turn, in arcseconds.

View File

@ -28,6 +28,8 @@ use core::f64::consts::PI;
const UNIT_TO_RADIAN: f64 = 1.0e-7 * PI / (180.0 * 3_600.0);
/// Converts arcseconds to radians.
///
/// 把角秒转换为弧度。
const ARCSECOND_TO_RADIAN: f64 = PI / (180.0 * 3_600.0);
/// The nutation in longitude and obliquity, in radians.
@ -112,6 +114,8 @@ fn planetary_term(term: &PlanetaryTerm, arguments: &PlanetaryArguments) -> Nutat
/// Returns the nutation in longitude and obliquity for a time.
///
/// The time is in Julian centuries from J2000.0 on the Terrestrial Time
///
/// 时间以 J2000.0 起的儒略世纪计,位于地球时(TT)标度
/// scale. This is the IAU 2000A model, which includes the planetary terms.
///
/// Source: IAU 2000A, as implemented by `eraNut00a`.

View File

@ -21,6 +21,8 @@ use apsis_math::Mat3;
use core::f64::consts::PI;
/// Converts arcseconds to radians.
///
/// 把角秒转换为弧度。
const ARCSECOND_TO_RADIAN: f64 = PI / (180.0 * 3_600.0);
/// The frame bias in right ascension, in radians.
@ -79,6 +81,8 @@ pub fn mean_obliquity(t: f64) -> f64 {
/// Returns the four precession angles for a time.
///
/// The time is in Julian centuries from J2000.0 on the Terrestrial Time
///
/// 时间以 J2000.0 起的儒略世纪计,位于地球时(TT)标度
/// scale.
///
/// Source: the P03 precession, as implemented by `eraPfw06`.
@ -129,6 +133,8 @@ pub fn frame_bias_matrix() -> Mat3 {
/// reach the true equator and equinox of date.
///
/// The time is in Julian centuries from J2000.0 on the Terrestrial Time
///
/// 时间以 J2000.0 起的儒略世纪计,位于地球时(TT)标度
/// scale.
///
/// Source: as implemented by `eraPmat06`.

View File

@ -29,6 +29,8 @@ use apsis_math::Mat3;
use core::f64::consts::PI;
/// Converts arcseconds to radians.
///
/// 把角秒转换为弧度。
const ARCSECOND_TO_RADIAN: f64 = PI / (180.0 * 3_600.0);
/// Returns the bias-precession-nutation matrix for a time.

View File

@ -56,6 +56,8 @@ fn sidelobe_branch(diameter_over_wavelength: f64) -> (f64, f64) {
/// The expression is `20 log10(D / lambda) + 7.7`.
///
/// Returns `None` when the ratio is not positive and finite.
///
/// 比值非正或非有限时返回 `None`。
pub fn reference_peak_gain(diameter_over_wavelength: f64) -> Option<f64> {
if !diameter_over_wavelength.is_finite() || diameter_over_wavelength <= 0.0 {
return None;
@ -174,6 +176,8 @@ pub fn diameter_over_wavelength_from_peak_gain(peak_gain_dbi: f64) -> Option<f64
/// full width between the two three decibel points is twice that value.
///
/// Returns `None` when the ratio is not positive and finite.
///
/// 比值非正或非有限时返回 `None`。
pub fn reference_beam_width(diameter_over_wavelength: f64) -> Option<f64> {
if !diameter_over_wavelength.is_finite() || diameter_over_wavelength <= 0.0 {
return None;

View File

@ -853,7 +853,11 @@ impl Atmosphere {
///
/// The frequency is in gigahertz.
///
/// 频率单位为吉赫。
///
/// Returns `None` when the frequency or atmosphere is not usable.
///
/// 频率或大气不可用时返回 `None`。
pub fn specific_attenuation_dry_air(frequency_ghz: f64, atmosphere: Atmosphere) -> Option<f64> {
if !frequency_ghz.is_finite() || frequency_ghz <= 0.0 || !atmosphere.is_valid() {
return None;
@ -900,7 +904,11 @@ pub fn specific_attenuation_dry_air(frequency_ghz: f64, atmosphere: Atmosphere)
///
/// The frequency is in gigahertz.
///
/// 频率单位为吉赫。
///
/// Returns `None` when the frequency or atmosphere is not usable.
///
/// 频率或大气不可用时返回 `None`。
pub fn specific_attenuation_water_vapour(
frequency_ghz: f64,
atmosphere: Atmosphere,
@ -939,6 +947,8 @@ pub fn specific_attenuation_water_vapour(
/// This is the sum of the dry air and water vapour contributions.
///
/// Returns `None` when the frequency or atmosphere is not usable.
///
/// 频率或大气不可用时返回 `None`。
pub fn specific_attenuation(frequency_ghz: f64, atmosphere: Atmosphere) -> Option<f64> {
Some(
specific_attenuation_dry_air(frequency_ghz, atmosphere)?

View File

@ -69,8 +69,12 @@ pub struct EquivalentHeights {
///
/// The frequency is in gigahertz.
///
/// 频率单位为吉赫。
///
/// Returns `None` when the frequency or atmosphere is not usable.
///
/// 频率或大气不可用时返回 `None`。
///
/// Source: ITU-R Recommendation P.676-12, equations 30 through 38.
pub fn equivalent_heights(frequency_ghz: f64, atmosphere: Atmosphere) -> Option<EquivalentHeights> {
if !frequency_ghz.is_finite() || frequency_ghz <= 0.0 || !atmosphere.is_valid() {
@ -138,7 +142,11 @@ pub fn equivalent_heights(frequency_ghz: f64, atmosphere: Atmosphere) -> Option<
///
/// The frequency is in gigahertz.
///
/// 频率单位为吉赫。
///
/// Returns `None` when the frequency or atmosphere is not usable.
///
/// 频率或大气不可用时返回 `None`。
pub fn zenith_attenuation(frequency_ghz: f64, atmosphere: Atmosphere) -> Option<f64> {
let heights = equivalent_heights(frequency_ghz, atmosphere)?;
let dry = specific_attenuation_dry_air(frequency_ghz, atmosphere)?;

View File

@ -47,6 +47,8 @@ pub fn geopotential_height(geometric_height_km: f64) -> f64 {
/// function returns the value at 100 km.
///
/// The geometric height is in kilometers.
///
/// 几何高度单位为千米。
pub fn standard_temperature(geometric_height_km: f64) -> f64 {
let height = geopotential_height(geometric_height_km);
if height <= 11.0 {
@ -80,6 +82,8 @@ pub fn standard_temperature(geometric_height_km: f64) -> f64 {
/// segment.
///
/// The geometric height is in kilometers.
///
/// 几何高度单位为千米。
pub fn standard_pressure(geometric_height_km: f64) -> f64 {
let height = geopotential_height(geometric_height_km);
if height <= 11.0 {
@ -113,6 +117,8 @@ pub fn standard_pressure(geometric_height_km: f64) -> f64 {
/// so that the density at the surface is the value given.
///
/// The geometric height is in kilometers.
///
/// 几何高度单位为千米。
pub fn standard_water_vapour_density(geometric_height_km: f64, surface_density: f64) -> f64 {
surface_density * (-geometric_height_km / 2.0).exp()
}

View File

@ -91,6 +91,8 @@ pub fn carrier_to_interference(carrier: Power, interferers: &[Interferer]) -> Op
/// This is a convenience for the common case of one dominant interferer.
///
/// Returns `None` when either power is not positive.
///
/// 两个功率之一非正时返回 `None`。
pub fn carrier_to_interference_single(carrier: Power, interferer: Interferer) -> Option<Decibel> {
carrier_to_interference(carrier, &[interferer])
}
@ -147,6 +149,8 @@ pub fn carrier_to_noise_plus_interference(
/// zero means it must be accounted for.
///
/// Returns `None` when either power is not positive.
///
/// 两个功率之一非正时返回 `None`。
pub fn interference_to_noise_ratio(interference: Power, noise: Power) -> Option<Decibel> {
if !interference.is_valid() || !noise.is_valid() {
return None;

View File

@ -67,6 +67,8 @@ impl LinkBudget {
/// density in the direction of the receiver.
///
/// Returns `None` when any input is not usable.
///
/// 任一输入不可用时返回 `None`。
pub fn eirp(&self) -> Option<Power> {
if !self.transmit_loss.is_finite() || !self.geometry.is_valid() {
return None;
@ -79,6 +81,8 @@ impl LinkBudget {
/// Returns the carrier power at the receiver input, in watts.
///
/// Returns `None` when any input is not usable.
///
/// 任一输入不可用时返回 `None`。
pub fn received_power(&self) -> Option<Power> {
if !self.receive_loss.is_finite() {
return None;
@ -113,6 +117,8 @@ impl LinkBudget {
/// separately.
///
/// Returns `None` when any input is not usable.
///
/// 任一输入不可用时返回 `None`。
pub fn carrier_to_noise_density(&self) -> Option<Decibel> {
let carrier = self.received_power()?;
let density = self.noise_density()?;
@ -133,6 +139,8 @@ impl LinkBudget {
/// different bandwidth.
///
/// Returns `None` when any input is not usable.
///
/// 任一输入不可用时返回 `None`。
pub fn carrier_to_noise(&self) -> Option<Decibel> {
if !self.bandwidth.is_finite() || self.bandwidth <= 0.0 {
return None;

View File

@ -45,6 +45,8 @@ impl Decibel {
/// Use this for a voltage or field ratio.
///
/// Returns `None` when the ratio is not positive and finite.
///
/// 比值非正或非有限时返回 `None`。
pub fn from_amplitude_ratio(ratio: f64) -> Option<Self> {
if ratio > 0.0 && ratio.is_finite() {
Some(Self(20.0 * ratio.log10()))

View File

@ -85,6 +85,8 @@ impl Gain {
/// Returns this gain in decibels relative to an isotropic radiator.
///
/// Returns `None` when the ratio is not positive.
///
/// 比值非正时返回 `None`。
pub fn dbi(self) -> Option<f64> {
if self.0 > 0.0 && self.0.is_finite() {
Some(10.0 * self.0.log10())
@ -96,6 +98,8 @@ impl Gain {
/// Returns this gain in decibels relative to a half wave dipole.
///
/// Returns `None` when the ratio is not positive.
///
/// 比值非正时返回 `None`。
pub fn dbd(self) -> Option<f64> {
self.dbi().map(|dbi| dbi - DIPOLE_OVER_ISOTROPIC_DB)
}
@ -103,6 +107,8 @@ impl Gain {
/// Returns this gain as a ratio in decibels.
///
/// Returns `None` when the ratio is not positive.
///
/// 比值非正时返回 `None`。
pub fn as_decibel(self) -> Option<Decibel> {
Decibel::from_ratio(self.0)
}

View File

@ -101,6 +101,8 @@ impl Power {
/// between two power levels.
///
/// Returns `None` when either power is not positive.
///
/// 两个功率之一非正时返回 `None`。
pub fn ratio_in_decibels(self, rhs: Self) -> Option<Decibel> {
if self.0 > 0.0 && rhs.0 > 0.0 {
Decibel::from_ratio(self.0 / rhs.0)

View File

@ -56,6 +56,8 @@ pub struct QueueState {
impl QueueState {
/// Returns `true` when no events are pending.
///
/// 当没有待处理事件时返回 `true`。
pub const fn is_idle(&self) -> bool {
self.pending == 0
}
@ -98,6 +100,8 @@ impl<T> EventQueue<T> {
}
/// Returns `true` when no events are pending.
///
/// 当没有待处理事件时返回 `true`。
pub fn is_empty(&self) -> bool {
self.pending.is_empty()
}

View File

@ -72,6 +72,8 @@ pub struct ScenarioError {
impl ScenarioError {
/// Creates an error with the given category.
///
/// 用给定类别创建一个错误。
pub fn new(kind: ScenarioErrorKind) -> Self {
Self {
kind,
@ -81,6 +83,8 @@ impl ScenarioError {
}
/// Attaches a description of the values that caused the failure.
///
/// 附加对该失败所涉数值的说明。
pub fn with_detail(mut self, detail: impl Into<String>) -> Self {
self.detail = Some(detail.into());
self
@ -93,11 +97,15 @@ impl ScenarioError {
}
/// Returns the category of this failure.
///
/// 返回该失败的类别。
pub fn kind(&self) -> ScenarioErrorKind {
self.kind
}
/// Returns the detail text attached to this error, if any.
///
/// 返回附加在该错误上的说明文本,若有。
pub fn detail(&self) -> Option<&str> {
self.detail.as_deref()
}

View File

@ -96,6 +96,8 @@ impl<T> Engine<T> {
}
/// Returns `true` when no events are pending.
///
/// 当没有待处理事件时返回 `true`。
pub fn is_idle(&self) -> bool {
self.queue.is_empty()
}

View File

@ -113,6 +113,8 @@ pub struct EngineState {
impl EngineState {
/// Returns `true` when no events are pending.
///
/// 当没有待处理事件时返回 `true`。
pub const fn is_idle(&self) -> bool {
self.pending == 0
}

View File

@ -34,6 +34,8 @@ pub struct SimulationError {
impl SimulationError {
/// Creates an error with the given category.
///
/// 用给定类别创建一个错误。
pub fn new(kind: SimulationErrorKind) -> Self {
Self { kind, detail: None }
}
@ -45,11 +47,15 @@ impl SimulationError {
}
/// Returns the category of this failure.
///
/// 返回该失败的类别。
pub const fn kind(&self) -> SimulationErrorKind {
self.kind
}
/// Returns the detail text attached to this error, if any.
///
/// 返回附加在该错误上的说明文本,若有。
pub fn detail(&self) -> Option<&str> {
self.detail.as_deref()
}

View File

@ -141,6 +141,8 @@ impl Simulation {
}
/// Returns `true` when every offered task was placed.
///
/// 当所有提交任务均被放置时返回 `true`。
pub fn has_full_plan(&self) -> bool {
self.result.is_complete()
}