当前位置:网站首页>【VTK】MFC基于VTK8.2的网格编辑器
【VTK】MFC基于VTK8.2的网格编辑器
2022-06-29 10:51:00 【十年一梦实验室】
视频演示


主界面截图
主要源码:
// 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)
边栏推荐
- Oracle NetSuite 助力 TCM Bio,洞悉数据变化,让业务发展更灵活
- 通过网上进行股票开户安全吗
- 安全 创新 实践|海泰方圆受邀参加“数字时代的网信创新与价值共创”技术交流研讨会
- 2.8万字的Callable和Future面试知识点总结,看完我直接面进了字节跳动,原谅我有点飘了(下)
- 基于鲲鹏开发套件实现x86平台到Kunpeng平台的源码迁移【玩转华为云】
- TTL serial port learning infrared remote control module can be extended to network control
- Uber前安全主管面临欺诈指控 曾隐瞒数据泄露事件
- seekg ()[通俗易懂]
- Nature | biosynthetic potential of global marine microbiome
- What is the experience of working in an IT company in Japan?
猜你喜欢

How to test the performance of container platform, including stability, expansion efficiency and component performance

leetcode刷题:字符串07(重复的子字符串)

稳定币风险状况:USDT 和 USDC 安全吗?

Qt学习07 Qt中的坐标系统

又拍雲 Redis 的改進之路

【文献翻译】Concealed Object Detection(伪装目标检测)

(JS) array de duplication

Modbustcp protocol network learning single channel infrared module (double-layer board)

QT learning 08 set sail! First application instance

高效远程办公的基石:有效沟通 |社区征文
随机推荐
The use of Fibonacci sequence and bubble sort in C language
The first "cyborg" in the world died, and he only transformed himself to "change his life against the sky"
记一次 MSI 笔记本 GE63 播放网页视频 闪屏和随机发绿 问题解决
Object 类——万类之父
seekg ()[通俗易懂]
(JS) pure function in array
Modbustcp protocol network learning single channel infrared module (medium shell version)
Design and implementation of IDS
(JS) isnan() method determines the reason why undefined is true
【毕业季】总结过去,展望未来
毕业5年,我问遍了身边的大佬,总结了他们的学习方法
QT learning 09 calculator interface code reconstruction
【高并发】2.8万字的Callable和Future面试知识点总结,看完我直接面进了字节跳动,原谅我有点飘了(中)
MySQL enable slow query
Modbus RTU protocol 485 learning 2-way infrared module
二叉树递归与迭代
Pull and push ideas behind rxjs observable design principles
哈希Hash竞猜游戏系统开发详解技术丨哈希竞猜游戏系统开发方案解析
Oracle扩充分布式云端服务 为更多客户带来全面公有云服务
ES6 数组方法