re_types/archetypes/
points3d.rs

1// DO NOT EDIT! This file was auto-generated by crates/build/re_types_builder/src/codegen/rust/api.rs
2// Based on "crates/store/re_types/definitions/rerun/archetypes/points3d.fbs".
3
4#![allow(unused_braces)]
5#![allow(unused_imports)]
6#![allow(unused_parens)]
7#![allow(clippy::allow_attributes)]
8#![allow(clippy::clone_on_copy)]
9#![allow(clippy::cloned_instead_of_copied)]
10#![allow(clippy::map_flatten)]
11#![allow(clippy::needless_question_mark)]
12#![allow(clippy::new_without_default)]
13#![allow(clippy::redundant_closure)]
14#![allow(clippy::too_many_arguments)]
15#![allow(clippy::too_many_lines)]
16#![allow(clippy::wildcard_imports)]
17
18use ::re_types_core::SerializationResult;
19use ::re_types_core::try_serialize_field;
20use ::re_types_core::{ComponentBatch as _, SerializedComponentBatch};
21use ::re_types_core::{ComponentDescriptor, ComponentType};
22use ::re_types_core::{DeserializationError, DeserializationResult};
23
24/// **Archetype**: A 3D point cloud with positions and optional colors, radii, labels, etc.
25///
26/// If there are multiple instance poses, the entire point cloud will be repeated for each of the poses.
27///
28/// ## Examples
29///
30/// ### Simple 3D points
31/// ```ignore
32/// fn main() -> Result<(), Box<dyn std::error::Error>> {
33///     let rec = rerun::RecordingStreamBuilder::new("rerun_example_points3d").spawn()?;
34///
35///     rec.log(
36///         "points",
37///         &rerun::Points3D::new([(0.0, 0.0, 0.0), (1.0, 1.0, 1.0)]),
38///     )?;
39///
40///     Ok(())
41/// }
42/// ```
43/// <center>
44/// <picture>
45///   <source media="(max-width: 480px)" srcset="https://static.rerun.io/point3d_simple/32fb3e9b65bea8bd7ffff95ad839f2f8a157a933/480w.png">
46///   <source media="(max-width: 768px)" srcset="https://static.rerun.io/point3d_simple/32fb3e9b65bea8bd7ffff95ad839f2f8a157a933/768w.png">
47///   <source media="(max-width: 1024px)" srcset="https://static.rerun.io/point3d_simple/32fb3e9b65bea8bd7ffff95ad839f2f8a157a933/1024w.png">
48///   <source media="(max-width: 1200px)" srcset="https://static.rerun.io/point3d_simple/32fb3e9b65bea8bd7ffff95ad839f2f8a157a933/1200w.png">
49///   <img src="https://static.rerun.io/point3d_simple/32fb3e9b65bea8bd7ffff95ad839f2f8a157a933/full.png" width="640">
50/// </picture>
51/// </center>
52///
53/// ### Update a point cloud over time
54/// ```ignore
55/// fn main() -> Result<(), Box<dyn std::error::Error>> {
56///     let rec = rerun::RecordingStreamBuilder::new("rerun_example_points3d_row_updates").spawn()?;
57///
58///     // Prepare a point cloud that evolves over 5 timesteps, changing the number of points in the process.
59///     #[rustfmt::skip]
60///     let positions = [
61///         vec![[1.0, 0.0, 1.0], [0.5, 0.5, 2.0]],
62///         vec![[1.5, -0.5, 1.5], [1.0, 1.0, 2.5], [-0.5, 1.5, 1.0], [-1.5, 0.0, 2.0]],
63///         vec![[2.0, 0.0, 2.0], [1.5, -1.5, 3.0], [0.0, -2.0, 2.5], [1.0, -1.0, 3.5]],
64///         vec![[-2.0, 0.0, 2.0], [-1.5, 1.5, 3.0], [-1.0, 1.0, 3.5]],
65///         vec![[1.0, -1.0, 1.0], [2.0, -2.0, 2.0], [3.0, -1.0, 3.0], [2.0, 0.0, 4.0]],
66///     ];
67///
68///     // At each timestep, all points in the cloud share the same but changing color and radius.
69///     let colors = [0xFF0000FF, 0x00FF00FF, 0x0000FFFF, 0xFFFF00FF, 0x00FFFFFF];
70///     let radii = [0.05, 0.01, 0.2, 0.1, 0.3];
71///
72///     for (time, positions, color, radius) in itertools::izip!(10..15, positions, colors, radii) {
73///         rec.set_duration_secs("time", time);
74///
75///         let point_cloud = rerun::Points3D::new(positions)
76///             .with_colors([color])
77///             .with_radii([radius]);
78///
79///         rec.log("points", &point_cloud)?;
80///     }
81///
82///     Ok(())
83/// }
84/// ```
85/// <center>
86/// <picture>
87///   <source media="(max-width: 480px)" srcset="https://static.rerun.io/points3d_row_updates/fba056871b1ec3fc6978ab605d9a63e44ef1f6de/480w.png">
88///   <source media="(max-width: 768px)" srcset="https://static.rerun.io/points3d_row_updates/fba056871b1ec3fc6978ab605d9a63e44ef1f6de/768w.png">
89///   <source media="(max-width: 1024px)" srcset="https://static.rerun.io/points3d_row_updates/fba056871b1ec3fc6978ab605d9a63e44ef1f6de/1024w.png">
90///   <source media="(max-width: 1200px)" srcset="https://static.rerun.io/points3d_row_updates/fba056871b1ec3fc6978ab605d9a63e44ef1f6de/1200w.png">
91///   <img src="https://static.rerun.io/points3d_row_updates/fba056871b1ec3fc6978ab605d9a63e44ef1f6de/full.png" width="640">
92/// </picture>
93/// </center>
94///
95/// ### Update a point cloud over time, in a single operation
96/// ```ignore
97/// fn main() -> Result<(), Box<dyn std::error::Error>> {
98///     let rec =
99///         rerun::RecordingStreamBuilder::new("rerun_example_points3d_column_updates").spawn()?;
100///
101///     let times = rerun::TimeColumn::new_duration_secs("time", 10..15);
102///
103///     // Prepare a point cloud that evolves over 5 timesteps, changing the number of points in the process.
104///     #[rustfmt::skip]
105///     let positions = [
106///         [1.0, 0.0, 1.0], [0.5, 0.5, 2.0],
107///         [1.5, -0.5, 1.5], [1.0, 1.0, 2.5], [-0.5, 1.5, 1.0], [-1.5, 0.0, 2.0],
108///         [2.0, 0.0, 2.0], [1.5, -1.5, 3.0], [0.0, -2.0, 2.5], [1.0, -1.0, 3.5],
109///         [-2.0, 0.0, 2.0], [-1.5, 1.5, 3.0], [-1.0, 1.0, 3.5],
110///         [1.0, -1.0, 1.0], [2.0, -2.0, 2.0], [3.0, -1.0, 3.0], [2.0, 0.0, 4.0],
111///     ];
112///
113///     // At each timestep, all points in the cloud share the same but changing color and radius.
114///     let colors = [0xFF0000FF, 0x00FF00FF, 0x0000FFFF, 0xFFFF00FF, 0x00FFFFFF];
115///     let radii = [0.05, 0.01, 0.2, 0.1, 0.3];
116///
117///     // Partition our data as expected across the 5 timesteps.
118///     let position = rerun::Points3D::update_fields()
119///         .with_positions(positions)
120///         .columns([2, 4, 4, 3, 4])?;
121///     let color_and_radius = rerun::Points3D::update_fields()
122///         .with_colors(colors)
123///         .with_radii(radii)
124///         .columns_of_unit_batches()?;
125///
126///     rec.send_columns("points", [times], position.chain(color_and_radius))?;
127///
128///     Ok(())
129/// }
130/// ```
131/// <center>
132/// <picture>
133///   <source media="(max-width: 480px)" srcset="https://static.rerun.io/points3d_row_updates/fba056871b1ec3fc6978ab605d9a63e44ef1f6de/480w.png">
134///   <source media="(max-width: 768px)" srcset="https://static.rerun.io/points3d_row_updates/fba056871b1ec3fc6978ab605d9a63e44ef1f6de/768w.png">
135///   <source media="(max-width: 1024px)" srcset="https://static.rerun.io/points3d_row_updates/fba056871b1ec3fc6978ab605d9a63e44ef1f6de/1024w.png">
136///   <source media="(max-width: 1200px)" srcset="https://static.rerun.io/points3d_row_updates/fba056871b1ec3fc6978ab605d9a63e44ef1f6de/1200w.png">
137///   <img src="https://static.rerun.io/points3d_row_updates/fba056871b1ec3fc6978ab605d9a63e44ef1f6de/full.png" width="640">
138/// </picture>
139/// </center>
140///
141/// ### Update specific properties of a point cloud over time
142/// ```ignore
143/// fn main() -> Result<(), Box<dyn std::error::Error>> {
144///     let rec =
145///         rerun::RecordingStreamBuilder::new("rerun_example_points3d_partial_updates").spawn()?;
146///
147///     let positions = || (0..10).map(|i| (i as f32, 0.0, 0.0));
148///
149///     rec.set_time_sequence("frame", 0);
150///     rec.log("points", &rerun::Points3D::new(positions()))?;
151///
152///     for i in 0..10 {
153///         let colors = (0..10).map(|n| {
154///             if n < i {
155///                 rerun::Color::from_rgb(20, 200, 20)
156///             } else {
157///                 rerun::Color::from_rgb(200, 20, 20)
158///             }
159///         });
160///         let radii = (0..10).map(|n| if n < i { 0.6 } else { 0.2 });
161///
162///         // Update only the colors and radii, leaving everything else as-is.
163///         rec.set_time_sequence("frame", i);
164///         rec.log(
165///             "points",
166///             &rerun::Points3D::update_fields()
167///                 .with_radii(radii)
168///                 .with_colors(colors),
169///         )?;
170///     }
171///
172///     // Update the positions and radii, and clear everything else in the process.
173///     rec.set_time_sequence("frame", 20);
174///     rec.log(
175///         "points",
176///         &rerun::Points3D::clear_fields()
177///             .with_positions(positions())
178///             .with_radii([0.3]),
179///     )?;
180///
181///     Ok(())
182/// }
183/// ```
184/// <center>
185/// <picture>
186///   <source media="(max-width: 480px)" srcset="https://static.rerun.io/points3d_partial_updates/d8bec9c3388d2bd0fe59dff01ab8cde0bdda135e/480w.png">
187///   <source media="(max-width: 768px)" srcset="https://static.rerun.io/points3d_partial_updates/d8bec9c3388d2bd0fe59dff01ab8cde0bdda135e/768w.png">
188///   <source media="(max-width: 1024px)" srcset="https://static.rerun.io/points3d_partial_updates/d8bec9c3388d2bd0fe59dff01ab8cde0bdda135e/1024w.png">
189///   <source media="(max-width: 1200px)" srcset="https://static.rerun.io/points3d_partial_updates/d8bec9c3388d2bd0fe59dff01ab8cde0bdda135e/1200w.png">
190///   <img src="https://static.rerun.io/points3d_partial_updates/d8bec9c3388d2bd0fe59dff01ab8cde0bdda135e/full.png" width="640">
191/// </picture>
192/// </center>
193#[derive(Clone, Debug, PartialEq, Default)]
194pub struct Points3D {
195    /// All the 3D positions at which the point cloud shows points.
196    pub positions: Option<SerializedComponentBatch>,
197
198    /// Optional radii for the points, effectively turning them into circles.
199    pub radii: Option<SerializedComponentBatch>,
200
201    /// Optional colors for the points.
202    pub colors: Option<SerializedComponentBatch>,
203
204    /// Optional text labels for the points.
205    ///
206    /// If there's a single label present, it will be placed at the center of the entity.
207    /// Otherwise, each instance will have its own label.
208    pub labels: Option<SerializedComponentBatch>,
209
210    /// Whether the text labels should be shown.
211    ///
212    /// If not set, labels will automatically appear when there is exactly one label for this entity
213    /// or the number of instances on this entity is under a certain threshold.
214    pub show_labels: Option<SerializedComponentBatch>,
215
216    /// Optional class Ids for the points.
217    ///
218    /// The [`components::ClassId`][crate::components::ClassId] provides colors and labels if not specified explicitly.
219    pub class_ids: Option<SerializedComponentBatch>,
220
221    /// Optional keypoint IDs for the points, identifying them within a class.
222    ///
223    /// If keypoint IDs are passed in but no [`components::ClassId`][crate::components::ClassId]s were specified, the [`components::ClassId`][crate::components::ClassId] will
224    /// default to 0.
225    /// This is useful to identify points within a single classification (which is identified
226    /// with `class_id`).
227    /// E.g. the classification might be 'Person' and the keypoints refer to joints on a
228    /// detected skeleton.
229    pub keypoint_ids: Option<SerializedComponentBatch>,
230}
231
232impl Points3D {
233    /// Returns the [`ComponentDescriptor`] for [`Self::positions`].
234    ///
235    /// The corresponding component is [`crate::components::Position3D`].
236    #[inline]
237    pub fn descriptor_positions() -> ComponentDescriptor {
238        ComponentDescriptor {
239            archetype: Some("rerun.archetypes.Points3D".into()),
240            component: "Points3D:positions".into(),
241            component_type: Some("rerun.components.Position3D".into()),
242        }
243    }
244
245    /// Returns the [`ComponentDescriptor`] for [`Self::radii`].
246    ///
247    /// The corresponding component is [`crate::components::Radius`].
248    #[inline]
249    pub fn descriptor_radii() -> ComponentDescriptor {
250        ComponentDescriptor {
251            archetype: Some("rerun.archetypes.Points3D".into()),
252            component: "Points3D:radii".into(),
253            component_type: Some("rerun.components.Radius".into()),
254        }
255    }
256
257    /// Returns the [`ComponentDescriptor`] for [`Self::colors`].
258    ///
259    /// The corresponding component is [`crate::components::Color`].
260    #[inline]
261    pub fn descriptor_colors() -> ComponentDescriptor {
262        ComponentDescriptor {
263            archetype: Some("rerun.archetypes.Points3D".into()),
264            component: "Points3D:colors".into(),
265            component_type: Some("rerun.components.Color".into()),
266        }
267    }
268
269    /// Returns the [`ComponentDescriptor`] for [`Self::labels`].
270    ///
271    /// The corresponding component is [`crate::components::Text`].
272    #[inline]
273    pub fn descriptor_labels() -> ComponentDescriptor {
274        ComponentDescriptor {
275            archetype: Some("rerun.archetypes.Points3D".into()),
276            component: "Points3D:labels".into(),
277            component_type: Some("rerun.components.Text".into()),
278        }
279    }
280
281    /// Returns the [`ComponentDescriptor`] for [`Self::show_labels`].
282    ///
283    /// The corresponding component is [`crate::components::ShowLabels`].
284    #[inline]
285    pub fn descriptor_show_labels() -> ComponentDescriptor {
286        ComponentDescriptor {
287            archetype: Some("rerun.archetypes.Points3D".into()),
288            component: "Points3D:show_labels".into(),
289            component_type: Some("rerun.components.ShowLabels".into()),
290        }
291    }
292
293    /// Returns the [`ComponentDescriptor`] for [`Self::class_ids`].
294    ///
295    /// The corresponding component is [`crate::components::ClassId`].
296    #[inline]
297    pub fn descriptor_class_ids() -> ComponentDescriptor {
298        ComponentDescriptor {
299            archetype: Some("rerun.archetypes.Points3D".into()),
300            component: "Points3D:class_ids".into(),
301            component_type: Some("rerun.components.ClassId".into()),
302        }
303    }
304
305    /// Returns the [`ComponentDescriptor`] for [`Self::keypoint_ids`].
306    ///
307    /// The corresponding component is [`crate::components::KeypointId`].
308    #[inline]
309    pub fn descriptor_keypoint_ids() -> ComponentDescriptor {
310        ComponentDescriptor {
311            archetype: Some("rerun.archetypes.Points3D".into()),
312            component: "Points3D:keypoint_ids".into(),
313            component_type: Some("rerun.components.KeypointId".into()),
314        }
315    }
316}
317
318static REQUIRED_COMPONENTS: std::sync::LazyLock<[ComponentDescriptor; 1usize]> =
319    std::sync::LazyLock::new(|| [Points3D::descriptor_positions()]);
320
321static RECOMMENDED_COMPONENTS: std::sync::LazyLock<[ComponentDescriptor; 2usize]> =
322    std::sync::LazyLock::new(|| [Points3D::descriptor_radii(), Points3D::descriptor_colors()]);
323
324static OPTIONAL_COMPONENTS: std::sync::LazyLock<[ComponentDescriptor; 4usize]> =
325    std::sync::LazyLock::new(|| {
326        [
327            Points3D::descriptor_labels(),
328            Points3D::descriptor_show_labels(),
329            Points3D::descriptor_class_ids(),
330            Points3D::descriptor_keypoint_ids(),
331        ]
332    });
333
334static ALL_COMPONENTS: std::sync::LazyLock<[ComponentDescriptor; 7usize]> =
335    std::sync::LazyLock::new(|| {
336        [
337            Points3D::descriptor_positions(),
338            Points3D::descriptor_radii(),
339            Points3D::descriptor_colors(),
340            Points3D::descriptor_labels(),
341            Points3D::descriptor_show_labels(),
342            Points3D::descriptor_class_ids(),
343            Points3D::descriptor_keypoint_ids(),
344        ]
345    });
346
347impl Points3D {
348    /// The total number of components in the archetype: 1 required, 2 recommended, 4 optional
349    pub const NUM_COMPONENTS: usize = 7usize;
350}
351
352impl ::re_types_core::Archetype for Points3D {
353    #[inline]
354    fn name() -> ::re_types_core::ArchetypeName {
355        "rerun.archetypes.Points3D".into()
356    }
357
358    #[inline]
359    fn display_name() -> &'static str {
360        "Points 3D"
361    }
362
363    #[inline]
364    fn required_components() -> ::std::borrow::Cow<'static, [ComponentDescriptor]> {
365        REQUIRED_COMPONENTS.as_slice().into()
366    }
367
368    #[inline]
369    fn recommended_components() -> ::std::borrow::Cow<'static, [ComponentDescriptor]> {
370        RECOMMENDED_COMPONENTS.as_slice().into()
371    }
372
373    #[inline]
374    fn optional_components() -> ::std::borrow::Cow<'static, [ComponentDescriptor]> {
375        OPTIONAL_COMPONENTS.as_slice().into()
376    }
377
378    #[inline]
379    fn all_components() -> ::std::borrow::Cow<'static, [ComponentDescriptor]> {
380        ALL_COMPONENTS.as_slice().into()
381    }
382
383    #[inline]
384    fn from_arrow_components(
385        arrow_data: impl IntoIterator<Item = (ComponentDescriptor, arrow::array::ArrayRef)>,
386    ) -> DeserializationResult<Self> {
387        re_tracing::profile_function!();
388        use ::re_types_core::{Loggable as _, ResultExt as _};
389        let arrays_by_descr: ::nohash_hasher::IntMap<_, _> = arrow_data.into_iter().collect();
390        let positions = arrays_by_descr
391            .get(&Self::descriptor_positions())
392            .map(|array| {
393                SerializedComponentBatch::new(array.clone(), Self::descriptor_positions())
394            });
395        let radii = arrays_by_descr
396            .get(&Self::descriptor_radii())
397            .map(|array| SerializedComponentBatch::new(array.clone(), Self::descriptor_radii()));
398        let colors = arrays_by_descr
399            .get(&Self::descriptor_colors())
400            .map(|array| SerializedComponentBatch::new(array.clone(), Self::descriptor_colors()));
401        let labels = arrays_by_descr
402            .get(&Self::descriptor_labels())
403            .map(|array| SerializedComponentBatch::new(array.clone(), Self::descriptor_labels()));
404        let show_labels = arrays_by_descr
405            .get(&Self::descriptor_show_labels())
406            .map(|array| {
407                SerializedComponentBatch::new(array.clone(), Self::descriptor_show_labels())
408            });
409        let class_ids = arrays_by_descr
410            .get(&Self::descriptor_class_ids())
411            .map(|array| {
412                SerializedComponentBatch::new(array.clone(), Self::descriptor_class_ids())
413            });
414        let keypoint_ids = arrays_by_descr
415            .get(&Self::descriptor_keypoint_ids())
416            .map(|array| {
417                SerializedComponentBatch::new(array.clone(), Self::descriptor_keypoint_ids())
418            });
419        Ok(Self {
420            positions,
421            radii,
422            colors,
423            labels,
424            show_labels,
425            class_ids,
426            keypoint_ids,
427        })
428    }
429}
430
431impl ::re_types_core::AsComponents for Points3D {
432    #[inline]
433    fn as_serialized_batches(&self) -> Vec<SerializedComponentBatch> {
434        use ::re_types_core::Archetype as _;
435        [
436            self.positions.clone(),
437            self.radii.clone(),
438            self.colors.clone(),
439            self.labels.clone(),
440            self.show_labels.clone(),
441            self.class_ids.clone(),
442            self.keypoint_ids.clone(),
443        ]
444        .into_iter()
445        .flatten()
446        .collect()
447    }
448}
449
450impl ::re_types_core::ArchetypeReflectionMarker for Points3D {}
451
452impl Points3D {
453    /// Create a new `Points3D`.
454    #[inline]
455    pub fn new(
456        positions: impl IntoIterator<Item = impl Into<crate::components::Position3D>>,
457    ) -> Self {
458        Self {
459            positions: try_serialize_field(Self::descriptor_positions(), positions),
460            radii: None,
461            colors: None,
462            labels: None,
463            show_labels: None,
464            class_ids: None,
465            keypoint_ids: None,
466        }
467    }
468
469    /// Update only some specific fields of a `Points3D`.
470    #[inline]
471    pub fn update_fields() -> Self {
472        Self::default()
473    }
474
475    /// Clear all the fields of a `Points3D`.
476    #[inline]
477    pub fn clear_fields() -> Self {
478        use ::re_types_core::Loggable as _;
479        Self {
480            positions: Some(SerializedComponentBatch::new(
481                crate::components::Position3D::arrow_empty(),
482                Self::descriptor_positions(),
483            )),
484            radii: Some(SerializedComponentBatch::new(
485                crate::components::Radius::arrow_empty(),
486                Self::descriptor_radii(),
487            )),
488            colors: Some(SerializedComponentBatch::new(
489                crate::components::Color::arrow_empty(),
490                Self::descriptor_colors(),
491            )),
492            labels: Some(SerializedComponentBatch::new(
493                crate::components::Text::arrow_empty(),
494                Self::descriptor_labels(),
495            )),
496            show_labels: Some(SerializedComponentBatch::new(
497                crate::components::ShowLabels::arrow_empty(),
498                Self::descriptor_show_labels(),
499            )),
500            class_ids: Some(SerializedComponentBatch::new(
501                crate::components::ClassId::arrow_empty(),
502                Self::descriptor_class_ids(),
503            )),
504            keypoint_ids: Some(SerializedComponentBatch::new(
505                crate::components::KeypointId::arrow_empty(),
506                Self::descriptor_keypoint_ids(),
507            )),
508        }
509    }
510
511    /// Partitions the component data into multiple sub-batches.
512    ///
513    /// Specifically, this transforms the existing [`SerializedComponentBatch`]es data into [`SerializedComponentColumn`]s
514    /// instead, via [`SerializedComponentBatch::partitioned`].
515    ///
516    /// This makes it possible to use `RecordingStream::send_columns` to send columnar data directly into Rerun.
517    ///
518    /// The specified `lengths` must sum to the total length of the component batch.
519    ///
520    /// [`SerializedComponentColumn`]: [::re_types_core::SerializedComponentColumn]
521    #[inline]
522    pub fn columns<I>(
523        self,
524        _lengths: I,
525    ) -> SerializationResult<impl Iterator<Item = ::re_types_core::SerializedComponentColumn>>
526    where
527        I: IntoIterator<Item = usize> + Clone,
528    {
529        let columns = [
530            self.positions
531                .map(|positions| positions.partitioned(_lengths.clone()))
532                .transpose()?,
533            self.radii
534                .map(|radii| radii.partitioned(_lengths.clone()))
535                .transpose()?,
536            self.colors
537                .map(|colors| colors.partitioned(_lengths.clone()))
538                .transpose()?,
539            self.labels
540                .map(|labels| labels.partitioned(_lengths.clone()))
541                .transpose()?,
542            self.show_labels
543                .map(|show_labels| show_labels.partitioned(_lengths.clone()))
544                .transpose()?,
545            self.class_ids
546                .map(|class_ids| class_ids.partitioned(_lengths.clone()))
547                .transpose()?,
548            self.keypoint_ids
549                .map(|keypoint_ids| keypoint_ids.partitioned(_lengths.clone()))
550                .transpose()?,
551        ];
552        Ok(columns.into_iter().flatten())
553    }
554
555    /// Helper to partition the component data into unit-length sub-batches.
556    ///
557    /// This is semantically similar to calling [`Self::columns`] with `std::iter::take(1).repeat(n)`,
558    /// where `n` is automatically guessed.
559    #[inline]
560    pub fn columns_of_unit_batches(
561        self,
562    ) -> SerializationResult<impl Iterator<Item = ::re_types_core::SerializedComponentColumn>> {
563        let len_positions = self.positions.as_ref().map(|b| b.array.len());
564        let len_radii = self.radii.as_ref().map(|b| b.array.len());
565        let len_colors = self.colors.as_ref().map(|b| b.array.len());
566        let len_labels = self.labels.as_ref().map(|b| b.array.len());
567        let len_show_labels = self.show_labels.as_ref().map(|b| b.array.len());
568        let len_class_ids = self.class_ids.as_ref().map(|b| b.array.len());
569        let len_keypoint_ids = self.keypoint_ids.as_ref().map(|b| b.array.len());
570        let len = None
571            .or(len_positions)
572            .or(len_radii)
573            .or(len_colors)
574            .or(len_labels)
575            .or(len_show_labels)
576            .or(len_class_ids)
577            .or(len_keypoint_ids)
578            .unwrap_or(0);
579        self.columns(std::iter::repeat_n(1, len))
580    }
581
582    /// All the 3D positions at which the point cloud shows points.
583    #[inline]
584    pub fn with_positions(
585        mut self,
586        positions: impl IntoIterator<Item = impl Into<crate::components::Position3D>>,
587    ) -> Self {
588        self.positions = try_serialize_field(Self::descriptor_positions(), positions);
589        self
590    }
591
592    /// Optional radii for the points, effectively turning them into circles.
593    #[inline]
594    pub fn with_radii(
595        mut self,
596        radii: impl IntoIterator<Item = impl Into<crate::components::Radius>>,
597    ) -> Self {
598        self.radii = try_serialize_field(Self::descriptor_radii(), radii);
599        self
600    }
601
602    /// Optional colors for the points.
603    #[inline]
604    pub fn with_colors(
605        mut self,
606        colors: impl IntoIterator<Item = impl Into<crate::components::Color>>,
607    ) -> Self {
608        self.colors = try_serialize_field(Self::descriptor_colors(), colors);
609        self
610    }
611
612    /// Optional text labels for the points.
613    ///
614    /// If there's a single label present, it will be placed at the center of the entity.
615    /// Otherwise, each instance will have its own label.
616    #[inline]
617    pub fn with_labels(
618        mut self,
619        labels: impl IntoIterator<Item = impl Into<crate::components::Text>>,
620    ) -> Self {
621        self.labels = try_serialize_field(Self::descriptor_labels(), labels);
622        self
623    }
624
625    /// Whether the text labels should be shown.
626    ///
627    /// If not set, labels will automatically appear when there is exactly one label for this entity
628    /// or the number of instances on this entity is under a certain threshold.
629    #[inline]
630    pub fn with_show_labels(
631        mut self,
632        show_labels: impl Into<crate::components::ShowLabels>,
633    ) -> Self {
634        self.show_labels = try_serialize_field(Self::descriptor_show_labels(), [show_labels]);
635        self
636    }
637
638    /// This method makes it possible to pack multiple [`crate::components::ShowLabels`] in a single component batch.
639    ///
640    /// This only makes sense when used in conjunction with [`Self::columns`]. [`Self::with_show_labels`] should
641    /// be used when logging a single row's worth of data.
642    #[inline]
643    pub fn with_many_show_labels(
644        mut self,
645        show_labels: impl IntoIterator<Item = impl Into<crate::components::ShowLabels>>,
646    ) -> Self {
647        self.show_labels = try_serialize_field(Self::descriptor_show_labels(), show_labels);
648        self
649    }
650
651    /// Optional class Ids for the points.
652    ///
653    /// The [`components::ClassId`][crate::components::ClassId] provides colors and labels if not specified explicitly.
654    #[inline]
655    pub fn with_class_ids(
656        mut self,
657        class_ids: impl IntoIterator<Item = impl Into<crate::components::ClassId>>,
658    ) -> Self {
659        self.class_ids = try_serialize_field(Self::descriptor_class_ids(), class_ids);
660        self
661    }
662
663    /// Optional keypoint IDs for the points, identifying them within a class.
664    ///
665    /// If keypoint IDs are passed in but no [`components::ClassId`][crate::components::ClassId]s were specified, the [`components::ClassId`][crate::components::ClassId] will
666    /// default to 0.
667    /// This is useful to identify points within a single classification (which is identified
668    /// with `class_id`).
669    /// E.g. the classification might be 'Person' and the keypoints refer to joints on a
670    /// detected skeleton.
671    #[inline]
672    pub fn with_keypoint_ids(
673        mut self,
674        keypoint_ids: impl IntoIterator<Item = impl Into<crate::components::KeypointId>>,
675    ) -> Self {
676        self.keypoint_ids = try_serialize_field(Self::descriptor_keypoint_ids(), keypoint_ids);
677        self
678    }
679}
680
681impl ::re_byte_size::SizeBytes for Points3D {
682    #[inline]
683    fn heap_size_bytes(&self) -> u64 {
684        self.positions.heap_size_bytes()
685            + self.radii.heap_size_bytes()
686            + self.colors.heap_size_bytes()
687            + self.labels.heap_size_bytes()
688            + self.show_labels.heap_size_bytes()
689            + self.class_ids.heap_size_bytes()
690            + self.keypoint_ids.heap_size_bytes()
691    }
692}