There are methods to retrieve the screen position from a given Chart position, i.e. Chart::getXCoor, Chart::getYCoor, or Axis::getCoor. However, there does not seem to be any method that does the reverse thing, i.e. transform a given screen position to the corresponding Chart position (after the Chart has been layouted, of course). As a workaround, I currently use getXCoor, getYCoor and binary search (see below). This works, but I wonder if there is any better way to do this.
BOOL ChartViewer::relPosToXYChartPos (int nRelPosX, int nRelPosY,
double &dChartPosX, double &dChartPosY, KisDevice &ks)
{
if (m_pXYChart != NULL)
{
Axis *pXAxis = m_pXYChart->xAxis();
Axis *pYAxis = m_pXYChart->yAxis();
if (pXAxis != NULL && pYAxis != NULL)
{
double dX1 = pXAxis->getMinValue();
double dX2 = pXAxis->getMaxValue();
if (m_pXYChart->getXCoor (dX1) > m_pXYChart->getXCoor (dX2))
{
// X-Axis is oriented right to left.
double dTmp = dX1;
dX1 = dX2;
dX2 = dTmp;
}
double dY1 = pYAxis->getMinValue();
double dY2 = pYAxis->getMaxValue();
if (m_pXYChart->getYCoor (dY1) > m_pXYChart->getYCoor (dY2))
{
// Y-Axis is oriented bottom to top.
double dTmp = dY1;
dY1 = dY2;
dY2 = dTmp;
}
int nPixelX = ks.lmToTm (nRelPosX);
int nPixelY = ks.lmToTm (nRelPosY);
int nToGo = 20; // max number of iterations
int nTryX, nTryY;
while (nToGo > 0)
{
dChartPosX = (dX1 + dX2) * 0.5;
dChartPosY = (dY1 + dY2) * 0.5;
nTryX = m_pXYChart->getXCoor (dChartPosX);
nTryY = m_pXYChart->getYCoor (dChartPosY);
if (nTryX == nPixelX && nTryY == nPixelY) break;
if (nTryX < nPixelX) dX1 = dChartPosX; else dX2 = dChartPosX;
if (nTryY < nPixelY) dY1 = dChartPosY; else dY2 = dChartPosY;
nToGo--;
}
return TRUE;
}
}
return FALSE;
} |