There are three adjustment stages of the cone in our test.
: rotate the cone and make it bigger.
: translate the cone after
: translate the cone from the original position.
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 in the following math expression.
All code is uploaded to GitHub: Remove Pre Change