void cleanMesh(const Mesh& mesh, simple_mesh<typename mesh_adaptor<Mesh>::point_type>& result, typename mesh_adaptor<Mesh>::scalar minEdgeLength, std::vector<int>* point_remapping, std::vector<int>* poly_remapping) { typedef mesh_adaptor<Mesh> Adaptor; typedef typename Adaptor::scalar T; typedef typename Adaptor::point_type vec_type; typedef typename Adaptor::poly_type poly_type; typedef typename Adaptor::const_point_ref const_point_ref; typedef simple_mesh<vec_type> simple_mesh; typedef points_adaptor<poly_type> PointsAdaptor; typedef boost::unordered_map<unsigned int, unsigned int> u_u_map; typedef boost::unordered_set<unsigned int> u_set; typedef std::vector<unsigned int> u_vec; Adaptor a(mesh); unsigned int npoints = a.numPoints(); unsigned int npolys = a.numPolys(); T epsilon = minEdgeLength*minEdgeLength; // prepare output result.clear(); result.m_points.reserve(npoints/2); result.m_polys.reserve(npolys/2); if(point_remapping) { point_remapping->clear(); point_remapping->reserve(npoints/2); } if(poly_remapping) { poly_remapping->clear(); poly_remapping->reserve(npoints/2); } u_u_map degen_pt_map; u_vec pt_islands; u_set s; // iterate over edges. If an edge is too short, put both its pts into an island. If // the pts belong to different islands then merge the islands for(unsigned int i=0; i<npolys; ++i) { PointsAdaptor pa(a.getPoly(i)); unsigned int nverts = pa.size(); for(unsigned int j=0; j<nverts; ++j) { unsigned int k = (j+1) % nverts; if((pa[j] - pa[k]).length2() <= epsilon) { unsigned int pt1 = pa.index(j); unsigned int pt2 = pa.index(k); u_u_map::const_iterator it1 = degen_pt_map.find(pt1); u_u_map::const_iterator it2 = degen_pt_map.find(pt2); bool found1 = (it1 != degen_pt_map.end()); bool found2 = (it2 != degen_pt_map.end()); if(found1 && found2) { // merge islands pt_islands[it1->second] = pt_islands[it2->second]; } else if(found1 != found2) { // add new pt to existing island if(found1) degen_pt_map.insert(u_u_map::value_type(pt2, it1->second)); else degen_pt_map.insert(u_u_map::value_type(pt1, it2->second)); } else { // create new island containing both pts unsigned int n = pt_islands.size(); pt_islands.push_back(n); degen_pt_map.insert(u_u_map::value_type(pt1, n)); degen_pt_map.insert(u_u_map::value_type(pt2, n)); } } } } u_u_map pt_remap; u_u_map pt_island_remap; // iterate over polys, building a new point list as we go, and skipping polys that // are or have become degenerate for(int i=0; i<npolys; ++i) { PointsAdaptor pa(a.getPoly(i)); unsigned int nverts = pa.size(); if(nverts < 3) continue; // check if poly is degenerate unsigned int num_nondegen_pts = 0; s.clear(); for(unsigned int j=0; j<nverts; ++j) { unsigned int ptnum = pa.index(j); u_u_map::const_iterator it = degen_pt_map.find(ptnum); if(it == degen_pt_map.end()) ++num_nondegen_pts; else s.insert(pt_islands[it->second]); } unsigned int nverts_result = num_nondegen_pts + s.size(); if(nverts_result < 3) continue; // add poly, remapping verts at the same time result.m_polys.push_back(u_vec()); u_vec& resultPoly = result.m_polys.back(); resultPoly.resize(nverts_result); if(poly_remapping) poly_remapping->push_back((nverts_result == nverts)? i+1 : -1-i); unsigned int k = 0; s.clear(); for(unsigned int j=0; j<nverts; ++j) { unsigned int ptnum = pa.index(j); u_u_map::const_iterator it = pt_remap.find(ptnum); if(it == pt_remap.end()) { it = degen_pt_map.find(ptnum); if(it == degen_pt_map.end()) { unsigned int new_ptnum = result.m_points.size(); result.m_points.push_back(pa[j]); if(point_remapping) point_remapping->push_back(ptnum); pt_remap.insert(u_u_map::value_type(ptnum, new_ptnum)); resultPoly[k++] = new_ptnum; } else { unsigned int pt_island = pt_islands[it->second]; if(s.find(pt_island) == s.end()) { it = pt_island_remap.find(pt_island); if(it == pt_island_remap.end()) { unsigned int new_ptnum = result.m_points.size(); result.m_points.push_back(pa[j]); if(point_remapping) point_remapping->push_back(ptnum); pt_island_remap.insert(u_u_map::value_type(pt_island, new_ptnum)); resultPoly[k++] = new_ptnum; } else resultPoly[k++] = it->second; s.insert(pt_island); } } } else resultPoly[k++] = it->second; } assert(k == nverts_result); } }
unsigned int addMeshPoints(const Mesh& mesh, simple_mesh<typename mesh_adaptor<Mesh>::point_type>& result, EdgeIntersectionConstIterator pointsBegin, EdgeIntersectionConstIterator pointsEnd, std::vector<int>* point_remapping, std::vector<int>* poly_remapping) { typedef mesh_adaptor<Mesh> Adaptor; typedef typename Adaptor::index_type index_type; typedef typename Adaptor::scalar scalar_type; typedef typename Adaptor::point_type point_type; typedef typename Adaptor::const_point_ref const_point_ref; typedef EdgeIntersection<index_type,scalar_type> edge_intersection; typedef typename Adaptor::poly_type poly_type; typedef points_adaptor<poly_type> PointsAdaptor; typedef bidirectional_edge<index_type> bi_edge; typedef std::pair<scalar_type, index_type> mapped_intersection; typedef std::set<mapped_intersection> mapped_intersections; typedef boost::unordered_map<bi_edge, mapped_intersections> new_pt_map; BOOST_MPL_ASSERT((boost::is_same<edge_intersection, typename std::iterator_traits<EdgeIntersectionConstIterator>::value_type>)); Adaptor a(mesh); unsigned int npoints = a.numPoints(); unsigned int npolys = a.numPolys(); // prepare output result.clear(); result.m_points.resize(npoints); result.m_polys.resize(npolys); // create directly-mapped points unsigned int nnew_pts = 0; new_pt_map new_pts; for(unsigned int i=0; i<npoints; ++i) result.m_points[i] = a.getPoint(i); if(point_remapping) { point_remapping->resize(npoints); for(unsigned int i=0; i<npoints; ++i) (*point_remapping)[i] = i; } // append new points { mesh_points<Mesh> meshPts(mesh); for(EdgeIntersectionConstIterator it=pointsBegin; it!=pointsEnd; ++it) { if((it->m_point1 >= npoints) || (it->m_point2 >= npoints)) continue; unsigned int newpt_index = result.m_points.size(); result.m_points.push_back(point_type()); it->getPos(meshPts, result.m_points.back()); bi_edge e(it->m_point1, it->m_point2); mapped_intersections& mi = new_pts[e]; scalar_type frac = (e.first() == it->m_point1)? it->m_u : 1-it->m_u; mi.insert(mapped_intersection(frac, newpt_index)); if(point_remapping) point_remapping->push_back(-1); ++nnew_pts; } } // create polys if(poly_remapping) poly_remapping->resize(npolys); for(unsigned int i=0; i<npolys; ++i) { PointsAdaptor srcPoly(a.getPoly(i)); std::vector<index_type>& destPoly = result.m_polys[i]; destPoly.clear(); bool added_verts = false; unsigned int nverts = srcPoly.size(); for(unsigned int j=0; j<nverts; ++j) { unsigned int pt1 = srcPoly.index(j); unsigned int pt2 = srcPoly.index((j+1)%nverts); destPoly.push_back(pt1); bi_edge e(pt1, pt2); typename new_pt_map::const_iterator it = new_pts.find(e); if(it != new_pts.end()) { added_verts = true; const mapped_intersections& mis = it->second; bool reverse = (e.first() != pt1); if(reverse) { for(typename mapped_intersections::const_reverse_iterator it2=mis.rbegin(); it2!=mis.rend(); ++it2) destPoly.push_back(it2->second); } else { for(typename mapped_intersections::const_iterator it2=mis.begin(); it2!=mis.end(); ++it2) destPoly.push_back(it2->second); } } } if(poly_remapping) (*poly_remapping)[i] = (added_verts)? -1-i : i+1; } return nnew_pts; }