SetUserMatrix vs using vtkTransformPolyDataFilter

Can anyone explain me what’s the difference between transforming actor when using this two different approach ?

The first one is using the vtkTransformPolyDataFilter on the 3D object PolyData.

The second one is calling to SetUserMatrix on the vtkActor.

The problem is that I am getting wrong bounding box when calling GetBounds on the vtkActor when using the SetUserMatrix function.

In this image you can see 2 different vtkActor’s , both of them transformed to the correct location(same transformation matrix), but the GetBounds using the SetUserMatrix are wrong .

Why the function called UserMatrix ?

Thanks !

This method modifies the underlying coordinates of the vtkPoints before rendering. When you call actor->GetBounds(), it returns the bounds of these transformed coordinates.

This method applies transformation matrix in the GPU during rendering. The coordinates of vtkPoints are not transformed.

1 Like

Thanks for the explanation, so from this we can’t understand why GetBounds returns a different result, sounds like a bug ?

Note : the wrong bounds are not the bounds before transform the object from 0,0,0 (green circle in the image ) the wrong bounds are actually transformed and rotate but in wrong scale .

Does sound like a bug. But I’m unsure if it actually is. Maybe a new method called GetDataBounds() is needed?

1 Like

@cory.quammen

1 Like

I just edited my answer :

“Note : the wrong bounds are not the bounds before transform the object from 0,0,0 (green circle in the image ) the wrong bounds are actually translated and rotated but with wrong scale .”

Trying to workaround, getting the bbox after setusermatrix without get bounds, by using the transformation matrix multiply by points(min,max) got from getbounds after reading the ply file ,before setting user matrix.

nothing works

Why matrix × point is not working ?

@jaswantp

It is not clear to me what you’re trying to achieve. GetBounds always returns the bounding box of the actual geometry. Not the transformed actor’s bounds.

@jaswantp

Take the min,max (2 3D points) of the object before applying transformation.

Apply the transformation on all poly data (3D Object)
Apply the transformation on this 2 points and draw bounding box using this 2 transformed points.

You can see that the bounding box after transforming the two points is wrong.

The UserMatrix is applied in model-space. This may be different from the world-space in which vtkTransformPolyDataFilter operates. Can you try using actor->GetMatrix() to transform the original min and max?

For now I am trying to do the same only in world space with the filter, not using UserMatrix.

Look I also tried this approach , same results, wrong coordinates after calculating rotation for 2 circle blue points :

    vtkMatrix4x4*  transformMatrix = loadWorkVolumeTransform(transformFilePath);



    vtkNew<vtkConeSource> vtkConeSource;
    vtkConeSource->SetRadius(0.6);
    vtkConeSource->SetCenter(0, 0, 0);
    vtkConeSource->Update();


    double originalBounds[6] = { 0 };
    vtkConeSource->GetOutput()->GetBounds(originalBounds);



    vtkNew<vtkTransform> transform3D;
    transform3D->SetMatrix(transformMatrix);
    transform3D->Update();


    vtkNew <vtkTransformPolyDataFilter> transformFilter3D;
    transformFilter3D->SetInputData(vtkConeSource->GetOutput());
    transformFilter3D->SetTransform(transform3D);
    transformFilter3D->Update();

    appender_result->AddInputConnection(transformFilter3D->GetOutputPort());
    appender_result->Update();


    double originalMin[3] = { originalBounds[0],originalBounds[2],originalBounds[4]};
    double originalMax[3] = { originalBounds[1],originalBounds[3],originalBounds[5]};

    double center[3] = { originalMin[0]+(originalMax[0] - originalMin[0]) / 2,originalMin[1]+(originalMax[1] - originalMin[1])/2,originalMin[2]+(originalMax[2] - originalMin[2])/2 };


    vtkSmartPointer<vtkPoints> boundsPoints = vtkSmartPointer<vtkPoints>::New();
    vtkSmartPointer<vtkPolyData> boundsPolydata = vtkSmartPointer<vtkPolyData>::New();
    boundsPoints->InsertNextPoint(originalMin);
    boundsPoints->InsertNextPoint(originalMax);
    boundsPolydata->SetPoints(boundsPoints);

    vtkNew<vtkTransform> transform;
    transform->SetMatrix(transformMatrix);
    transform->Update();



    vtkTransformPolyDataFilter* transformFilter = vtkTransformPolyDataFilter::New();
    transformFilter->SetInputData(boundsPolydata);
    transformFilter->SetTransform(transform);
    transformFilter->Update();

    double transformedMin[3];
    transformFilter->GetOutput()->GetPoint(0, transformedMin);

    double transformedMax[3];
    transformFilter->GetOutput()->GetPoint(1, transformedMax);



    drawCircle1(transformedMin, color_blue);
    drawCircle1(transformedMax, color_blue);

    vtkSmartPointer<vtkPolyDataMapper> polyDataMapper_result = vtkSmartPointer<vtkPolyDataMapper>::New();
    vtkSmartPointer<vtkActor> actor_result = vtkSmartPointer<vtkActor>::New();
    actor_result->SetMapper(polyDataMapper_result);

    polyDataMapper_result->SetInputData(appender_result->GetOutput());

    drawBoundingBox(actor_result->GetBounds());
    vtkRendered->AddActor(actor_result);

Same result @jaswantp

vtkMatrix4x4*  transformMatrix = loadWorkVolumeTransform(transformFilePath);



vtkNew<vtkConeSource> vtkConeSource;
vtkConeSource->SetRadius(0.6);
vtkConeSource->SetCenter(0, 0, 0);
vtkConeSource->Update();


double originalBounds[6] = { 0 };
vtkConeSource->GetOutput()->GetBounds(originalBounds);



vtkNew<vtkTransform> transform3D;
transform3D->SetMatrix(transformMatrix);
transform3D->Update();


vtkNew <vtkTransformPolyDataFilter> transformFilter3D;
transformFilter3D->SetInputData(vtkConeSource->GetOutput());
transformFilter3D->SetTransform(transform3D);
transformFilter3D->Update();

appender_result->AddInputConnection(transformFilter3D->GetOutputPort());
appender_result->Update();


double originalMin[3] = { originalBounds[0],originalBounds[2],originalBounds[4]};
double originalMax[3] = { originalBounds[1],originalBounds[3],originalBounds[5]};
double center[3] = { originalMin[0]+(originalMax[0] - originalMin[0]) / 2,originalMin[1]+(originalMax[1] - originalMin[1])/2,originalMin[2]+(originalMax[2] - originalMin[2])/2 };


double* transformedMin = transform3D->TransformDoublePoint(originalMin);
double transformedMinNew[3] = { 0 };
std::memcpy(transformedMinNew, transformedMin, sizeof(double) * 3);



double* transformedMax = transform3D->TransformDoublePoint(originalMax);


drawCircle1(transformedMinNew, color_blue);
drawCircle1(transformedMax, color_blue);

vtkSmartPointer<vtkPolyDataMapper> polyDataMapper_result = vtkSmartPointer<vtkPolyDataMapper>::New();
vtkSmartPointer<vtkActor> actor_result = vtkSmartPointer<vtkActor>::New();
actor_result->SetMapper(polyDataMapper_result);

polyDataMapper_result->SetInputData(appender_result->GetOutput());

drawBoundingBox(actor_result->GetBounds());
vtkRendered->AddActor(actor_result);

@jaswantp GOT IT! the orintation of the boundingbox is NOT THE SAME after rotation, I need to figure out how to calculate it correctly .

Here is image before and after rotation 30 DEG around the Z axis !

I guess, I have to rotate all the corners and to find new min,max of the bbox (: