A few macros we need in our project are in the following code snippet. They can make our project cleaner.
#define vtkPtr( var, className ) vtkSmartPointer<className> var = \
vtkSmartPointer<className>::New()
#define CPP_SET_MACRO(name,type) \
void Set##name(type _arg) \
{ \
if (this->name != _arg) \
{ \
this->name = _arg; \
} \
}
To show all 3D objects which includes cone, ring, and axis, we just need these logics.
The axis is just for users to observe whether the cone is rotated.
int main()
{
setbuf( stdout, nullptr );
vtkPtr( cone, vtkConeSource );
vtkPtr( coneMapper, vtkPolyDataMapper );
coneMapper->SetInputConnection( cone->GetOutputPort() );
vtkPtr( coneActor, vtkActor );
coneActor->SetMapper( coneMapper );
vtkPtr( renderer, vtkRenderer );
renderer->SetBackground( 0, 0, 0 );
vtkPtr( renderWindow, vtkRenderWindow );
renderWindow->AddRenderer( renderer );
vtkPtr( renderWindowInteractor, vtkRenderWindowInteractor );
renderWindowInteractor->SetRenderWindow( renderWindow );
vtkPtr( axes, vtkAxesActor );
axes->SetTotalLength( 1, 1, 1 ); // change length of three axis
vtkPtr( cellPicker, vtkCellPicker );
vtkPtr(parametricTorus, vtkParametricTorus);
parametricTorus->SetRingRadius(1);
parametricTorus->SetCrossSectionRadius(0.1);
vtkPtr(parametricFunctionSource, vtkParametricFunctionSource);
parametricFunctionSource->SetParametricFunction(parametricTorus);
parametricFunctionSource->Update();
vtkPtr( parametricMapper, vtkPolyDataMapper );
parametricMapper->SetInputData( parametricFunctionSource->GetOutput() );
vtkPtr( zRingActor, vtkActor );
zRingActor->SetMapper( parametricMapper );
zRingActor->GetProperty()->SetOpacity( 0.5 );
renderer->AddActor( zRingActor );
renderer->AddActor( axes );
renderer->AddActor( coneActor );
cellPicker->AddPickList( zRingActor );
cellPicker->PickFromListOn();
renderer->ResetCamera();
renderWindow->Render();
renderWindowInteractor->Start();
return 0;
}
Let’s make the center cone rotating as mouse moving on a ring.
We need to define our subclass of vtkInteractorStyle to archive customized interactor event.
The subclass of vtkCommand can also be used to listen for interaction event, but it can be suited here because we want to keep the camera static while we are rotating center cone.
The rotating function is in the following section. The complete example is out in Github, https://github.com/theArcticOcean/CLib/tree/master/AxisActor
void vtkCustomStyle::RotateOnZRing(int *lastPos, int *pos)
{
vtkPtr( transform, vtkTransform );
transform->SetMatrix( m_ConeActor->GetMatrix() );
PointStruct ZAxis( transform->TransformDoubleVector( 0, 0, 1 ) );
PointStruct origin( m_ConeActor->GetCenter() ); //( transform->TransformDoublePoint( 0, 0, 0 ) );
m_Render->SetWorldPoint( origin.point );
m_Render->WorldToDisplay();
PointStruct originDisplay( m_Render->GetDisplayPoint() );
PointStruct lastPosStruct( lastPos[0], lastPos[1], 0 );
PointStruct posStruct( pos[0], pos[1], 0 );
PointStruct vec1 = lastPosStruct - originDisplay;
PointStruct vec2 = posStruct - originDisplay;
PointStruct crossPt = vec1 ^ vec2;
double radianDelta = vtkMath::AngleBetweenVectors( vec1.point, vec2.point );
double degreeDelta = 180.0 / vtkMath::Pi() * radianDelta;
cout << "RotateOnZRing degreeDelta: " << degreeDelta << endl;
PointStruct viewDirection = GetViewDirect();
double radianDeltaBetweenViewAndZAixs =
vtkMath::AngleBetweenVectors( ZAxis.point, viewDirection.point );
double degreeDeltaBetweenViewAndZAixs =
180.0 / vtkMath::Pi() * radianDeltaBetweenViewAndZAixs;
cout << "degreeDeltaBetweenViewAndZAixs: " << fabs( degreeDeltaBetweenViewAndZAixs ) << endl;
// Rotating axis
if( crossPt[2] < 0 )
{
degreeDelta = -degreeDelta;
}
// View direct vector is in different direct comparing with rotating axis
if( degreeDeltaBetweenViewAndZAixs > 90 )
{
degreeDelta = -degreeDelta;
}
//m_ConeActor->RotateWXYZ( degreeDelta, crossPt.point[0], crossPt.point[1], crossPt.point[2] );
transform->SetMatrix( m_ZRingActor->GetMatrix() );
PointStruct rotateAxis( transform->TransformDoubleVector( 0, 0, 1 ) );
m_ConeActor->RotateZ( degreeDelta );
cout << "Changing, degreeDelta: " << degreeDelta << ", " << rotateAxis;
}
[…] two rotating vectors, the details can be found in my previous article [VTK Rotate Cone With Ring](https://www.weiy.city/2019/08/vtk-rotate-cone-with-ring/) , so skip it and go ahead. To rotate the cone with the rotating center is its center is easy for […]