效果
关键代码
#include "View3D.h"
#include "Axis.h"
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
decltype(auto) View3D::buildBoard(double r, double g, double b)
{
vtkNew<vtkCubeSource> cube;
cube->SetXLength(1);
cube->SetYLength(0.05);
cube->SetZLength(0.2);
cube->Update();
vtkNew<vtkCylinderSource> cy;
cy->SetRadius(0.1);
cy->SetHeight(0.05);
cy->SetCenter(0.5, 0, 0);
cy->SetResolution(100);
cy->Update();
vtkNew<vtkCylinderSource> cy1;
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;
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);
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);
this->renderWindow()->GetRenderers()->GetFirstRenderer()->AddActor(axes);
this->renderWindow()->Render();
}
void View3D::rotateBaseSlot(double angle)
{
auto&& [a, b, c] = connectRods;
a->SetOrientation(0, 0, 0);
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)
{
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();
}