MEOS
MEOS (Mobility Engine, Open Source) is a C library for temporal and spatiotemporal data — moving objects, time-varying values, and time spans / sets. Databases, query engines, and language bindings consume MEOS to expose temporal types in their respective environments.
The library is inspired by GEOS (Geometry Engine, Open Source) — hence the name.
MEOS implements published standards rather than ad-hoc representations:
- ISO 19141:2008 — Geographic information — Schema for moving features. MEOS extends it to also represent the evolution of non-spatial attributes and the temporal gaps inherent to real mobility data (periods during which no observations were collected, for instance due to signal loss).
- OGC Moving Features JSON — the canonical JSON encoding for moving features, an extension of GeoJSON. MEOS implements it as its MF-JSON encoding.
- Well-Known Text and Well-Known Binary — the same conventions used by GEOS and PostGIS, extended to the time dimension. See WKT and WKB.
The encoding choice is up to the consumer; values move losslessly between the three so a binding can pick whichever fits its transport.
MEOS exposes its type system through bindings tailored to each host environment.
| Environment | Binding |
|---|---|
| PostgreSQL | MobilityDB |
| DuckDB | MobilityDuck |
| Python | PyMEOS |
| Java | JMEOS |
| Rust | meos-rs |
| Go | GoMEOS |
| .NET | MEOS.NET |
| JavaScript | MEOS.js |
Each binding exposes the same MEOS type system using the conventions of its host environment: SQL functions in PostgreSQL/DuckDB, idiomatic classes in PyMEOS / JMEOS / meos-rs / GoMEOS / MEOS.NET / MEOS.js. The C library is the source of truth for type semantics, encoding, and behaviour.
flowchart TB meos(["MEOS<br/>C library"]) pg["MobilityDB<br/>(PostgreSQL)"] duck["MobilityDuck<br/>(DuckDB)"] py["PyMEOS<br/>(Python)"] java["JMEOS<br/>(Java)"] rust["meos-rs<br/>(Rust)"] go["GoMEOS<br/>(Go)"] net["MEOS.NET<br/>(.NET / C#)"] js["MEOS.js<br/>(JavaScript)"] pg --> meos duck --> meos py --> meos java --> meos rust --> meos go --> meos net --> meos js --> meos
Other consumers can be built directly on top of MEOS — additional language bindings, integrations with other DBMSs, or analytics platforms (Spark, Flink, Apache Beam, etc.). The MEOS C API is the common substrate.
The same temporal value travels through every binding. Three thirty-second tastes:
#include <stdio.h>
#include <stdlib.h>
#include <meos.h>
int main(void) {
meos_initialize();
meos_initialize_timezone("UTC");
Temporal *t = (Temporal *) tfloat_in(
"[1.5@2026-01-01, 2.5@2026-01-02]");
char *json = temporal_as_mfjson(t, true, 6, 1, NULL);
printf("%s\n", json);
free(json); free(t);
meos_finalize();
return 0;
}
Compile with gcc -I/usr/local/include -lmeos hello.c -o hello.
from pymeos import pymeos_initialize, TFloatSeq
pymeos_initialize()
t = TFloatSeq(string="[1.5@2026-01-01, 2.5@2026-01-02]")
print(t.as_mfjson())
Install with pip install pymeos.
CREATE EXTENSION mobilitydb CASCADE;
SELECT asMFJSON(tfloat '[1.5@2026-01-01, 2.5@2026-01-02]');
All three produce the same MF-JSON document — that’s the point of the encoding-as-common-substrate model.
A nine-step tutorial series walks through the essence of the library. Several steps offer variants that swap an axis without changing the lesson — typically a different coordinate system (Cartesian vs. geodetic), a different input source (real-world AIS vs. synthetic BerlinMOD), or a different I/O target (in-process, DB, file). Pick the variant that matches your stack:
- Hello World — first temporal point values and MF-JSON output.
- Cartesian —
tgeompointin a planar coordinate system. - Geodetic variant —
tgeogpointon the WGS84 sphere (01_hello_world_geodetic.c).
- Cartesian —
- AIS Read — parsing AIS observation records into temporal values.
- AIS / BerlinMOD Assemble — building trajectories from streaming observations.
- AIS — real-world AIS data (Danish Maritime Authority feed).
- BerlinMOD variant — synthetic data from the BerlinMOD generator (
03_berlinmod_assemble.c).
- AIS Persist — three variants for where the trajectories land:
- Bulk → DB — load a CSV file into MobilityDB in one shot.
- Stream → DB — streaming DB ingest using MEOS expandable temporal structures, sending batches to MobilityDB as they fill.
- Stream → File variant (
04_ais_stream_file.c) — same expandable-structure streaming pattern, writing to an output file instead of a database.
- BerlinMOD Disassemble — splitting trips into instants.
- BerlinMOD Clip — restricting trajectories to spatial regions.
- BerlinMOD Tile — spatiotemporal tiling.
- BerlinMOD Simplify — line-simplification of trajectories.
- BerlinMOD Aggregate — temporal aggregation.
The numbered series is intentionally simplified — small datasets, well-formed input, no error handling — so that the MEOS API is the focus of attention rather than the I/O scaffolding around it.
Some examples ship a *_full.c counterpart in meos/examples/ that handles real-world conditions: realistic file sizes, malformed inputs, edge cases, error recovery, retry / reconnect logic. The convention is that _full counterparts exist only where the data has real-world messiness — i.e. for examples that operate on a real AIS feed. The BerlinMOD examples (steps 5–9) operate on synthetic generator-produced data that’s clean by construction, so they intentionally have no _full counterpart.
Current pairs:
03_ais_assemble.c↔ais_assemble_full.cais_expand.c↔ais_expand_full.cais_transform.c↔ais_transform_full.c
Use the simplified example to learn the API; use the _full counterpart as a reference when wiring MEOS into production code.
Beyond the tutorial ladder, meos/examples/ also contains feature-specific examples: rtree indexing, k-means / DBSCAN clustering, projection, transforms, expansion, network points, and more.
MEOS defines stable on-the-wire encodings for temporal values, allowing data to round-trip between bindings without loss:
- Well-Known Text (WKT) — human-readable.
- Well-Known Binary (WKB) — compact binary, the canonical interchange format.
- Moving-Features JSON (MF-JSON) — OGC-aligned JSON.
A trajectory written from one binding can be read by any other.
A first version of MEOS, written in C++, was contributed by Krishna Chaitanya Bommakanti. The current C library evolved from that origin and has been the canonical implementation since.

The MobilityDB project has received funding from the European Union's Horizon Europe research and innovation programme under grant agreements No 101070279 MobiSpaces and No 101093051 EMERALDS.