我希望使用高斯函数平滑给定的 3D 网格,该网格使用半边结构来存储邻接信息。以下是提出的算法:
通过将每个顶点移动到由其直接邻居的加权平均值确定的位置来平滑网格(权重由高斯确定,sigma 等于连接到顶点的边的平均长度,归一化以使权重总和为 1)。
所以对于每个顶点curr_vertex
,我
- 计算其附加边的平均长度
- 获取所有相邻顶点
- 通过执行以下操作确定每个相邻顶点的权重:`
权重 = exp(-(距离*距离)/(2. sigma sigma))
where distance is the 3D distance between the
curr_vertexand the neighbor and
西格玛= average length of attached edges of
curr_vertex`
- 将所有权重相加并将每个邻居的权重除以该总和(归一化步骤)
- 将每个相邻顶点的位置乘以其相应的权重
- 将所有加权顶点相加并将结果添加到 curr_vertex 以生成新顶点。
当我这样做并运行我的算法时,实际发生的不是平滑而是缩放——我的网格只是被放大而没有任何明显的平滑。
对我做错了什么有任何想法吗?
编辑:这是我拥有的代码:
void R3Mesh::
Smooth(void)
{
R3Mesh *new_mesh = new R3Mesh(*this);
for(int i = 0; i < NVertices(); i++)
{
R3MeshVertex *v = Vertex(i);
map<R3MeshVertex *, double> neighbors; // stores vertex-weight pairs
map<R3MeshVertex *, double>::iterator neighbors_iter;
// store each vertex neighbor by going through
// all adjacent edges and obtaining those edges' vertices
R3MeshHalfEdge *tmp = v->half_edge;
do
{
neighbors.insert(make_pair(tmp->opposite->vertex,0));
tmp = tmp->opposite->next;
}while(tmp != v->half_edge);
// determine the sigma to use for Gaussian
double sigma = v->AverageEdgeLength();
double weight = 0, total_weight = 0;
double distance;
// determine and store the weight of each neighboring vertex
for(neighbors_iter = neighbors.begin(); neighbors_iter != neighbors.end();
neighbors_iter++)
{
distance = R3Distance(v->position, neighbors_iter->first->position);
weight = (1./(sigma*sqrt(2.*3.14)))*exp(-(distance*distance)/(2.*sigma*sigma));
total_weight += weight;
neighbors_iter->second = weight;
}
// determine new position of current vertex
R3Point new_pos = v->position;
for(neighbors_iter = neighbors.begin(); neighbors_iter != neighbors.end();
neighbors_iter++)
{
new_pos += (neighbors_iter->second/total_weight)*(neighbors_iter->first->position);
}
new_pos.Translate(new_pos - v->position);
new_mesh->Vertex(i)->position.Reset(new_pos.X(), new_pos.Y(), new_pos.Z());
neighbors.clear();
}
*this = *new_mesh;
}