meos 0.3.0

Rust bindings for MEOS C API
# meos-rs
[<img alt="github" src="https://img.shields.io/badge/github-meos--rs-8da0cb?&logo=github" height="20">](https://github.com/MobilityDB/meos-rs)
[<img alt="crates.io" src="https://img.shields.io/crates/v/meos.svg?&logo=rust" height="20">](https://crates.io/crates/meos)
[<img alt="docs.rs" src="https://img.shields.io/badge/docs.rs-meos-66c2a5?&logo=docs.rs" height="20">](https://docs.rs/meos)

**meos-rs** is a Rust library providing bindings for the [MEOS](https://libmeos.org/) C library, designed for spatiotemporal data management and analysis. It enables handling of temporal and spatial data, making it ideal for applications that need to work with moving objects, trajectories, and time-varying geographical data.

It supports MEOS version >= 1.2

## Overview

The primary goal of this library is to facilitate the creation and manipulation of temporal types, such as time-stamped geographic points, sequences, and numeric values. These temporal data structures can be used for various use cases including:

- **Tracking Movement:** Efficiently manage and analyze the movement of objects (e.g., vehicles, ships, animals) over time.
- **Spatiotemporal Queries**:
    - **Distance Calculations:** Compute the shortest distance between trajectories, which can be useful for determining when two moving objects were closest to each other.
    - **Time-Weighted Averages:** Analyze time-dependent data, like averaging speeds or temperatures over a period.
    - **Intersection Queries:** Check if a trajectory passes through specific points or regions, enabling location-based analysis of movement.

This library provides access to advanced spatiotemporal data handling capabilities of MEOS while maintaining Rust’s memory safety, concurrency, and performance benefits.

## Installation

Add the following dependency to your `Cargo.toml`:

```toml
[dependencies]
meos = "0.3"
```

This requires MEOS 1.3 to be installed on your system. Follow the [installation instructions](https://github.com/MobilityDB/MobilityDB/?tab=readme-ov-file#requirements) on the MEOS website.

Alternatively, enable the `bundled` feature to build MEOS and its dependencies from source:

```toml
meos = { version = "0.3", features = ["bundled"] }
```

This requires the following build tools:

```bash
# Debian/Ubuntu
apt-get install cmake clang libclang-dev pkg-config sqlite3 libsqlite3-dev
```

And the git submodules must be initialized:

```bash
git submodule update --init --recursive
```

See [sys/README.md](./sys/README.md) for more details and options.

## Key Features

The library offers a range of temporal data types, including:

- **Temporal Geometric Points (`TGeomPoint`):** These represent geometric points that change over time (e.g., location data of moving objects).
- **Temporal Float (`TFloat`):** These store numeric values associated with time, such as speed or temperature over time.
- **Temporal Boolean (`TBool`):** Represents true/false values that vary over time, useful for tracking binary states such as whether an object is within a specific area at given times.

The type hierarchy is the following, the main types (`TGeomPoint`, `TFloat`, etc.) are enums that encapsulate the different kinds of temporal subtypes, **Instant**, **Sequence**, and **SequenceSet**, to learn more about these, refer to the [`meos` documentation](https://libmeos.org/documentation/datamodel/). Users can almost seamlessly use either the enums or the concrete structs (e.g. `TGeomPointSequence`). Some users may benefit from using the concrete structs since more concrete types can be inferred in some functions.

## Usage example

You can check more examples in the `examples/` directory.

### Constructing trajectories from text:

```rust
use meos::{meos_initialize, TGeomPoint};

meos_initialize();

let trajectory: TGeomPoint = "[POINT(1 1)@2000-01-01 08:00, POINT(2 2)@2000-01-01 08:01]".parse().unwrap();
```

### Constructing trajectories from a list of pairs (point, timestamp):

```rust
    use chrono::{DateTime, TimeZone, Utc};
    use geos::Geometry;
    use meos::{meos_initialize, TGeomPointSequence};

    meos_initialize();

    let geometries_with_time: Vec<(Geometry, DateTime<Utc>)> = vec![
        (
            Geometry::new_from_wkt("POINT(1 1)").unwrap(),
            Utc.with_ymd_and_hms(2020, 1, 1, 0, 0, 0).unwrap(),
        ),
        (
            Geometry::new_from_wkt("POINT(3 2)").unwrap(),
            Utc.with_ymd_and_hms(2020, 1, 1, 0, 1, 0).unwrap(),
        ),
        (
            Geometry::new_from_wkt("POINT(3 3)").unwrap(),
            Utc.with_ymd_and_hms(2020, 1, 1, 0, 2, 0).unwrap(),
        ),
    ];

    let tpoint: TGeomPointSequence = geometries_with_time.into_iter().collect();

    println!("{tpoint:?}");
```

### Get the shortest distance ever between two temporal points

```rust
use meos::{meos_initialize, TGeomPoint, TPointTrait};

meos_initialize();

let tpoint1: TGeomPoint =
    "[Point(0 0 0)@2001-01-01, Point(1 1 1)@2001-01-03, Point(0 0 0)@2001-01-05)"
        .parse()
        .unwrap();
let tpoint2: TGeomPoint =
    "[Point(2 0 0)@2001-01-02, Point(1 1 1)@2001-01-04, Point(2 2 2)@2001-01-06)"
        .parse()
        .unwrap();

let distance = tpoint1.nearest_approach_distance(&tpoint2);
println!("{distance}"); // Prints 0.5
```

### Check if a trajectory ever goes through a point (using `geos`)

```rust
use geos::Geometry;
use meos::{meos_initialize, TGeomPoint, Temporal};

meos_initialize();

let trajectory: TGeomPoint = "[Point(0 0 0)@2001-01-01, Point(2 2 2)@2001-01-05)"
    .parse()
    .unwrap();
let geom = Geometry::new_from_wkt("Point (1 1 1)").expect("Invalid geometry");

println!(
    "Does go through `geom`: {}",
    trajectory.ever_equal_than_value(geom).unwrap()
); // `true`
```

## Multithreading
Right now it should only be used in single-threaded applications. In the foreseeable future this could change.

## Build

This crate links dynamically to your system-installed `meos`, or can build it from source via the `bundled` feature. See [sys/README.md](./sys/README.md) for more information.

## Contributing

Only a subset of `meos` has been implemented, feel free to add wrappers for missing features.

All added features needs to be tested and this being a C wrapper, valgrind runs on all examples/tests to check that
no bugs / memory leaks are lurking.

## Acknowledgments
This wrapper has been deeply influenced by the Rust wrapper of [`geos`](https://github.com/georust/geos)