Open-source project
georust/geo avatar
georust/geo

geo is the geometry kernel the Geo ecosystem is built on, not the whole stack

Rust geospatial primitives & algorithms

1,951 stars272 forksRustNOASSERTION

At a glance

What is it?
geo is a Rust crate of geospatial primitive types and algorithms, covering DE-9IM topology, boolean operations, buffering, convex hulls, DBSCAN clustering and distance calculation, with coordinate reference system support delegated to PROJ and IO delegated to geojson and geozero. It suits a Rust program that already has coordinates and needs reliable operations on them, and it is licensed Apache-2.0 or MIT at your option.
Who is it for?
Adopt geo when your Rust code holds Point, LineString and Polygon values and needs topology, boolean operations, buffering or clustering done correctly, since the primitives and the DE-9IM relationships are the part everything else in the ecosystem is built on.
Can I use it commercially?
Check first. The repository uses a licence we do not classify automatically, so read its LICENSE file before any commercial use.
Is it still maintained?
Yes. The repository last received commits 4 days ago.
What is it written in?
Mainly Rust, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on October 22, 2026, and from our analysis. They are not legal advice.

Editorial analysis

Primitives in, algorithms attached to them

geo starts with types: Point, LineString and Polygon, among others. The algorithms are implemented as traits on those types rather than as free functions over some other representation, so the operation is chosen by importing it.

The README's example makes both halves visible, and it is worth reading closely because the naming style is unusual:

rust
// primitives
use geo::{line_string, polygon};

// algorithms
use geo::ConvexHull;

// An L shape
let poly = polygon![
    (x: 0.0, y: 0.0),
    (x: 4.0, y: 0.0),
    (x: 4.0, y: 1.0),
    (x: 1.0, y: 1.0),
    (x: 1.0, y: 4.0),
    (x: 0.0, y: 4.0),
    (x: 0.0, y: 0.0),
];

let hull = poly.convex_hull();

The primitive constructors are macros, polygon! and line_string!, so they read like literal syntax rather than like function calls, and the coordinates use the labelled form (x: 0.0, y: 0.0). The algorithm is a trait, ConvexHull, brought into scope with a use, after which convex_hull() is a method. Nothing about the trait is visible at the call site, which is convenient when you know the trait and unhelpful when you do not, since the compiler will point you at a missing import rather than at a list of candidates.

The assertion in the example checks the hull's exterior against a line_string of five coordinates plus the repeated closing point, which is also a small lesson in the crate's convention: rings close explicitly.

What the algorithm list actually covers

The README enumerates capabilities rather than individual functions, and defers to docs.rs for the complete list. The categories are specific enough to be useful.

Topology is the deepest part: full DE-9IM support and topological relationship calculations such as containment and intersection. DE-9IM is the matrix that says, for any two geometries, how they intersect, and implementing it properly is the kind of work most projects should not redo.

Affine operations cover scale, rotate, skew and translate on geometries. Boolean operations are clip, union, difference, intersection and xor. Buffering, described as an offset operation, is the workhorse for proximity questions. Repair is there for invalid polygons and multipolygons, and the README specifies the method: constrained Delaunay triangulation to produce valid geometry, which is a meaningful detail because repairing by hand-built heuristics is where many implementations quietly produce shapes that are valid and wrong.

Clustering includes DBSCAN and k-means. Distance calculation is split into Euclidean and non-planar variants, the README naming spherical and haversine among the latter, which matters if your coordinates are longitude and latitude rather than metres.

One limitation is visible in that list: nothing is 3D. The primitives and the operations are planar, so elevation and volumetric geometry are out of scope.

Projection and file formats are somebody else's crate

This is the most important structural fact about the project, and the README is explicit about it. Support for projecting and converting between coordinate reference systems is not implemented in geo; it comes from the separate georust/proj crate. IO using the geojson and geozero crates is also separate.

The rest of the ecosystem follows from the primitives: the README lists coordinate transformation and projection, serialization to and from GeoJSON and WKT, geocoding, and working with GPS data, each with its own repository.

So the shape of a real program is: parse or fetch coordinates, decide what reference system they are in, use geo for the geometry work, and hand results to a serializer. If your task is reading a shapefile and reprojecting it, geo is one piece of that pipeline and the projection piece is the part that decides your accuracy.

The workspace layout reinforces the separation. The Cargo.toml at the root lists six members: geo, geo-benches, geo-test-fixtures, geo-traits, geo-types and jts-test-runner. Splitting the primitive types into geo-types and the algorithm traits into geo-traits means a dependency that only needs coordinate types does not have to pull in the whole algorithm set, which matters for compile time in a large workspace.

There is also a patch section in the workspace manifest that forces geo and geo-types to resolve to the local paths, with a comment explaining the reason is to ensure transitive dependencies also use the local copies. That is a development-only arrangement, not something that affects consumers on crates.io.

How it differs from shapely, JTS and geotools

The obvious comparison is with Shapely in Python, which offers the same shape of API: primitive geometries with methods attached, boolean operations, and buffering. The difference in approach is the underlying algorithm library. geo's boolean operations and validity repair are implemented in Rust directly, with repair using constrained Delaunay triangulation, whereas Shapely delegates to GEOS, which in turn descends from JTS.

That lineage shows in this repository. jts-test-runner is a workspace member, which is a test harness rather than a dependency, and its presence says the implementation is validated against the JTS test suite. For a team deciding whether to trust the boolean operations, that is the concrete evidence to look at, and the README does not describe it, so read the directory.

Against Java's JTS directly, geo offers the same capability without a JVM and with the ergonomic advantage of traits selected by import. Against a service such as PostGIS, the trade is different in kind: geo does everything in process with no round trip and no database, but it also has no spatial indexes and no query language, so a scan over millions of rows is not its job.

If you are working in Rust already, the alternative is writing the geometry code yourself, which the README implicitly addresses by being an ecosystem foundation rather than a product.

Licence, versioning and how to evaluate the surface

The licence is a choice rather than a single grant. The README states that the project is licensed under either the Apache License, Version 2.0, or the MIT license, at your option, with LICENSE-APACHE and LICENSE-MIT both present at the root. Apache 2.0 carries an explicit patent grant and NOTICE obligations; MIT is shorter and requires only the notice. For most Rust projects the practical difference is the patent clause.

Contributions carry the same terms: anything submitted for inclusion is dual licensed as above unless the contributor states otherwise, as defined by the Apache-2.0 licence.

On versioning, the repository has no GitHub releases, so the version badge in the README points at crates.io and CHANGES.md at the root is the release history. The last push was on 2026-10-11, and the working tree carries an AGENTS.md alongside CONTRIBUTING.md and CODE_OF_CONDUCT.md, which tells you the project expects automated contributions and keeps its contribution rules in-repo.

There is no installation command in the README, because a library crate is added the usual way, as a dependency on geo from crates.io, whose homepage the repository points at. What the README does not give you is a feature flag list or a minimum supported Rust version, so read geo/Cargo.toml for those before you pin a version.

Editorial conclusion

Adopt geo when your Rust code holds Point, LineString and Polygon values and needs topology, boolean operations, buffering or clustering done correctly, since the primitives and the DE-9IM relationships are the part everything else in the ecosystem is built on. Do not adopt it as an end-to-end GIS stack, because projection lives in the separate proj crate and IO in geojson and wkt, so a program reading files and handling coordinate reference systems needs more than one dependency. Check first which algorithm set you actually need, since the README defers to the documentation for a complete list rather than enumerating it, and verify the licence choice for your organisation: the README offers Apache License 2.0 or MIT at your option, and contributions are dual licensed under those terms unless stated otherwise.

Frequently asked questions

What does the geo crate provide in Rust?

It provides geospatial primitive types such as Point, LineString and Polygon, plus algorithms including DE-9IM topological relationships, affine operations, boolean operations such as clip, union, difference, intersection and xor, buffering, polygon repair through constrained Delaunay triangulation, DBSCAN and k-means clustering, and Euclidean, spherical and haversine distance calculations.

Does geo handle coordinate reference systems and file formats?

Projection and conversion between coordinate reference systems come from the separate georust/proj crate, and IO is handled through the geojson and geozero crates, with WKT handled by another repository in the ecosystem. The README lists these as companion crates rather than features of geo itself.

What licence is the geo crate released under?

At your option, either the Apache License Version 2.0 or the MIT license, with both LICENSE-APACHE and LICENSE-MIT in the repository. Contributions are dual licensed under the same terms unless the contributor states otherwise.

How do I compute a convex hull with geo?

Import the ConvexHull trait and call convex_hull() on the geometry. The README's example builds the polygon with the polygon! macro and then asserts that hull.exterior() equals an expected line_string! value.

Why is there a jts-test-runner directory in the geo repository?

It is a workspace member listed in the root Cargo.toml, alongside geo, geo-benches, geo-test-fixtures, geo-traits and geo-types. The README does not describe it, so consult the directory itself, but its name indicates the geometry implementation is validated against the JTS test suite.

Official sources

  1. georust/geo on GitHub
  2. Issues
  3. Project website
  4. README
Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/georust-geo.svg)](https://hysenlabs.com/projects/georust-geo)