Skip to content

Commit

Permalink
add unit test for convex hull vertex order
Browse files Browse the repository at this point in the history
  • Loading branch information
gisogrimm committed Jul 5, 2024
1 parent 9763ad7 commit dc550f4
Show file tree
Hide file tree
Showing 3 changed files with 93 additions and 72 deletions.
77 changes: 7 additions & 70 deletions libtascar/src/coordinates.cc
Original file line number Diff line number Diff line change
Expand Up @@ -39,16 +39,10 @@
#include <string.h>
#include <vector>

#define QUICKHULL_1

#ifdef QUICKHULL_1
#include "quickhull/QuickHull.cpp"
#include "quickhull/QuickHull.hpp"

using namespace quickhull;
#else
#define CONVHULL_3D_ENABLE
#include "convhull_3d/convhull_3d.h"
#endif

using namespace TASCAR;

Expand Down Expand Up @@ -433,81 +427,24 @@ std::vector<pos_t> TASCAR::generate_icosahedron()
return m;
}

#ifdef QUICKHULL_1
uint32_t findindex2(const std::vector<Vector3<double>>& spklist,
const Vector3<double>& vertex)
{
for(uint32_t k = 0; k < spklist.size(); ++k)
if((spklist[k].x == vertex.x) && (spklist[k].y == vertex.y) &&
(spklist[k].z == vertex.z))
return k;
throw TASCAR::ErrMsg("Simplex index not found in list");
return (uint32_t)(spklist.size());
}

TASCAR::quickhull_t::quickhull_t(const std::vector<pos_t>& mesh)
TASCAR::quickhull_t::quickhull_t(const std::vector<pos_t>& vertices)
{
std::vector<Vector3<double>> spklist;
for(auto it = mesh.begin(); it != mesh.end(); ++it)
spklist.push_back(Vector3<double>(it->x, it->y, it->z));
for(const auto& vert : vertices)
spklist.push_back(Vector3<double>(vert.x, vert.y, vert.z));
QuickHull<double> qh;
auto hull = qh.getConvexHull(spklist, true, true);
auto indexBuffer = hull.getIndexBuffer();
if(indexBuffer.size() < 12)
throw TASCAR::ErrMsg("Invalid convex hull.");
auto vertexBuffer = hull.getVertexBuffer();
for(uint32_t khull = 0; khull < indexBuffer.size(); khull += 3) {
simplex_t sim;
sim.c1 = findindex2(spklist, vertexBuffer[indexBuffer[khull]]);
sim.c2 = findindex2(spklist, vertexBuffer[indexBuffer[khull + 1]]);
sim.c3 = findindex2(spklist, vertexBuffer[indexBuffer[khull + 2]]);
faces.push_back(sim);
}
}
#else

uint32_t findindex2(const std::vector<TASCAR::pos_t>& spklist,
const ch_vertex& vertex)
{
for(uint32_t k = 0; k < spklist.size(); ++k)
if((spklist[k].x == vertex.x) && (spklist[k].y == vertex.y) &&
(spklist[k].z == vertex.z))
return k;
throw TASCAR::ErrMsg("Simplex index not found in list");
return spklist.size();
}

TASCAR::quickhull_t::quickhull_t(const std::vector<pos_t>& mesh)
{
ch_vertex* vertices;
vertices = (ch_vertex*)malloc(mesh.size() * sizeof(ch_vertex));
size_t k(0);
for(auto it = mesh.begin(); it != mesh.end(); ++it) {
vertices[k].x = it->x;
vertices[k].y = it->y;
vertices[k].z = it->z;
++k;
}
int* faceIndices(NULL);
int nFaces(0);
convhull_3d_build(vertices, mesh.size(), &faceIndices, &nFaces);
for(int khull = 0; khull < nFaces; ++khull) {
simplex_t sim;
// sim.c1 = faceIndices[khull];
// sim.c2 = faceIndices[khull+nFaces];
// sim.c3 = faceIndices[khull+2*nFaces];
sim.c1 = faceIndices[3 * khull];
sim.c2 = faceIndices[3 * khull + 1];
sim.c3 = faceIndices[3 * khull + 2];
sim.c1 = findindex2(mesh, vertices[faceIndices[3 * khull]]);
sim.c2 = findindex2(mesh, vertices[faceIndices[3 * khull + 1]]);
sim.c3 = findindex2(mesh, vertices[faceIndices[3 * khull + 2]]);
sim.c1 = indexBuffer[khull];
sim.c2 = indexBuffer[khull + 1];
sim.c3 = indexBuffer[khull + 2];
faces.push_back(sim);
}
free(vertices);
free(faceIndices);
}
#endif

std::vector<pos_t> TASCAR::subdivide_and_normalize_mesh(std::vector<pos_t> mesh,
uint32_t iterations)
Expand Down
83 changes: 83 additions & 0 deletions libtascar/src/coordinates_unit_tests.cc
Original file line number Diff line number Diff line change
Expand Up @@ -831,6 +831,89 @@ TEST(quaternion, localeuler)
ASSERT_NEAR(0.0, p.z, 1e-7);
}

TEST(convhull, vertexorder)
{
std::vector<TASCAR::pos_t> th;
th.push_back(TASCAR::pos_t(1.0, 0.0, -sqrt(0.5)));
th.push_back(TASCAR::pos_t(-1.0, 0.0, -sqrt(0.5)));
th.push_back(TASCAR::pos_t(0.0, 1.0, sqrt(0.5)));
th.push_back(TASCAR::pos_t(0.0, -1.0, sqrt(0.5)));
ASSERT_EQ(4u, th.size());
{
auto hull = TASCAR::quickhull_t(th);
ASSERT_EQ(4u, hull.faces.size());
std::cout << "-- th --\n";
for(auto f : hull.faces)
std::cout << f.c1 << " " << f.c2 << " " << f.c3 << std::endl;
ASSERT_EQ(1u, hull.faces[0].c1);
ASSERT_EQ(0u, hull.faces[0].c2);
ASSERT_EQ(2u, hull.faces[0].c3);
ASSERT_EQ(2u, hull.faces[1].c1);
ASSERT_EQ(0u, hull.faces[1].c2);
ASSERT_EQ(3u, hull.faces[1].c3);
ASSERT_EQ(0u, hull.faces[2].c1);
ASSERT_EQ(1u, hull.faces[2].c2);
ASSERT_EQ(3u, hull.faces[2].c3);
ASSERT_EQ(1u, hull.faces[3].c1);
ASSERT_EQ(2u, hull.faces[3].c2);
ASSERT_EQ(3u, hull.faces[3].c3);
}
std::vector<TASCAR::pos_t> hex;
TASCAR::pos_t pos;
for(uint32_t k = 0; k < 6; ++k) {
double az = k * TASCAR_PI / 3.0;
pos.set_sphere(1.0, az, -TASCAR_PI / 4.0);
hex.push_back(pos);
}
pos.set_sphere(1.0, 0.0, TASCAR_PI / 2.0);
hex.push_back(pos);
ASSERT_EQ(7u, hex.size());
{
auto hull = TASCAR::quickhull_t(hex);
ASSERT_EQ(10u, hull.faces.size());
std::cout << "-- hex --\n";
for(auto f : hull.faces)
std::cout << f.c1 << " " << f.c2 << " " << f.c3 << std::endl;
ASSERT_EQ(3u, hull.faces[0].c1);
ASSERT_EQ(1u, hull.faces[0].c2);
ASSERT_EQ(2u, hull.faces[0].c3);
ASSERT_EQ(1u, hull.faces[1].c1);
ASSERT_EQ(6u, hull.faces[1].c2);
ASSERT_EQ(2u, hull.faces[1].c3);
ASSERT_EQ(6u, hull.faces[2].c1);
ASSERT_EQ(3u, hull.faces[2].c2);
ASSERT_EQ(2u, hull.faces[2].c3);
ASSERT_EQ(3u, hull.faces[3].c1);
ASSERT_EQ(6u, hull.faces[3].c2);
ASSERT_EQ(4u, hull.faces[3].c3);
ASSERT_EQ(6u, hull.faces[4].c1);
ASSERT_EQ(5u, hull.faces[4].c2);
ASSERT_EQ(4u, hull.faces[4].c3);
ASSERT_EQ(5u, hull.faces[5].c1);
ASSERT_EQ(3u, hull.faces[5].c2);
ASSERT_EQ(4u, hull.faces[5].c3);
ASSERT_EQ(0u, hull.faces[6].c1);
ASSERT_EQ(3u, hull.faces[6].c2);
ASSERT_EQ(5u, hull.faces[6].c3);
ASSERT_EQ(6u, hull.faces[7].c1);
ASSERT_EQ(0u, hull.faces[7].c2);
ASSERT_EQ(5u, hull.faces[7].c3);
ASSERT_EQ(0u, hull.faces[8].c1);
ASSERT_EQ(6u, hull.faces[8].c2);
ASSERT_EQ(1u, hull.faces[8].c3);
ASSERT_EQ(3u, hull.faces[9].c1);
ASSERT_EQ(0u, hull.faces[9].c2);
ASSERT_EQ(1u, hull.faces[9].c3);
// for(size_t k = 0; k < hull.faces.size(); ++k) {
// auto f = hull.faces[k];
// std::cout << "ASSERT_EQ(" << f.c1 << "u,hull.faces[" << k <<
// "].c1);\n"; std::cout << "ASSERT_EQ(" << f.c2 << "u,hull.faces[" <<
// k << "].c2);\n"; std::cout << "ASSERT_EQ(" << f.c3 <<
// "u,hull.faces[" << k << "].c3);\n";
// }
}
}

// Local Variables:
// compile-command: "make -C ../.. unit-tests"
// coding: utf-8-unix
Expand Down
5 changes: 3 additions & 2 deletions test/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -135,17 +135,18 @@ test_snd_door4: RMSTOL=1e-4
#test_level_hoa3d_allrad: LEVTHR=2.7
# test_snd_hoa3d_allrad_hor test_snd_hoa3d_allrad_vert
# test_level_hoa3d_allrad_lidhan test_level_hoa3d_allrad
# test_snd_hoa3d_allrad_hor test_snd_hoa3d_allrad_hor

ifeq ($(UNAME_S),Linux)
hoa3d: test_snd_hoa3d_allrad_hor test_snd_hoa3d_enc_hor \
hoa3d: test_snd_hoa3d_enc_hor \
test_snd_hoa3d_enc_vert test_snd_hoa3d_pinv_hor \
test_snd_hoa3d_pinv_vert test_level_hoa3d_pinv \
test_level_hoa3d_pinv_lidhan test_level_hoa3d_pinv_maxre \
test_level_hoa3d_pinv_lidhan_maxre \
test_level_hoa3d_pinv_lidhan45_maxre \
test_level_hoa3d_pinv_lidhan45sub_maxre
else
hoa3d: test_snd_hoa3d_allrad_hor test_snd_hoa3d_enc_hor \
hoa3d: test_snd_hoa3d_enc_hor \
test_snd_hoa3d_enc_vert test_snd_hoa3d_pinv_hor \
test_snd_hoa3d_pinv_vert test_level_hoa3d_pinv \
test_level_hoa3d_pinv_lidhan test_level_hoa3d_pinv_maxre \
Expand Down

0 comments on commit dc550f4

Please sign in to comment.