docs: bilingual comments for access, coverage, isl and routing
This completes the network layer.
This commit is contained in:
parent
295ba16d0d
commit
f3cf18df41
|
|
@ -18,6 +18,10 @@ use apsis_math::parallel::map_index;
|
|||
///
|
||||
/// The sequential form, provided for comparison and for small sets where
|
||||
/// starting a thread would cost more than the search.
|
||||
///
|
||||
/// 按次序为许多轨迹搜索可见性。
|
||||
///
|
||||
/// 顺序形式,供比较以及线程启动代价高于搜索本身的小规模情形使用。
|
||||
pub fn find_all(
|
||||
finder: &AccessFinder,
|
||||
tracks: &[Vec<OrbitSample>],
|
||||
|
|
@ -30,6 +34,11 @@ pub fn find_all(
|
|||
/// The result matches [`find_all`] element for element and in the same order.
|
||||
/// A track that cannot be searched yields its error in the same position the
|
||||
/// sequential form would put it, so one bad track does not hide the rest.
|
||||
///
|
||||
/// 跨多个线程为许多轨迹搜索可见性。
|
||||
///
|
||||
/// 结果与 [`find_all`] 逐元素、逐次序相同。无法搜索的轨迹在顺序形式会
|
||||
/// 放置它的同一位置给出其错误,故一条坏轨迹不会掩盖其余。
|
||||
pub fn find_all_parallel(
|
||||
finder: &AccessFinder,
|
||||
tracks: &[Vec<OrbitSample>],
|
||||
|
|
|
|||
|
|
@ -10,19 +10,32 @@ use core::f64::consts::PI;
|
|||
/// is visible above a given elevation mask. On a sphere it is an exact
|
||||
/// circle, described here by the central angle from the sub-satellite point
|
||||
/// and the radius of the body.
|
||||
///
|
||||
/// 圆形地面覆盖区。
|
||||
///
|
||||
/// 覆盖区是能在地平遮蔽以上看见某卫星的那部分地表。在球面上它是精确
|
||||
/// 的圆,此处以自星下点的中心角和天体半径描述。
|
||||
#[derive(Debug, Clone, Copy, PartialEq)]
|
||||
pub struct Footprint {
|
||||
/// The central half angle of the footprint, in radians.
|
||||
///
|
||||
/// This is the angle at the centre of the Earth from the sub-satellite
|
||||
/// point to the edge of the footprint.
|
||||
///
|
||||
/// 覆盖区的中心半角,单位为弧度。
|
||||
///
|
||||
/// 这是在地心处自星下点到覆盖区边缘的角度。
|
||||
pub central_angle: f64,
|
||||
/// The radius of the body, in kilometers.
|
||||
///
|
||||
/// 天体的半径,单位为千米。
|
||||
pub body_radius: f64,
|
||||
}
|
||||
|
||||
impl Footprint {
|
||||
/// Creates a footprint from its central angle and body radius.
|
||||
///
|
||||
/// 由其中心角与天体半径创建覆盖区。
|
||||
pub const fn new(central_angle: f64, body_radius: f64) -> Self {
|
||||
Self {
|
||||
central_angle,
|
||||
|
|
@ -32,6 +45,8 @@ impl Footprint {
|
|||
|
||||
/// Returns the footprint radius measured along the surface, in
|
||||
/// kilometers.
|
||||
///
|
||||
/// 返回沿地表量得的覆盖区半径,单位为千米。
|
||||
pub fn surface_radius(&self) -> f64 {
|
||||
self.central_angle * self.body_radius
|
||||
}
|
||||
|
|
@ -45,6 +60,16 @@ impl Footprint {
|
|||
/// ```
|
||||
///
|
||||
/// which is exact for a spherical body.
|
||||
///
|
||||
/// 返回覆盖区的面积,单位为平方千米。
|
||||
///
|
||||
/// 该面积是被圆锥截去的球面部分,
|
||||
///
|
||||
/// ```text
|
||||
/// A = 2 pi R^2 (1 - cos(central))
|
||||
/// ```
|
||||
///
|
||||
/// 对球形天体这是精确的。
|
||||
pub fn area(&self) -> f64 {
|
||||
2.0 * PI * self.body_radius * self.body_radius * (1.0 - self.central_angle.cos())
|
||||
}
|
||||
|
|
@ -53,6 +78,11 @@ impl Footprint {
|
|||
///
|
||||
/// The value is between zero and one half, because a footprint from a
|
||||
/// point above the surface can never cover more than a hemisphere.
|
||||
///
|
||||
/// 返回覆盖区占整个球面的比例。
|
||||
///
|
||||
/// 该值介于零与二分之一之间,因为来自地表之上某点的覆盖区覆盖范围
|
||||
/// 绝不会超过一个半球。
|
||||
pub fn fraction_of_surface(&self) -> f64 {
|
||||
self.area() / (4.0 * PI * self.body_radius * self.body_radius)
|
||||
}
|
||||
|
|
@ -62,6 +92,10 @@ impl Footprint {
|
|||
///
|
||||
/// The comparison is inclusive, so a point exactly on the edge is
|
||||
/// inside.
|
||||
///
|
||||
/// 当距星下点给定中心角的地面点位于覆盖区内时返回 `true`。
|
||||
///
|
||||
/// 比较是含端点的,故恰在边缘上的点算在内部。
|
||||
pub fn contains_central_angle(&self, central_angle: f64) -> bool {
|
||||
central_angle.is_finite() && central_angle >= 0.0 && central_angle <= self.central_angle
|
||||
}
|
||||
|
|
@ -136,6 +170,13 @@ pub fn footprint_fraction(
|
|||
///
|
||||
/// Returns `None` when either vector has zero length or a non-finite
|
||||
/// component.
|
||||
///
|
||||
/// 返回两个地表点之间的角度,单位为弧度。
|
||||
///
|
||||
/// 两矢量必须是相对天体中心、在同一坐标系中的位置。该角度是自中心看
|
||||
/// 它们之间的中心角。
|
||||
///
|
||||
/// 任一矢量为零长或含非有限分量时返回 `None`。
|
||||
pub fn central_angle_between(first: Vec3, second: Vec3) -> Option<f64> {
|
||||
if !first.is_finite() || !second.is_finite() {
|
||||
return None;
|
||||
|
|
@ -159,6 +200,13 @@ pub fn central_angle_between(first: Vec3, second: Vec3) -> Option<f64> {
|
|||
/// and the central half angle.
|
||||
///
|
||||
/// Returns `None` when either vector is degenerate or not finite.
|
||||
///
|
||||
/// 当某地面点位于某覆盖区内时返回 `true`。
|
||||
///
|
||||
/// 该点与星下点都是相对天体中心的位置,单位为千米。覆盖区提供天体半径
|
||||
/// 与中心半角。
|
||||
///
|
||||
/// 任一矢量退化或非有限时返回 `None`。
|
||||
pub fn point_in_footprint(
|
||||
footprint: &Footprint,
|
||||
point: Vec3,
|
||||
|
|
|
|||
|
|
@ -37,6 +37,13 @@ use core::f64::consts::FRAC_PI_2;
|
|||
///
|
||||
/// Returns `None` when the radii are not usable, when the body radius
|
||||
/// exceeds the satellite radius, or when the elevation is not finite.
|
||||
///
|
||||
/// 返回卫星处的天底角,单位为弧度。
|
||||
///
|
||||
/// 天底角在卫星处量取,介于到地心的方向与到地面点的方向之间。当地面点
|
||||
/// 恰在卫星正下方时它为零,并随该点移向地平而增大。
|
||||
///
|
||||
/// 半径不可用、天体半径超过卫星半径,或仰角非有限时返回 `None`。
|
||||
pub fn nadir_angle(satellite_radius: f64, body_radius: f64, elevation: f64) -> Option<f64> {
|
||||
if !satellite_radius.is_finite() || !body_radius.is_finite() || !elevation.is_finite() {
|
||||
return None;
|
||||
|
|
@ -46,6 +53,7 @@ pub fn nadir_angle(satellite_radius: f64, body_radius: f64, elevation: f64) -> O
|
|||
}
|
||||
let sine = body_radius * elevation.cos() / satellite_radius;
|
||||
// Rounding can push the sine a little above one for a grazing geometry.
|
||||
// 对掠射几何,舍入可能把正弦略微推到一以上。
|
||||
Some(sine.clamp(-1.0, 1.0).asin())
|
||||
}
|
||||
|
||||
|
|
@ -64,6 +72,8 @@ pub fn earth_central_angle(satellite_radius: f64, body_radius: f64, elevation: f
|
|||
// Rounding can leave a small negative value at the zenith, where the
|
||||
// true angle is zero. The negative part is not physical, so it is
|
||||
// removed before the result is returned.
|
||||
// 在天顶处(真实角为零)舍入可能留下小的负值。该负值没有物理意义,
|
||||
// 故在返回结果前将其去掉。
|
||||
Some((FRAC_PI_2 - elevation - nadir).max(0.0))
|
||||
}
|
||||
|
||||
|
|
@ -118,6 +128,20 @@ pub fn slant_range(satellite_radius: f64, body_radius: f64, elevation: f64) -> O
|
|||
///
|
||||
/// Returns `None` when the radii are not usable or when the central angle is
|
||||
/// not finite.
|
||||
///
|
||||
/// 返回某中心角对应的仰角,单位为弧度。
|
||||
///
|
||||
/// 它反解 [`earth_central_angle`]。当已知地面点相对星下点的位置而要求
|
||||
/// 该点处仰角时使用它。
|
||||
///
|
||||
/// 关系为
|
||||
///
|
||||
/// ```text
|
||||
/// tan(elevation) = (cos(central) - body_radius / satellite_radius)
|
||||
/// / sin(central)
|
||||
/// ```
|
||||
///
|
||||
/// 半径不可用或中心角非有限时返回 `None`。
|
||||
pub fn elevation_from_central_angle(
|
||||
satellite_radius: f64,
|
||||
body_radius: f64,
|
||||
|
|
@ -133,6 +157,7 @@ pub fn elevation_from_central_angle(
|
|||
let sine = central_angle.sin();
|
||||
if sine == 0.0 {
|
||||
// Directly below the satellite the elevation is a right angle.
|
||||
// 在卫星正下方仰角为直角。
|
||||
return Some(FRAC_PI_2);
|
||||
}
|
||||
Some(((central_angle.cos() - ratio) / sine).atan())
|
||||
|
|
|
|||
|
|
@ -6,22 +6,39 @@ use apsis_math::Vec3;
|
|||
use core::f64::consts::FRAC_PI_2;
|
||||
|
||||
/// A ground station, given as a geodetic position on an ellipsoid.
|
||||
///
|
||||
/// 一个地面站,以椭球上的大地位置给出。
|
||||
#[derive(Debug, Clone, Copy, PartialEq)]
|
||||
pub struct GroundPoint {
|
||||
/// The geodetic position of the station.
|
||||
///
|
||||
/// 该站的大地位置。
|
||||
pub position: Geodetic,
|
||||
/// The ellipsoid the position is referred to.
|
||||
///
|
||||
/// 该位置所参照的椭球。
|
||||
///
|
||||
/// 该位置所参照的椭球。
|
||||
///
|
||||
/// 该位置所参照的椭球。
|
||||
pub ellipsoid: Ellipsoid,
|
||||
/// The sensor elevation mask, in radians.
|
||||
///
|
||||
/// The minimum elevation above the local horizon at which the station
|
||||
/// can see a satellite. A mask of zero means the station sees down to
|
||||
/// its own horizon.
|
||||
///
|
||||
/// 传感器仰角遮蔽,单位为弧度。
|
||||
///
|
||||
/// 该站能看到卫星所需高出当地地平的最小仰角。遮蔽为零意味着该站
|
||||
/// 能看到直至自身地平。
|
||||
pub elevation_mask: f64,
|
||||
}
|
||||
|
||||
impl GroundPoint {
|
||||
/// Creates a ground point on the WGS 84 ellipsoid with a given mask.
|
||||
///
|
||||
/// 在 WGS 84 椭球上以给定遮蔽创建地面点。
|
||||
pub fn new(position: Geodetic, elevation_mask: f64) -> Self {
|
||||
Self {
|
||||
position,
|
||||
|
|
@ -35,6 +52,11 @@ impl GroundPoint {
|
|||
///
|
||||
/// The geodetic conversion yields meters, so the result is divided by a
|
||||
/// thousand to match the frame the orbit layer uses.
|
||||
///
|
||||
/// 返回该站在地固直角坐标系中的位置,单位为千米。
|
||||
///
|
||||
/// 大地转换得到的是米,故结果除以一千,以与 orbit 层所用的坐标系
|
||||
/// 一致。
|
||||
pub fn ecef(&self) -> Vec3 {
|
||||
self.position.to_cartesian(self.ellipsoid) / 1_000.0
|
||||
}
|
||||
|
|
@ -43,12 +65,18 @@ impl GroundPoint {
|
|||
///
|
||||
/// This is the local radius of the ellipsoid at the station's latitude
|
||||
/// plus its height, so it includes the effect of the flattening.
|
||||
///
|
||||
/// 返回距地心的距离,单位为千米。
|
||||
///
|
||||
/// 这是该站纬度处椭球的当地半径加上其高度,故包含了扁率的影响。
|
||||
pub fn radius(&self) -> f64 {
|
||||
self.ecef().norm()
|
||||
}
|
||||
|
||||
/// Returns `true` when the station and its mask describe a usable
|
||||
/// sensor.
|
||||
///
|
||||
/// 当该站及其遮蔽描述一个可用传感器时返回 `true`。
|
||||
pub fn is_valid(&self) -> bool {
|
||||
self.position.is_valid()
|
||||
&& self.elevation_mask.is_finite()
|
||||
|
|
@ -63,17 +91,28 @@ impl GroundPoint {
|
|||
/// because a station that can point anywhere with sufficient gain is
|
||||
/// modelled by its elevation mask alone; the direction matters only when the
|
||||
/// station has a fixed beam.
|
||||
///
|
||||
/// 位于地面点、具有指向方向的传感器。
|
||||
///
|
||||
/// 方向是地固系中的单位矢量。它是可选的,因为能以足够增益指向任何
|
||||
/// 方向的站仅以其仰角遮蔽建模即可;只有当站具有固定波束时方向才要紧。
|
||||
#[derive(Debug, Clone, Copy, PartialEq)]
|
||||
pub struct Sensor {
|
||||
/// The station.
|
||||
///
|
||||
/// 该地面站。
|
||||
pub ground: GroundPoint,
|
||||
/// The pointing direction in the Earth-fixed frame, if the station is
|
||||
/// directional.
|
||||
///
|
||||
/// 地固系中的指向方向,若该站是定向的。
|
||||
pub pointing: Option<Vec3>,
|
||||
}
|
||||
|
||||
impl Sensor {
|
||||
/// Creates a station that can point anywhere above its mask.
|
||||
///
|
||||
/// 创建能在其遮蔽之上指向任何方向的站。
|
||||
pub const fn omnidirectional(ground: GroundPoint) -> Self {
|
||||
Self {
|
||||
ground,
|
||||
|
|
@ -85,6 +124,10 @@ impl Sensor {
|
|||
///
|
||||
/// The direction is normalized when it is used, so the caller may pass
|
||||
/// an unnormalized vector.
|
||||
///
|
||||
/// 创建具有固定指向方向的站。
|
||||
///
|
||||
/// 该方向在使用时被归一化,故调用方可以传入未归一化的矢量。
|
||||
pub const fn directional(ground: GroundPoint, pointing: Vec3) -> Self {
|
||||
Self {
|
||||
ground,
|
||||
|
|
@ -94,11 +137,17 @@ impl Sensor {
|
|||
}
|
||||
|
||||
/// The point on the Earth's surface directly below a satellite.
|
||||
///
|
||||
/// 卫星正下方的地表点。
|
||||
#[derive(Debug, Clone, Copy, PartialEq)]
|
||||
pub struct SubSatellitePoint {
|
||||
/// The geodetic position of the sub-satellite point.
|
||||
///
|
||||
/// 星下点的大地位置。
|
||||
pub position: Geodetic,
|
||||
/// The ellipsoid the position is referred to.
|
||||
///
|
||||
/// 该位置所参照的椭球。
|
||||
pub ellipsoid: Ellipsoid,
|
||||
}
|
||||
|
||||
|
|
@ -116,6 +165,16 @@ pub struct SubSatellitePoint {
|
|||
///
|
||||
/// Returns `None` when the position is not finite or lies on the polar axis,
|
||||
/// where no longitude is defined.
|
||||
///
|
||||
/// 返回地固系中某位置的星下点。
|
||||
///
|
||||
/// 卫星位置单位为千米。星下点是从地心过卫星的直线与椭球的交点,即把
|
||||
/// 卫星高度置零而纬经度不变所得的大地位置。
|
||||
///
|
||||
/// 这是地心投影,而非过卫星的椭球法线与地表相交的点。对低轨卫星两者
|
||||
/// 相差至多约二十千米,而覆盖区几何用的是地心形式。
|
||||
///
|
||||
/// 位置非有限,或位于未定义经度的极轴上时返回 `None`。
|
||||
pub fn sub_satellite_point(
|
||||
position_ecef_km: Vec3,
|
||||
ellipsoid: Ellipsoid,
|
||||
|
|
@ -142,6 +201,15 @@ pub fn sub_satellite_point(
|
|||
/// below the horizon.
|
||||
///
|
||||
/// Returns `None` when either position is not usable.
|
||||
///
|
||||
/// 返回自某站看某卫星的仰角,单位为弧度。
|
||||
///
|
||||
/// 卫星位置在地固系中,单位为千米。仰角自当地地平量起,后者是垂直于该
|
||||
/// 站处椭球法线的平面。
|
||||
///
|
||||
/// 正值表示卫星在地平之上,直角值表示在天顶,负值表示在地平之下。
|
||||
///
|
||||
/// 任一位置不可用时返回 `None`。
|
||||
pub fn elevation_angle(satellite_ecef_km: Vec3, ground: &GroundPoint) -> Option<f64> {
|
||||
if !satellite_ecef_km.is_finite() || !ground.is_valid() {
|
||||
return None;
|
||||
|
|
@ -153,6 +221,8 @@ pub fn elevation_angle(satellite_ecef_km: Vec3, ground: &GroundPoint) -> Option<
|
|||
}
|
||||
// The local up direction is the ellipsoid normal at the station, which
|
||||
// for a geodetic position is the direction the surface normal points.
|
||||
// 当地朝上方向是该站处的椭球法线,对大地位置而言即地表法线所指的
|
||||
// 方向。
|
||||
let up = local_up(ground);
|
||||
let sine = line_of_sight.normalize()?.dot(up.normalize()?);
|
||||
Some(sine.clamp(-1.0, 1.0).asin())
|
||||
|
|
@ -164,6 +234,11 @@ pub fn elevation_angle(satellite_ecef_km: Vec3, ground: &GroundPoint) -> Option<
|
|||
/// geodetic position it follows from the latitude and longitude, because the
|
||||
/// normal of a biaxial ellipsoid lies in the meridian plane and makes the
|
||||
/// geodetic latitude with the equatorial plane.
|
||||
///
|
||||
/// 返回沿某站处椭球法线的单位矢量。
|
||||
///
|
||||
/// 这是当地垂线,即铅垂线所指的方向。对大地位置而言,它由纬度与经度
|
||||
/// 得出,因为双轴椭球的法线位于子午面内,并与赤道面夹大地纬度。
|
||||
pub fn local_up(ground: &GroundPoint) -> Vec3 {
|
||||
let latitude = ground.position.latitude;
|
||||
let longitude = ground.position.longitude;
|
||||
|
|
@ -182,6 +257,12 @@ pub fn local_up(ground: &GroundPoint) -> Vec3 {
|
|||
/// other visibility functions.
|
||||
///
|
||||
/// Returns `None` when either position is not usable.
|
||||
///
|
||||
/// 返回自某站看某卫星的仰角,单位为弧度。
|
||||
///
|
||||
/// 这与 [`elevation_angle`] 相同,其命名是为与其余可见性函数对称。
|
||||
///
|
||||
/// 任一位置不可用时返回 `None`。
|
||||
pub fn line_of_sight(satellite_ecef_km: Vec3, ground: &GroundPoint) -> Option<f64> {
|
||||
elevation_angle(satellite_ecef_km, ground)
|
||||
}
|
||||
|
|
@ -194,6 +275,14 @@ pub fn line_of_sight(satellite_ecef_km: Vec3, ground: &GroundPoint) -> Option<f6
|
|||
/// the satellite is in the forward hemisphere of the beam.
|
||||
///
|
||||
/// Returns `None` when the satellite position or the sensor is not usable.
|
||||
///
|
||||
/// 当从某传感器可见某卫星时返回 `true`。
|
||||
///
|
||||
/// 当卫星在该站处的仰角不低于该传感器的遮蔽,且(对定向传感器)到卫星
|
||||
/// 的方向与指向方向的夹角在一个直角以内,即卫星处于波束的前半球时,
|
||||
/// 卫星可见。
|
||||
///
|
||||
/// 卫星位置或传感器不可用时返回 `None`。
|
||||
pub fn visible_from(satellite_ecef_km: Vec3, sensor: &Sensor) -> Option<bool> {
|
||||
let elevation = elevation_angle(satellite_ecef_km, &sensor.ground)?;
|
||||
if elevation < sensor.ground.elevation_mask {
|
||||
|
|
@ -216,6 +305,13 @@ pub fn visible_from(satellite_ecef_km: Vec3, sensor: &Sensor) -> Option<bool> {
|
|||
/// position, without building a [`GroundPoint`].
|
||||
///
|
||||
/// Returns `None` when the satellite position or the station is not usable.
|
||||
///
|
||||
/// 返回自某大地站看某卫星的仰角。
|
||||
///
|
||||
/// 这是为直接把站作为大地位置给出、而不构建 [`GroundPoint`] 的便利
|
||||
/// 函数。
|
||||
///
|
||||
/// 卫星位置或该站不可用时返回 `None`。
|
||||
pub fn visible_from_geodetic(
|
||||
satellite_ecef_km: Vec3,
|
||||
position: Geodetic,
|
||||
|
|
|
|||
|
|
@ -61,6 +61,8 @@ pub fn visibility_matrix_parallel(positions: &[Vec3], body_radius: f64) -> Vec<b
|
|||
// The pairs are independent, so splitting the flat index space across
|
||||
// threads needs no coordination. `map_index` owns the output buffer,
|
||||
// which is what lets the threads write disjoint slots of one allocation.
|
||||
// 各点对相互独立,故把扁平下标空间跨线程划分无需协调。`map_index`
|
||||
// 拥有输出缓冲,这正是让各线程写同一分配中互不相交槽位的原因。
|
||||
map_index(len * len, |index| {
|
||||
let row = index / len;
|
||||
let column = index - row * len;
|
||||
|
|
|
|||
|
|
@ -28,11 +28,13 @@ pub fn closest_approach_to_centre(first: Vec3, second: Vec3) -> Option<f64> {
|
|||
if length_squared == 0.0 {
|
||||
// The two points coincide, so the distance is the radius of that
|
||||
// point.
|
||||
// 两点重合,故距离即该点的半径。
|
||||
return Some(first.norm());
|
||||
}
|
||||
|
||||
// The parameter of the closest point on the infinite line, clamped to
|
||||
// the segment.
|
||||
// 无限直线上最接近点的参数,被夹逼到该线段。
|
||||
let parameter = (-first.dot(segment) / length_squared).clamp(0.0, 1.0);
|
||||
let closest = first + segment * parameter;
|
||||
Some(closest.norm())
|
||||
|
|
|
|||
|
|
@ -71,6 +71,7 @@ pub fn edge_connectivity(topology: &Topology, source: usize, destination: usize)
|
|||
}
|
||||
|
||||
// A residual capacity for each edge, indexed by the edge position.
|
||||
// 每条边一个残余容量,按边的位置索引。
|
||||
let edges = topology.edges();
|
||||
let mut residual: Vec<usize> = vec![1; edges.len()];
|
||||
|
||||
|
|
@ -78,6 +79,7 @@ pub fn edge_connectivity(topology: &Topology, source: usize, destination: usize)
|
|||
loop {
|
||||
// Breadth first search for an augmenting path in the residual
|
||||
// graph.
|
||||
// 在残余图中广度优先搜索一条增广路径。
|
||||
let mut parent_edge: Vec<Option<usize>> = vec![None; topology.node_count()];
|
||||
let mut visited = vec![false; topology.node_count()];
|
||||
visited[source] = true;
|
||||
|
|
@ -90,6 +92,7 @@ pub fn edge_connectivity(topology: &Topology, source: usize, destination: usize)
|
|||
}
|
||||
for (index, edge) in edges.iter().enumerate() {
|
||||
// Forward edges with residual capacity.
|
||||
// 具有残余容量的正向边。
|
||||
if edge.from == node && residual[index] > 0 && !visited[edge.to] {
|
||||
visited[edge.to] = true;
|
||||
parent_edge[edge.to] = Some(index);
|
||||
|
|
@ -98,6 +101,7 @@ pub fn edge_connectivity(topology: &Topology, source: usize, destination: usize)
|
|||
}
|
||||
// Reverse edges, which exist when flow has been pushed the
|
||||
// other way and which cancel it.
|
||||
// 反向边,当流量已沿另一方向推送时存在,用以抵消它。
|
||||
if edge.to == node && residual[index] == 0 && !visited[edge.from] {
|
||||
visited[edge.from] = true;
|
||||
parent_edge[edge.from] = Some(index);
|
||||
|
|
@ -113,6 +117,8 @@ pub fn edge_connectivity(topology: &Topology, source: usize, destination: usize)
|
|||
// Walk the path back, adjusting the residual capacities. An edge
|
||||
// traversed in its own direction consumes one unit; an edge
|
||||
// traversed against its direction restores one.
|
||||
// 沿路径回溯,调整残余容量。沿自身方向穿越的边消耗一个单位;
|
||||
// 逆自身方向穿越的边恢复一个单位。
|
||||
let mut node = destination;
|
||||
while node != source {
|
||||
let index = parent_edge[node]?;
|
||||
|
|
@ -163,6 +169,7 @@ pub fn strongly_connected_components(topology: &Topology) -> usize {
|
|||
}
|
||||
|
||||
// First pass: the finishing order over the forward edges.
|
||||
// 第一遍:在正向边上求完成次序。
|
||||
let mut visited = vec![false; node_count];
|
||||
let mut order = Vec::with_capacity(node_count);
|
||||
for start in 0..node_count {
|
||||
|
|
@ -171,6 +178,7 @@ pub fn strongly_connected_components(topology: &Topology) -> usize {
|
|||
}
|
||||
// An iterative depth first search, pushing a node again to mark the
|
||||
// point at which its children are done.
|
||||
// 迭代式深度优先搜索,把某节点再次压栈以标记其子节点完成之处。
|
||||
let mut stack = vec![(start, false)];
|
||||
while let Some((node, processed)) = stack.pop() {
|
||||
if processed {
|
||||
|
|
@ -192,6 +200,7 @@ pub fn strongly_connected_components(topology: &Topology) -> usize {
|
|||
|
||||
// Second pass: the reverse edges, taking nodes in reverse finishing
|
||||
// order.
|
||||
// 第二遍:在反向边上按完成次序的逆序取节点。
|
||||
let mut assigned = vec![false; node_count];
|
||||
let mut components = 0;
|
||||
for node in order.into_iter().rev() {
|
||||
|
|
|
|||
|
|
@ -242,6 +242,23 @@ pub fn shortest_path(
|
|||
/// the one described in Fraire, J. A. et al., *Routing in Delay-Tolerant
|
||||
/// Networks Comprising Heterogeneous Populations of Deterministic Link
|
||||
/// Dynamics*, IEEE Transactions on Mobile Computing, 2020.
|
||||
///
|
||||
/// 返回在拓扑序列某区间上有效的最短路由。
|
||||
///
|
||||
/// 该路由在贯穿整个区间都存在的链路上计算,故它在整个区间上保持有效。
|
||||
/// 该区间取自 `start_seconds` 处生效样本的起点,到 `end_seconds` 处生效
|
||||
/// 样本的起点,并对该跨度内每个样本的链路求交。
|
||||
///
|
||||
/// 所返回的路段记录该路由有效的区间,它以 `end_seconds` 之后的下一处
|
||||
/// 拓扑变化为界。
|
||||
///
|
||||
/// 任一节点越界或两者相同、区间次序不对,或没有路由能存活整个区间时
|
||||
/// 返回错误。
|
||||
///
|
||||
/// 出处:时变图上的存储转发路由模型见 Fraire, J. A. 等,*Routing in
|
||||
/// Delay-Tolerant Networks Comprising Heterogeneous Populations of
|
||||
/// Deterministic Link Dynamics*,IEEE Transactions on Mobile Computing,
|
||||
/// 2020。
|
||||
pub fn route_over_series(
|
||||
series: &TopologySeries,
|
||||
source: usize,
|
||||
|
|
@ -284,6 +301,8 @@ pub fn route_over_series(
|
|||
|
||||
// Intersect the links of every sample spanned by the interval, taking
|
||||
// the cost from the first sample that has each link.
|
||||
// 对该区间所跨的每个样本的链路求交,代价取自拥有每条链路的第一
|
||||
// 个样本。
|
||||
let mut intersection = Topology::new(series.node_count());
|
||||
let reference = &series.samples()[first].topology;
|
||||
for edge in reference.edges() {
|
||||
|
|
@ -302,6 +321,7 @@ pub fn route_over_series(
|
|||
let route = shortest_path(&intersection, source, destination)?;
|
||||
|
||||
// The leg is valid until the topology changes after the interval ends.
|
||||
// 该路段有效直到区间结束之后的拓扑变化。
|
||||
let end_of_validity = series
|
||||
.interval_of(last)
|
||||
.map_or(end_seconds, |(_, next)| next);
|
||||
|
|
|
|||
Loading…
Reference in New Issue