update documentation
This commit is contained in:
62
Doc/Tutorial/11-smart_handles/smooth.cc
Normal file
62
Doc/Tutorial/11-smart_handles/smooth.cc
Normal file
@@ -0,0 +1,62 @@
|
||||
|
||||
#include <OpenMesh/Core/IO/MeshIO.hh>
|
||||
#include <OpenMesh/Core/Mesh/DefaultTriMesh.hh>
|
||||
#include <OpenMesh/Core/Utils/PropertyManager.hh>
|
||||
|
||||
#include <iostream>
|
||||
#include <vector>
|
||||
|
||||
using MyMesh = OpenMesh::TriMesh;
|
||||
|
||||
int main(int argc, char** argv)
|
||||
{
|
||||
// Read command line options
|
||||
MyMesh mesh;
|
||||
if (argc != 4) {
|
||||
std::cerr << "Usage: " << argv[0] << " #iterations infile outfile" << std::endl;
|
||||
return 1;
|
||||
}
|
||||
const int iterations = argv[1];
|
||||
const std::string infile = argv[2];
|
||||
const std::string outfile = argv[3];
|
||||
|
||||
// Read mesh file
|
||||
if (!OpenMesh::IO::read_mesh(mesh, infile)) {
|
||||
std::cerr << "Error: Cannot read mesh from " << infile << std::endl;
|
||||
return 1;
|
||||
}
|
||||
|
||||
{
|
||||
// Add a vertex property storing the laplace vector
|
||||
auto laplace = OpenMesh::VProp<MyMesh::Point>(mesh);
|
||||
|
||||
// Add a vertex property storing the laplace of the laplace
|
||||
auto bi_laplace = OpenMesh::VProp<MyMesh::Point>(mesh);
|
||||
|
||||
// Get a propertymanager of the points property of the mesh to use as functor
|
||||
auto points = OpenMesh::getPointsProperty(mesh);
|
||||
|
||||
// Smooth the mesh several times
|
||||
for (int i = 0; i < iterations; ++i) {
|
||||
// Iterate over all vertices to compute laplace vector
|
||||
for (const auto& vh : mesh.vertices())
|
||||
laplace(vh) = vh.vertices().avg(points) - points(vh);
|
||||
|
||||
// Iterate over all vertices to compte update vectors as the negative of the laplace of the laplace damped by 0.5
|
||||
for (const auto& vh : mesh.vertices())
|
||||
bi_laplace(vh) = (vh.vertices().avg(laplace) - laplace(vh));
|
||||
|
||||
// update points
|
||||
for (const auto& vh : mesh.vertices())
|
||||
points(vh) += -0.5 * bi_laplace(vh);
|
||||
}
|
||||
} // The laplace and update properties are removed is removed from the mesh at the end of this scope.
|
||||
|
||||
|
||||
// Write mesh file
|
||||
if (!OpenMesh::IO::read_mesh(mesh, outfile)) {
|
||||
std::cerr << "Error: Cannot write mesh to " << outfile << std::endl;
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -82,6 +82,7 @@ repeatedly replacing each vertex' position by the center of gravity
|
||||
\li \ref tutorial_02
|
||||
\li \ref tutorial_03
|
||||
\li \ref tutorial_04
|
||||
\li \ref tutorial_11
|
||||
\li \ref tutorial_05
|
||||
\li \ref tutorial_06
|
||||
\li \ref tutorial_07
|
||||
|
||||
85
Doc/tutorial_11.docu
Normal file
85
Doc/tutorial_11.docu
Normal file
@@ -0,0 +1,85 @@
|
||||
/** \page tutorial_11 Using Smart Handles
|
||||
|
||||
This examples shows:
|
||||
- How to use Smart Handles and ranges to navigate on the mesh
|
||||
- How to use Smart Ranges
|
||||
|
||||
So far we have used methods such as halfedge_handle(), next_halfedge_handle(), prev_halfedge_handle(), oppopsite_halfedge_handle(), face_handle(), to_vertex_handle(), and some others, to navigate on that mesh. These functions are defined on a mesh and require as input a handle to an element of the mesh, such as VertexHandle or HalfedgeHandle. In the following example we iterate over all vertices of a triangle mesh and for each vertex we create a list of the vertices that lie opposite of the edges in the ring around the vertex:
|
||||
|
||||
\code
|
||||
// iterate over vertices of the mesh
|
||||
for (auto vh : mesh.vertices())
|
||||
{
|
||||
std::vector<OpenMesh::VertexHandle> opposite_vertices;
|
||||
// iterate over all outgoing halfedges
|
||||
for (auto heh : mesh.voh_range(vh))
|
||||
{
|
||||
// navigate to the opposite vertex and store it in the vector
|
||||
opposite_vertices.push_back(mesh.to_vertex_handle(mesh.next_halfedge_handle(mesh.opposite_halfedge_handle(mesh.next_halfedge_handle(heh)))));
|
||||
}
|
||||
}
|
||||
\endcode
|
||||
|
||||
For a more concise way of navigating OpenMesh provides smart handles, OpenMesh::SmartVertexHandle, OpenMesh::SmartHalfedgeHandle, OpenMesh::SmartEdgeHandle, and OpenMesh::SmartFaceHandle. Smart handles are smart, because they know to which mesh they belong. This allows them to provide functions for navigating the mesh allowing us to write the above code much simpler:
|
||||
|
||||
\code
|
||||
// iterate over vertices of the mesh
|
||||
for (auto vh : mesh.vertices())
|
||||
{
|
||||
// iterate over all outgoing halfedges
|
||||
std::vector<OpenMesh::VertexHandle> opposite_vertices;
|
||||
for (auto heh : vh.outgoing_halfedges())
|
||||
{
|
||||
// navigate to the opposite vertex and store it in the vector
|
||||
opposite_vertices.push_back(heh.next().opp().next().to());
|
||||
}
|
||||
}
|
||||
\endcode
|
||||
|
||||
The ranges of OpenMesh that are returned by functions like voh_range() or outgoing_halfedges() all provide a few methods than can simplify some calculations (see OpenMesh::SmartRangeT). One example is the to_vector() method which convertes the range of elements into a vector containing the elements. All of these methods take a functor as argument (sometimes optional) which is called for each element of the range. With this, the above code can also be implemented like this:
|
||||
|
||||
\code
|
||||
// iterate over vertices of the mesh
|
||||
for (auto vh : mesh.vertices())
|
||||
{
|
||||
// create lambda that returns opposite vertex
|
||||
auto opposite_vertex = [](OpenMesh::SmartHalfedgeHandle heh) { return heh.next().opp().next().to(); };
|
||||
// create vector containing all opposite vertices
|
||||
auto opposite_vertices = vh.outgoing_halfedges().to_vector(opposite_vertex);
|
||||
}
|
||||
\endcode
|
||||
|
||||
---
|
||||
|
||||
## Code Example
|
||||
|
||||
In this example, we will use bi-laplacian smoothing on a mesh. We store the \c laplace vector which is the vector pointing from a vertex to the center of gravity of its neighboring vertices in a vertex property.
|
||||
|
||||
\dontinclude 11-smart_handles/smooth.cc
|
||||
\skipline laplace
|
||||
\skipline laplace
|
||||
|
||||
To compute the center of gravity, i.e. the average position, we use the avg() method of the range of 1-ring vertices and pass in a PropertyManager acting as functor returning the corresponding point of a vertex.
|
||||
|
||||
\skipline points
|
||||
\until avg(points)
|
||||
|
||||
Similarily we compute the update vector as the laplace of the freshly computed laplace vectors by simply exchanging the points property manager with the laplace property manager.
|
||||
|
||||
\skipline Iterate
|
||||
\until bi_laplace
|
||||
|
||||
Finally, we apply the update after damping it by a factor of -0.5.
|
||||
|
||||
\skipline udpate points
|
||||
\until bi_laplace
|
||||
|
||||
Below is the complete source code:
|
||||
|
||||
\include 11-smart_handles/smooth.cc
|
||||
|
||||
---
|
||||
|
||||
|
||||
|
||||
*/
|
||||
@@ -33,6 +33,7 @@ repeatedly replacing each vertex' position by the center of gravity
|
||||
<li> \subpage tutorial_02
|
||||
<li> \subpage tutorial_03
|
||||
<li> \subpage tutorial_04
|
||||
<li> \subpage tutorial_11
|
||||
<li> \subpage tutorial_05
|
||||
<li> \subpage tutorial_06
|
||||
<li> \subpage tutorial_07
|
||||
|
||||
Reference in New Issue
Block a user