aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Cargo.lock1
-rw-r--r--README.adoc24
-rw-r--r--hittekaart-py/src/lib.rs68
3 files changed, 75 insertions, 18 deletions
diff --git a/Cargo.lock b/Cargo.lock
index 9a97edc..0594ef5 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -637,6 +637,7 @@ version = "0.1.0"
dependencies = [
"hittekaart",
"pyo3",
+ "rayon",
]
[[package]]
diff --git a/README.adoc b/README.adoc
index b628a68..5479979 100644
--- a/README.adoc
+++ b/README.adoc
@@ -260,6 +260,30 @@ With the tile server running, you can then open a HTML file like the following:
</html>
----
+== PYTHON INTERFACE
+
+This program comes with a Python interface, which allows easy use from Python
+scripts. The `hittekaart_py` subfolder in the repository is an installable
+module.
+
+The Python API is documented in the docstrings, and at
+https://docs.fietsboek.org/developer/module/hittekaart_py.html. An example
+program may look like:
+
+[source,python]
+----
+from hittekaart_py import (
+ Track, HeatmapRenderer, Storage, generate
+)
+
+tracks = [
+ Track.from_file(b"Documents/track.gpx", None),
+ Track.from_coordinates([(45.0, 47.0)]),
+]
+storage = Storage.Sqlite(b"/tmp/tiles.sqlite")
+generate(tracks, HeatmapRenderer(), storage)
+----
+
== BUGS
Feel free you report bugs on the issue tracker at
diff --git a/hittekaart-py/src/lib.rs b/hittekaart-py/src/lib.rs
index 782f9e7..8cd51d9 100644
--- a/hittekaart-py/src/lib.rs
+++ b/hittekaart-py/src/lib.rs
@@ -31,7 +31,13 @@ fn err_to_py(mut error: &dyn Error) -> PyErr {
HitteError::new_err(text)
}
-/// Python representation of a track.
+/// Represents a track.
+///
+/// This is what you want to load in order to render the heatmaps.
+///
+/// Tracks can be loaded from GPX files (see Track.from_file()) or from in-memory coordinates
+/// (Track.from_coordinates()). Otherwise, tracks should be treated as opaque objects, whose only
+/// purpose is to be passed to generate().
#[pyclass]
#[derive(Debug, Clone)]
struct Track {
@@ -42,7 +48,10 @@ struct Track {
impl Track {
/// Load a track from a file.
///
- /// Compression - if given - should be one of the strings "gzip" or "brotli".
+ /// The path should be given as a bytes object.
+ ///
+ /// The compression parameter - if given - should be one of the strings "gzip" or "brotli". It
+ /// can be set to None to use no compression.
#[staticmethod]
fn from_file(path: &[u8], compression: Option<&str>) -> PyResult<Track> {
let compression = match compression {
@@ -57,6 +66,9 @@ impl Track {
}
/// Load a track from the given coordinates.
+ ///
+ /// The coordinates should be a list of (longitude, latitude) tuples, where longitude and
+ /// latitude are represented as floats.
#[staticmethod]
fn from_coordinates(coordinates: Vec<(f64, f64)>) -> Track {
Track {
@@ -68,22 +80,18 @@ impl Track {
}
}
-impl Track {
- fn coordinates(&self) -> Vec<(f64, f64)> {
- self.inner
- .iter()
- .map(|c| (c.longitude, c.latitude))
- .collect()
- }
-}
-
#[derive(Debug, Clone, PartialEq, Eq)]
enum StorageType {
Folder(PathBuf),
Sqlite(PathBuf),
}
-/// Python representation of a storage target.
+/// Represents a storage target.
+///
+/// Hittekaart can store tiles either in folders (easy-to-use, but wasteful), or as a SQLite
+/// database (more space-efficient).
+///
+/// See hittekaart's README for more detailed information.
#[pyclass]
#[derive(Debug, Clone, PartialEq, Eq)]
struct Storage(StorageType);
@@ -91,6 +99,9 @@ struct Storage(StorageType);
#[pymethods]
impl Storage {
/// Output to the given folder.
+ ///
+ /// This will create files path/{z}/{x}/{y}.png, where {z} is the zoom level, and {x} and {y}
+ /// are the tile coordinates.
#[staticmethod]
#[pyo3(name = "Folder")]
fn folder(path: &[u8]) -> Self {
@@ -98,7 +109,11 @@ impl Storage {
Storage(StorageType::Folder(path.into()))
}
- /// Output to the given sqlite file.
+ /// Output to the given SQLite file.
+ ///
+ /// This will create a single table 'tiles' with the columns 'zoom', 'x', 'y' and 'data'.
+ ///
+ /// Note that you cannot "append" to an existing database, it must be a non-existing file.
#[staticmethod]
#[pyo3(name = "Sqlite")]
fn sqlite(path: &[u8]) -> Self {
@@ -123,7 +138,9 @@ impl Storage {
}
}
-/// Python representation of a heatmap renderer.
+/// A renderer that produces a heatmap.
+///
+/// The constructor takes no parameters: HeatmapRenderer()
#[pyclass]
struct HeatmapRenderer {
inner: renderer::heatmap::Renderer,
@@ -141,9 +158,9 @@ impl HeatmapRenderer {
/// Generate the heatmap.
///
-/// * `items` is an iterable of [`Track`]s
-/// * `renderer` should be a renderer (like [`HeatmapRenderer`])
-/// * `storage` is the [`Storage`] output
+/// * items is an iterable of Track
+/// * renderer should be one of the renderers (such as HeatmapRenderer)
+/// * storage is the Storage output
#[pyfunction]
fn generate(
items: &Bound<'_, PyAny>,
@@ -188,6 +205,12 @@ fn do_generate<R: Renderer>(
Ok(())
}
+/// Set the number of threads that hittekaart will use.
+///
+/// Note that this is a global function, it will affect all subsequent calls.
+///
+/// Note further that you may only call this function once, at startup. Calls after the thread pool
+/// has been initialized (e.g. via a generate() or set_threads() call) will raise an exception.
#[pyfunction]
fn set_threads(threads: usize) -> PyResult<()> {
rayon::ThreadPoolBuilder::new()
@@ -196,7 +219,16 @@ fn set_threads(threads: usize) -> PyResult<()> {
.map_err(|e| err_to_py(&e))
}
-/// A Python module implemented in Rust.
+/// Python bindings for the hittekaart heatmap tile generator.
+///
+/// hittekaart renders GPS tracks (usually from GPX files) to heatmap tiles for consumption with
+/// OpenStreetMap data.
+///
+/// You can find more documentation about hittekaart in its README:
+/// <https://gitlab.com/dunj3/hittekaart>
+///
+/// You can find rendered docs as part of fietsboek's documentation:
+/// <https://docs.fietsboek.org/developer/module/hittekaart_py.html>
#[pymodule]
fn hittekaart_py(py: Python<'_>, m: &Bound<'_, PyModule>) -> PyResult<()> {
m.add_class::<Track>()?;