Skip to content

Commit

Permalink
Move object property heuristics to heuristics.rs (#2764)
Browse files Browse the repository at this point in the history
### What

Small refactor that I pulled out of #2716 for readability of that pr 

### Checklist
* [x] I have read and agree to [Contributor
Guide](https://github.com/rerun-io/rerun/blob/main/CONTRIBUTING.md) and
the [Code of
Conduct](https://github.com/rerun-io/rerun/blob/main/CODE_OF_CONDUCT.md)
* [x] I've included a screenshot or gif (if applicable)
* [x] I have tested [demo.rerun.io](https://demo.rerun.io/pr/2764) (if
applicable)

- [PR Build Summary](https://build.rerun.io/pr/2764)
- [Docs
preview](https://rerun.io/preview/pr%3Aandreas%2Fmove-object-heuristics/docs)
- [Examples
preview](https://rerun.io/preview/pr%3Aandreas%2Fmove-object-heuristics/examples)
  • Loading branch information
Wumpf authored Jul 21, 2023
1 parent 8bad645 commit 4e5eb1f
Show file tree
Hide file tree
Showing 4 changed files with 183 additions and 183 deletions.
173 changes: 173 additions & 0 deletions crates/re_space_view_spatial/src/heuristics.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,8 @@
use egui::NumExt as _;
use nohash_hasher::IntSet;

use re_components::{Pinhole, Tensor, TensorDataMeaning, Transform3D};
use re_data_store::EditableAutoValue;
use re_log_types::{EntityPath, Timeline};
use re_viewer_context::{AutoSpawnHeuristic, SpaceViewClassName, ViewerContext};

Expand Down Expand Up @@ -45,3 +49,172 @@ pub fn auto_spawn_heuristic(

AutoSpawnHeuristic::SpawnClassWithHighestScoreForRoot(score)
}

pub fn update_object_property_heuristics(
ctx: &mut ViewerContext<'_>,
ent_paths: &IntSet<EntityPath>,
entity_properties: &mut re_data_store::EntityPropertyMap,
scene_bbox_accum: &macaw::BoundingBox,
spatial_kind: SpatialSpaceViewKind,
) {
re_tracing::profile_function!();

for entity_path in ent_paths {
update_pinhole_property_heuristics(ctx, entity_path, entity_properties, scene_bbox_accum);
update_depth_cloud_property_heuristics(ctx, entity_path, entity_properties, spatial_kind);
update_transform3d_lines_heuristics(ctx, entity_path, entity_properties, scene_bbox_accum);
}
}

pub fn auto_size_world_heuristic(
scene_bbox_accum: &macaw::BoundingBox,
scene_num_primitives: usize,
) -> f32 {
if scene_bbox_accum.is_nothing() || scene_bbox_accum.is_nan() {
return 0.01;
}

// Motivation: Size should be proportional to the scene extent, here covered by its diagonal
let diagonal_length = (scene_bbox_accum.max - scene_bbox_accum.min).length();
let heuristic0 = diagonal_length * 0.0025;

// Motivation: A lot of times we look at the entire scene and expect to see everything on a flat screen with some gaps between.
let size = scene_bbox_accum.size();
let mut sorted_components = size.to_array();
sorted_components.sort_by(|a, b| a.partial_cmp(b).unwrap());
// Median is more robust against outlier in one direction (as such pretty poor still though)
let median_extent = sorted_components[1];
// sqrt would make more sense but using a smaller root works better in practice.
let heuristic1 =
(median_extent / (scene_num_primitives.at_least(1) as f32).powf(1.0 / 1.7)) * 0.25;

heuristic0.min(heuristic1)
}

fn update_pinhole_property_heuristics(
ctx: &mut ViewerContext<'_>,
entity_path: &EntityPath,
entity_properties: &mut re_data_store::EntityPropertyMap,
scene_bbox_accum: &macaw::BoundingBox,
) {
let store = &ctx.store_db.entity_db.data_store;
if store
.query_latest_component::<Pinhole>(entity_path, &ctx.current_query())
.is_some()
{
let mut properties = entity_properties.get(entity_path);
if properties.pinhole_image_plane_distance.is_auto() {
let scene_size = scene_bbox_accum.size().length();
let default_image_plane_distance = if scene_size.is_finite() && scene_size > 0.0 {
scene_size * 0.02 // Works pretty well for `examples/python/open_photogrammetry_format/main.py --no-frames`
} else {
1.0
};
properties.pinhole_image_plane_distance =
EditableAutoValue::Auto(default_image_plane_distance);
entity_properties.set(entity_path.clone(), properties);
}
}
}

fn update_depth_cloud_property_heuristics(
ctx: &mut ViewerContext<'_>,
entity_path: &EntityPath,
entity_properties: &mut re_data_store::EntityPropertyMap,
spatial_kind: SpatialSpaceViewKind,
) -> Option<()> {
let store = &ctx.store_db.entity_db.data_store;
let tensor = store.query_latest_component::<Tensor>(entity_path, &ctx.current_query())?;

let mut properties = entity_properties.get(entity_path);
if properties.backproject_depth.is_auto() {
properties.backproject_depth = EditableAutoValue::Auto(
tensor.meaning == TensorDataMeaning::Depth
&& spatial_kind == SpatialSpaceViewKind::ThreeD,
);
}

if tensor.meaning == TensorDataMeaning::Depth {
if properties.depth_from_world_scale.is_auto() {
let auto = tensor.meter.unwrap_or_else(|| {
if tensor.dtype().is_integer() {
1000.0
} else {
1.0
}
});
properties.depth_from_world_scale = EditableAutoValue::Auto(auto);
}

if properties.backproject_radius_scale.is_auto() {
properties.backproject_radius_scale = EditableAutoValue::Auto(1.0);
}

entity_properties.set(entity_path.clone(), properties);
}

Some(())
}

fn update_transform3d_lines_heuristics(
ctx: &ViewerContext<'_>,
ent_path: &EntityPath,
entity_properties: &mut re_data_store::EntityPropertyMap,
scene_bbox_accum: &macaw::BoundingBox,
) {
if ctx
.store_db
.store()
.query_latest_component::<Transform3D>(ent_path, &ctx.current_query())
.is_none()
{
return;
}

let mut properties = entity_properties.get(ent_path);
if properties.transform_3d_visible.is_auto() {
fn path_or_child_has_pinhole(
store: &re_arrow_store::DataStore,
ent_path: &EntityPath,
ctx: &ViewerContext<'_>,
) -> bool {
if store
.query_latest_component::<Pinhole>(ent_path, &ctx.current_query())
.is_some()
{
return true;
} else {
// Any direct child has a pinhole camera?
if let Some(child_tree) = ctx.store_db.entity_db.tree.subtree(ent_path) {
for child in child_tree.children.values() {
if store
.query_latest_component::<Pinhole>(&child.path, &ctx.current_query())
.is_some()
{
return true;
}
}
}
}

false
}
// By default show the transform if it is a camera extrinsic or if it's the only component on this entity path.
let single_component = ctx
.store_db
.store()
.all_components(&ctx.current_query().timeline, ent_path)
.map_or(false, |c| c.len() == 1);
properties.transform_3d_visible = EditableAutoValue::Auto(
single_component || path_or_child_has_pinhole(ctx.store_db.store(), ent_path, ctx),
);
}

if properties.transform_3d_size.is_auto() {
// Size should be proportional to the scene extent, here covered by its diagonal
let diagonal_length = (scene_bbox_accum.max - scene_bbox_accum.min).length();
properties.transform_3d_size = EditableAutoValue::Auto(diagonal_length * 0.01);
}

entity_properties.set(ent_path.clone(), properties);
}
5 changes: 3 additions & 2 deletions crates/re_space_view_spatial/src/space_view_2d.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ use re_viewer_context::{

use crate::{
contexts::{register_contexts, PrimitiveCounter},
heuristics::auto_spawn_heuristic,
heuristics::{auto_spawn_heuristic, update_object_property_heuristics},
parts::{calculate_bounding_box, register_parts},
ui::SpatialSpaceViewState,
view_kind::SpatialSpaceViewKind,
Expand Down Expand Up @@ -57,10 +57,11 @@ impl SpaceViewClass for SpatialSpaceView2D {
ent_paths: &IntSet<EntityPath>,
entity_properties: &mut re_data_store::EntityPropertyMap,
) {
state.update_object_property_heuristics(
update_object_property_heuristics(
ctx,
ent_paths,
entity_properties,
&state.scene_bbox_accum,
SpatialSpaceViewKind::TwoD,
);
}
Expand Down
5 changes: 3 additions & 2 deletions crates/re_space_view_spatial/src/space_view_3d.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ use re_viewer_context::{

use crate::{
contexts::{register_contexts, PrimitiveCounter},
heuristics::auto_spawn_heuristic,
heuristics::{auto_spawn_heuristic, update_object_property_heuristics},
parts::{calculate_bounding_box, register_parts},
ui::SpatialSpaceViewState,
view_kind::SpatialSpaceViewKind,
Expand Down Expand Up @@ -93,10 +93,11 @@ impl SpaceViewClass for SpatialSpaceView3D {
ent_paths: &IntSet<EntityPath>,
entity_properties: &mut re_data_store::EntityPropertyMap,
) {
state.update_object_property_heuristics(
update_object_property_heuristics(
ctx,
ent_paths,
entity_properties,
&state.scene_bbox_accum,
SpatialSpaceViewKind::ThreeD,
);
}
Expand Down
Loading

0 comments on commit 4e5eb1f

Please sign in to comment.