There are three adjustment stages of the cone in our test.
P_1: rotate the cone and make it bigger.
P_2: translate the cone after P_1
P_3: translate the cone from the original position.

    \[P_1 = M_1 A\]

    \[P_2 = M_2 M_1 A\]

    \[P_3 = M_2 M_1 M_1^{-1} A = M_2 A\]

Original Scene

Create an initial scene like the following image.

The red lines are drawn in the back renderer, they display grid coordinates in the world coordinate system.
I make the back renderer not interactive and under the other renderer that shows cone.

Code snippet:

#define vtkSPtr vtkSmartPointer
#define vtkSPtrNew(Var, Type) vtkSPtr<Type> Var = vtkSPtr<Type>::New();

using namespace std;

int main()
{
    double zoomFactor = 0.3;
    vtkSPtrNew( cone, vtkConeSource );
    vtkSPtrNew( mapper, vtkPolyDataMapper );
    mapper->SetInputConnection( cone->GetOutputPort() );

    vtkSPtrNew( actor, vtkActor );
    actor->SetMapper( mapper );

    vtkSPtrNew( renderer, vtkRenderer );
    renderer->AddActor(actor);
    renderer->SetBackground( 0, 0, 0 );
    renderer->GetActiveCamera()->ParallelProjectionOn();
    renderer->GetActiveCamera()->Zoom( zoomFactor );
    renderer->SetLayer( 1 );

    vtkSPtrNew( backRenderer, vtkRenderer );
    backRenderer->SetBackground( 0, 0, 0 );
    backRenderer->SetInteractive( 0 );
    backRenderer->GetActiveCamera()->ParallelProjectionOn();
    backRenderer->GetActiveCamera()->Zoom( zoomFactor );
    backRenderer->SetLayer( 0 );

    vtkSPtrNew( renderWindow, vtkRenderWindow );
    renderWindow->SetNumberOfLayers( 2 );
    renderWindow->AddRenderer( backRenderer );
    renderWindow->AddRenderer( renderer );
    renderWindow->SetSize( 100, 100 );

    // ------------- add lmm lines -----------------
    vtkSPtrNew( v1mmMapper, vtkPolyDataMapper );
    vtkSPtrNew( v1mmPolyData, vtkPolyData );
    vtkSPtrNew( v1mmLines, vtkCellArray );
    vtkSPtrNew( v1mmPoints, vtkPoints );

    v1mmPolyData->SetPoints( v1mmPoints );
    v1mmPolyData->SetLines( v1mmLines );
    v1mmMapper->SetInputData( v1mmPolyData );

    vtkSPtrNew( v1mmLinesActor, vtkActor );
    v1mmLinesActor->SetMapper( v1mmMapper );
    v1mmLinesActor->GetProperty()->SetColor( 1, 0, 0 );
    v1mmLinesActor->GetProperty()->SetLineWidth( 1 );
    v1mmLinesActor->DragableOff();
    v1mmLinesActor->PickableOff();

    backRenderer->AddActor( v1mmLinesActor );

    //--------------------start generate lines------------------
    double mmSize = 1;
    v1mmPoints->Initialize();
    v1mmLines->Initialize();
    double width = renderWindow->GetScreenSize()[0]; //GetActualSize()[0];
    double height = renderWindow->GetScreenSize()[1];
    printf("w: %lf, h: %lf\n", width, height);

    double x, y;
    //--------------------vertical lines------------------
    for ( x = -width / 2; x <= width / 2; x += mmSize )
    {
        double linePoint1[3] = { x, -height/2, 0.0 };
        double linePoint2[3] = { x, height/2, 0.0 };
        vtkIdType pointId1 = v1mmPoints->InsertNextPoint(linePoint1);
        vtkIdType pointId2 = v1mmPoints->InsertNextPoint(linePoint2);
        vtkIdType lineIds[2] = { pointId1, pointId2 };
        v1mmLines->InsertNextCell(2, lineIds);
    }
    //--------------------horizontal lines----------------
    for ( y = -height/2; y <= height/2; y += mmSize )
    {
        double linePoint1[3] = { -width/2, y, 0.0 };
        double linePoint2[3] = { width/2, y, 0.0 };
        vtkIdType pointId1 = v1mmPoints->InsertNextPoint(linePoint1);
        vtkIdType pointId2 = v1mmPoints->InsertNextPoint(linePoint2);
        vtkIdType lineIds[2] = { pointId1, pointId2 };
        v1mmLines->InsertNextCell(2, lineIds);
    }

    v1mmPolyData->Modified();
    //-------------------- end ------------------

    // ------------- finished: 1mm lines -----------

    vtkSPtrNew( renderWindowInteractor, vtkRenderWindowInteractor );
    renderWindowInteractor->SetRenderWindow( renderWindow );

    renderWindow->Render();
    renderWindowInteractor->Start();
    return 0;
}

Stage 1: Rotate And Scale

Rotate the cone and make it twice as big, we get the following result.

Code snippet:

void ConvertToStage1( vtkActor *actor )
{
    vtkSPtrNew( trans, vtkTransform );
    trans->RotateZ( 30 );
    trans->Scale( 2, 2, 2 );
    trans->Update();

    actor->SetUserTransform( trans );
};

Stage 2: Translate After Rotating And Scaling

Then I moved it to position (2, 2, 0) after stage 1.

void ConvertToStage2( vtkActor *actor )
{
    vtkSPtrNew( trans, vtkTransform );
    trans->Translate( 2, 2, 0 );
    trans->Update();
    if( actor->GetUserTransform() )
    {
        trans->Concatenate( actor->GetUserTransform() );
        trans->Update();
    }

    actor->SetUserTransform( trans );
};

Stage 3: Only Translate

Now let’s move the cone without rotating and scaling it.
It’s very simple to do it by removing the statement that using function ConvertToStage1.

    //ConvertToStage1( actor );
    ConvertToStage2( actor );

But there is another way to implement it.

    ConvertToStage1( actor );
    vtkSPtrNew( trans1, vtkTransform );
    trans1->DeepCopy( actor->GetUserTransform() );

    ConvertToStage2( actor );
    vtkSPtrNew( trans2, vtkTransform );
    trans2->DeepCopy( actor->GetUserTransform() );

    trans1->Inverse();
    trans1->Update();
    trans2->Concatenate( trans1 );
    trans2->Update();
    actor->SetUserTransform( trans2 );

We must make trans2 Concatenate trans1 Because vtkTransform object has the default setting PreMultiply.
The new matrix computed by the above code snippet is equal to P_3 in the following math expression.

    \[P_1 = M_1 A\]

    \[P_2 = M_2 M_1 A\]

    \[P_3 = M_2 M_1 M_1^{-1} A = M_2 A\]

All code is uploaded to GitHub: Remove Pre Change

Categories: VTK

0 0 vote
Article Rating
Subscribe
Notify of
guest
0 Comments
Inline Feedbacks
View all comments
A prohibited operation
0
Would love your thoughts, please comment.x
()
x