摘要
文章目录
1 官方示例展示
2 代码搬运
2.1 graphitem.h
2.2 graphitem.cpp
2.3 vtkContextItem.h
2.4 vtkContextItem.cpp
3 运行效果
4 错误解决方法
Error: no override found for 'vtkContextDevice2D'.
★ 源码 ★
1 官方示例展示
前面有好几个例子有点复杂,现在还搞不到定,先搬运下这个。下图是官方的示例。
有个比较尴尬的是发生了,就是官方的Demo现在也不能演示了,没有内容了,直接给我白屏了。
2 代码搬运
2.1 graphitem.h
#include "graphitem.h" #include "ui_graphitem.h" GraphItem::GraphItem(QWidget *parent) : QWidget(parent), ui(new Ui::GraphItem) { ui->setupUi(this); mview = vtkSmartPointer<vtkContextView>::New(); mview->GetRenderer()->SetBackground(0.0, 1.0, 1.0); mview->GetRenderWindow()->SetSize(800, 600); source = vtkSmartPointer<vtkRandomGraphSource>::New(); source->SetNumberOfVertices(100); source->SetNumberOfEdges(0); source->StartWithTreeOn(); source->Update(); item = vtkSmartPointer<vtkGraphItem>::New(); item->SetGraph(source->GetOutput()); mview->GetScene()->AddItem(item); anim = vtkSmartPointer<GraphAnimate>::New(); anim->view = mview; anim->GraphItem = item; mview->SetRenderWindow(ui->widget->GetRenderWindow()); mview->GetRenderWindow()->GetInteractor()->Initialize(); mview->GetRenderWindow()->GetInteractor()->CreateOneShotTimer(10); mview->GetRenderWindow()->GetInteractor()->AddObserver(vtkCommand::TimerEvent, anim); } GraphItem::~GraphItem() { delete ui; } void GraphItem::startinteractor() { // view->GetRenderWindow()->GetInteractor()->Start(); }
2.2 graphitem.cpp
#include "graphitem.h" #include "ui_graphitem.h" GraphItem::GraphItem(QWidget *parent) : QWidget(parent), ui(new Ui::GraphItem) { ui->setupUi(this); mview = vtkSmartPointer<vtkContextView>::New(); mview->GetRenderer()->SetBackground(0.0, 1.0, 1.0); mview->GetRenderWindow()->SetSize(800, 600); source = vtkSmartPointer<vtkRandomGraphSource>::New(); source->SetNumberOfVertices(100); source->SetNumberOfEdges(0); source->StartWithTreeOn(); source->Update(); item = vtkSmartPointer<vtkGraphItem>::New(); item->SetGraph(source->GetOutput()); mview->GetScene()->AddItem(item); anim = vtkSmartPointer<GraphAnimate>::New(); anim->view = mview; anim->GraphItem = item; mview->SetRenderWindow(ui->widget->GetRenderWindow()); mview->GetRenderWindow()->GetInteractor()->Initialize(); mview->GetRenderWindow()->GetInteractor()->CreateOneShotTimer(10); mview->GetRenderWindow()->GetInteractor()->AddObserver(vtkCommand::TimerEvent, anim); } GraphItem::~GraphItem() { delete ui; } void GraphItem::startinteractor() { // view->GetRenderWindow()->GetInteractor()->Start(); }
2.3 vtkContextItem.h
#ifndef VTKGRAPHITEM_H #define VTKGRAPHITEM_H #include "vtkContextItem.h" #include "vtkEdgeListIterator.h" #include "vtkOutEdgeIterator.h" #include "vtkGraph.h" #include "vtkMinimalStandardRandomSequence.h" #include "vtkVariant.h" #include "vtkContext2D.h" #include "vtkContextScene.h" #include "vtkContextMouseEvent.h" #include "vtkPen.h" #include "vtkBrush.h" #include "vtkTextProperty.h" #include "vtkTransform2D.h" #include "vtkObjectFactory.h" #include "vtkSmartPointer.h" #include "utility" #include "vector" class vtkContext2D; class vtkGraph; class vtkGraphItem : public vtkContextItem { public: vtkTypeMacro(vtkGraphItem,vtkContextItem); void PrintSelf(ostream &os, vtkIndent indent) override; static vtkGraphItem *New(); vtkGetObjectMacro(Graph,vtkGraph); virtual void SetGraph(vtkGraph* g); bool Paint(vtkContext2D *painter) override; bool Hit(const vtkContextMouseEvent &mouse)override; bool MouseEnterEvent(const vtkContextMouseEvent &mouse)override; bool MouseMoveEvent(const vtkContextMouseEvent &mouse)override; bool MouseLeaveEvent(const vtkContextMouseEvent &mouse)override; bool MouseButtonPressEvent(const vtkContextMouseEvent &mouse)override; bool MouseButtonReleaseEvent(const vtkContextMouseEvent &mouse)override; void UpdatePositions(); protected: vtkGraphItem(); ~vtkGraphItem() override; float LastPosition[2]; bool MouseOver; int MouseButtonPressed; vtkGraph *Graph; vtkIdType HitVertex; class Implementation; Implementation *Impl; private: vtkGraphItem(const vtkGraphItem &) = delete; void operator =(const vtkGraphItem &) = delete; }; #endif // VTKGRAPHITEM_H
2.4 vtkContextItem.cpp
这段代码偷懒了,直接把Demo中的代码复制过来了
#include "vtkgraphitem.h" vtkCxxSetObjectMacro(vtkGraphItem, Graph, vtkGraph); vtkStandardNewMacro(vtkGraphItem); class vtkGraphItem::Implementation { public: Implementation() { Random = vtkSmartPointer<vtkMinimalStandardRandomSequence>::New(); } void CheckPositionSize(vtkIdType i) { while (i >= static_cast<vtkIdType>(this->Position.size())) { int size[2] = {100, 100}; if (this->Item->GetScene()) { this->Item->GetScene()->GetGeometry(size); } this->Random->Next(); float x = static_cast<int>(this->Random->GetValue()*size[0]); this->Random->Next(); float y = static_cast<int>(this->Random->GetValue()*size[1]); this->Position.push_back(std::make_pair(x, y)); } } void GetPosition(vtkIdType i, float x[2]) { this->CheckPositionSize(i); x[0] = this->Position[i].first; x[1] = this->Position[i].second; } void SetPosition(vtkIdType i, float x[2]) { this->CheckPositionSize(i); this->Position[i] = std::make_pair(x[0], x[1]); } void CheckVelocitySize(vtkIdType i) { while (i >= static_cast<vtkIdType>(this->Velocity.size())) { this->Velocity.push_back(std::make_pair(0.0f, 0.0f)); } } void GetVelocity(vtkIdType i, float x[2]) { this->CheckVelocitySize(i); x[0] = this->Velocity[i].first; x[1] = this->Velocity[i].second; } void SetVelocity(vtkIdType i, float x[2]) { this->CheckVelocitySize(i); this->Velocity[i] = std::make_pair(x[0], x[1]); } vtkSmartPointer<vtkMinimalStandardRandomSequence> Random; vtkGraphItem* Item; std::vector<std::pair<float, float> > Position; std::vector<std::pair<float, float> > Velocity; }; //----------------------------------------------------------------------------- vtkGraphItem::vtkGraphItem() { this->Impl = new Implementation(); this->Impl->Item = this; this->Graph = nullptr; this->MouseOver = false; this->MouseButtonPressed = -1; this->HitVertex = 0; } //----------------------------------------------------------------------------- vtkGraphItem::~vtkGraphItem() { delete this->Impl; this->SetGraph(nullptr); } //----------------------------------------------------------------------------- bool vtkGraphItem::Paint(vtkContext2D *painter) { painter->GetTextProp()->SetVerticalJustificationToCentered(); painter->GetTextProp()->SetJustificationToCentered(); painter->GetTextProp()->SetColor(0.0, 0.0, 0.0); painter->GetTextProp()->SetFontSize(12); painter->GetPen()->SetColorF(0.0f, 0.0f, 0.0f); painter->GetBrush()->SetColorF(0.8f, 0.8f, 1.0f, 0.5f); vtkSmartPointer<vtkEdgeListIterator> it = vtkSmartPointer<vtkEdgeListIterator>::New(); this->Graph->GetEdges(it); float line[4] = {0.0f, 0.0f, 0.0f, 0.0f}; while (it->HasNext()) { vtkEdgeType e = it->Next(); this->Impl->GetPosition(e.Source, line); this->Impl->GetPosition(e.Target, line+2); for (int i = 0; i < 4; ++i) { line[i] += 10.0f; } painter->DrawLine(line); } float dims[4] = {0.0f, 0.0f, 20.0f, 20.0f}; for (vtkIdType i = 0; i < this->Graph->GetNumberOfVertices(); ++i) { this->Impl->GetPosition(i, dims); painter->DrawRect(dims[0], dims[1], dims[2], dims[3]); float x = dims[0] + 0.5 * dims[2]; float y = dims[1] + 0.5 * dims[3]; painter->DrawString(x, y, vtkVariant(i).ToString()); } return true; } //----------------------------------------------------------------------------- bool vtkGraphItem::Hit(const vtkContextMouseEvent &mouse) { float pos[2] = {0.0f, 0.0f}; for (vtkIdType i = this->Graph->GetNumberOfVertices()-1; i >= 0; --i) { this->Impl->GetPosition(i, pos); if (mouse.GetPos()[0] > pos[0] && mouse.GetPos()[0] < pos[0] + 20.0f && mouse.GetPos()[1] > pos[1] && mouse.GetPos()[1] < pos[1] + 20.0f) { this->HitVertex = i; return true; } } return false; } //----------------------------------------------------------------------------- bool vtkGraphItem::MouseEnterEvent(const vtkContextMouseEvent &) { this->MouseOver = true; return true; } //----------------------------------------------------------------------------- bool vtkGraphItem::MouseMoveEvent(const vtkContextMouseEvent &mouse) { int deltaX = static_cast<int>(mouse.GetPos()[0] - this->LastPosition[0]); int deltaY = static_cast<int>(mouse.GetPos()[1] - this->LastPosition[1]); this->LastPosition[0] = mouse.GetPos()[0]; this->LastPosition[1] = mouse.GetPos()[1]; if (this->MouseButtonPressed == 0) { // Move the vertex by this amount float pos[2]; this->Impl->GetPosition(this->HitVertex, pos); pos[0] += deltaX; pos[1] += deltaY; this->Impl->SetPosition(this->HitVertex, pos); return true; } #if 0 if (this->MouseButtonPressed == 1) { if (deltaX > 0.0) { if (!this->GetTransform()) { vtkSmartPointer<vtkTransform2D> t = vtkSmartPointer<vtkTransform2D>::New(); t->Identity(); this->SetTransform(t); } this->GetTransform()->Scale(deltaX/50.0f, deltaX/50.0f); } return true; } #endif return false; } //----------------------------------------------------------------------------- bool vtkGraphItem::MouseLeaveEvent(const vtkContextMouseEvent &) { this->MouseOver = false; return true; } //----------------------------------------------------------------------------- bool vtkGraphItem::MouseButtonPressEvent(const vtkContextMouseEvent &mouse) { this->MouseButtonPressed = mouse.GetButton(); this->LastPosition[0] = mouse.GetPos()[0]; this->LastPosition[1] = mouse.GetPos()[1]; return true; } //----------------------------------------------------------------------------- bool vtkGraphItem::MouseButtonReleaseEvent(const vtkContextMouseEvent &) { this->MouseButtonPressed = -1; return true; } //----------------------------------------------------------------------------- void vtkGraphItem::UpdatePositions() { vtkIdType numVerts = this->Graph->GetNumberOfVertices(); float restDistance = 40.0f; float dampenLast = 0.5f; float springConstant = 0.3f; float repulseConstant = 1.0f; //float restDistance = 40.0f; //float dampenLast = 0.5f; //float springConstant = 0.1f; //float repulseConstant = 2.0f; float epsilon = 0.0000001f; float border = 20.0f; vtkSmartPointer<vtkOutEdgeIterator> it = vtkSmartPointer<vtkOutEdgeIterator>::New(); float uPos[2]; float vPos[2]; float uVel[2]; int geom[2] = {100, 100}; if (this->GetScene()) { this->GetScene()->GetGeometry(geom); } for (vtkIdType u = 0; u < numVerts; ++u) { if (this->MouseButtonPressed == 0 && u == this->HitVertex) { continue; } this->Impl->GetPosition(u, uPos); float fx = 0.0; float fy = 0.0; for (vtkIdType v = 0; v < numVerts; ++v) { this->Impl->GetPosition(v, vPos); float deltaX = uPos[0] - vPos[0]; float deltaY = uPos[1] - vPos[1]; float distSquared = deltaX*deltaX + deltaY*deltaY; // Avoid divide by zero distSquared += epsilon; fx += repulseConstant * deltaX / distSquared; fy += repulseConstant * deltaY / distSquared; } this->Graph->GetOutEdges(u, it); while (it->HasNext()) { vtkOutEdgeType e = it->Next(); vtkIdType v = e.Target; if (u == v) { continue; } this->Impl->GetPosition(v, vPos); float deltaX = uPos[0] - vPos[0]; float deltaY = uPos[1] - vPos[1]; float dist = sqrt(deltaX*deltaX + deltaY*deltaY); float force = springConstant*(dist - restDistance); fx -= force * deltaX / dist; fy -= force * deltaY / dist; } float center[2] = {uPos[0] + 10.0f, uPos[1] + 10.0f}; // Change the force if it is near the edge if (center[0] < border) { fx += -(center[0] - border); } else if (center[0] > geom[0] - border) { fx += -(center[0] - (geom[0] - border)); } if (center[1] < border) { fy += -(center[1] - border); } else if (center[1] > geom[1] - border) { fy += -(center[1] - (geom[1] - border)); } // Update velocity and position this->Impl->GetVelocity(u, uVel); uVel[0] = dampenLast*uVel[0] + fx; uVel[1] = dampenLast*uVel[1] + fy; uPos[0] += uVel[0]; uPos[1] += uVel[1]; this->Impl->SetPosition(u, uPos); this->Impl->SetVelocity(u, uVel); } } //----------------------------------------------------------------------------- void vtkGraphItem::PrintSelf(ostream &os, vtkIndent indent) { this->Superclass::PrintSelf(os, indent); }
3 运行效果
这个就尴尬了,目前在的这台电脑上市出不来效果了,包括官方的Demo也是白屏状态,目前还不知道啥情况。留坑。
4 错误解决方法
Error: no override found for ‘vtkContextDevice2D’.
在main中加入VTK_MODULE_INIT(vtkRenderingContextOpenGL);
在加入上面的语句后,会出现如下错误
老鸟一看这应该就是丢库了,我这二货还不知道,搞了好久,网上找了半天,终于找到了提示,需要看下库有没有包含进去
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-0Kj3nzL5-1628730592619)(https://raw.githubusercontent.com/DreamLife-Jianwei/CSDNResources/master/20210629093058.png)]
如上图所示,在检查了我包含的库文件后,修改代码为
VTK_MODULE_INIT(vtkRenderingContextOpenGL2);
搞定!!!
★ 源码 ★
源码分享一时爽,一直分享一直爽, 链接如下:
自取:https://github.com/DreamLife-Jianwei/Qt-Vtk