Skip to content

Commit

Permalink
Improve doc for TriangleMesh, LineSet and PointCloud (#980)
Browse files Browse the repository at this point in the history
* added local vimrc to .gitignore

* improved doc for TriangleMesh, PointCloud, and LineSet. Added checks in TriangleMeshFactory.
  • Loading branch information
griegler authored and yxlao committed May 23, 2019
1 parent cc5b1a9 commit 483275e
Show file tree
Hide file tree
Showing 10 changed files with 329 additions and 73 deletions.
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -27,3 +27,5 @@ static/
*.old*
docs/python_api/
_vimrc_local.vim
examples/TestData/Armadillo.ply
examples/TestData/Bunny.ply
9 changes: 6 additions & 3 deletions src/Open3D/Geometry/LineSet.h
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,7 @@ class LineSet : public Geometry3D {
points_[lines_[line_index][1]]);
}

/// Assigns each line in the LineSet the same color \param color.
void PaintUniformColor(const Eigen::Vector3d &color) {
colors_.resize(lines_.size());
for (size_t i = 0; i < lines_.size(); i++) {
Expand All @@ -86,14 +87,16 @@ class LineSet : public Geometry3D {
std::vector<Eigen::Vector3d> colors_;
};

/// Factory function to create a lineset from two pointclouds and a
/// correspondence set (LineSetFactory.cpp)
/// Factory function to create a LineSet from two PointClouds
/// (\param cloud0, \param cloud1) and a correspondence set
/// \param correspondences.
std::shared_ptr<LineSet> CreateLineSetFromPointCloudCorrespondences(
const PointCloud &cloud0,
const PointCloud &cloud1,
const std::vector<std::pair<int, int>> &correspondences);

/// Factory function to create a lineset from edges of a triangle mesh
/// Factory function to create a LineSet from edges of a triangle mesh
/// \param mesh.
std::shared_ptr<LineSet> CreateLineSetFromTriangleMesh(
const TriangleMesh &mesh);

Expand Down
1 change: 1 addition & 0 deletions src/Open3D/Geometry/PointCloud.h
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,7 @@ class PointCloud : public Geometry3D {
}
}

/// Assigns each point in the PointCloud the same color \param color.
void PaintUniformColor(const Eigen::Vector3d &color) {
colors_.resize(points_.size());
for (size_t i = 0; i < points_.size(); i++) {
Expand Down
2 changes: 1 addition & 1 deletion src/Open3D/Geometry/TriangleMesh.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -488,7 +488,7 @@ void TriangleMesh::FilterSmoothTaubin(int number_of_iterations,
FilterScope scope) {
for (int iter = 0; iter < number_of_iterations; ++iter) {
FilterSmoothLaplacian(1, lambda, scope);
FilterSmoothLaplacian(1, -mu, scope);
FilterSmoothLaplacian(1, mu, scope);
}
}

Expand Down
67 changes: 57 additions & 10 deletions src/Open3D/Geometry/TriangleMesh.h
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,21 @@ class PointCloud;

class TriangleMesh : public Geometry3D {
public:
/// Indicates the method that is used for mesh simplification if multiple
/// vertices are combined to a single one.
/// \param Average indicates that the average position is computed as
/// output.
/// \param Quadric indicates that the distance to the adjacent triangle
/// planes is minimized. Cf. "Simplifying Surfaces with Color and Texture
/// using Quadric Error Metrics" by Garland and Heckbert.
enum class SimplificationContraction { Average, Quadric };

/// Indicates the scope of filter operations.
/// \param All indicates that all properties (color, normal,
/// vertex position) are filtered.
/// \param Color indicates that only the colors are filtered.
/// \param Normal indicates that only the normals are filtered.
/// \param Vertex indicates that only the vertex positions are filtered.
enum class FilterScope { All, Color, Normal, Vertex };

TriangleMesh() : Geometry3D(Geometry::GeometryType::TriangleMesh) {}
Expand Down Expand Up @@ -75,24 +89,47 @@ class TriangleMesh : public Geometry3D {
/// Function to remove duplicated and non-manifold vertices/triangles
void Purge();

/// Function to sharpen triangle mesh
/// Function to sharpen triangle mesh. The output value ($v_o$) is the
/// input value ($v_i$) plus \param strength times the input value minus
/// the sum of he adjacent values.
/// $v_o = v_i x strength (v_i * |N| - \sum_{n \in N} v_n)$.
/// \param number_of_iterations defines the number of repetitions
/// of this operation.
void FilterSharpen(int number_of_iterations,
double strength,
FilterScope scope = FilterScope::All);

/// Function to smooth triangle mesh with simple neighbour average
/// Function to smooth triangle mesh with simple neighbour average.
/// $v_o = \frac{v_i + \sum_{n \in N} v_n)}{|N| + 1}$, with $v_i$
/// being the input value, $v_o$ the output value, and $N$ is the
/// set of adjacent neighbours.
/// \param number_of_iterations defines the number of repetitions
/// of this operation.
void FilterSmoothSimple(int number_of_iterations,
FilterScope scope = FilterScope::All);

/// Function to smooth triangle mesh using Laplacian
/// Function to smooth triangle mesh using Laplacian.
/// $v_o = v_i \cdot \lambda (sum_{n \in N} w_n v_n - v_i)$,
/// with $v_i$ being the input value, $v_o$ the output value, $N$ is the
/// set of adjacent neighbours, $w_n$ is the weighting of the neighbour
/// based on the inverse distance (closer neighbours have higher weight),
/// and \param lambda is the smoothing parameter.
/// \param number_of_iterations defines the number of repetitions
/// of this operation.
void FilterSmoothLaplacian(int number_of_iterations,
double lambda,
FilterScope scope = FilterScope::All);

/// Function to smooth triangle mesh using method of Taubin
/// Function to smooth triangle mesh using method of Taubin,
/// "Curve and Surface Smoothing Without Shrinkage", 1995.
/// Applies in each iteration two times FilterSmoothLaplacian, first
/// with \param lambda and second with \param mu as smoothing parameter.
/// This method avoids shrinkage of the triangle mesh.
/// \param number_of_iterations defines the number of repetitions
/// of this operation.
void FilterSmoothTaubin(int number_of_iterations,
double lambda,
double mu,
double lambda = 0.5,
double mu = -0.53,
FilterScope scope = FilterScope::All);

protected:
Expand Down Expand Up @@ -144,14 +181,17 @@ class TriangleMesh : public Geometry3D {
}
}

/// Assigns each vertex in the TriangleMesh the same color \param color.
void PaintUniformColor(const Eigen::Vector3d &color) {
vertex_colors_.resize(vertices_.size());
for (size_t i = 0; i < vertices_.size(); i++) {
vertex_colors_[i] = color;
}
}

/// Function that computes the Euler-Poincaré characteristic V + F - E
/// Function that computes the Euler-Poincaré characteristic, i.e.,
/// V + F - E, where V is the number of vertices, F is the number
/// of triangles, and E is the number of edges.
int EulerPoincareCharacteristic() const;

/// Function that returns the non-manifold edges of the triangle mesh.
Expand All @@ -162,8 +202,8 @@ class TriangleMesh : public Geometry3D {

/// Function that checks if the given triangle mesh is edge-manifold.
/// A mesh is edge­manifold if each edge is bounding either one or two
/// triangles. If allow_boundary_edges is set to false, than retuns false if
/// there exists boundary edges.
/// triangles. If allow_boundary_edges is set to false, than returns false
/// if there exists boundary edges.
bool IsEdgeManifold(bool allow_boundary_edges = true) const;

/// Function that returns a list of non-manifold vertex indices.
Expand Down Expand Up @@ -388,7 +428,14 @@ std::shared_ptr<TriangleMesh> CreateMeshCoordinateFrame(
double size = 1.0,
const Eigen::Vector3d &origin = Eigen::Vector3d(0.0, 0.0, 0.0));

/// Factory function to create a Moebius strip.
/// Factory function to create a Moebius strip. \param length_split
/// defines the number of segments along the Moebius strip, \param
/// width_split defines the number of segments along the width of
/// the Moebius strip, \param twists defines the number of twists of the
/// strip, \param radius defines the radius of the Moebius strip,
/// \param flatness controls the height of the strip, \param width
/// controls the width of the Moebius strip and \param scale is used
/// to scale the entire Moebius strip.
std::shared_ptr<TriangleMesh> CreateMeshMoebius(int length_split = 70,
int width_split = 15,
int twists = 1,
Expand Down
139 changes: 134 additions & 5 deletions src/Open3D/Geometry/TriangleMeshFactory.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -25,12 +25,17 @@
// ----------------------------------------------------------------------------

#include "Open3D/Geometry/TriangleMesh.h"
#include "Open3D/Utility/Console.h"

namespace open3d {
namespace geometry {

std::shared_ptr<TriangleMesh> CreateMeshTetrahedron(double radius /* = 1.0*/) {
auto mesh = std::make_shared<TriangleMesh>();
if (radius <= 0) {
utility::PrintWarning("[CreateMeshTetrahedron] radius <= 0");
return mesh;
}
mesh->vertices_.push_back(radius *
Eigen::Vector3d(std::sqrt(8. / 9.), 0, -1. / 3.));
mesh->vertices_.push_back(radius * Eigen::Vector3d(-std::sqrt(2. / 9.),
Expand All @@ -49,6 +54,10 @@ std::shared_ptr<TriangleMesh> CreateMeshTetrahedron(double radius /* = 1.0*/) {

std::shared_ptr<TriangleMesh> CreateMeshOctahedron(double radius /* = 1.0*/) {
auto mesh = std::make_shared<TriangleMesh>();
if (radius <= 0) {
utility::PrintWarning("[CreateMeshOctahedron] radius <= 0");
return mesh;
}
mesh->vertices_.push_back(radius * Eigen::Vector3d(1, 0, 0));
mesh->vertices_.push_back(radius * Eigen::Vector3d(0, 1, 0));
mesh->vertices_.push_back(radius * Eigen::Vector3d(0, 0, 1));
Expand All @@ -68,6 +77,10 @@ std::shared_ptr<TriangleMesh> CreateMeshOctahedron(double radius /* = 1.0*/) {

std::shared_ptr<TriangleMesh> CreateMeshIcosahedron(double radius /* = 1.0*/) {
auto mesh = std::make_shared<TriangleMesh>();
if (radius <= 0) {
utility::PrintWarning("[CreateMeshIcosahedron] radius <= 0");
return mesh;
}
const double p = (1. + std::sqrt(5.)) / 2.;
mesh->vertices_.push_back(radius * Eigen::Vector3d(-1, 0, p));
mesh->vertices_.push_back(radius * Eigen::Vector3d(1, 0, p));
Expand Down Expand Up @@ -108,6 +121,18 @@ std::shared_ptr<TriangleMesh> CreateMeshBox(double width /* = 1.0*/,
double height /* = 1.0*/,
double depth /* = 1.0*/) {
auto mesh_ptr = std::make_shared<TriangleMesh>();
if (width <= 0) {
utility::PrintWarning("[CreateMeshBox] width <= 0");
return mesh_ptr;
}
if (height <= 0) {
utility::PrintWarning("[CreateMeshBox] height <= 0");
return mesh_ptr;
}
if (depth <= 0) {
utility::PrintWarning("[CreateMeshBox] depth <= 0");
return mesh_ptr;
}
mesh_ptr->vertices_.resize(8);
mesh_ptr->vertices_[0] = Eigen::Vector3d(0.0, 0.0, 0.0);
mesh_ptr->vertices_[1] = Eigen::Vector3d(width, 0.0, 0.0);
Expand Down Expand Up @@ -135,7 +160,12 @@ std::shared_ptr<TriangleMesh> CreateMeshBox(double width /* = 1.0*/,
std::shared_ptr<TriangleMesh> CreateMeshSphere(double radius /* = 1.0*/,
int resolution /* = 20*/) {
auto mesh_ptr = std::make_shared<TriangleMesh>();
if (radius <= 0.0 || resolution <= 0) {
if (radius <= 0) {
utility::PrintWarning("[CreateMeshSphere] radius <= 0");
return mesh_ptr;
}
if (resolution <= 0) {
utility::PrintWarning("[CreateMeshSphere] resolution <= 0");
return mesh_ptr;
}
mesh_ptr->vertices_.resize(2 * resolution * (resolution - 1) + 2);
Expand Down Expand Up @@ -179,7 +209,20 @@ std::shared_ptr<TriangleMesh> CreateMeshCylinder(double radius /* = 1.0*/,
int resolution /* = 20*/,
int split /* = 4*/) {
auto mesh_ptr = std::make_shared<TriangleMesh>();
if (radius <= 0.0 || height <= 0.0 || resolution <= 0 || split <= 0) {
if (radius <= 0) {
utility::PrintWarning("[CreateMeshCylinder] radius <= 0");
return mesh_ptr;
}
if (height <= 0) {
utility::PrintWarning("[CreateMeshCylinder] height <= 0");
return mesh_ptr;
}
if (resolution <= 0) {
utility::PrintWarning("[CreateMeshCylinder] resolution <= 0");
return mesh_ptr;
}
if (split <= 0) {
utility::PrintWarning("[CreateMeshCylinder] split <= 0");
return mesh_ptr;
}
mesh_ptr->vertices_.resize(resolution * (split + 1) + 2);
Expand Down Expand Up @@ -221,7 +264,20 @@ std::shared_ptr<TriangleMesh> CreateMeshCone(double radius /* = 1.0*/,
int resolution /* = 20*/,
int split /* = 4*/) {
auto mesh_ptr = std::make_shared<TriangleMesh>();
if (radius <= 0.0 || height <= 0.0 || resolution <= 0 || split <= 0) {
if (radius <= 0) {
utility::PrintWarning("[CreateMeshCone] radius <= 0");
return mesh_ptr;
}
if (height <= 0) {
utility::PrintWarning("[CreateMeshCone] height <= 0");
return mesh_ptr;
}
if (resolution <= 0) {
utility::PrintWarning("[CreateMeshCone] resolution <= 0");
return mesh_ptr;
}
if (split <= 0) {
utility::PrintWarning("[CreateMeshCone] split <= 0");
return mesh_ptr;
}
mesh_ptr->vertices_.resize(resolution * split + 2);
Expand Down Expand Up @@ -266,8 +322,20 @@ std::shared_ptr<TriangleMesh> CreateMeshTorus(
int radial_resolution /* = 20 */,
int tubular_resolution /* = 20 */) {
auto mesh = std::make_shared<TriangleMesh>();
if (torus_radius <= 0 || tube_radius >= torus_radius ||
radial_resolution <= 0 || tubular_resolution <= 0) {
if (torus_radius <= 0) {
utility::PrintWarning("[CreateMeshTorus] torus_radius <= 0");
return mesh;
}
if (tube_radius <= 0) {
utility::PrintWarning("[CreateMeshTorus] tube_radius <= 0");
return mesh;
}
if (radial_resolution <= 0) {
utility::PrintWarning("[CreateMeshTorus] radial_resolution <= 0");
return mesh;
}
if (tubular_resolution <= 0) {
utility::PrintWarning("[CreateMeshTorus] tubular_resolution <= 0");
return mesh;
}

Expand Down Expand Up @@ -311,6 +379,34 @@ std::shared_ptr<TriangleMesh> CreateMeshArrow(double cylinder_radius /* = 1.0*/,
int resolution /* = 20*/,
int cylinder_split /* = 4*/,
int cone_split /* = 1*/) {
if (cylinder_radius <= 0) {
utility::PrintWarning("[CreateMeshArrow] cylinder_radius <= 0");
return std::make_shared<TriangleMesh>();
}
if (cone_radius <= 0) {
utility::PrintWarning("[CreateMeshArrow] cone_radius <= 0");
return std::make_shared<TriangleMesh>();
}
if (cylinder_height <= 0) {
utility::PrintWarning("[CreateMeshArrow] cylinder_height <= 0");
return std::make_shared<TriangleMesh>();
}
if (cone_height <= 0) {
utility::PrintWarning("[CreateMeshArrow] cone_height <= 0");
return std::make_shared<TriangleMesh>();
}
if (resolution <= 0) {
utility::PrintWarning("[CreateMeshArrow] resolution <= 0");
return std::make_shared<TriangleMesh>();
}
if (cylinder_split <= 0) {
utility::PrintWarning("[CreateMeshArrow] cylinder_split <= 0");
return std::make_shared<TriangleMesh>();
}
if (cone_split <= 0) {
utility::PrintWarning("[CreateMeshArrow] cone_split <= 0");
return std::make_shared<TriangleMesh>();
}
Eigen::Matrix4d transformation = Eigen::Matrix4d::Identity();
auto mesh_cylinder = CreateMeshCylinder(cylinder_radius, cylinder_height,
resolution, cylinder_split);
Expand All @@ -328,6 +424,10 @@ std::shared_ptr<TriangleMesh> CreateMeshArrow(double cylinder_radius /* = 1.0*/,
std::shared_ptr<TriangleMesh> CreateMeshCoordinateFrame(
double size /* = 1.0*/,
const Eigen::Vector3d &origin /* = Eigen::Vector3d(0.0, 0.0, 0.0)*/) {
if (size <= 0) {
utility::PrintWarning("[CreateMeshCoordinateFrame] size <= 0");
return std::make_shared<TriangleMesh>();
}
auto mesh_frame = CreateMeshSphere(0.06 * size);
mesh_frame->ComputeVertexNormals();
mesh_frame->PaintUniformColor(Eigen::Vector3d(0.5, 0.5, 0.5));
Expand Down Expand Up @@ -374,6 +474,35 @@ std::shared_ptr<TriangleMesh> CreateMeshMoebius(int length_split /* = 70 */,
double width /* = 1 */,
double scale /* = 1 */) {
auto mesh = std::make_shared<TriangleMesh>();
if (length_split <= 0) {
utility::PrintWarning("[CreateMeshMoebius] length_split <= 0");
return mesh;
}
if (width_split <= 0) {
utility::PrintWarning("[CreateMeshMoebius] width_split <= 0");
return mesh;
}
if (twists < 0) {
utility::PrintWarning("[CreateMeshMoebius] twists < 0");
return mesh;
}
if (radius <= 0) {
utility::PrintWarning("[CreateMeshMoebius] radius <= 0");
return mesh;
}
if (flatness == 0) {
utility::PrintWarning("[CreateMeshMoebius] flatness == 0");
return mesh;
}
if (width <= 0) {
utility::PrintWarning("[CreateMeshMoebius] width <= 0");
return mesh;
}
if (scale <= 0) {
utility::PrintWarning("[CreateMeshMoebius] scale <= 0");
return mesh;
}

mesh->vertices_.resize(length_split * width_split);

double u_step = 2 * M_PI / length_split;
Expand Down
Loading

0 comments on commit 483275e

Please sign in to comment.