Skip to content

File DensitySampler.cpp

File List > algos > mesh_to_pointcloud > DensitySampler.cpp

Go to the documentation of this file

#include "mesh_to_pointcloud/DensitySampler.h"

namespace Argos {

    PointCloud DensitySampler::sample(const Mesh& mesh)
    {
        PointCloud cloud;

        const auto& faces = mesh.getFaces();
        const auto& vertices = mesh.getVertices();

        if (faces.empty())
            return cloud;

        std::size_t faceCount = faces.size();

        for (std::size_t f = 0; f < faceCount; ++f)
        {

            const Face& face = faces[f];
            const auto& indices = face.getIndices();

            if (indices.size() < 3)
                continue;

            std::size_t indices_size = indices.size();

            for (std::size_t i = 1; i < indices_size - 1; ++i)
            {
                auto ia = indices[0];
                auto ib = indices[i];
                auto ic = indices[i + 1];

                if (ia >= vertices.size() || ib >= vertices.size() || ic >= vertices.size())
                    continue; //

                const auto& A = vertices[ia];
                const auto& B = vertices[ib];
                const auto& C = vertices[ic];

                auto AB = B - A;
                auto AC = C - A;

                double area = 0.5 * (AB ^ AC).norm();

                if (area <= 0.0)
                    continue;

                double expected = m_density * area;

                std::size_t pointCount = static_cast<std::size_t>(expected);
                double remainder = expected - pointCount;

                double r = static_cast<double>(std::rand()) / static_cast<double>(RAND_MAX);
                if (r < remainder)
                    pointCount++;

                for (std::size_t j = 0; j < pointCount; j++) {
                    double u = static_cast<double>(std::rand()) / RAND_MAX;
                    double v = static_cast<double>(std::rand()) / RAND_MAX;

                    if (u + v > 1.0) {
                        u = 1.0 - u;
                        v = 1.0 - v;
                    }

                    double alpha = 1.0 - u - v;
                    double beta = u;
                    double gamma = v;

                    auto P = A * alpha + B * beta + C * gamma;

                    cloud.addPoint(P);
                }
            }
        }

        return cloud;
    }

}