C++ Qt/VTK装配体组成联动连接杆

news2024/12/22 21:06:24

效果

在这里插入图片描述

关键代码

#include "View3D.h"
#include "Axis.h"

#include <vtkActor.h>
#include <vtkAppendPolyData.h >
#include <vtkAreaPicker.h>
#include <vtkAxesActor.h>
#include <vtkBox.h>
#include <vtkCamera.h>
#include <vtkCaptionActor2D.h>
#include <vtkCellArray.h>
#include <vtkCleanPolyData.h >
#include <vtkContourFilter.h>
#include <vtkCubeSource.h>
#include <vtkCylinder.h>
#include <vtkCylinderSource.h>
#include <vtkDataSet.h>
#include <vtkGenericOpenGLRenderWindow.h>
#include <vtkImplicitBoolean.h>
#include <vtkInteractorStyleTrackballCamera.h>
#include <vtkLine.h>
#include <vtkMinimalStandardRandomSequence.h>
#include <vtkNamedColors.h>
#include <vtkObjectFactory.h>
#include <vtkOrientationMarkerWidget.h>
#include <vtkPlane.h>
#include <vtkPolyDataMapper.h>
#include <vtkPolyDataNormals.h>
#include <vtkPropPicker.h>
#include <vtkProperty.h>
#include <vtkRenderWindow.h>
#include <vtkRenderWindowInteractor.h>
#include <vtkRenderer.h>
#include <vtkRendererCollection.h>
#include <vtkReverseSense.h>
#include <vtkSTLReader.h>
#include <vtkSampleFunction.h>
#include <vtkSmartPointer.h>
#include <vtkSphere.h>
#include <vtkTransform.h>
#include <vtkTransformPolyDataFilter.h>

// 主体为长方体,端部两个半圆,半圆的圆心是空洞
decltype(auto) View3D::buildBoard(double r, double g, double b)
{
    // 创建长方体
    vtkNew<vtkCubeSource> cube;
    // 长度1,宽度0.2,厚度0.05
    cube->SetXLength(1);
    cube->SetYLength(0.05);
    cube->SetZLength(0.2);
    cube->Update();

    // 创建半圆
    vtkNew<vtkCylinderSource> cy;
    // 半径0.1,高度0.05,圆心0.5,0,0
    cy->SetRadius(0.1);
    cy->SetHeight(0.05);
    cy->SetCenter(0.5, 0, 0);
    cy->SetResolution(100);
    cy->Update();

    // 创建独立的对称半圆

    vtkNew<vtkCylinderSource> cy1;
    // 半径0.1,高度0.05,圆心-0.5,0,0
    cy1->SetRadius(0.1);
    cy1->SetHeight(0.05);
    cy1->SetResolution(100);
    cy1->SetCenter(-0.5, 0, 0);
    cy1->Update();

    // 小圆柱
    vtkNew<vtkCylinderSource> cy2;
    cy2->SetRadius(0.05);
    cy2->SetHeight(0.06);
    cy2->SetResolution(100);
    cy2->SetCenter(0.5, 0, 0);
    cy2->Update();

    // 小圆柱
    vtkNew<vtkCylinderSource> cy3;
    cy3->SetRadius(0.05);
    cy3->SetHeight(0.06);
    cy3->SetResolution(100);
    cy3->SetCenter(-0.5, 0, 0);
    cy3->Update();

    // 创建长方体和半圆的合体
    vtkNew<vtkAssembly> assembly;
    // cube actor
    vtkNew<vtkPolyDataMapper> cudeMapper;
    cudeMapper->SetInputConnection(cube->GetOutputPort());
    vtkNew<vtkActor> cudeActor;
    cudeActor->SetMapper(cudeMapper);
    cudeActor->GetProperty()->SetColor(r, g, b);
    assembly->AddPart(cudeActor);

    vtkNew<vtkPolyDataMapper> cyMapper;
    cyMapper->SetInputConnection(cy->GetOutputPort());
    vtkNew<vtkActor> cyActor;
    cyActor->SetMapper(cyMapper);
    cyActor->GetProperty()->SetColor(r, g, b);
    assembly->AddPart(cyActor);

    vtkNew<vtkPolyDataMapper> cy1Mapper;
    cy1Mapper->SetInputConnection(cy1->GetOutputPort());
    vtkNew<vtkActor> cy1Actor;
    cy1Actor->SetMapper(cy1Mapper);
    cy1Actor->GetProperty()->SetColor(r, g, b);
    assembly->AddPart(cy1Actor);

    vtkNew<vtkPolyDataMapper> cy2Mapper;
    cy2Mapper->SetInputConnection(cy2->GetOutputPort());
    vtkNew<vtkActor> cy2Actor;
    cy2Actor->SetMapper(cy2Mapper);
    cy2Actor->GetProperty()->SetColor(0.8, 0, 0);
    assembly->AddPart(cy2Actor);

    vtkNew<vtkPolyDataMapper> cy3Mapper;
    cy3Mapper->SetInputConnection(cy3->GetOutputPort());
    vtkNew<vtkActor> cy3Actor;
    cy3Actor->SetMapper(cy3Mapper);
    cy3Actor->GetProperty()->SetColor(0.8, 0, 0);
    assembly->AddPart(cy3Actor);
    return assembly;
}

decltype(auto) View3D::buildConnectRod()
{
    // 淡绿色
    auto actor1 = buildBoard(0.5, 1, 0.5);
    // 淡黄色
    auto actor2 = buildBoard(1, 1, 0.5);
    // 淡蓝色
    auto actor3 = buildBoard(0.5, 1, 1);
    // 平移actor
    actor1->AddPosition(0.5, 0, 0);
    actor2->AddPosition(1.5, 0.05, 0);
    actor3->AddPosition(2.5, 0.1, 0);
    vtkNew<vtkAssembly> assembly1, assembly2, assembly3;
    assembly1->AddPart(actor1);
    assembly1->AddPart(assembly2);
    assembly2->AddPart(actor2);
    assembly2->AddPart(assembly3);
    assembly3->AddPart(actor3);
    assembly2->SetOrigin(1, 0.05, 0);
    assembly3->SetOrigin(2, 0, 0);
    return std::make_tuple(vtkSmartPointer<vtkAssembly>(assembly1),
        vtkSmartPointer<vtkAssembly>(assembly2),
        vtkSmartPointer<vtkAssembly>(assembly3));
}

View3D::View3D(QWidget* parent)
    : QVTKOpenGLNativeWidget(parent)
{
    vtkNew<vtkRenderer> renderer;
    this->renderWindow()->AddRenderer(renderer);
    renderer->AddActor(baseAxes = getBaseAxes());
    addGuideLine(3, 0.2);
    connectRods = buildConnectRod();
    auto&& [actor1, actor2, actor3] = connectRods;
    renderer->AddActor(actor1);

    // 水平旋转
    renderer->GetActiveCamera()->Azimuth(90);
    renderer->GetActiveCamera()->SetRoll(-90);
    renderer->GetActiveCamera()->Azimuth(45);
    renderer->GetActiveCamera()->Elevation(15);
    renderer->GetActiveCamera()->SetPosition(3, 3, 1);

    vtkSmartPointer<vtkOrientationMarkerWidget> widget = vtkSmartPointer<vtkOrientationMarkerWidget>::New();
    ;
    this->borderWidget = widget;
    vtkSmartPointer<vtkAxesActor> widgetAxesActor = vtkSmartPointer<vtkAxesActor>::New();
    widgetAxesActor->SetPosition(0, 0, 0);
    widgetAxesActor->SetShaftType(0);
    widgetAxesActor->SetCylinderRadius(0.02);
    // 设置大小
    widgetAxesActor->SetTotalLength(2, 2, 2);
    widget->SetOrientationMarker(widgetAxesActor);
    widget->SetInteractor(this->interactor());
    widget->SetEnabled(1);
    widget->InteractiveOn();

    // 连接信号槽
    connect(this, &View3D::rotateBased, this, &View3D::rotateBaseSlot);
    connect(this, &View3D::rotateBigArmed, this, &View3D::rotateBigArmSlot);
    connect(this, &View3D::rotateMiddleArmed, this, &View3D::rotateMiddleArmSlot);
    connect(this, &View3D::rotateSmallArmed, this, &View3D::rotateSmallArmSlot);
}

void View3D::addAxis(const Axis& axis)
{
    vtkNew<vtkTransform> transform;
    transform->Translate(axis.xyz.x(), axis.xyz.y(), axis.xyz.z());

    vtkAxesActor* axes = vtkAxesActor::New();
    transform->RotateX(axis.xyzR.x());
    transform->RotateY(axis.xyzR.y());
    transform->RotateZ(axis.xyzR.z());
    axes->SetUserTransform(transform);
    // 设置大小
    axes->SetTotalLength(axis.xyzL.x(), axis.xyzL.y(), axis.xyzL.z());

    // 设置箭头大小
    axes->SetConeRadius(axis.xyzL[0] * 0.1);
    axes->SetCylinderRadius(axis.xyzL[0] * 0.1);
    axes->SetConeResolution(100);
    axes->SetCylinderResolution(100);

    axes->SetXAxisLabelText(axis.labels[0].toStdString().c_str());
    axes->SetYAxisLabelText(axis.labels[1].toStdString().c_str());
    axes->SetZAxisLabelText(axis.labels[2].toStdString().c_str());

    auto xLabelProperty = axes->GetXAxisCaptionActor2D();
    // 缩小
    xLabelProperty->SetWidth(axis.xyzL.x() * 0.1);

    auto yLabelProperty = axes->GetYAxisCaptionActor2D();
    yLabelProperty->SetWidth(axis.xyzL.y() * 0.1);

    auto zLabelProperty = axes->GetZAxisCaptionActor2D();
    zLabelProperty->SetWidth(axis.xyzL.z() * 0.1);

    // 添加到第一个render
    this->renderWindow()->GetRenderers()->GetFirstRenderer()->AddActor(axes);
    this->renderWindow()->Render();
}

void View3D::rotateBaseSlot(double angle)
{
    auto&& [a, b, c] = connectRods;
    // a世界坐标系旋转角归零
    a->SetOrientation(0, 0, 0);
    // a 绕世界坐标系旋转到angle
    a->RotateWXYZ(angle, 0, 0, 1);
    refresh();
}

void View3D::rotateBigArmSlot(double angle)
{
    auto&& [a, b, c] = connectRods;
    a->RotateY(angle - a->GetOrientation()[1]);
    refresh();
}

void View3D::rotateMiddleArmSlot(double angle)
{
    auto&& [a, b, c] = connectRods;
    b->RotateY(angle - b->GetOrientation()[1]);
    refresh();
}

void View3D::rotateSmallArmSlot(double angle)
{
    auto&& [a, b, c] = connectRods;
    c->RotateY(angle - c->GetOrientation()[1]);
    refresh();
}

void View3D::addGuideLine(float r, float space)
{
    // 创建网格线,间距space,范围-r~r
    vtkNew<vtkCellArray> lines;
    vtkNew<vtkPoints> points;
    for (size_t i = 0; i <= static_cast<unsigned long long>(r / space) * 2; i++) {
        points->InsertNextPoint(-r, r - space * i, 0);
        points->InsertNextPoint(r, r - space * i, 0);
        points->InsertNextPoint(-r + space * i, r, 0);
        points->InsertNextPoint(-r + space * i, -r, 0);
    }
    for (size_t i = 0; i <= static_cast<unsigned long long>(r / space) * 4 + 1; i++) {
        vtkNew<vtkLine> line;
        line->GetPointIds()->SetId(0, i * 2);
        line->GetPointIds()->SetId(1, i * 2 + 1);
        lines->InsertNextCell(line);
    }
    vtkNew<vtkPolyData> linesPolyData;
    linesPolyData->SetPoints(points);
    linesPolyData->SetLines(lines);
    vtkNew<vtkPolyDataMapper> mapper;
    mapper->SetInputData(linesPolyData);

    vtkNew<vtkActor> actor;
    actor->SetMapper(mapper);
    // 设置透明度
    actor->GetProperty()->SetOpacity(0.5);
    this->renderWindow()->GetRenderers()->GetFirstRenderer()->AddActor(actor);
    this->renderWindow()->Render();
}

vtkNew<vtkAxesActor> View3D::getBaseAxes()
{
    vtkNew<vtkAxesActor> axes;
    axes->SetTotalLength(1.0, 1.0, 1.0);
    axes->SetPosition(0, 0, 0);
    axes->SetShaftType(0);
    axes->SetConeResolution(100);
    axes->SetCylinderResolution(100);
    axes->SetConeRadius(0.1);
    axes->SetCylinderRadius(0.01);
    return axes;
}

void View3D::refresh()
{
    this->renderWindow()->Render();
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1138865.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

使用内网穿透本地MariaDB数据库,并实现在公网环境下使用navicat图形化工具

公网远程连接MariaDB数据库【cpolar内网穿透】 文章目录 公网远程连接MariaDB数据库【cpolar内网穿透】1. 配置MariaDB数据库1.1 安装MariaDB数据库1.2 测试局域网内远程连接 2. 内网穿透2.1 创建隧道映射2.2 测试随机地址公网远程访问3. 配置固定TCP端口地址3.1 保留一个固定的…

基于单片机的智能电子鼻的设计

欢迎大家点赞、收藏、关注、评论啦 &#xff0c;由于篇幅有限&#xff0c;只展示了部分核心代码。 技术交流认准下方 CSDN 官方提供的联系方式 文章目录 概要 一、智能电子鼻系统的设计方案1.1智能电子鼻系统的设计思路1.2智能电子鼻系统的设计流程图1.3智能电子鼻系统的硬件数…

软考高项-计算题理解

动态回收期主要是看净现值&#xff0c;仔细看&#xff0c;04年投资了925.93 &#xff0c;05,06合计共有825.59&#xff0c;也就是说2年还不能收完&#xff0c;剩余的部分要2年&#xff08;925.93-428.67-396.92&#xff09;2.27&#xff0c;也就是说这道题选C (6-1.1-0.35-0.05…

Jetpack:018-Jetpack中的导航一

文章目录 1. 概念介绍2. 使用方法2.1 基本概念2.2 传统用法2.3 新的用法 3. 示例代码4. 内容总结 我们在上一章回中介绍了Jetpack库中对话框相关的内容&#xff0c;本章回中主要介绍 导航。闲话休提&#xff0c;让我们一起Talk Android Jetpack吧&#xff01; 1. 概念介绍 我…

基于 Redis + Lua 脚本实现分布式锁,确保操作的原子性

1.加锁的Lua脚本&#xff1a; lock.lua --- -1 failed --- 1 success--- getLock key local result redis.call(setnx , KEYS[1] , ARGV[1]) if result 1 then--PEXPIRE:以毫秒的形式指定过期时间redis.call(pexpire , KEYS[1] , 3600000) elseresult -1;-- 如果value相同&…

动态规划(数位统计Dp)

AcWing 338. 计数问题 思路分析&#xff1a; 代码展示&#xff1a; #include <iostream> #include <algorithm> #include <cstring> #include <vector>using namespace std;//10的x次方 int pow10(int x) {int res 1;while(x --) res * 10;retur…

NIO和BIO编程

一、网络通信编程基本常识 1、什么是Socket&#xff1f; Socket是应用层与TCP/IP协议族通信的中间软件抽象层&#xff0c;它是一组接口&#xff0c;一般由操作系统提供。 2、短连接 短连接是指socket建立连接之后传输数据确定接收完后关闭连接 3、长连接 长连接是指建立so…

全新高速HID调试工具

全新高速 HID 调试工具&#xff0c;程序袁USB开发利器 支持一下特性&#xff1a; 支持高速USB自适应HID报告长度自动定时发送内置CRC小工具自定义显示 高速USB HID调试工具下载

Pytorch - 数据增广

增加一个已有数据集&#xff0c;使得有更多的多样性 在语言里面加入各种不同的背景噪音改变图片的颜色和形状 翻转 左右翻转上下翻转 但是并不总是可行的。 切割 从图片中切割一块&#xff0c;然后变形到固定形状 随机高宽比随机大小随机位置 颜色 改变色调、饱和度、明…

HackTheBox-Starting Point--Tier 0---Preignition

文章目录 一 题目二 实验过程 一 题目 Tags Web、Custom Applications、Apache、Reconnaissance、Web Site Structure Discovery、Default Credentials译文&#xff1a;Web、定制应用程序、Apache、侦察、网站结构发现、默认凭证Connect To attack the target machine, you …

【软件教程】如何用C++检查TCP或UDP端口是否被占用

一、检查步骤 使用socket函数创建socket_fd套接字。使用sockaddr_in结构体配置协议和端口号。使用bind函数尝试与端口进行绑定&#xff0c;成功返回0表示未被占用&#xff0c;失败返回-1表示已被占用。 二、CODE 其中port需要修改为想要检测的端口号&#xff0c;也可以将代码…

eslint提示 xxx should be listed in the project's dependencies

有时候手动安装了一个npm包A&#xff0c;npm包A里面包含了npm包B&#xff0c;这时候如果 import xxx from npm包B;eslint会报错&#xff0c;提示 npm包B 不在 package.json 里面 解决方法&#xff1a;在 eslintrc.js 增加配置 module.exports {rules: {import/no-extraneous-d…

Linux常见问题解决操作(yum被占用、lsb无此命令、Linux开机进入命令界面等)

Linux常见问题解决操作&#xff08;yum被占用、lsb无此命令、Linux开机进入命令界面等&#xff09; 问题一、新安装的Linux使用命令lsb_release提示无此命令&#xff0c;需先安装再使用 Linux安装lsb命令 lsb是Linux Standard Base的缩写&#xff08;Linux基本标准&#xff…

springboot的缓存和redis缓存,入门级别教程

一、springboot&#xff08;如果没有配置&#xff09;默认使用的是jvm缓存 1、Spring框架支持向应用程序透明地添加缓存。抽象的核心是将缓存应用于方法&#xff0c;从而根据缓存中可用的信息减少执行次数。缓存逻辑是透明地应用的&#xff0c;对调用者没有任何干扰。只要使用…

cocosCreator 之localStorage本地存储和封装拓展

版本&#xff1a; 3.8.0 语言&#xff1a; TypeScript 环境&#xff1a; Mac 简介 在cocosCreator中&#xff0c;针对于本地存储主要使用localStorage接口&#xff0c;通过key-value的格式进行存储和读取数据。 主要接口有&#xff1a; 接口描述setItem(key, value)保存指定…

Spring Security —漏洞防护—跨站请求伪造(CSRF)

在终端用户可以 登录 的应用程序中&#xff0c;必须考虑如何防止 跨站请求伪造&#xff08;CSRF&#xff09;。 Spring Security 默认为 不安全的HTTP方法&#xff08;如POST请求&#xff09;提供CSRF攻击防护&#xff0c;因此无需额外代码。你可以使用下面的方法明确指定默认…

今年天猫双11,打响电商AI时代第一枪

自阿里提出双11以来&#xff0c;今年已是第15个年头。在这15年间&#xff0c;双11见证了中国电商的发展轨迹&#xff0c;从野蛮生长、完善体验到重质重效。如今&#xff0c;在双11的见证下&#xff0c;中国电商的进化正悄然发生。 一些新的变化值得关注。“最值得买的电视”&a…

系列六、FactoryBean vs ApplicationContext

一、FactoryBean vs ApplicationContext 1.1、概述 BeanFactory是一个工厂类&#xff0c;负责生产和管理bean&#xff0c;在Spring中BeanFactory是IOC容器的核心接口&#xff0c;它的主要职责就是生产bean及建立各个bean之间的依赖。applicationContext是BeanFactory的一个子接…

Go 的连接池、重试和超时

这是一个来自 API 的间歇性 500 个内部服务器错误的故事&#xff0c;这些错误最终是由 Go 包中的硬编码常量引起的database/sql。我将主要为您省去冗长的故事&#xff0c;并直接讨论问题以及我们发现的原因。我们注意到来自特定 API 端点的 500 错误数量有所增加&#xff0c;并…

网络协议--BOOTP:引导程序协议

16.1 引言 在第5章我们介绍了一个无盘系统&#xff0c;它在不知道自身IP地址的情况下&#xff0c;在进行系统引导时能够通过RARP来获取它的IP地址。然而使用RARP有两个问题&#xff1a;&#xff08;1&#xff09;IP地址是返回的唯一结果&#xff1b;&#xff08;2&#xff09;…