【VTK】MFC基于VTK8.2的网格编辑器

视频演示

8fe9315974f823c64079e0a580193ec0.png

a0e5b6520c6df3d619359873af8c2bce.png

主界面截图

主要源码:

// appMeshEditorDlg.cpp : implementation file
//


#include "stdafx.h"
#include "appMeshEditor.h"
#include "appMeshEditorDlg.h"
#include "afxdialogex.h"
//转换
//#include "atlstr.h"




#ifdef _DEBUG
#define new DEBUG_NEW
#endif




// CAboutDlg dialog used for App About


class CAboutDlg : public CDialogEx
{
public:
  CAboutDlg();


  // Dialog Data
#ifdef AFX_DESIGN_TIME
  enum { IDD = IDD_ABOUTBOX };
#endif


protected:
  virtual void DoDataExchange(CDataExchange* pDX);    // DDX/DDV support


// Implementation
protected:
  DECLARE_MESSAGE_MAP()
};


CAboutDlg::CAboutDlg() : CDialogEx(IDD_ABOUTBOX)
{
}


void CAboutDlg::DoDataExchange(CDataExchange* pDX)
{
  CDialogEx::DoDataExchange(pDX);
}


BEGIN_MESSAGE_MAP(CAboutDlg, CDialogEx)
END_MESSAGE_MAP()




// CappMeshEditorDlg dialog






CappMeshEditorDlg::CappMeshEditorDlg(CWnd* pParent /*=NULL*/)
  : CDialogEx(IDD_APPMESHEDITOR_DIALOG, pParent)
{
  m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
}


void CappMeshEditorDlg::DoDataExchange(CDataExchange* pDX)
{
  CDialogEx::DoDataExchange(pDX);
}


BEGIN_MESSAGE_MAP(CappMeshEditorDlg, CDialogEx)
  ON_WM_SYSCOMMAND()
  ON_WM_PAINT()
  ON_WM_QUERYDRAGICON()
  ON_CBN_SELCHANGE(IDC_NEIGHBOR_STEP, &CappMeshEditorDlg::OnSelchangeNeighborStep)
  ON_BN_CLICKED(IDC_LOAD_STL, &CappMeshEditorDlg::OnBnClickedLoadStl)
  ON_BN_CLICKED(IDC_NEIGHBORFACE_RING, &CappMeshEditorDlg::OnBnClickedNeighborfaceRing)
  ON_BN_CLICKED(IDC_NEIGHBORFACE_AREA, &CappMeshEditorDlg::OnBnClickedNeighborfaceArea)
  ON_BN_CLICKED(IDC_FILL_HOLE, &CappMeshEditorDlg::OnBnClickedFillHole)
  ON_BN_CLICKED(IDC_DELETE_FACE, &CappMeshEditorDlg::OnBnClickedDeleteFace)
END_MESSAGE_MAP()




// CappMeshEditorDlg message handlers


BOOL CappMeshEditorDlg::OnInitDialog()
{
  CDialogEx::OnInitDialog();


  // Add "About..." menu item to system menu.


  // IDM_ABOUTBOX must be in the system command range.
  ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX);
  ASSERT(IDM_ABOUTBOX < 0xF000);


  CMenu* pSysMenu = GetSystemMenu(FALSE);
  if (pSysMenu != NULL)
  {
    BOOL bNameValid;
    CString strAboutMenu;
    bNameValid = strAboutMenu.LoadString(IDS_ABOUTBOX);
    ASSERT(bNameValid);
    if (!strAboutMenu.IsEmpty())
    {
      pSysMenu->AppendMenu(MF_SEPARATOR);
      pSysMenu->AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu);
    }
  }


  // Set the icon for this dialog.  The framework does this automatically
  //  when the application's main window is not a dialog
  SetIcon(m_hIcon, TRUE);      // Set big icon
  SetIcon(m_hIcon, FALSE);    // Set small icon


  // TODO: Add extra initialization here
  // VTK Code
  {
    if (this->GetDlgItem(IDC_STATIC_MAINFRAME))
    {
      this->CreateVTKWindow(this->GetDlgItem(IDC_STATIC_MAINFRAME)->GetSafeHwnd());//创建VTK窗口
      this->ResizeVtkWindow();
    }
  }


  // Init ComboBox of NeighborStep
  {
    CComboBox* pComboBox = (CComboBox*)this->GetDlgItem(IDC_NEIGHBOR_STEP); //获取下拉列表框
    pComboBox->AddString(_T("00"));//添加item
    pComboBox->AddString(_T("01"));
    pComboBox->AddString(_T("02"));
    pComboBox->AddString(_T("03"));
    pComboBox->AddString(_T("04"));
    pComboBox->AddString(_T("05"));
    pComboBox->AddString(_T("06"));
    pComboBox->AddString(_T("07"));
    pComboBox->AddString(_T("08"));
    pComboBox->AddString(_T("09"));
    pComboBox->AddString(_T("10"));


    pComboBox->SetCurSel(0);//选择首项
    this->m_nNeighborStep = pComboBox->GetCurSel();//获取选择网格的邻居数
  }


  return TRUE;  // return TRUE  unless you set the focus to a control
}


void CappMeshEditorDlg::OnSysCommand(UINT nID, LPARAM lParam)
{
  if ((nID & 0xFFF0) == IDM_ABOUTBOX)
  {
    CAboutDlg dlgAbout;
    dlgAbout.DoModal();
  }
  else
  {
    CDialogEx::OnSysCommand(nID, lParam);
  }
}


// If you add a minimize button to your dialog, you will need the code below
//  to draw the icon.  For MFC applications using the document/view model,
//  this is automatically done for you by the framework.


void CappMeshEditorDlg::OnPaint()
{
  if (IsIconic())
  {
    CPaintDC dc(this); // device context for painting


    SendMessage(WM_ICONERASEBKGND, reinterpret_cast<WPARAM>(dc.GetSafeHdc()), 0);


    // Center icon in client rectangle
    int cxIcon = GetSystemMetrics(SM_CXICON);
    int cyIcon = GetSystemMetrics(SM_CYICON);
    CRect rect;
    GetClientRect(&rect);
    int x = (rect.Width() - cxIcon + 1) / 2;
    int y = (rect.Height() - cyIcon + 1) / 2;


    // Draw the icon
    dc.DrawIcon(x, y, m_hIcon);
  }
  else
  {
    CDialogEx::OnPaint();
  }
}


// The system calls this function to obtain the cursor to display while the user drags
//  the minimized window.
HCURSOR CappMeshEditorDlg::OnQueryDragIcon()
{
  return static_cast<HCURSOR>(m_hIcon);
}


#pragma region // VTK Event
//鼠标悬停
void Callback_MouseOver_Face(vtkObject* caller, long unsigned int eventId,
  void* clientData, void* callData)
{
  // Interactor 获取交互器
  vtkSmartPointer<vtkRenderWindowInteractor> interactor =
    vtkRenderWindowInteractor::SafeDownCast(caller);
  if (interactor == NULL)
    return;


  // ClientData  获取客户端数据
  CappMeshEditorDlg* dlg = (CappMeshEditorDlg*)clientData;
  if (dlg == NULL)
    return;


  // 鼠标点击位置
  int pos[2];
  interactor->GetLastEventPosition(pos);


  // 在鼠标点击位置拾取
  vtkSmartPointer<vtkCellPicker> picker =
    vtkSmartPointer<vtkCellPicker>::New();
  picker->SetTolerance(0.005);    // 拾取灵敏度设置 
  picker->Pick(pos[0], pos[1], 0,
    interactor->GetRenderWindow()->GetRenderers()->GetFirstRenderer());


  vtkIdType mouseoverFaceIdx = picker->GetCellId();  // 如果为-1,则不被选中。
  if (mouseoverFaceIdx != -1)
  {
    //查找 polyData
    vtkSmartPointer<vtkRenderer> renderer =
      interactor->GetRenderWindow()->GetRenderers()->GetFirstRenderer();


    vtkSmartPointer<vtkActorCollection> actorCollection =
      renderer->GetActors();
    actorCollection->InitTraversal();


    vtkSmartPointer<vtkActor> actor =
      actorCollection->GetNextActor();


    vtkSmartPointer<vtkMapper> mapper =
      actor->GetMapper();


    vtkSmartPointer<vtkPolyData> polyData = (vtkPolyData*)mapper->GetInput();


    vtkSmartPointer<vtkTriangleFilter> triangleFilter =
      vtkSmartPointer<vtkTriangleFilter>::New();
    triangleFilter->SetInputData(polyData);
    triangleFilter->Update();


    // <#> MouseOverFace 选中面数据集映射器
    vtkSmartPointer<vtkDataSetMapper> mapperPickingFace =
      vtkSmartPointer<vtkDataSetMapper>::New();
    {
      vtkSmartPointer<vtkIdTypeArray> ids =
        vtkSmartPointer<vtkIdTypeArray>::New();
      ids->SetNumberOfComponents(1);
      ids->InsertNextValue(mouseoverFaceIdx);


      vtkSmartPointer<vtkSelectionNode> selectionNode =
        vtkSmartPointer<vtkSelectionNode>::New();
      selectionNode->SetFieldType(vtkSelectionNode::CELL);
      selectionNode->SetContentType(vtkSelectionNode::INDICES);
      selectionNode->SetSelectionList(ids);


      vtkSmartPointer<vtkSelection> selection =
        vtkSmartPointer<vtkSelection>::New();
      selection->AddNode(selectionNode);


      vtkSmartPointer<vtkExtractSelection> extractSelection =
        vtkSmartPointer<vtkExtractSelection>::New();
      extractSelection->SetInputConnection(0, triangleFilter->GetOutputPort());
      extractSelection->SetInputData(1, selection);
      extractSelection->Update();


      mapperPickingFace->SetInputConnection(extractSelection->GetOutputPort());
    }
    vtkSmartPointer<vtkActor> actorMouseoverFace =
      vtkSmartPointer<vtkActor>::New();
    actorMouseoverFace->SetMapper(mapperPickingFace);
    actorMouseoverFace->GetProperty()->SetColor(0.0, 1.0, 0.0);


    // <#> 显示到屏幕上
    {
      //Add the actors to the scene
      renderer->RemoveAllViewProps();
      renderer->AddActor(actor);
      renderer->AddActor(actorMouseoverFace);
      renderer->SetBackground(0.1, 0.2, 0.3);


      interactor->GetRenderWindow()->Render();
    }
  }
}
//邻居环
void Callback_NeighborFace_Ring(vtkObject* caller, long unsigned int eventId,
  void* clientData, void* callData)
{
  // Interactor 获取交互器
  vtkSmartPointer<vtkRenderWindowInteractor> interactor =
    vtkRenderWindowInteractor::SafeDownCast(caller);
  if (interactor == NULL)
    return;


  // ClientData  获取对话框数据  :传入的客户端数据
  CappMeshEditorDlg* dlg = (CappMeshEditorDlg*)clientData;
  if (dlg == NULL)
    return;


  // 鼠标点击位置
  int pos[2];
  interactor->GetLastEventPosition(pos);


  // 在鼠标点击位置拾取
  vtkSmartPointer<vtkCellPicker> picker =
    vtkSmartPointer<vtkCellPicker>::New();
  picker->SetTolerance(0.005);    // picking灵敏度设置  
  //使用提供的选择点执行拾取操作。通常前两个值是拾取的 (x,y) 像素坐标,第三个值是 z=0。如果成功选择了某些东西,则返回值将非零。
  picker->Pick(pos[0], pos[1], 0,
    interactor->GetRenderWindow()->GetRenderers()->GetFirstRenderer());//拾取操作,计算选中面
  //选中的面ID
  vtkIdType pikingFaceIdx = picker->GetCellId();  //如果为-1,则不被选中。
  if (pikingFaceIdx != -1)
  {
    // 获取网格数据 polyData   
    vtkSmartPointer<vtkRenderer> renderer =
      interactor->GetRenderWindow()->GetRenderers()->GetFirstRenderer();//渲染器


    vtkSmartPointer<vtkActorCollection> actorCollection =
      renderer->GetActors();//获取所有演员actors
    actorCollection->InitTraversal();//初始化集合的遍历。这意味着数据指针设置在列表的开头。


    vtkSmartPointer<vtkActor> actor =
      actorCollection->GetNextActor();//获取首个actor演员


    vtkSmartPointer<vtkMapper> mapper =
      actor->GetMapper();//获取演员的映射器


    vtkSmartPointer<vtkPolyData> polyData = (vtkPolyData*)mapper->GetInput();//获取网格数据
    //三角面片过滤器
    vtkSmartPointer<vtkTriangleFilter> triangleFilter =
      vtkSmartPointer<vtkTriangleFilter>::New();
    triangleFilter->SetInputData(polyData);
    triangleFilter->Update();


    // m_vecNeighborFace 初始化 
    dlg->m_vecNeighborFace.clear();


     查找选中点所在面的所有相邻面
    std::vector<vtkIdType> vec;
    vec.push_back(pikingFaceIdx);
    dlg->m_vecNeighborFace.push_back(vec);//先将当前选中面索引添加到m_vecNeighborFace
    vec.clear();
    dlg->m_vecNeighborFace.push_back(vec);//初始化空的面索引向量 添加到m_vecNeighborFace


    // call GenerateNeighborFace 生成邻居面片
    int nCntDepth = dlg->m_nNeighborStep;//邻居数量深度
    for (int i = 0; i < nCntDepth; ++i)
    {//逐层计算邻居
      dlg->GenerateNeighborList(dlg->m_vecNeighborFace.at(i + 1),
        dlg->m_vecNeighborFace.at(i),
        triangleFilter);


      //第i+1层 邻居去重
      dlg->Deduplication(dlg->m_vecNeighborFace.at(i + 1));


      vec.clear();
      dlg->m_vecNeighborFace.push_back(vec);//新得到的一层邻居添加到m_vecNeighborFace。


      // <#> Debug 输出
      OutputDebugString(L"\n Point neighbor ids are: ");
      for (std::vector<vtkIdType>::iterator it1 = dlg->m_vecNeighborFace.at(i + 1).begin(); it1 != dlg->m_vecNeighborFace.at(i + 1).end(); it1++)
      {
        CString strDebug;
        /*strDebug.Format(L" %d", *it1);*/
        strDebug.Format(_T(" %d"), *it1);
        ::OutputDebugString(strDebug);
      }
      OutputDebugString(L"\n");
    }


    /// <#> PickingFace 选中面的 数据集映射器
    vtkSmartPointer<vtkDataSetMapper> mapperPickingFace =
      vtkSmartPointer<vtkDataSetMapper>::New();
    {
      vtkSmartPointer<vtkIdTypeArray> ids =
        vtkSmartPointer<vtkIdTypeArray>::New();
      ids->SetNumberOfComponents(1);
      ids->InsertNextValue(dlg->m_vecNeighborFace.at(0).at(0));//选中面的id


      vtkSmartPointer<vtkSelectionNode> selectionNode =
        vtkSmartPointer<vtkSelectionNode>::New();
      selectionNode->SetFieldType(vtkSelectionNode::CELL);
      selectionNode->SetContentType(vtkSelectionNode::INDICES);
      selectionNode->SetSelectionList(ids);//选中的节点


      vtkSmartPointer<vtkSelection> selection =
        vtkSmartPointer<vtkSelection>::New();
      selection->AddNode(selectionNode);//添加到选中对象中


      vtkSmartPointer<vtkExtractSelection> extractSelection =
        vtkSmartPointer<vtkExtractSelection>::New();
      extractSelection->SetInputConnection(0, triangleFilter->GetOutputPort());
      extractSelection->SetInputData(1, selection);
      extractSelection->Update();//提取选中面


      mapperPickingFace->SetInputConnection(extractSelection->GetOutputPort());//关联数据集映射器与 选中面
    }
    //选中面actor 演员
    vtkSmartPointer<vtkActor> actorPickingFace =
      vtkSmartPointer<vtkActor>::New();
    actorPickingFace->SetMapper(mapperPickingFace);
    actorPickingFace->GetProperty()->SetColor(1, 0, 0);


    // <#> NeighborFace 最外层相邻面数据集映射器
    vtkSmartPointer<vtkDataSetMapper> mapperNeighborFace =
      vtkSmartPointer<vtkDataSetMapper>::New();
    {
      // GenerateNeighborRing 计算环形邻居
      std::vector<vtkIdType> vecNeighborRing;
      if (nCntDepth >= 1)
      {
        dlg->GenerateNeighborRing(vecNeighborRing,
          dlg->m_vecNeighborFace.at(nCntDepth),
          dlg->m_vecNeighborFace.at(nCntDepth - 1),
          dlg->m_vecNeighborFace.at(0)); //
      }
      else//只有选中面
      {
        vecNeighborRing.push_back(dlg->m_vecNeighborFace.at(0).at(0));
      }


      vtkSmartPointer<vtkIdTypeArray> ids =
        vtkSmartPointer<vtkIdTypeArray>::New();
      ids->SetNumberOfComponents(1);
      dlg->m_vecSelectedFace.clear();
      for (std::vector<vtkIdType>::iterator it1 = vecNeighborRing.begin(); it1 != vecNeighborRing.end(); it1++)
      {
        ids->InsertNextValue(*it1);//最外层邻居环 面索引
        dlg->m_vecSelectedFace.push_back(*it1);
      }
      //选择节点
      vtkSmartPointer<vtkSelectionNode> selectionNode =
        vtkSmartPointer<vtkSelectionNode>::New();
      selectionNode->SetFieldType(vtkSelectionNode::CELL);
      selectionNode->SetContentType(vtkSelectionNode::INDICES);
      selectionNode->SetSelectionList(ids);//最外层邻居索引


      vtkSmartPointer<vtkSelection> selection =
        vtkSmartPointer<vtkSelection>::New();
      selection->AddNode(selectionNode);//添加到选择对象中


      vtkSmartPointer<vtkExtractSelection> extractSelection =
        vtkSmartPointer<vtkExtractSelection>::New();
      extractSelection->SetInputConnection(0, triangleFilter->GetOutputPort());
      extractSelection->SetInputData(1, selection);
      extractSelection->Update();


      mapperNeighborFace->SetInputConnection(extractSelection->GetOutputPort());//最外层邻居  数据集映射器
    }
    vtkSmartPointer<vtkActor> actorNeighborFace =
      vtkSmartPointer<vtkActor>::New();
    actorNeighborFace->SetMapper(mapperNeighborFace);
    actorNeighborFace->GetProperty()->SetColor(0, 1, 0);//绿色 最外层邻居


    // <#> 显示到屏幕上
    {
      //Add the actors to the scene
      renderer->RemoveAllViewProps();
      renderer->AddActor(actor);//所有演员
      renderer->AddActor(actorPickingFace);//选中面
      renderer->AddActor(actorNeighborFace);//最外层面
      renderer->SetBackground(.1, .2, .3); // Background color dark red


      interactor->GetRenderWindow()->Render();
    }
  }
}
//邻居面片区域  
void Callback_NeighborFace_Area(vtkObject* caller, long unsigned int eventId,
  void* clientData, void* callData)
{
  // 获取交互器
  vtkSmartPointer<vtkRenderWindowInteractor> interactor =
    vtkRenderWindowInteractor::SafeDownCast(caller);//交互器  
  if (interactor == NULL)
    return;


  // 获取客户数据
  CappMeshEditorDlg* dlg = (CappMeshEditorDlg*)clientData;//客户端数据
  if (dlg == NULL)
    return;


  // 鼠标点击位置
  int pos[2];
  interactor->GetLastEventPosition(pos);//交互器:获取左键按下位置


  //在鼠标点击位置拾取
  vtkSmartPointer<vtkCellPicker> picker =
    vtkSmartPointer<vtkCellPicker>::New();
  picker->SetTolerance(0.005);    // 拾取灵敏度设置
  picker->Pick(pos[0], pos[1], 0,
    interactor->GetRenderWindow()->GetRenderers()->GetFirstRenderer());//根据点拾取三角面片


  vtkIdType pikingFaceIdx = picker->GetCellId();  //获取拾取到的三角面片索引   如果为-1,则不被选中。
  if (pikingFaceIdx != -1)
  {
    // 查找 polyData
    vtkSmartPointer<vtkRenderer> renderer =
      interactor->GetRenderWindow()->GetRenderers()->GetFirstRenderer();//获取渲染器


    vtkSmartPointer<vtkActorCollection> actorCollection =
      renderer->GetActors();  //返回此渲染器中的任何actors。
    actorCollection->InitTraversal();//初始化集合的遍历。这意味着数据指针设置在列表的开头。
    ///  所有演员
    vtkSmartPointer<vtkActor> actor =
      actorCollection->GetNextActor();


    vtkSmartPointer<vtkMapper> mapper =
      actor->GetMapper();//返回此actor从中获取数据的映射器。


    vtkSmartPointer<vtkPolyData> polyData = (vtkPolyData*)mapper->GetInput();//获取所有三角面片数据


    vtkSmartPointer<vtkTriangleFilter> triangleFilter =
      vtkSmartPointer<vtkTriangleFilter>::New();//三角面片过滤器
    triangleFilter->SetInputData(polyData);//将所有三角面片添加到过滤器
    triangleFilter->Update();


    // m_vecNeighborFace初始化选中点的邻居面片索引
    dlg->m_vecNeighborFace.clear();


    //查找连接到点 0 的所有单元格  Find all cells connected to point 0
    std::vector<vtkIdType> vec;
    vec.push_back(pikingFaceIdx); //选择的面片id
    dlg->m_vecNeighborFace.push_back(vec); //将选中的面片向量先添加进去 
    vec.clear();
    dlg->m_vecNeighborFace.push_back(vec);//添加 空的面片向量的向量  


    /调用生成邻居面片 call GenerateNeighborFace
    int nCntDepth = dlg->m_nNeighborStep; //设置的邻居数量级
    for (int i = 0; i < nCntDepth; ++i)
    {
      dlg->GenerateNeighborList(dlg->m_vecNeighborFace.at(i + 1),
        dlg->m_vecNeighborFace.at(i),
        triangleFilter);//生成 第i组面片向量的 邻近面片列表


      //   vec重复 清理
      dlg->Deduplication(dlg->m_vecNeighborFace.at(i + 1));//删除重复数据


      vec.clear();
      dlg->m_vecNeighborFace.push_back(vec);//添加空的面片向量的向量


      // <#>调试输出
      OutputDebugString(L"\n Point neighbor ids are: ");
      for (std::vector<vtkIdType>::iterator it1 = dlg->m_vecNeighborFace.at(i + 1).begin(); it1 != dlg->m_vecNeighborFace.at(i + 1).end(); it1++)
      {
        CString strDebug;
        /*strDebug.Format(L" %d", *it1);*/
        strDebug.Format(_T(" %d"), *it1);
        ::OutputDebugString(strDebug);
      }
      OutputDebugString(L"\n");
    }


    /// <#> PickingFace  :获取所有选中的面 数据集映射器
    vtkSmartPointer<vtkDataSetMapper> mapperPickingFace =
      vtkSmartPointer<vtkDataSetMapper>::New();//数据集映射器
    {  //选中三角面片索引数组
      vtkSmartPointer<vtkIdTypeArray> ids =
        vtkSmartPointer<vtkIdTypeArray>::New();
      ids->SetNumberOfComponents(1);
      ids->InsertNextValue(dlg->m_vecNeighborFace.at(0).at(0));//插入选中的面片
      //选择节点 
      vtkSmartPointer<vtkSelectionNode> selectionNode =
        vtkSmartPointer<vtkSelectionNode>::New();
      selectionNode->SetFieldType(vtkSelectionNode::CELL);//字段类型:单元
      selectionNode->SetContentType(vtkSelectionNode::INDICES);//内容类型:索引
      selectionNode->SetSelectionList(ids);//设置选择的三角面片列表,只一个


      vtkSmartPointer<vtkSelection> selection =
        vtkSmartPointer<vtkSelection>::New();
      selection->AddNode(selectionNode);//  添加选择节点
      //提取选择的
      vtkSmartPointer<vtkExtractSelection> extractSelection =
        vtkSmartPointer<vtkExtractSelection>::New();
      extractSelection->SetInputConnection(0, triangleFilter->GetOutputPort());//设置输入集合
      extractSelection->SetInputData(1, selection);//设置输入数据
      extractSelection->Update();


      mapperPickingFace->SetInputConnection(extractSelection->GetOutputPort());//选择的面 :数据集映射器
    }
    //actor 演员:选中的面,红色
    vtkSmartPointer<vtkActor> actorPickingFace =
      vtkSmartPointer<vtkActor>::New();
    actorPickingFace->SetMapper(mapperPickingFace);//设置actor的数据映射器
    actorPickingFace->GetProperty()->SetColor(1, 0, 0);//设置属性:颜色-红色


    <#> NeighborFace 邻居面数据集映射器
    vtkSmartPointer<vtkDataSetMapper> mapperNeighborFace =
      vtkSmartPointer<vtkDataSetMapper>::New();
    {
      // GenerateNeighborArea   获取邻居区域
      std::vector<vtkIdType> vecNeighborRing; //邻居索引向量
      dlg->GenerateNeighborArea(vecNeighborRing,
        dlg->m_vecNeighborFace.at(nCntDepth),//最外层(第nCntDepth次获取的邻居)所有邻居
        dlg->m_vecNeighborFace.at(0));


      vtkSmartPointer<vtkIdTypeArray> ids =
        vtkSmartPointer<vtkIdTypeArray>::New();
      ids->SetNumberOfComponents(1);//一维
      dlg->m_vecSelectedFace.clear();
      dlg->m_vecSelectedFace.push_back(pikingFaceIdx); //将选择的面片 添加到m_vecSelectedFace
      for (std::vector<vtkIdType>::iterator it1 = vecNeighborRing.begin(); it1 != vecNeighborRing.end(); it1++)
      {
        ids->InsertNextValue(*it1);
        dlg->m_vecSelectedFace.push_back(*it1);//最外层邻居索引添加到 m_vecSelectedFace
      }


      vtkSmartPointer<vtkSelectionNode> selectionNode =
        vtkSmartPointer<vtkSelectionNode>::New();
      selectionNode->SetFieldType(vtkSelectionNode::CELL);
      selectionNode->SetContentType(vtkSelectionNode::INDICES);
      selectionNode->SetSelectionList(ids);//选择的节点索引


      vtkSmartPointer<vtkSelection> selection =
        vtkSmartPointer<vtkSelection>::New();
      selection->AddNode(selectionNode);


      vtkSmartPointer<vtkExtractSelection> extractSelection =
        vtkSmartPointer<vtkExtractSelection>::New();
      extractSelection->SetInputConnection(0, triangleFilter->GetOutputPort());//三角面片过滤器
      extractSelection->SetInputData(1, selection);//设置输入:选中的面片索引
      extractSelection->Update();


      mapperNeighborFace->SetInputConnection(extractSelection->GetOutputPort());//获取 邻居面数据集映射器
    }
    //actor 演员:邻居面,绿色
    vtkSmartPointer<vtkActor> actorNeighborFace =
      vtkSmartPointer<vtkActor>::New();//邻居面片 
    actorNeighborFace->SetMapper(mapperNeighborFace);//设置映射器
    actorNeighborFace->GetProperty()->SetColor(0, 1, 0);//设置属性


    //<#>显示到屏幕上
    {
      //将演员添加到场景中
      renderer->RemoveAllViewProps();
      //向渲染器添加 / 删除不同类型的演员。
      //这些方法都是 AddViewProp 和 RemoveViewProp 的同义词。
      //它们在这里是为了方便和向后兼容。
      renderer->AddActor(actor);//所有面actor。loadstl得到
      renderer->AddActor(actorPickingFace);//添加选中面actor
      renderer->AddActor(actorNeighborFace);//添加邻居区域演员
      renderer->SetBackground(.1, .2, .3); // Background color dark red


      interactor->GetRenderWindow()->Render();
    }
  }
}
#pragma endregion


#pragma region // MFC Event
//选择邻居深度
void CappMeshEditorDlg::OnSelchangeNeighborStep()
{
  CComboBox* pComboBox = (CComboBox*)this->GetDlgItem(IDC_NEIGHBOR_STEP);
  this->m_nNeighborStep = pComboBox->GetCurSel();
}
//加载stl
void CappMeshEditorDlg::OnBnClickedLoadStl()
{
  try
  {
    // <#> 文件对话框过滤器 
    TCHAR szFilter[] = _T("STL (*.stl)|*.stl|All Files (*.*)|*.*||");


    // <#> 文件对话框  
    CFileDialog dlg(TRUE, NULL, NULL, OFN_HIDEREADONLY, szFilter);


    // <#> 数据 
    {
      //获取执行的 appPath
      TCHAR appPath[MAX_PATH];
      GetCurrentDirectory(MAX_PATH, appPath);


      //分离 appPath
      CString strDefaultPath;
      CString strSubPath;
      int nCount = 0;
      while (AfxExtractSubString(strSubPath, appPath, nCount, _T('\\')) == TRUE)
      {
        CString strTemp;
        BOOL bRtn = AfxExtractSubString(strTemp, appPath, nCount + 1, _T('\\'));
        if (bRtn == FALSE)
          break;


        strDefaultPath.Format(_T("%s%s\\"), strDefaultPath, strSubPath);
        ++nCount;
      }
      strDefaultPath.Format(_T("%s%s"), strDefaultPath, _T("data"));//data文件夹


      // CString to TCHAR[]
      TCHAR szDataFolder[MAX_PATH];
      memset(szDataFolder, 0x00, sizeof(TCHAR) * MAX_PATH);
      _tcscpy_s(szDataFolder, MAX_PATH, strDefaultPath.GetBuffer(0));
      strDefaultPath.ReleaseBuffer();


      // Default Folder 默认文件夹
      dlg.m_ofn.lpstrInitialDir = szDataFolder;//data文件夹
      //char* szStr = "./data/";
      //CString str = CString(szStr);
      //USES_CONVERSION;
      //LPCWSTR wszName = A2CW(W2A(str));
      //str.ReleaseBuffer();
      //dlg.m_ofn.lpstrInitialDir = wszName;
      //dlg.m_ofn.lpstrInitialDir = appPath;
    }


    //char* szStr = "./data/";
    //CString str = CString(szStr);
    //USES_CONVERSION;
    //LPCWSTR wszName = A2CW(W2A(str));
    //str.ReleaseBuffer();
    //dlg.m_ofn.lpstrInitialDir = wszName;


    if (dlg.DoModal() == IDOK)
    {
      // 只能处理stl
      CString strFilePath = dlg.GetPathName();//文件路径
      CString strExtention = PathFindExtension(strFilePath);//文件扩展名
      if (strExtention.Compare(_T(".stl")) != 0)
      {
        ::MessageBox(NULL, _T("Only Load STL Files"), _T("ERROR"), MB_OK);
        return;
      }


      // <#> 将 STL 加载到主窗口
      {
        if (m_vtkMainWindow == NULL)
          throw;


        // <#0> 初始化渲染器
        vtkSmartPointer<vtkRenderer> prevRenderer =
          m_vtkMainWindow->GetRenderers()->GetFirstRenderer();//获取当前渲染器
        if (prevRenderer != NULL)//当前渲染器非空
          m_vtkMainWindow->RemoveRenderer(prevRenderer);//移除当前渲染器


        // <#1>加载 STL 模型
        vtkSmartPointer<vtkSTLReader> STLReader =
          vtkSmartPointer<vtkSTLReader>::New();
        STLReader->SetFileName(CT2A(strFilePath));
        STLReader->Update();


        // <#2> 将 STL 保存到 PolyData 转换
        m_vtkPolyData = STLReader->GetOutput();


        // <#3>STL FaceCnt & VertexCnt 信息
        //SetGeneralInfo(m_vtkPolyData);


        // <#4>创建网格数据映射器
        vtkSmartPointer<vtkPolyDataMapper> mapper =
          vtkSmartPointer<vtkPolyDataMapper>::New();
        mapper->SetInputData(m_vtkPolyData);
        mapper->Update();


        // <#5> 创建演员
        vtkSmartPointer<vtkActor> actor =
          vtkSmartPointer<vtkActor>::New();
        actor->SetMapper(mapper);//stl数据的 演员
        actor->GetProperty()->SetEdgeColor(0.0, 0.0, 0.0);//设置边的颜色:黑色
        actor->GetProperty()->EdgeVisibilityOn();


        // <#6> 创建渲染器
        vtkSmartPointer<vtkRenderer> renderer =
          vtkSmartPointer<vtkRenderer>::New();
        renderer->AddActor(actor);//添加渲染对象
        renderer->SetBackground(0.1, 0.2, 0.3);//背景色
        renderer->ResetCamera();//重置相机
        m_vtkMainWindow->AddRenderer(renderer);


        // <#7> Interactor交互器
        //vtkSmartPointer<vtkRenderWindowInteractor> newIntoractor =
        //  vtkSmartPointer<vtkRenderWindowInteractor>::New();
        //newIntoractor->SetInteractorStyle(
        //  vtkSmartPointer<vtkInteractorStyleTrackballCamera>::New());
        //m_vtkWindow->SetInteractor(newIntoractor);


        // <#9> 在屏幕上绘图
        //m_vtkMainWindow->Render();


      }
    }
  }
  catch (...)
  {
    ::MessageBox(NULL, _T("OnBnClickedLoadStl"), _T("Exception"), MB_OK);
  }
}
//邻居环
void CappMeshEditorDlg::OnBnClickedNeighborfaceRing()
{
  // <#1> 交互器 Interactor
  vtkSmartPointer<vtkRenderWindowInteractor> newIntoractor =
    vtkSmartPointer<vtkRenderWindowInteractor>::New();
  newIntoractor->SetInteractorStyle(
    vtkSmartPointer<vtkInteractorStyleTrackballCamera>::New());
  m_vtkMainWindow->SetInteractor(newIntoractor);


  // <#2> 回调函数设置
  vtkSmartPointer<vtkCallbackCommand> pickCallback =
    vtkSmartPointer<vtkCallbackCommand>::New();
  pickCallback->SetCallback(Callback_NeighborFace_Ring);//邻居环
  pickCallback->SetClientData(this);


  // <#3>将回调函数连接到交互器
  m_vtkMainWindow->GetInteractor()->
    AddObserver(vtkCommand::LeftButtonPressEvent, pickCallback);//给交互器添加左键按下事件  pickCallback为左键按下的处理函数


  // <#3> 在屏幕上绘图
  m_vtkMainWindow->Render();
}


//邻居面片区域: 单击鼠标左键,选中三角面片(红色绘制),其邻居绿色绘制。
void CappMeshEditorDlg::OnBnClickedNeighborfaceArea()
{
  // <#1> 新的交互器 Interactor
  vtkSmartPointer<vtkRenderWindowInteractor> newIntoractor =
    vtkSmartPointer<vtkRenderWindowInteractor>::New();
  newIntoractor->SetInteractorStyle(
    vtkSmartPointer<vtkInteractorStyleTrackballCamera>::New());//设置交互器风格
  m_vtkMainWindow->SetInteractor(newIntoractor);//设置渲染窗口的 交互器


  // <#2> CallBack功能设置
  vtkSmartPointer<vtkCallbackCommand> pickCallback =
    vtkSmartPointer<vtkCallbackCommand>::New();
  pickCallback->SetCallback(Callback_NeighborFace_Area);
  pickCallback->SetClientData(this);//窗口指针作为客户端数据传给回调函数


  // <#3> 将回调函数连接到交互器
  m_vtkMainWindow->GetInteractor()->
    AddObserver(vtkCommand::LeftButtonPressEvent, pickCallback);


  // <#3> 在屏幕上绘图
  m_vtkMainWindow->Render();
}
//删除三角面片
void CappMeshEditorDlg::OnBnClickedDeleteFace()
{
  // <#1> 将选中的单元格标记为已删除。
  for (std::vector<vtkIdType>::iterator iter = m_vecSelectedFace.begin(); iter != m_vecSelectedFace.end(); ++iter)
    m_vtkPolyData->DeleteCell(*iter);//标记为已删除 


  // <#2> 删除标记的单元格。
  m_vtkPolyData->RemoveDeletedCells();


  // <#3> STL FaceCnt & VertexCnt 信息
  //SetGeneralInfo(m_pPolyData);


  // <#4> 创建映射器
  vtkSmartPointer<vtkPolyDataMapper> mapper =
    vtkSmartPointer<vtkPolyDataMapper>::New();
  mapper->SetInputData(m_vtkPolyData);
  mapper->Update();


  // <#5> 创建演员
  vtkSmartPointer<vtkActor> actor =
    vtkSmartPointer<vtkActor>::New();
  actor->SetMapper(mapper);
  actor->GetProperty()->SetEdgeColor(0, 0, 0);
  actor->GetProperty()->EdgeVisibilityOn();


  // <#6> 查找相机
  vtkSmartPointer<vtkCamera> camera =
    m_vtkMainWindow->GetRenderers()->GetFirstRenderer()->GetActiveCamera();


  // <#7> 创建渲染器
  vtkSmartPointer<vtkRenderer> prevRenderer =
    m_vtkMainWindow->GetRenderers()->GetFirstRenderer();
  if (prevRenderer != NULL)
    m_vtkMainWindow->RemoveRenderer(prevRenderer);


  vtkSmartPointer<vtkRenderer> renderer =
    vtkSmartPointer<vtkRenderer>::New();
  renderer->AddActor(actor);//将演员添加到渲染器
  renderer->SetBackground(.1, .2, .3);
  renderer->SetActiveCamera(camera);//设置激活的相机
  m_vtkMainWindow->AddRenderer(renderer);//将渲染器添加到 渲染窗口


  // <#8>在屏幕上绘图
  m_vtkMainWindow->Render();
}
//填充孔洞
void CappMeshEditorDlg::OnBnClickedFillHole()
{
  try
  {
    // <#>填充孔洞过滤器设置
    vtkSmartPointer<vtkFillHolesFilter> fillHolesFilter =
      vtkSmartPointer<vtkFillHolesFilter>::New();
    fillHolesFilter->SetInputData(m_vtkPolyData);//设置输入数据
    fillHolesFilter->SetHoleSize(100000.0);//孔尺寸
    fillHolesFilter->Update();


    // <#> Mapper  填充的数据集映射器
    vtkSmartPointer<vtkPolyDataMapper> filledMapper =
      vtkSmartPointer<vtkPolyDataMapper>::New();
    filledMapper->SetInputData(fillHolesFilter->GetOutput());
    filledMapper->Update();


    // <#>颜色设置
    vtkSmartPointer<vtkNamedColors> colors =
      vtkSmartPointer<vtkNamedColors>::New();




    //original原来,backFace 是正确的,但在 FillHole 中,它是 FilledFace 颜色。
    // 在FillHole中,为了区分颜色,我们需要检查法线是否反转填充。
    vtkSmartPointer<vtkProperty> backfaceProp =
      vtkSmartPointer<vtkProperty>::New();
    backfaceProp->SetDiffuseColor(colors->GetColor3d("red").GetData());//红色


    // <#> 演员设置
    vtkSmartPointer<vtkActor> filledActor =
      vtkSmartPointer<vtkActor>::New();
    filledActor->SetMapper(filledMapper);//设置数据集映射器
    //设置/获取控制此演员背面backface属性的属性对象。这应该是 vtkProperty 对象的一个实例。
    //如果未指定,则将使用front face正面属性。多个actor可以共享一个属性对象。
    filledActor->SetBackfaceProperty(backfaceProp);// 
    filledActor->GetProperty()->SetDiffuseColor(
      colors->GetColor3d("white").GetData());//设置/获取漫反射表面颜色。
    filledActor->GetProperty()->SetEdgeColor(0, 0, 0);//设置图元边的颜色
    filledActor->GetProperty()->EdgeVisibilityOn();//边可见


    // <#> Renderer 渲染
    vtkSmartPointer<vtkRenderer> prevRenderer =
      m_vtkMainWindow->GetRenderers()->GetFirstRenderer();
    if (prevRenderer != NULL)
      m_vtkMainWindow->RemoveRenderer(prevRenderer);


    vtkSmartPointer<vtkRenderer> Renderer =
      vtkSmartPointer<vtkRenderer>::New();
    Renderer->AddActor(filledActor);//填充的对象
    Renderer->SetBackground(0.1, 0.2, 0.3);
    m_vtkMainWindow->AddRenderer(Renderer);


    // <#>在屏幕上绘图
    m_vtkMainWindow->Render();


    // <#>更新 m_pPolyData 
    m_vtkPolyData = fillHolesFilter->GetOutput();
  }
  catch (...)
  {
    ::MessageBox(NULL, _T("OnBnClickedHoleFilling"), _T("Exception"), MB_OK);
  }
}
#pragma endregion


#pragma region // VTK Code
void CappMeshEditorDlg::CreateVTKWindow(void* hWnd)
{
  try
  {
    if (m_vtkMainWindow != NULL)
      throw;


    // <#>创建交互器  Create Interactor
    vtkSmartPointer<vtkRenderWindowInteractor> interactor =
      vtkSmartPointer<vtkRenderWindowInteractor>::New();


    // <#> 设置轨迹球类型 Set Trackball type
    //在VTK中,对于vtkInteractorStyle类继承类,常用的有2中,vtkInteractorStyleTrackballCamera和
    //vtkInteractorStyleTrackballActor.第一个类是通过修改相机来该改变察角度和物体大小。第二个类是通过改变actor来改变物体的位置和大小。
    interactor->SetInteractorStyle(
      vtkSmartPointer<vtkInteractorStyleTrackballCamera>::New());


    // <#> 将观察者添加到交互器 Add observer to Interactor
    vtkSmartPointer<vtkCallbackCommand> mouseoverCallback =
      vtkSmartPointer<vtkCallbackCommand>::New();
    mouseoverCallback->SetCallback(Callback_MouseOver_Face);
    mouseoverCallback->SetClientData(this);
    interactor->AddObserver(vtkCommand::MouseMoveEvent, mouseoverCallback); //鼠标移动事件


    // <#>创建渲染器  Create Renderer
    vtkSmartPointer<vtkRenderer> renderer =
      vtkSmartPointer<vtkRenderer>::New();


    // <#> 设置渲染器的背景 Set Backgrund of Renderer
    renderer->SetBackground(0.1, 0.2, 0.3);


    // <#>将渲染器添加到 RenderWindow  
    m_vtkMainWindow = vtkSmartPointer<vtkRenderWindow>::New();
    m_vtkMainWindow->SetParentId(hWnd);  //(hun) IDC_STATIC_MAINFRAME设置父句柄 .
    //RECT rect;
    //GetDlgItem(IDC_STATIC_MAINFRAME)->GetWindowRect(&rect);
    //int title_height = 0;//32;
    //int button_test_height = 0;//30;
    //rect = rc;
    ///m_vtkMainWindow->SetSize(rect.right - rect.left, rect.bottom - rect.top - title_height - button_test_height);
    //m_vtkMainWindow->SetPosition(rect.left, rect.top + title_height + button_test_height);
    m_vtkMainWindow->SetInteractor(interactor);//设置渲染窗口的 交互器
    m_vtkMainWindow->AddRenderer(renderer);//添加渲染器到渲染窗口 
    //interactor->SetRenderWindow(m_vtkMainWindow);
    m_vtkMainWindow->Render(); //渲染 
    //iren->SetRenderWindow(m_vtkMainWindow);


    //interactor->Initialize();
    //interactor->Start();
  }
  catch (...)
  {
    ::MessageBox(NULL, _T("CreateVTKWindow"), _T("Exception"), MB_OK);
  }
}
//删除渲染窗口
void CappMeshEditorDlg::DeleteVTKWindow()
{
  try
  {
    if (m_vtkMainWindow == NULL)
      throw;


    m_vtkMainWindow = NULL;  // (hun) SmartPointer将其更改为 NULL 以供使用,以便垃圾收集器将其删除。
  }
  catch (...)
  {
    ::MessageBox(NULL, _T("DeleteVTKWindow"), _T("Exception"), MB_OK);
  }
}
//调整渲染窗口大小
void CappMeshEditorDlg::ResizeVtkWindow()
{
  CRect rc;
  GetDlgItem(IDC_STATIC_MAINFRAME)->GetClientRect(rc);
  m_vtkMainWindow->SetSize(rc.Width(), rc.Height());//设置窗口大小
}
//调整窗口尺寸
void CappMeshEditorDlg::OnSize(UINT nType, int cx, int cy)
{
  CDialog::OnSize(nType, cx, cy);
  this->ResizeVtkWindow();
}
//生成邻居列表  输出相邻面索引向量vecOut,  输入选中索引向量,三角面片过滤器
void CappMeshEditorDlg::GenerateNeighborList(OUT std::vector<vtkIdType>& vecOut,
  IN std::vector<vtkIdType>& vecIn, IN vtkSmartPointer<vtkTriangleFilter>& triangleFilter)
{
  for (std::vector<vtkIdType>::iterator iter = vecIn.begin(); iter != vecIn.end(); ++iter)//遍历所有待求邻居的面索引
  {
    vtkIdType cellId = *(iter);//获取一个面单元


    vtkSmartPointer<vtkIdList> cellPointIds =
      vtkSmartPointer<vtkIdList>::New();//
    // 获取面的顶点索引  Get Vertex Ids From Face Id
    triangleFilter->GetOutput()->GetCellPoints(cellId, cellPointIds);//获取面单元的顶点ID


    for (vtkIdType i = 0; i < cellPointIds->GetNumberOfIds(); i++)//遍历面的顶点
    {
      vtkSmartPointer<vtkIdList> idList =
        vtkSmartPointer<vtkIdList>::New();
      vtkIdType temp = cellPointIds->GetId(i);  // 顶点索引  Vertex Id
      idList->InsertNextId(temp);//添加到顶点列表


      //获取单元的邻居 get the neighbors of the cell
      vtkSmartPointer<vtkIdList> neighborCellIds =
        vtkSmartPointer<vtkIdList>::New();//邻居索引列表


      triangleFilter->GetOutput()->GetCellNeighbors(cellId, idList,
        neighborCellIds);// 根据面id,顶点id,计算相邻面id


      for (vtkIdType j = 0; j < neighborCellIds->GetNumberOfIds(); j++)
        vecOut.push_back(neighborCellIds->GetId(j));//将面id添加到vecOut
    }
  }
}
//删除重复数据     面片索引矢量
void CappMeshEditorDlg::Deduplication(std::vector<vtkIdType>& vec)
{
  std::sort(vec.begin(), vec.end());
  std::vector<vtkIdType>::iterator iter = std::unique(vec.begin(), vec.end());
  vec.erase(iter, vec.end());
}
//获取邻居环
void CappMeshEditorDlg::GenerateNeighborRing(OUT std::vector<vtkIdType>& vecOut,//输出
  IN std::vector<vtkIdType>& vecMax,//最外层计算的邻居索引
  IN std::vector<vtkIdType>& vecMin,//倒数第二层计算的邻居索引
  IN std::vector<vtkIdType>& vecPickFace)//选中面
{
  std::vector<vtkIdType> vecRef = vecMin;
  vecRef.push_back(vecPickFace.at(0));
  for (std::vector<vtkIdType>::iterator iterMax = vecMax.begin(); iterMax != vecMax.end(); ++iterMax)
  {
    bool bIsSame = false;
    for (std::vector<vtkIdType>::iterator iterMin = vecRef.begin(); iterMin != vecRef.end(); ++iterMin)
    {
      if ((*iterMax) == (*iterMin))
      {
        bIsSame = true;//最外层计算的邻居中有 且倒数第二层计算的邻居中也有,排除掉
        break;
      }
    }


    if (bIsSame == false)
      vecOut.push_back((*iterMax));
  }
}
//邻居区域:输出vecOut, 输入邻居索引,输入选中点所在三角面片的索引
void CappMeshEditorDlg::GenerateNeighborArea(OUT std::vector<vtkIdType>& vecOut,
  IN std::vector<vtkIdType>& vecMax,
  IN std::vector<vtkIdType>& vecPickFace)
{
  for (std::vector<vtkIdType>::iterator iterMax = vecMax.begin(); iterMax != vecMax.end(); ++iterMax)
  {
    if ((*iterMax) == vecPickFace.at(0))//选中面
      continue;


    vecOut.push_back((*iterMax));//邻居面索引
  }
}
#pragma endregion

 参考网址:

https://vtk.org/ VTK - The Visualization Toolkit

https://blog.csdn.net/ddffmm66/article/details/83577521 VTK入门_ddffmm66的博客-CSDN博客_vtk入门

https://www.jianshu.com/p/b32a657b8649 vtk学习笔记 - 简书 (jianshu.com)

https://blog.csdn.net/qq_34690929/article/details/78146523  ITK和VTK比较_Florence_Janie的博客-CSDN博客_itk vtk

https://www.zhihu.com/question/48405161 VTK ITK OPENCV,从图像处理的角度来说,哪种用的人多? - 知乎 (zhihu.com)

  • 2
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
vtk8.2是一个用于数据可视化和图像处理的开源库,可以在MFC应用程序中使用。以下是在MFC应用程序中安装vtk8.2的步骤: 1. 下载vtk8.2的安装文件:可以在vtk的官方网站上下载vtk8.2的安装包,选择与您的系统相匹配的版本。 2. 解压安装文件:将下载的文件解压到您想要安装vtk的位置。 3. 配置环境变量:在系统环境变量中添加vtk的路径。打开控制面板,选择“系统和安全”,然后选择“系统”。在弹出的对话框中,选择“高级系统设置”,然后点击“环境变量”。在系统变量中找到“Path”,点击“编辑”,将vtk的路径添加到变量值中。 4. 配置MFC项目:打开您的MFC项目,右击“属性”选项,选择“VC++目录”,然后选择“包含目录”并添加vtk的路径。同样,选择“库目录”并添加vtk的lib文件路径。 5. 包含vtk头文件:在您的MFC项目中的源文件中包含vtk的头文件。例如: ```cpp #include "vtkAutoInit.h" VTK_MODULE_INIT(vtkRenderingOpenGL2) #include "vtkActor.h" #include "vtkRenderWindow.h" ... ``` 6. 链接vtk库文件:在您的MFC项目的链接器设置中,添加vtk库文件的名称。例如,在“连接器”->“输入”->“附加依赖项”中添加以下文件名: ```txt vtkCommonCore-8.2.lib vtkFiltersCore-8.2.lib vtkRenderingCore-8.2.lib ... ``` 7. 构建和运行项目:保存并构建您的MFC项目,然后运行它。现在,您可以在MFC应用程序中使用vtk8.2库来进行数据可视化和图像处理了。 这是vtk8.2MFC应用程序中的安装过程。希望能够帮助到您!

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值