use crate::area::AreaKm2;
use crate::geo::{BoundingBox, OutletCoord, WkbGeometry};
use crate::id::UnitId;
use crate::level::Level;
#[derive(Debug, Clone, PartialEq)]
pub struct CatchmentUnit {
id: UnitId,
level: Level,
parent_id: Option<UnitId>,
area: AreaKm2,
upstream_area: Option<AreaKm2>,
outlet: OutletCoord,
bbox: BoundingBox,
geometry: WkbGeometry,
source_id: Option<String>,
level_label: Option<String>,
}
impl CatchmentUnit {
#[allow(clippy::too_many_arguments)]
pub fn new(
id: UnitId,
level: Level,
parent_id: Option<UnitId>,
area: AreaKm2,
upstream_area: Option<AreaKm2>,
outlet: OutletCoord,
bbox: BoundingBox,
geometry: WkbGeometry,
source_id: Option<String>,
level_label: Option<String>,
) -> Self {
Self {
id,
level,
parent_id,
area,
upstream_area,
outlet,
bbox,
geometry,
source_id,
level_label,
}
}
pub fn id(&self) -> UnitId {
self.id
}
pub fn level(&self) -> Level {
self.level
}
pub fn parent_id(&self) -> Option<UnitId> {
self.parent_id
}
pub fn area(&self) -> AreaKm2 {
self.area
}
pub fn upstream_area(&self) -> Option<AreaKm2> {
self.upstream_area
}
pub fn outlet(&self) -> OutletCoord {
self.outlet
}
pub fn bbox(&self) -> &BoundingBox {
&self.bbox
}
pub fn geometry(&self) -> &WkbGeometry {
&self.geometry
}
pub fn source_id(&self) -> Option<&str> {
self.source_id.as_deref()
}
pub fn level_label(&self) -> Option<&str> {
self.level_label.as_deref()
}
}
#[cfg(test)]
mod tests {
use super::*;
fn test_unit_id(raw: i64) -> UnitId {
UnitId::new(raw).unwrap()
}
fn test_level(raw: i16) -> Level {
Level::new(raw).unwrap()
}
fn test_outlet() -> OutletCoord {
OutletCoord::new(0.0, 0.0).unwrap()
}
fn test_bbox() -> BoundingBox {
BoundingBox::new(-10.0, -5.0, 10.0, 5.0).unwrap()
}
fn test_wkb() -> WkbGeometry {
WkbGeometry::new(vec![0x01, 0x02, 0x03]).unwrap()
}
fn test_area(km2: f32) -> AreaKm2 {
AreaKm2::new(km2).unwrap()
}
#[test]
fn valid_catchment_unit_getters_return_expected_values() {
let id = test_unit_id(42);
let level = test_level(1);
let parent_id = Some(test_unit_id(7));
let area = test_area(100.0);
let upstream_area = Some(test_area(500.0));
let outlet = test_outlet();
let bbox = test_bbox();
let geometry = test_wkb();
let unit = CatchmentUnit::new(
id,
level,
parent_id,
area,
upstream_area,
outlet,
bbox,
geometry.clone(),
Some("src-42".to_string()),
Some("l1".to_string()),
);
assert_eq!(unit.id(), id);
assert_eq!(unit.level(), level);
assert_eq!(unit.parent_id(), parent_id);
assert_eq!(unit.area(), area);
assert_eq!(unit.upstream_area(), upstream_area);
assert_eq!(unit.outlet(), outlet);
assert_eq!(unit.bbox(), &bbox);
assert_eq!(unit.geometry(), &geometry);
assert_eq!(unit.source_id(), Some("src-42"));
assert_eq!(unit.level_label(), Some("l1"));
}
#[test]
fn upstream_area_none_returns_none() {
let unit = CatchmentUnit::new(
test_unit_id(1),
test_level(0),
None,
test_area(50.0),
None,
test_outlet(),
test_bbox(),
test_wkb(),
None,
None,
);
assert_eq!(unit.upstream_area(), None);
}
#[test]
fn upstream_area_some_returns_some() {
let up_area = test_area(999.9);
let unit = CatchmentUnit::new(
test_unit_id(1),
test_level(0),
None,
test_area(50.0),
Some(up_area),
test_outlet(),
test_bbox(),
test_wkb(),
None,
None,
);
assert_eq!(unit.upstream_area(), Some(up_area));
}
}