Mesh lissage gaussien avec
Question
Je souhaite lisser un maillage 3D donné, qui utilise la structure demi-bord pour stocker des informations contiguïté, en utilisant une fonction gaussienne. Ce qui suit est l'algorithme qui a été proposé:
lisser le maillage en déplaçant chaque sommet à une position déterminée par un pondéré moyenne de ses voisins immédiats (Avec des poids déterminés par une gaussienne avec sigma égale à la longueur moyenne Les bords de joint au sommet, normalisée de telle sorte que la somme des poids à un).
Ainsi, pour chaque curr_vertex
sommet, I
- calculer la durée moyenne de ses bords joints
- obtenir tous les sommets voisins
- déterminer le poids de chaque sommet voisin en procédant comme suit: `
poids = exp (- (distance distance *) / (2. sigma sigma))
where distance is the 3D distance between the
curr_vertexand the neighbor and
sigma= average length of attached edges of
curr_vertex`
- résumer tous les poids et diviser le poids de chaque voisin par cette somme (étape de normalisation)
- multiplier la position de chaque sommet voisin par son poids correspondant
- additionnez tous les sommets pondérés et ajouter le résultat à curr_vertex pour produire le nouveau sommet.
Quand je fais cela et exécuter mon algorithme, au lieu de lisser ce qui se passe en réalité est une échelle - ma maille juste s'agrandit sans lissage apparent
.Les réflexions sur ce que je fais mal?
Edit: Voici le code que j'ai:
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;
}
La solution
relents d'une tête-slapping bug de style typo. L'algorithme que vous avez décrit semble bien pour moi.
Tout d'abord vérifier clairement la normalisation des poids.
Vérifiez ensuite votre code où vous écrivez de nouveau le sommet calculé pos dans le nouveau maillage lissé.
Ce sont mes suppositions. Ne hésitez pas à poster un extrait de code si ceux-ci ne fonctionnent pas.