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

  1. calculer la durée moyenne de ses bords joints
  2. obtenir tous les sommets voisins
  3. 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 thecurr_vertexand the neighbor andsigma= average length of attached edges ofcurr_vertex`

  1. résumer tous les poids et diviser le poids de chaque voisin par cette somme (étape de normalisation)
  2. multiplier la position de chaque sommet voisin par son poids correspondant
  3. 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;
}
Était-ce utile?

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.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top