スポンサーリンク
class mykdtree { std::vector<Eigen::Vector3d>& _points; node* node_root; public: mykdtree(std::vector<Eigen::Vector3d>& points) : _points(points) {} // ツリーの構築 void build() { // 最初のindexリストを作成 std::vector<size_t> indices(_points.size()); for (size_t i = 0; i < _points.size(); i++) { indices[i] = i; } // 再帰的にツリー作成 node_root = buildnode(_points, indices, 0/*X軸*/); } node* getRoot() { return node_root; }
// 半径内の頂点を探索する関数 // 再帰的に探索する関数 // nd: 現在のノード // query: 探索する点 // radius: 探索半径 // results: 探索結果のindexリスト void radiusSearch_core( node* nd, const Eigen::Vector3d& query, double radius, std::vector<size_t>& results) { if (nd == nullptr) { return; } const auto& nodePt = _points[nd->index]; // ノード と query の距離を計算 float dist = (query - nodePt).norm(); // 現在のノードがqueryを中心とした探索範囲内にあるか確認 if (dist <= radius) { results.push_back(nd->index);//現在のノードを結果に追加 } // サブツリーの探索条件 // 軸に沿った距離を計算 /////////////////////////////////////////////////////////// // // | // ------------●-------------○---------------- // query nodePt // | // // query.x - nodePt.x < 0 // queryが現在のノードの左側にある → nodePtの左側を探索 /////////////////////////////////////////////////////////// // // | // ------------○-------------●---------------- // nodePt query // | // // query.x - nodePt.x > 0 // queryが現在のノードの右側にある → nodePtの右側を探索 /////////////////////////////////////////////////////////// float axisDist = query[nd->axis] - nodePt[nd->axis]; // ケース1 queryがノードの左側にある if (axisDist < 0) { // 左側にあるので、左側を探索 radiusSearch_core(nd->left, query, radius, results); // ケース1(2)nodePtが、queryの半径以内にあるなら、右側にもあるかもしれない if (axisDist * axisDist <= radius * radius) { radiusSearch_core(nd->right, query, radius, results); } } else { // ケース2 queryがノードの右側にある // 右側にあるので、右側を探索 radiusSearch_core(nd->right, query, radius, results); // ケース2(2)nodePtが、queryの半径以内にあるなら、左側にもあるかもしれない if (axisDist * axisDist <= radius * radius) { radiusSearch_core(nd->left, query, radius, results); } } }
// 半径内の頂点を探索する関数 // query: 探索する点 // radius: 探索半径 // results: 探索結果のindexリスト void radiusSearch( const Eigen::Vector3d& query, double radius, std::vector<size_t>& results) { results.clear(); radiusSearch_core(node_root, query, radius, results); }
};
#include <iostream> //VTK_MODULE_INITに必要 #include <vtkAutoInit.h> #include <vtkSmartPointer.h> #include <vtkRenderer.h> #include <vtkRenderWindow.h> #include <vtkRenderWindowInteractor.h> //円筒とその表示に必要 #include <vtkPolyDataMapper.h> #pragma comment(lib,"opengl32.lib") #pragma comment(lib,"psapi.lib") #pragma comment(lib,"dbghelp.lib") #pragma comment(lib,"ws2_32.lib") #include <Eigen/Core> #include <array> #include <vtkActor.h> #include <vtkPoints.h> #include <vtkPolyData.h> #include <vtkUnsignedCharArray.h> #include <vtkPointData.h> #include <vtkVertexGlyphFilter.h> #include <vtkProperty.h> #include "mykdtree.hpp" //必須 VTK_MODULE_INIT(vtkRenderingOpenGL2); VTK_MODULE_INIT(vtkInteractionStyle); // VTK表示用 struct MyVtkCloud { std::vector<Eigen::Vector3d> points; std::array<unsigned char, 3> color; std::vector<std::array<unsigned char, 3> > color_array; vtkSmartPointer<vtkActor> actor; void makeActor() { // VTKのデータ構造に変換 vtkSmartPointer<vtkPoints> vtk_points = vtkSmartPointer<vtkPoints>::New(); vtkSmartPointer<vtkUnsignedCharArray> vtk_colors = vtkSmartPointer<vtkUnsignedCharArray>::New(); vtk_colors->SetNumberOfComponents(3); // RGB vtk_colors->SetName("Colors"); for (size_t i = 0; i < points.size(); ++i) { // 点を追加 vtk_points->InsertNextPoint(points[i].x(), points[i].y(), points[i].z()); if (color_array.size() == 0) { vtk_colors->InsertNextTypedTuple(color.data()); } else { vtk_colors->InsertNextTypedTuple(color_array[i].data()); } } //////////////////////////////////////////////////////////// vtkSmartPointer<vtkPolyData> polyData = vtkSmartPointer<vtkPolyData>::New(); polyData->SetPoints(vtk_points); polyData->GetPointData()->SetScalars(vtk_colors); //////////////////////////////////////////////////////////// vtkSmartPointer<vtkVertexGlyphFilter> vertexFilter = vtkSmartPointer<vtkVertexGlyphFilter>::New(); vertexFilter->SetInputData(polyData); vertexFilter->Update(); //////////////////////////////////////////////////////////// vtkSmartPointer<vtkPolyDataMapper> mapper = vtkSmartPointer<vtkPolyDataMapper>::New(); mapper->SetInputConnection(vertexFilter->GetOutputPort()); vtkSmartPointer<vtkActor> actor = vtkSmartPointer<vtkActor>::New(); actor->SetMapper(mapper); // 頂点サイズを指定 actor->GetProperty()->SetPointSize(5); // ここで頂点サイズを指定します this->actor = actor; } };
int main(int /*argc*/, char** /*argv*/) { MyVtkCloud cloud1; std::vector<std::array<unsigned char, 3> > color_array; srand((unsigned int)5); //// ランダムな点群を作成 for (size_t i = 0; i < 10000; ++i) { cloud1.points.push_back(Eigen::Vector3d::Random()); color_array.push_back({ 255,0,0 }); } cloud1.color = std::array<unsigned char, 3>{ 0, 255, 0 }; cloud1.makeActor(); mykdtree kdtree(cloud1.points); kdtree.build(); node* root = kdtree.getRoot(); std::vector<size_t> indices; kdtree.radiusSearch( Eigen::Vector3d(0.3,0.3,0.3), 0.3, indices); for(auto i:indices){ color_array[i] = { 0,255,0 }; } cloud1.color_array = color_array; cloud1.makeActor(); // 表示 std::vector<size_t> indices_look = indices; // 昇順ソート std::sort(indices_look.begin(), indices_look.end()); // コンソールに表示 for (auto i : indices_look) { std::cout << i << std::endl; } ////////////////////////////////////// auto renderer = vtkSmartPointer<vtkRenderer>::New(); renderer->AddActor(cloud1.actor); renderer->ResetCamera(); ////////////////////////////////////// auto interactor = vtkSmartPointer<vtkRenderWindowInteractor>::New(); ////////////////////////////////////// auto renderWindow = vtkSmartPointer<vtkRenderWindow>::New(); renderWindow->AddRenderer(renderer); renderWindow->SetInteractor(interactor); renderWindow->Render(); interactor->Start(); //イベントループへ入る return 0; }