LVR API (examples)

In addition to several tools, LVR features an API to enable users writing their own mesh algorithms and work with meshes in general. Most of the API is well documented, so you should generate and read that documentation to really understand how to work with LVR. To get started, this pages features several common examples.  

Reconstructing a point cloud

Creating a mesh from a point cloud is a pretty complex process with many parameters. To see the full code, take a look at 'src/tools/reconstruct2/Main.cpp'. This file performs a reconstruction and sets all possible parameters. But you most likely won't need to use all parameters, so here is a simplified version:

You first need to load your point cloud in the form of a 'PointSetSurface'. This is an interface which describes classes that manage points. LVR features different implementations with different search trees. Choose one which best suits your needs. Next, you need to create a 'FastReconstructionBase' which is an interface describing different reconstruction algorithms. Again, LVR features several different algorithms and you need to choose one best fitting your requirements. Finally, you can call 'getMesh()' to reconstruct the mesh.

This could look like this:

auto pointSetSurface = loadPointCloud("scan.pts");
auto reconstruction = createReconstruction(pointSetSurface);

HalfEdgeMesh<Vec> mesh;
reconstruction->getMesh(mesh);

Executing mesh algorithms

Most of the time, you want to enhance the mesh after reconstruction. LVR offers some algorithms to help with that.

For example, you can simply reduce the complexity of your mesh (decreasing the number of faces) with the 'simpleMeshReduction()' algorithm:

#include <algorithms/ReductionAlgorithms.hpp>
#include <algorithms/NormalAlgorithms.hpp>

// ...

reconstruction->getMesh(mesh);

auto faceNormals = calcFaceNormals(mesh);
simpleMeshReduction(mesh, 100, faceNormals);

The above code will first calculate the face normals and then simplify the mesh by collapsing up to 100 edges (each edge collapse generally removes one face).

Writing your own mesh algorithm

To write your own algorithm, you should get familiar with the 'BaseMesh' API and attribute maps (see documentation).

As an example, suppose you want to assign a grey value to each faces, depending on its orientation (up or down). A possible implementation looks like this:

template<typename BaseVecT>
DenseFaceMap<float> faceGreyValue(
    const BaseMesh<BaseVecT>& mesh, 
    const FaceMap<Normal<BaseVecT>>& faceNormals
)
{
    DenseFaceMap<float> greyValues;
    greyValues.reserve(mesh.nextFaceIndex());

    // Iterate over all faces.
    for (auto fH: mesh.faces())
    {
        // A face pointing up should be white, a face point down should be
        // black. We normalize the value to be in the range 0 to 1.
        auto greyValue = (faceNormals[fH].getZ() + 1) / 2;

        // Here we insert the value into the map associated with the face we
        // are currently looking at.
        greyValues.insert(fH, greyValue);
    }

    return greyValues;
}

Storing your mesh into a file

You usually want to store the resulting mesh somewhere. The LVR IO interface can store meshes in different formats.

To write a mesh to file, you have to use a finalizer. A finalizer class takes the mesh and a bunch of attribute maps and stores everything in a file. See the documentation in 'algorithms/FinalizeAlgorithms.hpp' for more information. As an example on how to use such a finalizer class, see 'src/tools/reconstruct2/Main.cpp'.