Originally posted by C-Loftus December 19, 2025
Thank you very much for your excellent work on galileo.
I am trying to adapt the georust example here to support arbitrary geometries, not just points / geojson.
I am using to georust gdal bindings which work well, but I can't figure out how to render arbitrary geometries. No matter how I convert the types to_geo2d doesn't seem to work for an arbitrary geometry.
If I try to use something like this I get an error with trait bounds
let dataset = Dataset::open(Path::new(json)).unwrap();
let mut geometries = vec![];
for mut layer in dataset.layers() {
for feature in layer.features() {
let geometry = feature.geometry().unwrap();
let geom = geometry.to_geo().unwrap();
geom.to_geo2d()
the method `to_geo2d` exists for enum `geo_types::Geometry`, but its trait bounds were not satisfied
the following trait bounds were not satisfied:
`<geo_types::Geometry as GeometryType>::Space = AmbiguousSpace`
which is required by `geo_types::Geometry: Disambiguate`
`geo_types::Geometry: GeometryType`
which is required by `geo_types::Geometry: Disambiguate`
`<&geo_types::Geometry as GeometryType>::Space = AmbiguousSpace`
which is required by `&geo_types::Geometry: Disambiguate`
`&geo_types::Geometry: GeometryType`
which is required by `&geo_types::Geometry: Disambiguate`
`<&mut geo_types::Geometry as GeometryType>::Space = AmbiguousSpace`
which is required by `&mut geo_types::Geometry: Disambiguate`
`&mut geo_types::Geometry: GeometryType`
which is required by `&mut geo_types::Geometry: Disambiguate`
My Current Code
This is some code I have that works with the rust gdal bindings, very similar to the georust example, to render points to a file. However, I am unclear how to adapt this to arbitrary geometry.
use std::error::Error;
use std::path::Path;
use std::time::Duration;
use std::vec;
use galileo::layer::FeatureLayer;
use galileo::layer::raster_tile_layer::RasterTileLayerBuilder;
use galileo::render::WgpuRenderer;
use galileo::symbol::{
ArbitraryGeometrySymbol, CirclePointSymbol, SimpleContourSymbol, SimplePolygonSymbol,
};
use galileo::tile_schema::TileSchemaBuilder;
use galileo::{Color, Map, MapView, Messenger};
use galileo_types::cartesian::Size;
use galileo_types::geo::Crs;
use galileo_types::geometry_type::GeoSpace2d;
use galileo_types::{Disambig, Disambiguate};
use gdal::Dataset;
use gdal::vector::LayerAccess;
use image::{ImageBuffer, Rgba};
fn load_points(json: &str) -> Vec<Disambig<geo_types::Point, GeoSpace2d>> {
let dataset = Dataset::open(Path::new(json)).unwrap();
let mut points = vec![];
for mut layer in dataset.layers() {
for feature in layer.features() {
let geometry = feature.geometry().unwrap();
let geom = geometry.to_geo().unwrap();
if let geo_types::Geometry::Point(point) = geom {
points.push(point.to_geo2d());
}
}
}
points
}
pub async fn generate_map(geojson: &str) -> Result<String, Box<dyn Error>> {
let symbol = ArbitraryGeometrySymbol::new(
CirclePointSymbol::new(Color::RED, 10.0),
SimpleContourSymbol::new(Color::GREEN, 2.0),
SimplePolygonSymbol::new(Color::BLUE),
);
let point_layer = FeatureLayer::new(load_points(geojson), symbol, Crs::WGS84);
// To calculate the area of the map which we want to draw, we use map's CRS instead of
// layer CRS.
let extent = point_layer
.extent_projected(&Crs::EPSG3857)
.expect("cannot project extent");
let center = extent.center();
let image_size = Size::new(400, 400);
let width_resolution = extent.width() / image_size.width() as f64;
let height_resolution = extent.height() / image_size.height() as f64;
let resolution = (width_resolution.max(height_resolution) * 1.1).max(
TileSchemaBuilder::web_mercator(0..=18)
.build()
.expect("default tile schema is valid")
.lod_resolution(10)
.expect("the tile schema has resolution for zoom level 17"),
);
// Create OSM layer for background
let mut osm = RasterTileLayerBuilder::new_osm()
.with_file_cache_checked(".tile_cache")
.build()
.expect("failed to create layer");
// If we don't set fade in duration to 0, when the image is first drawn, all tiles will
// be transparent.
osm.set_fade_in_duration(Duration::default());
let map_view = MapView::new_projected(¢er, resolution).with_size(image_size.cast());
// Load all tiles required for the given view before we request rendering.
osm.load_tiles(&map_view).await;
let map = Map::new(
map_view,
vec![Box::new(osm), Box::new(point_layer)],
None::<Box<dyn Messenger>>,
);
// We create a renderer without window, so it will use internal texture to render to.
// Every time the `render` method is called, the image is updated and can be retrieved
// by the `get_image` method.
let renderer = WgpuRenderer::new_with_texture_rt(image_size)
.await
.expect("failed to create renderer");
renderer.render(&map).expect("failed to render the map");
let bitmap = renderer
.get_image()
.await
.expect("failed to get image bitmap from texture");
let buffer =
ImageBuffer::<Rgba<u8>, _>::from_raw(image_size.width(), image_size.height(), bitmap)
.expect("failed to read bitmap");
buffer
.save("/tmp/output_map.png")
.expect("failed to encode or write image");
Ok("/tmp/output_map.png".to_string())
}
What I have tried
If I try to switch the code to just return geo_types::Geometry then I get this issue
let features = FeatureLayer::new(load_geometries(dataset), symbol, Crs::WGS84);
the trait bound `geo_types::Geometry: GeometryType` is not satisfied
the following other types implement trait `GeometryType`:
Coord<T>
Disambig<T, Space>
GeoPoint2d
Point2<Num>
galileo_mvt::contour::ClosedMvtContour
galileo_mvt::contour::MvtContour
galileo_mvt::contour::MvtContours
galileo_mvt::contour::MvtPolygon
and 12 others
required for `Disambig<geo_types::Geometry, GeoSpace2d>` to implement `galileo::layer::feature_layer::Feature`
```</div>
Discussed in #288
Originally posted by C-Loftus December 19, 2025
Thank you very much for your excellent work on galileo.
I am trying to adapt the georust example here to support arbitrary geometries, not just points / geojson.
I am using to georust gdal bindings which work well, but I can't figure out how to render arbitrary geometries. No matter how I convert the types
to_geo2ddoesn't seem to work for an arbitrary geometry.If I try to use something like this I get an error with trait bounds
My Current Code
This is some code I have that works with the rust gdal bindings, very similar to the georust example, to render points to a file. However, I am unclear how to adapt this to arbitrary geometry.
What I have tried
If I try to switch the code to just return
geo_types::Geometrythen I get this issue