From 3af2270ebd4353b735fde7af5b5a3be4d6f7f190 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?F=C3=B6ldi=20Tam=C3=A1s?= Date: Sat, 26 Oct 2024 07:20:48 -0400 Subject: [PATCH] Map View and `GeoPoints` archetype (#6561) ### What Map Space View for GNSS/GPS data logged through new GPS Coordinates archetype. https://github.com/rerun-io/rerun/assets/82426/86b13ba3-97af-47d2-9422-7052d7064265 - Added a new `re_space_view_map` crate for visualizing `Points3D` with gps coordinates. - `map_visualizer_system.rs` implements the `VisualizerSystem` trait. It has only one meaningful function, that takes the `Positions3D` components and turns into `vec` array along with optional `Color` and `Radius` components. This `vec` is the only field of the `MapVisualizerSystem`. - `map_space_view.rs` is where the magic happens. It uses `walkers` slippy map implementation to show an OpenStreetMap or Mapbox map. On the `selection_ui ` you can change the map providers. To view Mapbox maps, you need to set mapbox tokens (you can get free tokens from Mapbox's site) and pass it via the env variable (`MAPBOX_ACCESS_TOKEN`) or via the blueprint - `map_windows.rs` is a small helper to show the zoom controls and acknowledgment on the UIs. - For blueprints I made `MapProvider` component (enum with providers+styles), and a `MapOptions` archetype. The logging of data is performed as follows: ```rust //! Log some GPS coordinates fn main() -> Result<(), Box> { let rec = rerun::RecordingStreamBuilder::new("rerun_example_gps_coordinates").spawn()?; rec.log( "points", &rerun::Points3D::new([(47.6344, 19.1397, 0.0), (47.6344, 19.1399, 1.0)]), )?; Ok(()) } ``` The blueprint is defined as follows: ```python """Use a blueprint to show a map.""" import rerun as rr import rerun.blueprint as rrb rr.init("rerun_example_gps_coordinates", spawn=True) rr.log("points", Points3D([[47.6344, 19.1397, 0], [47.6334, 19.1399, 1]])) # Create a map view to display the chart. blueprint = rrb.Blueprint( rrb.MapView( origin="points", name="MapView", map_options=rrb.archetypes.MapOptions(provider=rrb.components.MapProvider.MapboxStreets), ), collapse_panels=True, ) rr.send_blueprint(blueprint) ``` The PR is not perfect, but the view is usable. Please review the changes and evaluate their potential utility for your needs. If you don't like, prefer not to merge just close it - no hard feelings. ### To be discussed * Check with you guys to see if the name is right at all. Maybe instead of GPS we can go with something better * Position3D is limited to `f32` instead of `f64`. This makes it less precise than `/NavSatFix` ### Checklist * [x] I have read and agree to [Contributor Guide](https://github.com/rerun-io/rerun/blob/main/CONTRIBUTING.md) and the [Code of Conduct](https://github.com/rerun-io/rerun/blob/main/CODE_OF_CONDUCT.md) * [x] I've included a screenshot or gif (if applicable) * [x] I have tested the web demo (if applicable): * Using my own lame demo app which is not part of the PR. * [x] The PR title and labels are set such as to maximize their usefulness for the next release's CHANGELOG - [PR Build Summary](https://build.rerun.io/pr/6561) - [Recent benchmark results](https://build.rerun.io/graphs/crates.html) - [Wasm size tracking](https://build.rerun.io/graphs/sizes.html) To run all checks from `main`, comment on the PR with `@rerun-bot full-check`. --------- Co-authored-by: Antoine Beyeler --- ARCHITECTURE.md | 12 +- Cargo.lock | 844 +++++++++++++++++- Cargo.toml | 3 +- .../re_types/definitions/rerun/archetypes.fbs | 1 + .../rerun/archetypes/geo_points.fbs | 33 + .../rerun/blueprint/archetypes.fbs | 2 + .../blueprint/archetypes/map_background.fbs | 15 + .../rerun/blueprint/archetypes/map_zoom.fbs | 16 + .../rerun/blueprint/components.fbs | 2 + .../blueprint/components/map_provider.fbs | 29 + .../rerun/blueprint/components/zoom_level.fbs | 14 + .../definitions/rerun/blueprint/views.fbs | 1 + .../definitions/rerun/blueprint/views/map.fbs | 16 + .../re_types/definitions/rerun/components.fbs | 1 + .../definitions/rerun/components/latlon.fbs | 15 + .../re_types/definitions/rerun/datatypes.fbs | 1 + .../definitions/rerun/datatypes/dvec2d.fbs | 16 + .../re_types/src/archetypes/.gitattributes | 1 + .../re_types/src/archetypes/geo_points.rs | 230 +++++ crates/store/re_types/src/archetypes/mod.rs | 2 + .../src/blueprint/archetypes/.gitattributes | 2 + .../blueprint/archetypes/map_background.rs | 157 ++++ .../src/blueprint/archetypes/map_zoom.rs | 155 ++++ .../re_types/src/blueprint/archetypes/mod.rs | 4 + .../src/blueprint/components/.gitattributes | 2 + .../src/blueprint/components/map_provider.rs | 181 ++++ .../re_types/src/blueprint/components/mod.rs | 4 + .../src/blueprint/components/zoom_level.rs | 115 +++ .../src/blueprint/views/.gitattributes | 1 + .../re_types/src/blueprint/views/map_view.rs | 49 + .../store/re_types/src/blueprint/views/mod.rs | 2 + .../re_types/src/components/.gitattributes | 1 + .../store/re_types/src/components/lat_lon.rs | 113 +++ .../re_types/src/components/lat_lon_ext.rs | 25 + crates/store/re_types/src/components/mod.rs | 3 + .../re_types/src/datatypes/.gitattributes | 1 + crates/store/re_types/src/datatypes/dvec2d.rs | 252 ++++++ .../re_types/src/datatypes/dvec2d_ext.rs | 103 +++ crates/store/re_types/src/datatypes/mod.rs | 3 + crates/top/rerun-cli/Cargo.toml | 7 +- crates/top/rerun/Cargo.toml | 5 + crates/utils/re_case/src/lib.rs | 6 +- crates/utils/re_log/src/lib.rs | 2 + .../src/datatype_uis/float_drag.rs | 14 +- .../re_component_ui/src/datatype_uis/mod.rs | 5 +- .../src/datatype_uis/singleline_string.rs | 8 +- crates/viewer/re_component_ui/src/lib.rs | 8 +- .../viewer/re_component_ui/src/zoom_level.rs | 27 + .../src/visible_time_range_ui.rs | 2 + crates/viewer/re_space_view_map/Cargo.toml | 34 + crates/viewer/re_space_view_map/README.md | 10 + crates/viewer/re_space_view_map/src/lib.rs | 9 + .../re_space_view_map/src/map_overlays.rs | 65 ++ .../re_space_view_map/src/map_space_view.rs | 284 ++++++ .../src/visualizers/geo_points.rs | 163 ++++ .../re_space_view_map/src/visualizers/mod.rs | 119 +++ .../viewer/re_ui/data/icons/spaceview_map.png | Bin 0 -> 601 bytes crates/viewer/re_ui/src/icons.rs | 1 + crates/viewer/re_viewer/Cargo.toml | 4 + crates/viewer/re_viewer/src/app.rs | 2 + .../src/blueprint/validation_gen/mod.rs | 4 + crates/viewer/re_viewer/src/reflection/mod.rs | 65 ++ .../re_viewer_context/src/space_view/mod.rs | 3 + deny.toml | 3 +- docs/content/reference/types/archetypes.md | 4 + .../reference/types/archetypes/.gitattributes | 1 + .../reference/types/archetypes/geo_points.md | 24 + docs/content/reference/types/components.md | 1 + .../reference/types/components/.gitattributes | 1 + .../reference/types/components/color.md | 1 + .../reference/types/components/lat_lon.md | 20 + .../reference/types/components/radius.md | 1 + docs/content/reference/types/datatypes.md | 1 + .../reference/types/datatypes/.gitattributes | 1 + .../reference/types/datatypes/dvec2d.md | 20 + docs/content/reference/types/views.md | 1 + .../reference/types/views/.gitattributes | 1 + .../content/reference/types/views/map_view.md | 28 + docs/snippets/all/views/map.py | 22 + rerun_cpp/src/rerun/archetypes.hpp | 1 + rerun_cpp/src/rerun/archetypes/.gitattributes | 2 + rerun_cpp/src/rerun/archetypes/geo_points.cpp | 43 + rerun_cpp/src/rerun/archetypes/geo_points.hpp | 77 ++ rerun_cpp/src/rerun/blueprint/archetypes.hpp | 2 + .../rerun/blueprint/archetypes/.gitattributes | 4 + .../blueprint/archetypes/map_background.cpp | 34 + .../blueprint/archetypes/map_background.hpp | 54 ++ .../rerun/blueprint/archetypes/map_zoom.cpp | 33 + .../rerun/blueprint/archetypes/map_zoom.hpp | 53 ++ rerun_cpp/src/rerun/blueprint/components.hpp | 2 + .../rerun/blueprint/components/.gitattributes | 3 + .../blueprint/components/map_provider.cpp | 58 ++ .../blueprint/components/map_provider.hpp | 69 ++ .../rerun/blueprint/components/zoom_level.hpp | 74 ++ rerun_cpp/src/rerun/components.hpp | 1 + rerun_cpp/src/rerun/components/.gitattributes | 1 + rerun_cpp/src/rerun/components/lat_lon.hpp | 88 ++ .../src/rerun/components/lat_lon_ext.cpp | 31 + rerun_cpp/src/rerun/datatypes.hpp | 1 + rerun_cpp/src/rerun/datatypes/.gitattributes | 2 + rerun_cpp/src/rerun/datatypes/dvec2d.cpp | 63 ++ rerun_cpp/src/rerun/datatypes/dvec2d.hpp | 75 ++ rerun_cpp/src/rerun/datatypes/dvec2d_ext.cpp | 34 + rerun_py/docs/gen_common_index.py | 7 + rerun_py/rerun_sdk/rerun/__init__.py | 1 + .../rerun_sdk/rerun/archetypes/.gitattributes | 1 + .../rerun_sdk/rerun/archetypes/__init__.py | 2 + .../rerun_sdk/rerun/archetypes/geo_points.py | 104 +++ .../rerun_sdk/rerun/blueprint/__init__.py | 1 + .../rerun/blueprint/archetypes/.gitattributes | 2 + .../rerun/blueprint/archetypes/__init__.py | 4 + .../blueprint/archetypes/map_background.py | 68 ++ .../rerun/blueprint/archetypes/map_zoom.py | 69 ++ .../rerun/blueprint/components/.gitattributes | 2 + .../rerun/blueprint/components/__init__.py | 10 + .../blueprint/components/map_provider.py | 106 +++ .../rerun/blueprint/components/zoom_level.py | 36 + .../rerun/blueprint/views/.gitattributes | 1 + .../rerun/blueprint/views/__init__.py | 2 + .../rerun/blueprint/views/map_view.py | 118 +++ .../rerun_sdk/rerun/components/.gitattributes | 1 + .../rerun_sdk/rerun/components/__init__.py | 4 + .../rerun_sdk/rerun/components/lat_lon.py | 36 + .../rerun_sdk/rerun/datatypes/.gitattributes | 1 + .../rerun_sdk/rerun/datatypes/__init__.py | 6 + rerun_py/rerun_sdk/rerun/datatypes/dvec2d.py | 68 ++ .../rerun_sdk/rerun/datatypes/dvec2d_ext.py | 31 + .../check_all_components_ui.py | 1 + 128 files changed, 4832 insertions(+), 59 deletions(-) create mode 100644 crates/store/re_types/definitions/rerun/archetypes/geo_points.fbs create mode 100644 crates/store/re_types/definitions/rerun/blueprint/archetypes/map_background.fbs create mode 100644 crates/store/re_types/definitions/rerun/blueprint/archetypes/map_zoom.fbs create mode 100644 crates/store/re_types/definitions/rerun/blueprint/components/map_provider.fbs create mode 100644 crates/store/re_types/definitions/rerun/blueprint/components/zoom_level.fbs create mode 100644 crates/store/re_types/definitions/rerun/blueprint/views/map.fbs create mode 100644 crates/store/re_types/definitions/rerun/components/latlon.fbs create mode 100644 crates/store/re_types/definitions/rerun/datatypes/dvec2d.fbs create mode 100644 crates/store/re_types/src/archetypes/geo_points.rs create mode 100644 crates/store/re_types/src/blueprint/archetypes/map_background.rs create mode 100644 crates/store/re_types/src/blueprint/archetypes/map_zoom.rs create mode 100644 crates/store/re_types/src/blueprint/components/map_provider.rs create mode 100644 crates/store/re_types/src/blueprint/components/zoom_level.rs create mode 100644 crates/store/re_types/src/blueprint/views/map_view.rs create mode 100644 crates/store/re_types/src/components/lat_lon.rs create mode 100644 crates/store/re_types/src/components/lat_lon_ext.rs create mode 100644 crates/store/re_types/src/datatypes/dvec2d.rs create mode 100644 crates/store/re_types/src/datatypes/dvec2d_ext.rs create mode 100644 crates/viewer/re_component_ui/src/zoom_level.rs create mode 100644 crates/viewer/re_space_view_map/Cargo.toml create mode 100644 crates/viewer/re_space_view_map/README.md create mode 100644 crates/viewer/re_space_view_map/src/lib.rs create mode 100644 crates/viewer/re_space_view_map/src/map_overlays.rs create mode 100644 crates/viewer/re_space_view_map/src/map_space_view.rs create mode 100644 crates/viewer/re_space_view_map/src/visualizers/geo_points.rs create mode 100644 crates/viewer/re_space_view_map/src/visualizers/mod.rs create mode 100644 crates/viewer/re_ui/data/icons/spaceview_map.png create mode 100644 docs/content/reference/types/archetypes/geo_points.md create mode 100644 docs/content/reference/types/components/lat_lon.md create mode 100644 docs/content/reference/types/datatypes/dvec2d.md create mode 100644 docs/content/reference/types/views/map_view.md create mode 100644 docs/snippets/all/views/map.py create mode 100644 rerun_cpp/src/rerun/archetypes/geo_points.cpp create mode 100644 rerun_cpp/src/rerun/archetypes/geo_points.hpp create mode 100644 rerun_cpp/src/rerun/blueprint/archetypes/map_background.cpp create mode 100644 rerun_cpp/src/rerun/blueprint/archetypes/map_background.hpp create mode 100644 rerun_cpp/src/rerun/blueprint/archetypes/map_zoom.cpp create mode 100644 rerun_cpp/src/rerun/blueprint/archetypes/map_zoom.hpp create mode 100644 rerun_cpp/src/rerun/blueprint/components/map_provider.cpp create mode 100644 rerun_cpp/src/rerun/blueprint/components/map_provider.hpp create mode 100644 rerun_cpp/src/rerun/blueprint/components/zoom_level.hpp create mode 100644 rerun_cpp/src/rerun/components/lat_lon.hpp create mode 100644 rerun_cpp/src/rerun/components/lat_lon_ext.cpp create mode 100644 rerun_cpp/src/rerun/datatypes/dvec2d.cpp create mode 100644 rerun_cpp/src/rerun/datatypes/dvec2d.hpp create mode 100644 rerun_cpp/src/rerun/datatypes/dvec2d_ext.cpp create mode 100644 rerun_py/rerun_sdk/rerun/archetypes/geo_points.py create mode 100644 rerun_py/rerun_sdk/rerun/blueprint/archetypes/map_background.py create mode 100644 rerun_py/rerun_sdk/rerun/blueprint/archetypes/map_zoom.py create mode 100644 rerun_py/rerun_sdk/rerun/blueprint/components/map_provider.py create mode 100644 rerun_py/rerun_sdk/rerun/blueprint/components/zoom_level.py create mode 100644 rerun_py/rerun_sdk/rerun/blueprint/views/map_view.py create mode 100644 rerun_py/rerun_sdk/rerun/components/lat_lon.py create mode 100644 rerun_py/rerun_sdk/rerun/datatypes/dvec2d.py create mode 100644 rerun_py/rerun_sdk/rerun/datatypes/dvec2d_ext.py diff --git a/ARCHITECTURE.md b/ARCHITECTURE.md index cdd9347e7980..611a6da980eb 100644 --- a/ARCHITECTURE.md +++ b/ARCHITECTURE.md @@ -88,15 +88,14 @@ Of course, this will only take us so far. In the future we plan on caching queri Here is an overview of the crates included in the project: - - - - - + + + + + - + +Geospatial points with positions expressed in EPSG:4326 altitude and longitude, and optional colors and radii. + +**Note**: Geospatial entities are experimental. + +## Components + +**Required**: [`LatLon`](../components/lat_lon.md) + +**Recommended**: [`Radius`](../components/radius.md), [`Color`](../components/color.md) + +## Shown in +* [MapView](../views/map_view.md) +* [DataframeView](../views/dataframe_view.md) + +## API reference links + * 🌊 [C++ API docs for `GeoPoints`](https://ref.rerun.io/docs/cpp/stable/structrerun_1_1archetypes_1_1GeoPoints.html?speculative-link) + * 🐍 [Python API docs for `GeoPoints`](https://ref.rerun.io/docs/python/stable/common/archetypes?speculative-link#rerun.archetypes.GeoPoints) + * 🦀 [Rust API docs for `GeoPoints`](https://docs.rs/rerun/latest/rerun/archetypes/struct.GeoPoints.html?speculative-link) + diff --git a/docs/content/reference/types/components.md b/docs/content/reference/types/components.md index 2132eb2acd2a..798724396464 100644 --- a/docs/content/reference/types/components.md +++ b/docs/content/reference/types/components.md @@ -35,6 +35,7 @@ on [Entities and Components](../../concepts/entity-component.md). * [`ImageFormat`](components/image_format.md): The metadata describing the contents of a [`components.ImageBuffer`](https://rerun.io/docs/reference/types/components/image_buffer). * [`ImagePlaneDistance`](components/image_plane_distance.md): The distance from the camera origin to the image plane when the projection is shown in a 3D viewer. * [`KeypointId`](components/keypoint_id.md): A 16-bit ID representing a type of semantic keypoint within a class. +* [`LatLon`](components/lat_lon.md): A geographical position expressed in EPSG:4326 latitude and longitude. * [`LineStrip2D`](components/line_strip2d.md): A line strip in 2D space. * [`LineStrip3D`](components/line_strip3d.md): A line strip in 3D space. * [`MagnificationFilter`](components/magnification_filter.md): Filter used when magnifying an image/texture such that a single pixel/texel is displayed as multiple pixels on screen. diff --git a/docs/content/reference/types/components/.gitattributes b/docs/content/reference/types/components/.gitattributes index c07d94eee94f..a3e8630da4a9 100644 --- a/docs/content/reference/types/components/.gitattributes +++ b/docs/content/reference/types/components/.gitattributes @@ -23,6 +23,7 @@ image_buffer.md linguist-generated=true image_format.md linguist-generated=true image_plane_distance.md linguist-generated=true keypoint_id.md linguist-generated=true +lat_lon.md linguist-generated=true line_strip2d.md linguist-generated=true line_strip3d.md linguist-generated=true magnification_filter.md linguist-generated=true diff --git a/docs/content/reference/types/components/color.md b/docs/content/reference/types/components/color.md index c5703e66ea2f..7fc08869822d 100644 --- a/docs/content/reference/types/components/color.md +++ b/docs/content/reference/types/components/color.md @@ -26,6 +26,7 @@ byte is `R` and the least significant byte is `A`. * [`Boxes2D`](../archetypes/boxes2d.md) * [`Boxes3D`](../archetypes/boxes3d.md) * [`Ellipsoids3D`](../archetypes/ellipsoids3d.md) +* [`GeoPoints`](../archetypes/geo_points.md?speculative-link) * [`LineStrips2D`](../archetypes/line_strips2d.md) * [`LineStrips3D`](../archetypes/line_strips3d.md) * [`Mesh3D`](../archetypes/mesh3d.md) diff --git a/docs/content/reference/types/components/lat_lon.md b/docs/content/reference/types/components/lat_lon.md new file mode 100644 index 000000000000..5dfd2835a7da --- /dev/null +++ b/docs/content/reference/types/components/lat_lon.md @@ -0,0 +1,20 @@ +--- +title: "LatLon" +--- + + +A geographical position expressed in EPSG:4326 latitude and longitude. + +## Fields + +* lat_lon: [`DVec2D`](../datatypes/dvec2d.md) + +## API reference links + * 🌊 [C++ API docs for `LatLon`](https://ref.rerun.io/docs/cpp/stable/structrerun_1_1components_1_1LatLon.html?speculative-link) + * 🐍 [Python API docs for `LatLon`](https://ref.rerun.io/docs/python/stable/common/components?speculative-link#rerun.components.LatLon) + * 🦀 [Rust API docs for `LatLon`](https://docs.rs/rerun/latest/rerun/components/struct.LatLon.html?speculative-link) + + +## Used by + +* [`GeoPoints`](../archetypes/geo_points.md?speculative-link) diff --git a/docs/content/reference/types/components/radius.md b/docs/content/reference/types/components/radius.md index e180c8d5a312..b3d4c91f59f5 100644 --- a/docs/content/reference/types/components/radius.md +++ b/docs/content/reference/types/components/radius.md @@ -29,6 +29,7 @@ The Viewer's UI scaling defaults to the OS scaling which typically is 100% for f * [`Boxes2D`](../archetypes/boxes2d.md) * [`Boxes3D`](../archetypes/boxes3d.md) * [`Ellipsoids3D`](../archetypes/ellipsoids3d.md) +* [`GeoPoints`](../archetypes/geo_points.md?speculative-link) * [`LineStrips2D`](../archetypes/line_strips2d.md) * [`LineStrips3D`](../archetypes/line_strips3d.md) * [`Points2D`](../archetypes/points2d.md) diff --git a/docs/content/reference/types/datatypes.md b/docs/content/reference/types/datatypes.md index c5b333ee7fb4..bb33cebb6c34 100644 --- a/docs/content/reference/types/datatypes.md +++ b/docs/content/reference/types/datatypes.md @@ -16,6 +16,7 @@ Data types are the lowest layer of the data model hierarchy. They are re-usable * [`ClassDescriptionMapElem`](datatypes/class_description_map_elem.md): A helper type for mapping [`datatypes.ClassId`](https://rerun.io/docs/reference/types/datatypes/class_id)s to class descriptions. * [`ClassId`](datatypes/class_id.md): A 16-bit ID representing a type of semantic class. * [`ColorModel`](datatypes/color_model.md): Specified what color components are present in an [`archetypes.Image`](https://rerun.io/docs/reference/types/archetypes/image). +* [`DVec2D`](datatypes/dvec2d.md): A double-precision vector in 2D space. * [`EntityPath`](datatypes/entity_path.md): A path to an entity in the `ChunkStore`. * [`Float32`](datatypes/float32.md): A single-precision 32-bit IEEE 754 floating point number. * [`Float64`](datatypes/float64.md): A double-precision 64-bit IEEE 754 floating point number. diff --git a/docs/content/reference/types/datatypes/.gitattributes b/docs/content/reference/types/datatypes/.gitattributes index 0998d55ed838..408958b8fb1c 100644 --- a/docs/content/reference/types/datatypes/.gitattributes +++ b/docs/content/reference/types/datatypes/.gitattributes @@ -10,6 +10,7 @@ class_description.md linguist-generated=true class_description_map_elem.md linguist-generated=true class_id.md linguist-generated=true color_model.md linguist-generated=true +dvec2d.md linguist-generated=true entity_path.md linguist-generated=true float32.md linguist-generated=true float64.md linguist-generated=true diff --git a/docs/content/reference/types/datatypes/dvec2d.md b/docs/content/reference/types/datatypes/dvec2d.md new file mode 100644 index 000000000000..f39668b29bdf --- /dev/null +++ b/docs/content/reference/types/datatypes/dvec2d.md @@ -0,0 +1,20 @@ +--- +title: "DVec2D" +--- + + +A double-precision vector in 2D space. + +## Fields + +* xy: 2x `f64` + +## API reference links + * 🌊 [C++ API docs for `DVec2D`](https://ref.rerun.io/docs/cpp/stable/structrerun_1_1datatypes_1_1DVec2D.html?speculative-link) + * 🐍 [Python API docs for `DVec2D`](https://ref.rerun.io/docs/python/stable/common/datatypes?speculative-link#rerun.datatypes.DVec2D) + * 🦀 [Rust API docs for `DVec2D`](https://docs.rs/rerun/latest/rerun/datatypes/struct.DVec2D.html?speculative-link) + + +## Used by + +* [`LatLon`](../components/lat_lon.md?speculative-link) diff --git a/docs/content/reference/types/views.md b/docs/content/reference/types/views.md index 8d7b8e11948c..3593e261a958 100644 --- a/docs/content/reference/types/views.md +++ b/docs/content/reference/types/views.md @@ -9,6 +9,7 @@ Views are the panels shown in the viewer's viewport and the primary means of ins * [`BarChartView`](views/bar_chart_view.md): A bar chart view. * [`DataframeView`](views/dataframe_view.md): A view to display any data in a tabular form. +* [`MapView`](views/map_view.md): A 2D map view to display geospatial primitives. * [`Spatial2DView`](views/spatial2d_view.md): For viewing spatial 2D data. * [`Spatial3DView`](views/spatial3d_view.md): For viewing spatial 3D data. * [`TensorView`](views/tensor_view.md): A view on a tensor of any dimensionality. diff --git a/docs/content/reference/types/views/.gitattributes b/docs/content/reference/types/views/.gitattributes index ee86a2002ccb..bf43e7d7a6a8 100644 --- a/docs/content/reference/types/views/.gitattributes +++ b/docs/content/reference/types/views/.gitattributes @@ -3,6 +3,7 @@ .gitattributes linguist-generated=true bar_chart_view.md linguist-generated=true dataframe_view.md linguist-generated=true +map_view.md linguist-generated=true spatial2d_view.md linguist-generated=true spatial3d_view.md linguist-generated=true tensor_view.md linguist-generated=true diff --git a/docs/content/reference/types/views/map_view.md b/docs/content/reference/types/views/map_view.md new file mode 100644 index 000000000000..730d94cbd175 --- /dev/null +++ b/docs/content/reference/types/views/map_view.md @@ -0,0 +1,28 @@ +--- +title: "MapView" +--- + + +A 2D map view to display geospatial primitives. + +## Properties + +### `zoom` +Configures the zoom level of the map view. +### `background` +Configuration for the background map of the map view. + +## API reference links + * 🐍 [Python API docs for `MapView`](https://ref.rerun.io/docs/python/stable/common/blueprint_views?speculative-link#rerun.blueprint.views.MapView) + +## Example + +### Use a blueprint to create a map view. + +snippet: views/map + + +## Visualized archetypes + +* [`GeoPoints`](../archetypes/geo_points.md) + diff --git a/docs/snippets/all/views/map.py b/docs/snippets/all/views/map.py new file mode 100644 index 000000000000..64fa46a4f48c --- /dev/null +++ b/docs/snippets/all/views/map.py @@ -0,0 +1,22 @@ +"""Use a blueprint to show a map.""" + +import rerun as rr +import rerun.blueprint as rrb + +rr.init("rerun_example_map_view", spawn=True) + +rr.log("points", rr.GeoPoints([[47.6344, 19.1397], [47.6334, 19.1399]])) + +# Create a map view to display the chart. +# TODO(#7903): cleanup the blueprint API for the map view +blueprint = rrb.Blueprint( + rrb.MapView( + origin="points", + name="MapView", + zoom=rrb.archetypes.MapZoom(16.0), + background=rrb.archetypes.MapBackground(rrb.components.MapProvider.OpenStreetMap), + ), + collapse_panels=True, +) + +rr.send_blueprint(blueprint) diff --git a/rerun_cpp/src/rerun/archetypes.hpp b/rerun_cpp/src/rerun/archetypes.hpp index 4922c62f6956..12b9bc511b9a 100644 --- a/rerun_cpp/src/rerun/archetypes.hpp +++ b/rerun_cpp/src/rerun/archetypes.hpp @@ -15,6 +15,7 @@ #include "archetypes/disconnected_space.hpp" #include "archetypes/ellipsoids3d.hpp" #include "archetypes/encoded_image.hpp" +#include "archetypes/geo_points.hpp" #include "archetypes/image.hpp" #include "archetypes/instance_poses3d.hpp" #include "archetypes/line_strips2d.hpp" diff --git a/rerun_cpp/src/rerun/archetypes/.gitattributes b/rerun_cpp/src/rerun/archetypes/.gitattributes index 0151357a4f60..c95d5b78136f 100644 --- a/rerun_cpp/src/rerun/archetypes/.gitattributes +++ b/rerun_cpp/src/rerun/archetypes/.gitattributes @@ -27,6 +27,8 @@ ellipsoids3d.cpp linguist-generated=true ellipsoids3d.hpp linguist-generated=true encoded_image.cpp linguist-generated=true encoded_image.hpp linguist-generated=true +geo_points.cpp linguist-generated=true +geo_points.hpp linguist-generated=true image.cpp linguist-generated=true image.hpp linguist-generated=true instance_poses3d.cpp linguist-generated=true diff --git a/rerun_cpp/src/rerun/archetypes/geo_points.cpp b/rerun_cpp/src/rerun/archetypes/geo_points.cpp new file mode 100644 index 000000000000..dfd990f5e8a8 --- /dev/null +++ b/rerun_cpp/src/rerun/archetypes/geo_points.cpp @@ -0,0 +1,43 @@ +// DO NOT EDIT! This file was auto-generated by crates/build/re_types_builder/src/codegen/cpp/mod.rs +// Based on "crates/store/re_types/definitions/rerun/archetypes/geo_points.fbs". + +#include "geo_points.hpp" + +#include "../collection_adapter_builtins.hpp" + +namespace rerun::archetypes {} + +namespace rerun { + + Result> AsComponents::serialize( + const archetypes::GeoPoints& archetype + ) { + using namespace archetypes; + std::vector cells; + cells.reserve(4); + + { + auto result = ComponentBatch::from_loggable(archetype.positions); + RR_RETURN_NOT_OK(result.error); + cells.push_back(std::move(result.value)); + } + if (archetype.radii.has_value()) { + auto result = ComponentBatch::from_loggable(archetype.radii.value()); + RR_RETURN_NOT_OK(result.error); + cells.push_back(std::move(result.value)); + } + if (archetype.colors.has_value()) { + auto result = ComponentBatch::from_loggable(archetype.colors.value()); + RR_RETURN_NOT_OK(result.error); + cells.push_back(std::move(result.value)); + } + { + auto indicator = GeoPoints::IndicatorComponent(); + auto result = ComponentBatch::from_loggable(indicator); + RR_RETURN_NOT_OK(result.error); + cells.emplace_back(std::move(result.value)); + } + + return cells; + } +} // namespace rerun diff --git a/rerun_cpp/src/rerun/archetypes/geo_points.hpp b/rerun_cpp/src/rerun/archetypes/geo_points.hpp new file mode 100644 index 000000000000..4f58ca761083 --- /dev/null +++ b/rerun_cpp/src/rerun/archetypes/geo_points.hpp @@ -0,0 +1,77 @@ +// DO NOT EDIT! This file was auto-generated by crates/build/re_types_builder/src/codegen/cpp/mod.rs +// Based on "crates/store/re_types/definitions/rerun/archetypes/geo_points.fbs". + +#pragma once + +#include "../collection.hpp" +#include "../compiler_utils.hpp" +#include "../component_batch.hpp" +#include "../components/color.hpp" +#include "../components/lat_lon.hpp" +#include "../components/radius.hpp" +#include "../indicator_component.hpp" +#include "../result.hpp" + +#include +#include +#include +#include + +namespace rerun::archetypes { + /// **Archetype**: Geospatial points with positions expressed in EPSG:4326 altitude and longitude, and optional colors and radii. + /// + /// **Note**: Geospatial entities are experimental. + struct GeoPoints { + /// The EPSG:4326 coordinates for the points. + Collection positions; + + /// Optional radii for the points, effectively turning them into circles. + std::optional> radii; + + /// Optional colors for the points. + std::optional> colors; + + public: + static constexpr const char IndicatorComponentName[] = + "rerun.components.GeoPointsIndicator"; + + /// Indicator component, used to identify the archetype when converting to a list of components. + using IndicatorComponent = rerun::components::IndicatorComponent; + + public: + GeoPoints() = default; + GeoPoints(GeoPoints&& other) = default; + + explicit GeoPoints(Collection _positions) + : positions(std::move(_positions)) {} + + /// Optional radii for the points, effectively turning them into circles. + GeoPoints with_radii(Collection _radii) && { + radii = std::move(_radii); + // See: https://github.com/rerun-io/rerun/issues/4027 + RR_WITH_MAYBE_UNINITIALIZED_DISABLED(return std::move(*this);) + } + + /// Optional colors for the points. + GeoPoints with_colors(Collection _colors) && { + colors = std::move(_colors); + // See: https://github.com/rerun-io/rerun/issues/4027 + RR_WITH_MAYBE_UNINITIALIZED_DISABLED(return std::move(*this);) + } + }; + +} // namespace rerun::archetypes + +namespace rerun { + /// \private + template + struct AsComponents; + + /// \private + template <> + struct AsComponents { + /// Serialize all set component batches. + static Result> serialize(const archetypes::GeoPoints& archetype + ); + }; +} // namespace rerun diff --git a/rerun_cpp/src/rerun/blueprint/archetypes.hpp b/rerun_cpp/src/rerun/blueprint/archetypes.hpp index eae71f6b2164..2fd779424b1f 100644 --- a/rerun_cpp/src/rerun/blueprint/archetypes.hpp +++ b/rerun_cpp/src/rerun/blueprint/archetypes.hpp @@ -5,6 +5,8 @@ #include "blueprint/archetypes/background.hpp" #include "blueprint/archetypes/container_blueprint.hpp" #include "blueprint/archetypes/dataframe_query.hpp" +#include "blueprint/archetypes/map_background.hpp" +#include "blueprint/archetypes/map_zoom.hpp" #include "blueprint/archetypes/panel_blueprint.hpp" #include "blueprint/archetypes/plot_legend.hpp" #include "blueprint/archetypes/scalar_axis.hpp" diff --git a/rerun_cpp/src/rerun/blueprint/archetypes/.gitattributes b/rerun_cpp/src/rerun/blueprint/archetypes/.gitattributes index 40240eeaa29b..26e1a60b89a6 100644 --- a/rerun_cpp/src/rerun/blueprint/archetypes/.gitattributes +++ b/rerun_cpp/src/rerun/blueprint/archetypes/.gitattributes @@ -7,6 +7,10 @@ container_blueprint.cpp linguist-generated=true container_blueprint.hpp linguist-generated=true dataframe_query.cpp linguist-generated=true dataframe_query.hpp linguist-generated=true +map_background.cpp linguist-generated=true +map_background.hpp linguist-generated=true +map_zoom.cpp linguist-generated=true +map_zoom.hpp linguist-generated=true panel_blueprint.cpp linguist-generated=true panel_blueprint.hpp linguist-generated=true plot_legend.cpp linguist-generated=true diff --git a/rerun_cpp/src/rerun/blueprint/archetypes/map_background.cpp b/rerun_cpp/src/rerun/blueprint/archetypes/map_background.cpp new file mode 100644 index 000000000000..dab7d3dbbd1c --- /dev/null +++ b/rerun_cpp/src/rerun/blueprint/archetypes/map_background.cpp @@ -0,0 +1,34 @@ +// DO NOT EDIT! This file was auto-generated by crates/build/re_types_builder/src/codegen/cpp/mod.rs +// Based on "crates/store/re_types/definitions/rerun/blueprint/archetypes/map_background.fbs". + +#include "map_background.hpp" + +#include "../../collection_adapter_builtins.hpp" + +namespace rerun::blueprint::archetypes {} + +namespace rerun { + + Result> + AsComponents::serialize( + const blueprint::archetypes::MapBackground& archetype + ) { + using namespace blueprint::archetypes; + std::vector cells; + cells.reserve(2); + + { + auto result = ComponentBatch::from_loggable(archetype.provider); + RR_RETURN_NOT_OK(result.error); + cells.push_back(std::move(result.value)); + } + { + auto indicator = MapBackground::IndicatorComponent(); + auto result = ComponentBatch::from_loggable(indicator); + RR_RETURN_NOT_OK(result.error); + cells.emplace_back(std::move(result.value)); + } + + return cells; + } +} // namespace rerun diff --git a/rerun_cpp/src/rerun/blueprint/archetypes/map_background.hpp b/rerun_cpp/src/rerun/blueprint/archetypes/map_background.hpp new file mode 100644 index 000000000000..3d63b252107f --- /dev/null +++ b/rerun_cpp/src/rerun/blueprint/archetypes/map_background.hpp @@ -0,0 +1,54 @@ +// DO NOT EDIT! This file was auto-generated by crates/build/re_types_builder/src/codegen/cpp/mod.rs +// Based on "crates/store/re_types/definitions/rerun/blueprint/archetypes/map_background.fbs". + +#pragma once + +#include "../../blueprint/components/map_provider.hpp" +#include "../../collection.hpp" +#include "../../component_batch.hpp" +#include "../../indicator_component.hpp" +#include "../../result.hpp" + +#include +#include +#include + +namespace rerun::blueprint::archetypes { + /// **Archetype**: Configuration for the background map of the map view. + struct MapBackground { + /// Map provider and style to use. + /// + /// **Note**: Requires a Mapbox API key in the `RERUN_MAPBOX_ACCESS_TOKEN` environment variable. + rerun::blueprint::components::MapProvider provider; + + public: + static constexpr const char IndicatorComponentName[] = + "rerun.blueprint.components.MapBackgroundIndicator"; + + /// Indicator component, used to identify the archetype when converting to a list of components. + using IndicatorComponent = rerun::components::IndicatorComponent; + + public: + MapBackground() = default; + MapBackground(MapBackground&& other) = default; + + explicit MapBackground(rerun::blueprint::components::MapProvider _provider) + : provider(std::move(_provider)) {} + }; + +} // namespace rerun::blueprint::archetypes + +namespace rerun { + /// \private + template + struct AsComponents; + + /// \private + template <> + struct AsComponents { + /// Serialize all set component batches. + static Result> serialize( + const blueprint::archetypes::MapBackground& archetype + ); + }; +} // namespace rerun diff --git a/rerun_cpp/src/rerun/blueprint/archetypes/map_zoom.cpp b/rerun_cpp/src/rerun/blueprint/archetypes/map_zoom.cpp new file mode 100644 index 000000000000..a4f7f16d4798 --- /dev/null +++ b/rerun_cpp/src/rerun/blueprint/archetypes/map_zoom.cpp @@ -0,0 +1,33 @@ +// DO NOT EDIT! This file was auto-generated by crates/build/re_types_builder/src/codegen/cpp/mod.rs +// Based on "crates/store/re_types/definitions/rerun/blueprint/archetypes/map_zoom.fbs". + +#include "map_zoom.hpp" + +#include "../../collection_adapter_builtins.hpp" + +namespace rerun::blueprint::archetypes {} + +namespace rerun { + + Result> AsComponents::serialize( + const blueprint::archetypes::MapZoom& archetype + ) { + using namespace blueprint::archetypes; + std::vector cells; + cells.reserve(2); + + { + auto result = ComponentBatch::from_loggable(archetype.zoom); + RR_RETURN_NOT_OK(result.error); + cells.push_back(std::move(result.value)); + } + { + auto indicator = MapZoom::IndicatorComponent(); + auto result = ComponentBatch::from_loggable(indicator); + RR_RETURN_NOT_OK(result.error); + cells.emplace_back(std::move(result.value)); + } + + return cells; + } +} // namespace rerun diff --git a/rerun_cpp/src/rerun/blueprint/archetypes/map_zoom.hpp b/rerun_cpp/src/rerun/blueprint/archetypes/map_zoom.hpp new file mode 100644 index 000000000000..4c4b3a65901a --- /dev/null +++ b/rerun_cpp/src/rerun/blueprint/archetypes/map_zoom.hpp @@ -0,0 +1,53 @@ +// DO NOT EDIT! This file was auto-generated by crates/build/re_types_builder/src/codegen/cpp/mod.rs +// Based on "crates/store/re_types/definitions/rerun/blueprint/archetypes/map_zoom.fbs". + +#pragma once + +#include "../../blueprint/components/zoom_level.hpp" +#include "../../collection.hpp" +#include "../../component_batch.hpp" +#include "../../indicator_component.hpp" +#include "../../result.hpp" + +#include +#include +#include + +namespace rerun::blueprint::archetypes { + /// **Archetype**: Configuration of the map view zoom level. + struct MapZoom { + /// Zoom level for the map. + /// + /// Zoom level follow the [`OpenStreetMap` definition](https://wiki.openstreetmap.org/wiki/Zoom_levels). + rerun::blueprint::components::ZoomLevel zoom; + + public: + static constexpr const char IndicatorComponentName[] = + "rerun.blueprint.components.MapZoomIndicator"; + + /// Indicator component, used to identify the archetype when converting to a list of components. + using IndicatorComponent = rerun::components::IndicatorComponent; + + public: + MapZoom() = default; + MapZoom(MapZoom&& other) = default; + + explicit MapZoom(rerun::blueprint::components::ZoomLevel _zoom) : zoom(std::move(_zoom)) {} + }; + +} // namespace rerun::blueprint::archetypes + +namespace rerun { + /// \private + template + struct AsComponents; + + /// \private + template <> + struct AsComponents { + /// Serialize all set component batches. + static Result> serialize( + const blueprint::archetypes::MapZoom& archetype + ); + }; +} // namespace rerun diff --git a/rerun_cpp/src/rerun/blueprint/components.hpp b/rerun_cpp/src/rerun/blueprint/components.hpp index 7f08ea1cf13d..9499183c3571 100644 --- a/rerun_cpp/src/rerun/blueprint/components.hpp +++ b/rerun_cpp/src/rerun/blueprint/components.hpp @@ -18,6 +18,7 @@ #include "blueprint/components/included_space_view.hpp" #include "blueprint/components/interactive.hpp" #include "blueprint/components/lock_range_during_zoom.hpp" +#include "blueprint/components/map_provider.hpp" #include "blueprint/components/panel_state.hpp" #include "blueprint/components/query_expression.hpp" #include "blueprint/components/root_container.hpp" @@ -34,3 +35,4 @@ #include "blueprint/components/visible_time_range.hpp" #include "blueprint/components/visual_bounds2d.hpp" #include "blueprint/components/visualizer_overrides.hpp" +#include "blueprint/components/zoom_level.hpp" diff --git a/rerun_cpp/src/rerun/blueprint/components/.gitattributes b/rerun_cpp/src/rerun/blueprint/components/.gitattributes index 6e54a8293f6e..8bf0eaf38c0e 100644 --- a/rerun_cpp/src/rerun/blueprint/components/.gitattributes +++ b/rerun_cpp/src/rerun/blueprint/components/.gitattributes @@ -20,6 +20,8 @@ included_content.hpp linguist-generated=true included_space_view.hpp linguist-generated=true interactive.hpp linguist-generated=true lock_range_during_zoom.hpp linguist-generated=true +map_provider.cpp linguist-generated=true +map_provider.hpp linguist-generated=true panel_state.cpp linguist-generated=true panel_state.hpp linguist-generated=true query_expression.hpp linguist-generated=true @@ -38,3 +40,4 @@ visible.hpp linguist-generated=true visible_time_range.hpp linguist-generated=true visual_bounds2d.hpp linguist-generated=true visualizer_overrides.hpp linguist-generated=true +zoom_level.hpp linguist-generated=true diff --git a/rerun_cpp/src/rerun/blueprint/components/map_provider.cpp b/rerun_cpp/src/rerun/blueprint/components/map_provider.cpp new file mode 100644 index 000000000000..318b228ae589 --- /dev/null +++ b/rerun_cpp/src/rerun/blueprint/components/map_provider.cpp @@ -0,0 +1,58 @@ +// DO NOT EDIT! This file was auto-generated by crates/build/re_types_builder/src/codegen/cpp/mod.rs +// Based on "crates/store/re_types/definitions/rerun/blueprint/components/map_provider.fbs". + +#include "map_provider.hpp" + +#include +#include + +namespace rerun { + const std::shared_ptr& + Loggable::arrow_datatype() { + static const auto datatype = arrow::uint8(); + return datatype; + } + + Result> Loggable::to_arrow( + const blueprint::components::MapProvider* instances, size_t num_instances + ) { + // TODO(andreas): Allow configuring the memory pool. + arrow::MemoryPool* pool = arrow::default_memory_pool(); + auto datatype = arrow_datatype(); + + ARROW_ASSIGN_OR_RAISE(auto builder, arrow::MakeBuilder(datatype, pool)) + if (instances && num_instances > 0) { + RR_RETURN_NOT_OK(Loggable::fill_arrow_array_builder( + static_cast(builder.get()), + instances, + num_instances + )); + } + std::shared_ptr array; + ARROW_RETURN_NOT_OK(builder->Finish(&array)); + return array; + } + + rerun::Error Loggable::fill_arrow_array_builder( + arrow::UInt8Builder* builder, const blueprint::components::MapProvider* elements, + size_t num_elements + ) { + if (builder == nullptr) { + return rerun::Error(ErrorCode::UnexpectedNullArgument, "Passed array builder is null."); + } + if (elements == nullptr) { + return rerun::Error( + ErrorCode::UnexpectedNullArgument, + "Cannot serialize null pointer to arrow array." + ); + } + + ARROW_RETURN_NOT_OK(builder->Reserve(static_cast(num_elements))); + for (size_t elem_idx = 0; elem_idx < num_elements; elem_idx += 1) { + const auto variant = elements[elem_idx]; + ARROW_RETURN_NOT_OK(builder->Append(static_cast(variant))); + } + + return Error::ok(); + } +} // namespace rerun diff --git a/rerun_cpp/src/rerun/blueprint/components/map_provider.hpp b/rerun_cpp/src/rerun/blueprint/components/map_provider.hpp new file mode 100644 index 000000000000..dae74d04929f --- /dev/null +++ b/rerun_cpp/src/rerun/blueprint/components/map_provider.hpp @@ -0,0 +1,69 @@ +// DO NOT EDIT! This file was auto-generated by crates/build/re_types_builder/src/codegen/cpp/mod.rs +// Based on "crates/store/re_types/definitions/rerun/blueprint/components/map_provider.fbs". + +#pragma once + +#include "../../result.hpp" + +#include +#include + +namespace arrow { + /// \private + template + class NumericBuilder; + + class Array; + class DataType; + class UInt8Type; + using UInt8Builder = NumericBuilder; +} // namespace arrow + +namespace rerun::blueprint::components { + /// **Component**: Name of the map provider to be used in Map views. + enum class MapProvider : uint8_t { + + /// `OpenStreetMap` is the default map provider. + OpenStreetMap = 1, + + /// Mapbox Streets is a minimalistic map designed by Mapbox. + /// + /// **Note**: Requires a Mapbox API key in the `RERUN_MAPBOX_ACCESS_TOKEN` environment variable. + MapboxStreets = 2, + + /// Mapbox Dark is a dark-themed map designed by Mapbox. + /// + /// **Note**: Requires a Mapbox API key in the `RERUN_MAPBOX_ACCESS_TOKEN` environment variable. + MapboxDark = 3, + + /// Mapbox Satellite is a satellite map designed by Mapbox. + /// + /// **Note**: Requires a Mapbox API key in the `RERUN_MAPBOX_ACCESS_TOKEN` environment variable. + MapboxSatellite = 4, + }; +} // namespace rerun::blueprint::components + +namespace rerun { + template + struct Loggable; + + /// \private + template <> + struct Loggable { + static constexpr const char Name[] = "rerun.blueprint.components.MapProvider"; + + /// Returns the arrow data type this type corresponds to. + static const std::shared_ptr& arrow_datatype(); + + /// Serializes an array of `rerun::blueprint:: components::MapProvider` into an arrow array. + static Result> to_arrow( + const blueprint::components::MapProvider* instances, size_t num_instances + ); + + /// Fills an arrow array builder with an array of this type. + static rerun::Error fill_arrow_array_builder( + arrow::UInt8Builder* builder, const blueprint::components::MapProvider* elements, + size_t num_elements + ); + }; +} // namespace rerun diff --git a/rerun_cpp/src/rerun/blueprint/components/zoom_level.hpp b/rerun_cpp/src/rerun/blueprint/components/zoom_level.hpp new file mode 100644 index 000000000000..a6e32f86bf52 --- /dev/null +++ b/rerun_cpp/src/rerun/blueprint/components/zoom_level.hpp @@ -0,0 +1,74 @@ +// DO NOT EDIT! This file was auto-generated by crates/build/re_types_builder/src/codegen/cpp/mod.rs +// Based on "crates/store/re_types/definitions/rerun/blueprint/components/zoom_level.fbs". + +#pragma once + +#include "../../datatypes/float32.hpp" +#include "../../result.hpp" + +#include +#include + +namespace rerun::blueprint::components { + /// **Component**: A zoom level determines how much of the world is visible on a map. + struct ZoomLevel { + /// Zoom level: 0 being the lowest zoom level (fully zoomed out) and 22 being the highest (fully zoomed in). + rerun::datatypes::Float32 zoom; + + public: + ZoomLevel() = default; + + ZoomLevel(rerun::datatypes::Float32 zoom_) : zoom(zoom_) {} + + ZoomLevel& operator=(rerun::datatypes::Float32 zoom_) { + zoom = zoom_; + return *this; + } + + ZoomLevel(float value_) : zoom(value_) {} + + ZoomLevel& operator=(float value_) { + zoom = value_; + return *this; + } + + /// Cast to the underlying Float32 datatype + operator rerun::datatypes::Float32() const { + return zoom; + } + }; +} // namespace rerun::blueprint::components + +namespace rerun { + static_assert(sizeof(rerun::datatypes::Float32) == sizeof(blueprint::components::ZoomLevel)); + + /// \private + template <> + struct Loggable { + static constexpr const char Name[] = "rerun.blueprint.components.ZoomLevel"; + + /// Returns the arrow data type this type corresponds to. + static const std::shared_ptr& arrow_datatype() { + return Loggable::arrow_datatype(); + } + + /// Serializes an array of `rerun::blueprint:: components::ZoomLevel` into an arrow array. + static Result> to_arrow( + const blueprint::components::ZoomLevel* instances, size_t num_instances + ) { + if (num_instances == 0) { + return Loggable::to_arrow(nullptr, 0); + } else if (instances == nullptr) { + return rerun::Error( + ErrorCode::UnexpectedNullArgument, + "Passed array instances is null when num_elements> 0." + ); + } else { + return Loggable::to_arrow( + &instances->zoom, + num_instances + ); + } + } + }; +} // namespace rerun diff --git a/rerun_cpp/src/rerun/components.hpp b/rerun_cpp/src/rerun/components.hpp index e11d74969590..4451d0a4b038 100644 --- a/rerun_cpp/src/rerun/components.hpp +++ b/rerun_cpp/src/rerun/components.hpp @@ -24,6 +24,7 @@ #include "components/image_format.hpp" #include "components/image_plane_distance.hpp" #include "components/keypoint_id.hpp" +#include "components/lat_lon.hpp" #include "components/line_strip2d.hpp" #include "components/line_strip3d.hpp" #include "components/magnification_filter.hpp" diff --git a/rerun_cpp/src/rerun/components/.gitattributes b/rerun_cpp/src/rerun/components/.gitattributes index a63cd0bb87b8..0973ed640da4 100644 --- a/rerun_cpp/src/rerun/components/.gitattributes +++ b/rerun_cpp/src/rerun/components/.gitattributes @@ -27,6 +27,7 @@ image_buffer.hpp linguist-generated=true image_format.hpp linguist-generated=true image_plane_distance.hpp linguist-generated=true keypoint_id.hpp linguist-generated=true +lat_lon.hpp linguist-generated=true line_strip2d.cpp linguist-generated=true line_strip2d.hpp linguist-generated=true line_strip3d.cpp linguist-generated=true diff --git a/rerun_cpp/src/rerun/components/lat_lon.hpp b/rerun_cpp/src/rerun/components/lat_lon.hpp new file mode 100644 index 000000000000..c17a4be43c97 --- /dev/null +++ b/rerun_cpp/src/rerun/components/lat_lon.hpp @@ -0,0 +1,88 @@ +// DO NOT EDIT! This file was auto-generated by crates/build/re_types_builder/src/codegen/cpp/mod.rs +// Based on "crates/store/re_types/definitions/rerun/components/latlon.fbs". + +#pragma once + +#include "../datatypes/dvec2d.hpp" +#include "../result.hpp" + +#include +#include +#include + +namespace rerun::components { + /// **Component**: A geographical position expressed in EPSG:4326 latitude and longitude. + struct LatLon { + rerun::datatypes::DVec2D lat_lon; + + public: // START of extensions from lat_lon_ext.cpp: + /// Construct LatLon from x/y values. + LatLon(double lat, double lon) : lat_lon{lat, lon} {} + + double latitude() const { + return lat_lon.x(); + } + + double longitude() const { + return lat_lon.y(); + } + + // END of extensions from lat_lon_ext.cpp, start of generated code: + + public: + LatLon() = default; + + LatLon(rerun::datatypes::DVec2D lat_lon_) : lat_lon(lat_lon_) {} + + LatLon& operator=(rerun::datatypes::DVec2D lat_lon_) { + lat_lon = lat_lon_; + return *this; + } + + LatLon(std::array xy_) : lat_lon(xy_) {} + + LatLon& operator=(std::array xy_) { + lat_lon = xy_; + return *this; + } + + /// Cast to the underlying DVec2D datatype + operator rerun::datatypes::DVec2D() const { + return lat_lon; + } + }; +} // namespace rerun::components + +namespace rerun { + static_assert(sizeof(rerun::datatypes::DVec2D) == sizeof(components::LatLon)); + + /// \private + template <> + struct Loggable { + static constexpr const char Name[] = "rerun.components.LatLon"; + + /// Returns the arrow data type this type corresponds to. + static const std::shared_ptr& arrow_datatype() { + return Loggable::arrow_datatype(); + } + + /// Serializes an array of `rerun::components::LatLon` into an arrow array. + static Result> to_arrow( + const components::LatLon* instances, size_t num_instances + ) { + if (num_instances == 0) { + return Loggable::to_arrow(nullptr, 0); + } else if (instances == nullptr) { + return rerun::Error( + ErrorCode::UnexpectedNullArgument, + "Passed array instances is null when num_elements> 0." + ); + } else { + return Loggable::to_arrow( + &instances->lat_lon, + num_instances + ); + } + } + }; +} // namespace rerun diff --git a/rerun_cpp/src/rerun/components/lat_lon_ext.cpp b/rerun_cpp/src/rerun/components/lat_lon_ext.cpp new file mode 100644 index 000000000000..3938ebfc0175 --- /dev/null +++ b/rerun_cpp/src/rerun/components/lat_lon_ext.cpp @@ -0,0 +1,31 @@ +#include "lat_lon.hpp" + +// Uncomment for better auto-complete while editing the extension. +// #define EDIT_EXTENSION + +namespace rerun { + namespace components { + +#ifdef EDIT_EXTENSION + struct LatLonExt { + double lat_lon[2]; +#define LatLon LatLonExt + + // + + /// Construct LatLon from x/y values. + LatLon(double lat, double lon) : lat_lon{lat, lon} {} + + double latitude() const { + return lat_lon.x(); + } + + double longitude() const { + return lat_lon.y(); + } + + // + }; +#endif + } // namespace components +} // namespace rerun diff --git a/rerun_cpp/src/rerun/datatypes.hpp b/rerun_cpp/src/rerun/datatypes.hpp index 9cd8ab48bdd2..e1ebcff3a151 100644 --- a/rerun_cpp/src/rerun/datatypes.hpp +++ b/rerun_cpp/src/rerun/datatypes.hpp @@ -11,6 +11,7 @@ #include "datatypes/class_description_map_elem.hpp" #include "datatypes/class_id.hpp" #include "datatypes/color_model.hpp" +#include "datatypes/dvec2d.hpp" #include "datatypes/entity_path.hpp" #include "datatypes/float32.hpp" #include "datatypes/float64.hpp" diff --git a/rerun_cpp/src/rerun/datatypes/.gitattributes b/rerun_cpp/src/rerun/datatypes/.gitattributes index 315de38d7a47..133573f66723 100644 --- a/rerun_cpp/src/rerun/datatypes/.gitattributes +++ b/rerun_cpp/src/rerun/datatypes/.gitattributes @@ -19,6 +19,8 @@ class_id.cpp linguist-generated=true class_id.hpp linguist-generated=true color_model.cpp linguist-generated=true color_model.hpp linguist-generated=true +dvec2d.cpp linguist-generated=true +dvec2d.hpp linguist-generated=true entity_path.cpp linguist-generated=true entity_path.hpp linguist-generated=true float32.cpp linguist-generated=true diff --git a/rerun_cpp/src/rerun/datatypes/dvec2d.cpp b/rerun_cpp/src/rerun/datatypes/dvec2d.cpp new file mode 100644 index 000000000000..ff9e24900863 --- /dev/null +++ b/rerun_cpp/src/rerun/datatypes/dvec2d.cpp @@ -0,0 +1,63 @@ +// DO NOT EDIT! This file was auto-generated by crates/build/re_types_builder/src/codegen/cpp/mod.rs +// Based on "crates/store/re_types/definitions/rerun/datatypes/dvec2d.fbs". + +#include "dvec2d.hpp" + +#include +#include + +namespace rerun::datatypes {} + +namespace rerun { + const std::shared_ptr& Loggable::arrow_datatype() { + static const auto datatype = + arrow::fixed_size_list(arrow::field("item", arrow::float64(), false), 2); + return datatype; + } + + Result> Loggable::to_arrow( + const datatypes::DVec2D* instances, size_t num_instances + ) { + // TODO(andreas): Allow configuring the memory pool. + arrow::MemoryPool* pool = arrow::default_memory_pool(); + auto datatype = arrow_datatype(); + + ARROW_ASSIGN_OR_RAISE(auto builder, arrow::MakeBuilder(datatype, pool)) + if (instances && num_instances > 0) { + RR_RETURN_NOT_OK(Loggable::fill_arrow_array_builder( + static_cast(builder.get()), + instances, + num_instances + )); + } + std::shared_ptr array; + ARROW_RETURN_NOT_OK(builder->Finish(&array)); + return array; + } + + rerun::Error Loggable::fill_arrow_array_builder( + arrow::FixedSizeListBuilder* builder, const datatypes::DVec2D* elements, size_t num_elements + ) { + if (builder == nullptr) { + return rerun::Error(ErrorCode::UnexpectedNullArgument, "Passed array builder is null."); + } + if (elements == nullptr) { + return rerun::Error( + ErrorCode::UnexpectedNullArgument, + "Cannot serialize null pointer to arrow array." + ); + } + + auto value_builder = static_cast(builder->value_builder()); + + ARROW_RETURN_NOT_OK(builder->AppendValues(static_cast(num_elements))); + static_assert(sizeof(elements[0].xy) == sizeof(elements[0])); + ARROW_RETURN_NOT_OK(value_builder->AppendValues( + elements[0].xy.data(), + static_cast(num_elements * 2), + nullptr + )); + + return Error::ok(); + } +} // namespace rerun diff --git a/rerun_cpp/src/rerun/datatypes/dvec2d.hpp b/rerun_cpp/src/rerun/datatypes/dvec2d.hpp new file mode 100644 index 000000000000..881c78112749 --- /dev/null +++ b/rerun_cpp/src/rerun/datatypes/dvec2d.hpp @@ -0,0 +1,75 @@ +// DO NOT EDIT! This file was auto-generated by crates/build/re_types_builder/src/codegen/cpp/mod.rs +// Based on "crates/store/re_types/definitions/rerun/datatypes/dvec2d.fbs". + +#pragma once + +#include "../result.hpp" + +#include +#include +#include + +namespace arrow { + class Array; + class DataType; + class FixedSizeListBuilder; +} // namespace arrow + +namespace rerun::datatypes { + /// **Datatype**: A double-precision vector in 2D space. + struct DVec2D { + std::array xy; + + public: // START of extensions from dvec2d_ext.cpp: + /// Construct DVec2D from x/y values. + DVec2D(double x, double y) : xy{x, y} {} + + /// Construct DVec2D from x/y double pointer. + explicit DVec2D(const double* xy_) : xy{xy_[0], xy_[1]} {} + + double x() const { + return xy[0]; + } + + double y() const { + return xy[1]; + } + + // END of extensions from dvec2d_ext.cpp, start of generated code: + + public: + DVec2D() = default; + + DVec2D(std::array xy_) : xy(xy_) {} + + DVec2D& operator=(std::array xy_) { + xy = xy_; + return *this; + } + }; +} // namespace rerun::datatypes + +namespace rerun { + template + struct Loggable; + + /// \private + template <> + struct Loggable { + static constexpr const char Name[] = "rerun.datatypes.DVec2D"; + + /// Returns the arrow data type this type corresponds to. + static const std::shared_ptr& arrow_datatype(); + + /// Serializes an array of `rerun::datatypes::DVec2D` into an arrow array. + static Result> to_arrow( + const datatypes::DVec2D* instances, size_t num_instances + ); + + /// Fills an arrow array builder with an array of this type. + static rerun::Error fill_arrow_array_builder( + arrow::FixedSizeListBuilder* builder, const datatypes::DVec2D* elements, + size_t num_elements + ); + }; +} // namespace rerun diff --git a/rerun_cpp/src/rerun/datatypes/dvec2d_ext.cpp b/rerun_cpp/src/rerun/datatypes/dvec2d_ext.cpp new file mode 100644 index 000000000000..aec931e932d5 --- /dev/null +++ b/rerun_cpp/src/rerun/datatypes/dvec2d_ext.cpp @@ -0,0 +1,34 @@ +#include "dvec2d.hpp" + +// Uncomment for better auto-complete while editing the extension. +// #define EDIT_EXTENSION + +namespace rerun { + namespace datatypes { + +#ifdef EDIT_EXTENSION + struct DVec2DExt { + double xy[2]; +#define DVec2D DVec2DExt + + // + + /// Construct DVec2D from x/y values. + DVec2D(double x, double y) : xy{x, y} {} + + /// Construct DVec2D from x/y double pointer. + explicit DVec2D(const double* xy_) : xy{xy_[0], xy_[1]} {} + + double x() const { + return xy[0]; + } + + double y() const { + return xy[1]; + } + + // + }; +#endif + } // namespace datatypes +} // namespace rerun diff --git a/rerun_py/docs/gen_common_index.py b/rerun_py/docs/gen_common_index.py index 2056f52e673c..8462277bb0d3 100755 --- a/rerun_py/docs/gen_common_index.py +++ b/rerun_py/docs/gen_common_index.py @@ -207,6 +207,13 @@ class Section: ], gen_page=False, ), + Section( + title="Geospatial Archetypes", + class_list=[ + "archetypes.GeoPoints", + ], + gen_page=False, + ), Section( title="Tensors", class_list=["archetypes.Tensor"], diff --git a/rerun_py/rerun_sdk/rerun/__init__.py b/rerun_py/rerun_sdk/rerun/__init__.py index 42df3f2fc339..ef36706e1059 100644 --- a/rerun_py/rerun_sdk/rerun/__init__.py +++ b/rerun_py/rerun_sdk/rerun/__init__.py @@ -64,6 +64,7 @@ DisconnectedSpace as DisconnectedSpace, Ellipsoids3D as Ellipsoids3D, EncodedImage as EncodedImage, + GeoPoints as GeoPoints, Image as Image, InstancePoses3D as InstancePoses3D, LineStrips2D as LineStrips2D, diff --git a/rerun_py/rerun_sdk/rerun/archetypes/.gitattributes b/rerun_py/rerun_sdk/rerun/archetypes/.gitattributes index b57110b5036e..1e2fbcfe9406 100644 --- a/rerun_py/rerun_sdk/rerun/archetypes/.gitattributes +++ b/rerun_py/rerun_sdk/rerun/archetypes/.gitattributes @@ -15,6 +15,7 @@ depth_image.py linguist-generated=true disconnected_space.py linguist-generated=true ellipsoids3d.py linguist-generated=true encoded_image.py linguist-generated=true +geo_points.py linguist-generated=true image.py linguist-generated=true instance_poses3d.py linguist-generated=true line_strips2d.py linguist-generated=true diff --git a/rerun_py/rerun_sdk/rerun/archetypes/__init__.py b/rerun_py/rerun_sdk/rerun/archetypes/__init__.py index 8ba5d3fcdee3..bb31399d85ff 100644 --- a/rerun_py/rerun_sdk/rerun/archetypes/__init__.py +++ b/rerun_py/rerun_sdk/rerun/archetypes/__init__.py @@ -15,6 +15,7 @@ from .disconnected_space import DisconnectedSpace from .ellipsoids3d import Ellipsoids3D from .encoded_image import EncodedImage +from .geo_points import GeoPoints from .image import Image from .instance_poses3d import InstancePoses3D from .line_strips2d import LineStrips2D @@ -48,6 +49,7 @@ "DisconnectedSpace", "Ellipsoids3D", "EncodedImage", + "GeoPoints", "Image", "InstancePoses3D", "LineStrips2D", diff --git a/rerun_py/rerun_sdk/rerun/archetypes/geo_points.py b/rerun_py/rerun_sdk/rerun/archetypes/geo_points.py new file mode 100644 index 000000000000..3cec4449b52b --- /dev/null +++ b/rerun_py/rerun_sdk/rerun/archetypes/geo_points.py @@ -0,0 +1,104 @@ +# DO NOT EDIT! This file was auto-generated by crates/build/re_types_builder/src/codegen/python/mod.rs +# Based on "crates/store/re_types/definitions/rerun/archetypes/geo_points.fbs". + +# You can extend this class by creating a "GeoPointsExt" class in "geo_points_ext.py". + +from __future__ import annotations + +from typing import Any + +from attrs import define, field + +from .. import components, datatypes +from .._baseclasses import ( + Archetype, +) +from ..error_utils import catch_and_log_exceptions + +__all__ = ["GeoPoints"] + + +@define(str=False, repr=False, init=False) +class GeoPoints(Archetype): + """ + **Archetype**: Geospatial points with positions expressed in EPSG:4326 altitude and longitude, and optional colors and radii. + + **Note**: Geospatial entities are experimental. + """ + + def __init__( + self: Any, + positions: datatypes.DVec2DArrayLike, + *, + radii: datatypes.Float32ArrayLike | None = None, + colors: datatypes.Rgba32ArrayLike | None = None, + ): + """ + Create a new instance of the GeoPoints archetype. + + Parameters + ---------- + positions: + The EPSG:4326 coordinates for the points. + radii: + Optional radii for the points, effectively turning them into circles. + colors: + Optional colors for the points. + + The colors are interpreted as RGB or RGBA in sRGB gamma-space, + As either 0-1 floats or 0-255 integers, with separate alpha. + + """ + + # You can define your own __init__ function as a member of GeoPointsExt in geo_points_ext.py + with catch_and_log_exceptions(context=self.__class__.__name__): + self.__attrs_init__(positions=positions, radii=radii, colors=colors) + return + self.__attrs_clear__() + + def __attrs_clear__(self) -> None: + """Convenience method for calling `__attrs_init__` with all `None`s.""" + self.__attrs_init__( + positions=None, # type: ignore[arg-type] + radii=None, # type: ignore[arg-type] + colors=None, # type: ignore[arg-type] + ) + + @classmethod + def _clear(cls) -> GeoPoints: + """Produce an empty GeoPoints, bypassing `__init__`.""" + inst = cls.__new__(cls) + inst.__attrs_clear__() + return inst + + positions: components.LatLonBatch = field( + metadata={"component": "required"}, + converter=components.LatLonBatch._required, # type: ignore[misc] + ) + # The EPSG:4326 coordinates for the points. + # + # (Docstring intentionally commented out to hide this field from the docs) + + radii: components.RadiusBatch | None = field( + metadata={"component": "optional"}, + default=None, + converter=components.RadiusBatch._optional, # type: ignore[misc] + ) + # Optional radii for the points, effectively turning them into circles. + # + # (Docstring intentionally commented out to hide this field from the docs) + + colors: components.ColorBatch | None = field( + metadata={"component": "optional"}, + default=None, + converter=components.ColorBatch._optional, # type: ignore[misc] + ) + # Optional colors for the points. + # + # The colors are interpreted as RGB or RGBA in sRGB gamma-space, + # As either 0-1 floats or 0-255 integers, with separate alpha. + # + # (Docstring intentionally commented out to hide this field from the docs) + + __str__ = Archetype.__str__ + __repr__ = Archetype.__repr__ # type: ignore[assignment] diff --git a/rerun_py/rerun_sdk/rerun/blueprint/__init__.py b/rerun_py/rerun_sdk/rerun/blueprint/__init__.py index 0da791c5fb26..3ba51bcc058f 100644 --- a/rerun_py/rerun_sdk/rerun/blueprint/__init__.py +++ b/rerun_py/rerun_sdk/rerun/blueprint/__init__.py @@ -52,6 +52,7 @@ from .views import ( BarChartView as BarChartView, DataframeView as DataframeView, + MapView as MapView, Spatial2DView as Spatial2DView, Spatial3DView as Spatial3DView, TensorView as TensorView, diff --git a/rerun_py/rerun_sdk/rerun/blueprint/archetypes/.gitattributes b/rerun_py/rerun_sdk/rerun/blueprint/archetypes/.gitattributes index 1db9a825f2e9..bb528bfbaf9a 100644 --- a/rerun_py/rerun_sdk/rerun/blueprint/archetypes/.gitattributes +++ b/rerun_py/rerun_sdk/rerun/blueprint/archetypes/.gitattributes @@ -5,6 +5,8 @@ __init__.py linguist-generated=true background.py linguist-generated=true container_blueprint.py linguist-generated=true dataframe_query.py linguist-generated=true +map_background.py linguist-generated=true +map_zoom.py linguist-generated=true panel_blueprint.py linguist-generated=true plot_legend.py linguist-generated=true scalar_axis.py linguist-generated=true diff --git a/rerun_py/rerun_sdk/rerun/blueprint/archetypes/__init__.py b/rerun_py/rerun_sdk/rerun/blueprint/archetypes/__init__.py index 423f025dc7aa..018ec6c34d5e 100644 --- a/rerun_py/rerun_sdk/rerun/blueprint/archetypes/__init__.py +++ b/rerun_py/rerun_sdk/rerun/blueprint/archetypes/__init__.py @@ -5,6 +5,8 @@ from .background import Background from .container_blueprint import ContainerBlueprint from .dataframe_query import DataframeQuery +from .map_background import MapBackground +from .map_zoom import MapZoom from .panel_blueprint import PanelBlueprint from .plot_legend import PlotLegend from .scalar_axis import ScalarAxis @@ -21,6 +23,8 @@ "Background", "ContainerBlueprint", "DataframeQuery", + "MapBackground", + "MapZoom", "PanelBlueprint", "PlotLegend", "ScalarAxis", diff --git a/rerun_py/rerun_sdk/rerun/blueprint/archetypes/map_background.py b/rerun_py/rerun_sdk/rerun/blueprint/archetypes/map_background.py new file mode 100644 index 000000000000..bd32323fc481 --- /dev/null +++ b/rerun_py/rerun_sdk/rerun/blueprint/archetypes/map_background.py @@ -0,0 +1,68 @@ +# DO NOT EDIT! This file was auto-generated by crates/build/re_types_builder/src/codegen/python/mod.rs +# Based on "crates/store/re_types/definitions/rerun/blueprint/archetypes/map_background.fbs". + +# You can extend this class by creating a "MapBackgroundExt" class in "map_background_ext.py". + +from __future__ import annotations + +from typing import Any + +from attrs import define, field + +from ..._baseclasses import ( + Archetype, +) +from ...blueprint import components as blueprint_components +from ...error_utils import catch_and_log_exceptions + +__all__ = ["MapBackground"] + + +@define(str=False, repr=False, init=False) +class MapBackground(Archetype): + """**Archetype**: Configuration for the background map of the map view.""" + + def __init__(self: Any, provider: blueprint_components.MapProviderLike): + """ + Create a new instance of the MapBackground archetype. + + Parameters + ---------- + provider: + Map provider and style to use. + + **Note**: Requires a Mapbox API key in the `RERUN_MAPBOX_ACCESS_TOKEN` environment variable. + + """ + + # You can define your own __init__ function as a member of MapBackgroundExt in map_background_ext.py + with catch_and_log_exceptions(context=self.__class__.__name__): + self.__attrs_init__(provider=provider) + return + self.__attrs_clear__() + + def __attrs_clear__(self) -> None: + """Convenience method for calling `__attrs_init__` with all `None`s.""" + self.__attrs_init__( + provider=None, # type: ignore[arg-type] + ) + + @classmethod + def _clear(cls) -> MapBackground: + """Produce an empty MapBackground, bypassing `__init__`.""" + inst = cls.__new__(cls) + inst.__attrs_clear__() + return inst + + provider: blueprint_components.MapProviderBatch = field( + metadata={"component": "required"}, + converter=blueprint_components.MapProviderBatch._required, # type: ignore[misc] + ) + # Map provider and style to use. + # + # **Note**: Requires a Mapbox API key in the `RERUN_MAPBOX_ACCESS_TOKEN` environment variable. + # + # (Docstring intentionally commented out to hide this field from the docs) + + __str__ = Archetype.__str__ + __repr__ = Archetype.__repr__ # type: ignore[assignment] diff --git a/rerun_py/rerun_sdk/rerun/blueprint/archetypes/map_zoom.py b/rerun_py/rerun_sdk/rerun/blueprint/archetypes/map_zoom.py new file mode 100644 index 000000000000..60f518bd77b8 --- /dev/null +++ b/rerun_py/rerun_sdk/rerun/blueprint/archetypes/map_zoom.py @@ -0,0 +1,69 @@ +# DO NOT EDIT! This file was auto-generated by crates/build/re_types_builder/src/codegen/python/mod.rs +# Based on "crates/store/re_types/definitions/rerun/blueprint/archetypes/map_zoom.fbs". + +# You can extend this class by creating a "MapZoomExt" class in "map_zoom_ext.py". + +from __future__ import annotations + +from typing import Any + +from attrs import define, field + +from ... import datatypes +from ..._baseclasses import ( + Archetype, +) +from ...blueprint import components as blueprint_components +from ...error_utils import catch_and_log_exceptions + +__all__ = ["MapZoom"] + + +@define(str=False, repr=False, init=False) +class MapZoom(Archetype): + """**Archetype**: Configuration of the map view zoom level.""" + + def __init__(self: Any, zoom: datatypes.Float32Like): + """ + Create a new instance of the MapZoom archetype. + + Parameters + ---------- + zoom: + Zoom level for the map. + + Zoom level follow the [`OpenStreetMap` definition](https://wiki.openstreetmap.org/wiki/Zoom_levels). + + """ + + # You can define your own __init__ function as a member of MapZoomExt in map_zoom_ext.py + with catch_and_log_exceptions(context=self.__class__.__name__): + self.__attrs_init__(zoom=zoom) + return + self.__attrs_clear__() + + def __attrs_clear__(self) -> None: + """Convenience method for calling `__attrs_init__` with all `None`s.""" + self.__attrs_init__( + zoom=None, # type: ignore[arg-type] + ) + + @classmethod + def _clear(cls) -> MapZoom: + """Produce an empty MapZoom, bypassing `__init__`.""" + inst = cls.__new__(cls) + inst.__attrs_clear__() + return inst + + zoom: blueprint_components.ZoomLevelBatch = field( + metadata={"component": "required"}, + converter=blueprint_components.ZoomLevelBatch._required, # type: ignore[misc] + ) + # Zoom level for the map. + # + # Zoom level follow the [`OpenStreetMap` definition](https://wiki.openstreetmap.org/wiki/Zoom_levels). + # + # (Docstring intentionally commented out to hide this field from the docs) + + __str__ = Archetype.__str__ + __repr__ = Archetype.__repr__ # type: ignore[assignment] diff --git a/rerun_py/rerun_sdk/rerun/blueprint/components/.gitattributes b/rerun_py/rerun_sdk/rerun/blueprint/components/.gitattributes index 44c616a62b0a..d169ad0ec28c 100644 --- a/rerun_py/rerun_sdk/rerun/blueprint/components/.gitattributes +++ b/rerun_py/rerun_sdk/rerun/blueprint/components/.gitattributes @@ -18,6 +18,7 @@ included_content.py linguist-generated=true included_space_view.py linguist-generated=true interactive.py linguist-generated=true lock_range_during_zoom.py linguist-generated=true +map_provider.py linguist-generated=true panel_state.py linguist-generated=true query_expression.py linguist-generated=true root_container.py linguist-generated=true @@ -34,3 +35,4 @@ visible.py linguist-generated=true visible_time_range.py linguist-generated=true visual_bounds2d.py linguist-generated=true visualizer_overrides.py linguist-generated=true +zoom_level.py linguist-generated=true diff --git a/rerun_py/rerun_sdk/rerun/blueprint/components/__init__.py b/rerun_py/rerun_sdk/rerun/blueprint/components/__init__.py index 7ed14ed9c1f8..1f82d7bb448a 100644 --- a/rerun_py/rerun_sdk/rerun/blueprint/components/__init__.py +++ b/rerun_py/rerun_sdk/rerun/blueprint/components/__init__.py @@ -34,6 +34,7 @@ from .included_space_view import IncludedSpaceView, IncludedSpaceViewBatch, IncludedSpaceViewType from .interactive import Interactive, InteractiveBatch, InteractiveType from .lock_range_during_zoom import LockRangeDuringZoom, LockRangeDuringZoomBatch, LockRangeDuringZoomType +from .map_provider import MapProvider, MapProviderArrayLike, MapProviderBatch, MapProviderLike, MapProviderType from .panel_state import PanelState, PanelStateArrayLike, PanelStateBatch, PanelStateLike, PanelStateType from .query_expression import QueryExpression, QueryExpressionBatch, QueryExpressionType from .root_container import RootContainer, RootContainerBatch, RootContainerType @@ -58,6 +59,7 @@ from .visible_time_range import VisibleTimeRange, VisibleTimeRangeBatch, VisibleTimeRangeType from .visual_bounds2d import VisualBounds2D, VisualBounds2DBatch, VisualBounds2DType from .visualizer_overrides import VisualizerOverrides, VisualizerOverridesBatch, VisualizerOverridesType +from .zoom_level import ZoomLevel, ZoomLevelBatch, ZoomLevelType __all__ = [ "ActiveTab", @@ -114,6 +116,11 @@ "LockRangeDuringZoom", "LockRangeDuringZoomBatch", "LockRangeDuringZoomType", + "MapProvider", + "MapProviderArrayLike", + "MapProviderBatch", + "MapProviderLike", + "MapProviderType", "PanelState", "PanelStateArrayLike", "PanelStateBatch", @@ -166,4 +173,7 @@ "VisualizerOverrides", "VisualizerOverridesBatch", "VisualizerOverridesType", + "ZoomLevel", + "ZoomLevelBatch", + "ZoomLevelType", ] diff --git a/rerun_py/rerun_sdk/rerun/blueprint/components/map_provider.py b/rerun_py/rerun_sdk/rerun/blueprint/components/map_provider.py new file mode 100644 index 000000000000..30fe170506cd --- /dev/null +++ b/rerun_py/rerun_sdk/rerun/blueprint/components/map_provider.py @@ -0,0 +1,106 @@ +# DO NOT EDIT! This file was auto-generated by crates/build/re_types_builder/src/codegen/python/mod.rs +# Based on "crates/store/re_types/definitions/rerun/blueprint/components/map_provider.fbs". + +# You can extend this class by creating a "MapProviderExt" class in "map_provider_ext.py". + +from __future__ import annotations + +from typing import Literal, Sequence, Union + +import pyarrow as pa + +from ..._baseclasses import ( + BaseBatch, + BaseExtensionType, + ComponentBatchMixin, +) + +__all__ = ["MapProvider", "MapProviderArrayLike", "MapProviderBatch", "MapProviderLike", "MapProviderType"] + + +from enum import Enum + + +class MapProvider(Enum): + """**Component**: Name of the map provider to be used in Map views.""" + + OpenStreetMap = 1 + """`OpenStreetMap` is the default map provider.""" + + MapboxStreets = 2 + """ + Mapbox Streets is a minimalistic map designed by Mapbox. + + **Note**: Requires a Mapbox API key in the `RERUN_MAPBOX_ACCESS_TOKEN` environment variable. + """ + + MapboxDark = 3 + """ + Mapbox Dark is a dark-themed map designed by Mapbox. + + **Note**: Requires a Mapbox API key in the `RERUN_MAPBOX_ACCESS_TOKEN` environment variable. + """ + + MapboxSatellite = 4 + """ + Mapbox Satellite is a satellite map designed by Mapbox. + + **Note**: Requires a Mapbox API key in the `RERUN_MAPBOX_ACCESS_TOKEN` environment variable. + """ + + @classmethod + def auto(cls, val: str | int | MapProvider) -> MapProvider: + """Best-effort converter, including a case-insensitive string matcher.""" + if isinstance(val, MapProvider): + return val + if isinstance(val, int): + return cls(val) + try: + return cls[val] + except KeyError: + val_lower = val.lower() + for variant in cls: + if variant.name.lower() == val_lower: + return variant + raise ValueError(f"Cannot convert {val} to {cls.__name__}") + + def __str__(self) -> str: + """Returns the variant name.""" + return self.name + + +MapProviderLike = Union[ + MapProvider, + Literal[ + "MapboxDark", + "MapboxSatellite", + "MapboxStreets", + "OpenStreetMap", + "mapboxdark", + "mapboxsatellite", + "mapboxstreets", + "openstreetmap", + ], + int, +] +MapProviderArrayLike = Union[MapProviderLike, Sequence[MapProviderLike]] + + +class MapProviderType(BaseExtensionType): + _TYPE_NAME: str = "rerun.blueprint.components.MapProvider" + + def __init__(self) -> None: + pa.ExtensionType.__init__(self, pa.uint8(), self._TYPE_NAME) + + +class MapProviderBatch(BaseBatch[MapProviderArrayLike], ComponentBatchMixin): + _ARROW_TYPE = MapProviderType() + + @staticmethod + def _native_to_pa_array(data: MapProviderArrayLike, data_type: pa.DataType) -> pa.Array: + if isinstance(data, (MapProvider, int, str)): + data = [data] + + pa_data = [MapProvider.auto(v).value if v is not None else None for v in data] # type: ignore[redundant-expr] + + return pa.array(pa_data, type=data_type) diff --git a/rerun_py/rerun_sdk/rerun/blueprint/components/zoom_level.py b/rerun_py/rerun_sdk/rerun/blueprint/components/zoom_level.py new file mode 100644 index 000000000000..ad6f066c0d18 --- /dev/null +++ b/rerun_py/rerun_sdk/rerun/blueprint/components/zoom_level.py @@ -0,0 +1,36 @@ +# DO NOT EDIT! This file was auto-generated by crates/build/re_types_builder/src/codegen/python/mod.rs +# Based on "crates/store/re_types/definitions/rerun/blueprint/components/zoom_level.fbs". + +# You can extend this class by creating a "ZoomLevelExt" class in "zoom_level_ext.py". + +from __future__ import annotations + +from ... import datatypes +from ..._baseclasses import ( + ComponentBatchMixin, + ComponentMixin, +) + +__all__ = ["ZoomLevel", "ZoomLevelBatch", "ZoomLevelType"] + + +class ZoomLevel(datatypes.Float32, ComponentMixin): + """**Component**: A zoom level determines how much of the world is visible on a map.""" + + _BATCH_TYPE = None + # You can define your own __init__ function as a member of ZoomLevelExt in zoom_level_ext.py + + # Note: there are no fields here because ZoomLevel delegates to datatypes.Float32 + pass + + +class ZoomLevelType(datatypes.Float32Type): + _TYPE_NAME: str = "rerun.blueprint.components.ZoomLevel" + + +class ZoomLevelBatch(datatypes.Float32Batch, ComponentBatchMixin): + _ARROW_TYPE = ZoomLevelType() + + +# This is patched in late to avoid circular dependencies. +ZoomLevel._BATCH_TYPE = ZoomLevelBatch # type: ignore[assignment] diff --git a/rerun_py/rerun_sdk/rerun/blueprint/views/.gitattributes b/rerun_py/rerun_sdk/rerun/blueprint/views/.gitattributes index 75df45e0a870..b95c2652ca07 100644 --- a/rerun_py/rerun_sdk/rerun/blueprint/views/.gitattributes +++ b/rerun_py/rerun_sdk/rerun/blueprint/views/.gitattributes @@ -4,6 +4,7 @@ __init__.py linguist-generated=true bar_chart_view.py linguist-generated=true dataframe_view.py linguist-generated=true +map_view.py linguist-generated=true spatial2d_view.py linguist-generated=true spatial3d_view.py linguist-generated=true tensor_view.py linguist-generated=true diff --git a/rerun_py/rerun_sdk/rerun/blueprint/views/__init__.py b/rerun_py/rerun_sdk/rerun/blueprint/views/__init__.py index c2aee9b89942..992739f85bd3 100644 --- a/rerun_py/rerun_sdk/rerun/blueprint/views/__init__.py +++ b/rerun_py/rerun_sdk/rerun/blueprint/views/__init__.py @@ -4,6 +4,7 @@ from .bar_chart_view import BarChartView from .dataframe_view import DataframeView +from .map_view import MapView from .spatial2d_view import Spatial2DView from .spatial3d_view import Spatial3DView from .tensor_view import TensorView @@ -14,6 +15,7 @@ __all__ = [ "BarChartView", "DataframeView", + "MapView", "Spatial2DView", "Spatial3DView", "TensorView", diff --git a/rerun_py/rerun_sdk/rerun/blueprint/views/map_view.py b/rerun_py/rerun_sdk/rerun/blueprint/views/map_view.py new file mode 100644 index 000000000000..19ec551472d6 --- /dev/null +++ b/rerun_py/rerun_sdk/rerun/blueprint/views/map_view.py @@ -0,0 +1,118 @@ +# DO NOT EDIT! This file was auto-generated by crates/build/re_types_builder/src/codegen/python/mod.rs +# Based on "crates/store/re_types/definitions/rerun/blueprint/views/map.fbs". + +from __future__ import annotations + +from typing import Union + +__all__ = ["MapView"] + + +from ... import datatypes +from ..._baseclasses import AsComponents, ComponentBatchLike +from ...datatypes import EntityPathLike, Utf8Like +from .. import archetypes as blueprint_archetypes +from ..api import SpaceView, SpaceViewContentsLike + + +class MapView(SpaceView): + """ + **View**: A 2D map view to display geospatial primitives. + + Example + ------- + ### Use a blueprint to create a map view.: + ```python + import rerun as rr + import rerun.blueprint as rrb + + rr.init("rerun_example_map_view", spawn=True) + + rr.log("points", rr.GeoPoints([[47.6344, 19.1397], [47.6334, 19.1399]])) + + # Create a map view to display the chart. + # TODO(#7903): cleanup the blueprint API for the map view + blueprint = rrb.Blueprint( + rrb.MapView( + origin="points", + name="MapView", + zoom=rrb.archetypes.MapZoom(16.0), + background=rrb.archetypes.MapBackground(rrb.components.MapProvider.OpenStreetMap), + ), + collapse_panels=True, + ) + + rr.send_blueprint(blueprint) + ``` + + """ + + def __init__( + self, + *, + origin: EntityPathLike = "/", + contents: SpaceViewContentsLike = "$origin/**", + name: Utf8Like | None = None, + visible: datatypes.BoolLike | None = None, + defaults: list[Union[AsComponents, ComponentBatchLike]] = [], + overrides: dict[EntityPathLike, list[ComponentBatchLike]] = {}, + zoom: blueprint_archetypes.MapZoom | None = None, + background: blueprint_archetypes.MapBackground | None = None, + ) -> None: + """ + Construct a blueprint for a new MapView view. + + Parameters + ---------- + origin: + The `EntityPath` to use as the origin of this view. + All other entities will be transformed to be displayed relative to this origin. + contents: + The contents of the view specified as a query expression. + This is either a single expression, or a list of multiple expressions. + See [rerun.blueprint.archetypes.SpaceViewContents][]. + name: + The display name of the view. + visible: + Whether this view is visible. + + Defaults to true if not specified. + defaults: + List of default components or component batches to add to the space view. When an archetype + in the view is missing a component included in this set, the value of default will be used + instead of the normal fallback for the visualizer. + overrides: + Dictionary of overrides to apply to the space view. The key is the path to the entity where the override + should be applied. The value is a list of component or component batches to apply to the entity. + + Important note: the path must be a fully qualified entity path starting at the root. The override paths + do not yet support `$origin` relative paths or glob expressions. + This will be addressed in . + zoom: + Configures the zoom level of the map view. + background: + Configuration for the background map of the map view. + + """ + + properties: dict[str, AsComponents] = {} + if zoom is not None: + if not isinstance(zoom, blueprint_archetypes.MapZoom): + zoom = blueprint_archetypes.MapZoom(zoom) + properties["MapZoom"] = zoom + + if background is not None: + if not isinstance(background, blueprint_archetypes.MapBackground): + background = blueprint_archetypes.MapBackground(background) + properties["MapBackground"] = background + + super().__init__( + class_identifier="Map", + origin=origin, + contents=contents, + name=name, + visible=visible, + properties=properties, + defaults=defaults, + overrides=overrides, + ) diff --git a/rerun_py/rerun_sdk/rerun/components/.gitattributes b/rerun_py/rerun_sdk/rerun/components/.gitattributes index 6541e94fa6eb..19b08d9c70aa 100644 --- a/rerun_py/rerun_sdk/rerun/components/.gitattributes +++ b/rerun_py/rerun_sdk/rerun/components/.gitattributes @@ -24,6 +24,7 @@ image_buffer.py linguist-generated=true image_format.py linguist-generated=true image_plane_distance.py linguist-generated=true keypoint_id.py linguist-generated=true +lat_lon.py linguist-generated=true line_strip2d.py linguist-generated=true line_strip3d.py linguist-generated=true magnification_filter.py linguist-generated=true diff --git a/rerun_py/rerun_sdk/rerun/components/__init__.py b/rerun_py/rerun_sdk/rerun/components/__init__.py index 7fa9bf8b8c02..89bf4caad67c 100644 --- a/rerun_py/rerun_sdk/rerun/components/__init__.py +++ b/rerun_py/rerun_sdk/rerun/components/__init__.py @@ -36,6 +36,7 @@ from .image_format import ImageFormat, ImageFormatBatch, ImageFormatType from .image_plane_distance import ImagePlaneDistance, ImagePlaneDistanceBatch, ImagePlaneDistanceType from .keypoint_id import KeypointId, KeypointIdBatch, KeypointIdType +from .lat_lon import LatLon, LatLonBatch, LatLonType from .line_strip2d import LineStrip2D, LineStrip2DArrayLike, LineStrip2DBatch, LineStrip2DLike, LineStrip2DType from .line_strip3d import LineStrip3D, LineStrip3DArrayLike, LineStrip3DBatch, LineStrip3DLike, LineStrip3DType from .magnification_filter import ( @@ -169,6 +170,9 @@ "KeypointId", "KeypointIdBatch", "KeypointIdType", + "LatLon", + "LatLonBatch", + "LatLonType", "LineStrip2D", "LineStrip2DArrayLike", "LineStrip2DBatch", diff --git a/rerun_py/rerun_sdk/rerun/components/lat_lon.py b/rerun_py/rerun_sdk/rerun/components/lat_lon.py new file mode 100644 index 000000000000..2777c2737dea --- /dev/null +++ b/rerun_py/rerun_sdk/rerun/components/lat_lon.py @@ -0,0 +1,36 @@ +# DO NOT EDIT! This file was auto-generated by crates/build/re_types_builder/src/codegen/python/mod.rs +# Based on "crates/store/re_types/definitions/rerun/components/latlon.fbs". + +# You can extend this class by creating a "LatLonExt" class in "lat_lon_ext.py". + +from __future__ import annotations + +from .. import datatypes +from .._baseclasses import ( + ComponentBatchMixin, + ComponentMixin, +) + +__all__ = ["LatLon", "LatLonBatch", "LatLonType"] + + +class LatLon(datatypes.DVec2D, ComponentMixin): + """**Component**: A geographical position expressed in EPSG:4326 latitude and longitude.""" + + _BATCH_TYPE = None + # You can define your own __init__ function as a member of LatLonExt in lat_lon_ext.py + + # Note: there are no fields here because LatLon delegates to datatypes.DVec2D + pass + + +class LatLonType(datatypes.DVec2DType): + _TYPE_NAME: str = "rerun.components.LatLon" + + +class LatLonBatch(datatypes.DVec2DBatch, ComponentBatchMixin): + _ARROW_TYPE = LatLonType() + + +# This is patched in late to avoid circular dependencies. +LatLon._BATCH_TYPE = LatLonBatch # type: ignore[assignment] diff --git a/rerun_py/rerun_sdk/rerun/datatypes/.gitattributes b/rerun_py/rerun_sdk/rerun/datatypes/.gitattributes index 4181907f6192..8f23c5dee36a 100644 --- a/rerun_py/rerun_sdk/rerun/datatypes/.gitattributes +++ b/rerun_py/rerun_sdk/rerun/datatypes/.gitattributes @@ -11,6 +11,7 @@ class_description.py linguist-generated=true class_description_map_elem.py linguist-generated=true class_id.py linguist-generated=true color_model.py linguist-generated=true +dvec2d.py linguist-generated=true entity_path.py linguist-generated=true float32.py linguist-generated=true float64.py linguist-generated=true diff --git a/rerun_py/rerun_sdk/rerun/datatypes/__init__.py b/rerun_py/rerun_sdk/rerun/datatypes/__init__.py index 3521f94f07d9..ada89d7b2531 100644 --- a/rerun_py/rerun_sdk/rerun/datatypes/__init__.py +++ b/rerun_py/rerun_sdk/rerun/datatypes/__init__.py @@ -35,6 +35,7 @@ ) from .class_id import ClassId, ClassIdArrayLike, ClassIdBatch, ClassIdLike, ClassIdType from .color_model import ColorModel, ColorModelArrayLike, ColorModelBatch, ColorModelLike, ColorModelType +from .dvec2d import DVec2D, DVec2DArrayLike, DVec2DBatch, DVec2DLike, DVec2DType from .entity_path import EntityPath, EntityPathArrayLike, EntityPathBatch, EntityPathLike, EntityPathType from .float32 import Float32, Float32ArrayLike, Float32Batch, Float32Like, Float32Type from .float64 import Float64, Float64ArrayLike, Float64Batch, Float64Like, Float64Type @@ -166,6 +167,11 @@ "ColorModelBatch", "ColorModelLike", "ColorModelType", + "DVec2D", + "DVec2DArrayLike", + "DVec2DBatch", + "DVec2DLike", + "DVec2DType", "EntityPath", "EntityPathArrayLike", "EntityPathBatch", diff --git a/rerun_py/rerun_sdk/rerun/datatypes/dvec2d.py b/rerun_py/rerun_sdk/rerun/datatypes/dvec2d.py new file mode 100644 index 000000000000..07a41155af50 --- /dev/null +++ b/rerun_py/rerun_sdk/rerun/datatypes/dvec2d.py @@ -0,0 +1,68 @@ +# DO NOT EDIT! This file was auto-generated by crates/build/re_types_builder/src/codegen/python/mod.rs +# Based on "crates/store/re_types/definitions/rerun/datatypes/dvec2d.fbs". + +# You can extend this class by creating a "DVec2DExt" class in "dvec2d_ext.py". + +from __future__ import annotations + +from typing import TYPE_CHECKING, Any, Sequence, Union + +import numpy as np +import numpy.typing as npt +import pyarrow as pa +from attrs import define, field + +from .._baseclasses import ( + BaseBatch, + BaseExtensionType, +) +from .._converters import ( + to_np_float64, +) +from .dvec2d_ext import DVec2DExt + +__all__ = ["DVec2D", "DVec2DArrayLike", "DVec2DBatch", "DVec2DLike", "DVec2DType"] + + +@define(init=False) +class DVec2D(DVec2DExt): + """**Datatype**: A double-precision vector in 2D space.""" + + def __init__(self: Any, xy: DVec2DLike): + """Create a new instance of the DVec2D datatype.""" + + # You can define your own __init__ function as a member of DVec2DExt in dvec2d_ext.py + self.__attrs_init__(xy=xy) + + xy: npt.NDArray[np.float64] = field(converter=to_np_float64) + + def __array__(self, dtype: npt.DTypeLike = None) -> npt.NDArray[Any]: + # You can define your own __array__ function as a member of DVec2DExt in dvec2d_ext.py + return np.asarray(self.xy, dtype=dtype) + + +if TYPE_CHECKING: + DVec2DLike = Union[DVec2D, npt.NDArray[Any], npt.ArrayLike, Sequence[float]] +else: + DVec2DLike = Any + +DVec2DArrayLike = Union[ + DVec2D, Sequence[DVec2DLike], npt.NDArray[Any], npt.ArrayLike, Sequence[Sequence[float]], Sequence[float] +] + + +class DVec2DType(BaseExtensionType): + _TYPE_NAME: str = "rerun.datatypes.DVec2D" + + def __init__(self) -> None: + pa.ExtensionType.__init__( + self, pa.list_(pa.field("item", pa.float64(), nullable=False, metadata={}), 2), self._TYPE_NAME + ) + + +class DVec2DBatch(BaseBatch[DVec2DArrayLike]): + _ARROW_TYPE = DVec2DType() + + @staticmethod + def _native_to_pa_array(data: DVec2DArrayLike, data_type: pa.DataType) -> pa.Array: + return DVec2DExt.native_to_pa_array_override(data, data_type) diff --git a/rerun_py/rerun_sdk/rerun/datatypes/dvec2d_ext.py b/rerun_py/rerun_sdk/rerun/datatypes/dvec2d_ext.py new file mode 100644 index 000000000000..e92d9cf60e97 --- /dev/null +++ b/rerun_py/rerun_sdk/rerun/datatypes/dvec2d_ext.py @@ -0,0 +1,31 @@ +from __future__ import annotations + +from typing import TYPE_CHECKING, Sequence + +import numpy as np +import pyarrow as pa + +from .._validators import flat_np_float64_array_from_array_like + +if TYPE_CHECKING: + from . import DVec2DArrayLike + +NUMPY_VERSION = tuple(map(int, np.version.version.split(".")[:2])) + + +class DVec2DExt: + """Extension for [DVec2D][rerun.datatypes.DVec2D].""" + + @staticmethod + def native_to_pa_array_override(data: DVec2DArrayLike, data_type: pa.DataType) -> pa.Array: + # TODO(ab): get rid of this once we drop support for Python 3.8. Make sure to pin numpy>=1.25. + if NUMPY_VERSION < (1, 25): + # Older numpy doesn't seem to support `data` in the form of [Point3D(1, 2), Point3D(3, 4)] + # this happens for python 3.8 (1.25 supports 3.9+) + from . import DVec2D + + if isinstance(data, Sequence): + data = [np.array(p.xy) if isinstance(p, DVec2D) else p for p in data] + + points = flat_np_float64_array_from_array_like(data, 2) + return pa.FixedSizeListArray.from_arrays(points, type=data_type) diff --git a/tests/python/release_checklist/check_all_components_ui.py b/tests/python/release_checklist/check_all_components_ui.py index 9d2f17ad221d..a1db03894aaa 100644 --- a/tests/python/release_checklist/check_all_components_ui.py +++ b/tests/python/release_checklist/check_all_components_ui.py @@ -140,6 +140,7 @@ def alternatives(self) -> list[Any] | None: ), "ImagePlaneDistanceBatch": TestCase(batch=[100.0, 200.0, 300.0]), "KeypointIdBatch": TestCase(batch=[5, 6, 7]), + "LatLonBatch": TestCase(batch=[(0, 1), (2, 3), (4, 5)]), "LineStrip2DBatch": TestCase( batch=[ ((0, 0), (1, 1), (2, 2)),