开发环境:
- Windows 11 家庭中文版
- Microsoft Visual Studio Community 2019
- VTK-9.3.0.rc0
- vtk-example
demo解决问题:在图像上添加标记和数字的功能。
关键点:
- MyStyle类继承自vtkActorStyleImage,用于创建图像渲染的自定义交互式样式。
- 在’MyStyle’类中,'OnLeftButtonDown’函数被重写以处理鼠标左键点击。它会获取用户点击的像素位置,在该位置添加一个标记,然后执行交互样式的默认行为。
- 'MyStyle’中的’AddNumber’函数负责在指定的2D位置添加一个数字作为标记。它使用vtkCaptionActor2D类创建一个文本标签,并将其附加到指定的位置上。注意:vtkCaptionActor2D 是一个混合的 2D/3D 角色,用于将文本与场景中的点(AttachmentPoint)关联。绘制的标题可带有矩形边框和连接标题与附件点的引线。可以选择在其端点处对引线进行字形化,以创建箭头或其他指示符。
- 'main’函数设置了图像渲染的流水线。它创建了一个空白图像,在其中绘制了一个红色圆圈,并设置了窗口、渲染器和交互器。
prj name: CaptionActor2D
#include <vtkAbstractPicker.h>
#include <vtkActor2D.h>
#include <vtkCaptionActor2D.h>
#include <vtkImageActor.h>
#include <vtkImageCanvasSource2D.h>
#include <vtkImageMapper3D.h>
#include <vtkInteractorStyleImage.h>
#include <vtkNamedColors.h>
#include <vtkNew.h>
#include <vtkObjectFactory.h>
#include <vtkProperty.h>
#include <vtkRenderWindow.h>
#include <vtkRenderWindowInteractor.h>
#include <vtkRenderer.h>
#include <vtkTextProperty.h>
#include <iostream>
#include <sstream>
#include <string>
namespace {
class MyStyle : public vtkInteractorStyleImage
{
public:
static MyStyle* New();
vtkTypeMacro(MyStyle, vtkInteractorStyleImage);
std::vector<vtkActor2D*> Numbers;
void OnLeftButtonDown()
{
// std::cout << "Picking pixel: " << this->Interactor->GetEventPosition()[0]
// << " " << this->Interactor->GetEventPosition()[1] << std::endl;
this->Interactor->GetPicker()->Pick(
this->Interactor->GetEventPosition()[0],
this->Interactor->GetEventPosition()[1],
0, // always zero.
// this->Interactor->GetRenderWindow()->GetRenderers()->GetFirstRenderer());
this->CurrentRenderer);
double picked[3];
this->Interactor->GetPicker()->GetPickPosition(picked);
// std::cout << "Picked point with coordinate: " << picked[0] << " " <<
// picked[1] << " " << picked[2] << std::endl;
this->AddNumber(picked);
// Forward events
vtkInteractorStyleImage::OnLeftButtonDown();
// this->Interactor->GetRenderWindow()->Render();
this->Interactor->Render();
}
void AddNumber(double p[3])
{
std::cout << "Adding marker at " << p[0] << " " << p[1]; //<< std::endl;
// normally, with an image you would do
// double* s = image->GetSpacing();
// double* o = image->GetOrigin();
// p[0] = static_cast<int>( (p[0] - o[0]) / s[0] + 0.5 );
p[0] = static_cast<int>(p[0] + 0.5);
p[1] = static_cast<int>(p[1] + 0.5);
std::cout << " -> " << p[0] << " " << p[1] << std::endl;
// Convert the current number to a string
std::stringstream ss;
ss << Numbers.size();
std::cout << "Adding number: " << ss.str() << std::endl;
// Create an actor for the text
vtkNew<vtkCaptionActor2D> captionActor;
captionActor->SetCaption(ss.str().c_str());
captionActor->SetAttachmentPoint(p);
captionActor->BorderOff();
captionActor->GetCaptionTextProperty()->BoldOff();
captionActor->GetCaptionTextProperty()->ItalicOff();
captionActor->GetCaptionTextProperty()->ShadowOff();
captionActor->ThreeDimensionalLeaderOff();
this->CurrentRenderer->AddViewProp(captionActor);
this->Numbers.push_back(captionActor);
}
};
vtkStandardNewMacro(MyStyle);
} // namespace
int main(int, char*[])
{
vtkNew<vtkNamedColors> colors;
// Create a blank, black image.
vtkNew<vtkImageCanvasSource2D> drawing;
drawing->SetScalarTypeToUnsignedChar();
drawing->SetNumberOfScalarComponents(3);
drawing->SetExtent(0, 20, 0, 50, 0, 0);
drawing->FillBox(0, 20, 0, 50);
// Draw a red circle of radius 5 centered at (9,10).
drawing->SetDrawColor(255, 0, 0, 0);
drawing->DrawCircle(9, 10, 5);
drawing->Update();
vtkNew<vtkImageActor> actor;
actor->GetMapper()->SetInputConnection(drawing->GetOutputPort());
actor->InterpolateOff();
vtkNew<vtkRenderer> renderer;
vtkNew<vtkRenderWindow> renderWindow;
renderWindow->AddRenderer(renderer);
renderWindow->SetWindowName("CaptionActor2D");
vtkNew<vtkRenderWindowInteractor> renderWindowInteractor;
renderWindowInteractor->SetRenderWindow(renderWindow);
renderer->AddActor(actor);
renderer->SetBackground(colors->GetColor3d("Silver").GetData());
renderer->GradientBackgroundOn();
renderer->SetBackground2(colors->GetColor3d("Blue").GetData());
renderWindow->Render();
vtkNew<MyStyle> style;
renderWindowInteractor->SetInteractorStyle(style);
style->SetDefaultRenderer(renderer);
style->SetCurrentRenderer(renderer);
renderWindowInteractor->Start();
return EXIT_SUCCESS;
}