|
MFC DrawXY Realtime chart using V6 Library + Zoom feature |
Posted by Sal on May-21-2015 01:27 |
|
Hello Peter,
I studied your V6 XyZoomScrollDlg.cpp code, and adapted to produce a dialog similar yours with the following differences:
1: Data is loaded not in OnInitDialog, statically as in your sample code
2: Each data sample I received is composed of different sections
3: The User can select which subset section of the whole data set to observe
4: Each data set has different Graph Limits that must be considered
5: Each set must be displayed in a XY chart Graph (by Selecting one of them).
6: The set might requires inversion of axis as been displayed,
so that is why the code uses the "setReverse()" of both axis when needed
7: The user data XY is not in synch with what is plotted in XY
Any new User "Set Selection", calls the drawFullChartMethod(), prior calling drawChart()
At the arrival of new data for the same selection the drawChart() is called to update the graph with the new data.
The results I Observe, are telling me the following:
1: The Aux. View shows correctly the area I Zoomed in a rectangle as expected
2: For my testing that area shows also the points subset I care to observe as zoomed
3: The above view handles correctly the use of "setReverse()" in all cases
4: Data points are drawn as in the Main Graph Area View as expected
5: In the above View, the Axis orientation is also as expected in all cases
6: Assume no Zoom is active, as new Data Set selection are triggered, data graph in both controls properly shown and orienting the axis the data been displayed.
THE PROBLEM:
When I zoom on the Graph View that was produced by using the "setReverse()" method, the Main Graph shows a grid which granularity has expanded in size in X,Y as expected, but the axis limits and the graph overall, show an area of the original view that is not in synch with what the Aux. View shows
It is like the graph was shifted in the main View by shifting the Origin of what I want to see in the opposite direction of what was intended
--------------
These are portions of the 2 Functions mentioned previously, to keep this posting short
--------------
drawFullChart()
{
RECT r;
pViewPortControl->GetWindowRect(&r);
int iDrawingWidth = r.right-r.left;
int iDrawingHeight = r.bottom-r.top;
// Create a XYChart object
XYChart *c = new XYChart(iDrawingWidth - 5, iDrawingHeight - 5, Chart::brushedSilverColor(), 0x888888);
// Fill the whole Plot area with Laminated Silver looking Brush, no grid lines
int iX = 2;
int iY = 3;
PlotArea* pPlotArea = c->setPlotArea(iX, iY, c->getWidth() - 1 - (iX*2), c->getHeight() -1 - (iY*2),
-1, -1, -1, Chart::Transparent, Chart::Transparent);
// Enable clipping mode to clip the part of the data that is outside the plot area.
c->setClipping();
// Set Grid Background Area only to "wheat1" (solid color, a sort of light yellow)
pPlotArea->setBackground(0xFFE7BA);
// Define Color of Lines in Grid (Major: Black, Minor: Light Gray)
pPlotArea->setGridColor(0, 0, 0xc0c0c0, 0xc0c0c0);
Axis* pAxisX = c->xAxis();
Axis* pAxisY = c->yAxis();
// Set the axes line width in pixels
pAxisX->setWidth(2);
pAxisY->setWidth(2);
// Load the View Limits imposed by device
GetViewedLimit(iSelection, &dLimits);
pAxisX->setLinearScale(dLimits.dMinY, dLimits.dMaxY, (dLimits.dMaxY-dLimits.dMinY)/2, 2500);
pAxisY->setLinearScale(dLimits.dMinX, dLimits.dMaxX, 5000, 2500);
// Since we selected a new device, assign boundary
pViewer->setFullRange("x", dLimits.dMinY, dLimits.dMaxY);
pViewer->setFullRange("y", dLimits.dMinX, dLimits.dMaxX);
// Show all the Points reported by device as Red Dots (if data is present)
if (nPoints)
{
c->addScatterLayer(DoubleArray(DataX, nPoints), DoubleArray(DataY,
Points),
"", Chart::CircleSymbol, 1, 0xff0000, 0xff0000);
}
// Since view looks the same without any data point from the heads been displayed,
// add a point to display, so I can orient my-self
double dX = dLimits.dMinY;
double dY = dLimits.dMinX;
// Plot the smallest X,Y values in the axis, that will appear as a Red Dot (Used for Debugging)
// Because of the Clipping, we see only 1/4 of the Dot (a sort of small filled triangle in Red)
c->addScatterLayer(DoubleArray(&dX, 1), DoubleArray(&dY, 1),
"", Chart::CircleSymbol, 7, 0xff0000, 0xff0000);
// Flip orientation if needed to stay in sinch with the reporting device
if (bFlipBothAxis)
{
pAxisY->setReverse();
pAxisX->setReverse();
}
// Set the chart image to the WinChartViewer
pViewPortControl->setChart(c); // Output the chart
}
drawChart()
{
RECT r;
pViewer->GetWindowRect(&r);
int iDrawingWidth = r.right-r.left;
int iDrawingHeight = r.bottom-r.top;
// Create a XYChart object
XYChart *c = new XYChart(iDrawingWidth, iDrawingHeight, Chart::brushedSilverColor(), 0x888888);
// Shift graph away from the margins of the windows (all 4)
// Make room at the top to put a Colored Header that will contain what I am observing
int iLeftMargin = 45;
int iRightMargin = 67;
int iTopmargin = 55;
int iBottomMargin = 80;
// Fill the whole Plot area with Laminated Silver looking Brush
// Turn on both horizontal and vertical grid lines with light grey color (0xc0c0c0)
PlotArea* pPlotArea = c->setPlotArea(iLeftMargin, iTopmargin, iDrawingWidth - iRightMargin, iDrawingHeight - iBottomMargin, -1, -1, 0xc0c0c0, 0xc0c0c0, -1);
// Set Grid Background Area only to "wheat1" (solid color, a sort of light yellow)
pPlotArea->setBackground(0xFFE7BA);
c->setClipping();
// Define Color of Lines in Grid (Major: Black, Minor: Light Gray)
pPlotArea->setGridColor(0, 0, 0xc0c0c0, 0xc0c0c0);
// Add a title to the chart using 18 pts Times Bold Itatic font.
// This will appear above the chart, as inside a sort of colored box
CString sz;
sz.Format("Device: %d", iSelection);
TextBox* pTextBox = c->addTitle(sz.GetBuffer(), "timesbi.ttf", 15);
// Add a top title to the chart with a light blue (ccccff) background,
// black (000000) border, and a cylinder surface like raised effect.
pTextBox->setBackground(0xccccff, 0x0, Chart::cylinderEffect());
// Add a legend box area at top of the chart with horizontal layout. Use 12
// pts Times Bold Italic font. Set the background and border color to Transparent.
c->addLegend(iLeftMargin - 13, iTopmargin - 33, false, "timesbi.ttf", 12)->setBackground(Chart::Transparent);
Axis* pAxisX = c->xAxis();
Axis* pAxisY = c->yAxis();
// Add a title to the y axis using 12 pts Arial Bold Italic font
pAxisY->setTitle("X", "arialbi.ttf", 12);
// Add a title to the x axis using 12 pts Arial Bold Italic font
pAxisX->setTitle("Y", "arialbi.ttf", 12);
// Set the axes line width in pixels
pAxisX->setWidth(2);
pAxisY->setWidth(2);
// Flip interpretation of axis since needed
pAxisX->setLinearScale(dLimits.dMinY, dLimits.dMaxY, (dLimits.dMaxY-dLimits.dMinY)/2, 1000);
pAxisY->setLinearScale(dLimits.dMinX, dLimits.dMaxX, 5000, 2500);
-----------------
MISSING Section Not Critical ro Important
-----------------
// Show all the Points as Red Dots if data has arrived
if (nPoints)
c->addScatterLayer(DoubleArray(DataX, nPoints), DoubleArray(DataY, nPoints),
s, Chart::CircleSymbol, iDotSize, 0xff0000, 0xff0000);
// Required to have the View to show the selected part into the Zoomed Control View:
// Compute the visible data scale based on the viewport coordinates using linear interpolation,
// and then sets the axis to that linear scale
pViewer->syncLinearAxisWithViewPort("x", pAxisX);
pViewer->syncLinearAxisWithViewPort("y", pAxisY);
// Flip orientation if needed
if (bFlipBothAxis)
{
pAxisY->setReverse();
pAxisX->setReverse();
}
// Set the chart image to the WinChartViewer
delete pViewer->getChart();
pViewer->setChart(c); // Output the chart
}
----------------
Peter,
Any Idea of what is wrong in the above code ?
Any clarifications of Library API operation due to my miss-understanding are appreciated
Thanks for any Help
Sal |
Re: MFC DrawXY Realtime chart using V6 Library + Zoom feature |
Posted by Sal on May-21-2015 02:24 |
|
Peter,
I should have included my Sample code in the previous message as an attachment
I hope the following screen shots illustrate the issue in full clarity
Thanks
Sal |
Re: MFC DrawXY Realtime chart using V6 Library + Zoom feature |
Posted by Sal on May-21-2015 02:41 |
|
Sorry,
Forgot to attach files
|
Re: MFC DrawXY Realtime chart using V6 Library + Zoom feature |
Posted by Peter Kwan on May-21-2015 03:52 |
|
Hi Sal,
There issue is in these two lines:
// Since we selected a new device, assign boundary
pViewer->setFullRange("x", dLimits.dMinY, dLimits.dMaxY);
pViewer->setFullRange("y", dLimits.dMinX, dLimits.dMaxX);
If the axis is reversed, it should be:
pViewer->setFullRange("x", dLimits.dMaxY, dLimits.dMinY);
pViewer->setFullRange("y", dLimits.dMaxX, dLimits.dMinX);
Basically, the full range determines the range of the viewport. When you select from the
viewport, the CChartViewer will determine the axis range based on the full range, which is
not inverted in your code. So when the user selects near the top of the chart, the
CChartViewer believes the user must have selected somewhere near dMaxX, so it
determines the axis scale should be something like 31000 to 33000.
But then the chart is configured to reverse the axis, so it plots 31000 on the top and 33000
at the bottom. This is the behaviour you have encountered. To the solve issue, the full
range should be configured as reverse if the axis is reversed.
Hope this can help.
Regards
Peter Kwan |
Re: MFC DrawXY Realtime chart using V6 Library + Zoom feature |
Posted by Sal on May-21-2015 04:09 |
|
Peter,
It worked as you described it.
Thanks
Sal |
|