hacdHACD.cpp 30 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851
  1. /* Copyright (c) 2011 Khaled Mamou (kmamou at gmail dot com)
  2. All rights reserved.
  3. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
  4. 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
  5. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
  6. 3. The names of the contributors may not be used to endorse or promote products derived from this software without specific prior written permission.
  7. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  8. */
  9. #ifndef _CRT_SECURE_NO_WARNINGS
  10. #define _CRT_SECURE_NO_WARNINGS
  11. #endif //_CRT_SECURE_NO_WARNINGS
  12. #include <sstream>
  13. #include "hacdGraph.h"
  14. #include "hacdHACD.h"
  15. #include "hacdICHull.h"
  16. #include <string.h>
  17. #include <algorithm>
  18. #include <iterator>
  19. #include <limits>
  20. #include "assert.h"
  21. bool gCancelRequest=false;
  22. namespace HACD
  23. {
  24. double HACD::Concavity(ICHull & ch, std::map<long, DPoint> & distPoints)
  25. {
  26. double concavity = 0.0;
  27. double distance = 0.0;
  28. std::map<long, DPoint>::iterator itDP(distPoints.begin());
  29. std::map<long, DPoint>::iterator itDPEnd(distPoints.end());
  30. for(; itDP != itDPEnd; ++itDP)
  31. {
  32. if (!(itDP->second).m_computed)
  33. {
  34. if (itDP->first >= 0)
  35. {
  36. distance = ch.ComputeDistance(itDP->first, m_points[itDP->first], m_normals[itDP->first], (itDP->second).m_computed, true);
  37. }
  38. else
  39. {
  40. distance = ch.ComputeDistance(itDP->first, m_facePoints[-itDP->first-1], m_faceNormals[-itDP->first-1], (itDP->second).m_computed, true);
  41. }
  42. }
  43. else
  44. {
  45. distance = (itDP->second).m_dist;
  46. }
  47. if (concavity < distance)
  48. {
  49. concavity = distance;
  50. }
  51. }
  52. return concavity;
  53. }
  54. void HACD::CreateGraph()
  55. {
  56. // vertex to triangle adjacency information
  57. std::vector< std::set<long> > vertexToTriangles;
  58. vertexToTriangles.resize(m_nPoints);
  59. for(size_t t = 0; t < m_nTriangles; ++t)
  60. {
  61. vertexToTriangles[m_triangles[t].X()].insert(static_cast<long>(t));
  62. vertexToTriangles[m_triangles[t].Y()].insert(static_cast<long>(t));
  63. vertexToTriangles[m_triangles[t].Z()].insert(static_cast<long>(t));
  64. }
  65. m_graph.Clear();
  66. m_graph.Allocate(m_nTriangles, 5 * m_nTriangles);
  67. unsigned long long tr1[3];
  68. unsigned long long tr2[3];
  69. long i1, j1, k1, i2, j2, k2;
  70. long t1, t2;
  71. for (size_t v = 0; v < m_nPoints; v++)
  72. {
  73. std::set<long>::const_iterator it1(vertexToTriangles[v].begin()), itEnd(vertexToTriangles[v].end());
  74. for(; it1 != itEnd; ++it1)
  75. {
  76. t1 = *it1;
  77. i1 = m_triangles[t1].X();
  78. j1 = m_triangles[t1].Y();
  79. k1 = m_triangles[t1].Z();
  80. tr1[0] = GetEdgeIndex(i1, j1);
  81. tr1[1] = GetEdgeIndex(j1, k1);
  82. tr1[2] = GetEdgeIndex(k1, i1);
  83. std::set<long>::const_iterator it2(it1);
  84. for(++it2; it2 != itEnd; ++it2)
  85. {
  86. t2 = *it2;
  87. i2 = m_triangles[t2].X();
  88. j2 = m_triangles[t2].Y();
  89. k2 = m_triangles[t2].Z();
  90. tr2[0] = GetEdgeIndex(i2, j2);
  91. tr2[1] = GetEdgeIndex(j2, k2);
  92. tr2[2] = GetEdgeIndex(k2, i2);
  93. int shared = 0;
  94. for(int i = 0; i < 3; ++i)
  95. {
  96. for(int j = 0; j < 3; ++j)
  97. {
  98. if (tr1[i] == tr2[j])
  99. {
  100. shared++;
  101. }
  102. }
  103. }
  104. if (shared == 1) // two triangles are connected if they share exactly one edge
  105. {
  106. m_graph.AddEdge(t1, t2);
  107. }
  108. }
  109. }
  110. }
  111. if (m_ccConnectDist >= 0.0)
  112. {
  113. m_graph.ExtractCCs();
  114. if (m_graph.m_nCCs > 1)
  115. {
  116. std::vector< std::set<long> > cc2V;
  117. cc2V.resize(m_graph.m_nCCs);
  118. long cc;
  119. for(size_t t = 0; t < m_nTriangles; ++t)
  120. {
  121. cc = m_graph.m_vertices[t].m_cc;
  122. cc2V[cc].insert(m_triangles[t].X());
  123. cc2V[cc].insert(m_triangles[t].Y());
  124. cc2V[cc].insert(m_triangles[t].Z());
  125. }
  126. for(size_t cc1 = 0; cc1 < m_graph.m_nCCs; ++cc1)
  127. {
  128. for(size_t cc2 = cc1+1; cc2 < m_graph.m_nCCs; ++cc2)
  129. {
  130. std::set<long>::const_iterator itV1(cc2V[cc1].begin()), itVEnd1(cc2V[cc1].end());
  131. for(; itV1 != itVEnd1; ++itV1)
  132. {
  133. double distC1C2 = std::numeric_limits<double>::max();
  134. double dist;
  135. t1 = -1;
  136. t2 = -1;
  137. std::set<long>::const_iterator itV2(cc2V[cc2].begin()), itVEnd2(cc2V[cc2].end());
  138. for(; itV2 != itVEnd2; ++itV2)
  139. {
  140. dist = (m_points[*itV1] - m_points[*itV2]).GetNorm();
  141. if (dist < distC1C2)
  142. {
  143. distC1C2 = dist;
  144. t1 = *vertexToTriangles[*itV1].begin();
  145. std::set<long>::const_iterator it2(vertexToTriangles[*itV2].begin()),
  146. it2End(vertexToTriangles[*itV2].end());
  147. t2 = -1;
  148. for(; it2 != it2End; ++it2)
  149. {
  150. if (*it2 != t1)
  151. {
  152. t2 = *it2;
  153. break;
  154. }
  155. }
  156. }
  157. }
  158. if (distC1C2 <= m_ccConnectDist && t1 > 0 && t2 > 0)
  159. {
  160. m_graph.AddEdge(t1, t2);
  161. }
  162. }
  163. }
  164. }
  165. }
  166. }
  167. }
  168. void HACD::InitializeDualGraph()
  169. {
  170. long i, j, k;
  171. Vec3<Real> u, v, w, normal;
  172. delete [] m_normals;
  173. m_normals = new Vec3<Real>[m_nPoints];
  174. if (m_addFacesPoints)
  175. {
  176. delete [] m_facePoints;
  177. delete [] m_faceNormals;
  178. m_facePoints = new Vec3<Real>[m_nTriangles];
  179. m_faceNormals = new Vec3<Real>[m_nTriangles];
  180. }
  181. memset(m_normals, 0, sizeof(Vec3<Real>) * m_nPoints);
  182. for(unsigned long f = 0; f < m_nTriangles; f++)
  183. {
  184. if (m_callBack) (*m_callBack)("+ InitializeDualGraph\n", f, m_nTriangles, 0);
  185. if (gCancelRequest)
  186. return;
  187. i = m_triangles[f].X();
  188. j = m_triangles[f].Y();
  189. k = m_triangles[f].Z();
  190. m_graph.m_vertices[f].m_distPoints[i].m_distOnly = false;
  191. m_graph.m_vertices[f].m_distPoints[j].m_distOnly = false;
  192. m_graph.m_vertices[f].m_distPoints[k].m_distOnly = false;
  193. ICHull * ch = new ICHull;
  194. m_graph.m_vertices[f].m_convexHull = ch;
  195. ch->AddPoint(m_points[i], i);
  196. ch->AddPoint(m_points[j], j);
  197. ch->AddPoint(m_points[k], k);
  198. ch->SetDistPoints(&m_graph.m_vertices[f].m_distPoints);
  199. u = m_points[j] - m_points[i];
  200. v = m_points[k] - m_points[i];
  201. w = m_points[k] - m_points[j];
  202. normal = u ^ v;
  203. m_normals[i] += normal;
  204. m_normals[j] += normal;
  205. m_normals[k] += normal;
  206. m_graph.m_vertices[f].m_surf = normal.GetNorm();
  207. m_graph.m_vertices[f].m_perimeter = u.GetNorm() + v.GetNorm() + w.GetNorm();
  208. normal.Normalize();
  209. m_graph.m_vertices[f].m_boudaryEdges.insert(GetEdgeIndex(i,j));
  210. m_graph.m_vertices[f].m_boudaryEdges.insert(GetEdgeIndex(j,k));
  211. m_graph.m_vertices[f].m_boudaryEdges.insert(GetEdgeIndex(k,i));
  212. if(m_addFacesPoints)
  213. {
  214. m_faceNormals[f] = normal;
  215. m_facePoints[f] = (m_points[i] + m_points[j] + m_points[k]) / 3.0;
  216. m_graph.m_vertices[f].m_distPoints[-static_cast<long>(f)-1].m_distOnly = true;
  217. }
  218. if (m_addExtraDistPoints)
  219. {// we need a kd-tree structure to accelerate this part!
  220. long i1, j1, k1;
  221. Vec3<Real> u1, v1, normal1;
  222. normal = -normal;
  223. double distance = 0.0;
  224. double distMin = 0.0;
  225. size_t faceIndex = m_nTriangles;
  226. Vec3<Real> seedPoint((m_points[i] + m_points[j] + m_points[k]) / 3.0);
  227. long nhit = 0;
  228. for(size_t f1 = 0; f1 < m_nTriangles; f1++)
  229. {
  230. i1 = m_triangles[f1].X();
  231. j1 = m_triangles[f1].Y();
  232. k1 = m_triangles[f1].Z();
  233. u1 = m_points[j1] - m_points[i1];
  234. v1 = m_points[k1] - m_points[i1];
  235. normal1 = (u1 ^ v1);
  236. if (normal * normal1 > 0.0)
  237. {
  238. nhit = IntersectRayTriangle(Vec3<double>(seedPoint.X(), seedPoint.Y(), seedPoint.Z()),
  239. Vec3<double>(normal.X(), normal.Y(), normal.Z()),
  240. Vec3<double>(m_points[i1].X(), m_points[i1].Y(), m_points[i1].Z()),
  241. Vec3<double>(m_points[j1].X(), m_points[j1].Y(), m_points[j1].Z()),
  242. Vec3<double>(m_points[k1].X(), m_points[k1].Y(), m_points[k1].Z()),
  243. distance);
  244. if ((nhit==1) && ((distMin > distance) || (faceIndex == m_nTriangles)))
  245. {
  246. distMin = distance;
  247. faceIndex = f1;
  248. }
  249. }
  250. }
  251. if (faceIndex < m_nTriangles )
  252. {
  253. i1 = m_triangles[faceIndex].X();
  254. j1 = m_triangles[faceIndex].Y();
  255. k1 = m_triangles[faceIndex].Z();
  256. m_graph.m_vertices[f].m_distPoints[i1].m_distOnly = true;
  257. m_graph.m_vertices[f].m_distPoints[j1].m_distOnly = true;
  258. m_graph.m_vertices[f].m_distPoints[k1].m_distOnly = true;
  259. if (m_addFacesPoints)
  260. {
  261. m_graph.m_vertices[f].m_distPoints[-static_cast<long>(faceIndex)-1].m_distOnly = true;
  262. }
  263. }
  264. }
  265. }
  266. for (size_t v = 0; v < m_nPoints; v++)
  267. {
  268. m_normals[v].Normalize();
  269. }
  270. }
  271. void HACD::NormalizeData()
  272. {
  273. if (m_nPoints == 0)
  274. {
  275. return;
  276. }
  277. m_barycenter = m_points[0];
  278. Vec3<Real> min = m_points[0];
  279. Vec3<Real> max = m_points[0];
  280. Real x, y, z;
  281. for (size_t v = 1; v < m_nPoints ; v++)
  282. {
  283. m_barycenter += m_points[v];
  284. x = m_points[v].X();
  285. y = m_points[v].Y();
  286. z = m_points[v].Z();
  287. if ( x < min.X()) min.X() = x;
  288. else if ( x > max.X()) max.X() = x;
  289. if ( y < min.Y()) min.Y() = y;
  290. else if ( y > max.Y()) max.Y() = y;
  291. if ( z < min.Z()) min.Z() = z;
  292. else if ( z > max.Z()) max.Z() = z;
  293. }
  294. m_barycenter /= static_cast<Real>(m_nPoints);
  295. m_diag = (max-min).GetNorm();
  296. const Real invDiag = static_cast<Real>(2.0 * m_scale / m_diag);
  297. if (m_diag != 0.0)
  298. {
  299. for (size_t v = 0; v < m_nPoints ; v++)
  300. {
  301. m_points[v] = (m_points[v] - m_barycenter) * invDiag;
  302. }
  303. }
  304. }
  305. void HACD::DenormalizeData()
  306. {
  307. if (m_nPoints == 0)
  308. {
  309. return;
  310. }
  311. if (m_diag != 0.0)
  312. {
  313. const Real diag = static_cast<Real>(m_diag / (2.0 * m_scale));
  314. for (size_t v = 0; v < m_nPoints ; v++)
  315. {
  316. m_points[v] = m_points[v] * diag + m_barycenter;
  317. }
  318. }
  319. }
  320. HACD::HACD(void)
  321. {
  322. m_convexHulls = 0;
  323. m_triangles = 0;
  324. m_points = 0;
  325. m_normals = 0;
  326. m_nTriangles = 0;
  327. m_nPoints = 0;
  328. m_nClusters = 0;
  329. m_concavity = 0.0;
  330. m_diag = 1.0;
  331. m_barycenter = Vec3<Real>(0.0, 0.0,0.0);
  332. m_alpha = 0.1;
  333. m_beta = 0.1;
  334. m_nVerticesPerCH = 30;
  335. m_callBack = 0;
  336. m_addExtraDistPoints = false;
  337. m_addNeighboursDistPoints = false;
  338. m_scale = 1000.0;
  339. m_partition = 0;
  340. m_nMinClusters = 3;
  341. m_facePoints = 0;
  342. m_faceNormals = 0;
  343. m_ccConnectDist = 30;
  344. }
  345. HACD::~HACD(void)
  346. {
  347. delete [] m_normals;
  348. delete [] m_convexHulls;
  349. delete [] m_partition;
  350. delete [] m_facePoints;
  351. delete [] m_faceNormals;
  352. }
  353. int iteration = 0;
  354. void HACD::ComputeEdgeCost(size_t e)
  355. {
  356. GraphEdge & gE = m_graph.m_edges[e];
  357. long v1 = gE.m_v1;
  358. long v2 = gE.m_v2;
  359. if (m_graph.m_vertices[v2].m_distPoints.size()>m_graph.m_vertices[v1].m_distPoints.size())
  360. {
  361. gE.m_v1 = v2;
  362. gE.m_v2 = v1;
  363. //std::swap<long>(v1, v2);
  364. std::swap(v1, v2);
  365. }
  366. GraphVertex & gV1 = m_graph.m_vertices[v1];
  367. GraphVertex & gV2 = m_graph.m_vertices[v2];
  368. // delete old convex-hull
  369. delete gE.m_convexHull;
  370. // create the edge's convex-hull
  371. ICHull * ch = new ICHull;
  372. gE.m_convexHull = ch;
  373. (*ch) = (*gV1.m_convexHull);
  374. // update distPoints
  375. gE.m_distPoints = gV1.m_distPoints;
  376. std::map<long, DPoint>::iterator itDP(gV2.m_distPoints.begin());
  377. std::map<long, DPoint>::iterator itDPEnd(gV2.m_distPoints.end());
  378. std::map<long, DPoint>::iterator itDP1;
  379. for(; itDP != itDPEnd; ++itDP)
  380. {
  381. itDP1 = gE.m_distPoints.find(itDP->first);
  382. if (itDP1 == gE.m_distPoints.end())
  383. {
  384. gE.m_distPoints[itDP->first].m_distOnly = (itDP->second).m_distOnly;
  385. if ( !(itDP->second).m_distOnly )
  386. {
  387. ch->AddPoint(m_points[itDP->first], itDP->first);
  388. }
  389. }
  390. else
  391. {
  392. if ( (itDP1->second).m_distOnly && !(itDP->second).m_distOnly)
  393. {
  394. gE.m_distPoints[itDP->first].m_distOnly = false;
  395. ch->AddPoint(m_points[itDP->first], itDP->first);
  396. }
  397. }
  398. }
  399. ch->SetDistPoints(&gE.m_distPoints);
  400. // create the convex-hull
  401. while (ch->Process() == ICHullErrorInconsistent) // if we face problems when constructing the visual-hull. really ugly!!!!
  402. {
  403. // if (m_callBack) (*m_callBack)("\t Problem with convex-hull construction [HACD::ComputeEdgeCost]\n", 0.0, 0.0, 0);
  404. ch = new ICHull;
  405. CircularList<TMMVertex> & verticesCH = (gE.m_convexHull)->GetMesh().m_vertices;
  406. size_t nV = verticesCH.GetSize();
  407. long ptIndex = 0;
  408. verticesCH.Next();
  409. for(size_t v = 1; v < nV; ++v)
  410. {
  411. ptIndex = verticesCH.GetHead()->GetData().m_name;
  412. if (ptIndex != ICHull::sc_dummyIndex/* && ptIndex < m_nPoints*/)
  413. ch->AddPoint(m_points[ptIndex], ptIndex);
  414. verticesCH.Next();
  415. }
  416. delete gE.m_convexHull;
  417. gE.m_convexHull = ch;
  418. }
  419. double volume = 0.0;
  420. double concavity = 0.0;
  421. if (ch->IsFlat())
  422. {
  423. bool insideHull;
  424. std::map<long, DPoint>::iterator itDP(gE.m_distPoints.begin());
  425. std::map<long, DPoint>::iterator itDPEnd(gE.m_distPoints.end());
  426. for(; itDP != itDPEnd; ++itDP)
  427. {
  428. if (itDP->first >= 0)
  429. {
  430. concavity = std::max<double>(concavity, ch->ComputeDistance(itDP->first, m_points[itDP->first], m_normals[itDP->first], insideHull, false));
  431. }
  432. }
  433. }
  434. else
  435. {
  436. if (m_addNeighboursDistPoints)
  437. { // add distance points from adjacent clusters
  438. std::set<long> eEdges;
  439. std::set_union(gV1.m_edges.begin(),
  440. gV1.m_edges.end(),
  441. gV2.m_edges.begin(),
  442. gV2.m_edges.end(),
  443. std::inserter( eEdges, eEdges.begin() ) );
  444. std::set<long>::const_iterator ed(eEdges.begin());
  445. std::set<long>::const_iterator itEnd(eEdges.end());
  446. long a, b, c;
  447. for(; ed != itEnd; ++ed)
  448. {
  449. a = m_graph.m_edges[*ed].m_v1;
  450. b = m_graph.m_edges[*ed].m_v2;
  451. if ( a != v2 && a != v1)
  452. {
  453. c = a;
  454. }
  455. else if ( b != v2 && b != v1)
  456. {
  457. c = b;
  458. }
  459. else
  460. {
  461. c = -1;
  462. }
  463. if ( c > 0)
  464. {
  465. GraphVertex & gVC = m_graph.m_vertices[c];
  466. std::map<long, DPoint>::iterator itDP(gVC.m_distPoints.begin());
  467. std::map<long, DPoint>::iterator itDPEnd(gVC.m_distPoints.end());
  468. std::map<long, DPoint>::iterator itDP1;
  469. for(; itDP != itDPEnd; ++itDP)
  470. {
  471. itDP1 = gE.m_distPoints.find(itDP->first);
  472. if (itDP1 == gE.m_distPoints.end())
  473. {
  474. if (itDP->first >= 0 && itDP1 == gE.m_distPoints.end() && ch->IsInside(m_points[itDP->first]))
  475. {
  476. gE.m_distPoints[itDP->first].m_distOnly = true;
  477. }
  478. else if (itDP->first < 0 && ch->IsInside(m_facePoints[-itDP->first-1]))
  479. {
  480. gE.m_distPoints[itDP->first].m_distOnly = true;
  481. }
  482. }
  483. }
  484. }
  485. }
  486. }
  487. concavity = Concavity(*ch, gE.m_distPoints);
  488. }
  489. // compute boudary edges
  490. double perimeter = 0.0;
  491. double surf = 1.0;
  492. if (m_alpha > 0.0)
  493. {
  494. gE.m_boudaryEdges.clear();
  495. std::set_symmetric_difference (gV1.m_boudaryEdges.begin(),
  496. gV1.m_boudaryEdges.end(),
  497. gV2.m_boudaryEdges.begin(),
  498. gV2.m_boudaryEdges.end(),
  499. std::inserter( gE.m_boudaryEdges,
  500. gE.m_boudaryEdges.begin() ) );
  501. std::set<unsigned long long>::const_iterator itBE(gE.m_boudaryEdges.begin());
  502. std::set<unsigned long long>::const_iterator itBEEnd(gE.m_boudaryEdges.end());
  503. for(; itBE != itBEEnd; ++itBE)
  504. {
  505. perimeter += (m_points[static_cast<long>((*itBE) >> 32)] -
  506. m_points[static_cast<long>((*itBE) & 0xFFFFFFFFULL)]).GetNorm();
  507. }
  508. surf = gV1.m_surf + gV2.m_surf;
  509. }
  510. double ratio = perimeter * perimeter / (4.0 * sc_pi * surf);
  511. gE.m_volume = (m_beta == 0.0)?0.0:ch->ComputeVolume()/pow(m_scale, 3.0); // cluster's volume
  512. gE.m_surf = surf; // cluster's area
  513. gE.m_perimeter = perimeter; // cluster's perimeter
  514. gE.m_concavity = concavity; // cluster's concavity
  515. gE.m_error = static_cast<Real>(concavity + m_alpha * ratio + m_beta * volume); // cluster's priority
  516. }
  517. bool HACD::InitializePriorityQueue()
  518. {
  519. m_pqueue.reserve(m_graph.m_nE + 100);
  520. for (size_t e=0; e < m_graph.m_nE; ++e)
  521. {
  522. ComputeEdgeCost(static_cast<long>(e));
  523. m_pqueue.push(GraphEdgePriorityQueue(static_cast<long>(e), m_graph.m_edges[e].m_error));
  524. }
  525. return true;
  526. }
  527. void HACD::Simplify()
  528. {
  529. long v1 = -1;
  530. long v2 = -1;
  531. double progressOld = -1.0;
  532. double progress = 0.0;
  533. double globalConcavity = 0.0;
  534. char msg[1024];
  535. double ptgStep = 1.0;
  536. while ( (globalConcavity < m_concavity) &&
  537. (m_graph.GetNVertices() > m_nMinClusters) &&
  538. (m_graph.GetNEdges() > 0))
  539. {
  540. progress = 100.0-m_graph.GetNVertices() * 100.0 / m_nTriangles;
  541. if (fabs(progress-progressOld) > ptgStep && m_callBack)
  542. {
  543. sprintf(msg, "%3.2f %% V = %lu \t C = %f \t \t \r", progress, static_cast<unsigned long>(m_graph.GetNVertices()), globalConcavity);
  544. (*m_callBack)(msg, progress, globalConcavity, m_graph.GetNVertices());
  545. progressOld = progress;
  546. if (progress > 99.0)
  547. {
  548. ptgStep = 0.01;
  549. }
  550. else if (progress > 90.0)
  551. {
  552. ptgStep = 0.1;
  553. }
  554. }
  555. GraphEdgePriorityQueue currentEdge(0,0.0);
  556. bool done = false;
  557. do
  558. {
  559. done = false;
  560. if (m_pqueue.size() == 0)
  561. {
  562. done = true;
  563. break;
  564. }
  565. currentEdge = m_pqueue.top();
  566. m_pqueue.pop();
  567. }
  568. while ( m_graph.m_edges[currentEdge.m_name].m_deleted ||
  569. m_graph.m_edges[currentEdge.m_name].m_error != currentEdge.m_priority);
  570. if (m_graph.m_edges[currentEdge.m_name].m_concavity < m_concavity && !done)
  571. {
  572. globalConcavity = std::max<double>(globalConcavity ,m_graph.m_edges[currentEdge.m_name].m_concavity);
  573. v1 = m_graph.m_edges[currentEdge.m_name].m_v1;
  574. v2 = m_graph.m_edges[currentEdge.m_name].m_v2;
  575. // update vertex info
  576. m_graph.m_vertices[v1].m_error = m_graph.m_edges[currentEdge.m_name].m_error;
  577. m_graph.m_vertices[v1].m_surf = m_graph.m_edges[currentEdge.m_name].m_surf;
  578. m_graph.m_vertices[v1].m_volume = m_graph.m_edges[currentEdge.m_name].m_volume;
  579. m_graph.m_vertices[v1].m_concavity = m_graph.m_edges[currentEdge.m_name].m_concavity;
  580. m_graph.m_vertices[v1].m_perimeter = m_graph.m_edges[currentEdge.m_name].m_perimeter;
  581. m_graph.m_vertices[v1].m_distPoints = m_graph.m_edges[currentEdge.m_name].m_distPoints;
  582. (*m_graph.m_vertices[v1].m_convexHull) = (*m_graph.m_edges[currentEdge.m_name].m_convexHull);
  583. (m_graph.m_vertices[v1].m_convexHull)->SetDistPoints(&(m_graph.m_vertices[v1].m_distPoints));
  584. m_graph.m_vertices[v1].m_boudaryEdges = m_graph.m_edges[currentEdge.m_name].m_boudaryEdges;
  585. // We apply the optimal ecol
  586. // std::cout << "v1 " << v1 << " v2 " << v2 << std::endl;
  587. m_graph.EdgeCollapse(v1, v2);
  588. // recompute the adjacent edges costs
  589. std::set<long>::const_iterator itE(m_graph.m_vertices[v1].m_edges.begin()),
  590. itEEnd(m_graph.m_vertices[v1].m_edges.end());
  591. for(; itE != itEEnd; ++itE)
  592. {
  593. size_t e = *itE;
  594. ComputeEdgeCost(static_cast<long>(e));
  595. m_pqueue.push(GraphEdgePriorityQueue(static_cast<long>(e), m_graph.m_edges[e].m_error));
  596. }
  597. }
  598. else
  599. {
  600. break;
  601. }
  602. }
  603. while (!m_pqueue.empty())
  604. {
  605. m_pqueue.pop();
  606. }
  607. m_cVertices.clear();
  608. m_nClusters = m_graph.GetNVertices();
  609. m_cVertices.reserve(m_nClusters);
  610. for (size_t p=0, v = 0; v != m_graph.m_vertices.size(); ++v)
  611. {
  612. if (!m_graph.m_vertices[v].m_deleted)
  613. {
  614. if (m_callBack)
  615. {
  616. char msg[1024];
  617. sprintf(msg, "\t CH \t %lu \t %lf \t %lf\n", static_cast<unsigned long>(p), m_graph.m_vertices[v].m_concavity, m_graph.m_vertices[v].m_error);
  618. (*m_callBack)(msg, 0.0, 0.0, m_nClusters);
  619. p++;
  620. }
  621. m_cVertices.push_back(static_cast<long>(v));
  622. }
  623. }
  624. if (m_callBack)
  625. {
  626. sprintf(msg, "# clusters = %lu \t C = %f\n", static_cast<unsigned long>(m_nClusters), globalConcavity);
  627. (*m_callBack)(msg, progress, globalConcavity, m_graph.GetNVertices());
  628. }
  629. }
  630. bool HACD::Compute(bool fullCH, bool exportDistPoints)
  631. {
  632. gCancelRequest = false;
  633. if ( !m_points || !m_triangles || !m_nPoints || !m_nTriangles)
  634. {
  635. return false;
  636. }
  637. size_t nV = m_nTriangles;
  638. if (m_callBack)
  639. {
  640. std::ostringstream msg;
  641. msg << "+ Mesh" << std::endl;
  642. msg << "\t # vertices \t" << m_nPoints << std::endl;
  643. msg << "\t # triangles \t" << m_nTriangles << std::endl;
  644. msg << "+ Parameters" << std::endl;
  645. msg << "\t min # of clusters \t" << m_nMinClusters << std::endl;
  646. msg << "\t max concavity \t" << m_concavity << std::endl;
  647. msg << "\t compacity weigth \t" << m_alpha << std::endl;
  648. msg << "\t volume weigth \t" << m_beta << std::endl;
  649. msg << "\t # vertices per convex-hull \t" << m_nVerticesPerCH << std::endl;
  650. msg << "\t scale \t" << m_scale << std::endl;
  651. msg << "\t add extra distance points \t" << m_addExtraDistPoints << std::endl;
  652. msg << "\t add neighbours distance points \t" << m_addNeighboursDistPoints << std::endl;
  653. msg << "\t add face distance points \t" << m_addFacesPoints << std::endl;
  654. msg << "\t produce full convex-hulls \t" << fullCH << std::endl;
  655. msg << "\t max. distance to connect CCs \t" << m_ccConnectDist << std::endl;
  656. (*m_callBack)(msg.str().c_str(), 0.0, 0.0, nV);
  657. }
  658. if (m_callBack) (*m_callBack)("+ Normalizing Data\n", 0.0, 0.0, nV);
  659. NormalizeData();
  660. if (m_callBack) (*m_callBack)("+ Creating Graph\n", 0.0, 0.0, nV);
  661. CreateGraph();
  662. // Compute the surfaces and perimeters of all the faces
  663. if (m_callBack) (*m_callBack)("+ Initializing Dual Graph\n", 0.0, 0.0, nV);
  664. if (gCancelRequest)
  665. return false;
  666. InitializeDualGraph();
  667. if (m_callBack) (*m_callBack)("+ Initializing Priority Queue\n", 0.0, 0.0, nV);
  668. if (gCancelRequest)
  669. return false;
  670. InitializePriorityQueue();
  671. // we simplify the graph
  672. if (m_callBack) (*m_callBack)("+ Simplification ...\n", 0.0, 0.0, m_nTriangles);
  673. Simplify();
  674. if (m_callBack) (*m_callBack)("+ Denormalizing Data\n", 0.0, 0.0, m_nClusters);
  675. DenormalizeData();
  676. if (m_callBack) (*m_callBack)("+ Computing final convex-hulls\n", 0.0, 0.0, m_nClusters);
  677. delete [] m_convexHulls;
  678. m_convexHulls = new ICHull[m_nClusters];
  679. delete [] m_partition;
  680. m_partition = new long [m_nTriangles];
  681. for (size_t p = 0; p != m_cVertices.size(); ++p)
  682. {
  683. size_t v = m_cVertices[p];
  684. m_partition[v] = static_cast<long>(p);
  685. for(size_t a = 0; a < m_graph.m_vertices[v].m_ancestors.size(); a++)
  686. {
  687. m_partition[m_graph.m_vertices[v].m_ancestors[a]] = static_cast<long>(p);
  688. }
  689. // compute the convex-hull
  690. const std::map<long, DPoint> & pointsCH = m_graph.m_vertices[v].m_distPoints;
  691. std::map<long, DPoint>::const_iterator itCH(pointsCH.begin());
  692. std::map<long, DPoint>::const_iterator itCHEnd(pointsCH.end());
  693. for(; itCH != itCHEnd; ++itCH)
  694. {
  695. if (!(itCH->second).m_distOnly)
  696. {
  697. m_convexHulls[p].AddPoint(m_points[itCH->first], itCH->first);
  698. }
  699. }
  700. m_convexHulls[p].SetDistPoints(&m_graph.m_vertices[v].m_distPoints);
  701. if (fullCH)
  702. {
  703. m_convexHulls[p].Process();
  704. }
  705. else
  706. {
  707. m_convexHulls[p].Process(static_cast<unsigned long>(m_nVerticesPerCH));
  708. }
  709. if (exportDistPoints)
  710. {
  711. itCH = pointsCH.begin();
  712. for(; itCH != itCHEnd; ++itCH)
  713. {
  714. if ((itCH->second).m_distOnly)
  715. {
  716. if (itCH->first >= 0)
  717. {
  718. m_convexHulls[p].AddPoint(m_points[itCH->first], itCH->first);
  719. }
  720. else
  721. {
  722. m_convexHulls[p].AddPoint(m_facePoints[-itCH->first-1], itCH->first);
  723. }
  724. }
  725. }
  726. }
  727. }
  728. return true;
  729. }
  730. size_t HACD::GetNTrianglesCH(size_t numCH) const
  731. {
  732. if (numCH >= m_nClusters)
  733. {
  734. return 0;
  735. }
  736. return m_convexHulls[numCH].GetMesh().GetNTriangles();
  737. }
  738. size_t HACD::GetNPointsCH(size_t numCH) const
  739. {
  740. if (numCH >= m_nClusters)
  741. {
  742. return 0;
  743. }
  744. return m_convexHulls[numCH].GetMesh().GetNVertices();
  745. }
  746. bool HACD::GetCH(size_t numCH, Vec3<Real> * const points, Vec3<long> * const triangles)
  747. {
  748. if (numCH >= m_nClusters)
  749. {
  750. return false;
  751. }
  752. m_convexHulls[numCH].GetMesh().GetIFS(points, triangles);
  753. return true;
  754. }
  755. bool HACD::Save(const char * fileName, bool uniColor, long numCluster) const
  756. {
  757. std::ofstream fout(fileName);
  758. if (fout.is_open())
  759. {
  760. if (m_callBack)
  761. {
  762. char msg[1024];
  763. sprintf(msg, "Saving %s\n", fileName);
  764. (*m_callBack)(msg, 0.0, 0.0, m_graph.GetNVertices());
  765. }
  766. Material mat;
  767. if (numCluster < 0)
  768. {
  769. for (size_t p = 0; p != m_nClusters; ++p)
  770. {
  771. if (!uniColor)
  772. {
  773. mat.m_diffuseColor.X() = mat.m_diffuseColor.Y() = mat.m_diffuseColor.Z() = 0.0;
  774. while (mat.m_diffuseColor.X() == mat.m_diffuseColor.Y() ||
  775. mat.m_diffuseColor.Z() == mat.m_diffuseColor.Y() ||
  776. mat.m_diffuseColor.Z() == mat.m_diffuseColor.X() )
  777. {
  778. mat.m_diffuseColor.X() = (rand()%100) / 100.0;
  779. mat.m_diffuseColor.Y() = (rand()%100) / 100.0;
  780. mat.m_diffuseColor.Z() = (rand()%100) / 100.0;
  781. }
  782. }
  783. m_convexHulls[p].GetMesh().SaveVRML2(fout, mat);
  784. }
  785. }
  786. else if (numCluster < static_cast<long>(m_cVertices.size()))
  787. {
  788. m_convexHulls[numCluster].GetMesh().SaveVRML2(fout, mat);
  789. }
  790. fout.close();
  791. return true;
  792. }
  793. else
  794. {
  795. if (m_callBack)
  796. {
  797. char msg[1024];
  798. sprintf(msg, "Error saving %s\n", fileName);
  799. (*m_callBack)(msg, 0.0, 0.0, m_graph.GetNVertices());
  800. }
  801. return false;
  802. }
  803. }
  804. }