From e257be3e0bd71a40574d9ce5ff3d29b1c8f29d71 Mon Sep 17 00:00:00 2001 From: Max Lyon Date: Thu, 15 Oct 2020 16:54:29 +0200 Subject: [PATCH] add docu --- Doc/Tutorial/12-predicates/predicates.cc | 58 ++++++++++++++++++++++++ Doc/mainpage.docu | 1 + Doc/tutorial_11.docu | 2 +- Doc/tutorial_12.docu | 38 ++++++++++++++++ Doc/tutorial_main.docu | 1 + 5 files changed, 99 insertions(+), 1 deletion(-) create mode 100644 Doc/Tutorial/12-predicates/predicates.cc create mode 100644 Doc/tutorial_12.docu diff --git a/Doc/Tutorial/12-predicates/predicates.cc b/Doc/Tutorial/12-predicates/predicates.cc new file mode 100644 index 00000000..790a0fbb --- /dev/null +++ b/Doc/Tutorial/12-predicates/predicates.cc @@ -0,0 +1,58 @@ + +#include +#include +#include +#include + +#include +#include + +using MyMesh = OpenMesh::TriMesh; + +bool is_divisible_by_3(OpenMesh::FaceHandle vh) { return vh.idx() % 3 == 0; } + +int main(int argc, char** argv) +{ + using namespace OpenMesh::Predicates; // for easier access to predicates + + // Read command line options + MyMesh mesh; + if (argc != 4) { + std::cerr << "Usage: " << argv[0] << " infile" << std::endl; + return 1; + } + const std::string infile = argv[1]; + + // Read mesh file + if (!OpenMesh::IO::read_mesh(mesh, infile)) { + std::cerr << "Error: Cannot read mesh from " << infile << std::endl; + return 1; + } + + // Count boundary vertices + std::cout << "Mesh contains " << mesh.vertices().count_if(Boundary()) << " boundary vertices"; + + // Selected inner vertices + std::cout << "These are the selected inner vertices: " << std::endl; + for (auto vh : mesh.vertices().filtered(!Boundary() && Selected())) + std::cout << vh.idx() << ", "; + std::cout << std::endl; + + // Faces whose id is divisible by 3 + auto vec = mesh.faces().filtered(is_divisible_by_3).to_vector(); + std::cout << "There are " << vec.size() << " faces whose id is divisible by 3" << std::endl; + + // Faces which are tagged or whose id is not divisible by 3 + auto vec2 = mesh.faces().filtered(Tagged() || !make_predicate(is_divisible_by_3)).to_vector(); + std::cout << "There are " << vec2.size() << " faces which are tagged or whose id is not divisible by 3" << std::endl; + + // Edges that are longer than 10 or shorter than 2 + OpenMesh::EProp longer_than_10(mesh); + for (auto eh : mesh.edges()) + longer_than_10[eh] = mesh.calc_edge_length(eh) > 10; + std::cout << "There are " << + mesh.edges().count_if(make_predicate(longer_than_10) || make_predicate([&](OpenMesh::EdgeHandle eh) { return mesh.calc_edge_length(eh) < 2; })) << + " edges which are shorter than 2 or longer than 10" << std::endl; + +} + diff --git a/Doc/mainpage.docu b/Doc/mainpage.docu index 63bfee8c..d31b189c 100644 --- a/Doc/mainpage.docu +++ b/Doc/mainpage.docu @@ -83,6 +83,7 @@ repeatedly replacing each vertex' position by the center of gravity \li \ref tutorial_03 \li \ref tutorial_04 \li \ref tutorial_11 +\li \ref tutorial_12 \li \ref tutorial_05 \li \ref tutorial_06 \li \ref tutorial_07 diff --git a/Doc/tutorial_11.docu b/Doc/tutorial_11.docu index f99724cf..50b9b787 100644 --- a/Doc/tutorial_11.docu +++ b/Doc/tutorial_11.docu @@ -71,7 +71,7 @@ Similarily we compute the update vector as the laplace of the freshly computed l Finally, we apply the update after damping it by a factor of -0.5. -\skipline udpate points +\skipline update points \until bi_laplace Below is the complete source code: diff --git a/Doc/tutorial_12.docu b/Doc/tutorial_12.docu new file mode 100644 index 00000000..80ad2a8a --- /dev/null +++ b/Doc/tutorial_12.docu @@ -0,0 +1,38 @@ +/** \page tutorial_12 Filtering ranges with predicates + +This examples shows: +- How to use predicates to filter which elements of a mesh you want iterate over + +In the previous tutorial we discussed already that the ranges returned by functions like all_vertices(), voh_range() or outgoing_halfedges() provide a few helpful methods such as avg() or to_vector(). Another interesting method is filtered() which requires as argument something that can be called for an element of the range and returns a bool. The resulting range will then only iterate over elements for which the filter returs true. +The filter can be a lambda, a function pointer, a property manager holding a bool property, or a functor object such as the predicates defined in . The predefined predicates can check the status of a mesh element and test if they are boundary. +With their help you can for example count all boundary vertices: + +\dontinclude 12-predicates/predicates.cc +\skipline Count boundary vertices +\until boundary vertices + +Predicates can be composed using the operators ||, &&, and !. This enables you to specify precisely which elements you want process in your loop, e.g. inner vertices that are selected: + +\skipline Selected inner vertices +\until std::cout << std::endl + +As mentioned above, the filter argument can be anything returning a bool for a given input, e.g. a function pointer: + +\skipline Faces whose id is divisible by 3 +\until faces whose id is divisible by 3 + +However, function pointers, lambdas etc are not composable. Fortunately, you can use make_predicate to turn them into composable predicates: + + +\skipline Faces which are tagged or whose id is not divisible by 3 +\until faces which are tagged or whose id is not divisible by 3 + +Below is the complete source code: + +\include 12-predicates/predicates.cc + +--- + + + +*/ diff --git a/Doc/tutorial_main.docu b/Doc/tutorial_main.docu index 908099dc..3bb81314 100644 --- a/Doc/tutorial_main.docu +++ b/Doc/tutorial_main.docu @@ -34,6 +34,7 @@ repeatedly replacing each vertex' position by the center of gravity
  • \subpage tutorial_03
  • \subpage tutorial_04
  • \subpage tutorial_11 +
  • \subpage tutorial_12
  • \subpage tutorial_05
  • \subpage tutorial_06
  • \subpage tutorial_07