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;
}


 


0 0 vote
Article Rating
Subscribe
Notify of
guest
1 Comment
Oldest
Newest Most Voted
Inline Feedbacks
View all comments
trackback

[…] 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 […]

A prohibited operation
1
0
Would love your thoughts, please comment.x
()
x