void HACD::ComputeEdgeCost(size_t e) { GraphEdge & gE = m_graph.m_edges[e]; long v1 = gE.m_v1; long v2 = gE.m_v2; if (m_graph.m_vertices[v2].m_ancestors.size()>m_graph.m_vertices[v1].m_ancestors.size()) { gE.m_v1 = v2; gE.m_v2 = v1; std::swap(v1, v2); } GraphVertex & gV1 = m_graph.m_vertices[v1]; GraphVertex & gV2 = m_graph.m_vertices[v2]; #ifdef HACD_DEBUG if (v1 == 308 && v2==276) { gV1.m_convexHull->m_mesh.Save("debug1.wrl"); gV2.m_convexHull->m_mesh.Save("debug2.wrl"); } #endif // create the edge's convex-hull ICHull * ch = new ICHull(m_heapManager); (*ch) = (*gV1.m_convexHull); // update distPoints #ifdef HACD_PRECOMPUTE_CHULLS delete gE.m_convexHull; gE.m_convexHull = 0; #endif std::map<long, DPoint> distPoints; for(size_t p = 0; p < gV1.m_distPoints.Size(); ++p) { distPoints[gV1.m_distPoints[p].m_name] = gV1.m_distPoints[p]; } std::map<long, DPoint>::iterator itDP1; for(size_t p = 0; p < gV2.m_distPoints.Size(); ++p) { const DPoint & point = gV2.m_distPoints[p]; itDP1 = distPoints.find(point.m_name); if (itDP1 == distPoints.end()) { DPoint newPoint(point.m_name, 0, false, point.m_distOnly); distPoints.insert(std::pair<long, DPoint>(point.m_name, newPoint)); if ( !point.m_distOnly ) { ch->AddPoint(m_points[point.m_name], point.m_name); } } else { if ( (itDP1->second).m_distOnly && !point.m_distOnly) { (itDP1->second).m_distOnly = false; ch->AddPoint(m_points[point.m_name], point.m_name); } } } ch->SetDistPoints(&distPoints); // create the convex-hull while (ch->Process() == ICHullErrorInconsistent) // if we face problems when constructing the visual-hull. really ugly!!!! { // if (m_callBack) (*m_callBack)("\t Problem with convex-hull construction [HACD::ComputeEdgeCost]\n", 0.0, 0.0, 0); ICHull * chOld = ch; ch = new ICHull(m_heapManager); CircularList<TMMVertex> & verticesCH = chOld->GetMesh().m_vertices; size_t nV = verticesCH.GetSize(); long ptIndex = 0; verticesCH.Next(); // add noise to avoid the problem ptIndex = verticesCH.GetHead()->GetData().m_name; ch->AddPoint(m_points[ptIndex]+ m_scale * 0.0001 * Vec3<Real>(rand() % 10 - 5, rand() % 10 - 5, rand() % 10 - 5), ptIndex); for(size_t v = 1; v < nV; ++v) { ptIndex = verticesCH.GetHead()->GetData().m_name; ch->AddPoint(m_points[ptIndex], ptIndex); verticesCH.Next(); } delete chOld; } #ifdef HACD_DEBUG if (v1 == 438 && v2==468) { const long nPoints = static_cast<long>(m_nPoints); std::map<long, DPoint>::iterator itDP(distPoints.begin()); std::map<long, DPoint>::iterator itDPEnd(distPoints.end()); for(; itDP != itDPEnd; ++itDP) { if (itDP->first >= nPoints) { long pt = itDP->first - nPoints; ch->AddPoint(m_extraDistPoints[pt], itDP->first); } else if (itDP->first >= 0) { long pt = itDP->first; ch->AddPoint(m_points[pt], itDP->first); } else { long pt = -itDP->first-1; ch->AddPoint(m_facePoints[pt], itDP->first); ch->AddPoint(m_facePoints[pt] + 10.0 * m_faceNormals[pt] , itDP->first); } } printf("-***->\n"); ch->m_mesh.Save("debug.wrl"); } #endif double surf = gV1.m_surf + gV2.m_surf; double concavity = 0.0; double surfCH = ch->ComputeArea() / 2.0; double volumeCH = ch->ComputeVolume(); double vol2Surf = volumeCH / surfCH; double concavity_flat = sqrt(fabs(surfCH-surf)); double weightFlat = std::max(0.0, 1.0 - pow(- vol2Surf * 100.0 / (m_scale * m_flatRegionThreshold), 2.0)); // concavity_flat *= std::max(exp(- vol2Surf * 100.0 / (m_scale * m_flatRegionThreshold)) - exp(-1.0), 0.0); concavity_flat *= weightFlat; if(!ch->IsFlat()) { concavity = Concavity(*ch, distPoints); } concavity += concavity_flat; #ifdef HACD_PRECOMPUTE_CHULLS gE.m_convexHull = ch; #else delete ch; #endif // compute boudary edges double perimeter = 0.0; if (m_alpha > 0.0) { std::set<unsigned long long> boudaryEdges1; for(size_t edV1 = 0; edV1 < gV1.m_boudaryEdges.Size(); ++edV1) { boudaryEdges1.insert(gV1.m_boudaryEdges[edV1]); } std::set<unsigned long long> boudaryEdges2; for(size_t edV2 = 0; edV2 < gV2.m_boudaryEdges.Size(); ++edV2) { boudaryEdges2.insert(gV2.m_boudaryEdges[edV2]); } std::set<unsigned long long> boudaryEdges; std::set_symmetric_difference (boudaryEdges1.begin(), boudaryEdges1.end(), boudaryEdges2.begin(), boudaryEdges2.end(), std::inserter( boudaryEdges, boudaryEdges.begin() ) ); std::set<unsigned long long>::const_iterator itBE(boudaryEdges.begin()); std::set<unsigned long long>::const_iterator itBEEnd(boudaryEdges.end()); for(; itBE != itBEEnd; ++itBE) { perimeter += (m_points[static_cast<long>((*itBE) >> 32)] - m_points[static_cast<long>((*itBE) & 0xFFFFFFFFULL)]).GetNorm(); } }
void HACD::ComputeEdgeCost(size_t e) { GraphEdge & gE = m_graph.m_edges[e]; long v1 = gE.m_v1; long v2 = gE.m_v2; if (m_graph.m_vertices[v2].m_distPoints.size()>m_graph.m_vertices[v1].m_distPoints.size()) { gE.m_v1 = v2; gE.m_v2 = v1; //std::swap<long>(v1, v2); std::swap(v1, v2); } GraphVertex & gV1 = m_graph.m_vertices[v1]; GraphVertex & gV2 = m_graph.m_vertices[v2]; // delete old convex-hull delete gE.m_convexHull; // create the edge's convex-hull ICHull * ch = new ICHull; gE.m_convexHull = ch; (*ch) = (*gV1.m_convexHull); // update distPoints gE.m_distPoints = gV1.m_distPoints; std::map<long, DPoint>::iterator itDP(gV2.m_distPoints.begin()); std::map<long, DPoint>::iterator itDPEnd(gV2.m_distPoints.end()); std::map<long, DPoint>::iterator itDP1; for(; itDP != itDPEnd; ++itDP) { itDP1 = gE.m_distPoints.find(itDP->first); if (itDP1 == gE.m_distPoints.end()) { gE.m_distPoints[itDP->first].m_distOnly = (itDP->second).m_distOnly; if ( !(itDP->second).m_distOnly ) { ch->AddPoint(m_points[itDP->first], itDP->first); } } else { if ( (itDP1->second).m_distOnly && !(itDP->second).m_distOnly) { gE.m_distPoints[itDP->first].m_distOnly = false; ch->AddPoint(m_points[itDP->first], itDP->first); } } } ch->SetDistPoints(&gE.m_distPoints); // create the convex-hull while (ch->Process() == ICHullErrorInconsistent) // if we face problems when constructing the visual-hull. really ugly!!!! { // if (m_callBack) (*m_callBack)("\t Problem with convex-hull construction [HACD::ComputeEdgeCost]\n", 0.0, 0.0, 0); ch = new ICHull; CircularList<TMMVertex> & verticesCH = (gE.m_convexHull)->GetMesh().m_vertices; size_t nV = verticesCH.GetSize(); long ptIndex = 0; verticesCH.Next(); for(size_t v = 1; v < nV; ++v) { ptIndex = verticesCH.GetHead()->GetData().m_name; ch->AddPoint(m_points[ptIndex], ptIndex); verticesCH.Next(); } delete gE.m_convexHull; gE.m_convexHull = ch; } double volume = 0.0; double concavity = 0.0; if (ch->IsFlat()) { bool insideHull; std::map<long, DPoint>::iterator itDP(gE.m_distPoints.begin()); std::map<long, DPoint>::iterator itDPEnd(gE.m_distPoints.end()); for(; itDP != itDPEnd; ++itDP) { if (itDP->first >= 0) { concavity = std::max<double>(concavity, ch->ComputeDistance(itDP->first, m_points[itDP->first], m_normals[itDP->first], insideHull, false)); } } } else { if (m_addNeighboursDistPoints) { // add distance points from adjacent clusters std::set<long> eEdges; std::set_union(gV1.m_edges.begin(), gV1.m_edges.end(), gV2.m_edges.begin(), gV2.m_edges.end(), std::inserter( eEdges, eEdges.begin() ) ); std::set<long>::const_iterator ed(eEdges.begin()); std::set<long>::const_iterator itEnd(eEdges.end()); long a, b, c; for(; ed != itEnd; ++ed) { a = m_graph.m_edges[*ed].m_v1; b = m_graph.m_edges[*ed].m_v2; if ( a != v2 && a != v1) { c = a; } else if ( b != v2 && b != v1) { c = b; } else { c = -1; } if ( c > 0) { GraphVertex & gVC = m_graph.m_vertices[c]; std::map<long, DPoint>::iterator itDP(gVC.m_distPoints.begin()); std::map<long, DPoint>::iterator itDPEnd(gVC.m_distPoints.end()); std::map<long, DPoint>::iterator itDP1; for(; itDP != itDPEnd; ++itDP) { itDP1 = gE.m_distPoints.find(itDP->first); if (itDP1 == gE.m_distPoints.end()) { if (itDP->first >= 0 && itDP1 == gE.m_distPoints.end() && ch->IsInside(m_points[itDP->first])) { gE.m_distPoints[itDP->first].m_distOnly = true; } else if (itDP->first < 0 && ch->IsInside(m_facePoints[-itDP->first-1])) { gE.m_distPoints[itDP->first].m_distOnly = true; } } } } } } concavity = Concavity(*ch, gE.m_distPoints); } // compute boudary edges double perimeter = 0.0; double surf = 1.0; if (m_alpha > 0.0) { gE.m_boudaryEdges.clear(); std::set_symmetric_difference (gV1.m_boudaryEdges.begin(), gV1.m_boudaryEdges.end(), gV2.m_boudaryEdges.begin(), gV2.m_boudaryEdges.end(), std::inserter( gE.m_boudaryEdges, gE.m_boudaryEdges.begin() ) ); std::set<unsigned long long>::const_iterator itBE(gE.m_boudaryEdges.begin()); std::set<unsigned long long>::const_iterator itBEEnd(gE.m_boudaryEdges.end()); for(; itBE != itBEEnd; ++itBE) { perimeter += (m_points[static_cast<long>((*itBE) >> 32)] - m_points[static_cast<long>((*itBE) & 0xFFFFFFFFULL)]).GetNorm(); } surf = gV1.m_surf + gV2.m_surf; }
void HACD::InitializeDualGraph() { long i, j, k; Vec3<Real> u, v, w, normal; delete [] m_normals; m_normals = new Vec3<Real>[m_nPoints]; if (m_addFacesPoints) { delete [] m_facePoints; delete [] m_faceNormals; m_facePoints = new Vec3<Real>[m_nTriangles]; m_faceNormals = new Vec3<Real>[m_nTriangles]; /* m_facePoints = new Vec3<Real>[4*m_nTriangles]; m_faceNormals = new Vec3<Real>[4*m_nTriangles]; */ } memset(m_normals, 0, sizeof(Vec3<Real>) * m_nPoints); RaycastMesh rm; if (m_addExtraDistPoints) { rm.Initialize(m_nPoints, m_nTriangles, m_points, m_triangles, 15); m_extraDistPoints = new Vec3<Real>[m_nTriangles]; m_extraDistNormals = new Vec3<Real>[m_nTriangles]; } double progressOld = -1.0; double progress = 0.0; char msg[1024]; double ptgStep = 1.0; m_area = 0.0; for(unsigned long f = 0; f < m_nTriangles; f++) { progress = f * 100.0 / m_nTriangles; if (fabs(progress-progressOld) > ptgStep && m_callBack) { sprintf(msg, "%3.2f %% \t \t \r", progress); (*m_callBack)(msg, progress, 0.0, m_nTriangles); progressOld = progress; } i = m_triangles[f].X(); j = m_triangles[f].Y(); k = m_triangles[f].Z(); m_graph.m_vertices[f].m_distPoints.PushBack(DPoint(i, 0, false, false)); m_graph.m_vertices[f].m_distPoints.PushBack(DPoint(j, 0, false, false)); m_graph.m_vertices[f].m_distPoints.PushBack(DPoint(k, 0, false, false)); ICHull * ch = new ICHull(m_heapManager); m_graph.m_vertices[f].m_convexHull = ch; ch->AddPoint(m_points[i], i); ch->AddPoint(m_points[j], j); ch->AddPoint(m_points[k], k); ch->SetDistPoints(0); u = m_points[j] - m_points[i]; v = m_points[k] - m_points[i]; w = m_points[k] - m_points[j]; normal = u ^ v; m_normals[i] += normal; m_normals[j] += normal; m_normals[k] += normal; m_graph.m_vertices[f].m_surf = normal.GetNorm(); m_area += m_graph.m_vertices[f].m_surf; normal.Normalize(); m_graph.m_vertices[f].m_boudaryEdges.Insert(GetEdgeIndex(i,j)); m_graph.m_vertices[f].m_boudaryEdges.Insert(GetEdgeIndex(j,k)); m_graph.m_vertices[f].m_boudaryEdges.Insert(GetEdgeIndex(k,i)); if(m_addFacesPoints) { m_faceNormals[f] = normal; m_facePoints[f] = (m_points[i] + m_points[j] + m_points[k]) / 3.0; m_graph.m_vertices[f].m_distPoints.PushBack(DPoint(-static_cast<long>(f)-1, 0, false, true)); } } // Now we have all the points in the KD tree, optimize the distance points insertion by running them in parallel // if possible. if (m_addExtraDistPoints) { if (m_callBack) (*m_callBack)("++ Also adding distance points\n", 0.0, 0.0, 0); progressOld = -1.0; progress = 0.0; long completed = 0; #ifdef THREAD_DIST_POINTS #pragma omp parallel for #endif for(long f = 0; f < (long)m_nTriangles; f++) { Vec3<Real> seedPoint((m_points[i] + m_points[j] + m_points[k]) / 3.0); Vec3<Real> hitPoint; Vec3<Real> hitNormal; normal = -normal; size_t faceIndex = m_nTriangles; Float dist; long hitTriangle; if (rm.Raycast(seedPoint,normal,hitTriangle,dist, hitPoint, hitNormal)) { faceIndex = hitTriangle; } if (faceIndex < m_nTriangles ) { m_extraDistPoints[f] = hitPoint; m_extraDistNormals[f] = hitNormal; m_graph.m_vertices[f].m_distPoints.PushBack(DPoint(m_nPoints+f, 0, false, true)); } // Atomic update of the progress #ifdef THREAD_DIST_POINTS #pragma omp critical #endif { completed++; progress = completed * 100.0 / m_nTriangles; if (fabs(progress-progressOld) > ptgStep && m_callBack) { sprintf(msg, "%3.2f %% \t \t \r", progress); (*m_callBack)(msg, progress, 0.0, m_nTriangles); progressOld = progress; } } } } for (size_t v = 0; v < m_nPoints; v++) { m_normals[v].Normalize(); } }
void HACD::InitializeDualGraph() { long i, j, k; Vec3<Real> u, v, w, normal; delete [] m_normals; m_normals = new Vec3<Real>[m_nPoints]; if (m_addFacesPoints) { delete [] m_facePoints; delete [] m_faceNormals; m_facePoints = new Vec3<Real>[m_nTriangles]; m_faceNormals = new Vec3<Real>[m_nTriangles]; } memset(m_normals, 0, sizeof(Vec3<Real>) * m_nPoints); for(unsigned long f = 0; f < m_nTriangles; f++) { if (m_callBack) (*m_callBack)("+ InitializeDualGraph\n", f, m_nTriangles, 0); if (gCancelRequest) return; i = m_triangles[f].X(); j = m_triangles[f].Y(); k = m_triangles[f].Z(); m_graph.m_vertices[f].m_distPoints[i].m_distOnly = false; m_graph.m_vertices[f].m_distPoints[j].m_distOnly = false; m_graph.m_vertices[f].m_distPoints[k].m_distOnly = false; ICHull * ch = new ICHull; m_graph.m_vertices[f].m_convexHull = ch; ch->AddPoint(m_points[i], i); ch->AddPoint(m_points[j], j); ch->AddPoint(m_points[k], k); ch->SetDistPoints(&m_graph.m_vertices[f].m_distPoints); u = m_points[j] - m_points[i]; v = m_points[k] - m_points[i]; w = m_points[k] - m_points[j]; normal = u ^ v; m_normals[i] += normal; m_normals[j] += normal; m_normals[k] += normal; m_graph.m_vertices[f].m_surf = normal.GetNorm(); m_graph.m_vertices[f].m_perimeter = u.GetNorm() + v.GetNorm() + w.GetNorm(); normal.Normalize(); m_graph.m_vertices[f].m_boudaryEdges.insert(GetEdgeIndex(i,j)); m_graph.m_vertices[f].m_boudaryEdges.insert(GetEdgeIndex(j,k)); m_graph.m_vertices[f].m_boudaryEdges.insert(GetEdgeIndex(k,i)); if(m_addFacesPoints) { m_faceNormals[f] = normal; m_facePoints[f] = (m_points[i] + m_points[j] + m_points[k]) / 3.0; m_graph.m_vertices[f].m_distPoints[-static_cast<long>(f)-1].m_distOnly = true; } if (m_addExtraDistPoints) {// we need a kd-tree structure to accelerate this part! long i1, j1, k1; Vec3<Real> u1, v1, normal1; normal = -normal; double distance = 0.0; double distMin = 0.0; size_t faceIndex = m_nTriangles; Vec3<Real> seedPoint((m_points[i] + m_points[j] + m_points[k]) / 3.0); long nhit = 0; for(size_t f1 = 0; f1 < m_nTriangles; f1++) { i1 = m_triangles[f1].X(); j1 = m_triangles[f1].Y(); k1 = m_triangles[f1].Z(); u1 = m_points[j1] - m_points[i1]; v1 = m_points[k1] - m_points[i1]; normal1 = (u1 ^ v1); if (normal * normal1 > 0.0) { nhit = IntersectRayTriangle(Vec3<double>(seedPoint.X(), seedPoint.Y(), seedPoint.Z()), Vec3<double>(normal.X(), normal.Y(), normal.Z()), Vec3<double>(m_points[i1].X(), m_points[i1].Y(), m_points[i1].Z()), Vec3<double>(m_points[j1].X(), m_points[j1].Y(), m_points[j1].Z()), Vec3<double>(m_points[k1].X(), m_points[k1].Y(), m_points[k1].Z()), distance); if ((nhit==1) && ((distMin > distance) || (faceIndex == m_nTriangles))) { distMin = distance; faceIndex = f1; } } } if (faceIndex < m_nTriangles ) { i1 = m_triangles[faceIndex].X(); j1 = m_triangles[faceIndex].Y(); k1 = m_triangles[faceIndex].Z(); m_graph.m_vertices[f].m_distPoints[i1].m_distOnly = true; m_graph.m_vertices[f].m_distPoints[j1].m_distOnly = true; m_graph.m_vertices[f].m_distPoints[k1].m_distOnly = true; if (m_addFacesPoints) { m_graph.m_vertices[f].m_distPoints[-static_cast<long>(faceIndex)-1].m_distOnly = true; } } } } for (size_t v = 0; v < m_nPoints; v++) { m_normals[v].Normalize(); } }