diff --git a/Cargo.lock b/Cargo.lock index a6e95f923a30..b77ad3b52c34 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -908,8 +908,12 @@ dependencies = [ [[package]] name = "code_examples" -version = "0.7.0-alpha.0" +version = "0.8.0-alpha.0" dependencies = [ + "ahash 0.8.3", + "ndarray", + "rand", + "rand_distr", "rerun", ] diff --git a/docs/code-examples/Cargo.toml b/docs/code-examples/Cargo.toml index c55006e4bd65..e3568282fb1e 100644 --- a/docs/code-examples/Cargo.toml +++ b/docs/code-examples/Cargo.toml @@ -1,14 +1,116 @@ [package] name = "code_examples" -version = "0.7.0-alpha.0" -edition = "2021" -rust-version = "1.69" -license = "MIT OR Apache-2.0" +version.workspace = true +edition.workspace = true +rust-version.workspace = true +license.workspace = true publish = false + +[[bin]] +name = "annotation_context_connections" +path = "annotation_context_connections.rs" + +[[bin]] +name = "annotation_context_rects" +path = "annotation_context_rects.rs" + +[[bin]] +name = "annotation_context_segmentation" +path = "annotation_context_segmentation.rs" + +[[bin]] +name = "arrow3d_simple" +path = "arrow3d_simple.rs" + +[[bin]] +name = "box3d_simple" +path = "box3d_simple.rs" + +[[bin]] +name = "depth_image_3d" +path = "depth_image_3d.rs" + +[[bin]] +name = "depth_image_simple" +path = "depth_image_simple.rs" + +[[bin]] +name = "image_simple" +path = "image_simple.rs" + +[[bin]] +name = "line_segments2d_simple" +path = "line_segments2d_simple.rs" + +[[bin]] +name = "line_segments3d_simple" +path = "line_segments3d_simple.rs" + +[[bin]] +name = "line_strip2d_simple" +path = "line_strip2d_simple.rs" + +[[bin]] +name = "line_strip3d_simple" +path = "line_strip3d_simple.rs" + [[bin]] -name = 'point2d_simple' -path = 'point2d_simple.rs' +name = "mesh_simple" +path = "mesh_simple.rs" + +[[bin]] +name = "pinhole_simple" +path = "pinhole_simple.rs" + +[[bin]] +name = "point2d_simple" +path = "point2d_simple.rs" + +[[bin]] +name = "point2d_random" +path = "point2d_random.rs" + +[[bin]] +name = "point3d_random" +path = "point3d_random.rs" + +[[bin]] +name = "point3d_simple" +path = "point3d_simple.rs" + +[[bin]] +name = "rect2d_simple" +path = "rect2d_simple.rs" + +[[bin]] +name = "scalar_simple" +path = "scalar_simple.rs" + +[[bin]] +name = "segmentation_image_simple" +path = "segmentation_image_simple.rs" + +[[bin]] +name = "tensor_one_dim" +path = "tensor_one_dim.rs" + +[[bin]] +name = "tensor_simple" +path = "tensor_simple.rs" + +[[bin]] +name = "text_entry_simple" +path = "text_entry_simple.rs" + +[[bin]] +name = "transform3d_simple" +path = "transform3d_simple.rs" + [dependencies] +ahash.workspace = true +ndarray.workspace = true +rand.workspace = true +rand_distr.workspace = true rerun = { path = "../../crates/rerun", features = ["native_viewer"] } diff --git a/docs/code-examples/annotation_context_connections.rs b/docs/code-examples/annotation_context_connections.rs new file mode 100644 index 000000000000..af7d223ba7b0 --- /dev/null +++ b/docs/code-examples/annotation_context_connections.rs @@ -0,0 +1,82 @@ +//! Log some very simple points. +use rerun::components::{ + AnnotationContext, AnnotationInfo, ClassDescription, ClassId, ColorRGBA, KeypointId, Label, + Point3D, +}; +use rerun::{MsgSender, RecordingStreamBuilder}; + +fn main() -> Result<(), Box> { + let (rec_stream, storage) = + RecordingStreamBuilder::new("annotation_context_connections").memory()?; + + // Log an annotation context to assign a label and color to each class + // Create a class description with labels and color for each keypoint ID as well as some + // connections between keypoints. + let mut class_desc = ClassDescription::default(); + class_desc.keypoint_map.insert( + KeypointId(0), + AnnotationInfo { + id: 0, + label: Some(Label("zero".to_owned())), + color: Some(ColorRGBA::from_rgb(255, 0, 0)), + }, + ); + class_desc.keypoint_map.insert( + KeypointId(1), + AnnotationInfo { + id: 1, + label: Some(Label("one".to_owned())), + color: Some(ColorRGBA::from_rgb(0, 255, 0)), + }, + ); + class_desc.keypoint_map.insert( + KeypointId(2), + AnnotationInfo { + id: 2, + label: Some(Label("two".to_owned())), + color: Some(ColorRGBA::from_rgb(0, 0, 255)), + }, + ); + class_desc.keypoint_map.insert( + KeypointId(3), + AnnotationInfo { + id: 3, + label: Some(Label("three".to_owned())), + color: Some(ColorRGBA::from_rgb(255, 255, 0)), + }, + ); + class_desc.keypoint_connections = [(0, 2), (1, 2), (2, 3)] + .into_iter() + .map(|(a, b)| (KeypointId(a), KeypointId(b))) + .collect(); + + let mut annotation = AnnotationContext::default(); + annotation.class_map.insert(ClassId(0), class_desc); + + MsgSender::new("/") + .with_component(&[annotation])? + .send(&rec_stream)?; + + // Log some points with different keypoint IDs + let points = [ + [0., 0., 0.], + [50., 0., 20.], + [100., 100., 30.], + [0., 50., 40.], + ] + .into_iter() + .map(Point3D::from) + .collect::>(); + + MsgSender::new("points") + .with_component(&points)? + .with_component(&[KeypointId(0), KeypointId(1), KeypointId(2), KeypointId(3)])? + .with_splat(ClassId(0))? + .send(&rec_stream)?; + + rec_stream.flush_blocking(); + + rerun::native_viewer::show(storage.take())?; + + Ok(()) +} diff --git a/docs/code-examples/annotation_context_rects.rs b/docs/code-examples/annotation_context_rects.rs new file mode 100644 index 000000000000..730ca74cedf0 --- /dev/null +++ b/docs/code-examples/annotation_context_rects.rs @@ -0,0 +1,56 @@ +//! Log rectangles with different colors and labels. +use rerun::components::{ + AnnotationContext, AnnotationInfo, ClassDescription, ClassId, ColorRGBA, Label, Rect2D, Vec4D, +}; +use rerun::{MsgSender, RecordingStreamBuilder}; + +fn main() -> Result<(), Box> { + let (rec_stream, storage) = RecordingStreamBuilder::new("annotation_context_rects").memory()?; + + // Log an annotation context to assign a label and color to each class + let mut annotation = AnnotationContext::default(); + annotation.class_map.insert( + ClassId(1), + ClassDescription { + info: AnnotationInfo { + id: 1, + label: Some(Label("red".to_owned())), + color: Some(ColorRGBA::from_rgb(255, 0, 0)), + }, + ..Default::default() + }, + ); + annotation.class_map.insert( + ClassId(2), + ClassDescription { + info: AnnotationInfo { + id: 2, + label: Some(Label("green".to_owned())), + color: Some(ColorRGBA::from_rgb(0, 255, 0)), + }, + ..Default::default() + }, + ); + + MsgSender::new("/") + .with_component(&[annotation])? + .send(&rec_stream)?; + + // Log a batch of 2 rectangles with different class IDs + MsgSender::new("detections") + .with_component(&[ + Rect2D::XYWH(Vec4D([-2., -2., 3., 3.])), + Rect2D::XYWH(Vec4D([0., 0., 2., 2.])), + ])? + .with_component(&[ClassId(1), ClassId(2)])? + .send(&rec_stream)?; + + // Log an extra rect to set the view bounds + MsgSender::new("bounds") + .with_component(&[Rect2D::XCYCWH(Vec4D([0.0, 0.0, 5.0, 5.0]))])? + .send(&rec_stream)?; + + rec_stream.flush_blocking(); + rerun::native_viewer::show(storage.take())?; + Ok(()) +} diff --git a/docs/code-examples/annotation_context_segmentation.rs b/docs/code-examples/annotation_context_segmentation.rs new file mode 100644 index 000000000000..b9ae5b92053c --- /dev/null +++ b/docs/code-examples/annotation_context_segmentation.rs @@ -0,0 +1,58 @@ +//! Log a segmentation image with annotations. +use ndarray::{s, Array, ShapeBuilder}; +use rerun::components::{ + AnnotationContext, AnnotationInfo, ClassDescription, ClassId, ColorRGBA, Label, Tensor, + TensorDataMeaning, +}; +use rerun::{MsgSender, RecordingStreamBuilder}; + +fn main() -> Result<(), Box> { + let (rec_stream, storage) = + RecordingStreamBuilder::new("annotation_context_segmentation").memory()?; + + // create a segmentation image + let mut data = Array::::zeros((200, 300).f()); + data.slice_mut(s![50..150, 50..120]).fill(1); + data.slice_mut(s![100..180, 130..280]).fill(2); + + let mut image = Tensor::try_from(data.as_standard_layout().view())?; + image.meaning = TensorDataMeaning::ClassId; + + // create an annotation context to describe the classes + let mut annotation = AnnotationContext::default(); + annotation.class_map.insert( + ClassId(1), + ClassDescription { + info: AnnotationInfo { + id: 1, + label: Some(Label("red".to_owned())), + color: Some(ColorRGBA::from_rgb(255, 0, 0)), + }, + ..Default::default() + }, + ); + annotation.class_map.insert( + ClassId(2), + ClassDescription { + info: AnnotationInfo { + id: 2, + label: Some(Label("green".to_owned())), + color: Some(ColorRGBA::from_rgb(0, 255, 0)), + }, + ..Default::default() + }, + ); + + // log the annotation and the image + MsgSender::new("segmentation") + .with_component(&[annotation])? + .send(&rec_stream)?; + + MsgSender::new("segmentation/image") + .with_component(&[image])? + .send(&rec_stream)?; + + rec_stream.flush_blocking(); + rerun::native_viewer::show(storage.take())?; + Ok(()) +} diff --git a/docs/code-examples/arrow3d_simple.rs b/docs/code-examples/arrow3d_simple.rs new file mode 100644 index 000000000000..2785764df948 --- /dev/null +++ b/docs/code-examples/arrow3d_simple.rs @@ -0,0 +1,21 @@ +//! Log a single arrow +use rerun::components::{Arrow3D, Radius, Vec3D}; +use rerun::{MsgSender, RecordingStreamBuilder}; + +fn main() -> Result<(), Box> { + let (rec_stream, storage) = RecordingStreamBuilder::new("arrow").memory()?; + + let arrow = Arrow3D { + origin: Vec3D::from([0.0, 0.0, 0.0]), + vector: Vec3D::from([1.0, 0.0, 1.0]), + }; + + MsgSender::new("arrow") + .with_component(&[arrow])? + .with_component(&[Radius(0.05)])? + .send(&rec_stream)?; + + rec_stream.flush_blocking(); + rerun::native_viewer::show(storage.take())?; + Ok(()) +} diff --git a/docs/code-examples/box3d_simple.rs b/docs/code-examples/box3d_simple.rs new file mode 100644 index 000000000000..c1dda7c17dc0 --- /dev/null +++ b/docs/code-examples/box3d_simple.rs @@ -0,0 +1,15 @@ +//! Log some a single oriented bounding box +use rerun::components::Box3D; +use rerun::{MsgSender, RecordingStreamBuilder}; + +fn main() -> Result<(), Box> { + let (rec_stream, storage) = RecordingStreamBuilder::new("box3d").memory()?; + + MsgSender::new("simple") + .with_component(&[Box3D::new(2.0, 2.0, 1.0)])? + .send(&rec_stream)?; + + rec_stream.flush_blocking(); + rerun::native_viewer::show(storage.take())?; + Ok(()) +} diff --git a/docs/code-examples/depth_image_3d.rs b/docs/code-examples/depth_image_3d.rs new file mode 100644 index 000000000000..1190526752a0 --- /dev/null +++ b/docs/code-examples/depth_image_3d.rs @@ -0,0 +1,40 @@ +//! Create and log a depth image. +use ndarray::{s, Array, ShapeBuilder}; +use rerun::components::{Mat3x3, Pinhole, Tensor, TensorDataMeaning, Vec2D}; +use rerun::{MsgSender, RecordingStreamBuilder}; + +fn main() -> Result<(), Box> { + let (rec_stream, storage) = RecordingStreamBuilder::new("depth_image").memory()?; + + // Create a dummy depth image + let mut image = Array::::from_elem((200, 300).f(), 65535); + image.slice_mut(s![50..150, 50..150]).fill(20000); + image.slice_mut(s![130..180, 100..280]).fill(45000); + let mut tensor = Tensor::try_from(image.as_standard_layout().view())?; + tensor.meaning = TensorDataMeaning::Depth; + tensor.meter = Some(10000.); + + // If we log a pinhole camera model, the depth gets automatically back-projected to 3D + let focal_length = 200.; + MsgSender::new("world/camera") + .with_component(&[Pinhole { + image_from_cam: Mat3x3::from([ + [focal_length, 0., image.shape()[1] as f32 / 2.], + [0., focal_length, image.shape()[0] as f32 / 2.], + [0., 0., 1.], + ]), + resolution: Some(Vec2D::from([ + image.shape()[1] as f32, + image.shape()[0] as f32, + ])), + }])? + .send(&rec_stream)?; + + MsgSender::new("world/camera/depth") + .with_component(&[tensor])? + .send(&rec_stream)?; + + rec_stream.flush_blocking(); + rerun::native_viewer::show(storage.take())?; + Ok(()) +} diff --git a/docs/code-examples/depth_image_simple.rs b/docs/code-examples/depth_image_simple.rs new file mode 100644 index 000000000000..7445f21b6373 --- /dev/null +++ b/docs/code-examples/depth_image_simple.rs @@ -0,0 +1,23 @@ +//! Create and log a depth image. +use ndarray::{s, Array, ShapeBuilder}; +use rerun::components::{Tensor, TensorDataMeaning}; +use rerun::{MsgSender, RecordingStreamBuilder}; + +fn main() -> Result<(), Box> { + let (rec_stream, storage) = RecordingStreamBuilder::new("depth_image").memory()?; + + let mut image = Array::::from_elem((200, 300).f(), 65535); + image.slice_mut(s![50..150, 50..150]).fill(20000); + image.slice_mut(s![130..180, 100..280]).fill(45000); + + let mut tensor = Tensor::try_from(image.as_standard_layout().view())?; + tensor.meaning = TensorDataMeaning::Depth; + + MsgSender::new("depth") + .with_component(&[tensor])? + .send(&rec_stream)?; + + rec_stream.flush_blocking(); + rerun::native_viewer::show(storage.take())?; + Ok(()) +} diff --git a/docs/code-examples/image_simple.rs b/docs/code-examples/image_simple.rs new file mode 100644 index 000000000000..ea46757284bd --- /dev/null +++ b/docs/code-examples/image_simple.rs @@ -0,0 +1,21 @@ +//! Create and log an image +use ndarray::{s, Array, ShapeBuilder}; +use rerun::components::Tensor; +use rerun::{MsgSender, RecordingStreamBuilder}; + +fn main() -> Result<(), Box> { + let (rec_stream, storage) = RecordingStreamBuilder::new("pinhole").memory()?; + + let mut image = Array::::zeros((200, 300, 3).f()); + image.slice_mut(s![.., .., 0]).fill(255); + image.slice_mut(s![50..150, 50..150, 0]).fill(0); + image.slice_mut(s![50..150, 50..150, 1]).fill(255); + + MsgSender::new("image") + .with_component(&[Tensor::try_from(image.as_standard_layout().view())?])? + .send(&rec_stream)?; + + rec_stream.flush_blocking(); + rerun::native_viewer::show(storage.take())?; + Ok(()) +} diff --git a/docs/code-examples/line_segments2d_simple.rs b/docs/code-examples/line_segments2d_simple.rs new file mode 100644 index 000000000000..8d4ca5bfa21b --- /dev/null +++ b/docs/code-examples/line_segments2d_simple.rs @@ -0,0 +1,27 @@ +//! Log a simple line segment. +use rerun::components::{LineStrip2D, Rect2D, Vec4D}; +use rerun::{MsgSender, RecordingStreamBuilder}; + +fn main() -> Result<(), Box> { + let (rec_stream, storage) = RecordingStreamBuilder::new("linestrip2d").memory()?; + + let points = vec![[0., 0.], [2., 1.], [4., -1.], [6., 0.]]; + + MsgSender::new("simple") + .with_component( + &points + .chunks(2) + .map(|p| LineStrip2D(vec![p[0].into(), p[1].into()])) + .collect::>(), + )? + .send(&rec_stream)?; + + // Log an extra rect to set the view bounds + MsgSender::new("bounds") + .with_component(&[Rect2D::XCYCWH(Vec4D([3.0, 0.0, 8.0, 6.0]))])? + .send(&rec_stream)?; + + rec_stream.flush_blocking(); + rerun::native_viewer::show(storage.take())?; + Ok(()) +} diff --git a/docs/code-examples/line_segments3d_simple.rs b/docs/code-examples/line_segments3d_simple.rs new file mode 100644 index 000000000000..1d10dfb51812 --- /dev/null +++ b/docs/code-examples/line_segments3d_simple.rs @@ -0,0 +1,31 @@ +//! Log a simple set of line segments. +use rerun::components::LineStrip3D; +use rerun::{MsgSender, RecordingStreamBuilder}; + +fn main() -> Result<(), Box> { + let (rec_stream, storage) = RecordingStreamBuilder::new("linestrip2d").memory()?; + + let points = vec![ + [0., 0., 0.], + [0., 0., 1.], + [1., 0., 0.], + [1., 0., 1.], + [1., 1., 0.], + [1., 1., 1.], + [0., 1., 0.], + [0., 1., 1.], + ]; + + MsgSender::new("simple") + .with_component( + &points + .chunks(2) + .map(|p| LineStrip3D(vec![p[0].into(), p[1].into()])) + .collect::>(), + )? + .send(&rec_stream)?; + + rec_stream.flush_blocking(); + rerun::native_viewer::show(storage.take())?; + Ok(()) +} diff --git a/docs/code-examples/line_strip2d_simple.rs b/docs/code-examples/line_strip2d_simple.rs new file mode 100644 index 000000000000..f3127bb187f2 --- /dev/null +++ b/docs/code-examples/line_strip2d_simple.rs @@ -0,0 +1,22 @@ +//! Log a simple line strip. +use rerun::components::{LineStrip2D, Rect2D, Vec4D}; +use rerun::{MsgSender, RecordingStreamBuilder}; + +fn main() -> Result<(), Box> { + let (rec_stream, storage) = RecordingStreamBuilder::new("linestrip2d").memory()?; + + let points = vec![[0., 0.], [2., 1.], [4., -1.], [6., 0.]]; + + MsgSender::new("simple") + .with_component(&[LineStrip2D(points.into_iter().map(Into::into).collect())])? + .send(&rec_stream)?; + + // Log an extra rect to set the view bounds + MsgSender::new("bounds") + .with_component(&[Rect2D::XCYCWH(Vec4D([3.0, 0.0, 8.0, 6.0]))])? + .send(&rec_stream)?; + + rec_stream.flush_blocking(); + rerun::native_viewer::show(storage.take())?; + Ok(()) +} diff --git a/docs/code-examples/line_strip3d_simple.rs b/docs/code-examples/line_strip3d_simple.rs new file mode 100644 index 000000000000..7d94e67d0a72 --- /dev/null +++ b/docs/code-examples/line_strip3d_simple.rs @@ -0,0 +1,26 @@ +//! Log a simple line strip. +use rerun::components::LineStrip3D; +use rerun::{MsgSender, RecordingStreamBuilder}; + +fn main() -> Result<(), Box> { + let (rec_stream, storage) = RecordingStreamBuilder::new("linestrip2d").memory()?; + + let points = vec![ + [0., 0., 0.], + [0., 0., 1.], + [1., 0., 0.], + [1., 0., 1.], + [1., 1., 0.], + [1., 1., 1.], + [0., 1., 0.], + [0., 1., 1.], + ]; + + MsgSender::new("simple") + .with_component(&[LineStrip3D(points.into_iter().map(Into::into).collect())])? + .send(&rec_stream)?; + + rec_stream.flush_blocking(); + rerun::native_viewer::show(storage.take())?; + Ok(()) +} diff --git a/docs/code-examples/mesh_simple.rs b/docs/code-examples/mesh_simple.rs new file mode 100644 index 000000000000..32c34a8d739c --- /dev/null +++ b/docs/code-examples/mesh_simple.rs @@ -0,0 +1,32 @@ +//! Log a simple colored triangle. +use rerun::components::{Mesh3D, MeshId, RawMesh3D}; +use rerun::{MsgSender, RecordingStreamBuilder}; + +fn main() -> Result<(), Box> { + let (rec_stream, storage) = RecordingStreamBuilder::new("mesh").memory()?; + + let mesh = RawMesh3D { + mesh_id: MeshId::random(), + vertex_positions: [[0.0, 0.0, 0.0], [1.0, 0.0, 0.0], [0.0, 1.0, 0.0]] + .into_iter() + .flatten() + .collect(), + indices: Some([0, 1, 2].into_iter().collect()), + vertex_normals: Some( + [[0.0, 0.0, 1.0], [0.0, 0.0, 1.0], [0.0, 0.0, 1.0]] + .into_iter() + .flatten() + .collect(), + ), + vertex_colors: Some([0xff0000ff, 0x00ff00ff, 0x0000ffff].into_iter().collect()), + albedo_factor: None, + }; + + MsgSender::new("triangle") + .with_component(&[Mesh3D::Raw(mesh)])? + .send(&rec_stream)?; + + rec_stream.flush_blocking(); + rerun::native_viewer::show(storage.take())?; + Ok(()) +} diff --git a/docs/code-examples/pinhole_simple.rs b/docs/code-examples/pinhole_simple.rs new file mode 100644 index 000000000000..53e652d28829 --- /dev/null +++ b/docs/code-examples/pinhole_simple.rs @@ -0,0 +1,26 @@ +//! Log a pinhole and a random image. +use ndarray::{Array, ShapeBuilder}; +use rerun::components::{Mat3x3, Pinhole, Tensor, Vec2D}; +use rerun::{MsgSender, RecordingStreamBuilder}; + +fn main() -> Result<(), Box> { + let (rec_stream, storage) = RecordingStreamBuilder::new("pinhole").memory()?; + + let mut image = Array::::default((3, 3, 3).f()); + image.map_inplace(|x| *x = rand::random()); + + MsgSender::new("world/image") + .with_component(&[Pinhole { + image_from_cam: Mat3x3::from([[3., 0., 1.5], [0., 3., 1.5], [0., 0., 1.]]), + resolution: Some(Vec2D::from([3., 3.])), + }])? + .send(&rec_stream)?; + + MsgSender::new("world/image") + .with_component(&[Tensor::try_from(image.as_standard_layout().view())?])? + .send(&rec_stream)?; + + rec_stream.flush_blocking(); + rerun::native_viewer::show(storage.take())?; + Ok(()) +} diff --git a/docs/code-examples/point2d_random.rs b/docs/code-examples/point2d_random.rs new file mode 100644 index 000000000000..689b36c2cf05 --- /dev/null +++ b/docs/code-examples/point2d_random.rs @@ -0,0 +1,39 @@ +//! Log some random points with color and radii. +use rand::distributions::Uniform; +use rand::Rng; +use rerun::components::{ColorRGBA, Point2D, Radius, Rect2D, Vec4D}; +use rerun::{MsgSender, RecordingStreamBuilder}; + +fn main() -> Result<(), Box> { + let (rec_stream, storage) = RecordingStreamBuilder::new("points").memory()?; + + let mut rng = rand::thread_rng(); + let position_distribs = Uniform::new(-3., 3.); + + let mut positions = vec![]; + let mut colors = vec![]; + let mut radii = vec![]; + for _ in 0..10 { + positions.push(Point2D::new( + rng.sample(position_distribs), + rng.sample(position_distribs), + )); + colors.push(ColorRGBA::from_rgb(rng.gen(), rng.gen(), rng.gen())); + radii.push(Radius(rng.gen())); + } + + MsgSender::new("random") + .with_component(&positions)? + .with_component(&colors)? + .with_component(&radii)? + .send(&rec_stream)?; + + // Log an extra rect to set the view bounds + MsgSender::new("bounds") + .with_component(&[Rect2D::XCYCWH(Vec4D([0.0, 0.0, 8.0, 6.0]))])? + .send(&rec_stream)?; + + rec_stream.flush_blocking(); + rerun::native_viewer::show(storage.take())?; + Ok(()) +} diff --git a/docs/code-examples/point3d_random.rs b/docs/code-examples/point3d_random.rs new file mode 100644 index 000000000000..50a10bf493c3 --- /dev/null +++ b/docs/code-examples/point3d_random.rs @@ -0,0 +1,35 @@ +//! Log some random points with color and radii.""" +use rand::distributions::Uniform; +use rand::Rng; +use rerun::components::{ColorRGBA, Point3D, Radius}; +use rerun::{MsgSender, RecordingStreamBuilder}; + +fn main() -> Result<(), Box> { + let (rec_stream, storage) = RecordingStreamBuilder::new("points").memory()?; + + let mut rng = rand::thread_rng(); + let position_distribs = Uniform::new(-5., 5.); + + let mut positions = vec![]; + let mut colors = vec![]; + let mut radii = vec![]; + for _ in 0..10 { + positions.push(Point3D::new( + rng.sample(position_distribs), + rng.sample(position_distribs), + rng.sample(position_distribs), + )); + colors.push(ColorRGBA::from_rgb(rng.gen(), rng.gen(), rng.gen())); + radii.push(Radius(rng.gen())); + } + + MsgSender::new("random") + .with_component(&positions)? + .with_component(&colors)? + .with_component(&radii)? + .send(&rec_stream)?; + + rec_stream.flush_blocking(); + rerun::native_viewer::show(storage.take())?; + Ok(()) +} diff --git a/docs/code-examples/point3d_simple.rs b/docs/code-examples/point3d_simple.rs new file mode 100644 index 000000000000..9a53efe74446 --- /dev/null +++ b/docs/code-examples/point3d_simple.rs @@ -0,0 +1,27 @@ +//! Log some very simple points. +use rerun::{ + components::{Point2D, Rect2D, Vec4D}, + MsgSender, RecordingStreamBuilder, +}; + +fn main() -> Result<(), Box> { + let (rec_stream, storage) = RecordingStreamBuilder::new("points").memory()?; + + let points = [[0.0, 0.0], [1.0, 1.0]] + .into_iter() + .map(Point2D::from) + .collect::>(); + + MsgSender::new("points") + .with_component(&points)? + .send(&rec_stream)?; + + // Log an extra rect to set the view bounds + MsgSender::new("bounds") + .with_component(&[Rect2D::XCYCWH(Vec4D([0.0, 0.0, 4.0, 3.0]))])? + .send(&rec_stream)?; + + rec_stream.flush_blocking(); + rerun::native_viewer::show(storage.take())?; + Ok(()) +} diff --git a/docs/code-examples/rect2d_simple.rs b/docs/code-examples/rect2d_simple.rs new file mode 100644 index 000000000000..b0c697967e9c --- /dev/null +++ b/docs/code-examples/rect2d_simple.rs @@ -0,0 +1,22 @@ +//! Log some very simple points. +use rerun::{ + components::{Rect2D, Vec4D}, + MsgSender, RecordingStreamBuilder, +}; + +fn main() -> Result<(), Box> { + let (rec_stream, storage) = RecordingStreamBuilder::new("rect2d").memory()?; + + MsgSender::new("simple") + .with_component(&[Rect2D::XYWH(Vec4D([-1., -1., 2., 2.]))])? + .send(&rec_stream)?; + + // Log an extra rect to set the view bounds + MsgSender::new("bounds") + .with_component(&[Rect2D::XCYCWH(Vec4D([0.0, 0.0, 4.0, 3.0]))])? + .send(&rec_stream)?; + + rec_stream.flush_blocking(); + rerun::native_viewer::show(storage.take())?; + Ok(()) +} diff --git a/docs/code-examples/scalar_simple.rs b/docs/code-examples/scalar_simple.rs new file mode 100644 index 000000000000..1b5be4133ec1 --- /dev/null +++ b/docs/code-examples/scalar_simple.rs @@ -0,0 +1,26 @@ +//! Log a scalar over time. +use rand::{thread_rng, Rng}; +use rand_distr::StandardNormal; +use rerun::components::Scalar; +use rerun::time::{TimeType, Timeline}; +use rerun::{MsgSender, RecordingStreamBuilder}; + +fn main() -> Result<(), Box> { + let (rec_stream, storage) = RecordingStreamBuilder::new("scalar").memory()?; + + let step_timeline = Timeline::new("step", TimeType::Sequence); + + let mut value = 1.0; + for step in 0..100 { + MsgSender::new("scalar") + .with_component(&[Scalar::from(value)])? + .with_time(step_timeline, step) + .send(&rec_stream)?; + + value += thread_rng().sample::(StandardNormal); + } + + rec_stream.flush_blocking(); + rerun::native_viewer::show(storage.take())?; + Ok(()) +} diff --git a/docs/code-examples/segmentation_image_simple.rs b/docs/code-examples/segmentation_image_simple.rs new file mode 100644 index 000000000000..5d341befcfb1 --- /dev/null +++ b/docs/code-examples/segmentation_image_simple.rs @@ -0,0 +1,57 @@ +//! Create and log a segmentation image. +use ndarray::{s, Array, ShapeBuilder}; +use rerun::components::{ + AnnotationContext, AnnotationInfo, ClassDescription, ClassId, ColorRGBA, Label, Tensor, + TensorDataMeaning, +}; +use rerun::{MsgSender, RecordingStreamBuilder}; + +fn main() -> Result<(), Box> { + let (rec_stream, storage) = RecordingStreamBuilder::new("segmentation_image").memory()?; + + // create a segmentation image + let mut image = Array::::zeros((200, 300).f()); + image.slice_mut(s![50..150, 50..120]).fill(1); + image.slice_mut(s![100..180, 130..280]).fill(2); + + let mut tensor = Tensor::try_from(image.as_standard_layout().view())?; + tensor.meaning = TensorDataMeaning::ClassId; + + // create an annotation context to describe the classes + let mut annotation = AnnotationContext::default(); + annotation.class_map.insert( + ClassId(1), + ClassDescription { + info: AnnotationInfo { + id: 1, + label: Some(Label("red".to_owned())), + color: Some(ColorRGBA::from_rgb(255, 0, 0)), + }, + ..Default::default() + }, + ); + annotation.class_map.insert( + ClassId(2), + ClassDescription { + info: AnnotationInfo { + id: 2, + label: Some(Label("green".to_owned())), + color: Some(ColorRGBA::from_rgb(0, 255, 0)), + }, + ..Default::default() + }, + ); + + // log the annotation and the image + MsgSender::new("/") + .with_component(&[annotation])? + .send(&rec_stream)?; + + MsgSender::new("image") + .with_component(&[tensor])? + .send(&rec_stream)?; + + rec_stream.flush_blocking(); + rerun::native_viewer::show(storage.take())?; + Ok(()) +} diff --git a/docs/code-examples/tensor_one_dim.rs b/docs/code-examples/tensor_one_dim.rs new file mode 100644 index 000000000000..fa09d4dc6f3b --- /dev/null +++ b/docs/code-examples/tensor_one_dim.rs @@ -0,0 +1,21 @@ +//! Create and log a one dimensional tensor. +use ndarray::{Array, ShapeBuilder}; +use rand::{thread_rng, Rng}; +use rand_distr::StandardNormal; +use rerun::components::Tensor; +use rerun::{MsgSender, RecordingStreamBuilder}; + +fn main() -> Result<(), Box> { + let (rec_stream, storage) = RecordingStreamBuilder::new("tensors").memory()?; + + let mut data = Array::::default((100).f()); + data.map_inplace(|x| *x = thread_rng().sample(StandardNormal)); + + MsgSender::new("tensor") + .with_component(&[Tensor::try_from(data.as_standard_layout().view())?])? + .send(&rec_stream)?; + + rec_stream.flush_blocking(); + rerun::native_viewer::show(storage.take())?; + Ok(()) +} diff --git a/docs/code-examples/tensor_simple.rs b/docs/code-examples/tensor_simple.rs new file mode 100644 index 000000000000..98ee811ceeb2 --- /dev/null +++ b/docs/code-examples/tensor_simple.rs @@ -0,0 +1,25 @@ +//! Create and log a tensor. +use ndarray::{Array, ShapeBuilder}; +use rerun::components::Tensor; +use rerun::{MsgSender, RecordingStreamBuilder}; + +fn main() -> Result<(), Box> { + let (rec_stream, storage) = RecordingStreamBuilder::new("tensors").memory()?; + + let mut data = Array::::default((8, 6, 3, 5).f()); + data.map_inplace(|x| *x = rand::random()); + + let mut tensor = Tensor::try_from(data.as_standard_layout().view())?; + tensor.shape[0].name = Some("width".to_owned()); + tensor.shape[1].name = Some("height".to_owned()); + tensor.shape[2].name = Some("channel".to_owned()); + tensor.shape[3].name = Some("batch".to_owned()); + + MsgSender::new("tensor") + .with_component(&[tensor])? + .send(&rec_stream)?; + + rec_stream.flush_blocking(); + rerun::native_viewer::show(storage.take())?; + Ok(()) +} diff --git a/docs/code-examples/text_entry_simple.rs b/docs/code-examples/text_entry_simple.rs new file mode 100644 index 000000000000..17ed168b6074 --- /dev/null +++ b/docs/code-examples/text_entry_simple.rs @@ -0,0 +1,25 @@ +//! Log some text entries +use rerun::components::TextEntry; +use rerun::{MsgSender, RecordingStreamBuilder}; + +fn main() -> Result<(), Box> { + let (rec_stream, storage) = RecordingStreamBuilder::new("text_entry").memory()?; + + MsgSender::new("logs") + .with_component(&[TextEntry::new( + "this entry as loglevel TRACE", + Some("TRACE".into()), + )])? + .send(&rec_stream)?; + + MsgSender::new("logs") + .with_component(&[TextEntry::new( + "this other entry as loglevel INFO", + Some("INFO".into()), + )])? + .send(&rec_stream)?; + + rec_stream.flush_blocking(); + rerun::native_viewer::show(storage.take())?; + Ok(()) +} diff --git a/docs/code-examples/transform3d_simple.rs b/docs/code-examples/transform3d_simple.rs new file mode 100644 index 000000000000..402b553f1873 --- /dev/null +++ b/docs/code-examples/transform3d_simple.rs @@ -0,0 +1,50 @@ +//! Log different transforms between three arrows. +use rerun::components::{Arrow3D, Mat3x3, Transform3D, Vec3D}; +use rerun::transform::{ + Angle, Rotation3D, RotationAxisAngle, Scale3D, TranslationAndMat3, TranslationRotationScale3D, +}; +use rerun::{MsgSender, RecordingStreamBuilder}; +use std::f32::consts::PI; + +fn main() -> Result<(), Box> { + let (rec_stream, storage) = RecordingStreamBuilder::new("transform").memory()?; + + let arrow = Arrow3D { + origin: Vec3D::from([0.0, 0.0, 0.0]), + vector: Vec3D::from([0.0, 1.0, 0.0]), + }; + + MsgSender::new("base") + .with_component(&[arrow])? + .send(&rec_stream)?; + + MsgSender::new("base/translated") + .with_component(&[Transform3D::new(TranslationAndMat3::new( + Vec3D::from([1.0, 0.0, 0.0]), + Mat3x3::IDENTITY, + ))])? + .send(&rec_stream)?; + + MsgSender::new("base/translated") + .with_component(&[arrow])? + .send(&rec_stream)?; + + MsgSender::new("base/rotated_scaled") + .with_component(&[Transform3D::new(TranslationRotationScale3D { + translation: None, + rotation: Some(Rotation3D::from(RotationAxisAngle::new( + Vec3D::new(0.0, 0.0, 1.0), + Angle::Radians(PI / 4.), + ))), + scale: Some(Scale3D::from(2.0)), + })])? + .send(&rec_stream)?; + + MsgSender::new("base/rotated_scaled") + .with_component(&[arrow])? + .send(&rec_stream)?; + + rec_stream.flush_blocking(); + rerun::native_viewer::show(storage.take())?; + Ok(()) +}