Hi Peter,
I'm going crazy with a very odd behavior while zooming in/out and using aggregated data.
Since I have too many points to plot, I have 3 versions of the data: the first with all the
points, the second with a tenth
of the points and the third with a hundredth of the points.
The array size that I display is always the same size, 10,000 samples, but depending on
the zoom value I take those 10,000 samples from one of the 3 versions of the data.
Obviously, when I change from one
data set to another, I set the x-axis full range again and I set the viewportWidth and
viewPortLeft to appropriate values.
For reference, every sample represents 1 millimeter (you will see the plot in meters).
It works well for the most part. HOWEVER, I noticed a very odd and reproducible behavior
a couple days ago:
If I zoom in with the mouse in a position to the right of the screen, then the data is
shown shifted in the y-axis. It's hard to explain, so I attached a word document with
pictures.
The code is as follows:
BOOL CZoomscrolltrackDlg::OnMouseWheel(UINT nFlags, short zDelta, CPoint pt) //
nothing fancy here, taken straight out of an example
{
// Process the mouse wheel only if the mouse is over the plot area
if (!m_ChartViewer.isMouseOnPlotArea())
return FALSE;
// We zoom in or out by 10% depending on the mouse wheel direction.
double newVpWidth = m_ChartViewer.getViewPortWidth() * (zDelta > 0 ? 0.9 : 1 /
0.9);
double newVpHeight = m_ChartViewer.getViewPortHeight() * (zDelta > 0 ? 0.9 : 1 /
0.9);
// We do not zoom beyond the zoom width or height limits.
double maxHeight = m_ChartViewer.getZoomOutHeightLimit();
double minHeight = m_ChartViewer.getZoomInHeightLimit();
double maxWidth = m_ChartViewer.getZoomOutWidthLimit();
double minWidth = m_ChartViewer.getZoomInWidthLimit();
newVpWidth = max(m_ChartViewer.getZoomInWidthLimit(), min(newVpWidth,
m_ChartViewer.getZoomOutWidthLimit()));
newVpHeight = max(m_ChartViewer.getZoomInHeightLimit(), min(newVpHeight,
m_ChartViewer.getZoomOutHeightLimit()));
if ((newVpWidth != m_ChartViewer.getViewPortWidth()) ||
(newVpHeight != m_ChartViewer.getViewPortHeight()))
{
// Set the view port position and size so that the point under the mouse remains
under
// the mouse after zooming.
double deltaX = (m_ChartViewer.getPlotAreaMouseX() -
m_ChartViewer.getPlotAreaLeft()) * (m_ChartViewer.getViewPortWidth() - newVpWidth)
/ m_ChartViewer.getPlotAreaWidth();
m_ChartViewer.setViewPortLeft(m_ChartViewer.getViewPortLeft() + deltaX);
m_ChartViewer.setViewPortWidth(newVpWidth);
double deltaY = (m_ChartViewer.getPlotAreaMouseY() -
m_ChartViewer.getPlotAreaTop()) * (m_ChartViewer.getViewPortHeight() - newVpHeight)
/ m_ChartViewer.getPlotAreaHeight();
m_ChartViewer.setViewPortTop(m_ChartViewer.getViewPortTop() + deltaY);
m_ChartViewer.setViewPortHeight(newVpHeight);
m_ChartViewer.updateViewPort(true, true);
}
return TRUE;
}
void CZoomscrolltrackDlg::OnViewPortChanged()
{
// Update the chart if necessary
//if (m_ChartViewer.needUpdateChart())
drawChart(&m_ChartViewer);
}
void CZoomscrolltrackDlg::drawChart(CChartViewer *viewer)
{
XYChart *c = new XYChart(kPlotWidth, kPlotHeight, 0xffffff, 0xaaaaaa);
// Set the plotaarea
c->setSize(kPlotWidth, kPlotHeight);
c->setPlotArea(kPlotOriginX, kPlotOriginY, kPlotWidth-kPlotMargin, kPlotHeight-
kPlotMargin, c->linearGradientColor(0, 55, 0, c->getHeight() - 35, 0xf0f6ff, 0xa0c0ff), -1,
Chart::Transparent,
Chart::Transparent,Chart::Transparent); //0xffffff, 0xffffff);
// As the data can lie outside the plotarea in a zoomed chart, we need enable
clipping.
c->setClipping();
// Set legend icon style to use line style icon, sized for 8pt font
c->getLegend()->setLineStyleKey();
c->getLegend()->setFontSize(8);
// Set the axis stem to transparent
c->xAxis()->setColors(Chart::Transparent); //, Chart::Transparent,
Chart::Transparent, Chart::Transparent);
c->yAxis()->setColors(Chart::Transparent); //,Chart::Transparent,
Chart::Transparent, Chart::Transparent);
c->setBackground(0x99CCFF);
// Add axis title using 10pts Arial Bold Italic font
c->yAxis()->setTitle("Channel", "arialbi.ttf", 10);
///////////////////////////////////////////////////////////////////////////////////////
// Add data to chart
///////////////////////////////////////////////////////////////////////////////////////
// Add a line layer for the channels
LineLayer *chLayer = c->addLineLayer();
chLayer->setLineWidth(1);
chLayer->setFastLineMode();
// Get the start index and end index that are visible on the chart.
double mmStart = viewer->getValueAtViewPort("x", viewer->getViewPortLeft());
double mmEnd = viewer->getValueAtViewPort("x", viewer->getViewPortLeft() +
viewer->getViewPortWidth());
// Get the start channel and end channel that are visible on the chart.
m_chEnd = (int)floor(m_databaseManager.getNumChannels() - viewer-
>getValueAtViewPort("y", viewer->getViewPortTop()) );
m_chStart = (int)ceil (m_databaseManager.getNumChannels() - viewer-
>getValueAtViewPort("y", viewer->getViewPortTop() + viewer->getViewPortHeight()) );
// Now we add the data series to the layer.
m_channelManager.addDataSets(chLayer, mmStart, mmEnd, m_chStart, m_chEnd,
viewer->needUpdateImageMap());
///////////////////////////////////////////////////////////////////////////////////////
// Configure axis scale and labelling
///////////////////////////////////////////////////////////////////////////////////////
// set data xAxis full range (according to the loaded data chunk) (the Y axis full
range is always all the channels
double minX = m_channelManager.getXAxisStart();
double maxX = m_channelManager.getXAxisEnd();
viewer->setFullRange("x", minX, maxX);
// set the viewPortWidth and viewPortLeft
double viewPortPercent = (mmEnd-mmStart) / (maxX-minX);
viewer->setViewPortWidth(viewPortPercent);
viewer->setViewPortLeft( (mmStart-minX) / (maxX-minX) );
// Set the x-axis as numeric axis with the scale according to the view port x range.
viewer->syncLinearAxisWithViewPort("x", c->xAxis());
viewer->syncLinearAxisWithViewPort("y", c->yAxis());
// Configure the x-axis depending on the zoom value to show mm, m, or km
c->xAxis()->setFormatCondition("align", 500000);
c->xAxis()->setLabelFormat("{={value}/1000000} km");
c->xAxis()->setFormatCondition("align", 1);
c->xAxis()->setLabelFormat("{={value}/1000} m");
///////////////////////////////////////////////////////////////////////////////////////
// Output the chart
///////////////////////////////////////////////////////////////////////////////////////
delete viewer->getChart();
viewer->setChart(c);
}
Any ideas??
|