スポンサーリンク

VTKでPointCloud表示(3)頂点をSphereで表示

vtkGlyph3Dで頂点をPolyDataに置き換えて表示

//VTK_MODULE_INITに必要
#include <vtkAutoInit.h>


#include <vtkSmartPointer.h>
#include <vtkRenderer.h>
#include <vtkRenderWindow.h>
#include <vtkRenderWindowInteractor.h>


#include <eigen/Core>

#include <vtkPolyDataMapper.h>
#include <vtkPolyData.h>
#include <vtkPoints.h>
#include <vtkPointData.h>
#include <vtkProperty.h>          // 色を設定するために必要
#include <vtkUnsignedCharArray.h> // 色を設定するために必要
#include <vtkVertexGlyphFilter.h> // 点を描画するために必要
#include <vtkGlyph3D.h>           // 点を球にするために必要

#include <vtkSphereSource.h>      // 球を作成するために必要

#pragma comment(lib,"opengl32.lib")
#pragma comment(lib,"psapi.lib")
#pragma comment(lib,"dbghelp.lib")
#pragma comment(lib,"ws2_32.lib")

//必須
VTK_MODULE_INIT(vtkRenderingOpenGL2);
VTK_MODULE_INIT(vtkInteractionStyle);

void CreatePointArray(
  std::vector<Eigen::Vector3d>& vertices,
  vtkSmartPointer<vtkPolyData> vtk_mesh,
  vtkSmartPointer<vtkPoints> vtk_points) {

  // 頂点配列を作成
  for (const auto& v : vertices) {
    vtk_points->InsertNextPoint(v.x(), v.y(), v.z());
  }
  // 頂点配列を設定
  vtk_mesh->SetPoints(vtk_points);

}

void CreateColorsArray(
  std::vector<Eigen::Vector3d>& vertex_colors,
  vtkSmartPointer<vtkPolyData> vtk_mesh,
  vtkSmartPointer<vtkUnsignedCharArray> vtk_colors) {

  vtk_colors->SetNumberOfComponents(3);

  for (const auto& c : vertex_colors) {
    vtk_colors->InsertNextTuple3(c.x() * 255, c.y() * 255, c.z() * 255);
  }
  vtk_mesh->GetPointData()->SetScalars(vtk_colors);

}

vtkSmartPointer<vtkActor>  CreatePointCloudActor(
  std::vector<Eigen::Vector3d> vertices,
  std::vector<Eigen::Vector3d> colors,
  vtkAlgorithmOutput* glyphpoly // 点を球にするためのvtkPolyData
) {
  auto vtk_cloud = vtkSmartPointer<vtkPolyData>::New();
  auto vtk_points = vtkSmartPointer<vtkPoints>::New();
  auto vtk_colors = vtkSmartPointer<vtkUnsignedCharArray>::New();

  ///////////////////////////////////////////////////////
  // 頂点の配列を生成
  CreatePointArray(vertices, vtk_cloud, vtk_points);
  ///////////////////////////////////////////////////////
  // 色の配列を生成
  CreateColorsArray(colors, vtk_cloud, vtk_colors);
  ///////////////////////////////////////////////////////

  ///////////////////////////////////////////////////////
  // Glyph3Dを使用して点に球を描画
  vtkSmartPointer<vtkGlyph3D> glyph3D = vtkSmartPointer<vtkGlyph3D>::New();
  glyph3D->SetSourceConnection(glyphpoly);
  glyph3D->SetInputData(vtk_cloud);
  glyph3D->SetColorModeToColorByScalar(); // 色情報を使用
  glyph3D->SetScaleFactor(0.1);           // 球をスケーリング
  glyph3D->SetScaleModeToDataScalingOff(); // サイズを一定にする

  glyph3D->Update();


  ///////////////////////////////////////////////////////

  auto vtk_mapper = vtkSmartPointer<vtkPolyDataMapper>::New();
  vtk_mapper->SetInputConnection(glyph3D->GetOutputPort());

  auto vtk_actor = vtkSmartPointer<vtkActor>::New();
  vtk_actor->SetMapper(vtk_mapper);

  return vtk_actor;
}

int main(int /*argc*/, char** /*argv*/)
{
  ////////////////////////////////////////
  // 点群の定義

  // ランダムの1000頂点を作成
  std::vector<Eigen::Vector3d> vertices;
  for (int i = 0; i < 1000; i++) {
    vertices.push_back(Eigen::Vector3d::Random());
  }
  // ランダムの色を設定
  std::vector<Eigen::Vector3d> colors;
  for (int i = 0; i < 1000; i++) {
    Eigen::Vector3d rnd = Eigen::Vector3d::Random();             // -1~1の乱数
    Eigen::Vector3d v01 = 0.5 * (rnd + Eigen::Vector3d::Ones()); //  0~1に変換
    colors.push_back(v01);
  }
  ////////////////////////////////////////


  // 球を作成
  vtkSmartPointer<vtkSphereSource> sphereSource = vtkSmartPointer<vtkSphereSource>::New();
  sphereSource->SetRadius(1.0); // 球の半径を設定
  sphereSource->Update();


  // 点群のアクタを作戦
  auto actor = CreatePointCloudActor(vertices, colors,sphereSource->GetOutputPort() );

  //////////////////////////////////////
  auto renderer = vtkSmartPointer<vtkRenderer>::New();
  renderer->AddActor(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;
}

球のサイズを変更

球サイズのスカラー値の配列を指定することで、球のサイズを変更できる

void CreateColorsArray(
  std::vector<Eigen::Vector3d>& vertex_colors,
  vtkSmartPointer<vtkPolyData> vtk_mesh,
  vtkSmartPointer<vtkUnsignedCharArray> vtk_colors) {

  vtk_colors->SetName("MY_POINT_COLOR"); // 明示的に指定するため名前を付ける
  vtk_colors->SetNumberOfComponents(3);

  for (const auto& c : vertex_colors) {
    vtk_colors->InsertNextTuple3(c.x() * 255, c.y() * 255, c.z() * 255);
  }
  vtk_mesh->GetPointData()->SetScalars(vtk_colors);

}

vtkSmartPointer<vtkFloatArray> CreateSizeScalarArray(const std::vector<Eigen::Vector3d>& points) {

  auto size_scalars = vtkSmartPointer<vtkFloatArray>::New();
  size_scalars->SetName("MY_SIZE_SCALAR"); // 明示的にアクティブにするため名前を付ける
  size_scalars->SetNumberOfComponents(1);
  size_scalars->SetNumberOfTuples(points.size());
  for (int i = 0; i < points.size(); i++) {

    float sz = points[i].z() + 1.0;
    sz *= 0.05;

    size_scalars->SetValue(i, sz);
  }
  return size_scalars;
}

vtkSmartPointer<vtkActor>  CreatePointCloudActor(
  std::vector<Eigen::Vector3d> vertices,
  std::vector<Eigen::Vector3d> colors,
  vtkAlgorithmOutput* glyphpoly // 点を球にするためのvtkPolyData
) {
  auto vtk_cloud = vtkSmartPointer<vtkPolyData>::New();
  auto vtk_points = vtkSmartPointer<vtkPoints>::New();
  auto vtk_colors = vtkSmartPointer<vtkUnsignedCharArray>::New();

  ///////////////////////////////////////////////////////
  // 頂点の配列を生成
  CreatePointArray(vertices, vtk_cloud, vtk_points);
  ///////////////////////////////////////////////////////
  // 色の配列を生成
  CreateColorsArray(colors, vtk_cloud, vtk_colors);
  ///////////////////////////////////////////////////////

  // 球のサイズを設定するスカラー配列を生成
  auto size_scalar_array = CreateSizeScalarArray(vertices);

  // 点群にサイズのスカラー配列を追加
  vtk_cloud->GetPointData()->AddArray(size_scalar_array);
  vtk_cloud->GetPointData()->SetActiveScalars("MY_SIZE_SCALAR");

  ///////////////////////////////////////////////////////
  // Glyph3Dを使用して点に球を描画
  vtkSmartPointer<vtkGlyph3D> glyph3D = vtkSmartPointer<vtkGlyph3D>::New();
  glyph3D->SetSourceConnection(glyphpoly);
  glyph3D->SetInputData(vtk_cloud);
  glyph3D->SetColorModeToColorByScalar(); // 色情報を使用
  //glyph3D->SetScaleFactor(0.1);           // 球をスケーリング
  
  glyph3D->SetScaleModeToScaleByScalar(); // スケールをスカラー値にする
  //glyph3D->SetScaleModeToDataScalingOff(); // サイズを一定にする

  glyph3D->Update();

  ///////////////////////////////////////////////////////


  auto vtk_mapper = vtkSmartPointer<vtkPolyDataMapper>::New();
  vtk_mapper->SetInputConnection(glyph3D->GetOutputPort());

  // 色の設定はデフォルトでアクティブなスカラー値が使用されるが
  // glyph3Dでスケーリングの指定をするため、スケール用のスカラー値をアクティブにする必要があるため
  // カラー用のスカラー値は明示的に指定する
  vtk_mapper->SetScalarModeToUsePointFieldData();
  vtk_mapper->SelectColorArray("MY_POINT_COLOR");

  auto vtk_actor = vtkSmartPointer<vtkActor>::New();
  vtk_actor->SetMapper(vtk_mapper);

  return vtk_actor;
}

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です

日本語が含まれない投稿は無視されますのでご注意ください。(スパム対策)


この記事のトラックバックURL: