Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 7 additions & 1 deletion .github/workflows/ci.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -38,10 +38,16 @@ jobs:
sudo apt-get update -y
sudo apt-get install libgdal-dev gdal-bin
- uses: Swatinem/rust-cache@v2
- name: Install cargo-nextest
uses: taiki-e/install-action@nextest
- name: Build
run: cargo build --verbose --all
- name: Run tests
run: cargo test
run: cargo nextest run
- name: Install wasm-pack
uses: taiki-e/install-action@wasm-pack
- name: Build WASM
run: wasm-pack build --target web crates/viewshed-reconstructor

e2e:
name: End to end tests
Expand Down
81 changes: 68 additions & 13 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

9 changes: 9 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,16 @@ resolver = "2"
members = [
"crates/total-viewsheds",
"crates/tvs-lib",
"crates/viewshed-reconstructor",
]

[workspace.dependencies]
color-eyre = "0.6.5"
geo = "0.31.0"
serde = "1.0.219"
serde_json = "1.0.143"
tracing = { version = "0.1.41" }
tracing-subscriber = { version = "0.3.19", features = ["env-filter"] }

# Canonical lints for whole crate
#
Expand All @@ -24,6 +27,7 @@ serde_json = "1.0.143"
[workspace.lints.rust]
# It's always good to write as much documentation as possible
missing_docs = "warn"
unreachable_pub = "warn"

[workspace.lints.clippy]
# `clippy::all` is already on by default. It implies the following:
Expand Down Expand Up @@ -93,3 +97,8 @@ multiple_unsafe_ops_per_block = "allow"

# i dont write docs with punctuation but you can still tell what im saying
doc_paragraphs_missing_punctuation = "allow"

# Along with `unreachable_pub = "warn"` this enforces the practice of explicitly defining visibility.
# Therefore, if a symbol isn't truly public to the outside world then it should be qualified with
# `pub(crate)`, `pub(super)`, etc.
redundant_pub_crate = "allow"
2 changes: 1 addition & 1 deletion benchmarks/cardiff-viewshed.json

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion benchmarks/run.sh
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
set -e

export RUST_BACKTRACE=1
export RUST_LOG=trace
export RUST_LOG=debug

PROJECT_ROOT="$(cd "$(dirname "$0")/.." && pwd -P)"

Expand Down
5 changes: 3 additions & 2 deletions crates/total-viewsheds/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,10 @@ memchr = "2.8.0"
serde_json.workspace = true
rusqlite = { version = "0.38.0", features = ["bundled"] }
rayon = "1.12.0"
tracing = { version = "0.1.41" }
tracing-subscriber = { version = "0.3.19", features = ["env-filter"] }
tracing.workspace = true
tracing-subscriber.workspace = true
tvs-lib = { path = "../tvs-lib", version = "0.1.0" }
viewshed-reconstructor = { path = "../viewshed-reconstructor", version = "0.1.0" }

[dev-dependencies]
tempfile = "3.20.0"
Expand Down
10 changes: 5 additions & 5 deletions crates/total-viewsheds/src/compute/area_of_interest.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ use color_eyre::Result;
use geo::Contains as _;

/// `Pruner`
pub struct Pruner {
pub(crate) struct Pruner {
/// Width of the DEM in points
width: u32,
/// The DEM coordinates for the Area of Interest.
Expand All @@ -14,12 +14,12 @@ pub struct Pruner {

impl Pruner {
/// Instantiate.
pub const fn new(width: u32, polygon: geo::Polygon) -> Self {
pub(crate) const fn new(width: u32, polygon: geo::Polygon) -> Self {
Self { width, polygon }
}

/// Convert user-provided lon/lat coordinates to a polygon.
pub fn lonlat_coords_to_polygon(
pub(crate) fn lonlat_coords_to_polygon(
points: Vec<(f32, f32)>,
metadata: &tvs_lib::metadata::MetaData,
) -> Result<geo::Polygon> {
Expand All @@ -41,7 +41,7 @@ impl Pruner {
}

/// Can the given DEM ID be ignored in computations.
pub fn is_prunable(&self, dem_id: i64) -> bool {
pub(crate) fn is_prunable(&self, dem_id: i64) -> bool {
let dem_coord = self.convert_dem_id_to_coord(dem_id);
!self.polygon.contains(&dem_coord.0)
}
Expand All @@ -52,7 +52,7 @@ impl Pruner {
reason = "We're only dealing with a max of the DEM's width"
)]
/// Convert a DEM 1D index to a 2D coordinate.
pub fn convert_dem_id_to_coord(&self, dem_id: i64) -> tvs_lib::dem::Coordinate {
pub(crate) fn convert_dem_id_to_coord(&self, dem_id: i64) -> tvs_lib::dem::Coordinate {
let x = dem_id.rem_euclid(self.width.into()) as f64;
let y = dem_id.div_euclid(self.width.into()) as f64;
tvs_lib::dem::Coordinate(geo::coord! {x: x, y: y})
Expand Down
4 changes: 2 additions & 2 deletions crates/total-viewsheds/src/compute/kernel.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ use geo::HasDimensions as _;
use itertools::izip;

/// The data output by a single angle.
pub struct OutputData {
pub(crate) struct OutputData {
/// The visibile surface area.
pub surfaces: Vec<f32>,
/// The longest lines of sight.
Expand Down Expand Up @@ -57,7 +57,7 @@ const DEFAULT_UNROLL: usize = const {

/// `kernel` will calculate the longest line of sight heatmap for a given angle and elevation map
/// assuming that the maximum line of sight is `max_los`
pub fn kernel(
pub(crate) fn kernel(
db_worker: &crate::storage::worker::Worker,
elevation_map: &[i16],
output: &mut OutputData,
Expand Down
9 changes: 5 additions & 4 deletions crates/total-viewsheds/src/compute/los.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
/// `LineOfSight` abstracts the implementation of line of sight calculations to
/// any "carry through" that can be materialized into a (f32, f32).
pub trait LineOfSight<Output: Into<(f32, f32)>, LOS: Angle + PrefixMax + Accumulate<Output>> {
pub(crate) trait LineOfSight<Output: Into<(f32, f32)>, LOS: Angle + PrefixMax + Accumulate<Output>>
{
/// `line_of_sight` calculates a line of sight for the given `pov_height`
/// and outputs a triple of the surface area, longest line of sight in meters
/// and a vector of bools of which
Expand All @@ -9,7 +10,7 @@ pub trait LineOfSight<Output: Into<(f32, f32)>, LOS: Angle + PrefixMax + Accumul

/// `Angle` abstracts the angle calculation between a pov and all the elevation data within
/// its band of sight
pub trait Angle {
pub(crate) trait Angle {
/// `calculate_angles` calculates the angle from the `pov_height` to a given elevation
fn calculate_angles(
pov_height: f32,
Expand All @@ -23,7 +24,7 @@ pub trait Angle {
/// `Accumulate` accumulates the surface area visible and longest line of sight
/// in a pair of (f32, f32). `Accumulate` doesn't care about the implementation details
/// of accumulation so long as the `Output` type can be materialized to (f32, f32)
pub trait Accumulate<Output: Into<(f32, f32)>> {
pub(crate) trait Accumulate<Output: Into<(f32, f32)>> {
/// `accumulate` accumulates the surface area using the distances by comparing
/// whether a point at a distance is visible (angle > prefix)
/// If `output_sector` is true, it should output a bitmap of which distances are visible
Expand All @@ -38,7 +39,7 @@ pub trait Accumulate<Output: Into<(f32, f32)>> {
}

/// `PrefixMax` calculates the prefix maximum of the given angles
pub trait PrefixMax {
pub(crate) trait PrefixMax {
/// `prefix_max` calculates the prefix max of the
fn prefix_max(highest: f32, angles_in: &[f32], angles_out: &mut [f32]);
}
2 changes: 1 addition & 1 deletion crates/total-viewsheds/src/compute/rotation.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ use std::rc::Rc;
reason = "rotation should not be out of bounds"
)]
#[expect(clippy::expect_used, reason = "invriants broken if options not none")]
pub fn lines(
pub(crate) fn lines(
elevs: &[i16],
max_los: usize,
angle: f64,
Expand Down
10 changes: 5 additions & 5 deletions crates/total-viewsheds/src/compute/rotator.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
/// * 180°: (`width_index` - x, `width_index` - y)
// * 270°: (y, `width_index` - x)
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum Quadrant {
pub(crate) enum Quadrant {
/// Top-right quadrant: 0° to 90°
TopRight,
/// Top-left quadrant: 90° to 180°
Expand Down Expand Up @@ -55,7 +55,7 @@ impl From<f64> for Quadrant {
}

/// Rotator struct.
pub struct Rotator {
pub(crate) struct Rotator {
/// The centre of the DEM in relative coordinates.
centre: (f64, f64),
/// The index of the last point in a row/column of the DEM.
Expand All @@ -72,7 +72,7 @@ pub struct Rotator {

impl Rotator {
/// Instantiate.
pub fn new(angle: f64, width: isize) -> Self {
pub(crate) fn new(angle: f64, width: isize) -> Self {
assert!(
(0.0f64..360.0f64).contains(&angle),
"Angle {angle} must be in range 0..360"
Expand Down Expand Up @@ -109,7 +109,7 @@ impl Rotator {
/// we'd just make the angle negative here. But seeing as the rest of the maths involved in
/// skew rotation is based in positive angles it's better to achieve the same rotation
/// through a positive but inverted angle.
pub fn invert_angle(angle: f64) -> f64 {
pub(crate) fn invert_angle(angle: f64) -> f64 {
if angle > 0.0f64 {
360.0f64 - angle
} else {
Expand All @@ -122,7 +122,7 @@ impl Rotator {
///
/// Note that each shear step _must_ be rounded. This is essential to achieving a bijective
/// mapping.
pub fn rotate(&self, x: isize, y: isize) -> (isize, isize) {
pub(crate) fn rotate(&self, x: isize, y: isize) -> (isize, isize) {
let (x_centre, y_centre) = self.centre;
let (quadrant_x, quadrant_y) = self.rotate_to_quadrant(x, y);

Expand Down
Loading
Loading