2

平面配置を検出したい非常に大きな点群(> 100000ポイント)があります。八分木を使用して点を非常に小さな平面クラスターに分割し、同一平面上にある隣接するクラスターをマージすることにしました。点群を小さな平面クラスターにすばやく分割するコードをC++で記述しましたが、それらを効果的にマージする方法はわかりません...

私のOctree実装では、ポインター構造を使用しています。子ノードへのポインターを含むOctreeNode配列を持つsがあり、リーフノードの場合はすべてのポインターがあります。OctreeNode* children[8]NULL

私が最初に考えたのは、各OctreeNodeオブジェクトで、オブジェクトへのポインターを保持するPlaneことでした。ポイントを最初に分割した後、八分木の各リーフは、リーフにPlane含まれるすべてのポイントに適合する最小二乗を表すを取得します。次に、ツリー内のすべてのリーフノードを反復処理します。リーフノードごとに、隣接するリーフノードのそれぞれをチェックします。隣接するリーフの平面を現在のリーフの平面とマージする必要がある場合はPlane* newPlane = Plane::mergePlanes(this->plane, neighbor->plane);、両方のノードのポイントを表す新しい平面を作成するために呼び出します。

ここで問題が発生しました...最初は、両方のプレーンを新しいプレーンに置き換えるだけでよいと思いました。つまりplane = newPlane; neighbor->plane = newPlane;、完了しました(メモリリークは別として、実際のコードで処理しました)。残念ながら、これは実際には機能しません。OctreeNode複数の平面をマージした後、単一のを指すいくつかの異なるが存在する可能性がありPlane、単にポインタを置き換えるだけで、古い平面を指すすべてのポインタを置き換えるわけではthis->planeありません。neighbor->plane

私が最初にそれを思いついたときでさえ、解決策はハックのように見えました、そして今、その欠陥はさらに明白です。誰かが私が思いついたマージ方法を修正する方法を考えたり、より良い方法を考えたりできますか?

ありがとうございました

4

2 に答える 2

2

標準的な修正は、ノードを遅延修正することです。あなたが指している飛行機を見て、それが他の場所を指しているかどうかを確認するアクセス方法を用意してください。ある場合は、それがどこにあるかが見つかるまで再帰的に検索し、すべてのオブジェクトを現在のオブジェクトに修正してから、正しい平面を戻します。

これは、ポインタをたどるよりもはるかにコストがかかりますが、実際には、最終的なオブジェクトは見た目1位または2位にあるため、実際には思ったほど高価ではありません。

于 2011-04-27T22:27:24.303 に答える
0

VTKには、同様のポイントハンドルクラスvtkIncrementalOctreePointLocatorがあります。挿入点をマージするのに理想的な点だと思います。

例えば:

double xyz[3];    // location
id_type point_id; // we get back the point id

// bool InsertUniquePoint( double xyz[3], id_type &point_id );
// return value is true, if new point inserted
bool value = inserter->InsertUniquePoint( xyz, point_id );

だから私の意見:クラスが大きすぎる場合、それを再構築する方が簡単です。

于 2011-04-27T21:16:14.563 に答える