VTK实现actor和坐标轴 缩放不变

5 篇文章 0 订阅
5 篇文章 0 订阅

VTK实现actor和坐标轴 缩放不变

描述

实现滚动鼠标中键(移动相机)时,保持坐标轴或者指定的actor在屏幕上看起来大小不变。
效果如下:视频中,立方体和坐标轴都设置了缩放不变,而旁边的圆柱体正常缩放。

vtk actor 和坐标轴缩放不变(相机距离不影响actor在屏幕上的大小)

源码

//CMakeLists.txt
project(sameDisplaySize)

find_package( VTK REQUIRED )
include( ${VTK_USE_FILE} )

add_executable(${PROJECT_NAME} "main.cpp" "customIteractorStyle.h" "customIteractorStyle.cpp" )

target_link_libraries( ${PROJECT_NAME} ${VTK_LIBRARIES} )

=========================================================================

//customIteractorStyle.h
#include <iostream>
#include <vtkSmartPointer.h>
#include <vtkInteractorStyleTrackballCamera.h>
#include <vtkActor.h>
#include <vtkRenderWindow.h>
#include <vtkRenderer.h>
#include <vtkRenderWindowInteractor.h>
#include <vtkTransform.h>
#include <vtkAxesActor.h>

class customIteractorStyle: public vtkInteractorStyleTrackballCamera
{
public:
    static customIteractorStyle *New(){ return new customIteractorStyle(); }
    void OnMouseWheelForward() override;
    void OnMouseWheelBackward() override;
    void SetFixedRegularActor(vtkActor * actor);
    void SetFixedAxesActor(vtkAxesActor * actor);

protected:    
    customIteractorStyle();
    ~customIteractorStyle() override;
    void ScaleCube( double factor );
    void ScaleAxes( double factor );

    double m_ScaleFator[2];
    vtkActor *m_regularActor;
    vtkAxesActor* m_axesActor;
};

=========================================================================

//customIteractorStyle.cpp
#include "customIteractorStyle.h"

#include <vtkAutoInit.h>

//VTK_MODULE_INIT(vtkRenderingOpenGL2)
//VTK_MODULE_INIT(vtkRenderingFreeType)
VTK_MODULE_INIT(vtkInteractionStyle)
//VTK_MODULE_INIT(vtkRenderingContextOpenGL2)
VTK_MODULE_INIT(vtkRenderingVolumeOpenGL2);

void customIteractorStyle::OnMouseWheelForward()
{
    ScaleCube( m_ScaleFator[0] );
    ScaleAxes( m_ScaleFator[0] );
    vtkInteractorStyleTrackballCamera::OnMouseWheelForward();
}

void customIteractorStyle::OnMouseWheelBackward()
{
    ScaleCube( m_ScaleFator[1] );
    ScaleAxes( m_ScaleFator[1] );
    vtkInteractorStyleTrackballCamera::OnMouseWheelBackward();
}

void customIteractorStyle::SetFixedRegularActor(vtkActor *actor)
{
    if(this->m_regularActor!=actor)
    {
        this->m_regularActor=actor;
    }
}

void customIteractorStyle::SetFixedAxesActor(vtkAxesActor *actor)
{
    if(this->m_axesActor!=actor)
    {
        this->m_axesActor=actor;
    }
}

customIteractorStyle::customIteractorStyle()
{
    m_regularActor = nullptr;
    m_axesActor = nullptr;

    double wheelFactor = 0;
    wheelFactor = this->MotionFactor * (-0.2) * this->MouseWheelMotionFactor;
    m_ScaleFator[0] = pow(1.1, wheelFactor); // forward wheel
    wheelFactor = this->MotionFactor * 0.2 * this->MouseWheelMotionFactor;
    m_ScaleFator[1] = pow(1.1, wheelFactor); // back wheel
}

customIteractorStyle::~customIteractorStyle()
{
    m_regularActor = nullptr;
    m_axesActor = nullptr;
}

void customIteractorStyle::ScaleCube(double factor)
{
    if(m_regularActor==nullptr)
    {
        return;
    }
    vtkNew<vtkTransform> scaleTrans;
    scaleTrans->Scale( factor, factor, factor );
    scaleTrans->Update();

    vtkNew<vtkTransform> transC;
    transC->Concatenate( m_regularActor->GetUserTransform() );
    transC->Concatenate( scaleTrans );
    transC->Update();

    m_regularActor->SetUserTransform( transC );
}

void customIteractorStyle::ScaleAxes(double factor)
{
    if(m_axesActor==nullptr)
    {
        return;
    }
    vtkNew<vtkTransform> scaleTrans;
    scaleTrans->Scale( factor, factor, factor );
    scaleTrans->Update();


    vtkNew<vtkTransform> trans;
    trans->Concatenate( m_axesActor->GetUserTransform() );
    trans->Concatenate( scaleTrans );
    trans->Update();
    m_axesActor->SetUserTransform( trans );
}

=========================================================================

//main.cpp
#include <iostream>
#include <vtkSmartPointer.h>
#include <vtkActor.h>
#include <vtkRenderer.h>
#include <vtkRenderWindow.h>
#include <vtkPolyDataMapper.h>
#include <vtkRenderWindowInteractor.h>
#include <vtkCubeSource.h>
#include <vtkAxesActor.h>
#include <vtkTransform.h>
#include <vtkCylinderSource.h>
#include <vtkCamera.h>
#include "customIteractorStyle.h"

using namespace std;

int main()
{
    vtkNew<vtkCubeSource> cube;
    cube->Update();
    vtkNew<vtkPolyDataMapper> mapper;
    mapper->SetInputData( cube->GetOutput() );
    vtkNew<vtkActor> cubeActor;
    cubeActor->SetMapper( mapper );
    vtkNew<vtkTransform> userTrans;
//    userTrans->Translate( 0, 1, 0 );
//    userTrans->RotateZ( 45 );
    userTrans->Update();
    cubeActor->SetUserTransform( userTrans );

    vtkNew<vtkAxesActor> axesActor;
    vtkNew<vtkTransform>  userTrans2;
    userTrans2->Update();
    axesActor->SetUserTransform( userTrans2 );
    axesActor->AxisLabelsOff();
    axesActor->SetTotalLength(10,1,1);


    vtkNew<vtkCylinderSource> cylinder;
    cylinder->Update();
    vtkNew<vtkPolyDataMapper> cylinderMapper;
    cylinderMapper->SetInputData(cylinder->GetOutput());
    vtkNew<vtkActor> cylinderActor;
    cylinderActor->SetMapper(cylinderMapper);
    cylinderActor->SetPosition(1,1,1);

    vtkNew<vtkRenderer> renderer;
    renderer->AddActor( axesActor );
    renderer->AddActor( cubeActor );
    renderer->AddActor( cylinderActor );
    renderer->SetBackground( 0, 0, 0 );

    vtkNew<vtkRenderWindow> renderWindow;
    renderWindow->AddRenderer( renderer );

    vtkNew<vtkRenderWindowInteractor> renderWindowInteractor;
    renderWindowInteractor->SetRenderWindow( renderWindow );

    vtkNew<customIteractorStyle> style;
    style->SetFixedRegularActor( cubeActor );
    style->SetFixedAxesActor(axesActor );
    renderWindowInteractor->SetInteractorStyle( style );

//    renderer->GetActiveCamera()->SetParallelProjection(1);

    renderer->ResetCamera();
    renderWindow->Render();
    renderWindowInteractor->Start();
    return 0;
}

参考链接

有修改,添加了坐标轴缩放不变
https://www.weiy.city/2020/10/keep-model-same-display-size-when-zooming-in-out/

在C#中使用VTK(Visualization Toolkit)来绘制坐标轴和网格线可以通过以下步骤实现: 1. 导入VTK库: ```csharp using Kitware.VTK; ``` 2. 创建vtkRenderer和vtkRenderWindow对象: ```csharp vtkRenderer renderer = vtkRenderer.New(); vtkRenderWindow renderWindow = vtkRenderWindow.New(); renderWindow.AddRenderer(renderer); ``` 3. 创建vtkRenderWindowInteractor对象并设置renderWindow: ```csharp vtkRenderWindowInteractor renderWindowInteractor = vtkRenderWindowInteractor.New(); renderWindowInteractor.SetRenderWindow(renderWindow); ``` 4. 创建vtkAxesActor对象来绘制坐标轴: ```csharp vtkAxesActor axesActor = vtkAxesActor.New(); axesActor.AxisLabelsOff(); // 关闭坐标轴标签 axesActor.SetTotalLength(1, 1, 1); // 设置坐标轴长度 axesActor.SetShaftTypeToCylinder(); // 设置坐标轴形状为圆柱体 axesActor.SetCylinderRadius(0.02); // 设置坐标轴圆柱体半径 axesActor.SetConeRadius(0.1); // 设置坐标轴锥形半径 vtkOrientationMarkerWidget axesWidget = vtkOrientationMarkerWidget.New(); axesWidget.SetOutlineColor(0.9300, 0.5700, 0.1300); // 设置边框颜色 axesWidget.SetOrientationMarker(axesActor); axesWidget.SetInteractor(renderWindowInteractor); axesWidget.EnabledOn(); ``` 5. 创建vtkCellArray和vtkPolyData对象来绘制网格线: ```csharp vtkCellArray cellArray = vtkCellArray.New(); vtkPolyData polyData = vtkPolyData.New(); polyData.SetPoints(points); // 设置网格点坐标 for (int i = 0; i < numberOfLines; i++) { vtkLine line = vtkLine.New(); line.GetPointIds().SetId(0, lineIndices[i, 0]); line.GetPointIds().SetId(1, lineIndices[i, 1]); cellArray.InsertNextCell(line); } polyData.SetLines(cellArray); ``` 6. 创建vtkPolyDataMapper和vtkActor对象来渲染网格线: ```csharp vtkPolyDataMapper mapper = vtkPolyDataMapper.New(); mapper.SetInputData(polyData); vtkActor actor = vtkActor.New(); actor.SetMapper(mapper); actor.GetProperty().SetColor(1, 1, 1); // 设置网格线颜色 renderer.AddViewProp(actor); ``` 7. 最后,启动渲染循环: ```csharp renderWindow.Render(); renderWindowInteractor.Start(); ``` 以上是简单的示例代码,你可以根据你的需求进行修改和扩展。希望对你有所帮助!
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值