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)),