ACloudViewer  3.9.4
A Modern Library for 3D Data Processing
TriangleMeshFactory.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 
8 #include <vtkFlyingEdges3D.h>
9 #include <vtkLinearExtrusionFilter.h>
10 #include <vtkNew.h>
11 #include <vtkTextSource.h>
12 #include <vtkTriangleFilter.h>
13 
17 
18 namespace cloudViewer {
19 namespace t {
20 namespace geometry {
21 
23  double height,
24  double depth,
25  core::Dtype float_dtype,
26  core::Dtype int_dtype,
27  const core::Device &device) {
28  // Check width, height, depth.
29  if (width <= 0) {
30  utility::LogError("width must be > 0, but got {}", width);
31  }
32  if (height <= 0) {
33  utility::LogError("height must be > 0, but got {}", height);
34  }
35  if (depth <= 0) {
36  utility::LogError("depth must be > 0, but got {}", depth);
37  }
38 
39  // Vertices.
40  core::Tensor vertex_positions =
41  core::Tensor::Init<double>({{0.0, 0.0, 0.0},
42  {width, 0.0, 0.0},
43  {0.0, 0.0, depth},
44  {width, 0.0, depth},
45  {0.0, height, 0.0},
46  {width, height, 0.0},
47  {0.0, height, depth},
48  {width, height, depth}},
49  device);
50 
51  if (float_dtype == core::Float32) {
52  vertex_positions = vertex_positions.To(core::Float32);
53  } else if (float_dtype != core::Float64) {
54  utility::LogError("float_dtype must be Float32 or Float64, but got {}.",
55  float_dtype.ToString());
56  }
57 
58  // Triangles.
59  core::Tensor triangle_indices = core::Tensor::Init<int64_t>({{4, 7, 5},
60  {4, 6, 7},
61  {0, 2, 4},
62  {2, 6, 4},
63  {0, 1, 2},
64  {1, 3, 2},
65  {1, 5, 7},
66  {1, 7, 3},
67  {2, 3, 7},
68  {2, 7, 6},
69  {0, 4, 1},
70  {1, 4, 5}},
71  device);
72 
73  if (int_dtype == core::Int32) {
74  triangle_indices = triangle_indices.To(core::Int32);
75  } else if (int_dtype != core::Int64) {
76  utility::LogError("int_dtype must be Int32 or Int64, but got {}.",
77  int_dtype.ToString());
78  }
79 
80  // Mesh.
81  TriangleMesh mesh(vertex_positions, triangle_indices);
82 
83  return mesh;
84 }
85 
87  int resolution,
88  core::Dtype float_dtype,
89  core::Dtype int_dtype,
90  const core::Device &device) {
91  std::shared_ptr<ccMesh> legacy_mesh =
92  ccMesh::CreateSphere(radius, resolution);
93 
94  TriangleMesh mesh = TriangleMesh::FromLegacy(*legacy_mesh, float_dtype,
95  int_dtype, device);
96  return mesh;
97 }
98 
100  core::Dtype float_dtype,
101  core::Dtype int_dtype,
102  const core::Device &device) {
103  std::shared_ptr<ccMesh> legacy_mesh = ccMesh::CreateTetrahedron(radius);
104 
105  TriangleMesh mesh = TriangleMesh::FromLegacy(*legacy_mesh, float_dtype,
106  int_dtype, device);
107 
108  return mesh;
109 }
110 
112  core::Dtype float_dtype,
113  core::Dtype int_dtype,
114  const core::Device &device) {
115  std::shared_ptr<ccMesh> legacy_mesh = ccMesh::CreateOctahedron(radius);
116 
117  TriangleMesh mesh = TriangleMesh::FromLegacy(*legacy_mesh, float_dtype,
118  int_dtype, device);
119 
120  return mesh;
121 }
122 
124  core::Dtype float_dtype,
125  core::Dtype int_dtype,
126  const core::Device &device) {
127  std::shared_ptr<ccMesh> legacy_mesh = ccMesh::CreateIcosahedron(radius);
128 
129  TriangleMesh mesh = TriangleMesh::FromLegacy(*legacy_mesh, float_dtype,
130  int_dtype, device);
131 
132  return mesh;
133 }
134 
136  double height,
137  int resolution,
138  int split,
139  core::Dtype float_dtype,
140  core::Dtype int_dtype,
141  const core::Device &device) {
142  std::shared_ptr<ccMesh> legacy_mesh =
143  ccMesh::CreateCylinder(radius, height, resolution, split);
144 
145  TriangleMesh mesh = TriangleMesh::FromLegacy(*legacy_mesh, float_dtype,
146  int_dtype, device);
147 
148  return mesh;
149 }
150 
152  double height,
153  int resolution,
154  int split,
155  core::Dtype float_dtype,
156  core::Dtype int_dtype,
157  const core::Device &device) {
158  std::shared_ptr<ccMesh> legacy_mesh =
159  ccMesh::CreateCone(radius, height, resolution, split);
160 
161  TriangleMesh mesh = TriangleMesh::FromLegacy(*legacy_mesh, float_dtype,
162  int_dtype, device);
163 
164  return mesh;
165 }
166 
168  double tube_radius,
169  int radial_resolution,
170  int tubular_resolution,
171  core::Dtype float_dtype,
172  core::Dtype int_dtype,
173  const core::Device &device) {
174  std::shared_ptr<ccMesh> legacy_mesh = ccMesh::CreateTorus(
175  torus_radius, tube_radius, radial_resolution, tubular_resolution);
176 
177  TriangleMesh mesh = TriangleMesh::FromLegacy(*legacy_mesh, float_dtype,
178  int_dtype, device);
179 
180  return mesh;
181 }
182 
184  double cone_radius,
185  double cylinder_height,
186  double cone_height,
187  int resolution,
188  int cylinder_split,
189  int cone_split,
190  core::Dtype float_dtype,
191  core::Dtype int_dtype,
192  const core::Device &device) {
193  std::shared_ptr<ccMesh> legacy_mesh = ccMesh::CreateArrow(
194  cylinder_radius, cone_radius, cylinder_height, cone_height,
195  resolution, cylinder_split, cone_split);
196 
197  TriangleMesh mesh = TriangleMesh::FromLegacy(*legacy_mesh, float_dtype,
198  int_dtype, device);
199 
200  return mesh;
201 }
202 
204  const Eigen::Vector3d &origin,
205  core::Dtype float_dtype,
206  core::Dtype int_dtype,
207  const core::Device &device) {
208  std::shared_ptr<ccMesh> legacy_mesh =
210 
211  TriangleMesh mesh = TriangleMesh::FromLegacy(*legacy_mesh, float_dtype,
212  int_dtype, device);
213 
214  return mesh;
215 }
216 
218  int width_split,
219  int twists,
220  double radius,
221  double flatness,
222  double width,
223  double scale,
224  core::Dtype float_dtype,
225  core::Dtype int_dtype,
226  const core::Device &device) {
227  std::shared_ptr<ccMesh> legacy_mesh = ccMesh::CreateMobius(
228  length_split, width_split, twists, radius, flatness, width, scale);
229 
230  TriangleMesh mesh = TriangleMesh::FromLegacy(*legacy_mesh, float_dtype,
231  int_dtype, device);
232 
233  return mesh;
234 }
235 
236 TriangleMesh TriangleMesh::CreateText(const std::string &text,
237  double depth,
238  core::Dtype float_dtype,
239  core::Dtype int_dtype,
240  const core::Device &device) {
241  using namespace vtkutils;
242 
243  if (float_dtype != core::Float32 && float_dtype != core::Float64) {
244  utility::LogError("float_dtype must be Float32 or Float64, but got {}.",
245  float_dtype.ToString());
246  }
247  if (int_dtype != core::Int32 && int_dtype != core::Int64) {
248  utility::LogError("int_dtype must be Int32 or Int64, but got {}.",
249  int_dtype.ToString());
250  }
251 
252  vtkNew<vtkTextSource> vector_text;
253  vector_text->SetText(text.c_str());
254  vector_text->BackingOff();
255 
256  vtkNew<vtkLinearExtrusionFilter> extrude;
257  vtkNew<vtkTriangleFilter> triangle_filter;
258  if (depth > 0) {
259  extrude->SetInputConnection(vector_text->GetOutputPort());
260  extrude->SetExtrusionTypeToNormalExtrusion();
261  extrude->SetVector(0, 0, 1);
262  extrude->SetScaleFactor(depth);
263 
264  triangle_filter->SetInputConnection(extrude->GetOutputPort());
265  } else {
266  triangle_filter->SetInputConnection(vector_text->GetOutputPort());
267  }
268 
269  triangle_filter->Update();
270  auto polydata = triangle_filter->GetOutput();
271  auto tmesh = CreateTriangleMeshFromVtkPolyData(polydata);
272  tmesh.GetVertexPositions() =
273  tmesh.GetVertexPositions().To(device, float_dtype);
274  tmesh.GetTriangleIndices() =
275  tmesh.GetTriangleIndices().To(device, int_dtype);
276  return tmesh;
277 }
278 
280  const core::Tensor &volume,
281  const std::vector<double> contour_values,
282  const core::Device &device) {
283  using namespace vtkutils;
286 
287  auto image_data = vtkutils::CreateVtkImageDataFromTensor(
288  const_cast<core::Tensor &>(volume));
289  vtkNew<vtkFlyingEdges3D> method;
290  method->SetNumberOfContours(contour_values.size());
291  for (int i = 0; i < int(contour_values.size()); ++i) {
292  method->SetValue(i, contour_values[i]);
293  }
294  method->SetInputData(image_data);
295  method->Update();
296  auto polydata = method->GetOutput();
297  auto tmesh = CreateTriangleMeshFromVtkPolyData(polydata);
298  return tmesh.To(device);
299 }
300 
301 } // namespace geometry
302 } // namespace t
303 } // namespace cloudViewer
int width
int size
int height
#define AssertTensorDtypes(tensor,...)
Definition: TensorCheck.h:33
#define AssertTensorShape(tensor,...)
Definition: TensorCheck.h:61
static std::shared_ptr< ccMesh > CreateCylinder(double radius=1.0, double height=2.0, int resolution=20, int split=4, bool create_uv_map=false)
static std::shared_ptr< ccMesh > CreateArrow(double cylinder_radius=1.0, double cone_radius=1.5, double cylinder_height=5.0, double cone_height=4.0, int resolution=20, int cylinder_split=4, int cone_split=1)
static std::shared_ptr< ccMesh > CreateCoordinateFrame(double size=1.0, const Eigen::Vector3d &origin=Eigen::Vector3d(0.0, 0.0, 0.0))
static std::shared_ptr< ccMesh > CreateMobius(int length_split=70, int width_split=15, int twists=1, double radius=1, double flatness=1, double width=1, double scale=1)
static std::shared_ptr< ccMesh > CreateIcosahedron(double radius=1.0, bool create_uv_map=false)
static std::shared_ptr< ccMesh > CreateTetrahedron(double radius=1.0, bool create_uv_map=false)
static std::shared_ptr< ccMesh > CreateCone(double radius=1.0, double height=2.0, int resolution=20, int split=1, bool create_uv_map=false)
static std::shared_ptr< ccMesh > CreateSphere(double radius=1.0, int resolution=20, bool create_uv_map=false)
static std::shared_ptr< ccMesh > CreateTorus(double torus_radius=1.0, double tube_radius=0.5, int radial_resolution=30, int tubular_resolution=20)
static std::shared_ptr< ccMesh > CreateOctahedron(double radius=1.0, bool create_uv_map=false)
std::string ToString() const
Definition: Dtype.h:65
Tensor To(Dtype dtype, bool copy=false) const
Definition: Tensor.cpp:739
A triangle mesh contains vertices and triangles.
Definition: TriangleMesh.h:98
static TriangleMesh CreateBox(double width=1.0, double height=1.0, double depth=1.0, core::Dtype float_dtype=core::Float32, core::Dtype int_dtype=core::Int64, const core::Device &device=core::Device("CPU:0"))
static TriangleMesh CreateIsosurfaces(const core::Tensor &volume, const std::vector< double > contour_values={0.0}, const core::Device &device=core::Device("CPU:0"))
static TriangleMesh CreateCylinder(double radius=1.0, double height=2.0, int resolution=20, int split=4, core::Dtype float_dtype=core::Float32, core::Dtype int_dtype=core::Int64, const core::Device &device=core::Device("CPU:0"))
static TriangleMesh CreateTetrahedron(double radius=1.0, core::Dtype float_dtype=core::Float32, core::Dtype int_dtype=core::Int64, const core::Device &device=core::Device("CPU:0"))
static geometry::TriangleMesh FromLegacy(const ccMesh &mesh_legacy, core::Dtype float_dtype=core::Float32, core::Dtype int_dtype=core::Int64, const core::Device &device=core::Device("CPU:0"))
static TriangleMesh CreateIcosahedron(double radius=1.0, core::Dtype float_dtype=core::Float32, core::Dtype int_dtype=core::Int64, const core::Device &device=core::Device("CPU:0"))
static TriangleMesh CreateText(const std::string &text, double depth=0.0, core::Dtype float_dtype=core::Float32, core::Dtype int_dtype=core::Int64, const core::Device &device=core::Device("CPU:0"))
static TriangleMesh CreateArrow(double cylinder_radius=1.0, double cone_radius=1.5, double cylinder_height=5.0, double cone_height=4.0, int resolution=20, int cylinder_split=4, int cone_split=1, core::Dtype float_dtype=core::Float32, core::Dtype int_dtype=core::Int64, const core::Device &device=core::Device("CPU:0"))
static TriangleMesh CreateMobius(int length_split=70, int width_split=15, int twists=1, double radius=1, double flatness=1, double width=1, double scale=1, core::Dtype float_dtype=core::Float32, core::Dtype int_dtype=core::Int64, const core::Device &device=core::Device("CPU:0"))
static TriangleMesh CreateCoordinateFrame(double size=1.0, const Eigen::Vector3d &origin=Eigen::Vector3d(0.0, 0.0, 0.0), core::Dtype float_dtype=core::Float32, core::Dtype int_dtype=core::Int64, const core::Device &device=core::Device("CPU:0"))
static TriangleMesh CreateCone(double radius=1.0, double height=2.0, int resolution=20, int split=1, core::Dtype float_dtype=core::Float32, core::Dtype int_dtype=core::Int64, const core::Device &device=core::Device("CPU:0"))
static TriangleMesh CreateTorus(double torus_radius=1.0, double tube_radius=0.5, int radial_resolution=30, int tubular_resolution=20, core::Dtype float_dtype=core::Float32, core::Dtype int_dtype=core::Int64, const core::Device &device=core::Device("CPU:0"))
static TriangleMesh CreateOctahedron(double radius=1.0, core::Dtype float_dtype=core::Float32, core::Dtype int_dtype=core::Int64, const core::Device &device=core::Device("CPU:0"))
static TriangleMesh CreateSphere(double radius=1.0, int resolution=20, core::Dtype float_dtype=core::Float32, core::Dtype int_dtype=core::Int64, const core::Device &device=core::Device("CPU:0"))
#define LogError(...)
Definition: Logging.h:60
const Dtype Int64
Definition: Dtype.cpp:47
const Dtype Float64
Definition: Dtype.cpp:43
constexpr utility::nullopt_t None
Definition: TensorKey.h:20
const Dtype Int32
Definition: Dtype.cpp:46
const Dtype Float32
Definition: Dtype.cpp:42
TriangleMesh CreateTriangleMeshFromVtkPolyData(vtkPolyData *polydata, bool copy)
Definition: VtkUtils.cpp:431
CLOUDVIEWER_LOCAL vtkSmartPointer< vtkImageData > CreateVtkImageDataFromTensor(core::Tensor &tensor, bool copy)
Definition: VtkUtils.cpp:186
Generic file read and write utility for python interface.