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 StrokeWidth component and use it for SeriesLine #5025

Merged
merged 6 commits into from
Feb 4, 2024
Merged
Show file tree
Hide file tree
Changes from 5 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
56 changes: 52 additions & 4 deletions crates/re_data_ui/src/editors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ use re_data_store::{DataStore, LatestAtQuery};
use re_log_types::EntityPath;
use re_query::ComponentWithInstances;
use re_types::{
components::{Color, MarkerShape, Radius, ScalarScattering, Text},
components::{Color, MarkerShape, Radius, ScalarScattering, StrokeWidth, Text},
Component, Loggable,
};
use re_viewer_context::{UiVerbosity, ViewerContext};
Expand Down Expand Up @@ -243,6 +243,53 @@ fn default_marker_shape(

// ----

#[allow(clippy::too_many_arguments)]
fn edit_stroke_width_ui(
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

it would be nice to have a module per editor

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_stroke_width = component
.lookup::<StrokeWidth>(instance_key)
.ok()
.unwrap_or_else(|| default_stroke_width(ctx, query, store, entity_path));

let current_stroke_width = current_stroke_width.0;
let mut edit_stroke_width = current_stroke_width;

let speed = (current_stroke_width * 0.01).at_least(0.001);

ui.add(
egui::DragValue::new(&mut edit_stroke_width)
.clamp_range(0.0..=f64::INFINITY)
.speed(speed),
);

if edit_stroke_width != current_stroke_width {
let new_stroke_width = StrokeWidth::from(edit_stroke_width);

ctx.save_blueprint_component(override_path, new_stroke_width);
}
}

#[inline]
fn default_stroke_width(
_ctx: &ViewerContext<'_>,
_query: &LatestAtQuery,
_store: &DataStore,
_entity_path: &EntityPath,
) -> StrokeWidth {
StrokeWidth::from(1.0)
}

// ----

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 @@ -272,8 +319,9 @@ fn register_editor<'a, C: Component + Loggable + 'static>(

pub fn register_editors(registry: &mut re_viewer_context::ComponentUiRegistry) {
register_editor::<Color>(registry, default_color, edit_color_ui);
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);
register_editor::<Radius>(registry, default_radius, edit_radius_ui);
register_editor::<ScalarScattering>(registry, default_scatter, edit_scatter_ui);
register_editor::<StrokeWidth>(registry, default_stroke_width, edit_stroke_width_ui);
register_editor::<Text>(registry, default_text, edit_text_ui);
}
23 changes: 14 additions & 9 deletions crates/re_space_view_time_series/src/aggregation.rs
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ impl AverageAggregator {
let point = &points[i + j];

acc.value += point.value;
acc.attrs.radius += point.attrs.radius;
acc.attrs.stroke_width += point.attrs.stroke_width;

ratio += 1.0;
j += 1;
Expand All @@ -48,14 +48,14 @@ impl AverageAggregator {

let w = aggregation_factor_fract;
acc.value += point.value * w;
acc.attrs.radius += (point.attrs.radius as f64 * w) as f32;
acc.attrs.stroke_width += (point.attrs.stroke_width as f64 * w) as f32;

ratio += aggregation_factor_fract;
j += 1;
}

acc.value /= ratio;
acc.attrs.radius = (acc.attrs.radius as f64 / ratio) as _;
acc.attrs.stroke_width = (acc.attrs.stroke_width as f64 / ratio) as _;

aggregated.push(acc);

Expand Down Expand Up @@ -124,17 +124,21 @@ impl MinMaxAggregator {
match self {
MinMaxAggregator::MinMax | MinMaxAggregator::MinMaxAverage => {
acc_min.value = f64::min(acc_min.value, point.value);
acc_min.attrs.radius = f32::min(acc_min.attrs.radius, point.attrs.radius);
acc_min.attrs.stroke_width =
f32::min(acc_min.attrs.stroke_width, point.attrs.stroke_width);
acc_max.value = f64::max(acc_max.value, point.value);
acc_max.attrs.radius = f32::max(acc_max.attrs.radius, point.attrs.radius);
acc_max.attrs.stroke_width =
f32::max(acc_max.attrs.stroke_width, point.attrs.stroke_width);
}
MinMaxAggregator::Min => {
acc_min.value = f64::min(acc_min.value, point.value);
acc_min.attrs.radius = f32::min(acc_min.attrs.radius, point.attrs.radius);
acc_min.attrs.stroke_width =
f32::min(acc_min.attrs.stroke_width, point.attrs.stroke_width);
}
MinMaxAggregator::Max => {
acc_max.value = f64::max(acc_max.value, point.value);
acc_max.attrs.radius = f32::max(acc_max.attrs.radius, point.attrs.radius);
acc_max.attrs.stroke_width =
f32::max(acc_max.attrs.stroke_width, point.attrs.stroke_width);
}
}

Expand All @@ -153,7 +157,8 @@ impl MinMaxAggregator {
// Don't average a single point with itself.
if j > 1 {
acc_min.value = (acc_min.value + acc_max.value) * 0.5;
acc_min.attrs.radius = (acc_min.attrs.radius + acc_max.attrs.radius) * 0.5;
acc_min.attrs.stroke_width =
(acc_min.attrs.stroke_width + acc_max.attrs.stroke_width) * 0.5;
}
aggregated.push(acc_min);
}
Expand Down Expand Up @@ -190,7 +195,7 @@ fn are_aggregatable(point1: &PlotPoint, point2: &PlotPoint, window_size: usize)
let PlotPointAttrs {
label,
color,
radius: _,
stroke_width: _,
kind,
} = attrs;

Expand Down
6 changes: 3 additions & 3 deletions crates/re_space_view_time_series/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ pub(crate) fn plot_id(space_view_id: re_viewer_context::SpaceViewId) -> egui::Id
pub struct PlotPointAttrs {
pub label: Option<String>,
pub color: egui::Color32,
pub radius: f32,
pub stroke_width: f32,
pub kind: PlotSeriesKind,
}

Expand All @@ -47,12 +47,12 @@ impl PartialEq for PlotPointAttrs {
let Self {
label,
color,
radius,
stroke_width: radius,
kind,
} = self;
label.eq(&rhs.label)
&& color.eq(&rhs.color)
&& radius.total_cmp(&rhs.radius).is_eq()
&& radius.total_cmp(&rhs.stroke_width).is_eq()
&& kind.eq(&rhs.kind)
}
}
Expand Down
32 changes: 19 additions & 13 deletions crates/re_space_view_time_series/src/line_visualizer_system.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
use re_query_cache::{MaybeCachedComponentData, QueryError};
use re_types::archetypes;
use re_types::components::StrokeWidth;
use re_types::{
archetypes::SeriesLine,
components::{Color, Radius, Scalar, Text},
components::{Color, Scalar, Text},
Archetype as _, ComponentNameSet, Loggable,
};
use re_viewer_context::{
Expand All @@ -29,6 +30,8 @@ impl IdentifiedViewSystem for SeriesLineSystem {
}
}

const DEFAULT_STROKE_WIDTH: f32 = 0.75;

impl VisualizerSystem for SeriesLineSystem {
fn visualizer_query_info(&self) -> VisualizerQueryInfo {
let mut query_info = VisualizerQueryInfo::from_archetype::<archetypes::Scalar>();
Expand Down Expand Up @@ -76,6 +79,8 @@ impl VisualizerSystem for SeriesLineSystem {
) -> Option<re_log_types::DataCell> {
if *component == Color::name() {
Some([initial_override_color(entity_path)].into())
} else if *component == StrokeWidth::name() {
Some([StrokeWidth(DEFAULT_STROKE_WIDTH)].into())
} else {
None
}
Expand Down Expand Up @@ -123,18 +128,19 @@ impl SeriesLineSystem {
let override_label =
lookup_override::<Text>(data_result, ctx).map(|t| t.to_string());

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

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, StrokeWidth, 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, stroke_width, labels)| {
let Some(time) = time else {
return;
}; // scalars cannot be timeless
Expand All @@ -147,46 +153,46 @@ impl SeriesLineSystem {
attrs: PlotPointAttrs {
label: None,
color: egui::Color32::BLACK,
radius: 0.0,
stroke_width: 0.0,
kind: PlotSeriesKind::Clear,
},
});
return;
}

for (scalar, color, label) in itertools::izip!(
for (scalar, color, stoke_width, label) in itertools::izip!(
scalars.iter(),
MaybeCachedComponentData::iter_or_repeat_opt(
&colors,
scalars.len()
),
MaybeCachedComponentData::iter_or_repeat_opt(
&stroke_width,
scalars.len()
),
//MaybeCachedComponentData::iter_or_repeat_opt(&radii, scalars.len()),
MaybeCachedComponentData::iter_or_repeat_opt(
&labels,
scalars.len()
),
) {
// TODO(jleibs): Replace with StrokeWidth
let radius: Option<Radius> = None;
let color = override_color.unwrap_or_else(|| {
annotation_info
.color(color.map(|c| c.to_array()), default_color)
});
let label = override_label.clone().or_else(|| {
annotation_info.label(label.as_ref().map(|l| l.as_str()))
});
let radius = override_radius
.unwrap_or_else(|| radius.map_or(DEFAULT_RADIUS, |r| r.0));

const DEFAULT_RADIUS: f32 = 0.75;
let stroke_width = override_stroke_width
.unwrap_or_else(|| stoke_width.map_or(DEFAULT_STROKE_WIDTH, |r| r.0));

points.push(PlotPoint {
time: time.as_i64(),
value: scalar.0,
attrs: PlotPointAttrs {
label,
color,
radius,
stroke_width,
kind: PlotSeriesKind::Continuous,
},
});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -159,7 +159,7 @@ impl SeriesPointSystem {
attrs: PlotPointAttrs {
label: None,
color: egui::Color32::BLACK,
radius: 0.0,
stroke_width: 0.0,
kind: PlotSeriesKind::Clear,
},
});
Expand Down Expand Up @@ -204,7 +204,7 @@ impl SeriesPointSystem {
attrs: PlotPointAttrs {
label,
color,
radius,
stroke_width: radius,
kind: PlotSeriesKind::Scatter(ScatterAttrs{marker}),
},
});
Expand Down
6 changes: 3 additions & 3 deletions crates/re_space_view_time_series/src/util.rs
Original file line number Diff line number Diff line change
Expand Up @@ -107,7 +107,7 @@ pub fn points_to_series(
all_series.push(PlotSeries {
label: series_label,
color: points[0].attrs.color,
width: 2.0 * points[0].attrs.radius,
width: 2.0 * points[0].attrs.stroke_width,
kind,
points: vec![(points[0].time, points[0].value)],
entity_path: data_result.entity_path.clone(),
Expand Down Expand Up @@ -204,7 +204,7 @@ fn add_series_runs(
let mut series: PlotSeries = PlotSeries {
label: series_label.to_owned(),
color: attrs.color,
width: 2.0 * attrs.radius,
width: 2.0 * attrs.stroke_width,
points: Vec::with_capacity(num_points),
kind: attrs.kind,
entity_path: entity_path.clone(),
Expand All @@ -228,7 +228,7 @@ fn add_series_runs(
PlotSeries {
label: series_label.to_owned(),
color: attrs.color,
width: 2.0 * attrs.radius,
width: 2.0 * attrs.stroke_width,
kind: attrs.kind,
points: Vec::with_capacity(num_points - i),
entity_path: entity_path.clone(),
Expand Down
4 changes: 2 additions & 2 deletions crates/re_space_view_time_series/src/visualizer_system.rs
Original file line number Diff line number Diff line change
Expand Up @@ -149,7 +149,7 @@ impl LegacyTimeSeriesSystem {
attrs: PlotPointAttrs {
label: None,
color: egui::Color32::BLACK,
radius: 0.0,
stroke_width: 0.0,
kind: PlotSeriesKind::Clear,
},
});
Expand Down Expand Up @@ -188,7 +188,7 @@ impl LegacyTimeSeriesSystem {
attrs: PlotPointAttrs {
label,
color,
radius,
stroke_width: radius,
kind,
},
});
Expand Down
4 changes: 4 additions & 0 deletions crates/re_types/definitions/rerun/archetypes/series_line.fbs
Original file line number Diff line number Diff line change
Expand Up @@ -18,4 +18,8 @@ table SeriesLine (
/// 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);

/// Stroke width for the corresponding series.
// TODO(jleibs): This should be batch if we make a batch Scalars loggable.
width: rerun.components.StrokeWidth ("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 @@ -25,6 +25,7 @@ include "./components/resolution.fbs";
include "./components/rotation3d.fbs";
include "./components/scalar_scattering.fbs";
include "./components/scalar.fbs";
include "./components/stroke_width.fbs";
include "./components/tensor_data.fbs";
include "./components/texcoord2d.fbs";
include "./components/text_log_level.fbs";
Expand Down
21 changes: 21 additions & 0 deletions crates/re_types/definitions/rerun/components/stroke_width.fbs
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
include "arrow/attributes.fbs";
include "python/attributes.fbs";
include "rust/attributes.fbs";

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

namespace rerun.components;

// ---

/// The width of a stroke specified in UI points.
struct StrokeWidth (
"attr.docs.unreleased",
"attr.python.aliases": "float",
"attr.python.array_aliases": "float, npt.ArrayLike",
"attr.rust.derive": "Copy, PartialEq, PartialOrd, bytemuck::Pod, bytemuck::Zeroable",
"attr.rust.repr": "transparent"
) {
width: float (order: 100);
}
Loading
Loading