Using the coordinate systems in SpatialDataView

This documentation will explain how the coordinate systems work in SpatialDataView.

There are three coordinate systems that are important to SpatialDataView:

The screen coordinate system is made up of Qt coordinates which is based on the location relative to the view widget. The place of origin for the screen coordinates is in the upper-left corner.

qt_screen_coordinate_system.JPG

Screen coordinate system

World coordinates on the other hand, use the OpenGL coordinate system which is the linear coordinate system used to draw the data. The world coordinate system is typically the same coordinate system as the data itself. Unlike the screen coordinate system, the world coordinate system origin is in the lower-left corner.

openGL_world_coordinate_system.JPG

World coordinate system

The data coordinate system is the coordinate system used in the layers inside a SpatialDataView. Each layer contains its own data coordinate system. Because of this, each layer can have an offset and scale factor based off the primary raster element pixel coordinates. The data coordinate system place of origin is the upper-left corner by default, but it can be changed to the lower-left corner by the user. When using the View::setDataOrigin() function, please keep in mind that it will not take into account of the type of coordinate system being used. View::setDataOrigin() will only effect data coordinates.

layer_data_coordinate_system.JPG

Each of these layers has a separate data coordinate system.

The functions to convert coordinates from one system to another include:

The View::translateWorldToScreen() function converts a world coordinate to a screen coordinate while the View::translateScreenToWorld() function will do the opposite. When using the View::translateScreenToWorld() function, make sure that the screen y-coordinate parameter is correct or it may return a bad result. To get the correct screen y-coordinate, subtract the mouse y-coordinate from the view height.

Here's an example on getting the correct y-coordinate:

 dScreenY = pViewWidget.height() - pMouseEvent.pos().y() 

Please note that each layer may have different data coordinates so if you convert a world/screen coordinate to a data coordinate in two different layers, we can expect it will have two different values.

The following example shows how to translate from a screen coordinate to a data coordinate:

bool CustomWidget::eventfilter(QObject* pObj, QEvent* pEvent)
{
   SpatialDataView* pView = dynamic_cast<SpatialDataView*>(pObj);
   if (pEvent->type() == QEvent::MouseButtonPress)
   {
      QMouseEvent* pMouseEvent = static_cast<QMouseEvent*>(pEvent);
      const QPoint& ptMouse = pMouseEvent->pos();

      LayerList* pLayerList = pView->getLayerList();
      if (pLayerList != NULL)
      {
         RasterElement* pRaster = pLayerList->getPrimaryRasterElement();
         if (pRaster != NULL)
         {
            const RasterDataDescriptor* pDescriptor =
               dynamic_cast<const RasterDataDescriptor*>(pRaster->getDataDescriptor());
            if (pDescriptor != NULL)
            {  
               RasterLayer* pRasterLayer = dynamic_cast<RasterLayer*>(pLayerList->getLayer(RASTER, pRaster));
               if (pRasterLayer != NULL)
               {
                  LocationType dataCoord;                 
                  pRasterLayer->translateScreenToData(ptMouse.x(), pView->getWidget()->height() - ptMouse.y(), dataCoord.mX, dataCoord.mY);
                  if (dataCoord.mY >= 0 && dataCoord.mY < pDescriptor->getRows().size() && dataCoord.mX >= 0 && dataCoord.mX < pDescriptor->getColumns().size())
                  {                     
                     ComplexComponent eComponent = pRasterLayer->getComplexComponent();
                     
                     double dValue = pRaster->getPixelValue(pDescriptor->getActiveColumn(dataCoord.mX),
                        pDescriptor->getActiveRow(dataCoord.mY), pDescriptor->getActiveBand(0), eComponent);
                        
                     QMessageBox::information(pView->getWidget(), "Display Pixel Value",
                        "The pixel value is " + QString::number(dValue));
                  }
               }
            }
         }
      }

   }
   return QObject::eventFilter(pObject, pEvent);
}

Other functions that might be helpful to data coordinates as well as other coordinates systems are View::getPixelSize() and PerspectiveView::getPixelAspect(). The View::getPixelSize() function returns the number of screen pixels between two world coordinates and the PerspectiveView::getPixelAspect() gets the view ratio of x compared to y. Since the x pixel ratio between two coordinates can be incorrect in a SpatialDataView, we'll calculate the correct x ratio by multiplying the world x coordinates by the aspect ratio of the pixel.

Here's an example on how these functions might work:

    double pixelSize = pPerspectiveView->getPixelSize(llCorner, urCorner);
    double pixelSizeX = pixelSize * pPerspectiveView->getPixelAspect();
    double pixelSizeY = pixelSize;

Software Development Kit - Opticks 4.9.0 Build 16218