image_framework_ymj/include/open3d/t/geometry/TriangleMesh.h
2024-12-06 16:25:16 +08:00

957 lines
43 KiB
C++
Executable File

// ----------------------------------------------------------------------------
// - Open3D: www.open3d.org -
// ----------------------------------------------------------------------------
// Copyright (c) 2018-2023 www.open3d.org
// SPDX-License-Identifier: MIT
// ----------------------------------------------------------------------------
#pragma once
#include <list>
#include "open3d/core/Tensor.h"
#include "open3d/core/TensorCheck.h"
#include "open3d/geometry/TriangleMesh.h"
#include "open3d/t/geometry/BoundingVolume.h"
#include "open3d/t/geometry/DrawableGeometry.h"
#include "open3d/t/geometry/Geometry.h"
#include "open3d/t/geometry/TensorMap.h"
namespace open3d {
namespace t {
namespace geometry {
class LineSet;
/// \class TriangleMesh
/// \brief A triangle mesh contains vertices and triangles.
///
/// The triangle mesh class stores the attribute data in key-value maps. There
/// are two maps: the vertex attributes map, and the triangle attribute map.
///
/// - Default attribute: vertex_attr_["positions"], triangle_attr_["indices"]
/// - Vertex positions
/// - TriangleMesh::GetVertexPositions()
/// - TriangleMesh::SetVertexPositions(const Tensor& vertex_positions)
/// - TriangleMesh::HasVertexPositions()
/// - Value tensor must have shape {num_vertices, 3}.
/// - Triangle indices
/// - TriangleMesh::GetTriangleIndices()
/// - TriangleMesh::SetTriangleIndices(const Tensor& triangle_indices)
/// - TriangleMesh::HasTriangleIndices()
/// - Value tensor must have shape {num_triangles, 3}.
/// - Created by default, required for all triangle meshes.
/// - The device of vertex positions and triangle indices must be the same.
/// They determine the device of the trianglemesh.
///
/// - Common attributes: vertex_attr_["normals"], vertex_attr_["colors"]
/// triangle_attr_["normals"], triangle_attr_["colors"]
/// - Vertex normals
/// - TriangleMesh::GetVertexNormals()
/// - TriangleMesh::SetVertexNormals(const Tensor& vertex_normals)
/// - TriangleMesh::HasVertexNormals()
/// - Value tensor must have shape {num_vertices, 3}.
/// - Value tensor can have any dtype.
/// - Vertex colors
/// - TriangleMesh::GetVertexColors()
/// - TriangleMesh::SetVertexColors(const Tensor& vertex_colors)
/// - TriangleMesh::HasVertexColors()
/// - Value tensor must have shape {num_vertices, 3}.
/// - Value tensor can have any dtype.
/// - Triangle normals
/// - TriangleMesh::GetTriangleNormals()
/// - TriangleMesh::SetTriangleNormals(const Tensor& triangle_normals)
/// - TriangleMesh::HasTriangleNormals()
/// - Value tensor must have shape {num_triangles, 3}.
/// - Value tensor can have any dtype.
/// - Triangle colors
/// - TriangleMesh::GetTriangleColors()
/// - TriangleMesh::SetTriangleColors(const Tensor& triangle_colors)
/// - TriangleMesh::HasTriangleColors()
/// - Value tensor must have shape {num_triangles, 3}.
/// - Value tensor can have any dtype.
/// - Not created by default.
/// - For all attributes above, the device must be consistent with the
/// device of the triangle mesh.
///
/// - Custom attributes: e.g. vetex_attr_["labels"], triangle_attr_["labels"]
/// - Use generalized helper functions, e.g.:
/// - TriangleMesh::GetVertexAttr(const std::string& key)
/// - TriangleMesh::SetVertexAttr(const std::string& key,
/// const Tensor& value)
/// - TriangleMesh::HasVertexAttr(const std::string& key)
/// - TriangleMesh::GetTriangleAttr(const std::string& key)
/// - TriangleMesh::SetTriangleAttr(const std::string& key,
/// const Tensor& value)
/// - TriangleMesh::HasTriangleAttr(const std::string& key)
/// - Not created by default. Users can add their own custom attributes.
/// - Value tensor must be on the same device as the triangle mesh.
///
/// Note that the we can also use the generalized helper functions for the
/// default and common attributes.
class TriangleMesh : public Geometry, public DrawableGeometry {
public:
/// Construct an empty trianglemesh on the provided device.
/// \param device The device on which to initialize the trianglemesh
/// (default: 'CPU:0').
TriangleMesh(const core::Device &device = core::Device("CPU:0"));
/// Construct a trianglemesh from vertices and triangles.
///
/// The input tensors will be directly used as the underlying storage of
/// the triangle mesh (no memory copy). The device for \p vertex_positions
/// must be consistent with \p triangle_indices.
///
/// \param vertex_positions A tensor with element shape {3}.
/// \param triangle_indices A tensor with element shape {3}.
TriangleMesh(const core::Tensor &vertex_positions,
const core::Tensor &triangle_indices);
virtual ~TriangleMesh() override {}
public:
/// \brief Text description.
std::string ToString() const;
/// Transfer the triangle mesh to a specified device.
/// \param device The targeted device to convert to.
/// \param copy If true, a new triangle mesh is always created; if false,
/// the copy is avoided when the original triangle mesh is already on the
/// targeted device.
TriangleMesh To(const core::Device &device, bool copy = false) const;
/// Returns copy of the triangle mesh on the same device.
TriangleMesh Clone() const { return To(GetDevice(), /*copy=*/true); }
/// Getter for vertex_attr_ TensorMap. Used in Pybind.
const TensorMap &GetVertexAttr() const { return vertex_attr_; }
/// Getter for vertex_attr_ TensorMap.
TensorMap &GetVertexAttr() { return vertex_attr_; }
/// Get vertex attributes in vertex_attr_. Throws exception if the attribute
/// does not exist.
///
/// \param key Attribute name.
core::Tensor &GetVertexAttr(const std::string &key) {
return vertex_attr_.at(key);
}
/// Get the value of the "positions" attribute in vertex_attr_.
/// Convenience function.
core::Tensor &GetVertexPositions() { return GetVertexAttr("positions"); }
/// Get the value of the "colors" attribute in vertex_attr_.
/// Convenience function.
core::Tensor &GetVertexColors() { return GetVertexAttr("colors"); }
/// Get the value of the "normals" attribute in vertex_attr_.
/// Convenience function.
core::Tensor &GetVertexNormals() { return GetVertexAttr("normals"); }
/// Getter for triangle_attr_ TensorMap. Used in Pybind.
const TensorMap &GetTriangleAttr() const { return triangle_attr_; }
/// Getter for triangle_attr_ TensorMap.
TensorMap &GetTriangleAttr() { return triangle_attr_; }
/// Get triangle attributes in triangle_attr_. Throws exception if the
/// attribute does not exist.
///
/// \param key Attribute name.
core::Tensor &GetTriangleAttr(const std::string &key) {
return triangle_attr_.at(key);
}
/// Get the value of the "indices" attribute in triangle_attr_.
/// Convenience function.
core::Tensor &GetTriangleIndices() { return GetTriangleAttr("indices"); }
/// Get the value of the "normals" attribute in triangle_attr_.
/// Convenience function.
core::Tensor &GetTriangleNormals() { return GetTriangleAttr("normals"); }
/// Get the value of the "colors" attribute in triangle_attr_.
/// Convenience function.
core::Tensor &GetTriangleColors() { return GetTriangleAttr("colors"); }
/// Get vertex attributes. Throws exception if the attribute does not exist.
///
/// \param key Attribute name.
const core::Tensor &GetVertexAttr(const std::string &key) const {
return vertex_attr_.at(key);
}
/// Removes vertex attribute by key value. Primary attribute "positions"
/// cannot be removed. Throws warning if attribute key does not exists.
///
/// \param key Attribute name.
void RemoveVertexAttr(const std::string &key) { vertex_attr_.Erase(key); }
/// Get the value of the "positions" attribute in vertex_attr_.
/// Convenience function.
const core::Tensor &GetVertexPositions() const {
return GetVertexAttr("positions");
}
/// Get the value of the "colors" attribute in vertex_attr_.
/// Convenience function.
const core::Tensor &GetVertexColors() const {
return GetVertexAttr("colors");
}
/// Get the value of the "normals" attribute in vertex_attr_.
/// Convenience function.
const core::Tensor &GetVertexNormals() const {
return GetVertexAttr("normals");
}
/// Get triangle attributes in triangle_attr_. Throws exception if the
/// attribute does not exist.
///
/// \param key Attribute name.
const core::Tensor &GetTriangleAttr(const std::string &key) const {
return triangle_attr_.at(key);
}
/// Removes triangle attribute by key value. Primary attribute "indices"
/// cannot be removed. Throws warning if attribute key does not exists.
///
/// \param key Attribute name.
void RemoveTriangleAttr(const std::string &key) {
triangle_attr_.Erase(key);
}
/// Get the value of the "indices" attribute in triangle_attr_.
/// Convenience function.
const core::Tensor &GetTriangleIndices() const {
return GetTriangleAttr("indices");
}
/// Get the value of the "normals" attribute in triangle_attr_.
/// Convenience function.
const core::Tensor &GetTriangleNormals() const {
return GetTriangleAttr("normals");
}
/// Get the value of the "colors" attribute in triangle_attr_.
/// Convenience function.
const core::Tensor &GetTriangleColors() const {
return GetTriangleAttr("colors");
}
/// Set vertex attributes. If the attribute key already exists, its value
/// will be overwritten, otherwise, the new key will be created.
///
/// \param key Attribute name.
/// \param value A tensor.
void SetVertexAttr(const std::string &key, const core::Tensor &value) {
core::AssertTensorDevice(value, device_);
vertex_attr_[key] = value;
}
/// Set the value of the "positions" attribute in vertex_attr_.
/// Convenience function.
void SetVertexPositions(const core::Tensor &value) {
core::AssertTensorShape(value, {utility::nullopt, 3});
SetVertexAttr("positions", value);
}
/// Set the value of the "colors" attribute in vertex_attr_.
/// Convenience function.
void SetVertexColors(const core::Tensor &value) {
core::AssertTensorShape(value, {utility::nullopt, 3});
SetVertexAttr("colors", value);
}
/// Set the value of the "normals" attribute in vertex_attr_.
/// This is a convenience function.
void SetVertexNormals(const core::Tensor &value) {
core::AssertTensorShape(value, {utility::nullopt, 3});
SetVertexAttr("normals", value);
}
/// Set triangle attributes. If the attribute key already exists, its value
/// will be overwritten, otherwise, the new key will be created.
///
/// \param key Attribute name.
/// \param value A tensor.
void SetTriangleAttr(const std::string &key, const core::Tensor &value) {
core::AssertTensorDevice(value, device_);
triangle_attr_[key] = value;
}
/// Set the value of the "indices" attribute in triangle_attr_.
void SetTriangleIndices(const core::Tensor &value) {
core::AssertTensorShape(value, {utility::nullopt, 3});
SetTriangleAttr("indices", value);
}
/// Set the value of the "normals" attribute in triangle_attr_.
/// This is a convenience function.
void SetTriangleNormals(const core::Tensor &value) {
core::AssertTensorShape(value, {utility::nullopt, 3});
SetTriangleAttr("normals", value);
}
/// Set the value of the "colors" attribute in triangle_attr_.
/// This is a convenience function.
void SetTriangleColors(const core::Tensor &value) {
core::AssertTensorShape(value, {utility::nullopt, 3});
SetTriangleAttr("colors", value);
}
/// Returns true if all of the following are true in vertex_attr_:
/// 1) attribute key exist
/// 2) attribute's length as vertices' length
/// 3) attribute's length > 0
bool HasVertexAttr(const std::string &key) const {
return vertex_attr_.Contains(key) &&
GetVertexAttr(key).GetLength() > 0 &&
GetVertexAttr(key).GetLength() ==
GetVertexPositions().GetLength();
}
/// Check if the "positions" attribute's value in vertex_attr_ has length >
/// 0. Convenience function.
bool HasVertexPositions() const { return HasVertexAttr("positions"); }
/// Returns true if all of the following are true in vertex_attr_:
/// 1) attribute "colors" exist
/// 2) attribute "colors"'s length as vertices' length
/// 3) attribute "colors"'s length > 0
/// Convenience function.
bool HasVertexColors() const { return HasVertexAttr("colors"); }
/// Returns true if all of the following are true in vertex_attr_:
/// 1) attribute "normals" exist
/// 2) attribute "normals"'s length as vertices' length
/// 3) attribute "normals"'s length > 0
/// Convenience function.
bool HasVertexNormals() const { return HasVertexAttr("normals"); }
/// Returns true if all of the following are true in triangle_attr_:
/// 1) attribute key exist
/// 2) attribute's length as triangles' length
/// 3) attribute's length > 0
bool HasTriangleAttr(const std::string &key) const {
return triangle_attr_.Contains(key) &&
GetTriangleAttr(key).GetLength() > 0 &&
GetTriangleAttr(key).GetLength() ==
GetTriangleIndices().GetLength();
}
/// Check if the "indices" attribute's value in triangle_attr_ has length
/// > 0.
/// Convenience function.
bool HasTriangleIndices() const { return HasTriangleAttr("indices"); }
/// Returns true if all of the following are true in triangle_attr_:
/// 1) attribute "normals" exist
/// 2) attribute "normals"'s length as vertices' length
/// 3) attribute "normals"'s length > 0
/// Convenience function.
bool HasTriangleNormals() const { return HasTriangleAttr("normals"); }
/// Returns true if all of the following are true in triangle_attr_:
/// 1) attribute "colors" exist
/// 2) attribute "colors"'s length as vertices' length
/// 3) attribute "colors"'s length > 0
/// Convenience function.
bool HasTriangleColors() const { return HasTriangleAttr("colors"); }
/// Create a box triangle mesh. One vertex of the box will be placed at
/// the origin and the box aligns with the positive x, y, and z axes.
/// \param width is x-directional length.
/// \param height is y-directional length.
/// \param depth is z-directional length.
/// \param float_dtype Float32 or Float64, used to store floating point
/// values, e.g. vertices, normals, colors.
/// \param int_dtype Int32 or Int64, used to store index values, e.g.
/// triangles.
/// \param device The device where the resulting TriangleMesh resides in.
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"));
/// Create a sphere triangle mesh. The sphere with radius will be centered
/// at (0, 0, 0). Its axis is aligned with z-axis.
/// \param radius defines the radius of the sphere.
/// \param resolution defines the resolution of the sphere. The longitudes
/// will be split into resolution segments (i.e. there are resolution + 1
/// latitude lines including the north and south pole). The latitudes will
/// be split into `2 * resolution segments (i.e. there are 2 * resolution
/// longitude lines.)
/// \param float_dtype Float32 or Float64, used to store floating point
/// values, e.g. vertices, normals, colors.
/// \param int_dtype Int32 or Int64, used to store index values, e.g.
/// triangles.
/// \param device The device where the resulting TriangleMesh resides in.
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"));
/// Create a tetrahedron triangle mesh. The centroid of the mesh will be
/// placed at (0, 0, 0) and the vertices have a distance of radius to the
/// center.
/// \param radius defines the distance from centroid to mesh vetices.
/// \param float_dtype Float32 or Float64, used to store floating point
/// values, e.g. vertices, normals, colors.
/// \param int_dtype Int32 or Int64, used to store index values, e.g.
/// triangles.
/// \param device The device where the resulting TriangleMesh resides in.
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"));
/// Create a octahedron triangle mesh. The centroid of the mesh will be
/// placed at (0, 0, 0) and the vertices have a distance of radius to the
/// center.
/// \param radius defines the distance from centroid to mesh vetices.
/// \param float_dtype Float32 or Float64, used to store floating point
/// values, e.g. vertices, normals, colors.
/// \param int_dtype Int32 or Int64, used to store index values, e.g.
/// triangles.
/// \param device The device where the resulting TriangleMesh resides in.
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"));
/// Create a icosahedron triangle mesh. The centroid of the mesh will be
/// placed at (0, 0, 0) and the vertices have a distance of radius to the
/// center.
/// \param radius defines the distance from centroid to mesh vetices.
/// \param float_dtype Float32 or Float64, used to store floating point
/// values, e.g. vertices, normals, colors.
/// \param int_dtype Int32 or Int64, used to store index values, e.g.
/// triangles.
/// \param device The device where the resulting TriangleMesh resides in.
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"));
/// Create a cylinder triangle mesh.
/// \param radius defines the radius of the cylinder.
/// \param height defines the height of the cylinder. The axis of the
/// cylinder will be from (0, 0, -height/2) to (0, 0, height/2).
/// \param resolution defines the resolution of the cylinder. The circle
/// will be split into resolution segments
/// \param split defines the number of segments along the height direction.
/// \param float_dtype Float32 or Float64, used to store floating point
/// values, e.g. vertices, normals, colors.
/// \param int_dtype Int32 or Int64, used to store index values, e.g.
/// triangles.
/// \param device The device where the resulting TriangleMesh resides in.
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"));
/// Create a cone triangle mesh.
/// \param radius defines the radius of the cone.
/// \param height defines the height of the cone. The axis of the
/// cone will be from (0, 0, 0) to (0, 0, height).
/// \param resolution defines the resolution of the cone. The circle
/// will be split into resolution segments.
/// \param split defines the number of segments along the height direction.
/// \param float_dtype Float32 or Float64, used to store floating point
/// values, e.g. vertices, normals, colors.
/// \param int_dtype Int32 or Int64, used to store index values, e.g.
/// triangles.
/// \param device The device where the resulting TriangleMesh resides in.
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"));
/// Create a torus triangle mesh.
/// \param torus_radius defines the radius from the center of the
/// torus to the center of the tube.
/// \param tube_radius defines the radius of the torus tube.
/// \param radial_resolution defines the number of segments along the
/// radial direction.
/// \param tubular_resolution defines the number of segments along
/// the tubular direction.
/// \param float_dtype Float32 or Float64, used to store floating point
/// values, e.g. vertices, normals, colors.
/// \param int_dtype Int32 or Int64, used to store index values, e.g.
/// triangles.
/// \param device The device where the resulting TriangleMesh resides in.
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"));
/// Create a arrow triangle mesh.
/// \param cylinder_radius defines the radius of the cylinder.
/// \param cone_radius defines the radius of the cone.
/// \param cylinder_height defines the height of the cylinder. The axis of
/// cylinder is from (0, 0, 0) to (0, 0, cylinder_height).
/// \param cone_height defines the height of the cone. The axis of the
/// cone will be from (0, 0, cylinder_height) to (0, 0, cylinder_height +
/// cone_height). \param resolution defines the resolution of the cone. The
/// circle will be split into resolution segments. \param cylinder_split
/// defines the number of segments along the cylinder_height direction.
/// \param cone_split defines the number of segments along
/// the cone_height direction.
/// \param float_dtype Float32 or Float64, used to store floating point
/// values, e.g. vertices, normals, colors.
/// \param int_dtype Int32 or Int64, used to store index values, e.g.
/// triangles.
/// \param device The device where the resulting TriangleMesh resides in.
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"));
/// Create a coordinate frame mesh.
/// \param size defines the size of the coordinate frame.
/// \param origin defines the origin of the coordinate frame.
/// \param float_dtype Float32 or Float64, used to store floating point
/// values, e.g. vertices, normals, colors.
/// \param int_dtype Int32 or Int64, used to store index values, e.g.
/// triangles.
/// \param device The device where the resulting TriangleMesh resides in.
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"));
/// Create a Mobius strip.
/// \param length_split defines the number of segments along the Mobius
/// strip.
/// \param width_split defines the number of segments along the width
/// of the Mobius strip.
/// \param twists defines the number of twists of the strip.
/// \param radius defines the radius of the Mobius strip.
/// \param flatness controls the height of the strip.
/// \param width controls the width of the Mobius strip.
/// \param scale is used to scale the entire Mobius strip.
/// \param float_dtype Float32 or Float64, used to store floating point
/// values, e.g. vertices, normals, colors.
/// \param int_dtype Int32 or Int64, used to store index values, e.g.
/// triangles.
/// \param device The device where the resulting TriangleMesh resides in.
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"));
/// Create a text triangle mesh.
/// \param text The text for generating the mesh. ASCII characters 32-126
/// are supported (includes alphanumeric characters and punctuation). In
/// addition the line feed '\n' is supported to start a new line.
/// \param depth The depth of the generated mesh. If depth is 0 then a flat
/// mesh will be generated.
/// \param int_dtype Int32 or Int64, used to store index values, e.g.
/// triangles.
/// \param device The device where the resulting TriangleMesh resides in.
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"));
public:
/// Clear all data in the trianglemesh.
TriangleMesh &Clear() override {
vertex_attr_.clear();
triangle_attr_.clear();
return *this;
}
/// Returns !HasVertexPositions(), triangles are ignored.
bool IsEmpty() const override { return !HasVertexPositions(); }
core::Tensor GetMinBound() const { return GetVertexPositions().Min({0}); }
core::Tensor GetMaxBound() const { return GetVertexPositions().Max({0}); }
core::Tensor GetCenter() const { return GetVertexPositions().Mean({0}); }
/// \brief Transforms the VertexPositions, VertexNormals and TriangleNormals
/// (if exist) of the TriangleMesh.
///
/// Transformation matrix is a 4x4 matrix.
/// T (4x4) = [[ R(3x3) t(3x1) ],
/// [ O(1x3) s(1x1) ]]
/// (s = 1 for Transformation without scaling)
///
/// It applies the following general transform to each `positions` and
/// `normals`.
/// |x'| | R(0,0) R(0,1) R(0,2) t(0)| |x|
/// |y'| = | R(1,0) R(1,1) R(1,2) t(1)| @ |y|
/// |z'| | R(2,0) R(2,1) R(2,2) t(2)| |z|
/// |w'| | O(0,0) O(0,1) O(0,2) s | |1|
///
/// [x, y, z] = [x', y', z'] / w'
///
/// \param transformation Transformation [Tensor of dim {4,4}].
/// \return Transformed TriangleMesh
TriangleMesh &Transform(const core::Tensor &transformation);
/// \brief Translates the VertexPositions of the TriangleMesh.
/// \param translation translation tensor of dimension {3}
/// \param relative if true (default): translates relative to Center
/// \return Translated TriangleMesh
TriangleMesh &Translate(const core::Tensor &translation,
bool relative = true);
/// \brief Scales the VertexPositions of the TriangleMesh.
/// \param scale Scale [double] of dimension
/// \param center Center [Tensor of dim {3}] about which the TriangleMesh is
/// to be scaled.
/// \return Scaled TriangleMesh
TriangleMesh &Scale(double scale, const core::Tensor &center);
/// \brief Rotates the VertexPositions, VertexNormals and TriangleNormals
/// (if exists).
/// \param R Rotation [Tensor of dim {3,3}].
/// \param center Center [Tensor of dim {3}] about which the TriangleMesh is
/// to be scaled.
/// \return Rotated TriangleMesh
TriangleMesh &Rotate(const core::Tensor &R, const core::Tensor &center);
/// Normalize both triangle normals and vertex normals to length 1.
TriangleMesh &NormalizeNormals();
/// \brief Function to compute triangle normals, usually called before
/// rendering.
TriangleMesh &ComputeTriangleNormals(bool normalized = true);
/// \brief Function to compute vertex normals, usually called before
/// rendering.
TriangleMesh &ComputeVertexNormals(bool normalized = true);
/// \brief Function that computes the surface area of the mesh, i.e. the sum
/// of the individual triangle surfaces.
double GetSurfaceArea() const;
/// \brief Clip mesh with a plane.
/// This method clips the triangle mesh with the specified plane.
/// Parts of the mesh on the positive side of the plane will be kept and
/// triangles intersected by the plane will be cut.
/// \param point A point on the plane as [Tensor of dim {3}].
/// \param normal The normal of the plane as [Tensor of dim {3}]. The normal
/// points to the positive side of the plane for which the geometry will be
/// kept.
/// \return New triangle mesh clipped with the plane.
TriangleMesh ClipPlane(const core::Tensor &point,
const core::Tensor &normal) const;
/// \brief Extract contour slices given a plane.
/// This method extracts slices as LineSet from the mesh at specific
/// contour values defined by the specified plane.
/// \param point A point on the plane as [Tensor of dim {3}].
/// \param normal The normal of the plane as [Tensor of dim {3}].
/// \param contour_values Contour values at which slices will be generated.
/// The value describes the signed distance to the plane.
/// \return LineSet with the extracted contours.
LineSet SlicePlane(const core::Tensor &point,
const core::Tensor &normal,
const std::vector<double> contour_values = {0.0}) const;
core::Device GetDevice() const override { return device_; }
/// Create a TriangleMesh from a legacy Open3D TriangleMesh.
/// \param mesh_legacy Legacy Open3D TriangleMesh.
/// \param float_dtype Float32 or Float64, used to store floating point
/// values, e.g. vertices, normals, colors.
/// \param int_dtype Int32 or Int64, used to store index values, e.g.
/// triangles.
/// \param device The device where the resulting TriangleMesh resides in.
static geometry::TriangleMesh FromLegacy(
const open3d::geometry::TriangleMesh &mesh_legacy,
core::Dtype float_dtype = core::Float32,
core::Dtype int_dtype = core::Int64,
const core::Device &device = core::Device("CPU:0"));
/// Convert to a legacy Open3D TriangleMesh.
open3d::geometry::TriangleMesh ToLegacy() const;
/// Compute the convex hull of the triangle mesh using qhull.
///
/// This runs on the CPU.
///
/// \param joggle_inputs (default False). Handle precision problems by
/// randomly perturbing the input data. Set to True if perturbing the input
/// iis acceptable but you need convex simplicial output. If False,
/// neighboring facets may be merged in case of precision problems. See
/// [QHull docs](http://www.qhull.org/html/qh-impre.htm#joggle) for more
/// details.
///
/// \return TriangleMesh representing the convexh hull. This contains an
/// extra vertex property "point_map" that contains the index of the
/// corresponding vertex in the original mesh.
TriangleMesh ComputeConvexHull(bool joggle_inputs = false) const;
/// Function to simplify mesh using Quadric Error Metric Decimation by
/// Garland and Heckbert.
///
/// This function always uses the CPU device.
///
/// \param target_reduction The factor of triangles to delete, i.e.,
/// setting this to 0.9 will return a mesh with about 10% of the original
/// triangle count.
/// It is not guaranteed that the target reduction factor will be reached.
/// \param preserve_volume If set to true this enables volume preservation
/// which reduces the error in triangle normal direction.
///
/// \return Simplified TriangleMesh.
TriangleMesh SimplifyQuadricDecimation(double target_reduction,
bool preserve_volume = true) const;
/// Computes the mesh that encompasses the union of the volumes of two
/// meshes.
/// Both meshes should be manifold.
///
/// This function always uses the CPU device.
///
/// \param mesh This is the second operand for the boolean operation.
/// \param tolerance Threshold which determines when point distances are
/// considered to be 0.
///
/// \return The mesh describing the union volume.
TriangleMesh BooleanUnion(const TriangleMesh &mesh,
double tolerance = 1e-6) const;
/// Computes the mesh that encompasses the intersection of the volumes of
/// two meshes. Both meshes should be manifold.
///
/// This function always uses the CPU device.
///
/// \param mesh This is the second operand for the boolean operation.
/// \param tolerance Threshold which determines when point distances are
/// considered to be 0.
///
/// \return The mesh describing the intersection volume.
TriangleMesh BooleanIntersection(const TriangleMesh &mesh,
double tolerance = 1e-6) const;
/// Computes the mesh that encompasses the volume after subtracting the
/// volume of the second operand. Both meshes should be manifold.
///
/// This function always uses the CPU device.
///
/// \param mesh This is the second operand for the boolean operation.
/// \param tolerance Threshold which determines when point distances are
/// considered to be 0.
///
/// \return The mesh describing the difference volume.
TriangleMesh BooleanDifference(const TriangleMesh &mesh,
double tolerance = 1e-6) const;
/// Create an axis-aligned bounding box from vertex attribute "positions".
AxisAlignedBoundingBox GetAxisAlignedBoundingBox() const;
/// Create an oriented bounding box from vertex attribute "positions".
OrientedBoundingBox GetOrientedBoundingBox() const;
/// Fill holes by triangulating boundary edges.
///
/// This function always uses the CPU device.
///
/// \param hole_size This is the approximate threshold for filling holes.
/// The value describes the maximum radius of holes to be filled.
///
/// \return New mesh after filling holes.
TriangleMesh FillHoles(double hole_size = 1e6) const;
/// Creates an UV atlas and adds it as triangle attr 'texture_uvs' to the
/// mesh.
///
/// Input meshes must be manifold for this method to work.
///
/// The algorithm is based on:
/// - Zhou et al, "Iso-charts: Stretch-driven Mesh Parameterization using
/// Spectral Analysis", Eurographics Symposium on Geometry Processing (2004)
/// - Sander et al. "Signal-Specialized Parametrization" Europgraphics 2002
///
/// This function always uses the CPU device.
///
/// \param size The target size of the texture (size x size). The uv
/// coordinates will still be in the range [0..1] but parameters like gutter
/// use pixels as units.
/// \param gutter This is the space around the uv islands in pixels.
/// \param max_stretch The maximum amount of stretching allowed. The
/// parameter range is [0..1] with 0 meaning no stretch allowed.
/// \param parallel_partitions The approximate number of partitions created
/// before computing the UV atlas for parallelizing the computation.
/// Parallelization can be enabled with values > 1. Note that
/// parallelization increases the number of UV islands and can lead to
/// results with lower quality.
/// \param nthreads The number of threads used
/// when parallel_partitions is > 1. Set to 0 for automatic number of thread
/// detection.
///
/// \return Tuple with (max stretch, num_charts, num_partitions) storing the
/// actual amount of stretch, the number of created charts, and the number
/// of parallel partitions created.
std::tuple<float, int, int> ComputeUVAtlas(size_t size = 512,
float gutter = 1.0f,
float max_stretch = 1.f / 6,
int parallel_partitions = 1,
int nthreads = 0);
/// Bake vertex attributes into textures.
///
/// This function assumes a triangle attribute with name 'texture_uvs'.
/// Only float type attributes can be baked to textures.
///
/// This function always uses the CPU device.
///
/// \param size The width and height of the texture in pixels. Only square
/// textures are supported.
///
/// \param vertex_attr The vertex attributes for which textures should be
/// generated.
///
/// \param margin The margin in pixels. The recommended value is 2. The
/// margin are additional pixels around the UV islands to avoid
/// discontinuities.
///
/// \param fill The value used for filling texels outside the UV islands.
///
/// \param update_material If true updates the material of the mesh.
/// Baking a vertex attribute with the name 'albedo' will become the albedo
/// texture in the material. Existing textures in the material will be
/// overwritten.
///
/// \return A dictionary of textures.
std::unordered_map<std::string, core::Tensor> BakeVertexAttrTextures(
int size,
const std::unordered_set<std::string> &vertex_attr = {},
double margin = 2.,
double fill = 0.,
bool update_material = true);
/// Bake triangle attributes into textures.
///
/// This function assumes a triangle attribute with name 'texture_uvs'.
///
/// This function always uses the CPU device.
///
/// \param size The width and height of the texture in pixels. Only square
/// textures are supported.
///
/// \param vertex_attr The vertex attributes for which textures should be
/// generated.
///
/// \param margin The margin in pixels. The recommended value is 2. The
/// margin are additional pixels around the UV islands to avoid
/// discontinuities.
///
/// \param fill The value used for filling texels outside the UV islands.
///
/// \param update_material If true updates the material of the mesh.
/// Baking a vertex attribute with the name 'albedo' will become the albedo
/// texture in the material. Existing textures in the material will be
/// overwritten.
///
/// \return A dictionary of textures.
std::unordered_map<std::string, core::Tensor> BakeTriangleAttrTextures(
int size,
const std::unordered_set<std::string> &triangle_attr = {},
double margin = 2.,
double fill = 0.,
bool update_material = true);
/// Sweeps the triangle mesh rotationally about an axis.
/// \param angle The rotation angle in degree.
/// \param axis The rotation axis.
/// \param resolution The resolution defines the number of intermediate
/// sweeps about the rotation axis.
/// \param translation The translation along the rotation axis.
/// \param capping If true adds caps to the mesh.
/// \return A triangle mesh with the result of the sweep operation.
TriangleMesh ExtrudeRotation(double angle,
const core::Tensor &axis,
int resolution = 16,
double translation = 0.0,
bool capping = true) const;
/// Sweeps the triangle mesh along a direction vector.
/// \param vector The direction vector.
/// \param scale Scalar factor which essentially scales the direction
/// vector. \param capping If true adds caps to the mesh. \return A triangle
/// mesh with the result of the sweep operation.
TriangleMesh ExtrudeLinear(const core::Tensor &vector,
double scale = 1.0,
bool capping = true) const;
/// Partition the mesh by recursively doing PCA.
/// This function creates a new triangle attribute with the name
/// "partition_ids".
/// \param max_faces The maximum allowed number of faces in a partition.
/// \return The number of partitions.
int PCAPartition(int max_faces);
/// Returns a new mesh with the faces selected by a boolean mask.
/// \param mask A boolean mask with the shape (N) with N as the number of
/// faces in the mesh.
/// \return A new mesh with the selected faces. If the original mesh is
/// empty, return an empty mesh.
TriangleMesh SelectFacesByMask(const core::Tensor &mask) const;
/// Returns a new mesh with the vertices selected by a vector of indices.
/// If an item from the indices list exceeds the max vertex number of
/// the mesh or has a negative value, it is ignored.
/// \param indices An integer list of indices. Duplicates are
/// allowed, but ignored. Signed and unsigned integral types are allowed.
/// \return A new mesh with the selected vertices and faces built
/// from the selected vertices. If the original mesh is empty, return
/// an empty mesh.
TriangleMesh SelectByIndex(const core::Tensor &indices) const;
protected:
core::Device device_ = core::Device("CPU:0");
TensorMap vertex_attr_;
TensorMap triangle_attr_;
};
} // namespace geometry
} // namespace t
} // namespace open3d