Example #1
0
void Delaunay::computeDelaunay(Mesh &mesh)
{
	int size = (int)mesh.getVerticesSize();
	if (size == 0)
	{
		return;
	}
	mesh.computeVerticesNormals();
	m_preSize = mesh.m_curIndex;

	TriangleSet triSet;
	// 依次遍历每个点,寻找最近邻,进行三角化
	for (; mesh.m_curIndex < size; mesh.m_curIndex++)
	{
		Vertex v = mesh.getVertex(mesh.m_curIndex);
		if (v.m_isInner)
		{
			mesh.pushTriBeginIndex((int)triSet.size());
			continue;
		}

		Vec3d normal = v.m_normal;
		int id = 2;
		// 判断法向量哪个不为0,z->y->x
		if (normal[2] != 0)		// z
		{
			id = 2;
		}
		else if (normal[1] != 0)// y
		{
			id = 1;
		}
		else if (normal[0] != 0)// x
		{
			id = 0;
		}
		else	// 法向量为(0, 0, 0),
		{
			mesh.pushTriBeginIndex((int)triSet.size());
			continue;
		}

		double minDistance = -1;
		int cnt = v.m_neighbors[0];					// 最近邻数目
		double dists[k];
		for (int j = 1; j < cnt + 1; j++)
		{
			Vec3d dv = mesh.getVertex(v.m_neighbors[j]).m_xyz - v.m_xyz;
			dists[j] = dv.ddot(dv);
		}
		minDistance = dists[1];
		VertexVector vVector, tmpvVector;
		// 将最近邻点投射到该点的切平面上
		for (int j = 1; j < cnt + 1; j++)
		{
			Vertex tmpv = mesh.getVertex(v.m_neighbors[j]);
			if (dists[j] < u * minDistance ||		// 去除非常接近的点
				(tmpv.m_index < v.m_index && tmpv.m_index >= m_preSize) ||	// 去除已遍历过的点
				tmpv.m_isInner)						// 去除内点
			{
				continue;
			}
			
			Vec3d vv = tmpv.m_xyz - v.m_xyz;
			double dist2 = dists[j] * 0.75f;	// sqrt
			double alpha = vv.dot(normal);
			alpha = alpha * alpha;
			if (alpha > dist2)		// 去除与法向量夹角小于30度或大于150度的点
			{
				continue;
			}
			Vec3d proj = tmpv.m_xyz - alpha * normal;		// 投射到切平面
			tmpvVector.push_back(Vertex(proj, v.m_neighbors[j]));
		}
		if (tmpvVector.size() < 3)	// 少于3个不能构成三角形
		{
			mesh.pushTriBeginIndex((int)triSet.size());
			continue;
		}

		// 将切平面转换为x-y平面进行三角形计算
		vVector.push_back(Vertex(Vec3d(0, 0, 0), mesh.m_curIndex));	// 原点
		Vec3d vx = tmpvVector[0].m_xyz - v.m_xyz;		// x轴
		vx = normalize(vx);
		for (int j = 0; j < tmpvVector.size(); j++)
		{
			Vec3d vv = tmpvVector[j].m_xyz - v.m_xyz;
			double x = vv.dot(vx);
			double y = vx.cross(vv)[id] / normal[id];
			Vec3d proj(x, y, 0);
			vVector.push_back(Vertex(proj, tmpvVector[j].m_index));
		}

		TriangleVector tVector;
		computeDelaunay(vVector, tVector);
// 		cout << vVector.size() << " " << tVector.size() << endl; 
// 		drawTrianglesOnPlane(tVector);
		for (int j = 0; j < tVector.size(); j++)
		{
			Triangle t = tVector[j];
			t.m_vertices[0] = mesh.getVertex(t.m_vertices[0].m_index);
			t.m_vertices[1] = mesh.getVertex(t.m_vertices[1].m_index);
			t.m_vertices[2] = mesh.getVertex(t.m_vertices[2].m_index);
			triSet.insert(t);
		}
		mesh.pushTriBeginIndex((int)triSet.size());
	}

	for (TriangleSet::iterator iter = triSet.begin(); 
		iter != triSet.end(); iter++)
	{
		mesh.m_triangles.push_back(*iter);
	}
}