Skip to content

Querying

Shiny.Spatial provides both direct query methods for common spatial operations and a fluent query builder for composing complex queries.

Returns all features whose bounding box overlaps the given envelope. This is the fastest query type — it uses only the R*Tree index without C# geometry refinement.

var envelope = new Envelope(
minX: -109.05, maxX: -102.05,
minY: 37.0, maxY: 41.0
);
var results = table.FindInEnvelope(envelope);

Returns features whose geometry actually intersects with the query geometry (two-pass: R*Tree filter + exact geometry check).

var colorado = new Polygon(new[]
{
new Coordinate(-109.05, 37.0),
new Coordinate(-102.05, 37.0),
new Coordinate(-102.05, 41.0),
new Coordinate(-109.05, 41.0),
new Coordinate(-109.05, 37.0)
});
var results = table.FindIntersecting(colorado);

Returns features that are fully contained within the given geometry.

var results = table.FindContainedBy(colorado);

Returns features within a specified distance (in meters for WGS84) from a center point.

var results = table.FindWithinDistance(
center: new Coordinate(-104.99, 39.74),
distanceMeters: 150_000 // 150km
);

The fluent query builder lets you compose complex queries by chaining spatial filters, property filters, sorting, and paging.

var results = table.Query()
.WithinDistance(center, 150_000)
.WhereProperty("population", ">", 200000L)
.OrderByDistance(center)
.Limit(10)
.ToList();
MethodDescription
InEnvelope(envelope)Bounding box filter
Intersecting(geometry)Geometry intersection filter
ContainedBy(container)Geometry containment filter
WithinDistance(center, meters)Distance radius filter
// Combine spatial filters
var results = table.Query()
.InEnvelope(envelope)
.Intersecting(polygon)
.ToList();

Filter by user-defined properties using standard comparison operators.

var results = table.Query()
.WhereProperty("name", "=", "Denver")
.ToList();
var results = table.Query()
.WhereProperty("population", ">", 500000L)
.ToList();
var results = table.Query()
.WhereProperty("name", "LIKE", "%ville")
.ToList();

Supported operators: =, !=, <, <=, >, >=, LIKE

var center = new Coordinate(-104.99, 39.74);
var results = table.Query()
.WithinDistance(center, 500_000)
.OrderByDistance(center) // sort by distance from center
.Offset(10) // skip first 10 results
.Limit(10) // return next 10
.ToList();
MethodReturnsDescription
ToList()List<SpatialFeature>Execute query and return all results
Count()intExecute query and return result count
FirstOrDefault()SpatialFeature?Execute query and return first result or null
using var db = new SpatialDatabase("us-cities.db");
var cities = db.GetTable("cities");
var denver = new Coordinate(-104.99, 39.74);
// Find the 5 most populous cities within 500km of Denver
var nearbyCities = cities.Query()
.WithinDistance(denver, 500_000)
.WhereProperty("population", ">", 100000L)
.OrderByDistance(denver)
.Limit(5)
.ToList();
foreach (var city in nearbyCities)
{
Console.WriteLine($"{city.Properties["name"]} - Pop: {city.Properties["population"]}");
}

Benchmark results on 100K points (Apple M2, .NET 10, in-memory SQLite):

Query TypeMeanAllocated
FindWithinDistance183 us85 KB
FindContainedBy987 us448 KB
FindIntersecting (polygon)1.15 ms448 KB
FindInEnvelope (small, ~1% area)1.82 ms693 KB
FindInEnvelope (large, ~25% area)60.6 ms17.8 MB
GetById9.4 us3.5 KB
Fluent QueryMeanAllocated
Distance + order + limit254 us85 KB
Spatial + property filter1.44 ms426 KB
Spatial only (envelope)2.02 ms852 KB
Property filter only (no spatial)87 ms7.23 MB