We want to know the world coordinate of a point on a 3D widget event though we don’t know the widget’s position on the world coordinate system. I get a matrix from an actor and create a temporal vtkTransform object, then the function TransformDoublePoint can give me the real coordinate value of a single point on the 3D model. This is my solution for calculating real coordinate. It’s possible to get an inverse transform if we know coordinates of a point, the direction of the X-axis and the direction of the Y-axis of the 3D model. That means we have a second way to calculate the point’s position. For example, we have point (p0, p1, p2), vector (x0, x1, x2) and vector (y0, y1, y2). The third vector (z0, z1, z2) is the cross product result of vector1 and vector2.

For vtkTransform::Concatenate: In homogeneous matrix notation, M = M*A where M is the current transformation matrix and A is the applied matrix. The default is PreMultiply.

The local matrix can give us information about the coordinate system transform. Let’s read an example.

Before rotating plane:

#include <iostream>
#include <vtkSmartPointer.h>
#include <vtkSphereSource.h>
#include <vtkActor.h>
#include <vtkConeSource.h>
#include <vtkRenderer.h>
#include <vtkRenderWindow.h>
#include <vtkPolyDataMapper.h>
#include <vtkProperty.h>
#include <vtkRenderWindowInteractor.h>
#include <vtkLight.h>
#include <vtkCamera.h>
#include <vtkActor2D.h>
#include <vtkTransform.h>
#include <vtkLinearTransform.h>
#include <vtkPlaneSource.h>

#include "tool.h"

using namespace std;

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

vtkSmartPointer<vtkTransform> CreateLocalTrans(PointStruct origin, PointStruct xDir, PointStruct yDir)
{
    vtkSPtrNew( resultTrans, vtkTransform );
    PointStruct zDir = xDir ^ yDir;
    zDir.Unit();

    double elements1[16] = { xDir[0], xDir[1], xDir[2], 0,
                            yDir[0], yDir[1], yDir[2], 0,
                            zDir[0], zDir[1], zDir[2], 0,
                            0, 0, 0, 1 };

    resultTrans->Concatenate(elements1);     //rotation

    double elements2[16] = { 1, 0, 0, -origin[0],
                             0, 1, 0, -origin[1],
                             0, 0, 1, -origin[2],
                             0, 0, 0, 1 };

    resultTrans->Concatenate(elements2);    //translation
    resultTrans->Update();

    return resultTrans;
}

int main()
{
    setbuf( stdout, nullptr );

    // ============ plane start ================
    vtkSmartPointer<vtkPlaneSource> planeSource =
            vtkSmartPointer<vtkPlaneSource>::New();
    planeSource->SetOrigin( 0, 0, 0 ); //Relative
    planeSource->SetPoint1( 0, 2, 0 );
    planeSource->SetPoint2( 2, 0, 0 );

    vtkSmartPointer<vtkPolyDataMapper> planeMapper =
            vtkSmartPointer<vtkPolyDataMapper>::New();
    planeMapper->SetInputConnection( planeSource->GetOutputPort() );

    vtkSmartPointer<vtkActor> planeActor =
            vtkSmartPointer<vtkActor>::New();
    planeActor->SetMapper( planeMapper );
    //planeActor->SetPosition( 1, 1, 0 );
    // ============ plane end ================

    // ============ sphere start ================
    vtkSmartPointer<vtkSphereSource> sphereSource =
            vtkSmartPointer<vtkSphereSource>::New();
    sphereSource->SetCenter( 2, 2, 0 );
    sphereSource->SetRadius( 0.1 );

    vtkSmartPointer<vtkPolyDataMapper> sphereMapper =
            vtkSmartPointer<vtkPolyDataMapper>::New();
    sphereMapper->SetInputConnection( sphereSource->GetOutputPort() );

    vtkSmartPointer<vtkActor> sphereActor =
            vtkSmartPointer<vtkActor>::New();
    sphereActor->SetMapper( sphereMapper );
    sphereActor->GetProperty()->SetColor( 1, 0, 0 );
    // ============ plane end ================

    // Change actor status.
    planeActor->RotateY( 90 );

    // The first way
    vtkSmartPointer<vtkTransform> transform = vtkSmartPointer<vtkTransform>::New();
    transform->SetMatrix( planeActor->GetMatrix() );
    double pt1[3] = { 2, 2, 0 };
    double pt2[3] = { 1, 0, 0 };
    double *pt3 = transform->TransformDoublePoint( pt1 );
    printf( "(%lf, %lf, %lf)\n", pt3[0], pt3[1], pt3[2] );
    // (0.000000, 2.000000, -2.000000)

    // The second way
    PointStruct HomePt( 0, 0, 0 );
    PointStruct xPt( 0, 0, -1 );
    PointStruct yPt( 0, 1, 0 );
    vtkSmartPointer<vtkTransform> localTransform = CreateLocalTransform( HomePt, xPt, yPt );
    localTransform->Inverse();  // inverse get matrix's transform
    pt3 = localTransform->TransformDoublePoint( pt2 );
    printf( "(%lf, %lf, %lf)\n", pt3[0], pt3[1], pt3[2] );

    // localTransform
    // x: (0.000000, 0.000000, 1.000000)
    // y: (0.000000, 1.000000, 0.000000)
    // z: (-1.000000, 0.000000, 0.000000)

    // localTransform Inverse
    // x: (0.000000, 0.000000, -1.000000)
    // y: (0.000000, 1.000000, 0.000000)
    // z: (1.000000, 0.000000, 0.000000)

    vtkSmartPointer<vtkRenderer> renderer =
            vtkSmartPointer<vtkRenderer>::New();
    renderer->AddActor( planeActor );
    renderer->AddActor( sphereActor );
    renderer->SetBackground( 0, 0, 0 );

    vtkSmartPointer<vtkRenderWindow> renderWindow =
            vtkSmartPointer<vtkRenderWindow>::New();
    renderWindow->AddRenderer( renderer );

    vtkSmartPointer<vtkRenderWindowInteractor> renderWindowInteractor =
            vtkSmartPointer<vtkRenderWindowInteractor>::New();
    renderWindowInteractor->SetRenderWindow( renderWindow );

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

After rotating plane:


2 Comments

【VTK】Local To World Coordinate Transform – theArcticOcean · 2019年7月7日 at am7:56

[…] and at least two axis vectors to construct the transform. The example is similar to the article LOCAL COORDINATE SYSTEM […]

VTK - Local To World Coordinate Transform - theArcticOcean · 2019年7月20日 at pm6:16

[…] write an article about how to create a local coordinate system for a dependent 3d model, LOCAL COORDINATE SYSTEM We can get real value in the world coordinate system of vector or point on the 3D model. For […]

Leave a Reply

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

You cannot copy content of this page