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


 


1 Comment

To Rotate A Cone When The Rotating Center Is Not Its Center – theArcticOcean · 2019年9月3日 at pm8:48

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

Leave a Reply

Your email address will not be published. Required fields are marked *

You cannot copy content of this page