LIDAR ファイルから大量のポイント クラウド データを表示および変更するために使用するアプリケーションがあります (それぞれ最大数ギガバイトで、同時に読み込まれることもあります)。アプリでは、ユーザーはロードされたポイントの 2D 画像を (上から) 表示し、プロファイルを選択して別のウィンドウで (横から) 表示することができます。繰り返しますが、これには数百万のポイントが含まれ、それらは OpenGL を使用して表示されます。
データを処理するために、四分木ライブラリもあり、機能しますが、非常に低速です。しばらく使用されていましたが、最近、LIDAR ポイントの形式が変更され、LidarPoint オブジェクトに多数の属性 (クラス メンバー) を追加する必要がありました。これにより、サイズが大きくなり、パフォーマンスがほとんど使用できないレベルにまで影響しました (5 分と考えてください)。単一の 2GB ファイルをロードする場合)。
四分木は現在、指定された容量と定義された境界 (空間クエリ用) を持つ LidarPoint オブジェクトの単純な配列である PointBucket オブジェクトへのポインターで構成されています。バケット容量を超えると、4 つのバケットに分割されます。また、ポイント データが大量のメモリを消費している場合に、ポイント バケットがディスクにダンプされるようにする、一種のキャッシュ システムも用意されています。これらは、必要に応じてメモリにロードされます。最後に、すべての PointBucket には、元のデータの n 番目ごとのポイントを保持し、ズーム レベルに応じてデータを表示するときに使用されるサブバケット/解像度レベルが含まれます。これは、一度に数百万のポイントを表示するのは、そのレベルの詳細は必要ありませんが、非常に遅いためです。
そこからイメージしていただければ幸いです。そうでない場合は、お問い合わせください。詳細を提供するか、さらにコードをアップロードできます。たとえば、現在の(そして遅い)挿入方法は次のとおりです。
// Insert in QuadTree
bool QuadtreeNode::insert(LidarPoint newPoint)
{
// if the point dosen't belong in this subset of the tree return false
if (newPoint.getX() < minX_ || newPoint.getX() > maxX_ ||
newPoint.getY() < minY_ || newPoint.getY() > maxY_)
{
return false;
}
else
{
// if the node has overflowed and is a leaf
if ((numberOfPoints_ + 1) > capacity_ && leaf_ == true)
{
splitNode();
// insert the new point that caused the overflow
if (a_->insert(newPoint))
{
return true;
}
if (b_->insert(newPoint))
{
return true;
}
if (c_->insert(newPoint))
{
return true;
}
if (d_->insert(newPoint))
{
return true;
}
throw OutOfBoundsException("failed to insert new point into any \
of the four child nodes, big problem");
}
// if the node falls within the boundary but this node not a leaf
if (leaf_ == false)
{
return false;
}
// if the node falls within the boundary and will not cause an overflow
else
{
// insert new point
if (bucket_ == NULL)
{
bucket_ = new PointBucket(capacity_, minX_, minY_, maxX_, maxY_,
MCP_, instanceDirectory_, resolutionBase_,
numberOfResolutionLevels_);
}
bucket_->setPoint(newPoint);
numberOfPoints_++;
return true;
}
}
}
// Insert in PointBucket (quadtree holds pointers to PointBuckets which hold the points)
void PointBucket::setPoint(LidarPoint& newPoint)
{
//for each sub bucket
for (int k = 0; k < numberOfResolutionLevels_; ++k)
{
// check if the point falls into this subbucket (always falls into the big one)
if (((numberOfPoints_[0] + 1) % int(pow(resolutionBase_, k)) == 0))
{
if (!incache_[k])
cache(true, k);
// Update max/min intensity/Z values for the bucket.
if (newPoint.getIntensity() > maxIntensity_)
maxIntensity_ = newPoint.getIntensity();
else if (newPoint.getIntensity() < minIntensity_)
minIntensity_ = newPoint.getIntensity();
if (newPoint.getZ() > maxZ_)
maxZ_ = newPoint.getZ();
else if (newPoint.getZ() < minZ_)
minZ_ = newPoint.getZ();
points_[k][numberOfPoints_[k]] = newPoint;
numberOfPoints_[k]++;
}
}
}
私の質問は、このデザインを改善する方法を考えられるかどうかです。メモリに収まらない大量のデータを処理するときの一般的な戦略は何ですか? 四分木をより効率的にするにはどうすればよいですか? ポイントのレンダリングを高速化する方法はありますか?