update to the latest version of HACD (hierarchical approximate convex decomposition, http://sourceforge.net/projects/hacd)
Thanks to Khaled Mammou for the fix.
This commit is contained in:
@@ -34,6 +34,7 @@ namespace HACD
|
||||
{
|
||||
m_convexHull = 0;
|
||||
m_name = -1;
|
||||
m_cc = -1;
|
||||
m_error = 0;
|
||||
m_surf = 0;
|
||||
m_perimeter = 0;
|
||||
@@ -57,6 +58,7 @@ namespace HACD
|
||||
{
|
||||
m_nV = 0;
|
||||
m_nE = 0;
|
||||
m_nCCs = 0;
|
||||
}
|
||||
|
||||
Graph::~Graph()
|
||||
@@ -78,7 +80,7 @@ namespace HACD
|
||||
{
|
||||
size_t name = m_vertices.size();
|
||||
m_vertices.resize(name+1);
|
||||
m_vertices[name].m_name = name;
|
||||
m_vertices[name].m_name = static_cast<long>(name);
|
||||
m_nV++;
|
||||
return static_cast<long>(name);
|
||||
}
|
||||
@@ -87,11 +89,11 @@ namespace HACD
|
||||
{
|
||||
size_t name = m_edges.size();
|
||||
m_edges.push_back(GraphEdge());
|
||||
m_edges[name].m_name = name;
|
||||
m_edges[name].m_name = static_cast<long>(name);
|
||||
m_edges[name].m_v1 = v1;
|
||||
m_edges[name].m_v2 = v2;
|
||||
m_vertices[v1].AddEdge(name);
|
||||
m_vertices[v2].AddEdge(name);
|
||||
m_vertices[v1].AddEdge(static_cast<long>(name));
|
||||
m_vertices[v2].AddEdge(static_cast<long>(name));
|
||||
m_nE++;
|
||||
return static_cast<long>(name);
|
||||
}
|
||||
@@ -236,5 +238,55 @@ namespace HACD
|
||||
m_nV = 0;
|
||||
m_nE = 0;
|
||||
}
|
||||
|
||||
|
||||
long Graph::ExtractCCs()
|
||||
{
|
||||
// all CCs to -1
|
||||
for (size_t v = 0; v < m_vertices.size(); ++v)
|
||||
{
|
||||
if (!m_vertices[v].m_deleted)
|
||||
{
|
||||
m_vertices[v].m_cc = -1;
|
||||
}
|
||||
}
|
||||
|
||||
// we get the CCs
|
||||
m_nCCs = 0;
|
||||
long v2 = -1;
|
||||
std::vector<long> temp;
|
||||
for (size_t v = 0; v < m_vertices.size(); ++v)
|
||||
{
|
||||
if (!m_vertices[v].m_deleted && m_vertices[v].m_cc == -1)
|
||||
{
|
||||
m_vertices[v].m_cc = static_cast<long>(m_nCCs);
|
||||
temp.clear();
|
||||
temp.push_back(m_vertices[v].m_name);
|
||||
while (temp.size())
|
||||
{
|
||||
long vertex = temp[temp.size()-1];
|
||||
temp.pop_back();
|
||||
std::set<long>::const_iterator ed(m_vertices[vertex].m_edges.begin());
|
||||
std::set<long>::const_iterator itEnd(m_vertices[vertex].m_edges.end());
|
||||
for(; ed != itEnd; ++ed)
|
||||
{
|
||||
if (m_edges[*ed].m_v1 == vertex)
|
||||
{
|
||||
v2 = m_edges[*ed].m_v2;
|
||||
}
|
||||
else
|
||||
{
|
||||
v2 = m_edges[*ed].m_v1;
|
||||
}
|
||||
if ( !m_vertices[v2].m_deleted && m_vertices[v2].m_cc == -1)
|
||||
{
|
||||
m_vertices[v2].m_cc = static_cast<long>(m_nCCs);
|
||||
temp.push_back(v2);
|
||||
}
|
||||
}
|
||||
}
|
||||
m_nCCs++;
|
||||
}
|
||||
}
|
||||
return static_cast<long>(m_nCCs);
|
||||
}
|
||||
}
|
||||
@@ -42,6 +42,7 @@ namespace HACD
|
||||
~GraphVertex(){ delete m_convexHull;};
|
||||
private:
|
||||
long m_name;
|
||||
long m_cc;
|
||||
std::set<long> m_edges;
|
||||
bool m_deleted;
|
||||
std::vector<long> m_ancestors;
|
||||
@@ -100,12 +101,14 @@ namespace HACD
|
||||
long GetEdgeID(long v1, long v2) const;
|
||||
void Clear();
|
||||
void Print() const;
|
||||
long ExtractCCs();
|
||||
|
||||
Graph();
|
||||
virtual ~Graph();
|
||||
void Allocate(size_t nV, size_t nE);
|
||||
|
||||
private:
|
||||
size_t m_nCCs;
|
||||
size_t m_nV;
|
||||
size_t m_nE;
|
||||
std::vector<GraphEdge> m_edges;
|
||||
|
||||
@@ -20,6 +20,7 @@
|
||||
#include <string.h>
|
||||
#include <algorithm>
|
||||
#include <iterator>
|
||||
#include <limits>
|
||||
|
||||
namespace HACD
|
||||
{
|
||||
@@ -61,13 +62,13 @@ namespace HACD
|
||||
vertexToTriangles.resize(m_nPoints);
|
||||
for(size_t t = 0; t < m_nTriangles; ++t)
|
||||
{
|
||||
vertexToTriangles[m_triangles[t].X()].insert(t);
|
||||
vertexToTriangles[m_triangles[t].Y()].insert(t);
|
||||
vertexToTriangles[m_triangles[t].Z()].insert(t);
|
||||
vertexToTriangles[m_triangles[t].X()].insert(static_cast<long>(t));
|
||||
vertexToTriangles[m_triangles[t].Y()].insert(static_cast<long>(t));
|
||||
vertexToTriangles[m_triangles[t].Z()].insert(static_cast<long>(t));
|
||||
}
|
||||
|
||||
m_graph.Clear();
|
||||
m_graph.Allocate(m_nTriangles, 3 * m_nTriangles);
|
||||
m_graph.Allocate(m_nTriangles, 5 * m_nTriangles);
|
||||
unsigned long long tr1[3];
|
||||
unsigned long long tr2[3];
|
||||
long i1, j1, k1, i2, j2, k2;
|
||||
@@ -112,6 +113,65 @@ namespace HACD
|
||||
}
|
||||
}
|
||||
}
|
||||
if (m_ccConnectDist >= 0.0)
|
||||
{
|
||||
m_graph.ExtractCCs();
|
||||
if (m_graph.m_nCCs > 1)
|
||||
{
|
||||
std::vector< std::set<long> > cc2V;
|
||||
cc2V.resize(m_graph.m_nCCs);
|
||||
long cc;
|
||||
for(size_t t = 0; t < m_nTriangles; ++t)
|
||||
{
|
||||
cc = m_graph.m_vertices[t].m_cc;
|
||||
cc2V[cc].insert(m_triangles[t].X());
|
||||
cc2V[cc].insert(m_triangles[t].Y());
|
||||
cc2V[cc].insert(m_triangles[t].Z());
|
||||
}
|
||||
|
||||
for(size_t cc1 = 0; cc1 < m_graph.m_nCCs; ++cc1)
|
||||
{
|
||||
for(size_t cc2 = cc1+1; cc2 < m_graph.m_nCCs; ++cc2)
|
||||
{
|
||||
std::set<long>::const_iterator itV1(cc2V[cc1].begin()), itVEnd1(cc2V[cc1].end());
|
||||
for(; itV1 != itVEnd1; ++itV1)
|
||||
{
|
||||
double distC1C2 = std::numeric_limits<double>::max();
|
||||
double dist;
|
||||
t1 = -1;
|
||||
t2 = -1;
|
||||
std::set<long>::const_iterator itV2(cc2V[cc2].begin()), itVEnd2(cc2V[cc2].end());
|
||||
for(; itV2 != itVEnd2; ++itV2)
|
||||
{
|
||||
dist = (m_points[*itV1] - m_points[*itV2]).GetNorm();
|
||||
if (dist < distC1C2)
|
||||
{
|
||||
distC1C2 = dist;
|
||||
t1 = *vertexToTriangles[*itV1].begin();
|
||||
|
||||
std::set<long>::const_iterator it2(vertexToTriangles[*itV2].begin()),
|
||||
it2End(vertexToTriangles[*itV2].end());
|
||||
t2 = -1;
|
||||
for(; it2 != it2End; ++it2)
|
||||
{
|
||||
if (*it2 != t1)
|
||||
{
|
||||
t2 = *it2;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (distC1C2 < m_ccConnectDist && t1 > 0 && t2 > 0)
|
||||
{
|
||||
|
||||
m_graph.AddEdge(t1, t2);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
void HACD::InitializeDualGraph()
|
||||
{
|
||||
@@ -294,6 +354,7 @@ namespace HACD
|
||||
m_nMinClusters = 3;
|
||||
m_facePoints = 0;
|
||||
m_faceNormals = 0;
|
||||
m_ccConnectDist = 30;
|
||||
}
|
||||
HACD::~HACD(void)
|
||||
{
|
||||
@@ -479,8 +540,8 @@ namespace HACD
|
||||
m_pqueue.reserve(m_graph.m_nE + 100);
|
||||
for (size_t e=0; e < m_graph.m_nE; ++e)
|
||||
{
|
||||
ComputeEdgeCost(e);
|
||||
m_pqueue.push(GraphEdgePriorityQueue(e, m_graph.m_edges[e].m_error));
|
||||
ComputeEdgeCost(static_cast<long>(e));
|
||||
m_pqueue.push(GraphEdgePriorityQueue(static_cast<long>(e), m_graph.m_edges[e].m_error));
|
||||
}
|
||||
return true;
|
||||
}
|
||||
@@ -495,7 +556,7 @@ namespace HACD
|
||||
double ptgStep = 1.0;
|
||||
while ( (globalConcavity < m_concavity) &&
|
||||
(m_graph.GetNVertices() > m_nMinClusters) &&
|
||||
(m_graph.GetNEdges()> 1))
|
||||
(m_graph.GetNEdges() > 0))
|
||||
{
|
||||
progress = 100.0-m_graph.GetNVertices() * 100.0 / m_nTriangles;
|
||||
if (fabs(progress-progressOld) > ptgStep && m_callBack)
|
||||
@@ -520,18 +581,16 @@ namespace HACD
|
||||
done = false;
|
||||
if (m_pqueue.size() == 0)
|
||||
{
|
||||
done = true;
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
currentEdge = m_pqueue.top();
|
||||
m_pqueue.pop();
|
||||
done = true;
|
||||
break;
|
||||
}
|
||||
currentEdge = m_pqueue.top();
|
||||
m_pqueue.pop();
|
||||
}
|
||||
while ( m_graph.m_edges[currentEdge.m_name].m_deleted ||
|
||||
m_graph.m_edges[currentEdge.m_name].m_error != currentEdge.m_priority);
|
||||
|
||||
|
||||
if (m_graph.m_edges[currentEdge.m_name].m_concavity < m_concavity && !done)
|
||||
{
|
||||
globalConcavity = std::max<double>(globalConcavity ,m_graph.m_edges[currentEdge.m_name].m_concavity);
|
||||
@@ -557,8 +616,8 @@ namespace HACD
|
||||
for(; itE != itEEnd; ++itE)
|
||||
{
|
||||
size_t e = *itE;
|
||||
ComputeEdgeCost(e);
|
||||
m_pqueue.push(GraphEdgePriorityQueue(e, m_graph.m_edges[e].m_error));
|
||||
ComputeEdgeCost(static_cast<long>(e));
|
||||
m_pqueue.push(GraphEdgePriorityQueue(static_cast<long>(e), m_graph.m_edges[e].m_error));
|
||||
}
|
||||
}
|
||||
else
|
||||
@@ -570,10 +629,10 @@ namespace HACD
|
||||
{
|
||||
m_pqueue.pop();
|
||||
}
|
||||
|
||||
|
||||
m_cVertices.clear();
|
||||
m_cVertices.reserve(m_nClusters);
|
||||
m_nClusters = m_graph.GetNVertices();
|
||||
m_cVertices.reserve(m_nClusters);
|
||||
for (size_t p=0, v = 0; v != m_graph.m_vertices.size(); ++v)
|
||||
{
|
||||
if (!m_graph.m_vertices[v].m_deleted)
|
||||
@@ -585,7 +644,7 @@ namespace HACD
|
||||
(*m_callBack)(msg, 0.0, 0.0, m_nClusters);
|
||||
p++;
|
||||
}
|
||||
m_cVertices.push_back(v);
|
||||
m_cVertices.push_back(static_cast<long>(v));
|
||||
}
|
||||
}
|
||||
if (m_callBack)
|
||||
@@ -595,6 +654,7 @@ namespace HACD
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
bool HACD::Compute(bool fullCH, bool exportDistPoints)
|
||||
{
|
||||
if ( !m_points || !m_triangles || !m_nPoints || !m_nTriangles)
|
||||
@@ -614,11 +674,12 @@ namespace HACD
|
||||
msg << "\t compacity weigth \t" << m_alpha << std::endl;
|
||||
msg << "\t volume weigth \t" << m_beta << std::endl;
|
||||
msg << "\t # vertices per convex-hull \t" << m_nVerticesPerCH << std::endl;
|
||||
msg << "\t Scale \t" << m_scale << std::endl;
|
||||
msg << "\t Add extra distance points \t" << m_addExtraDistPoints << std::endl;
|
||||
msg << "\t Add neighbours distance points \t" << m_addNeighboursDistPoints << std::endl;
|
||||
msg << "\t Add face distance points \t" << m_addFacesPoints << std::endl;
|
||||
msg << "\t Produce full convex-hulls \t" << fullCH << std::endl;
|
||||
msg << "\t scale \t" << m_scale << std::endl;
|
||||
msg << "\t add extra distance points \t" << m_addExtraDistPoints << std::endl;
|
||||
msg << "\t add neighbours distance points \t" << m_addNeighboursDistPoints << std::endl;
|
||||
msg << "\t add face distance points \t" << m_addFacesPoints << std::endl;
|
||||
msg << "\t produce full convex-hulls \t" << fullCH << std::endl;
|
||||
msg << "\t max. distance to connect CCs \t" << m_ccConnectDist << std::endl;
|
||||
(*m_callBack)(msg.str().c_str(), 0.0, 0.0, nV);
|
||||
}
|
||||
if (m_callBack) (*m_callBack)("+ Normalizing Data\n", 0.0, 0.0, nV);
|
||||
@@ -643,10 +704,10 @@ namespace HACD
|
||||
for (size_t p = 0; p != m_cVertices.size(); ++p)
|
||||
{
|
||||
size_t v = m_cVertices[p];
|
||||
m_partition[v] = p;
|
||||
m_partition[v] = static_cast<long>(p);
|
||||
for(size_t a = 0; a < m_graph.m_vertices[v].m_ancestors.size(); a++)
|
||||
{
|
||||
m_partition[m_graph.m_vertices[v].m_ancestors[a]] = p;
|
||||
m_partition[m_graph.m_vertices[v].m_ancestors[a]] = static_cast<long>(p);
|
||||
}
|
||||
// compute the convex-hull
|
||||
const std::map<long, DPoint> & pointsCH = m_graph.m_vertices[v].m_distPoints;
|
||||
@@ -666,7 +727,7 @@ namespace HACD
|
||||
}
|
||||
else
|
||||
{
|
||||
m_convexHulls[p].Process(m_nVerticesPerCH);
|
||||
m_convexHulls[p].Process(static_cast<unsigned long>(m_nVerticesPerCH));
|
||||
}
|
||||
if (exportDistPoints)
|
||||
{
|
||||
|
||||
@@ -65,13 +65,11 @@ namespace HACD
|
||||
};
|
||||
inline bool operator<(const GraphEdgePriorityQueue & lhs, const GraphEdgePriorityQueue & rhs)
|
||||
{
|
||||
if (lhs.m_priority!=rhs.m_priority) return lhs.m_priority<rhs.m_priority;
|
||||
return lhs.m_name < rhs.m_name;
|
||||
return lhs.m_priority<rhs.m_priority;
|
||||
}
|
||||
inline bool operator>(const GraphEdgePriorityQueue & lhs, const GraphEdgePriorityQueue & rhs)
|
||||
{
|
||||
if (lhs.m_priority!=rhs.m_priority) return lhs.m_priority>rhs.m_priority;
|
||||
return lhs.m_name > rhs.m_name;
|
||||
return lhs.m_priority>rhs.m_priority;
|
||||
}
|
||||
typedef void (*CallBackFunction)(const char *, double, double, size_t);
|
||||
|
||||
@@ -150,6 +148,12 @@ namespace HACD
|
||||
//! Gives the maximum allowed concavity.
|
||||
//! @return maximum concavity
|
||||
double GetConcavity() const { return m_concavity;}
|
||||
//! Sets the maximum allowed distance to get CCs connected.
|
||||
//! @param concavity maximum distance to get CCs connected
|
||||
void SetConnectDist(double ccConnectDist) { m_ccConnectDist = ccConnectDist;}
|
||||
//! Gives the maximum allowed distance to get CCs connected.
|
||||
//! @return maximum distance to get CCs connected
|
||||
double GetConnectDist() const { return m_ccConnectDist;}
|
||||
//! Sets the volume weight.
|
||||
//! @param beta volume weight
|
||||
void SetVolumeWeight(double beta) { m_beta = beta;}
|
||||
@@ -252,6 +256,7 @@ namespace HACD
|
||||
size_t m_nPoints; //>! number of vertices in the original mesh
|
||||
size_t m_nClusters; //>! number of clusters
|
||||
size_t m_nMinClusters; //>! minimum number of clusters
|
||||
double m_ccConnectDist; //>! maximum allowed distance to connect CCs
|
||||
double m_concavity; //>! maximum concavity
|
||||
double m_alpha; //>! compacity weigth
|
||||
double m_beta; //>! volume weigth
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
#include <limits>
|
||||
namespace HACD
|
||||
{
|
||||
const long ICHull::sc_dummyIndex = static_cast<size_t>(-1);
|
||||
const long ICHull::sc_dummyIndex = std::numeric_limits<long>::max();
|
||||
ICHull::ICHull(void)
|
||||
{
|
||||
m_distPoints = 0;
|
||||
@@ -36,7 +36,7 @@ namespace HACD
|
||||
vertex->GetData().m_pos.X() = points[i].X();
|
||||
vertex->GetData().m_pos.Y() = points[i].Y();
|
||||
vertex->GetData().m_pos.Z() = points[i].Z();
|
||||
vertex->GetData().m_name = i;
|
||||
vertex->GetData().m_name = static_cast<long>(i);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
@@ -788,7 +788,7 @@ namespace HACD
|
||||
bary.Z() += m_mesh.m_vertices.GetHead()->GetData().m_pos.Z();
|
||||
m_mesh.m_vertices.Next();
|
||||
}
|
||||
bary /= nV;
|
||||
bary /= static_cast<double>(nV);
|
||||
|
||||
size_t nT = m_mesh.m_triangles.GetSize();
|
||||
Vec3<double> ver0, ver1, ver2;
|
||||
|
||||
@@ -231,9 +231,9 @@ namespace HACD
|
||||
for(size_t f = 0; f < nT; f++)
|
||||
{
|
||||
TMMTriangle & currentTriangle = m_triangles.GetData();
|
||||
triangles[f].X() = currentTriangle.m_vertices[0]->GetData().m_id;
|
||||
triangles[f].Y() = currentTriangle.m_vertices[1]->GetData().m_id;
|
||||
triangles[f].Z() = currentTriangle.m_vertices[2]->GetData().m_id;
|
||||
triangles[f].X() = static_cast<long>(currentTriangle.m_vertices[0]->GetData().m_id);
|
||||
triangles[f].Y() = static_cast<long>(currentTriangle.m_vertices[1]->GetData().m_id);
|
||||
triangles[f].Z() = static_cast<long>(currentTriangle.m_vertices[2]->GetData().m_id);
|
||||
m_triangles.Next();
|
||||
}
|
||||
}
|
||||
@@ -373,7 +373,7 @@ namespace HACD
|
||||
Vec3<double> s0 = (I-V0) ^ edge3;
|
||||
Vec3<double> s1 = (I-V1) ^ edge1;
|
||||
Vec3<double> s2 = (I-V2) ^ edge2;
|
||||
if (s0*s1 >= 0.0 && s2*s1 >= 0.0)
|
||||
if (s0*s1 > -1e-9 && s2*s1 > -1e-9)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -21,7 +21,7 @@
|
||||
|
||||
namespace HACD
|
||||
{
|
||||
typedef float Real;
|
||||
typedef double Real;
|
||||
//! Vector dim 3.
|
||||
template < typename T > class Vec3
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user