スポンサーリンク

VTKで三角柱・N角柱を描画

三角柱

作ってみたら意外と発見があったのでコードを置いておく。斬新だったのは、二つのvtkPolyDataをvtkAppendPolyDataで結合するところで、これができるといろいろと複雑なモデルを作りやすい。

#include <iostream>

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


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

// メッシュ生成に必要
#include <vtkQuad.h>
#include <vtkTriangle.h>
#include <vtkPolyDataMapper.h>
#include <vtkAppendPolyData.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);



vtkSmartPointer<vtkPolyData> MyCreateTriangularPrism(float height)
{

  float ph = height/2;
  float mh = -height/2;

  float x[6] = { 0.0,1.0,0.5,0.0,1.0,0.5 };
  float y[6] = { 0.0,0.0,0.866,0.0,0.0,0.866 };
  float z[6] = { mh,mh,mh,ph,ph,ph };

  // 頂点を定義
  vtkSmartPointer<vtkPoints> points = vtkSmartPointer<vtkPoints>::New();
  points->InsertNextPoint(x[0], z[0], y[0]); // 0
  points->InsertNextPoint(x[1], z[1], y[1]); // 1
  points->InsertNextPoint(x[2], z[2], y[2]); // 2
  points->InsertNextPoint(x[3], z[3], y[3]); // 3
  points->InsertNextPoint(x[4], z[4], y[4]); // 4
  points->InsertNextPoint(x[5], z[5], y[5]); // 5


  // 三角形一覧を定義
  vtkSmartPointer<vtkCellArray> top_bottom = vtkSmartPointer<vtkCellArray>::New();

  // 底面
  vtkSmartPointer<vtkTriangle> t_bottom = vtkSmartPointer<vtkTriangle>::New();
  t_bottom->GetPointIds()->SetId(0, 0);
  t_bottom->GetPointIds()->SetId(1, 2);
  t_bottom->GetPointIds()->SetId(2, 1);
  top_bottom->InsertNextCell(t_bottom);

  // 上面
  vtkSmartPointer<vtkTriangle> t_top = vtkSmartPointer<vtkTriangle>::New();
  t_top->GetPointIds()->SetId(0, 3);
  t_top->GetPointIds()->SetId(1, 4);
  t_top->GetPointIds()->SetId(2, 5);
  top_bottom->InsertNextCell(t_top);



  // 四角形一覧(側面用)を定義
  vtkSmartPointer<vtkCellArray> quads_sides = vtkSmartPointer<vtkCellArray>::New();

  vtkSmartPointer<vtkQuad> quad1 = vtkSmartPointer<vtkQuad>::New();
  quad1->GetPointIds()->SetId(0, 0);
  quad1->GetPointIds()->SetId(1, 1);
  quad1->GetPointIds()->SetId(2, 4);
  quad1->GetPointIds()->SetId(3, 3);
  quads_sides->InsertNextCell(quad1);

  vtkSmartPointer<vtkQuad> quad2 = vtkSmartPointer<vtkQuad>::New();
  quad2->GetPointIds()->SetId(0, 1);
  quad2->GetPointIds()->SetId(1, 2);
  quad2->GetPointIds()->SetId(2, 5);
  quad2->GetPointIds()->SetId(3, 4);
  quads_sides->InsertNextCell(quad2);

  vtkSmartPointer<vtkQuad> quad3 = vtkSmartPointer<vtkQuad>::New();
  quad3->GetPointIds()->SetId(0, 2);
  quad3->GetPointIds()->SetId(1, 0);
  quad3->GetPointIds()->SetId(2, 3);
  quad3->GetPointIds()->SetId(3, 5);
  quads_sides->InsertNextCell(quad3);

  ///////////////////////////////////////////////////////
  // 上下の三角形二枚からなるPolyDataを作成
  vtkSmartPointer<vtkPolyData> polyData1 = vtkSmartPointer<vtkPolyData>::New();
  polyData1->SetPoints(points);
  polyData1->SetPolys(top_bottom);

// 側面の四角形からなるPolyDataを作成 vtkSmartPointer<vtkPolyData> polyData2 = vtkSmartPointer<vtkPolyData>::New(); polyData2->SetPoints(points); polyData2->SetPolys(quads_sides); /////////////////////////////////////////////////////// // PolyDataを結合 vtkSmartPointer<vtkAppendPolyData> appendFilter = vtkSmartPointer<vtkAppendPolyData>::New(); appendFilter->AddInputData(polyData1); appendFilter->AddInputData(polyData2); appendFilter->Update(); vtkSmartPointer<vtkPolyData> polyData = appendFilter->GetOutput(); return polyData; }

int main(int /*argc*/, char** /*argv*/)
{
  
  vtkSmartPointer<vtkPolyData> triangularprim = MyCreateTriangularPrism(3.0f); // 三角柱(高さ3.0)

  // マッパーを作成
  vtkSmartPointer<vtkPolyDataMapper> mapper = vtkSmartPointer<vtkPolyDataMapper>::New();
  mapper->SetInputData(triangularprim);

  // アクターを作成
  vtkSmartPointer<vtkActor> actor = vtkSmartPointer<vtkActor>::New();
  actor->SetMapper(mapper);


  //////////////////////////////////////
  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;
}

N角柱

#include <iostream>

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


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

// メッシュ生成に必要
#include <vtkQuad.h>
#include <vtkTriangle.h>
#include <vtkPolyDataMapper.h>
#include <vtkAppendPolyData.h>
#include <vtkPolygon.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);



vtkSmartPointer<vtkPolyData> MyCreateNPrism(float height, int N)
{
  // 角柱の上面、底面の位置を定義
  float ph = height / 2;
  float mh = -height / 2;

  vtkSmartPointer<vtkPoints> points = vtkSmartPointer<vtkPoints>::New();
  vtkSmartPointer<vtkCellArray> top_bottom = vtkSmartPointer<vtkCellArray>::New();
  vtkSmartPointer<vtkCellArray> quads_sides = vtkSmartPointer<vtkCellArray>::New();

  // 底面と上面の頂点を定義
  for (int i = 0; i < N; ++i)
  {
    double angle = 2.0 * 3.1415926535 * i / N;
    double x = cos(angle);
    double y = sin(angle);
    points->InsertNextPoint(x, y, mh); // 底面
    points->InsertNextPoint(x, y, ph); // 上面
  }

  // 底面と上面のポリゴンを定義
  vtkSmartPointer<vtkPolygon> polygon_bottom = vtkSmartPointer<vtkPolygon>::New();
  polygon_bottom->GetPointIds()->SetNumberOfIds(N);
  vtkSmartPointer<vtkPolygon> polygon_top = vtkSmartPointer<vtkPolygon>::New();
  polygon_top->GetPointIds()->SetNumberOfIds(N);

  for (int i = 0; i < N; ++i)
  {
    polygon_bottom->GetPointIds()->SetId(i, i * 2);
    polygon_top->GetPointIds()->SetId(i, i * 2 + 1);
  }

  top_bottom->InsertNextCell(polygon_bottom);
  top_bottom->InsertNextCell(polygon_top);

  // 側面を定義
  for (int i = 0; i < N; ++i)
  {
    vtkSmartPointer<vtkQuad> quad = vtkSmartPointer<vtkQuad>::New();
    quad->GetPointIds()->SetId(0, (i * 2));
    quad->GetPointIds()->SetId(1, ((i * 2 + 2) % (N * 2)));
    quad->GetPointIds()->SetId(2, ((i * 2 + 3) % (N * 2)));
    quad->GetPointIds()->SetId(3, (i * 2 + 1));
    quads_sides->InsertNextCell(quad);
  }

  // 上下の面をなすPolyDataを作成
  vtkSmartPointer<vtkPolyData> polyData1 = vtkSmartPointer<vtkPolyData>::New();
  polyData1->SetPoints(points);
  polyData1->SetPolys(top_bottom);

  // 側面の四角形からなるPolyDataを作成
  vtkSmartPointer<vtkPolyData> polyData2 = vtkSmartPointer<vtkPolyData>::New();
  polyData2->SetPoints(points);
  polyData2->SetPolys(quads_sides);

  // PolyDataを結合
  vtkSmartPointer<vtkAppendPolyData> appendFilter = vtkSmartPointer<vtkAppendPolyData>::New();
  appendFilter->AddInputData(polyData1);
  appendFilter->AddInputData(polyData2);
  appendFilter->Update();

  vtkSmartPointer<vtkPolyData> polyData = appendFilter->GetOutput();

  return polyData;
}

int main(int /*argc*/, char** /*argv*/)
{
  
  vtkSmartPointer<vtkPolyData> nprim = MyCreateNPrism(3.0, 5);// 五角柱を作成

  // マッパーを作成
  vtkSmartPointer<vtkPolyDataMapper> mapper = vtkSmartPointer<vtkPolyDataMapper>::New();
  mapper->SetInputData(nprim);

  // アクターを作成
  vtkSmartPointer<vtkActor> actor = vtkSmartPointer<vtkActor>::New();
  actor->SetMapper(mapper);


  //////////////////////////////////////
  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;
}

コメントを残す

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

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


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