From d9ea39135564a86d26adeba097c2541a02140ade Mon Sep 17 00:00:00 2001 From: Daniel Schadt Date: Sat, 29 Nov 2025 14:19:54 +0100 Subject: add some more documentation --- hittekaart/src/error.rs | 22 ++++++++++++++++++++- hittekaart/src/gpx.rs | 10 ++++++---- hittekaart/src/layer.rs | 5 ++--- hittekaart/src/lib.rs | 51 ++++++++++++++++++++++++++++++++++++++++++++----- 4 files changed, 75 insertions(+), 13 deletions(-) diff --git a/hittekaart/src/error.rs b/hittekaart/src/error.rs index f5abd1b..16cd597 100644 --- a/hittekaart/src/error.rs +++ b/hittekaart/src/error.rs @@ -5,32 +5,52 @@ use thiserror::Error; use super::renderer::RenderedTile; +/// Main error type. All hittekaart errors are mapped to this enum. #[derive(Error, Debug)] pub enum Error { + /// Error for crossbeam operations. + /// + /// hittekaart uses multithreading internally to speed up tile generation. We use crossbeam to + /// pass messages between threads. #[error("crossbeam error")] - Crossbeam(#[from] crossbeam_channel::SendError::), + Crossbeam(#[from] crossbeam_channel::SendError), + /// Underlying image processing error. #[error("image processing error")] Image(#[from] image::ImageError), + /// The GPX file contains an invalid latitude value. #[error("the latitude is invalid")] InvalidLatitude(#[source] ParseFloatError), + /// The GPX file contains an invalid longitude value. #[error("the longitude is invalid")] InvalidLongitude(#[source] ParseFloatError), + /// The output directory is invalid. #[error("the output directory is invalid")] InvalidOutputDirectory, + /// Underlying I/O error. + /// + /// The first field contains a description of the action that was executed when the error + /// occurred. #[error("error when {0} because of an underlying I/O error")] Io(&'static str, #[source] std::io::Error), + /// The input point had no latitude value attached. #[error("input has no latitude value")] MissingLatitude, + /// The input point had no longitude value attached. #[error("input has no longitude value")] MissingLongitude, + /// The output folder already exists. #[error("output file {0} already exists")] OutputAlreadyExists(PathBuf), + /// Underlying SQLite error. #[error("SQLite error")] Sqlite(#[from] rusqlite::Error), + /// UTF-8 decoding error. #[error("invalid utf8 input data")] Utf8(#[from] FromUtf8Error), + /// XML parsing error. #[error("XML parse error")] Xml(#[from] roxmltree::Error), } +/// Type alias that defaults to [`enum@Error`] as error variant. pub type Result = std::result::Result; diff --git a/hittekaart/src/gpx.rs b/hittekaart/src/gpx.rs index 8bd076d..b645c21 100644 --- a/hittekaart/src/gpx.rs +++ b/hittekaart/src/gpx.rs @@ -1,8 +1,10 @@ //! GPX data extraction functions. //! -//! We *could* use the [gpx](https://github.com/georust/gpx) crate, but we don't care about much -//! other than the coordinates of the tracks. By implementing the little functionality ourselves, -//! we can use a fast XML parser ([roxmltree](https://github.com/RazrFalcon/roxmltree)). +//! Like the rest of hittekaart, this module is specialized to our use case. That's why this module +//! internally uses [roxmltree](https://github.com/RazrFalcon/roxmltree) for fast XML parsing, +//! instead of the [gpx](https://github.com/georust/gpx) crate that has more features. +//! +//! This module supports reading files that are `gzip` or `brotli` compressed. //! //! Note that we throw away all information that we don't care about. Since we need only the //! coordinates of a track, we simply use a `Vec` to represent a track. @@ -125,7 +127,7 @@ impl Compression { /// for files ending with `.gz` or `.gzip`, and [`Compression::None`] for files ending with /// `.gpx`. /// - /// If the file does not end with any of the aforementioned extensions, an error is returned + /// If the file does not end with any of the aforementioned extensions, `None` is returned /// instead. pub fn suggest_from_path>(path: P) -> Option { let Some(ext) = path.as_ref().extension() else { diff --git a/hittekaart/src/layer.rs b/hittekaart/src/layer.rs index 03a168b..e8fea25 100644 --- a/hittekaart/src/layer.rs +++ b/hittekaart/src/layer.rs @@ -1,8 +1,7 @@ //! Lazy tiled image. //! -//! This supports OSM-style "tiled" images, but not all of the tiles have to be present. If a tile -//! is not present, a default pixel is returned. The tile is allocated with the first call to a -//! mutating operation. +//! This represents an OSM tile layer with 256x256 map tiles, but "lazily" saved -- tiles are only +//! allocated on the first write access. use std::{ fs::File, io::{BufWriter, Write}, diff --git a/hittekaart/src/lib.rs b/hittekaart/src/lib.rs index 3a4c7a3..5d71d2c 100644 --- a/hittekaart/src/lib.rs +++ b/hittekaart/src/lib.rs @@ -1,10 +1,51 @@ -//! `hittekaart` is a program to generate heatmaps from GPX tracks. +//! `hittekaart` is a crate to generate heatmaps from GPS tracks. It reads GPX files and produces +//! OSM-compatible overlay tiles. //! -//! Note that this crate is not meant to be used as a library. Instead, use the command line -//! program that is included in this crate. +//! This crate is mainly written to power the CLI wrapper and the Python interface, and as such, is +//! opinionated (and leaky) at points. //! -//! This library therefore contains an API that is tailored to the use case of the `hittekaart` -//! binary. +//! # Example +//! +//! ``` +//! use hittekaart::{gpx, renderer::{self, heatmap}, storage::{self, Storage}}; +//! const ZOOM: u32 = 10; +//! let source = +//! r#" +//! +//! +//! +//! +//! +//! +//! "#; +//! let track = gpx::extract_from_str(source)?; +//! let tracks = &[track]; +//! // Generating a heat-map is a two-step process: First, we collect the "heat zones", then we +//! // render each zone to a PNG. +//! let heat = renderer::prepare( +//! &renderer::heatmap::Renderer, +//! ZOOM, +//! tracks, +//! // A callback you can use to show progress +//! || Ok(()), +//! )?; +//! // Before we run the second step, we set up the storage system. You can save the bytes in any +//! // way you want, but there are convenience functions in this crate: +//! let mut store = storage::Sqlite::connect(":memory:")?; +//! store.prepare()?; +//! store.prepare_zoom(ZOOM)?; +//! // Now we're ready to do the actual colorizing +//! renderer::colorize( +//! &renderer::heatmap::Renderer, +//! heat, +//! // The callback receives the rendered tile, with the PNG data ready to grab. +//! |tile| { +//! store.store(ZOOM, tile.x, tile.y, &tile.data) +//! }, +//! )?; +//! store.finish()?; +//! # Ok::<_, hittekaart::error::Error>(()) +//! ``` pub mod error; pub mod gpx; pub mod layer; -- cgit v1.2.3