{"id":13731562,"url":"https://github.com/gaschler/bounding-mesh","last_synced_at":"2025-05-08T04:34:40.704Z","repository":{"id":11864667,"uuid":"14424189","full_name":"gaschler/bounding-mesh","owner":"gaschler","description":"Implementation of the bounding mesh and bounding convex decomposition algorithms for single-sided mesh approximation","archived":false,"fork":false,"pushed_at":"2021-09-02T06:14:46.000Z","size":2666,"stargazers_count":332,"open_issues_count":7,"forks_count":47,"subscribers_count":19,"default_branch":"master","last_synced_at":"2024-08-04T02:10:15.607Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"http://www.boundingmesh.com","language":"C++","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"bsd-2-clause","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/gaschler.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2013-11-15T12:46:39.000Z","updated_at":"2024-06-27T10:45:45.000Z","dependencies_parsed_at":"2022-09-14T11:50:28.707Z","dependency_job_id":null,"html_url":"https://github.com/gaschler/bounding-mesh","commit_stats":null,"previous_names":[],"tags_count":2,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/gaschler%2Fbounding-mesh","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/gaschler%2Fbounding-mesh/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/gaschler%2Fbounding-mesh/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/gaschler%2Fbounding-mesh/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/gaschler","download_url":"https://codeload.github.com/gaschler/bounding-mesh/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":224702693,"owners_count":17355595,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-08-03T02:01:32.998Z","updated_at":"2025-05-08T04:34:40.693Z","avatar_url":"https://github.com/gaschler.png","language":"C++","funding_links":[],"categories":["Maths"],"sub_categories":[],"readme":"# Boundingmesh\n\nContributors: Andre Gaschler, Quirin Fischer, Philipp Gergen\n\nLicense: 2-clause BSD, a permissive license, see LICENSE file; see [License](#license) for details of linked libraries.\nSeveral features require more restrictive licenses.\n\nBoundingmesh is a library and tool set for generating *bounding meshes and\n bounding convex decompositions*.\nA bounding mesh encloses a given mesh and has fewer vertices; it\n is single-sided approximate mesh.\nA bounding convex decomposition is a set of convex hulls of few vertices\nthat enclose a given mesh.\n\n## Table of Contents\n*   [Overview](#overview)\n    *  [Features](#features)\n    *  [Publications](#publications)\n    *  [Screenshots](#screenshots)\n        * [GUI](#gui)\n        * [Bounding Convex Decomposition](#bounding-convex-decomposition)\n    *  [Example Models](#example-models)\n*   [Usage](#usage)\n\t*  [License](#license)\n    *  [Installation](#installation)\n        * [Building from Source](#building-from-source)\n        * [Binaries](#binaries)\n    *  [Command-Line Tools](#command-line-tools)\n    *  [GUI Application](#gui-application)\n        * [Linux Build](#linux-build)\n        * [Windows Build](#windows-build)\n    *  [Static Library](#static-library)\n*   [Code-Guide](#code-guide)\n    *  [Data Structures](#data-structures)\n    *  [Mesh Decimation](#mesh-decimation)\n    *  [Convex Decomposition](#convex-decomposition)\n*   [Documentation](#documentation)\n    *  [Command-line Tool](#command-line-tool-1)\n        *  [boundingmesh-bin/main.cpp](#boundingmesh-binmaincpp)\n    *  [Graphical User Interface](#graphical-user-interface)\n        *  [boundingmesh-gui/gui.h](#boundingmesh-guiguih)\n        *  [boundingmesh-gui/ViewerMesh.h](#boundingmesh-guiviewermeshh)\n    *  [Core Library](#core-library)\n        *  [boundingmesh/boundingmesh.h](#boundingmeshboundingmeshh)\n        *  [boundingmesh/Primitives.h](#boundingmeshprimitivesh)\n        *  [boundingmesh/Mesh.h](#boundingmeshmeshh)\n        *  [boundingmesh/ContractionUtils.h](#boundingmeshcontractionutilsh)\n        *  [boundingmesh/Decimator.h](#boundingmeshdecimatorh)\n        *  [boundingmesh/MetricGenerator.h](#boundingmeshmetricgeneratorh)\n        *  [boundingmesh/VoxelSet.h](#boundingmeshvoxelseth)\n        *  [boundingmesh/SegmenterSimple.h](#boundingmeshsegmenterh)\n\n## Overview\n\n\n### Features\n\n*   Reduce mesh complexity restricted either by vertex count or by mesh error. \n*   Import/Export various standard 3D geometry file formats: `.off`, `.obj`, `.stl`, `.wrl`.\n*   Simplification by successive edge collapse.\n*   Choose the direction of the changes to the mesh:\n    * Only expand the model (grow outward).\n    * Only shrink (grow inward).\n    * Closest approximation.\n*   Supports multiple algorithms to estimate the simplification error.\n*   Interactive GUI\n\nBounding convex decomposition:\n*   Generate a set of convex bodies to approximate a mesh\n*   Algorithms operate on a voxel representation\n*   Greedy splitting along axis-aligned planes (inspired by [V-HACD](https://github.com/kmammou/v-hacd))\n*   Make sure the convex bodies enclose the entire original mesh\n(in contrast to [V-HACD](https://github.com/kmammou/v-hacd) or other *approximate*\nconvex decomposition algorithms)\n\n### Publications\nFeel free to cite our publications:\n\n*   Andre K. Gaschler.\n[Efficient Geometric Predicates for Integrated Task and Motion Planning](http://www6.in.tum.de/Main/Publications/GaschlerPhd.pdf).\nDissertation, Technische Universität München, Munich, Germany, 2016\n*   Andre Gaschler, Quirin Fischer, and Alois Knoll.\n[The bounding mesh algorithm](http://www6.in.tum.de/Main/Publications/Gaschler2015d.pdf).\nTechnical Report TUM-I1522, Technische Universität München, Germany, June 2015.\n\n### Contribute\n\nPlease verify your change builds and tests successfully by\nrunning the docker build:\n\n```\ndocker build -f ubuntu18.Dockerfile .\n```\n\nThen, format syntax with\n`clang-format -style=Google -i src/**/**.cpp src/**/**.h`\nand create a pull request.\n\n### Screenshots\n\n#### GUI\n![The GUI interface.](https://github.com/gaschler/bounding-mesh/raw/master/images/ScreenshotGUI.png)\n\n![After some simplification.](https://github.com/gaschler/bounding-mesh/raw/master/images/ScreenshotGUIdecimated.png)\n\n#### Bounding Convex Decomposition\nOriginal model:\n![Original teapot model](https://github.com/gaschler/bounding-mesh/raw/master/images/teapot.png)\n\nConvex hull:\n![Convex hull](https://github.com/gaschler/bounding-mesh/raw/master/images/teapot_hull.png)\n\nVoxel set:\n![Voxelized model](https://github.com/gaschler/bounding-mesh/raw/master/images/teapot_voxelized.png)\n\nBounding convex decomposition:\n![Bounding convex decomposition](https://github.com/gaschler/bounding-mesh/raw/master/images/teapot_decomposed.png)\n\n### Example Models\n\nMultiple example meshes can be found in the directory `/examples/`. Simplified output files are named with a suffix `_decimated`.\n\nThe model in `/examples/bunny/` originates from [The Stanford 3D Scanning Repository](http://graphics.stanford.edu/data/3Dscanrep/).\n\n## Usage\n\n### License\nBoundingmesh itself is under the permissive 2-clause BSD license.\nHowever, it may use the following open source software libraries,\nwhich have other licenses: [Eigen](http://eigen.tuxfamily.org/),\n[EigenQP](https://github.com/wingsit/QP),\n[Coin3D](https://bitbucket.org/Coin3D/coin/wiki/Home),\n[Qt](https://www.qt.io/licensing/), [SOLID](http://dtecta.com/licence/index.html),\n[SoQt](https://bitbucket.org/Coin3D/soqt), [CGAL](http://www.cgal.org/license.html).\nPlease find their source code and licenses on their respective websites.\nBy default, EigenQP is compiled into Boundingmesh and LGPL applies unless\nyou deactivate the option `USE_EIGENQUADPROG`.\nFor instance, if you compile convex decomposition,\nCGAL components are linked whose GPL license applies to the rest of the code.\n\n### Installation\n\n#### Dependencies\nWe rely on the linear algebra library [Eigen](http://eigen.tuxfamily.org/) for most computations.  \nIf you perform loading of `.wrl` files, you also need the [Coin3D](https://bitbucket.org/Coin3D/coin/wiki/Home) toolkit.  \nThe included GUI application also requires __QT4__ and __SoQT4__.  \nThe modules involving convex bodies rely on [QHull](http://www.qhull.org/) and [CGAL](http://www.cgal.org/).\n\n#### Building from Source\nWe provide a CMake build file. We recommend building by\n\n    mkdir Release\n    cd Release\n    cmake ..\n    make\n\n#### Binaries\nWindows binaries may be included in the [releases](//github.com/gaschler/bounding-mesh/releases).\n\n### Command-Line Tools\n\n#### Bounding Mesh Simplification\nBounding meshes can be generated with a command-line executable. The interface is as follows:\n\n    ./boundingmesh [options] FilenameIn [FilenameOut]\n\n*   FileIn (required): The path of the mesh file thats is to be simplified. The filename extension has to indicate one of the supported file formats `.off`, `.obj`, `.stl` or `.wrl`. Loading `.wrl` files requires the Coin library to be available.\n*   FileOut (optional): The path where the resulting mesh will be stored. The filename extension determines the written format that has to be one of `.off`, `.obj`, `.stl` or `.wrl`. Defaults to `boundingmesh_[FileIn]`.\n\n*   --direction, -d: Direction of the simplification. `Inward`, `Outward` or `Any`.\n*   --vertices, -v: The target number of vertices. \n*   --error, -e: The maximum error an edge contraction may introduce.\n*   --metric, -m: The metric generation algorithm to be used. Available choices: `QEM_Classic`, `QEM_Modified`, `MinConstant`, `Diagonalization`, `Average`. \n*   --init, -i: The initialization algorithm of merge-based algorithms. Available choices: `Midpoint`, `DistancePrimitives`. \n*   --faceset: If the input format is .wrl, only the faceset with this number is loaded. Supply the index as an 0-indexed integer.\n*   --colored: If the output format is .wrl, disconnected submeshes will be assigned distinct colors. No arguments taken.\n\n#### Bounding Convex Decomposition\nBounding convex decompositions can be generated with the following command-line executable:\n\n    ./bounding-convex-decomposition [options] filename [filename_out.wrl]\n\n*   filename: Input file may be of type .off, .obj, .stl or .wrl\n*   --voxels, -x: Number of voxels to be used, a good value is 200000. Higher numbers increase quality and computation time.\n*   --alpha, -a: Parameter alpha, default is 1. Increases the number of splits into convex bodies.\n*   --error, -e: The maximum error that may be introduced by the bounding mesh post-processing step.\nRelative to the bounding box diagonal length. (Convex decomposition usually introduces a much\nhigher error than the bounding mesh approximation.)\n\n### GUI Application\n\nThe application providing the graphical user interface is built from the files located in`src/boundingmesh-gui/`. \nThe filenames of the binaries are respectively \n\n    ./boundingmesh-gui\n\nor \n    boundingmesh-gui.exe\n\nBuilding the boundingmesh software including the GUI requires the additional dependencies __Coin3, QT4, and SoQT4__ to be installed.\n\nThe GUI enables easy selection of the various decimation configurations. It shows the current mesh detail and allows interactive simplification. Contraction can be started for a single edge or batches of 100 or 5000 edges at a time. Furthermore, simplification down to a certain vertex count or error limit can be started.\n\n#### Linux Build\n\nMost build dependencies are available with the most common distributions.\nIn Ubuntu, you can install them with the command\n\n    sudo apt-get install build-essentials cmake-curses-gui libcoin60-dev libeigen3-dev libqt4-dev libqt4-opengl-dev libsoqt4-dev libqhull6 libqhull-dev\n\n#### Windows Build\n\nFor Windows, we recommend to find the required libraries\non the [Robotics Library Website](http://roboticslibrary.org).\nBoundingmesh requires a subset of the dependencies the \nRobotics Library requires, so the build instructions from there\napply to large extent.\n\n### Static Library\n\nBoundingmesh provides a static C++ library that can be used from other software.\n\nWe provide a central header:\n\n    #include \u003cboundingmesh.h\u003e\n\nThe build process will create the static library `libboundingmesh.a` to be linked against your program.\n\nA minimal example that loads a mesh from an `.off` file, simplifies it until it has 1000 or less vertices, and saves the result:\n\n    #include \u003cboundingmesh.h\u003e \n    int main(int argc, char** argv)\n    {\n        boundingmesh::Mesh mesh;\n        mesh.loadOff(\"mesh.off\");\n        boundingmesh::Decimator decimator;\n        decimator.setDirection(boundingmesh::Outward);\n        decimator.setTargetVertices(1000);\n        decimator.setMesh(mesh);\n        std::shared_ptr\u003cboundingmesh::Mesh\u003e result = decimator.compute();\n        result-\u003ewriteOff(\"mesh_simplified.off\");\n        return 0;\n    };\n\nThe following documentation describes the complete library and gives brief explanations of the provided functionality.\n\n## Code Guide\n\nThe following is a rough textual description of the control flow of the programs and algorithms. Hopefully it eases the familiarization with the codebase.\n\n### Data Structures\n\nThe primitives to represent 3D geometry are declared in [boundingmesh/Primitives.h](#boundingmeshprimitvesh). Vertices, edges and triangles all store their local neighbourhood. Referencing is always done through __Indices__ that are valid within the mesh.  \nFor example, assume you want to iterate through the adjacent vertices of one vertex. This is done by iterating over the adjacent triangles (their indices) and retrieving the triangle data to get the vertex indices.  \nMeshes can be loaded from a few file formats, which all extract vertex and triangle data encoded in some way. The vertices are added to the `Mesh` object and connected to form triangles. Vertex insertion is done through a proxy class `VertexPositionSet` which unifies vertices with equal coordinates (by checking if a vertex with the same coordinates exists).  \nRemoval of vertices, triangles... is deferred, marking the deleted objects until a call to `Mesh::cleanAndRenumber()` is made.\n\n### Mesh Decimation\n\nMesh decimation begins with the configuration of a `Decimator`. Besides setting parameters to select the error metric or the stopping criterion this also includes the selection of the mesh to process. This configuration prepares the decimation queue for the main algorithm by evaluating all edges of the mesh.  \nThe core decimation algorithm is located in `Decimator::compute()` and just repeatedly picks the best modification.  \nThe modification of the mesh is done in `Decimator::executeEdgeContraction()`. This method uses information about which parts have to be removed or reconnected collected in `Decimator::collectRemovalData()`.  \nThe scoring of contractions (and simultaneously the selection of inserted points) is done in `Decimator::computeEdgeContraction()` by minimizing cost functions. A cost function is represented by a matrix, which is computed in the [`MetricGenerator`](#boundingmeshmetricgeneratorh) class depending on the settings.\n\n### Convex Decomposition\n\nThe convex decomposition algorithm starts by rasterizing the mesh into a voxel model or `VoxelSet`.  \nThe voxel set is then repeatedly divided by collecting the voxels on the two sides of a plane into different subsets (methods `SegmenterSimple::compute()` and `VoxelSubset::partition()`).\nThe resulting subsets of voxels are then used to generate convex bodies, by collecting the points of the mesh that produced the voxels (method `VoxelSubset::calculateConvexHull()`).\n\n## Documentation\n\nThe whole library is contained in the namespace `boundingmesh`. Add it to your program by including `boundingmesh.h` and linking against `libboundingmesh.a`.  \nThe source code is written mostly conforming to the [Google C++ Style Guide](http://google-styleguide.googlecode.com/svn/trunk/cppguide.xml).\n\n### Command-line tool\n####`boundingmesh-bin/main.cpp`\n\n`int main(int argc, char** argv)`  \nReads the given arguments and adds default arguments if needed. Then the used file formats are determined and the input file loaded. The mesh is simplified and finally the results are written to the specified file.\n\n`FileFormat getFileFormat(std::string filename)`  \nDetermines the file format by extracting and matching the file extension.\n\n`enum FileFormat`  \nRepresentation of a parsed file format.\n\n`option::ArgStatus checkDirection(const option::Option\u0026 option, bool msg)`  \n`option::ArgStatus checkInt(const option::Option\u0026 option, bool msg)`  \n`option::ArgStatus checkFloat(const option::Option\u0026 option, bool msg)`  \nCallback functions for the option parser.\n\n### Graphical User Interface\n#### `boundingmesh-gui/gui.h`\n\n##### `class MainWindow`\nThe main window of the application, implemented using Qt. Keeps all the stateful GUI fields and \ndeclares callback functions for active components.\n\n*   `MainWindow(QWidget* parent, QApplication* app)`  \n    Sets up all the elements of the GUI and connects the appropriate callbacks.\n\n*   `void loadView()`  \n    Used to show a new model. Initializes the library, resets error values and displays the new mesh.\n\n*   `void reload()`  \n    Updates current vertex count and error. Also recalculates the recommendation fields and checks button states.\n\n##### `class CustomLineEdit`\nModified LineEdit that inserts a default value when empty.\n\n#### `boundingmesh-gui/ViewerMesh.h`\n##### `class ViewerMesh`\nConverts the data of a `boundingmesh::Mesh` into a Coin scene graph for display.\n\n*   `void replaceByMesh(const boundingmesh::Mesh *mesh)`  \n    Swaps the displayed mesh for a new one.\n\n### Core Library\n#### `boundingmesh/boundingmesh.h`\n\nMain header file of the library. Collects the other top-level headers.\n\n#### `boundingmesh/Primitives.h`\n\nDefinition of the geometric primitives used to construct meshes. The linear algebra library [Eigen](http://eigen.tuxfamily.org/) is used to represent mathematical objects and perform computations.\n\nThe geometric primitives provide no writing access to ensure the consistency of mesh data.\n\n`typedef ... Real`  \n Representation of a real number.\n\n`typedef ... Vector3`  \nA three dimensional vector.\n\n`typedef ... Vector4`  \nA 4D-vector used for homogeneous coordinates.\n\n`typedef ... Matrix44`  \nA 4x4 matrix.\n\n`typedef ... Index`  \nAn index referencing another geometric object. The type of the object and the underlying collection always depend on the context.\n\n##### `class Plane`  \nRepresentation of a plane in 3D space.\n\n*   `Plane()`  \n    Create an empty plane. Normal and d are initialized to zero.\n*   `Plane(Vector3\u0026 normal, Real d)`  \n    Define a plane using it's normal vector and the parameter d. \n*   `Plane(Vector3\u0026 normal, Vector3\u0026 point)`  \n    Define a plane using it's normal vector and a point on the plane. \n*   `Plane(Vector3 point1, Vector3 point2, Vector3 point3)`  \n    Construct a plane from three points. The orientation of the plane depends on the order of the given points; the normal is computed as the cross product of the positions of point2 and point3 relative to point 1.\n\n*   `Vector3 normal`  \n    The plane's normal vector.\n*   `Real d`  \n    Parameter for the plane equation. Points `x` on the plane satisfy `x*normal + d = 0`.\n\n*   `Real distance(const Vector\u0026 point) const`  \n    Computes the signed distance from `point` to the plane.\n*   `Vector4 vector() const`  \n    Returns the representation of the plane as a 4D-Vector.\n*   `Matrix44 distanceMatrix() const`  \n    Returns a matrix to compute the squared distance to the plane.\n\n##### `class Vertex`\nA vertex of a mesh. Contains references to all neighbouring triangles and edges.\n\n*   `Vertex()`  \n    Creates an empty vertex. Position initializes to zero.\n*   `Vertex(Vector3 position)`  \n    Creates a vertex at `position`. \n*   `Vertex(Real x, Real y, Real z)`  \n    Creates a vertex from three coordinates.\n\n*   `Vector3 position() const`  \n    Getter for the 3D position.\n\n*   `unsigned int nTriangles() const`  \n    Number of triangles containing the vertex.\n*   `unsigned int nEdges() const`  \n    Number of edges containing the vertex.\n\n*   `Index triangle(unsigned int i) const`  \n    Returns the ith triangle containing the vertex.\n*   `Index edge(unsigned int i) const`  \n    Returns the ith edge containing the vertex.\n\n##### `class Edge`\nAn edge of a mesh. Contains references to it's endpoints and the triangles it is part of. The references to the endpoints are always stored ordered to satisfy `vertex_1 \u003c vertex_2`.\n\n*   `Edge()`  \n    Creates an empty edge.\n*   `Edge(Index vertex_1, Index vertex_2)`  \n    Creates an edge connecting `vertex_1` and `vertex_2`.\n\n*   `unsigned int nTriangles() const`  \n    Returns the number of triangles containing the edge.\n*   `bool border() const`  \n    A flag indicating whether the edge lies on the border of the mesh.\n\n*   `Index vertex(unsigned int i) const`  \n    Returns the ith endpoint of the edge. `i` may only be `0` or `1`. \n*   `Index triangle(unsigned int i) const`  \n    Returns the ith triangle the edge is part of. `i` may be `0` or `1`. If `border()` is true, `i` may be only `0`.\n\n\n##### `class Triangle`\nA triangle of a mesh. Keeps references of it's vertices and edges. Also provides the plane containing the triangle in space.\n\n*   `Triangle()`  \n    Creates an empty triangle.\n*   `Triangle(Index vertex_1, Index vertex_2, Index vertex_3)`  \n    Creates a triangle with vertices `vertex_1`, `vertex_2`, `vertex_3`.\n\n*   `Index vertex(unsigned int i) const`  \n    Returns the ith vertex of the triangle. `i` may be `0`, `1` or `2`.\n*   `Index edge(unsigned int i) const`  \n    Returns the ith edge of the triangle. `i` may be `0`, `1` or `2`.\n\n*   `Plane plane() const`  \n    Returns the plane spanned by the triangles vertices.\n\n#### `boundingmesh/Mesh.h`\n\n##### `class VertexPosition`\nHelper class to efficiently find indices of vertices that were added to the mesh.\n\n*   `VertexPosition(Vector3 position)`  \n    Creates a vertex without specifying it's index. Used to find the indexed vertex with the same position.\n*   `VertexPosition(Index index, Vector3 position)`  \n    Creates a new vertex with it's index in the mesh.\n\n*   `Index index() const`  \n    Returns the index of the vertex.\n\n*   `friend bool operator\u003c(const VertexPosition \u0026 lhs, const VertexPosition \u0026 rhs)`  \n    `friend bool operator\u003e(const VertexPosition \u0026 lhs, const VertexPosition \u0026 rhs)`  \n    Compares two vertices by their position, component-by-component. \n\n##### `class VertexPositionSet`\nHelper class to add vertices to a mesh by position. Efficiently finds the index if a vertex with the given position already exists.\n\n*   `VertexPositionSet(Mesh\u0026 mesh)`  \n    Creates an empty set.\n\n*   `Index addVertex(Vector3 position)`  \n    Adds a vertex with the given position and returns it's index. If there already exists a vertex on the position, it's index is returned.\n\n##### `class Mesh`\nA triangle mesh. Stores it's vertices, edges and triangles. Meshes can be changed by adding and removing vertices or triangles. Load/Save methods for some file formats are provided.\n\n###### Construction\n\n*   `Mesh()`  \n    Creates an empty mesh.\n*   `Mesh(const std::vector\u003cVector\u003e\u0026 vertices,const std::vector\u003cIndex*\u003e\u0026 triangles)`  \n    Construct a mesh from a list of vertex positions and a list of index 3-tuples defining the triangles.\n\n*   `void loadOff(const std::string filename)`  \n    `void loadObj(const std::string filename)`  \n    `void loadStl(const std::string filename)`  \n    `void loadWrl(const std::string filename)`  \n    Loads mesh data from a file. `loadWrl` requires the Coin library.\n\n*   `void writeOff(const std::string filename)`  \n    `void writeObj(const std::string filename)`  \n    `void writeStl(const std::string filename)`  \n    `void writeWrl(const std::string filename)`  \n    Saves mesh data to a file.\n\n###### Getter\n\n*   `unsigned int nVertices() const`  \n    Returns the total number of vertices.\n*   `unsigned int nEdges() const`  \n    Returns the total number of Edges.\n*   `unsigned int nTriangles() const`  \n    Returns the total number of triangles.\n\n*   `const Vertex\u0026 vertex(Index i) const`  \n    Returns the ith vertex of the mesh.\n*   `const Edge\u0026 edge(Index i) const`  \n    Returns the ith edge of the mesh.\n*   `const Triangle\u0026 triangle(Index i) const`  \n    Returns the ith triangle of the mesh.\n\n*   `bool isDirty()`  \n    Can be used to check if the current mesh state is currently dirty because of removal actions. \n    If it is, call `void cleanAndRenumber()` before iterating over geometric objects.\n\n###### Modification\n\n*   `Index addVertex(const Vector3\u0026 vertex)`  \n    Adds a new vertex to the mesh.\n*   `Index addTriangle(Index vertex1, Index vertex2, Index vertex3)`  \n    Adds a new triangle to the mesh. Requires the three given indices to be valid.\n\nRemoval methods keep the mesh consistent, removing all references to the deleted object and deleting\nempty objects (i.e. edges whose triangles were removed). Be careful when accessing the mesh data after removal \nas they leave the mesh in a dirty state.\n\n*   `void removeVertex(Index vertex)`  \n    Removes a vertex (and all triangles containing it) from the mesh.\n*   `void removeTriangle(Index triangle)`  \n    Removes a triangle from the mesh. \n\n###### Helper Methods (internal)\nThese methods are only used internally.\n\n*   `void clean()`  \n    Resets the mesh to an empty state.\n*   `Index registerEdge(Index vertex1, Index vertex2, Index triangle)`  \n    Registers a new edge within the mesh.\n*   `void cleanAndRenumber()`  \n    Perfoms the deferred removal of vertices and triangles. A call to `removeVertex()` or `removeTriangle()` only marks them for later removal and removes all references to the index from the mesh. `cleanAndRenumber()` removes the data and calculates new indices.\n\n*   `std::vector\u003cstd::shared_ptr\u003cMesh\u003e \u003e computeSubmeshes()`  \n    Partitions the mesh graph, every connected component is a submesh. \n\n###### Static methods\n*   `void writeMultimeshWrl(std::vector\u003cstd::shared_ptr\u003cMesh\u003e \u003esubmeshes, std::string filename, bool colored = false)`  \n    Create a VRML file containing multiple meshes.\n*   `static Vector3 HSVtoRGB(Vector3 color)`  \n    Transformation from HSV to RGB color space.\n*   `static std::vector\u003cVector3\u003e generateColors(int n)`  \n    Generate `n` distinct colors.\n\n#### `boundingmesh/ContractionUtils.h`\nData structures used in the edge contraction algorithm.\n\n##### `class EdgeContraction`\nStores information for the contraction of an edge.\n\n*   `EdgeContraction(Index edge, Vector new_point, Real cost, const Matrix\u0026 qem)`  \n    Stores the contraction data for the edge with index `edge`: The resulting point after contraction, the cost of the introduced error and the QEM matrix of the new point.\n\n*   `Index edge() const`  \n    Returns the index of the edge to be contracted.\n*   `Vector new_point() const`  \n    Returns the position of the new point that will be inserted into the mesh instead. \n*   `Real cost() const`  \n    Returns the cost of the mesh change introduced by the contraction. \n*   `const Matrix44\u0026 qem() const`  \n    Returns the QEM matrix of the new point that will be used to measure mesh error.\n\n*   `friend bool operator\u003c(const EdgeContraction \u0026 lhs, const EdgeContraction \u0026 rhs)`  \n    `friend bool operator\u003e(const EdgeContraction \u0026 lhs, const EdgeContraction \u0026 rhs)`  \n    Compares two contractions by their cost.\n\n##### `class ContractionIndex`\nHelper class to access contractions in the `ContractionQueue` by edge index. \n\n*   `ContractionIndex(Index index)`  \n    Creates a contraction index containing only an edge index (but no iterator to a contraction). Used for finding the corresponding contraction.\n*   `ContractionIndex(Index index, std::set\u003cEdgeContraction\u003e::iterator contraction)`  \n    Creates a new contraction index from an edge index and the iterator of the corresponding contraction.\n\n*   `std::multiset\u003cEdgeContraction\u003e::iterator contraction() const`  \n    Returns the iterator of the contraction.\n\n*   `friend bool operator\u003c(const ContractionIndex \u0026 lhs, const ContractionIndex \u0026 rhs)`  \n*   `friend bool operator\u003e(const ContractionIndex \u0026 lhs, const ContractionIndex \u0026 rhs)`  \n    Compares two contraction indices by their edge index.\n\n##### `class ContractionQueue`\nContainer to efficiently add/remove contractions and retrieve the cheapest contraction.\n\n*   `ContractionQueue()`  \n    Creates an empty queue.\n\n*   `unsigned int size()`  \n    Returns the current size of the queue.\n*   `const EdgeContraction\u0026 first()`  \n    Returns a reference to the first contraction in the queue (the one with the lowest cost).\n\n*   `void insert(EdgeContraction contraction)`  \n    Inserts a contraction into the queue. Also internally creates the contraction index to access the contraction by edge index.\n*   `void remove(Index edge)`  \n    Removes the contraction of the edge with index `edge` from the queue.\n\n#### `boundingmesh/Decimator.h`\nContains all functionality for mesh simplification through edge contraction.\n\n##### `class Decimator`\nPerforms mesh simplification by edge decimation.\n\n###### Setup/Configuration\n\n*   `enum DecimationDirection`  \n    Options to control the direction of changes to the mesh. Values are `Outward`, `Inward` and `Any`.\n\n*   `Decimator()`  \n    Creates a decimator with the default configuration.\n*   `Decimator(int target_vertices, Real maximum_error, DecimationDirection direction)`  \n    Creates a decimator with a custom configuration. \n*   `void setTargetVertices(int target_vertices)`  \n    Changes the targeted number of vertices the output mesh should be made up of.\n*   `void setMaximumError(Real maximum_error)`  \n    Sets the maximum error by which the output may differ from the input mesh.\n*   `void setDirection(DecimationDirection direction)`  \n    Sets the allowed direction of changes to the mesh. The mesh may be decimated only outwards, only inwards or in any direction.\n\n###### Execution\n*   `Mesh* compute(const Mesh\u0026 mesh)`  \n    Simplifies the mesh according to the configuration. Returns a pointer to the resulting mesh.\n\t\n###### Submethods (internal)\n\n*   `void initialize()`  \n    Initializes the matrices to compute the error function and computes the initially possible contractions.\n*   `Matrix44 computeQEM(Index vertex)`  \n    Computes the quadratic error matrix used to evaluate the error function near the vertex with index `vertex`.\n*   `void executeEdgeContraction(EdgeContraction contraction)`  \n    Executes the edge contraction. Removes the referred edge, it's vertices and adjacent triangles. Then inserts the new point and connects it to the mesh.\n\n###### Decimation Computation (internal)\n\n*   `EdgeContraction computeEdgeContraction(Index edge_index)`  \n    Computes the new point and it's cost for contracting the edge with index `edge_index`.\n*   `unsigned int nSubsets(unsigned int subset_size, unsigned int total_size)`  \n    Calculates the number of `subset_size`-sized subsets of a set with `total_size` elements (the binomial coefficient).\n*   `void nextSubset(std::vector\u003cunsigned int\u003e\u0026 indices_subset,  unsigned int total_size)`  \n    Modifies the indices in `indices_subset` to iterate to the next subset of a `total_size`-sized set.\n\n*   `bool solveConstrainedMinimisation(const Matrix44\u0026 qem, const std::vector\u003cPlane\u003e\u0026 constraints,`  \n       ` const std::vector\u003cunsigned int\u003e\u0026 subset, Vector\u0026 result)`  \n    Minimizes the error function given by the matrix `qem` while satisfying the constraints defined by a subset of the plane set. Stores the solution in `result`.\n*   `Vector3 minimizeSubspace(const Matrix44\u0026 qadratic_cost)`  \n*   `Vector3 minimizeSubspace(const Matrix44\u0026 qadratic_cost, Plane plane)`  \n*   `Vector3 minimizeSubspace(const Matrix44\u0026 qadratic_cost, Plane plane1, Plane plane2)`  \n*   `Vector3 minimizeSubspace(const Matrix44\u0026 qadratic_cost, Plane plane1, Plane plane2, Plane plane3)`  \n    Minimizes the function specified by `quadratic_cost` with respect to 0-3 conditions. Solves in the subspace satisfying the constraints, then transforms back.\n*   `Vector3 minimizeLagrange(const Matrix44\u0026 qadratic_cost)`  \n*   `Vector3 minimizeLagrange(const Matrix44\u0026 qadratic_cost, Plane plane)`  \n*   `Vector3 minimizeLagrange(const Matrix44\u0026 qadratic_cost, Plane plane1, Plane plane2)`  \n*   `Vector3 minimizeLagrange(const Matrix44\u0026 qadratic_cost, Plane plane1, Plane plane2, Plane plane3)`  \n    Directly minimizes the function given by `quadratic_cost` with respect to 0-3 conditions using lagrange multipliers.\n\n#### `boundingmesh/MetricGenerator.h`\n##### `enum Metric`\nList of available metric generation algorithms provided by the `MetricGenerator`. Currently we support the following algorithms:  \n* `ClassicQEM`  \n* `ModifiedQEM`  \n* `MinimizedConstant`  \n* `Diagonalization`  \n* `MinimalMerge`  \n\n##### `class MetricGenerator`\nProduces quadratic error metrices for use by the Decimator. Allows selection of the desired metric.\n###### Initialization\n*   `void setMetric(Metric metric)`  \n    Select a generation algorithm.\n*   `void setInitialization(Initialization initialization)`  \n    Select the method a merge-based algorithm should use to generate the initial metrices for vertices.\n*   `void setMesh(Mesh* mesh)`  \n    Set the geometry that is being decimated.\n\n###### Interface to Decimator\n*   `Matrix44 getErrorMetric(Index edge_index)`  \n    Computes and returns the error metric for contracting a given edge.\n*   `void contractEdge(Index edge_index)`  \n    Updates metric data to account for the contraction of an edge.\n*   `void cleanAndRenumber()`  \n    Applies index changes caused by mesh cleanup to the metric data.\n\n###### General Internal Methods\n*   `void initialize()`  \n    Sets up the active generation algorithm for the current mesh. If a merging-based algorithm is used matrices are generated depending on the selected initialization method.\n*   `void shrinkIndexedArray(MatrixArray* array, std::stack\u003cIndex\u003e deleted_indices)`  \n    Removes all entries corresponding to indices on the stack from an array. Used for cleanup.\n\n###### ClassicQEM\n*   `Matrix44 computeQEM(esIndex vertex_index)`  \n\n###### ModifiedQEM\n*   `Matrix44 computeModifiedVertexQEM(Index vertex_index)`  \n*   `Matrix44 computeModifiedEdgeQEM(Index edge_index)`  \n*   `void contractEdgeModifiedQEM(Index edge_index)`  \n    Update all metric data according in reaction to a contraction.\n*   `void collectRemovalData(...)`  \n    Extract information about the neighbourhood of the contracted edge.\n\n###### Merging Based Algorithms\n*   `Matrix44 computeInitialMergeMetric(Index vertex_index)`  \n    Set up the initial error metric for a vertex\n*   `Matrix44 mergeMax(Matrix44 a, Matrix44 b)`\n    Merges two matrices so the result returns values greater or equal than the maximum of the evaluation of the input matrices.\n*   `Matrix44 mergeMatrices(Matrix44 a, Matrix44 b)`  \n    Merges two metrices according to the selected algorithm.\n*   `Matrix44 mergeMinConstant(Matrix44 a, Matrix44 b)`  \n    Implementation of MinimizedConstant merging. Addition of the matrices, minimization of the constant term.\n*   `Matrix44 mergeDiagonalization(Matrix44 a, Matrix44 b)`  \n    Implementation of Diagonalization merging. Computes a diagonal bound for each matrix, merges these.\n*   `Matrix44 mergeAverage(Matrix44 a, Matrix44 b)`  \n    Merges the matrices by computing their average.\n\n#### `boundingmesh/VoxelSet.h`\n##### `enum Metric`\nList of possible voxel types.\n* `INNER`: Added to fill the inner volume.  \n* `SURFACE`: A voxel generated by a triangle of the mesh.  \n\n##### `class Voxel`\nStores data for one voxel, currently position, type and triangles that created the voxel.\n\n###### Creation\n*   `Voxel(Index x, Index y, Index z, VoxelType type)`  \n    Create a voxel of certain type at some position. \n*   `void addTriangle(Index triangle)`  \n    Add a triangle to a vertain voxel.\n\n###### Getter Methods\n*   `Index x() const`  \n*   `Index y() const`  \n*   `Index z() const`  \n    Get the coordinates of the voxel's position.\n*   `Index coordinate(int dimension) const`  \n    Get the coordinate by dimension, 0-\u003eX, 1-\u003eY, 2-\u003eZ.\n*   `VoxelType type() const`  \n    Type of the voxel.\n*   `unsigned int nTriangles() const`  \n    Number of triangles intersecting the voxel.\n*   `Index triangle(unsigned int i) const`  \n    Returns the index of the ith triangle associated with the voxel.\n\n##### `class VoxelSet`\nA set of voxels, the equivalent of a mesh.\n###### Creation \n*   `VoxelSet(std::shared_ptr\u003cMesh\u003e triangle_mesh, Real voxel_size)`  \n    Creates a voxel set by rasterizing a mesh. The grid resolution is chosen according to the mesh size (it's bounding box) and the selected voxel size.\n\n###### Getters\n*   `unsigned int nVoxels() const`  \n*   `const Voxel\u0026 voxel(unsigned int i) const`  \n*   `const Vector3\u0026 origin() const`  \n*   `Real voxelSize() const`  \n*   `unsigned int resolution(int dimension) const`  \n*   `std::shared_ptr\u003cMesh\u003e mesh() const`  \n*   `int voxelAt(unsigned int x, unsigned int y, unsigned int z)`  \n*   `Vector3 computePosition(const Voxel\u0026 voxel) const`  \n\n###### Others\n*   `void addVoxel(const Voxel\u0026 voxel)`  \n    Add a voxel to the set.\n*   `void writeWRL(std::string filename)`  \n    Generate a VRML file to display the voxel set. Coloring dependent on voxel type.\n\n###### Internal data structures\n*   `std::vector\u003cVoxel\u003e voxels_`  \n    Set of all filled voxels.\n*   `std::vector\u003cint\u003e grid_`  \n    Field of size `resolution(0)*resolution(1)*resolution(2)`, storing the index of the voxel for a certain position.\n\n#### `boundingmesh/SegmenterSimple.h`\nClasses for the segmentation of a model into disjoint parts, especially for convex decomposition.\n\n##### `class Split`\nA splitting plane, currently axis aligned and at a voxel boundary.\n\n*   `Split(int dimension, int index)`  \n\n*   `int dimension`  \n    Dimension perpendicular to the split plane.\n*   `int index`  \n    Split between `index` and `index+1`.\n\n*   `bool test(const Voxel\u0026 voxel)`  \n    Classification of a voxel using the split. True if it's on the upper side of the split (greater coordinate than the split). \n\n##### `class AppliedSplit`\nInformation attached to a set after splitting. Stores the splitting plane and the side of this part.\n\n*   `AppliedSplit(Split\u0026 split, bool direction)`  \n\n*   `Split split`  \n    The corresponding split.\n*   `bool direction`  \n    Indicator which side of the plane was chosen.\n\n*   `Plane getPlane(const VoxelSet\u0026 voxel_set)`  \n    Mathematical plane of, oriented so that this subset lies on the front (distance \u003e 0).\n*   `static int mergeSplits(const AppliedSplit\u0026 a, const AppliedSplit\u0026 b)`  \n    Evaluation whether two splits can be merged (because one is a subset of the other).\n\n##### `class VoxelSubset`\nA subset of a voxelized mesh. Keeps a list of the voxels part of this subset and information about the splits made. A subset generates one convex body.\n\n###### Creation\n*   `VoxelSubset(std::shared_ptr\u003cVoxelSet\u003e voxels)`  \n    Creates an empty subset linked to a voxel set.\n*   `VoxelSubset(const VoxelSubset\u0026 subset, bool empty = false)`  \n    Creates a new subset by copying an existing one. Refine a subset by copying it, but removing the voxels(with set `empty` flag). Then add the voxels that fit your criteria.\n\n*   `void addVoxel(Index index)`  \n    Add a voxel to the subset.\n*   `void addSplit(AppliedSplit split)`  \n    Add a split that clips the subset.\n*   `void calculateConvexHull()`  \n    Compute the convex hull of the triangles associated with the subset. Clips triangles against the splits.\n\n###### Further partition\n*   `std::vector\u003cVoxelSubset\u003e partition(Split split)`  \n    Partition into two sets according to a split.\n*   `void setFinal()`  \n    Sets the flag to stop partitioning this set.\n\n###### Getter\n*   `Real convexVolume() const`  \n    Volume of the associated convex body.\n*   `Real volume() const`  \n    Volume of the geometry of the subset, approximated by the filled voxels.\n\n*   `std::shared_ptr\u003cMesh\u003e getConvexHull()`  \n    Get the mesh of the surface of the subsets convex hull.\n\n*   `bool isFinal()`  \n    Check whether the subset should be further split.\n\n##### `class SegmenterSimple`\n\n*   `SegmenterSimple(Real voxel_size)`\n    Create a segmenter, voxel_size will be used to rasterize the mesh.\n\n###### Configuration\n*   `void setMaxPasses(int passes)`  \n    Set the number of passes (iterations of splitting the subsets). \n*   `void setMinVolumeGain(Real min_gain)`  \n    Set the minimal improvement of the cost function that causes a partitioning.\n\n*   `void setMesh(std::shared_ptr \u003cMesh\u003e mesh)`  \n    Select the model to segment/decompose.\n\n###### Main algorithm\n*   `void compute()`  \n    Compute the segmentation of the mesh\n\n###### Results\n*   `std::vector\u003c std::shared_ptr\u003cMesh\u003e \u003e getSegmentation()`  \n    Get the convex meshes of the segmentation.\n\n####### Internal methods\n*   `std::vector\u003cSplit\u003e generateSplits(const VoxelSubset\u0026 subset)`  \n    Compute all possible splits that could partition a certain subset. They will will be evaluated and the one with the best rating is executed.\n*   `Real evaluatePartition(const VoxelSubset\u0026 previous_set, const std::vector\u003cVoxelSubset\u003e\u0026 partition)`  \n    Compute heuristic evaluation of previous set into a partition.\n*   `Real evaluateSubset(const VoxelSubset\u0026 subset)`  \n    Compute evaluation of a subset (currently normalized to 1).\n\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fgaschler%2Fbounding-mesh","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fgaschler%2Fbounding-mesh","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fgaschler%2Fbounding-mesh/lists"}