Loading...

1024Dong

2021/12/26  阅读：34  主题：默认主题

# VTK-DisplayToWorld坐标系转换

## 从Display坐标系点转世界坐标系点

``int eventDisplayPosition[3]{0};this->Interactor->GetEventPosition(eventDisplayPosition);this->Renderer->SetDisplayPoint((double)eventDisplayPosition[0], (double)eventDisplayPosition[1], (double)eventDisplayPosition[2]);this->Renderer->DisplayToWorld();double  eventWorldPoint[4];this->Renderer->GetWorldPoint(eventWorldPoint);``

## DisplayToWorld的源码实现

``/**   * Convert display (or screen) coordinates to world coordinates.   */  void DisplayToWorld()  {    this->DisplayToView();    this->ViewToWorld();  }``

## DisplayToView

``// Convert display coordinates to view coordinates.void vtkViewport::DisplayToView(){  if (this->VTKWindow)  {    double vx, vy, vz;    int sizex, sizey;    /* get physical window dimensions */    const int* size = this->VTKWindow->GetSize();    if (size == nullptr)    {      return;    }    sizex = size[0];    sizey = size[1];    vx = 0.0;    if (sizex != 0.0)    {      vx = 2.0 * (this->DisplayPoint[0] - sizex * this->Viewport[0]) /          (sizex * (this->Viewport[2] - this->Viewport[0])) -        1.0;    }    vy = 0.0;    if (sizey != 0.0)    {      vy = 2.0 * (this->DisplayPoint[1] - sizey * this->Viewport[1]) /          (sizey * (this->Viewport[3] - this->Viewport[1])) -        1.0;    }    vz = this->DisplayPoint[2];    this->SetViewPoint(vx, vy, vz);  }}``
• 其中Viewport[4] = {Xmin,Ymin,Xmax,Ymax}，DispayPoint[3]{x,y,0}

### 我计算vx的伪代码如下：

``view_x_Len= this->Viewport[2] - this->Viewport[0]// view 坐标系的x轴长度view_normal_x = 1/view_x_len;//sizex window坐标系x轴长度window_normal_x = 1/sizex;vx = this->DisplayPoint[0]*window_normal_x*view_normal_x-this->Viewport[0]*view_normal_x;//也就是vx = (this->DisplayPoint[0] - sizex * this->Viewport[0]) /          (sizex * (this->Viewport[2] - this->Viewport[0]))``

### 可是实际答案如下，这是为甚么呢？

``vx = 2.0 * (this->DisplayPoint[0] - sizex * this->Viewport[0]) /          (sizex * (this->Viewport[2] - this->Viewport[0])) -        1.0;``

## 带着问题接着探索

### vtkCoordinate and Coordinate Systems

The Visualization Toolkit supports several different coordinate systems, and the class vtkCoordinate

manages transformations between them. The supported coordinate systems are as follows.

• DISPLAY — x-y pixel values in the (rendering) window. (Note that vtkRenderWindow is a

subclass of vtkWindow). The origin is the lower-left corner (which is true for all 2D coordinate

systems described below).

• NORMALIZED DISPLAY — x-y (0,1) normalized values in the window.

• VIEWPORT — x-y pixel values in the viewport (or renderer — a subclass of vtkViewport)

• NORMALIZED VIEWPORT — x-y (0,1) normalized values in viewport

• VIEW — x-y-z (-1,1) values in camera coordinates (z is depth)

• WORLD — x-y-z global coordinate value

• USERDEFINED - x-y-z in user-defined space. The user must provide a transformation method

for user defined coordinate systems. See vtkCoordinate for more information.

The class vtkCoordinate can be used to transform between coordinate systems and can be linked

together to form “relative” or “offset” coordinate values. Refer to the next section for an example of

using vtkCoordinate in an application

## 从以上信息我们得出结论坐标系的表示方式不同导致的计算结果和想象的不一样，如下图

``vx = 2.0 * (this->DisplayPoint[0] - sizex * this->Viewport[0]) /          (sizex * (this->Viewport[2] - this->Viewport[0])) -        1.0;``

## ViewToWorld实现

``// Convert view point coordinates to world coordinates.void vtkRenderer::ViewToWorld(){  double result[4];  result[0] = this->ViewPoint[0];  result[1] = this->ViewPoint[1];  result[2] = this->ViewPoint[2];  result[3] = 1.0;  this->ViewToWorld(result[0],result[1],result[2]);  this->SetWorldPoint(result);}``

### 获取投影矩阵逆矩阵，把view 坐标系的点转换到世界坐标系

``void vtkRenderer::ViewToWorld(double &x, double &y, double &z){  double mat[16];  double result[4];  if (this->ActiveCamera == nullptr)  {    vtkErrorMacro("ViewToWorld: no active camera, cannot compute view to world, returning 0,0,0");    x = y = z = 0.0;    return;  }  // get the perspective transformation from the active camera  vtkMatrix4x4 *matrix = this->ActiveCamera->                GetCompositeProjectionTransformMatrix(                  this->GetTiledAspectRatio(),0,1);  // use the inverse matrix  vtkMatrix4x4::Invert(*matrix->Element, mat);  // Transform point to world coordinates  result[0] = x;  result[1] = y;  result[2] = z;  result[3] = 1.0;  vtkMatrix4x4::MultiplyPoint(mat,result,result);  // Get the transformed vector & set WorldPoint  // while we are at it try to keep w at one  if (result[3])  {    x = result[0] / result[3];    y = result[1] / result[3];    z = result[2] / result[3];  }}``

1024Dong

2021/12/26  阅读：34  主题：默认主题