1

ガウス関数を使用して、隣接情報を格納するためにハーフエッジ構造を使用する特定の3Dメッシュを平滑化したいと思います。提案されたアルゴリズムは次のとおりです。

すべての頂点を、隣接するエッジの加重平均によって決定される位置に移動してメッシュを滑らかにします(加重が頂点に接続されたエッジの平均長に等しいシグマを持つガウスによって決定され、重みの合計が1になるように正規化されます)。

したがって、各頂点curr_vertexについて、I

  1. 取り付けられたエッジの平均の長さを計算します
  2. 隣接するすべての頂点を取得します
  3. 次の手順を実行して、隣接する各頂点の重みを決定します。`

重み=exp(-(距離*距離)/(2。シグマシグマ))

where distance is the 3D distance between thecurr_vertex and the neighbor andsigma = average length of attached edges ofcurr_vertex`

  1. すべての重みを合計し、各ネイバーの重みをこの合計で除算します(正規化ステップ)。
  2. 隣接する各頂点の位置に対応する重みを掛けます
  3. 重み付けされたすべての頂点を合計し、その結果を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;
}
4

1 に答える 1

1

これは、頭を叩くタイプミススタイルのバグのスマックです。あなたが説明したアルゴリズムは私にはうまく見えます。

まず、重みの正規化を明確に確認します。

次に、計算された頂点位置を新しい平滑化されたメッシュに書き戻すコードを確認します。

それらは私の推測です。うまくいかない場合は、コードスニペットを投稿してください。

于 2010-02-24T16:37:26.167 に答える