class_docstr: This class provides functions for working with batches of 3d point clouds,
  and converting between representations.
  
  Within Pointclouds, there are three different representations of the data.
  
  List
     - only used for input as a starting point to convert to other representations.
  Padded
     - has specific batch dimension.
  Packed
     - no batch dimension.
     - has auxiliary variables used to index into the padded representation.
  
  Example
  
  Input list of points = [[P_1], [P_2], ... , [P_N]]
  where P_1, ... , P_N are the number of points in each cloud and N is the
  number of clouds.
  
  # SPHINX IGNORE
   List                      | Padded                  | Packed
  ---------------------------|-------------------------|------------------------
  [[P_1], ... , [P_N]]       | size = (N, max(P_n), 3) |  size = (sum(P_n), 3)
                             |                         |
  Example for locations      |                         |
  or colors:                 |                         |
                             |                         |
  P_1 = 3, P_2 = 4, P_3 = 5  | size = (3, 5, 3)        |  size = (12, 3)
                             |                         |
  List([                     | tensor([                |  tensor([
    [                        |     [                   |    [0.1, 0.3, 0.5],
      [0.1, 0.3, 0.5],       |       [0.1, 0.3, 0.5],  |    [0.5, 0.2, 0.1],
      [0.5, 0.2, 0.1],       |       [0.5, 0.2, 0.1],  |    [0.6, 0.8, 0.7],
      [0.6, 0.8, 0.7]        |       [0.6, 0.8, 0.7],  |    [0.1, 0.3, 0.3],
    ],                       |       [0,    0,    0],  |    [0.6, 0.7, 0.8],
    [                        |       [0,    0,    0]   |    [0.2, 0.3, 0.4],
      [0.1, 0.3, 0.3],       |     ],                  |    [0.1, 0.5, 0.3],
      [0.6, 0.7, 0.8],       |     [                   |    [0.7, 0.3, 0.6],
      [0.2, 0.3, 0.4],       |       [0.1, 0.3, 0.3],  |    [0.2, 0.4, 0.8],
      [0.1, 0.5, 0.3]        |       [0.6, 0.7, 0.8],  |    [0.9, 0.5, 0.2],
    ],                       |       [0.2, 0.3, 0.4],  |    [0.2, 0.3, 0.4],
    [                        |       [0.1, 0.5, 0.3],  |    [0.9, 0.3, 0.8],
      [0.7, 0.3, 0.6],       |       [0,    0,    0]   |  ])
      [0.2, 0.4, 0.8],       |     ],                  |
      [0.9, 0.5, 0.2],       |     [                   |
      [0.2, 0.3, 0.4],       |       [0.7, 0.3, 0.6],  |
      [0.9, 0.3, 0.8],       |       [0.2, 0.4, 0.8],  |
    ]                        |       [0.9, 0.5, 0.2],  |
  ])                         |       [0.2, 0.3, 0.4],  |
                             |       [0.9, 0.3, 0.8]   |
                             |     ]                   |
                             |  ])                     |
  -----------------------------------------------------------------------------
  
  Auxiliary variables for packed representation
  
  Name                           |   Size              |  Example from above
  -------------------------------|---------------------|-----------------------
                                 |                     |
  packed_to_cloud_idx            |  size = (sum(P_n))  |   tensor([
                                 |                     |     0, 0, 0, 1, 1, 1,
                                 |                     |     1, 2, 2, 2, 2, 2
                                 |                     |   )]
                                 |                     |   size = (12)
                                 |                     |
  cloud_to_packed_first_idx      |  size = (N)         |   tensor([0, 3, 7])
                                 |                     |   size = (3)
                                 |                     |
  num_points_per_cloud           |  size = (N)         |   tensor([3, 4, 5])
                                 |                     |   size = (3)
                                 |                     |
  padded_to_packed_idx           |  size = (sum(P_n))  |  tensor([
                                 |                     |     0, 1, 2, 5, 6, 7,
                                 |                     |     8, 10, 11, 12, 13,
                                 |                     |     14
                                 |                     |  )]
                                 |                     |  size = (12)
  -----------------------------------------------------------------------------
  # SPHINX IGNORE
class_docstr_tok: ["This","class","provides","functions","for","working","with","batches","of","3d","point","clouds",",","and","converting","between","representations",".","Within","Pointclouds",",","there","are","three","different","representations","of","the","data",".","List","-","only","used","for","input","as","a","starting","point","to","convert","to","other","representations",".","Padded","-","has","specific","batch","dimension",".","Packed","-","no","batch","dimension",".","-","has","auxiliary","variables","used","to","index","into","the","padded","representation",".","Example","Input","list","of","points","=","[","[","P_1","]",",","[","P_2","]",",","...",",","[","P_N","]","]","where","P_1",",","...",",","P_N","are","the","number","of","points","in","each","cloud","and","N","is","the","number","of","clouds",".","#","SPHINX","IGNORE","List","|","Padded","|","Packed","--","--","--","--","--","--","--","--","--","--","--","--","--","-|","--","--","--","--","--","--","--","--","--","--","--","--","-|","--","--","--","--","--","--","--","--","--","--","--","--","[","[","P_1","]",",","...",",","[","P_N","]","]","|","size","=","(","N",",","max","(","P_n",")",",","3",")","|","size","=","(","sum","(","P_n",")",",","3",")","|","|","Example","for","locations","|","|","or","colors",":","|","|","|","|","P_1","=","3",",","P_2","=","4",",","P_3","=","5","|","size","=","(","3",",","5",",","3",")","|","size","=","(","12",",","3",")","|","|","List","(","[","|","tensor","(","[","|","tensor","(","[","[","|","[","|","[","0.1",",","0.3",",","0.5","]",",","[","0.1",",","0.3",",","0.5","]",",","|","[","0.1",",","0.3",",","0.5","]",",","|","[","0.5",",","0.2",",","0.1","]",",","[","0.5",",","0.2",",","0.1","]",",","|","[","0.5",",","0.2",",","0.1","]",",","|","[","0.6",",","0.8",",","0.7","]",",","[","0.6",",","0.8",",","0.7","]","|","[","0.6",",","0.8",",","0.7","]",",","|","[","0.1",",","0.3",",","0.3","]",",","]",",","|","[","0",",","0",",","0","]",",","|","[","0.6",",","0.7",",","0.8","]",",","[","|","[","0",",","0",",","0","]","|","[","0.2",",","0.3",",","0.4","]",",","[","0.1",",","0.3",",","0.3","]",",","|","]",",","|","[","0.1",",","0.5",",","0.3","]",",","[","0.6",",","0.7",",","0.8","]",",","|","[","|","[","0.7",",","0.3",",","0.6","]",",","[","0.2",",","0.3",",","0.4","]",",","|","[","0.1",",","0.3",",","0.3","]",",","|","[","0.2",",","0.4",",","0.8","]",",","[","0.1",",","0.5",",","0.3","]","|","[","0.6",",","0.7",",","0.8","]",",","|","[","0.9",",","0.5",",","0.2","]",",","]",",","|","[","0.2",",","0.3",",","0.4","]",",","|","[","0.2",",","0.3",",","0.4","]",",","[","|","[","0.1",",","0.5",",","0.3","]",",","|","[","0.9",",","0.3",",","0.8","]",",","[","0.7",",","0.3",",","0.6","]",",","|","[","0",",","0",",","0","]","|","]",")","[","0.2",",","0.4",",","0.8","]",",","|","]",",","|","[","0.9",",","0.5",",","0.2","]",",","|","[","|","[","0.2",",","0.3",",","0.4","]",",","|","[","0.7",",","0.3",",","0.6","]",",","|","[","0.9",",","0.3",",","0.8","]",",","|","[","0.2",",","0.4",",","0.8","]",",","|","]","|","[","0.9",",","0.5",",","0.2","]",",","|","]",")","|","[","0.2",",","0.3",",","0.4","]",",","|","|","[","0.9",",","0.3",",","0.8","]","|","|","]","|","|","]",")","|","--","--","--","--","--","--","--","--","--","--","--","--","--","--","--","--","--","--","--","--","--","--","--","--","--","--","--","--","--","--","--","--","--","--","--","--","--","--","-","Auxiliary","variables","for","packed","representation","Name","|","Size","|","Example","from","above","--","--","--","--","--","--","--","--","--","--","--","--","--","--","--","-|","--","--","--","--","--","--","--","--","--","--","-|","--","--","--","--","--","--","--","--","--","--","--","-","|","|","packed_to_cloud_idx","|","size","=","(","sum","(","P_n",")",")","|","tensor","(","[","|","|","0",",","0",",","0",",","1",",","1",",","1",",","|","|","1",",","2",",","2",",","2",",","2",",","2","|","|",")","]","|","|","size","=","(","12",")","|","|","cloud_to_packed_first_idx","|","size","=","(","N",")","|","tensor","(","[","0",",","3",",","7","]",")","|","|","size","=","(","3",")","|","|","num_points_per_cloud","|","size","=","(","N",")","|","tensor","(","[","3",",","4",",","5","]",")","|","|","size","=","(","3",")","|","|","padded_to_packed_idx","|","size","=","(","sum","(","P_n",")",")","|","tensor","(","[","|","|","0",",","1",",","2",",","5",",","6",",","7",",","|","|","8",",","10",",","11",",","12",",","13",",","|","|","14","|","|",")","]","|","|","size","=","(","12",")","--","--","--","--","--","--","--","--","--","--","--","--","--","--","--","--","--","--","--","--","--","--","--","--","--","--","--","--","--","--","--","--","--","--","--","--","--","--","-","#","SPHINX","IGNORE"]
docstr: Args:
      points:
          Can be either
  
          - List where each element is a tensor of shape (num_points, 3)
            containing the (x, y, z) coordinates of each point.
          - Padded float tensor with shape (num_clouds, num_points, 3).
      normals:
          Can be either
  
          - None
          - List where each element is a tensor of shape (num_points, 3)
            containing the normal vector for each point.
          - Padded float tensor of shape (num_clouds, num_points, 3).
      features:
          Can be either
  
          - None
          - List where each element is a tensor of shape (num_points, C)
            containing the features for the points in the cloud.
          - Padded float tensor of shape (num_clouds, num_points, C).
          where C is the number of channels in the features.
          For example 3 for RGB color.
  
  Refer to comments above for descriptions of List and Padded
  representations.
docstr_tok: ["Args",":","points",":","Can","be","either","-","List","where","each","element","is","a","tensor","of","shape","(","num_points",",","3",")","containing","the","(","x",",","y",",","z",")","coordinates","of","each","point",".","-","Padded","float","tensor","with","shape","(","num_clouds",",","num_points",",","3",")",".","normals",":","Can","be","either","-","None","-","List","where","each","element","is","a","tensor","of","shape","(","num_points",",","3",")","containing","the","normal","vector","for","each","point",".","-","Padded","float","tensor","of","shape","(","num_clouds",",","num_points",",","3",")",".","features",":","Can","be","either","-","None","-","List","where","each","element","is","a","tensor","of","shape","(","num_points",",","C",")","containing","the","features","for","the","points","in","the","cloud",".","-","Padded","float","tensor","of","shape","(","num_clouds",",","num_points",",","C",")",".","where","C","is","the","number","of","channels","in","the","features",".","For","example","3","for","RGB","color",".","Refer","to","comments","above","for","descriptions","of","List","and","Padded","representations","."]
code: def __init__(self, points, normals=None, features=None) -> None:
      """
      Args:
          points:
              Can be either
  
              - List where each element is a tensor of shape (num_points, 3)
                containing the (x, y, z) coordinates of each point.
              - Padded float tensor with shape (num_clouds, num_points, 3).
          normals:
              Can be either
  
              - None
              - List where each element is a tensor of shape (num_points, 3)
                containing the normal vector for each point.
              - Padded float tensor of shape (num_clouds, num_points, 3).
          features:
              Can be either
  
              - None
              - List where each element is a tensor of shape (num_points, C)
                containing the features for the points in the cloud.
              - Padded float tensor of shape (num_clouds, num_points, C).
              where C is the number of channels in the features.
              For example 3 for RGB color.
  
      Refer to comments above for descriptions of List and Padded
      representations.
      """
      self.device = torch.device("cpu")
  
      # Indicates whether the clouds in the list/batch have the same number
      # of points.
      self.equisized = False
  
      # Boolean indicator for each cloud in the batch.
      # True if cloud has non zero number of points, False otherwise.
      self.valid = None
  
      self._N = 0  # batch size (number of clouds)
      self._P = 0  # (max) number of points per cloud
      self._C = None  # number of channels in the features
  
      # List of Tensors of points and features.
      self._points_list = None
      self._normals_list = None
      self._features_list = None
  
      # Number of points per cloud.
      self._num_points_per_cloud = None  # N
  
      # Packed representation.
      self._points_packed = None  # (sum(P_n), 3)
      self._normals_packed = None  # (sum(P_n), 3)
      self._features_packed = None  # (sum(P_n), C)
  
      self._packed_to_cloud_idx = None  # sum(P_n)
  
      # Index of each cloud's first point in the packed points.
      # Assumes packing is sequential.
      self._cloud_to_packed_first_idx = None  # N
  
      # Padded representation.
      self._points_padded = None  # (N, max(P_n), 3)
      self._normals_padded = None  # (N, max(P_n), 3)
      self._features_padded = None  # (N, max(P_n), C)
  
      # Index to convert points from flattened padded to packed.
      self._padded_to_packed_idx = None  # N * max_P
  
      # Identify type of points.
      if isinstance(points, list):
          self._points_list = points
          self._N = len(self._points_list)
          self.valid = torch.zeros(
              (self._N,), dtype=torch.bool, device=self.device
          )
  
          if self._N > 0:
              self.device = self._points_list[0].device
              for p in self._points_list:
                  if len(p) > 0 and (p.dim() != 2 or p.shape[1] != 3):
                      raise ValueError(
                          "Clouds in list must be of shape Px3 or empty"
                      )
                  if p.device != self.device:
                      raise ValueError(
                          "All points must be on the same device"
                      )
  
              num_points_per_cloud = torch.tensor(
                  [len(p) for p in self._points_list],
                  device=self.device,
              )
              self._P = int(num_points_per_cloud.max())
              self.valid = torch.tensor(
                  [len(p) > 0 for p in self._points_list],
                  dtype=torch.bool,
                  device=self.device,
              )
  
              if len(num_points_per_cloud.unique()) == 1:
                  self.equisized = True
              self._num_points_per_cloud = num_points_per_cloud
          else:
              self._num_points_per_cloud = torch.tensor(
                  [], dtype=torch.int64
              )
  
      elif torch.is_tensor(points):
          if points.dim() != 3 or points.shape[2] != 3:
              raise ValueError(
                  "Points tensor has incorrect dimensions."
              )
          self._points_padded = points
          self._N = self._points_padded.shape[0]
          self._P = self._points_padded.shape[1]
          self.device = self._points_padded.device
          self.valid = torch.ones(
              (self._N,), dtype=torch.bool, device=self.device
          )
          self._num_points_per_cloud = torch.tensor(
              [self._P] * self._N, device=self.device
          )
          self.equisized = True
      else:
          raise ValueError(
              "Points must be either a list or a tensor with \
                      shape (batch_size, P, 3) where P is the maximum number of \
                      points in a cloud."
          )
  
      # parse normals
      normals_parsed = self._parse_auxiliary_input(normals)
      (
          self._normals_list,
          self._normals_padded,
          normals_C,
      ) = normals_parsed
      if normals_C is not None and normals_C != 3:
          raise ValueError("Normals are expected to be 3-dimensional")
  
      # parse features
      features_parsed = self._parse_auxiliary_input(features)
      (
          self._features_list,
          self._features_padded,
          features_C,
      ) = features_parsed
      if features_C is not None:
          self._C = features_C
  
imports: from itertools import zip_longest
  from typing import List, Optional, Sequence, Tuple, Union
  import numpy
  import torch
  from ..common.datatypes import Device, make_device
  from .None import utils
label_desc: Use image node_id 1 to create a new Pointclouds object  with example: obj = Pointclouds(points, normals, features)