1 #ifndef TIL_MESH_DECIMATION 2 #define TIL_MESH_DECIMATION 14 template <
typename TVertexXsr,
typename TNeighborhoodXsr,
typename TPrec >
20 typedef typename TVertexXsr::value_type
Vertex;
26 : m_neighXsr(neighXsr)
27 , m_vertexXsr(vertexXsr)
28 , m_mc(vertexXsr, neighXsr)
37 NeighborhoodRef neigh = m_neighXsr(i);
38 for (
typename Neighborhood::const_iterator j = neigh.begin(); j != neigh.end(); ++j)
46 c *= TPrec(1.0) / neigh.size();
56 TNeighborhoodXsr m_neighXsr;
57 TVertexXsr m_vertexXsr;
69 template <
typename TVertexCollection,
typename TNeighborhoods,
typename TPrec >
73 typedef typename TVertexCollection::value_type
Vertex;
77 TVertexCollection
const & vertices
78 , TNeighborhoods
const & neighc
80 : m_vertices(vertices)
82 , m_mc(vertices, neighc)
91 for (std::size_t j = 0; j < m_neighc[i].size(); ++j)
93 c += m_vertices[m_neighc[i][j]];
95 c *= TPrec(1.0) / m_neighc[i].size();
103 const TVertexCollection & m_vertices;
104 const TNeighborhoods & m_neighc;
133 template <
typename T >
138 GroComp(T a, T b, T c)
145 helper(T a, T b, T c)
154 template <
typename TFace >
158 f->face == helper(m_a, m_b, m_c) ||
159 f->face == helper(m_c, m_a, m_b) ||
160 f->face == helper(m_b, m_c, m_a) ||
161 f->face == helper(m_b, m_a, m_c) ||
162 f->face == helper(m_c, m_b, m_a) ||
163 f->face == helper(m_a, m_c, m_b)
182 friend bool operator<(
const Temp & x,
const Temp & y) {
return x.angle < y.angle; }
186 bool operator()(
const Temp & x,
const Temp & y) {
return x.angle < y.angle; }
195 template <
typename TPo
intIterator,
typename TOutIterator >
202 for (; pbegin != pend; ++pbegin)
204 miny =
min(miny, (*pbegin)[1]);
211 M[1] = 2*miny/3 + (k1+k2)/6;
214 A[0] = (miny - k1) * (1/
std::sqrt(3.0f));
217 B[0] = (k2 - miny) * (1/
std::sqrt(3.0f));
250 std::list<boost::array<std::size_t,3> >
254 typedef std::list<Face> FaceList;
257 std::size_t n = points.size();
260 assert(points.size() >= 4);
271 for (std::size_t i = 0; i < points.size(); ++i)
273 miny =
min(miny, points[i][1]);
274 k1 =
max(k1, points[i][1] -
std::sqrt(3.0f)*points[i][0]);
275 k2 =
max(k2, points[i][1] +
std::sqrt(3.0f)*points[i][0]);
280 M[1] = 2*miny/3 + (k1+k2)/6;
283 A[0] = (miny - k1) * (1/
std::sqrt(3.0f));
286 B[0] = (k2 - miny) * (1/
std::sqrt(3.0f));
301 faces.push_back(face);
308 for (std::size_t i = 0; i < n; ++i)
313 std::set<std::size_t> neighbors;
317 FaceList::iterator f = faces.begin();
318 while (f != faces.end())
321 if (geo::is_in_circumcircle<double>(points[i], points[(*f)[0]], points[(*f)[1]], points[(*f)[2]]))
324 neighbors.insert((*f)[0]);
325 neighbors.insert((*f)[1]);
326 neighbors.insert((*f)[2]);
337 assert(neighbors.size() >= 3);
341 std::vector<Temp> tmp;
342 tmp.reserve(neighbors.size());
343 for (std::set<std::size_t>::iterator iNeighbor = neighbors.begin(); iNeighbor != neighbors.end(); ++iNeighbor)
346 t.index = *iNeighbor;
355 for (std::size_t it = 0; it < tmp.size(); ++it)
358 Face face = { {i, tmp[it].index, tmp[ (it+1) % tmp.size() ].index } };
359 faces.push_back(face);
375 FaceList::iterator f = faces.begin();
376 while (f != faces.end())
400 for (FaceList::iterator f = faces.begin(); f != faces.end(); ++f)
402 if (
cross(points[(*f)[1]] - points[(*f)[0]], points[(*f)[2]] - points[(*f)[0]]) < 0)
411 if (faces.size() != n-2)
444 FaceList::iterator f = faces.begin();
445 while (f != faces.end())
447 bool flagdel =
false;
449 for (
int i = 0; i < 3; ++i)
451 if ((*f)[i] > (*f)[(i+1)%3])
461 if (flagdel) f = faces.erase(f);
467 if (faces.size() != n-2)
469 std::cout <<
"NI2!" << faces.size() <<
"-" << n << std::endl;
471 std::cout <<
"faces2" << std::endl;
472 for (FaceList::iterator f = faces.begin(); f != faces.end(); ++f)
474 std::cout << (*f)[0] <<
" " << (*f)[1] <<
" " << (*f)[2] << std::endl;
476 std::cout <<
"endfaces" << std::endl;
477 std::cout <<
"points" << std::endl;
478 for (std::size_t i = 0; i < n; ++i) std::cout << points[i] << std::endl;
479 std::cout <<
"end points" << std::endl;
486 std::set<boost::array<std::size_t,2> > outer_edges;
487 for (FaceList::iterator f = faces.begin(); f != faces.end(); ++f)
489 for (std::size_t i = 0; i < 3; ++i)
491 std::size_t delta =
std::abs(
int((*f)[i]) -
int((*f)[(i+1)%3]));
492 if (delta == 1 || delta == (n-1))
495 outer_edges.insert(tmp);
499 if (outer_edges.size() != n)
525 template <
typename TVertexNode,
typename TFaceNode >
526 typename std::list<TVertexNode>::iterator
529 typename std::list<TVertexNode>::iterator i,
530 std::list<TVertexNode> & graph_vertices,
531 std::list<TFaceNode> & graph_faces
535 for (
typename TVertexNode::FaceIndexCollection::iterator j = i->faces().begin(); j != i->faces().end(); ++j)
538 for (std::size_t k = 0; k < 3; ++k)
542 if ((*j)->face[k] == i)
continue;
544 std::size_t tmp = (*j)->face[k]->faces().size();
546 (*j)->face[k]->faces().remove(*j);
547 assert((*j)->face[k]->faces().size() == tmp-1);
551 std::size_t tmp = graph_faces.size();
553 graph_faces.erase(*j);
554 assert(graph_faces.size() == tmp-1);
558 for (
typename TVertexNode::VertexIndexCollection::iterator j = i->neighbors().begin(); j != i->neighbors().end(); ++j)
560 (*j)->neighbors().remove(i);
563 return graph_vertices.erase(i);
570 template <
typename TNeighbors >
571 std::vector<numeric_array<float,2> >
576 const TNeighbors & neighbors
585 std::vector<double> angles;
586 std::vector<double> norms;
587 angles.reserve(neighbors.size());
588 norms.reserve(neighbors.size());
590 typename TNeighbors::const_iterator n = neighbors.begin();
593 for (; n != neighbors.end(); ++n, ++n2)
621 std::partial_sum(angles.begin(), angles.end(), angles.begin());
630 std::transform(angles.begin(), angles.end(), angles.begin(), std::bind2nd(std::multiplies<double>(), 2*
M_PI/angles.back()));
638 std::vector<numeric_array<float, 2> > res(neighbors.size());
639 for (std::size_t i = 0; i <
size(res); ++i)
641 res[i][0] = std::cos(angles[i]) * norms[i];
642 res[i][1] = std::sin(angles[i]) * norms[i];
664 template <
typename T >
667 ValueFinder(T value) : m_value(value) {}
672 template <
typename T >
673 ValueFinder<T> valueFinder(T value) {
return ValueFinder<T>(value); }
680 template <
typename TVertexNode,
typename TFaceNode >
694 typedef std::list<NeighborGraphNode> NeighborGraph;
695 typedef typename TVertexNode::VertexIndexCollection::value_type VertexPointer;
699 Vertex_remover(std::list<TVertexNode> & graph_vertices, std::list<TFaceNode> & graph_faces)
700 : m_graph_vertices(graph_vertices)
701 , m_graph_faces(graph_faces)
707 std::vector<VertexPointer> &
neighbors() {
return m_neighbors; }
715 bool neighborTriangulation(VertexPointer i)
718 std::size_t nneigh = m_neighbors.size();
726 else if (nneigh == 3)
729 m_tri.push_back(tmp);
735 m_error = invalid_neighborhood;
740 if (m_tri.size() != nneigh - 2)
742 m_error = triangulation_failure;
743 std::cout <<
"wK!" << m_tri.size() <<
"-" << nneigh-2;
752 void initializeOrientedEdges(VertexPointer i)
754 std::size_t nneigh = m_neighbors.size();
755 m_convmap.resize(nneigh);
756 for (std::size_t j = 0; j < nneigh; ++j)
760 for (
typename TVertexNode::VertexIndexCollection::const_iterator k = m_neighbors[j]->neighbors().begin(); k != m_neighbors[j]->neighbors().end(); ++k)
762 if (*k == i)
continue;
763 NeighborGraphNode node(*k);
764 m_convmap[j][*k] = m_neighborGraph[j].insert(m_neighborGraph[j].end(), node);
769 typename TVertexNode::VertexIndexCollection::const_iterator k = m_neighbors[j]->neighbors().begin();
775 for (; k != m_neighbors[j]->neighbors().end(); ++k, ++k2, ++k3)
777 if (*k2 == i)
continue;
778 if (*k != i) m_convmap[j][*k2]->from.push_back(m_convmap[j][*k]);
779 if (*k3 != i) m_convmap[j][*k2]->to.push_back(m_convmap[j][*k3]);
787 void updateNeighborGraph()
791 for (std::size_t n = 0; n < 3; ++n)
793 typename NeighborGraph::iterator p2, p3;
795 p2 = std::find_if(m_neighborGraph[(*newf)[n]].begin(), m_neighborGraph[(*newf)[n]].end(), valueFinder(m_neighbors[(*newf)[(n+1)%3]]));
796 p3 = std::find_if(m_neighborGraph[(*newf)[n]].begin(), m_neighborGraph[(*newf)[n]].end(), valueFinder(m_neighbors[(*newf)[(n+2)%3]]));
797 if (p2 == m_neighborGraph[(*newf)[n]].end()) p2 = m_neighborGraph[(*newf)[n]].insert(p2, NeighborGraphNode(m_neighbors[(*newf)[(n+1)%3]]));
798 if (p3 == m_neighborGraph[(*newf)[n]].end()) p3 = m_neighborGraph[(*newf)[n]].insert(p3, NeighborGraphNode(m_neighbors[(*newf)[(n+2)%3]]));
800 p2->to.push_back(p3);
801 p3->from.push_back(p2);
808 bool checkNeighborsHaveThreeNeighbors()
810 for (std::size_t k = 0; k < m_neighborGraph.size(); ++k)
812 if (m_neighborGraph[k].
size() < 3)
822 bool checkCorrectNeighborhood()
824 for (std::size_t k = 0; k < m_neighborGraph.size(); ++k)
827 typename NeighborGraph::iterator p = m_neighborGraph[k].begin();
828 typename NeighborGraph::iterator p0 = p;
845 if (p->to.size() != 1 || p->from.size() != 1)
859 void addFaces(VertexPointer i)
865 for (std::size_t n = 0; n < 3; ++n)
867 f.face[n] = m_neighbors[(*newf)[n]];
870 typename std::list<TFaceNode>::iterator gf = m_graph_faces.insert(m_graph_faces.end(), f);
872 i->faces().front()->face[0]->pos() - i->faces().front()->face[1]->pos(),
873 i->faces().front()->face[0]->pos() - i->faces().front()->face[2]->pos()
876 for (std::size_t n = 0; n < 3; ++n)
878 GroComp<VertexPointer> grocomp(f.face[0], f.face[1], f.face[2]);
879 typename TVertexNode::FaceIndexCollection::iterator p = find_if(f.face[n]->faces().begin(), f.face[n]->faces().end(), grocomp);
880 if (p != f.face[n]->faces().end())
882 std::cout <<
"FATAL: face already there: " << std::endl;
883 std::cout << &*f.face[0] <<
" " << &*f.face[1] <<
" " << &*f.face[2] << std::endl;
884 std::cout << &*(*p)->face[0] <<
" " << &*(*p)->face[1] <<
" " << &*(*p)->face[2] << std::endl;
885 std::cout <<
"I'll continue as if nothing happened, but this is a bug and your algorithm is likely to go bananas :)" << std::endl;
900 f.face[n]->faces().push_back(gf);
907 for (std::size_t j = 0; j < i->neighbors().size(); ++j)
909 typename TVertexNode::VertexIndexCollection ntmp = m_neighbors[j]->neighbors();
912 m_neighbors[j]->neighbors().clear();
914 typename NeighborGraph::iterator p = m_neighborGraph[j].begin();
915 typename NeighborGraph::iterator p0 = p;
919 if (flag) {
if (p == p0)
break; }
921 m_neighbors[j]->neighbors().push_back(p->value);
922 if (p->to.size() != 1)
957 if (p->to.size() == 0)
break;
973 m_neighbors.resize(i->neighbors().size());
975 std::copy(i->neighbors().begin(), i->neighbors().end(), m_neighbors.begin());
976 if (!this->neighborTriangulation(i))
return false;
979 m_neighborGraph.clear();
980 m_neighborGraph.resize(m_neighbors.size());
982 this->initializeOrientedEdges(i);
984 this->updateNeighborGraph();
986 if (!this->checkNeighborsHaveThreeNeighbors())
return false;
991 if (!this->checkCorrectNeighborhood())
return false;
998 VertexPointer
remove(VertexPointer i)
1208 m_neighbors.resize(i->neighbors().size());
1209 std::copy(i->neighbors().begin(), i->neighbors().end(), m_neighbors.begin());
1216 if (m_neighbors.size() >= 4)
1221 else if (m_neighbors.size() == 3)
1224 m_tri.push_back(tmp);
1228 else std::cout <<
"w2!";
1231 if (m_tri.size() != m_neighbors.size() - 2)
1233 std::cout <<
"wK!" << m_tri.size() <<
"-" << m_neighbors.size() - 2;
1239 m_neighborGraph.clear();
1240 m_neighborGraph.resize(i->neighbors().size());
1242 m_convmap.resize(i->neighbors().size());
1243 for (std::size_t j = 0; j < i->neighbors().size(); ++j)
1247 for (
typename TVertexNode::VertexIndexCollection::const_iterator k = m_neighbors[j]->neighbors().begin(); k != m_neighbors[j]->neighbors().end(); ++k)
1249 if (*k == i)
continue;
1250 NeighborGraphNode node(*k);
1251 m_convmap[j][*k] = m_neighborGraph[j].insert(m_neighborGraph[j].end(), node);
1256 typename TVertexNode::VertexIndexCollection::const_iterator k = m_neighbors[j]->neighbors().begin();
1262 for (; k != m_neighbors[j]->neighbors().end(); ++k, ++k2, ++k3)
1264 if (*k2 == i)
continue;
1265 if (*k != i) m_convmap[j][*k2]->from.push_back(m_convmap[j][*k]);
1266 if (*k3 != i) m_convmap[j][*k2]->to.push_back(m_convmap[j][*k3]);
1275 for (std::size_t n = 0; n < 3; ++n)
1277 typename NeighborGraph::iterator p2, p3;
1279 p2 = std::find_if(m_neighborGraph[(*newf)[n]].begin(), m_neighborGraph[(*newf)[n]].end(), valueFinder(m_neighbors[(*newf)[(n+1)%3]]));
1280 p3 = std::find_if(m_neighborGraph[(*newf)[n]].begin(), m_neighborGraph[(*newf)[n]].end(), valueFinder(m_neighbors[(*newf)[(n+2)%3]]));
1281 if (p2 == m_neighborGraph[(*newf)[n]].end()) p2 = m_neighborGraph[(*newf)[n]].insert(p2, NeighborGraphNode(m_neighbors[(*newf)[(n+1)%3]]));
1282 if (p3 == m_neighborGraph[(*newf)[n]].end()) p3 = m_neighborGraph[(*newf)[n]].insert(p3, NeighborGraphNode(m_neighbors[(*newf)[(n+2)%3]]));
1284 p2->to.push_back(p3);
1285 p3->from.push_back(p2);
1291 for (std::size_t k = 0; k < m_neighborGraph.size(); ++k)
1293 if (m_neighborGraph[k].
size() < 3)
1303 for (std::size_t k = 0; k < m_neighborGraph.size(); ++k)
1305 typename NeighborGraph::iterator p = m_neighborGraph[k].begin();
1306 typename NeighborGraph::iterator p0 = p;
1310 if (flag) {
if (p == p0)
break; }
1312 if (p->to.size() != 1 || p->from.size() != 1)
1328 for (std::size_t n = 0; n < 3; ++n)
1330 f.face[n] = m_neighbors[(*newf)[n]];
1333 typename std::list<TFaceNode>::iterator gf = m_graph_faces.insert(m_graph_faces.end(), f);
1339 for (std::size_t n = 0; n < 3; ++n)
1341 GroComp<VertexPointer> grocomp(f.face[0], f.face[1], f.face[2]);
1342 typename TVertexNode::FaceIndexCollection::iterator p = find_if(f.face[n]->faces().begin(), f.face[n]->faces().end(), grocomp);
1343 if (p != f.face[n]->faces().end())
1345 std::cout <<
"FATAL: face already there: " << std::endl;
1346 std::cout << &*f.face[0] <<
" " << &*f.face[1] <<
" " << &*f.face[2] << std::endl;
1347 std::cout << &*(*p)->face[0] <<
" " << &*(*p)->face[1] <<
" " << &*(*p)->face[2] << std::endl;
1348 std::cout <<
"I'll continue as if nothing happened, but this is a bug and your algorithm is likely to go bananas :)" << std::endl;
1350 f.face[n]->faces().push_back(gf);
1356 for (std::size_t j = 0; j < i->neighbors().size(); ++j)
1358 typename TVertexNode::VertexIndexCollection ntmp = m_neighbors[j]->neighbors();
1361 m_neighbors[j]->neighbors().clear();
1363 typename NeighborGraph::iterator p = m_neighborGraph[j].begin();
1364 typename NeighborGraph::iterator p0 = p;
1368 if (flag) {
if (p == p0)
break; }
1370 m_neighbors[j]->neighbors().push_back(p->value);
1371 if (p->to.size() != 1)
1375 if (p->to.size() == 0)
break;
1388 std::list<TVertexNode> & m_graph_vertices;
1389 std::list<TFaceNode> & m_graph_faces;
1397 std::vector<VertexPointer> m_neighbors;
1398 std::vector<NeighborGraph> m_neighborGraph;
1400 std::list<boost::array<std::size_t,3> > m_tri;
1412 template <
typename TIndexCollection >
1430 unsigned int niter()
const {
return m_iter; }
1433 unsigned int count()
const {
return m_count; }
1436 std::vector<unsigned char>
const &
removed() {
return m_res; }
1442 std::list<VertexNode> & graph_vertices
1443 , std::list<FaceNode> & graph_faces
1444 , TIndexCollection
const & removed
1447 std::size_t nVertices = graph_vertices.size();
1448 assert(removed.size() == nVertices);
1451 m_res.resize(nVertices, 0);
1463 std::list<VertexNode>::iterator i = graph_vertices.begin();
1464 std::list<FaceNode>::iterator itmp;
1465 while (i != graph_vertices.end())
1467 if (i->neighbors().size() != i->faces().size())
1469 std::cout <<
"[SERIOUS TOPOLOGY ERROR] F!=N -- I most probably screwed up your mesh, please report error; " << std::flush;
1472 std::size_t iInd = i->attribute();
1474 if (removed[iInd] == 1)
1480 if (vertexRemover(i))
1505 unsigned int m_iter;
1506 unsigned int m_count;
1507 std::vector<unsigned char> m_res;
1517 template <
typename TVertexCollection,
typename TFaceCollection,
typename TCNeighborhoods,
typename TIndexCollection >
1533 unsigned int count() {
return m_remover.count(); }
1536 std::vector<unsigned char>
const &
removed() {
return m_remover.removed(); }
1541 TVertexCollection
const & vertices
1542 , TFaceCollection
const & faces
1543 , TCNeighborhoods
const & neighc
1544 , TIndexCollection
const & removed
1545 , TVertexCollection & verticesOut
1546 , TFaceCollection & facesOut
1555 typename VertexNodeCollection::iterator it = graph_vertices.begin();
1556 std::size_t gvsize = graph_vertices.size();
1557 for (std::size_t i = 0; i < gvsize; ++i, ++it)
1559 it->attribute() = i;
1563 m_remover(graph_vertices, graph_faces, removed);
1566 g2l(graph_vertices, graph_faces, verticesOut, facesOut);
1583 template <
typename TVertexCollection,
typename TFaceCollection,
typename TCNeighborhoods,
typename TIndexCollection >
1585 std::vector<unsigned char>
1588 TVertexCollection & vertices,
1589 TFaceCollection & faces,
1590 TCNeighborhoods
const & neighc,
1591 TIndexCollection
const & removed
1596 remover(vertices, faces, neighc, removed, vertices, faces);
1605 template <
typename TVertexCollection,
typename TNeighborhoodCollection >
1616 enum { UNPROCESSED = 0, KEEP, REMOVE };
1620 TVertexCollection
const & vertices
1621 , TNeighborhoodCollection
const & neighs
1622 , LabelCollection & label
1624 : m_vertices(vertices)
1628 assert(vertices.size() == neighs.size());
1629 m_label.resize(vertices.size(), UNPROCESSED);
1632 TVertexCollection
const &
vertices() {
return m_vertices; }
1633 TNeighborhoodCollection
const &
neighs() {
return m_neighs; }
1634 LabelCollection &
label() {
return m_label; }
1640 if (label()[i] != UNPROCESSED)
return false;
1642 label()[i] = REMOVE;
1644 for (std::size_t j = 0; j < neighs()[i].size(); ++j)
1646 assert(neighs()[i][j] < label().
size());
1647 assert(label()[neighs()[i][j]] != REMOVE);
1648 label()[neighs()[i][j]] = KEEP;
1653 TVertexCollection
const & m_vertices;
1654 TNeighborhoodCollection
const & m_neighs;
1656 LabelCollection & m_label;
1663 template <
typename TVertexCollection,
typename TFaceCollection >
1664 std::list<std::size_t>
1667 TVertexCollection & vertices
1668 , TFaceCollection & faces
1669 , std::size_t newSize
1675 std::list<std::size_t> res(vertices.size());
1679 if (newSize >= vertices.size())
return res;
1684 std::size_t n = vertices.size();
1686 typedef std::vector<std::vector<std::size_t> > Neighborhoods;
1695 std::vector<std::pair<std::size_t, float> > sortedCurv(n);
1696 for (std::size_t i = 0; i < n; ++i)
1702 sortedCurv[i] = std::make_pair(i, mwe(i));
1711 std::vector<unsigned char> removed;
1713 declabeler(vertices, *neighc, removed);
1714 std::size_t count = 0;
1715 for (std::size_t i0 = 0; i0 < n; ++i0)
1718 std::size_t i = sortedCurv[i0].first;
1720 if (!declabeler(i))
continue;
1722 for (std::size_t j = 0; j < (*neighc)[i].size(); ++j)
1724 vertices[(*neighc)[i][j]] += (vertices[i] - vertices[(*neighc)[i][j]]) * (1.0f / (*neighc)[i].size());
1728 if (n - count < newSize)
break;
1731 for (std::size_t i = 0; i < n; ++i) removed[i] = (removed[i] == 2 ? 1 : 0);
1733 std::vector<unsigned char> tmp
1738 std::list<std::size_t>::iterator iRes = res.begin();
1739 for (; iRes != res.end(); ++i)
1743 iRes = res.erase(iRes);
1753 }
while (vertices.size() > newSize);
1762 template <
typename TVertexCollection,
typename TFaceCollection >
1763 std::list<std::size_t>
1766 TVertexCollection & vertices
1767 , TFaceCollection & faces
1770 std::size_t n = vertices.size();
1773 std::list<std::size_t> res(n);
1776 typedef std::vector<std::vector<std::size_t> > Neighborhoods;
1781 std::vector<std::pair<std::size_t, float> > sortedCurv(n);
1782 for (std::size_t i = 0; i < n; ++i)
1784 sortedCurv[i] = std::make_pair(i, mwe(i));
1790 std::vector<unsigned char> removed;
1792 declabeler(vertices, *neighc, removed);
1793 for (std::size_t i0 = 0; i0 < n; ++i0)
1796 std::size_t i = sortedCurv[i0].first;
1798 if (!declabeler(i))
continue;
1800 for (std::size_t j = 0; j < (*neighc)[i].size(); ++j)
1802 vertices[(*neighc)[i][j]] += (vertices[i] - vertices[(*neighc)[i][j]]) * (1.0f / (*neighc)[i].size());
1806 for (std::size_t i = 0; i < n; ++i) removed[i] = (removed[i] == 2 ? 1 : 0);
1808 std::vector<unsigned char> tmp
1813 std::list<std::size_t>::iterator iRes = res.begin();
1814 for (; iRes != res.end(); ++i)
1818 iRes = res.erase(iRes);
TVertexXsr::value_type Vertex
std::vector< Label > LabelCollection
numeric_array< TPrec, 3 > cross(const numeric_array< T1, 3 > &vec1, const numeric_array< T2, 3 > &vec2, prec< TPrec >)
Return the cross product of two 3D vectors.
boost::enable_if< is_Image< TImage >, typename TImage::value_type >::type min(const TImage &im)
std::vector< numeric_array< float, 2 > > simple_neighborhood_flattening(const numeric_array< float, 3 > &point, const TNeighbors &neighbors)
void sqrt(const TImage &in, TImage &out)
MeshVertexNodeX< std::size_t > VertexNode
Distance of a vertex to the mean of its neighbors divided by the area of its Voronoi cell...
bool complete() const
Returns true if it has been able to remove all desired points.
shared_ptr< std::vector< std::vector< typename TFaceCollection::value_type::value_type > > > circular_neighborhoods(TFaceCollection const &faces, std::size_t nVertices)
Get point neighbors so that they form a loop around points.
TPrec operator()(std::size_t i)
std::list< FaceNode > FaceNodeCollection
std::vector< VertexPointer > & neighbors()
TPrec dot(const numeric_array< T1, D > &a1, const numeric_array< T2, D > &a2, prec< TPrec >)
Return the dot product of two vectors.
INLINE double norm(const T &a, const T &b)
< Euclidean norm of 2D vector (a, b)
TNeighborhoodCollection const & neighs()
Belongs to package Box Do not include directly, include til/Box.h instead.
A const cyclic iterator is a const iterator that goes back to the begining of the container when it r...
std::vector< unsigned char > const & removed()
Returns a binary index of those points who have been removed.
std::list< std::size_t > quantizer(TVertexCollection &vertices, TFaceCollection &faces, std::size_t newSize)
Decimates a mesh until a specified number of vertices is reached.
void sort(T &a, T &b, T &c)
Sort a, b, c in decreasing order (a>=b>=c).
TPrec operator()(index_type i)
LabelCollection & label()
numeric_array< T, D > size(const Box< T, D > &box)
Return the size of a box.
TNeighborhoodXsr::reference NeighborhoodRef
TVertexCollection::value_type Vertex
std::list< VertexNode > VertexNodeCollection
numeric_array< T, D > abs(const numeric_array< T, D > &a)
Absolute value, element-wise.
std::list< boost::array< std::size_t, 3 > > simple_delaunay_triangulation(std::vector< numeric_array< float, 2 > > points)
std::vector< unsigned char > const & removed()
Returns a binary index of those points who have been removed.
TImage::value_type max(const TImage &im)
Returns the maximum intensity of the input image.
std::unique_ptr< VoxelList > addNeighbors(TImage &seg, const std::vector< numeric_array< int, 3 > > &vl, const std::vector< numeric_array< int, 3 > > &vnh, Ghost &ghost, typename TImage::value_type newColor)
< New boundary points
bool operator()(std::size_t i)
Try to remove i-th point. Returns true if successful.
bool complete()
Returns true if it has been able to remove all desired points.
void process(index_type i)
Computes all the good stuff at the i-th vertex.
Vertex_remover(std::list< TVertexNode > &graph_vertices, std::list< TFaceNode > &graph_faces)
T angle(T x, T y, T norm)
Returns the angle between (x,y) and the x-axis, with the norm of (x,y) provided.
TPrec dist(const numeric_array< T1, D > &v1, const numeric_array< T2, D > &v2, prec< TPrec >)
Return the Euclidean distance between two arrays.
TVertexCollection const & vertices()
void copy(const TImage &in, TImage &out)
Copy one image to another.
unsigned int count() const
Returns the number of points that have been effectively removed.
std::list< TVertexNode >::iterator remove_vertex(typename std::list< TVertexNode >::iterator i, std::list< TVertexNode > &graph_vertices, std::list< TFaceNode > &graph_faces)
Remove a vertex from a mesh.
Remove vertices from a mesh, given a set of index.
bool operator<(const AimsVector< T, D > &v1, const AimsVector< T, D > &v2)
Lexicographic order.
operator< on the address in memory of the pointed object
A class to remove a vertex from a mesh, and remeshing the hole.
TOutIterator bounding_triangle(TPointIterator pbegin, TPointIterator pend, TOutIterator out)
Given a list of 2D points, compute a bounding equilateral triangle.
Remove vertices from a graph list mesh, given a set of index.
TNeighborhoodXsr::value_type Neighborhood
A class which returns a value that is increased everytime it is returned.
void max_helper(T &maxx, T x)
Little helper for something often used when looking for a maximum.
unsigned int count()
Returns the number of points that have been effectively removed.
Remove_indexed_graph_vertices< TIndexCollection >::VertexNodeCollection VertexNodeCollection
bool isRemovable(VertexPointer i)
Check that vertex i can be removed from the mesh.
prec_type voronoiArea() const
Return computed voronoi area at vertex.
MeshFaceNodeX< VertexNode > FaceNode
Attempt to label a vertex as removable, and if successfull, label its neighbors as unremovable...
std::vector< unsigned char > remove_vertices(TVertexCollection &vertices, TFaceCollection &faces, TCNeighborhoods const &neighc, TIndexCollection const &removed)
NB: vertices are not removed one by one but in groups via this kind of functions, because the static ...
Remove_indexed_graph_vertices< TIndexCollection >::FaceNodeCollection FaceNodeCollection
TVertexXsr::index_type index_type
bool operator()(VertexPointer &i)
std::list< std::size_t > quantizer_2(TVertexCollection &vertices, TFaceCollection &faces)
Decimates a mesh until no more vertex with unremoved neighbors can be removed.
void list2graph_mesh_conversion(const TVerticesIn &verticesIn, const TFacesIn &facesIn, const TNeighbors &neighc, std::list< TVertexNode > &verticesOut, std::list< TFaceNode > &facesOut)
Remove_indexed_graph_vertices< TIndexCollection > & remover()
operator> on the second member of a pair.
A dummy class used to pass a precision type for computations to some functions.
MeshWaveletEnergy2(const TVertexXsr &vertexXsr, const TNeighborhoodXsr &neighXsr)
unsigned int niter() const
Number of iterations that has been necessary to remove all points or to reach a configuration where n...