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>
38 return VTK_TYPE_INT16;
40 return VTK_TYPE_INT32;
42 return VTK_TYPE_INT64;
44 return VTK_TYPE_UINT8;
46 return VTK_TYPE_UINT16;
48 return VTK_TYPE_UINT32;
50 return VTK_TYPE_UINT64;
73 struct CreateTensorFromVtkDataArrayWorker {
78 template <
class TArray>
79 void operator()(TArray* array) {
80 typedef typename TArray::ValueType T;
82 auto dtype = core::Dtype::FromType<TTensor>();
83 int64_t
length = array->GetNumberOfTuples();
84 int64_t num_components = array->GetNumberOfComponents();
87 if (
copy || !array->HasStandardMemoryLayout()) {
89 if (array->HasStandardMemoryLayout()) {
90 memcpy(array->GetVoidPointer(0),
result.GetDataPtr(),
91 dtype.ByteSize() *
result.NumElements());
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);
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};
108 result = core::Tensor(shape, strides, blob->GetDataPtr(), dtype,
124 CreateTensorFromVtkDataArrayWorker worker;
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;
143 "Tensor conversion with type Bool is not implemented!");
149 data_array.TakeReference(vtkDataArray::CreateDataArray(vtk_data_type));
164 dst_tensor.CopyFrom(tensor);
180 vtkSmartPointer<vtkPoints> pts = vtkSmartPointer<vtkPoints>::New();
192 "Cannot convert Tensor to vtkImageData. The number of "
193 "dimensions must be 2 or 3 but is {}",
199 if (tensor.
GetDataPtr() != tensor_flat.GetDataPtr()) {
204 vtkSmartPointer<vtkImageData> im = vtkSmartPointer<vtkImageData>::New();
206 std::array<int, 3>
size{1, 1, 1};
207 for (
int i = 0; i < tensor.
NumDims(); ++i) {
210 im->SetDimensions(
size.data());
216 struct GenerateOffsetsImpl {
220 template <
typename ArrayT>
221 void operator()(ArrayT* offsets) {
222 for (vtkIdType cc = 0,
max = (offsets->GetNumberOfTuples() - 1);
224 offsets->SetTypedComponent(cc, 0, cc * this->CellSize);
226 offsets->SetTypedComponent(offsets->GetNumberOfTuples() - 1, 0,
227 this->ConnectivityArraySize);
242 const int cell_size = tensor.
GetShape()[1];
245 if (tensor.
GetDataPtr() != tensor_flat.GetDataPtr()) {
252 vtkSmartPointer<vtkDataArray> offsets;
254 offsets.TakeReference(connectivity->NewInstance());
255 offsets->SetNumberOfTuples(1 + connectivity->GetNumberOfTuples() /
258 GenerateOffsetsImpl worker{cell_size,
259 connectivity->GetNumberOfTuples()};
260 using SupportedArrays = vtkCellArray::InputArrayList;
261 using Dispatch = vtkArrayDispatch::DispatchByArray<SupportedArrays>;
266 vtkSmartPointer<vtkCellArray> cells = vtkSmartPointer<vtkCellArray>::New();
269 cells->SetData(offsets, connectivity);
285 auto num_cells = cells->GetNumberOfCells();
288 cell_size = cells->GetCellSize(0);
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));
300 if (num_cells * cell_size !=
result.NumElements()) {
302 cell_size, num_cells * cell_size,
305 return result.Reshape({num_cells, cell_size});
313 vtkFieldData* field_data,
315 for (
int i = 0; i < field_data->GetNumberOfArrays(); ++i) {
316 auto array = field_data->GetArray(i);
317 char* array_name = array->GetName();
333 vtkFieldData* field_data,
336 std::unordered_set<std::string> include,
337 std::unordered_set<std::string> exclude = {}) {
338 for (
auto key_tensor : tmap) {
340 if (key_tensor.first == tmap.GetPrimaryKey()) {
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 "
351 "'{}' because of incompatible ndim={}",
352 key_tensor.first, tmap.GetPrimaryKey(),
353 key_tensor.second.NumDims());
358 array->SetName(key_tensor.first.c_str());
359 field_data->AddArray(array);
362 "Ignoring attribute '{}' for TensorMap with primary key "
364 key_tensor.first, tmap.GetPrimaryKey());
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,
376 vtkSmartPointer<vtkPolyData> polydata = vtkSmartPointer<vtkPolyData>::New();
379 auto pcd =
static_cast<const PointCloud&
>(geometry);
382 vtkSmartPointer<vtkCellArray> cells =
383 vtkSmartPointer<vtkCellArray>::New();
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);
391 polydata->SetVerts(cells);
393 copy, point_attr_include,
397 auto lineset =
static_cast<const LineSet&
>(geometry);
404 lineset.GetPointAttr(),
copy,
405 point_attr_include, point_attr_exclude);
407 lineset.GetLineAttr(),
copy,
408 face_attr_include, face_attr_exclude);
418 mesh.GetVertexAttr(),
copy,
419 point_attr_include, point_attr_exclude);
421 mesh.GetTriangleAttr(),
copy,
422 face_attr_include, face_attr_exclude);
433 if (!polydata->GetPoints()) {
437 polydata->GetPoints()->GetData(),
copy);
444 triangles = triangles.
Reshape({0, 3});
455 std::map<std::string, std::string> rename_map = {{
"Normals",
"normals"}};
456 for (
auto item : rename_map) {
475 if (!polydata->GetPoints()) {
479 polydata->GetPoints()->GetData(),
copy);
488 LineSet lineset(vertices, lines);
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);
521 vtkNew<vtkTriangleFilter> triangulate;
522 triangulate->SetInputConnection(extrude->GetOutputPort());
523 triangulate->Update();
524 vtkSmartPointer<vtkPolyData> swept_polydata = triangulate->GetOutput();
525 return swept_polydata;
536 translation, capping);
547 translation, capping);
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);
572 vtkNew<vtkTriangleFilter> triangulate;
573 triangulate->SetInputConnection(extrude->GetOutputPort());
574 triangulate->Update();
575 vtkSmartPointer<vtkPolyData> swept_polydata = triangulate->GetOutput();
576 return swept_polydata;
600 bool auto_orient_normals,
602 double feature_angle_deg) {
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);
615 vtkSmartPointer<vtkPolyData> normals_polydata =
normals->GetOutput();
#define CLOUDVIEWER_LOCAL
#define AssertTensorDtypes(tensor,...)
#define AssertTensorShape(tensor,...)
vtkDataArray * data_array
vtkIdType ConnectivityArraySize
std::string ToString() const
Tensor Contiguous() const
bool IsContiguous() const
int64_t NumElements() const
Device GetDevice() const override
Tensor Reshape(const SizeVector &dst_shape) const
SizeVector GetShape() const
Tensor To(Dtype dtype, bool copy=false) const
@ TriangleMesh
TriangleMesh.
GeometryType GetGeometryType() const
Returns one of registered geometry types.
A LineSet contains points and lines joining them and optionally attributes on the points and lines.
const TensorMap & GetLineAttr() const
Getter for line_attr_ TensorMap. Used in Pybind.
const TensorMap & GetPointAttr() const
Getter for point_attr_ TensorMap. Used in Pybind.
A point cloud contains a list of 3D points.
void SetPoints(const core::Tensor &value)
std::unordered_set< std::string > GetKeySet() const
Returns a set with all keys.
A triangle mesh contains vertices and triangles.
const TensorMap & GetVertexAttr() const
Getter for vertex_attr_ TensorMap. Used in Pybind.
void RemoveTriangleAttr(const std::string &key)
bool HasVertexAttr(const std::string &key) const
void RemoveVertexAttr(const std::string &key)
bool HasTriangleAttr(const std::string &key) const
void SetVertexAttr(const std::string &key, const core::Tensor &value)
void SetTriangleAttr(const std::string &key, const core::Tensor &value)
const TensorMap & GetTriangleAttr() const
Getter for triangle_attr_ TensorMap. Used in Pybind.
__host__ __device__ float length(float2 v)
SizeVector DefaultStrides(const SizeVector &shape)
Compute default strides for a shape when a tensor is contiguous.
constexpr utility::nullopt_t None
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)
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)
static vtkSmartPointer< vtkPolyData > ExtrudeRotationPolyData(const Geometry &geometry, const double angle, const core::Tensor &axis, int resolution, double translation, bool capping)
TriangleMesh CreateTriangleMeshFromVtkPolyData(vtkPolyData *polydata, bool copy)
static vtkSmartPointer< vtkDataArray > CreateVtkDataArrayFromTensor(core::Tensor &tensor, bool copy)
static vtkSmartPointer< vtkCellArray > CreateVtkCellArrayFromTensor(core::Tensor &tensor, bool copy=false)
CLOUDVIEWER_LOCAL vtkSmartPointer< vtkImageData > CreateVtkImageDataFromTensor(core::Tensor &tensor, bool copy)
static void AddTensorMapToVtkFieldData(vtkFieldData *field_data, TensorMap &tmap, bool copy, std::unordered_set< std::string > include, std::unordered_set< std::string > exclude={})
int DtypeToVtkType(const core::Dtype &dtype)
CLOUDVIEWER_LOCAL TriangleMesh ExtrudeLinearTriangleMesh(const Geometry &geometry, const core::Tensor &vector, double scale, bool capping)
static vtkSmartPointer< vtkPolyData > ExtrudeLinearPolyData(const Geometry &geometry, const core::Tensor &vector, double scale, bool capping)
static core::Tensor CreateTensorFromVtkCellArray(vtkCellArray *cells, bool copy=false)
static void AddVtkFieldDataToTensorMap(TensorMap &tmap, vtkFieldData *field_data, bool copy)
CLOUDVIEWER_LOCAL LineSet ExtrudeLinearLineSet(const PointCloud &pointcloud, const core::Tensor &vector, double scale, bool capping)
CLOUDVIEWER_LOCAL TriangleMesh ExtrudeRotationTriangleMesh(const Geometry &geometry, const double angle, const core::Tensor &axis, int resolution, double translation, bool capping)
CLOUDVIEWER_LOCAL LineSet CreateLineSetFromVtkPolyData(vtkPolyData *polydata, bool copy)
static vtkSmartPointer< vtkPoints > CreateVtkPointsFromTensor(core::Tensor &tensor, bool copy=false)
CLOUDVIEWER_LOCAL LineSet ExtrudeRotationLineSet(const PointCloud &pointcloud, const double angle, const core::Tensor &axis, int resolution, double translation, bool capping)
static core::Tensor CreateTensorFromVtkDataArray(vtkDataArray *array, bool copy=false)
Generic file read and write utility for python interface.