Skip to content
4 changes: 2 additions & 2 deletions GEOLIBRE_PARITY.md
Original file line number Diff line number Diff line change
Expand Up @@ -166,8 +166,8 @@ _GeoLibre: docs/features.md › Attribute data and expressions; docs/arcgis-edit
_GeoLibre: docs/features.md › Processing and analysis; docs/user-guide/processing.md,
model-builder.md, segmentation.md, obia.md_

- [ ] **Spatial join, intersect, union**. Partial: spatial join, clip, erase, intersect, identity
and union are built in; near is missing (_Roadmap: solid ground_).
- [x] **Spatial join, intersect, union** ([#959](https://github.com/opengeos/RustGIS/issues/959)):
spatial join, clip, erase, intersect, identity, union and near are built in.
- [ ] **More built-in vector tools**: attribute join, merge, extract vertices, points along lines,
fix/check geometry, random extract, buffer options. Partial (_Roadmap: solid ground_).
- [ ] **Routing services**: isochrones, service areas, OD matrix, multi-stop routing,
Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,7 @@ Every screenshot is RustGIS itself, rendered offscreen by `cargo run -p rustgis-
| **Web tiles** | XYZ/TMS/WMS raster tiles, Mapbox Vector Tiles and MapLibre styles (sprites, patterns, expressions), cached and fetched in the background |
| **Cartography** | Single symbol, unique values, graduated colours, proportional symbols; label classes with SQL queries, straight and curved line placement, installed font families, scale ranges and annotation; stacked and dashed line strokes, symbol levels, reference scales and polygons without fill; masking, display filters, aggregation bins, 2.5D extrusion; graphics and dynamic text |
| **Editing** | Create, move, rotate, scale, merge, split and explode features; snapping, templates, elevation, traverse, topology rules; domains, subtypes, attribute rules, relationships, archiving; undo for everything |
| **Analysis** | Selection by attributes (SQL) and location; Buffer, Clip, Erase, Intersect, Identity, Union, Dissolve, Summarize Within, Summary Statistics, Spatial Join, Zonal Statistics, A5 grids and a geometry calculator; viewshed, line of sight, IDW, ordinary kriging, shortest path, suitability modelling; ModelBuilder on a node canvas and scripts with command, parameter and value completion; 1,000+ [GeoLibre](https://github.com/opengeos/geolibre-rust) and Whitebox raster, vector, LiDAR, hydrology and terrain tools |
| **Analysis** | Selection by attributes (SQL) and location; Buffer, Near, Clip, Erase, Intersect, Identity, Union, Dissolve, Summarize Within, Summary Statistics, Spatial Join, Zonal Statistics, A5 grids and a geometry calculator; viewshed, line of sight, IDW, ordinary kriging, shortest path, suitability modelling; ModelBuilder on a node canvas and scripts with command, parameter and value completion; 1,000+ [GeoLibre](https://github.com/opengeos/geolibre-rust) and Whitebox raster, vector, LiDAR, hydrology and terrain tools |
| **Imagery** | Ortho and reality mapping, pixel classification (k-means, minimum distance, a trainable neural network), mensuration, hosted imagery tiles |
| **Layouts and reports** | Page layouts with map frames, legends, scale bars, grids and map series; publication sheets and figures in one command, format panes, guides, snapping and element locks; reports with groups, statistics, charts and subreports; presentations (HTML slideshow, PDF); notebooks (Jupyter in and out) |
| **Sharing** | PNG export at any DPI; PDF; web map pages, OGC API Features collections, MapLibre styles, glTF scenes, locators; project, map and mobile map packages; offline areas with sync |
Expand Down
11 changes: 5 additions & 6 deletions ROADMAP.md
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,6 @@ Correct, robust and recoverable, with the foundations other themes stand on.
administrator can fix for a managed install (no AI Assistant, plugins or web services).
- Extend the OS keychain secret store to service connections (database passwords, S3 keys,
AI provider keys and the ChatGPT sign-in's tokens are already kept there).
- A Near tool beside the overlay tools ([#959](https://github.com/opengeos/RustGIS/issues/959)).
- Spatial Join by distance, closest, centre in and largest overlap, with merge rules (sum, mean,
first…) for one-to-one joins ([#851](https://github.com/opengeos/RustGIS/issues/851)).
- Vector tools, each writing a new layer: join field (a one-off attribute join), merge (append
Expand Down Expand Up @@ -219,11 +218,11 @@ Open questions rather than plans; discuss before building.
templates, elevation, topology; domains, subtypes, attribute rules, contingent values,
relationships, archiving.
- Analysis: selection by attributes and location; polygon, lasso and radius on the map; overlay
(clip, erase, intersect, identity, union), proximity (buffer) and summary tools, spatial join,
zonal statistics, A5 grids, kriging and Calculate Geometry with metric or imperial units; guided
workflows (viewshed, line of sight, IDW, shortest path, suitability); ModelBuilder on a node
canvas, scripts with command, parameter and value completion, and history copied as code; the
GeoLibre and Whitebox suite (1,000+ tools) natively and in the browser.
(clip, erase, intersect, identity, union), proximity (buffer, near) and summary tools, spatial
join, zonal statistics, A5 grids, kriging and Calculate Geometry with metric or imperial units;
guided workflows (viewshed, line of sight, IDW, shortest path, suitability); ModelBuilder on a
node canvas, scripts with command, parameter and value completion, and history copied as code;
the GeoLibre and Whitebox suite (1,000+ tools) natively and in the browser.
- Layouts (map frames, surrounds, map series, publication sheets and figures in one command,
format panes, guides, snapping, element locking and PDF), reports, presentations and
notebooks; the web app embeddable in a page (`?embed`).
Expand Down
19 changes: 13 additions & 6 deletions crates/analysis/src/join.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
//! Spatial Join's measures and merge rules: the ground distance between two features, a test that
//! rules out features too far away to matter, the overlap a feature has with a polygon, and the
//! rules that roll the values of several matches up into one.
//! Spatial Join's and Near's measures, and Spatial Join's merge rules: the ground distance between
//! two features and their nearest points, a test that rules out features too far away to matter,
//! the overlap a feature has with a polygon, and the rules that roll the values of several matches
//! up into one.
//!
//! Distances are on the WGS 84 ellipsoid, as buffers' are. The nearest points of two features are
//! found in an azimuthal equidistant plane, centred first between the features and then between
Expand Down Expand Up @@ -35,12 +36,18 @@ pub fn first_coord(g: &Geometry) -> Option<Coord> {
/// in one centred between the pair found, where the plane is true near the answer however large
/// the features are.
pub fn distance_m(a: &Geometry, b: &Geometry) -> Option<f64> {
let (p, q) = nearest_points(a, b)?;
let d = wgs84_distance_m(p, q);
d.is_finite().then_some(d)
}

/// The nearest points (lon/lat) of two features that don't intersect, as [`distance_m`] finds
/// them: a point of `a`, then one of `b`. `None` for a geometry without a finite coordinate.
pub fn nearest_points(a: &Geometry, b: &Geometry) -> Option<(Coord, Coord)> {
// The features' first vertices are a pair of their points: the search starts from them.
let (fa, fb) = (first_coord(a)?, first_coord(b)?);
let (p, q) = nearest_pair(a, b, &Aeqd::new(geodesic_interpolate(fa, fb, 0.5)), Some((fa, fb)))?;
let (p, q) = nearest_pair(a, b, &Aeqd::new(geodesic_interpolate(p, q, 0.5)), Some((p, q))).unwrap_or((p, q));
let d = wgs84_distance_m(p, q);
d.is_finite().then_some(d)
Some(nearest_pair(a, b, &Aeqd::new(geodesic_interpolate(p, q, 0.5)), Some((p, q))).unwrap_or((p, q)))
}

/// The nearest points of two geometries (lon/lat) as found in `plane`: a point of `a`, one of `b`.
Expand Down
Loading
Loading