Hi All,
I am implementing a custom circle-shaped cursor using SVG and CSS. The radius of the circle should be calculated dynamically based on a given size in world coordinates (eg. 1mm). It should be calculated in place where I have rendered imageslice actor. Is it possible to calculate radius in pixels having information from:
imageSlice and imageMapper
renderWindow and renderer (activeCamera).
I was trying to use view.worldToDisplay(x,y,z,renderer) by
picking two points from the imageslice plane distant of 1mm from each other in World Coords,
by transforming these points to display coords and calculating distance between them,
but it did not work precisely.
Instead of using WorldToDisplay, the information can be extracted from the camera:
// Given a specific world point, return the scale factor
// from display coords to world coords at that point.
double DisplayToWorldScale(const double position[3], vtkRenderer *renderer)
{
// Start by computing the height of the window at the cursor position.
double worldHeight;
vtkCamera* camera = renderer->GetActiveCamera();
if (camera->GetParallelProjection())
{
worldHeight = 2*camera->GetParallelScale();
}
else
{
vtkMatrix4x4* matrix = camera->GetViewTransformMatrix();
// Get a 3x3 matrix with the camera orientation
double cvz[3];
cvz[0] = matrix->GetElement(2, 0);
cvz[1] = matrix->GetElement(2, 1);
cvz[2] = matrix->GetElement(2, 2);
double cameraPosition[3];
camera->GetPosition(cameraPosition);
double v[3];
v[0] = cameraPosition[0] - position[0];
v[1] = cameraPosition[1] - position[1];
v[2] = cameraPosition[2] - position[2];
worldHeight = 2*(vtkMath::Dot(v,cvz)
* tan(0.5*camera->GetViewAngle()/57.296));
}
// Compare world height to window height.
int windowHeight = renderer->GetSize()[1];
double scale = 1.0;
if (windowHeight > 0)
{
scale = worldHeight/windowHeight;
}
return scale;
}
Of course you can probably find ways to simplify my old code above, for example by calling GetDirectionOfProjection() instead pulling the camera’s Z vector from the view transform matrix…
Hi David,
Thank you very much for reply. I will try to implement your approach in vtk js (I forgot to mention about javascript;-), but as far as I remember vtk.js API, it should be doable.
I am using MANDATORY Parallel Projection, so in my case it is as simple as that:
function displayToWorldScale (renderer)
{ let camera = renderer.getActiveCamera();
let scale = 1.0;
let windowHeight = renderer.getRenderWindow().getViews()[0].getSize()[1];
let worldHeight = 2*camera.getParallelScale();
if (windowHeight > 0)
{
scale = worldHeight/windowHeight;
}
return scale;
};