效果
关键代码
# 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;
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 ( ) ;
}