Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Introduce a new component for MarkerShape and use it in SeriesPoint #5004

Merged
merged 6 commits into from
Feb 2, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
60 changes: 59 additions & 1 deletion crates/re_data_ui/src/editors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,13 @@ use re_data_store::{DataStore, LatestAtQuery};
use re_log_types::EntityPath;
use re_query::ComponentWithInstances;
use re_types::{
components::{Color, Radius, ScalarScattering, Text},
components::{Color, MarkerShape, Radius, ScalarScattering, Text},
Component, Loggable,
};
use re_viewer_context::{UiVerbosity, ViewerContext};

// ----

#[allow(clippy::too_many_arguments)]
fn edit_color_ui(
ctx: &ViewerContext<'_>,
Expand Down Expand Up @@ -55,6 +57,8 @@ fn default_color(
Color::from_rgb(255, 255, 255)
}

// ----

#[allow(clippy::too_many_arguments)]
fn edit_text_ui(
ctx: &ViewerContext<'_>,
Expand Down Expand Up @@ -94,6 +98,8 @@ fn default_text(
Text::from(entity_path.to_string())
}

// ----

#[allow(clippy::too_many_arguments)]
fn edit_scatter_ui(
ctx: &ViewerContext<'_>,
Expand Down Expand Up @@ -141,6 +147,8 @@ fn default_scatter(
ScalarScattering::from(false)
}

// ----

#[allow(clippy::too_many_arguments)]
fn edit_radius_ui(
ctx: &ViewerContext<'_>,
Expand Down Expand Up @@ -186,6 +194,55 @@ fn default_radius(
Radius::from(1.0)
}

// ----

#[allow(clippy::too_many_arguments)]
fn edit_marker_shape_ui(
ctx: &ViewerContext<'_>,
ui: &mut egui::Ui,
_verbosity: UiVerbosity,
query: &LatestAtQuery,
store: &DataStore,
entity_path: &EntityPath,
override_path: &EntityPath,
component: &ComponentWithInstances,
instance_key: &re_types::components::InstanceKey,
) {
let current_marker = component
.lookup::<MarkerShape>(instance_key)
.ok()
.unwrap_or_else(|| default_marker_shape(ctx, query, store, entity_path));

let mut edit_marker = current_marker;

let marker_text = edit_marker.as_str();

egui::ComboBox::from_id_source("marker_shape")
.selected_text(marker_text)
.show_ui(ui, |ui| {
ui.style_mut().wrap = Some(false);
for marker in MarkerShape::all_markers() {
ui.selectable_value(&mut edit_marker, marker, marker.as_str());
}
});

if edit_marker != current_marker {
ctx.save_blueprint_component(override_path, edit_marker);
}
}

#[inline]
fn default_marker_shape(
_ctx: &ViewerContext<'_>,
_query: &LatestAtQuery,
_store: &DataStore,
_entity_path: &EntityPath,
) -> MarkerShape {
MarkerShape::default()
}

// ----

fn register_editor<'a, C: Component + Loggable + 'static>(
registry: &mut re_viewer_context::ComponentUiRegistry,
default: fn(&ViewerContext<'_>, &LatestAtQuery, &DataStore, &EntityPath) -> C,
Expand Down Expand Up @@ -218,4 +275,5 @@ pub fn register_editors(registry: &mut re_viewer_context::ComponentUiRegistry) {
register_editor::<Text>(registry, default_text, edit_text_ui);
register_editor::<ScalarScattering>(registry, default_scatter, edit_scatter_ui);
register_editor::<Radius>(registry, default_radius, edit_radius_ui);
register_editor::<MarkerShape>(registry, default_marker_shape, edit_marker_shape_ui);
}
8 changes: 7 additions & 1 deletion crates/re_space_view_time_series/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ mod util;
mod visualizer_system;

use re_log_types::EntityPath;
use re_types::components::MarkerShape;
use re_viewer_context::external::re_entity_db::TimeSeriesAggregator;
pub use space_view_class::TimeSeriesSpaceView;

Expand All @@ -36,6 +37,11 @@ pub struct PlotPointAttrs {
pub kind: PlotSeriesKind,
}

#[derive(Clone, Copy, Default, Debug, PartialEq, Eq)]
pub struct ScatterAttrs {
pub marker: MarkerShape,
}

impl PartialEq for PlotPointAttrs {
fn eq(&self, rhs: &Self) -> bool {
let Self {
Expand Down Expand Up @@ -63,7 +69,7 @@ struct PlotPoint {
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub enum PlotSeriesKind {
Continuous,
Scatter,
Scatter(ScatterAttrs),
Clear,
}

Expand Down
28 changes: 23 additions & 5 deletions crates/re_space_view_time_series/src/point_visualizer_system.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
use re_query_cache::{MaybeCachedComponentData, QueryError};
use re_types::archetypes;
use re_types::components::MarkerShape;
use re_types::{
archetypes::SeriesPoint,
components::{Color, Radius, Scalar, Text},
Expand All @@ -14,6 +15,7 @@ use crate::overrides::initial_override_color;
use crate::util::{
determine_plot_bounds_and_time_per_pixel, determine_time_range, points_to_series,
};
use crate::ScatterAttrs;
use crate::{overrides::lookup_override, PlotPoint, PlotPointAttrs, PlotSeries, PlotSeriesKind};

/// The system for rendering [`SeriesPoint`] archetypes.
Expand All @@ -29,6 +31,10 @@ impl IdentifiedViewSystem for SeriesPointSystem {
}
}

// We use a larger default radius for scatter plots so the marker is
// visible.
const DEFAULT_RADIUS: f32 = 3.0;

impl VisualizerSystem for SeriesPointSystem {
fn visualizer_query_info(&self) -> VisualizerQueryInfo {
let mut query_info = VisualizerQueryInfo::from_archetype::<archetypes::Scalar>();
Expand All @@ -37,6 +43,8 @@ impl VisualizerSystem for SeriesPointSystem {
.map(ToOwned::to_owned)
.collect::<ComponentNameSet>();
query_info.queried.append(&mut series_point_queried);
// TODO(jleibs): Use StrokeWidth instead
query_info.queried.insert(Radius::name());
query_info
}

Expand Down Expand Up @@ -76,6 +84,8 @@ impl VisualizerSystem for SeriesPointSystem {
) -> Option<re_log_types::DataCell> {
if *component == Color::name() {
Some([initial_override_color(entity_path)].into())
} else if *component == Radius::name() {
Some([Radius(DEFAULT_RADIUS)].into())
} else {
None
}
Expand Down Expand Up @@ -125,16 +135,18 @@ impl SeriesPointSystem {

let override_radius = lookup_override::<Radius>(data_result, ctx).map(|r| r.0);

let override_marker = lookup_override::<MarkerShape>(data_result, ctx);

let query = re_data_store::RangeQuery::new(query.timeline, time_range);

// TODO(jleibs): need to do a "joined" archetype query
query_caches
.query_archetype_pov1_comp2::<archetypes::Scalar, Scalar, Color, Text, _>(
.query_archetype_pov1_comp3::<archetypes::Scalar, Scalar, Color, MarkerShape, Text, _>(
ctx.app_options.experimental_primary_caching_range,
store,
&query.clone().into(),
&data_result.entity_path,
|((time, _row_id), _, scalars, colors, labels)| {
|((time, _row_id), _, scalars, colors, markers, labels)| {
let Some(time) = time else {
return;
}; // scalars cannot be timeless
Expand All @@ -154,12 +166,16 @@ impl SeriesPointSystem {
return;
}

for (scalar, color, label) in itertools::izip!(
for (scalar, color, marker, label) in itertools::izip!(
scalars.iter(),
MaybeCachedComponentData::iter_or_repeat_opt(
&colors,
scalars.len()
),
MaybeCachedComponentData::iter_or_repeat_opt(
&markers,
scalars.len()
),
//MaybeCachedComponentData::iter_or_repeat_opt(&radii, scalars.len()),
MaybeCachedComponentData::iter_or_repeat_opt(
&labels,
Expand All @@ -178,7 +194,9 @@ impl SeriesPointSystem {
let radius = override_radius
.unwrap_or_else(|| radius.map_or(DEFAULT_RADIUS, |r| r.0));

const DEFAULT_RADIUS: f32 = 0.75;
let marker = override_marker.unwrap_or(marker.unwrap_or_default());



points.push(PlotPoint {
time: time.as_i64(),
Expand All @@ -187,7 +205,7 @@ impl SeriesPointSystem {
label,
color,
radius,
kind: PlotSeriesKind::Scatter,
kind: PlotSeriesKind::Scatter(ScatterAttrs{marker}),
},
});
}
Expand Down
23 changes: 12 additions & 11 deletions crates/re_space_view_time_series/src/space_view_class.rs
Original file line number Diff line number Diff line change
Expand Up @@ -406,30 +406,31 @@ It can greatly improve performance (and readability) in such situations as it pr
time_ctrl_write.pause();
}

for line in all_plot_series {
let points = line
for series in all_plot_series {
let points = series
.points
.iter()
.map(|p| [(p.0 - time_offset) as _, p.1])
.collect::<Vec<_>>();

let color = line.color;
let id = egui::Id::new(line.entity_path.hash());
plot_item_id_to_entity_path.insert(id, line.entity_path.clone());
let color = series.color;
let id = egui::Id::new(series.entity_path.hash());
plot_item_id_to_entity_path.insert(id, series.entity_path.clone());

match line.kind {
match series.kind {
PlotSeriesKind::Continuous => plot_ui.line(
Line::new(points)
.name(&line.label)
.name(&series.label)
.color(color)
.width(line.width)
.width(series.width)
.id(id),
),
PlotSeriesKind::Scatter => plot_ui.points(
PlotSeriesKind::Scatter(scatter_attrs) => plot_ui.points(
Points::new(points)
.name(&line.label)
.name(&series.label)
.color(color)
.radius(line.width)
.radius(series.width)
.shape(scatter_attrs.marker.into())
.id(id),
),
// Break up the chart. At some point we might want something fancier.
Expand Down
4 changes: 2 additions & 2 deletions crates/re_space_view_time_series/src/util.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ use re_viewer_context::{external::re_entity_db::TimeSeriesAggregator, ViewQuery,

use crate::{
aggregation::{AverageAggregator, MinMaxAggregator},
PlotPoint, PlotSeries, PlotSeriesKind,
PlotPoint, PlotSeries, PlotSeriesKind, ScatterAttrs,
};

/// Find the plot bounds and the per-ui-point delta from egui.
Expand Down Expand Up @@ -101,7 +101,7 @@ pub fn points_to_series(
// Can't draw a single point as a continuous line, so fall back on scatter
let mut kind = points[0].attrs.kind;
if kind == PlotSeriesKind::Continuous {
kind = PlotSeriesKind::Scatter;
kind = PlotSeriesKind::Scatter(ScatterAttrs::default());
}

all_series.push(PlotSeries {
Expand Down
6 changes: 3 additions & 3 deletions crates/re_space_view_time_series/src/visualizer_system.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ use re_viewer_context::{
use crate::{
overrides::{initial_override_color, lookup_override},
util::{determine_plot_bounds_and_time_per_pixel, determine_time_range, points_to_series},
PlotPoint, PlotPointAttrs, PlotSeries, PlotSeriesKind,
PlotPoint, PlotPointAttrs, PlotSeries, PlotSeriesKind, ScatterAttrs,
};

/// The legacy system for rendering [`TimeSeriesScalar`] archetypes.
Expand Down Expand Up @@ -174,8 +174,8 @@ impl LegacyTimeSeriesSystem {
let radius = override_radius
.unwrap_or_else(|| radius.map_or(DEFAULT_RADIUS, |r| r.0));

let kind = if scattered {
PlotSeriesKind::Scatter
let kind= if scattered {
PlotSeriesKind::Scatter(ScatterAttrs::default())
} else {
PlotSeriesKind::Continuous
};
Expand Down
3 changes: 3 additions & 0 deletions crates/re_types/definitions/rerun/archetypes/series_point.fbs
Original file line number Diff line number Diff line change
Expand Up @@ -18,4 +18,7 @@ table SeriesPoint (
/// Color for the corresponding series.
// TODO(jleibs): This should be batch if we make a batch Scalars loggable.
color: rerun.components.Color ("attr.rerun.component_optional", nullable, order: 1000);

/// What shape to use to represent the point
marker: rerun.components.MarkerShape ("attr.rerun.component_optional", nullable, order: 2000);
}
1 change: 1 addition & 0 deletions crates/re_types/definitions/rerun/components.fbs
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ include "./components/instance_key.fbs";
include "./components/keypoint_id.fbs";
include "./components/line_strip2d.fbs";
include "./components/line_strip3d.fbs";
include "./components/marker_shape.fbs";
include "./components/material.fbs";
include "./components/media_type.fbs";
include "./components/mesh_properties.fbs";
Expand Down
33 changes: 33 additions & 0 deletions crates/re_types/definitions/rerun/components/marker_shape.fbs
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
include "arrow/attributes.fbs";
include "python/attributes.fbs";
include "rust/attributes.fbs";

include "rerun/datatypes.fbs";
include "rerun/attributes.fbs";

namespace rerun.components;

// TODO(#3384)
/*
enum MarkerShape: byte {
Circle = 1,
Diamond = 2,
Square = 3,
Cross = 4,
Plus = 5,
Up = 6,
Down = 7,
Left = 8,
Right = 9,
Asterisk = 10,
}
*/

/// Shape of a marker.
struct MarkerShape (
"attr.docs.unreleased",
"attr.rust.derive": "PartialEq, Eq, PartialOrd, Copy",
"attr.rust.repr": "transparent"
) {
shape: ubyte (order: 100);
}
Loading
Loading