ACloudViewer  3.9.4
A Modern Library for 3D Data Processing
VtkUtils.cpp
Go to the documentation of this file.
1 // ----------------------------------------------------------------------------
2 // - CloudViewer: www.cloudViewer.org -
3 // ----------------------------------------------------------------------------
4 // Copyright (c) 2018-2024 www.cloudViewer.org
5 // SPDX-License-Identifier: MIT
6 // ----------------------------------------------------------------------------
7 
9 
10 #include <vtkArrayDispatch.h>
11 #include <vtkCellArray.h>
12 #include <vtkCellData.h>
13 #include <vtkDoubleArray.h>
14 #include <vtkFloatArray.h>
15 #include <vtkImageData.h>
16 #include <vtkLinearExtrusionFilter.h>
17 #include <vtkPointData.h>
18 #include <vtkPoints.h>
19 #include <vtkPolyDataNormals.h>
20 #include <vtkRotationalExtrusionFilter.h>
21 #include <vtkTriangleFilter.h>
22 
23 #include <map>
24 
25 namespace cloudViewer {
26 namespace t {
27 namespace geometry {
28 namespace vtkutils {
29 
30 int DtypeToVtkType(const core::Dtype& dtype) {
31  if (dtype == core::Float32) {
32  return VTK_FLOAT;
33  } else if (dtype == core::Float64) {
34  return VTK_DOUBLE;
35  } else if (dtype == core::Int8) {
36  return VTK_TYPE_INT8;
37  } else if (dtype == core::Int16) {
38  return VTK_TYPE_INT16;
39  } else if (dtype == core::Int32) {
40  return VTK_TYPE_INT32;
41  } else if (dtype == core::Int64) {
42  return VTK_TYPE_INT64;
43  } else if (dtype == core::UInt8) {
44  return VTK_TYPE_UINT8;
45  } else if (dtype == core::UInt16) {
46  return VTK_TYPE_UINT16;
47  } else if (dtype == core::UInt32) {
48  return VTK_TYPE_UINT32;
49  } else if (dtype == core::UInt64) {
50  return VTK_TYPE_UINT64;
51  } else if (dtype == core::Bool) {
52  // VTK_BIT arrays are compact and store 8 booleans per byte!
53  return VTK_BIT;
54  } else {
55  utility::LogError("Type {} cannot be converted to a vtk data type!",
56  dtype.ToString());
57  }
58  return VTK_INT;
59 }
60 
61 // map types used by vtk to compatible Tensor types
62 template <class T>
64  typedef T TensorType;
65 };
66 
67 template <>
68 struct VtkToTensorType<long long> {
69  typedef int64_t TensorType;
70 };
71 
72 namespace {
73 struct CreateTensorFromVtkDataArrayWorker {
74  bool copy;
75  vtkDataArray* data_array;
76  core::Tensor result;
77 
78  template <class TArray>
79  void operator()(TArray* array) {
80  typedef typename TArray::ValueType T;
81  typedef typename VtkToTensorType<T>::TensorType TTensor;
82  auto dtype = core::Dtype::FromType<TTensor>();
83  int64_t length = array->GetNumberOfTuples();
84  int64_t num_components = array->GetNumberOfComponents();
85 
86  // copy if requested or the layout is not contiguous
87  if (copy || !array->HasStandardMemoryLayout()) {
88  result = core::Tensor({length, num_components}, dtype);
89  if (array->HasStandardMemoryLayout()) {
90  memcpy(array->GetVoidPointer(0), result.GetDataPtr(),
91  dtype.ByteSize() * result.NumElements());
92  } else {
93  TTensor* data = result.GetDataPtr<TTensor>();
94  for (int64_t i = 0; i < length; ++i) {
95  for (int64_t j = 0; j < num_components; ++j) {
96  *data = array->GetTypedComponent(i, j);
97  ++data;
98  }
99  }
100  }
101  } else {
102  vtkSmartPointer<vtkDataArray> sp(data_array); // inc the refcount
103  auto blob = std::make_shared<core::Blob>(core::Device(),
104  array->GetVoidPointer(0),
105  [sp](void*) { (void)sp; });
106  core::SizeVector shape{length, num_components};
107  auto strides = core::shape_util::DefaultStrides(shape);
108  result = core::Tensor(shape, strides, blob->GetDataPtr(), dtype,
109  blob);
110  }
111  }
112 };
113 } // namespace
114 
122 static core::Tensor CreateTensorFromVtkDataArray(vtkDataArray* array,
123  bool copy = false) {
124  CreateTensorFromVtkDataArrayWorker worker;
125  worker.copy = copy;
126  worker.data_array = array;
127  typedef vtkTypeList_Create_7(float, double, int32_t, int64_t, uint32_t,
128  uint64_t, long long) ArrayTypes;
130  return worker.result;
131 }
132 
138 static vtkSmartPointer<vtkDataArray> CreateVtkDataArrayFromTensor(
139  core::Tensor& tensor, bool copy) {
141  if (tensor.GetDtype() == core::Bool) {
143  "Tensor conversion with type Bool is not implemented!");
144  }
145 
146  int vtk_data_type = DtypeToVtkType(tensor.GetDtype());
147 
148  vtkSmartPointer<vtkDataArray> data_array;
149  data_array.TakeReference(vtkDataArray::CreateDataArray(vtk_data_type));
150 
151  if (!copy && tensor.IsContiguous() &&
152  tensor.GetDevice() == core::Device()) {
153  // reuse tensor memory
154  data_array->SetVoidArray(tensor.GetDataPtr(), tensor.NumElements(),
155  1 /*dont delete*/);
156  data_array->SetNumberOfComponents(tensor.GetShape(1));
157  data_array->SetNumberOfTuples(tensor.GetShape(0));
158  } else {
159  // copy if requested or if data is not contiguous and/or is on different
160  // devices
161  data_array->SetNumberOfComponents(tensor.GetShape(1));
162  data_array->SetNumberOfTuples(tensor.GetShape(0));
163  auto dst_tensor = CreateTensorFromVtkDataArray(data_array, false);
164  dst_tensor.CopyFrom(tensor);
165  }
166 
167  return data_array;
168 } // namespace vtkutils
169 
175 static vtkSmartPointer<vtkPoints> CreateVtkPointsFromTensor(
176  core::Tensor& tensor, bool copy = false) {
177  core::AssertTensorShape(tensor, {core::None, 3});
179 
180  vtkSmartPointer<vtkPoints> pts = vtkSmartPointer<vtkPoints>::New();
182  pts->SetData(data_array);
183  return pts;
184 }
185 
186 CLOUDVIEWER_LOCAL vtkSmartPointer<vtkImageData> CreateVtkImageDataFromTensor(
187  core::Tensor& tensor, bool copy) {
190  if (tensor.NumDims() != 2 && tensor.NumDims() != 3) {
192  "Cannot convert Tensor to vtkImageData. The number of "
193  "dimensions must be 2 or 3 but is {}",
194  tensor.NumDims());
195  }
196 
197  // Create a flat tensor that can be converted to a vtkDataArray
198  auto tensor_flat = tensor.Reshape({tensor.NumElements(), 1});
199  if (tensor.GetDataPtr() != tensor_flat.GetDataPtr()) {
200  copy = true;
201  }
202  auto data_array = CreateVtkDataArrayFromTensor(tensor_flat, copy);
203 
204  vtkSmartPointer<vtkImageData> im = vtkSmartPointer<vtkImageData>::New();
205  im->GetPointData()->SetScalars(data_array);
206  std::array<int, 3> size{1, 1, 1};
207  for (int i = 0; i < tensor.NumDims(); ++i) {
208  size[i] = tensor.GetShape(tensor.NumDims() - i - 1);
209  }
210  im->SetDimensions(size.data());
211  return im;
212 }
213 
214 namespace {
215 // Helper for creating the offset array from Common/DataModel/vtkCellArray.cxx
216 struct GenerateOffsetsImpl {
217  vtkIdType CellSize;
219 
220  template <typename ArrayT>
221  void operator()(ArrayT* offsets) {
222  for (vtkIdType cc = 0, max = (offsets->GetNumberOfTuples() - 1);
223  cc < max; ++cc) {
224  offsets->SetTypedComponent(cc, 0, cc * this->CellSize);
225  }
226  offsets->SetTypedComponent(offsets->GetNumberOfTuples() - 1, 0,
227  this->ConnectivityArraySize);
228  }
229 };
230 } // namespace
231 
237 static vtkSmartPointer<vtkCellArray> CreateVtkCellArrayFromTensor(
238  core::Tensor& tensor, bool copy = false) {
241 
242  const int cell_size = tensor.GetShape()[1];
243 
244  auto tensor_flat = tensor.Reshape({tensor.NumElements(), 1}).Contiguous();
245  if (tensor.GetDataPtr() != tensor_flat.GetDataPtr()) {
246  copy = true;
247  }
248  auto connectivity = CreateVtkDataArrayFromTensor(tensor_flat, copy);
249 
250  // vtk nightly build (9.1.20220520) has a function cells->SetData(cell_size,
251  // connectivity) which allows to remove the code below
252  vtkSmartPointer<vtkDataArray> offsets;
253  {
254  offsets.TakeReference(connectivity->NewInstance());
255  offsets->SetNumberOfTuples(1 + connectivity->GetNumberOfTuples() /
256  cell_size);
257 
258  GenerateOffsetsImpl worker{cell_size,
259  connectivity->GetNumberOfTuples()};
260  using SupportedArrays = vtkCellArray::InputArrayList;
261  using Dispatch = vtkArrayDispatch::DispatchByArray<SupportedArrays>;
262  Dispatch::Execute(offsets, worker);
263  }
264  //--
265 
266  vtkSmartPointer<vtkCellArray> cells = vtkSmartPointer<vtkCellArray>::New();
267  // grr, this always makes a deep copy.
268  // See ShallowCopy() in Common/Core/vtkDataArray.cxx for why.
269  cells->SetData(offsets, connectivity);
270 
271  return cells;
272 }
273 
283 static core::Tensor CreateTensorFromVtkCellArray(vtkCellArray* cells,
284  bool copy = false) {
285  auto num_cells = cells->GetNumberOfCells();
286  int cell_size = 0;
287  if (num_cells) {
288  cell_size = cells->GetCellSize(0);
289  }
290  for (vtkIdType i = 1; i < num_cells; ++i) {
291  if (cells->GetCellSize(i) != cell_size) {
293  "Cannot convert to Tensor. All cells must have the same "
294  "size but first cell has size {} and cell {} has size {}",
295  cell_size, i, cells->GetCellSize(i));
296  }
297  }
299  CreateTensorFromVtkDataArray(cells->GetConnectivityArray(), copy);
300  if (num_cells * cell_size != result.NumElements()) {
301  utility::LogError("Expected {}*{}={} elements but got {}", num_cells,
302  cell_size, num_cells * cell_size,
303  result.NumElements());
304  }
305  return result.Reshape({num_cells, cell_size});
306 }
307 
313  vtkFieldData* field_data,
314  bool copy) {
315  for (int i = 0; i < field_data->GetNumberOfArrays(); ++i) {
316  auto array = field_data->GetArray(i);
317  char* array_name = array->GetName();
318  if (array_name) {
319  tmap[array_name] = CreateTensorFromVtkDataArray(array, copy);
320  }
321  }
322 }
323 
333  vtkFieldData* field_data,
334  TensorMap& tmap,
335  bool copy,
336  std::unordered_set<std::string> include,
337  std::unordered_set<std::string> exclude = {}) {
338  for (auto key_tensor : tmap) {
339  // we only want attributes and ignore the primary key here
340  if (key_tensor.first == tmap.GetPrimaryKey()) {
341  continue;
342  }
343  // we only support 2D tensors
344 
345  if (include.count(key_tensor.first) &&
346  !exclude.count(key_tensor.first)) {
347  if (key_tensor.second.NumDims() != 2) {
349  "Ignoring attribute '{}' for TensorMap with primary "
350  "key "
351  "'{}' because of incompatible ndim={}",
352  key_tensor.first, tmap.GetPrimaryKey(),
353  key_tensor.second.NumDims());
354  continue;
355  }
356 
357  auto array = CreateVtkDataArrayFromTensor(key_tensor.second, copy);
358  array->SetName(key_tensor.first.c_str());
359  field_data->AddArray(array);
360  } else {
362  "Ignoring attribute '{}' for TensorMap with primary key "
363  "'{}'",
364  key_tensor.first, tmap.GetPrimaryKey());
365  }
366  }
367 }
368 
369 vtkSmartPointer<vtkPolyData> CreateVtkPolyDataFromGeometry(
370  const Geometry& geometry,
371  const std::unordered_set<std::string>& point_attr_include,
372  const std::unordered_set<std::string>& face_attr_include,
373  const std::unordered_set<std::string>& point_attr_exclude,
374  const std::unordered_set<std::string>& face_attr_exclude,
375  bool copy) {
376  vtkSmartPointer<vtkPolyData> polydata = vtkSmartPointer<vtkPolyData>::New();
377 
379  auto pcd = static_cast<const PointCloud&>(geometry);
380  polydata->SetPoints(
381  CreateVtkPointsFromTensor(pcd.GetPointPositions(), copy));
382  vtkSmartPointer<vtkCellArray> cells =
383  vtkSmartPointer<vtkCellArray>::New();
384 
385  const size_t num_cells = pcd.GetPointPositions().GetLength();
386  for (size_t i = 0; i < num_cells; ++i) {
387  cells->InsertNextCell(1);
388  cells->InsertCellPoint(i);
389  }
390 
391  polydata->SetVerts(cells);
392  AddTensorMapToVtkFieldData(polydata->GetPointData(), pcd.GetPointAttr(),
393  copy, point_attr_include,
394  point_attr_exclude);
395 
396  } else if (geometry.GetGeometryType() == Geometry::GeometryType::LineSet) {
397  auto lineset = static_cast<const LineSet&>(geometry);
398  polydata->SetPoints(
399  CreateVtkPointsFromTensor(lineset.GetPointPositions(), copy));
400  polydata->SetLines(
401  CreateVtkCellArrayFromTensor(lineset.GetLineIndices(), copy));
402 
403  AddTensorMapToVtkFieldData(polydata->GetPointData(),
404  lineset.GetPointAttr(), copy,
405  point_attr_include, point_attr_exclude);
406  AddTensorMapToVtkFieldData(polydata->GetCellData(),
407  lineset.GetLineAttr(), copy,
408  face_attr_include, face_attr_exclude);
409  } else if (geometry.GetGeometryType() ==
411  auto mesh = static_cast<const TriangleMesh&>(geometry);
412  polydata->SetPoints(
413  CreateVtkPointsFromTensor(mesh.GetVertexPositions(), copy));
414  polydata->SetPolys(
415  CreateVtkCellArrayFromTensor(mesh.GetTriangleIndices(), copy));
416 
417  AddTensorMapToVtkFieldData(polydata->GetPointData(),
418  mesh.GetVertexAttr(), copy,
419  point_attr_include, point_attr_exclude);
420  AddTensorMapToVtkFieldData(polydata->GetCellData(),
421  mesh.GetTriangleAttr(), copy,
422  face_attr_include, face_attr_exclude);
423  } else {
424  utility::LogError("Unsupported geometry type {}",
425  static_cast<int>(geometry.GetGeometryType()));
426  }
427 
428  return polydata;
429 }
430 
432  bool copy) {
433  if (!polydata->GetPoints()) {
434  return TriangleMesh();
435  }
437  polydata->GetPoints()->GetData(), copy);
438 
439  core::Tensor triangles =
440  CreateTensorFromVtkCellArray(polydata->GetPolys(), copy);
441  // Some algorithms return an empty tensor with shape (0,0).
442  // Fix the last dim here.
443  if (triangles.GetShape() == core::SizeVector{0, 0}) {
444  triangles = triangles.Reshape({0, 3});
445  }
446  TriangleMesh mesh(vertices, triangles);
447 
448  AddVtkFieldDataToTensorMap(mesh.GetVertexAttr(), polydata->GetPointData(),
449  copy);
450  AddVtkFieldDataToTensorMap(mesh.GetTriangleAttr(), polydata->GetCellData(),
451  copy);
452 
453  // rename some attributes generated by vtk.
454  // Mapping: vtk name -> o3d name
455  std::map<std::string, std::string> rename_map = {{"Normals", "normals"}};
456  for (auto item : rename_map) {
457  if (mesh.HasVertexAttr(item.first) &&
458  !mesh.HasVertexAttr(item.second)) {
459  auto value = mesh.GetVertexAttr(item.first);
460  mesh.RemoveVertexAttr(item.first);
461  mesh.SetVertexAttr(item.second, value);
462  }
463  if (mesh.HasTriangleAttr(item.first) &&
464  !mesh.HasTriangleAttr(item.second)) {
465  auto value = mesh.GetTriangleAttr(item.first);
466  mesh.RemoveTriangleAttr(item.first);
467  mesh.SetTriangleAttr(item.second, value);
468  }
469  }
470  return mesh;
471 }
472 
474  bool copy) {
475  if (!polydata->GetPoints()) {
476  return LineSet();
477  }
479  polydata->GetPoints()->GetData(), copy);
480 
481  core::Tensor lines =
482  CreateTensorFromVtkCellArray(polydata->GetLines(), copy);
483  // Some algorithms return an empty tensor with shape (0,0).
484  // Fix the last dim here.
485  if (lines.GetShape() == core::SizeVector{0, 0}) {
486  lines = lines.Reshape({0, 2});
487  }
488  LineSet lineset(vertices, lines);
489 
490  AddVtkFieldDataToTensorMap(lineset.GetPointAttr(), polydata->GetPointData(),
491  copy);
492  AddVtkFieldDataToTensorMap(lineset.GetLineAttr(), polydata->GetCellData(),
493  copy);
494  return lineset;
495 }
496 
497 static vtkSmartPointer<vtkPolyData> ExtrudeRotationPolyData(
498  const Geometry& geometry,
499  const double angle,
500  const core::Tensor& axis,
501  int resolution,
502  double translation,
503  bool capping) {
504  core::AssertTensorShape(axis, {3});
505  // allow int types for convenience
508  auto axis_ = axis.To(core::Device(), core::Float64).Contiguous();
509 
510  auto polydata =
511  CreateVtkPolyDataFromGeometry(geometry, {}, {}, {}, {}, false);
512 
513  vtkNew<vtkRotationalExtrusionFilter> extrude;
514  extrude->SetInputData(polydata);
515  extrude->SetAngle(angle);
516  extrude->SetRotationAxis(axis_.GetDataPtr<double>());
517  extrude->SetResolution(resolution);
518  extrude->SetTranslation(translation);
519  extrude->SetCapping(capping);
520 
521  vtkNew<vtkTriangleFilter> triangulate;
522  triangulate->SetInputConnection(extrude->GetOutputPort());
523  triangulate->Update();
524  vtkSmartPointer<vtkPolyData> swept_polydata = triangulate->GetOutput();
525  return swept_polydata;
526 }
527 
530  const double angle,
531  const core::Tensor& axis,
532  int resolution,
533  double translation,
534  bool capping) {
535  auto polydata = ExtrudeRotationPolyData(geometry, angle, axis, resolution,
536  translation, capping);
537  return CreateTriangleMeshFromVtkPolyData(polydata);
538 }
539 
541  const double angle,
542  const core::Tensor& axis,
543  int resolution,
544  double translation,
545  bool capping) {
546  auto polydata = ExtrudeRotationPolyData(pointcloud, angle, axis, resolution,
547  translation, capping);
548  return CreateLineSetFromVtkPolyData(polydata);
549 }
550 
551 static vtkSmartPointer<vtkPolyData> ExtrudeLinearPolyData(
552  const Geometry& geometry,
553  const core::Tensor& vector,
554  double scale,
555  bool capping) {
556  core::AssertTensorShape(vector, {3});
557  // allow int types for convenience
560  auto vector_ = vector.To(core::Device(), core::Float64).Contiguous();
561 
562  auto polydata =
563  CreateVtkPolyDataFromGeometry(geometry, {}, {}, {}, {}, false);
564 
565  vtkNew<vtkLinearExtrusionFilter> extrude;
566  extrude->SetInputData(polydata);
567  extrude->SetExtrusionTypeToVectorExtrusion();
568  extrude->SetVector(vector_.GetDataPtr<double>());
569  extrude->SetScaleFactor(scale);
570  extrude->SetCapping(capping);
571 
572  vtkNew<vtkTriangleFilter> triangulate;
573  triangulate->SetInputConnection(extrude->GetOutputPort());
574  triangulate->Update();
575  vtkSmartPointer<vtkPolyData> swept_polydata = triangulate->GetOutput();
576  return swept_polydata;
577 }
578 
581  const core::Tensor& vector,
582  double scale,
583  bool capping) {
584  auto polydata = ExtrudeLinearPolyData(geometry, vector, scale, capping);
585  return CreateTriangleMeshFromVtkPolyData(polydata);
586 }
587 
589  const core::Tensor& vector,
590  double scale,
591  bool capping) {
592  auto polydata = ExtrudeLinearPolyData(pointcloud, vector, scale, capping);
593  return CreateLineSetFromVtkPolyData(polydata);
594 }
595 
597  bool vertex_normals,
598  bool face_normals,
599  bool consistency,
600  bool auto_orient_normals,
601  bool splitting,
602  double feature_angle_deg) {
603  auto polydata = CreateVtkPolyDataFromGeometry(
604  mesh, mesh.GetVertexAttr().GetKeySet(), {}, {}, {}, false);
605 
606  vtkNew<vtkPolyDataNormals> normals;
607  normals->SetInputData(polydata);
608  normals->SetComputePointNormals(vertex_normals);
609  normals->SetComputeCellNormals(face_normals);
610  normals->SetConsistency(consistency);
611  normals->SetAutoOrientNormals(auto_orient_normals);
612  normals->SetSplitting(splitting);
613  normals->SetFeatureAngle(feature_angle_deg);
614  normals->Update();
615  vtkSmartPointer<vtkPolyData> normals_polydata = normals->GetOutput();
616 
617  return CreateTriangleMeshFromVtkPolyData(normals_polydata);
618 }
619 
620 } // namespace vtkutils
621 } // namespace geometry
622 } // namespace t
623 } // namespace cloudViewer
int size
#define CLOUDVIEWER_LOCAL
Definition: Macro.h:30
int Execute(void)
#define AssertTensorDtypes(tensor,...)
Definition: TensorCheck.h:33
#define AssertTensorShape(tensor,...)
Definition: TensorCheck.h:61
core::Tensor result
Definition: VtkUtils.cpp:76
vtkIdType CellSize
Definition: VtkUtils.cpp:217
vtkDataArray * data_array
Definition: VtkUtils.cpp:75
bool copy
Definition: VtkUtils.cpp:74
vtkIdType ConnectivityArraySize
Definition: VtkUtils.cpp:218
std::string ToString() const
Definition: Dtype.h:65
Tensor Contiguous() const
Definition: Tensor.cpp:772
int64_t NumDims() const
Definition: Tensor.h:1172
bool IsContiguous() const
Definition: Tensor.h:1036
Dtype GetDtype() const
Definition: Tensor.h:1164
int64_t NumElements() const
Definition: Tensor.h:1170
Device GetDevice() const override
Definition: Tensor.cpp:1435
Tensor Reshape(const SizeVector &dst_shape) const
Definition: Tensor.cpp:671
SizeVector GetShape() const
Definition: Tensor.h:1127
Tensor To(Dtype dtype, bool copy=false) const
Definition: Tensor.cpp:739
The base geometry class.
Definition: Geometry.h:23
GeometryType GetGeometryType() const
Returns one of registered geometry types.
Definition: Geometry.h:79
A LineSet contains points and lines joining them and optionally attributes on the points and lines.
Definition: LineSet.h:85
const TensorMap & GetLineAttr() const
Getter for line_attr_ TensorMap. Used in Pybind.
Definition: LineSet.h:142
const TensorMap & GetPointAttr() const
Getter for point_attr_ TensorMap. Used in Pybind.
Definition: LineSet.h:124
A point cloud contains a list of 3D points.
Definition: PointCloud.h:82
void SetPoints(const core::Tensor &value)
Definition: PointCloud.h:156
std::unordered_set< std::string > GetKeySet() const
Returns a set with all keys.
Definition: TensorMap.h:162
A triangle mesh contains vertices and triangles.
Definition: TriangleMesh.h:98
const TensorMap & GetVertexAttr() const
Getter for vertex_attr_ TensorMap. Used in Pybind.
Definition: TriangleMesh.h:133
void RemoveTriangleAttr(const std::string &key)
Definition: TriangleMesh.h:227
bool HasVertexAttr(const std::string &key) const
Definition: TriangleMesh.h:314
void RemoveVertexAttr(const std::string &key)
Definition: TriangleMesh.h:195
bool HasTriangleAttr(const std::string &key) const
Definition: TriangleMesh.h:343
void SetVertexAttr(const std::string &key, const core::Tensor &value)
Definition: TriangleMesh.h:254
void SetTriangleAttr(const std::string &key, const core::Tensor &value)
Definition: TriangleMesh.h:285
const TensorMap & GetTriangleAttr() const
Getter for triangle_attr_ TensorMap. Used in Pybind.
Definition: TriangleMesh.h:159
double normals[3]
#define LogWarning(...)
Definition: Logging.h:72
#define LogError(...)
Definition: Logging.h:60
__host__ __device__ float length(float2 v)
Definition: cutil_math.h:1162
int max(int a, int b)
Definition: cutil_math.h:48
SizeVector DefaultStrides(const SizeVector &shape)
Compute default strides for a shape when a tensor is contiguous.
Definition: ShapeUtil.cpp:214
const Dtype Int8
Definition: Dtype.cpp:44
const Dtype Bool
Definition: Dtype.cpp:52
const Dtype Int64
Definition: Dtype.cpp:47
const Dtype UInt64
Definition: Dtype.cpp:51
const Dtype UInt32
Definition: Dtype.cpp:50
const Dtype UInt8
Definition: Dtype.cpp:48
const Dtype Int16
Definition: Dtype.cpp:45
const Dtype Float64
Definition: Dtype.cpp:43
const Dtype UInt16
Definition: Dtype.cpp:49
constexpr utility::nullopt_t None
Definition: TensorKey.h:20
const Dtype Int32
Definition: Dtype.cpp:46
const Dtype Float32
Definition: Dtype.cpp:42
vtkSmartPointer< vtkPolyData > CreateVtkPolyDataFromGeometry(const Geometry &geometry, const std::unordered_set< std::string > &point_attr_include, const std::unordered_set< std::string > &face_attr_include, const std::unordered_set< std::string > &point_attr_exclude, const std::unordered_set< std::string > &face_attr_exclude, bool copy)
Definition: VtkUtils.cpp:369
CLOUDVIEWER_LOCAL TriangleMesh ComputeNormals(const TriangleMesh &mesh, bool vertex_normals, bool face_normals, bool consistency, bool auto_orient_normals, bool splitting, double feature_angle_deg)
Definition: VtkUtils.cpp:596
static vtkSmartPointer< vtkPolyData > ExtrudeRotationPolyData(const Geometry &geometry, const double angle, const core::Tensor &axis, int resolution, double translation, bool capping)
Definition: VtkUtils.cpp:497
TriangleMesh CreateTriangleMeshFromVtkPolyData(vtkPolyData *polydata, bool copy)
Definition: VtkUtils.cpp:431
static vtkSmartPointer< vtkDataArray > CreateVtkDataArrayFromTensor(core::Tensor &tensor, bool copy)
Definition: VtkUtils.cpp:138
static vtkSmartPointer< vtkCellArray > CreateVtkCellArrayFromTensor(core::Tensor &tensor, bool copy=false)
Definition: VtkUtils.cpp:237
CLOUDVIEWER_LOCAL vtkSmartPointer< vtkImageData > CreateVtkImageDataFromTensor(core::Tensor &tensor, bool copy)
Definition: VtkUtils.cpp:186
static void AddTensorMapToVtkFieldData(vtkFieldData *field_data, TensorMap &tmap, bool copy, std::unordered_set< std::string > include, std::unordered_set< std::string > exclude={})
Definition: VtkUtils.cpp:332
int DtypeToVtkType(const core::Dtype &dtype)
Definition: VtkUtils.cpp:30
CLOUDVIEWER_LOCAL TriangleMesh ExtrudeLinearTriangleMesh(const Geometry &geometry, const core::Tensor &vector, double scale, bool capping)
Definition: VtkUtils.cpp:580
static vtkSmartPointer< vtkPolyData > ExtrudeLinearPolyData(const Geometry &geometry, const core::Tensor &vector, double scale, bool capping)
Definition: VtkUtils.cpp:551
static core::Tensor CreateTensorFromVtkCellArray(vtkCellArray *cells, bool copy=false)
Definition: VtkUtils.cpp:283
static void AddVtkFieldDataToTensorMap(TensorMap &tmap, vtkFieldData *field_data, bool copy)
Definition: VtkUtils.cpp:312
CLOUDVIEWER_LOCAL LineSet ExtrudeLinearLineSet(const PointCloud &pointcloud, const core::Tensor &vector, double scale, bool capping)
Definition: VtkUtils.cpp:588
CLOUDVIEWER_LOCAL TriangleMesh ExtrudeRotationTriangleMesh(const Geometry &geometry, const double angle, const core::Tensor &axis, int resolution, double translation, bool capping)
Definition: VtkUtils.cpp:529
CLOUDVIEWER_LOCAL LineSet CreateLineSetFromVtkPolyData(vtkPolyData *polydata, bool copy)
Definition: VtkUtils.cpp:473
static vtkSmartPointer< vtkPoints > CreateVtkPointsFromTensor(core::Tensor &tensor, bool copy=false)
Definition: VtkUtils.cpp:175
CLOUDVIEWER_LOCAL LineSet ExtrudeRotationLineSet(const PointCloud &pointcloud, const double angle, const core::Tensor &axis, int resolution, double translation, bool capping)
Definition: VtkUtils.cpp:540
static core::Tensor CreateTensorFromVtkDataArray(vtkDataArray *array, bool copy=false)
Definition: VtkUtils.cpp:122
Generic file read and write utility for python interface.