Program Listing for File BoundingSphereHierarchy.cpp

Return to documentation for file (Simulation/BoundingSphereHierarchy.cpp)

#include "BoundingSphereHierarchy.h"

#include <iostream>
#include <unordered_set>
#include <set>

using namespace Eigen;
using pool_set = std::set<unsigned int>;
using namespace PBD;


PointCloudBSH::PointCloudBSH()
    : super(0, 10)
{
}

Vector3r const& PointCloudBSH::entity_position(unsigned int i) const
{
    return m_vertices[i];
}

void PointCloudBSH::compute_hull(unsigned int b, unsigned int n, BoundingSphere& hull) const
{
    auto vertices_subset = std::vector<Vector3r>(n);
    for (unsigned int i=b; i < b+n; ++i)
        vertices_subset[i-b] = m_vertices[m_lst[i]];

    const BoundingSphere s(vertices_subset);

    hull.x() = s.x();
    hull.r() = s.r();
}

void PointCloudBSH::compute_hull_approx(unsigned int b, unsigned int n, BoundingSphere& hull) const
{
    // compute center
    Vector3r x;
    x.setZero();
    for (unsigned int i = b; i < b+n; i++)
        x += m_vertices[m_lst[i]];
    x /= (Real)n;

    Real radius2 = 0.0;
    for (unsigned int i = b; i < b+n; i++)
    {
        radius2 = std::max(radius2, (x - m_vertices[m_lst[i]]).squaredNorm());
    }

    hull.x() = x;
    hull.r() = sqrt(radius2);
}

void PointCloudBSH::init(const Vector3r *vertices, const unsigned int numVertices)
{
    m_lst.resize(numVertices);
    m_vertices = vertices;
    m_numVertices = numVertices;
}



TetMeshBSH::TetMeshBSH()
    : super(0)
{
}

Vector3r const& TetMeshBSH::entity_position(unsigned int i) const
{
    return m_com[i];
}

void TetMeshBSH::compute_hull(unsigned int b, unsigned int n, BoundingSphere& hull) const
{
    compute_hull_approx(b, n, hull);
}

void TetMeshBSH::compute_hull_approx(unsigned int b, unsigned int n, BoundingSphere& hull) const
{
    // compute center
    Vector3r x;
    x.setZero();
    for (unsigned int i = b; i < b + n; i++)
    {
        const unsigned int tet = m_lst[i];
        x += m_vertices[m_indices[4 * tet]];
        x += m_vertices[m_indices[4 * tet + 1]];
        x += m_vertices[m_indices[4 * tet + 2]];
        x += m_vertices[m_indices[4 * tet + 3]];
    }
    x /= ((Real)4.0* (Real)n);

    Real radius2 = 0.0;
    for (unsigned int i = b; i < b + n; i++)
    {
        const unsigned int tet = m_lst[i];
        radius2 = std::max(radius2, (x - m_vertices[m_indices[4 * tet]]).squaredNorm());
        radius2 = std::max(radius2, (x - m_vertices[m_indices[4 * tet+1]]).squaredNorm());
        radius2 = std::max(radius2, (x - m_vertices[m_indices[4 * tet+2]]).squaredNorm());
        radius2 = std::max(radius2, (x - m_vertices[m_indices[4 * tet+3]]).squaredNorm());
    }

    hull.x() = x;
    hull.r() = sqrt(radius2) + m_tolerance;
}

void TetMeshBSH::init(const Vector3r *vertices, const unsigned int numVertices, const unsigned int *indices, const unsigned int numTets, const Real tolerance)
{
    m_lst.resize(numTets);
    m_vertices = vertices;
    m_numVertices = numVertices;
    m_indices = indices;
    m_numTets = numTets;
    m_tolerance = tolerance;
    m_com.resize(numTets);
    for (unsigned int i = 0; i < numTets; i++)
    {
        m_com[i] = 0.25 * (m_vertices[m_indices[4*i]] + m_vertices[m_indices[4*i+1]] + m_vertices[m_indices[4*i+2]] + m_vertices[m_indices[4*i+3]]);
    }
}

void TetMeshBSH::updateVertices(const Vector3r* vertices)
{
    m_vertices = vertices;
}


void BVHTest::traverse(PointCloudBSH const& b1, TetMeshBSH const& b2, TraversalCallback func)
{
    traverse(b1, 0, b2, 0, func);
}

void BVHTest::traverse(PointCloudBSH const& b1, const unsigned int node_index1, TetMeshBSH const& b2, const unsigned int node_index2, TraversalCallback func)
{
    const BoundingSphere &bs1 = b1.hull(node_index1);
    const BoundingSphere &bs2 = b2.hull(node_index2);
    if (!bs1.overlaps(bs2))
        return;

    auto const& node1 = b1.node(node_index1);
    auto const& node2 = b2.node(node_index2);
    if (node1.is_leaf() && node2.is_leaf())
    {
        func(node_index1, node_index2);
        return;
    }

    if (bs1.r() < bs2.r())
    {
        if (!node1.is_leaf())
        {
            traverse(b1, node1.children[0], b2, node_index2, func);
            traverse(b1, node1.children[1], b2, node_index2, func);
        }
        else
        {
            traverse(b1, node_index1, b2, node2.children[0], func);
            traverse(b1, node_index1, b2, node2.children[1], func);
        }
    }
    else
    {
        if (!node2.is_leaf())
        {
            traverse(b1, node_index1, b2, node2.children[0], func);
            traverse(b1, node_index1, b2, node2.children[1], func);
        }
        else
        {
            traverse(b1, node1.children[0], b2, node_index2, func);
            traverse(b1, node1.children[1], b2, node_index2, func);
        }
    }

}