ASE Home Page Products Download Purchase Support About ASE
ChartDirector Support
Forum HomeForum Home   SearchSearch

Message ListMessage List     Post MessagePost Message

  Odd behaviour with zoom and aggregated data
Posted by Mauricio on Sep-22-2012 07:51
Attachments:
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??
Odd behavior with zoom and aggregated data.zip
Odd behavior with zoom and aggregated data.zip

234.67 Kb

  Re: Odd behaviour with zoom and aggregated data
Posted by Mauricio on Sep-22-2012 10:13
Never mind. I found the issue... shame on me... it was a problem with integer arithmetic vs
floating point arithmetic while calculating the indexes to get the data.