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);
	}
}
Beispiel #2
0
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;
}