|
How to Set the Same X and Y Grid Scale on a Chart? |
Posted by Fabio on Jan-12-2016 03:21 |
|
Hello,
I have a Qt 5.5 project with ChartDirector 6.0 that has a chart dialog, which is a mix of the examples xyzoomscroll and realtimezoomscroll. The dialog displays real-time line charts (as the one in realtimezoomscroll) and real-time scatter charts (as the one in xyzoomscroll).
So far, I have the attached real-time xyzoomscroll-like chart. As seen, the X and Y grids are not square nor do they have the same scale, in this case for example both X and Y 10 cm. How can I accomplish this? And my second question is about the view port control mini chart. The user can zoom in/out drawing any area (rectangular or squared) on the mini chart, but we need to limit that to a square only. How can I accomplish this as well?
Thanks in advance,
Fabio
|
Re: How to Set the Same X and Y Grid Scale on a Chart? |
Posted by Peter Kwan on Jan-13-2016 02:13 |
|
Hi Fabio,
If you know the x-axis and y-axis scale and the plot area width and height, you can
configure it using Axis.setLinearScale so that the grid lines from squares. For example:
//assuming the plot area width is the same as its height, the following grid lines
//will geometrically form squares.
c->xAxis()->setLinearScale(0, 100, 10, 5);
c->yAxis()->setLinearScale(-30, 70, 10, 5);
For zooming in/out, there are several methods. For example:
(a) You can completely disable user from "dragging" a rectangle for zooming. The user
can still use the mouse wheel for zooming. You can also add a "zoom slider" in the user
interface for zooming. It would be similar to zooming in Google Map. To disable
dragging a rectangle zooming, on the main chart itself, you can set the mouse usage to
"drag to scroll". In the mini chart, you can use setDragBorderToResize and
setDragOutsideToSelect to disable "drag to zoom". In this case, dragging the mini chart
will move the viewport window rather than resizing it.
(b) You can let user drag a rectangle for zooming in the mini chart, but in the
"onViewPortChanged" handler, before it does anything, it first adjusts the viewport
position and size so that it is a square. In the simplest implementation, the following
code can ensure the viewport is a square:
//Set the width equals to the height before further processing
m_ChartViewer->setViewPortWidth(m_ChartViewer->getViewPortHeight());
However, in practice, the code may be more complicated. For example, if the user is
dragging on the top-left corner, you may need to adjust the viewport left and top so that
the bottom-right corner is not moved (if you just set the width and height to be the
same, it is possible the bottom-right corner may move when the user drags the top-left
corner, which is counter-intuitive.) Instead of setting the width equals the height, you
can need to set the height equals the width in some cases, etc.. So for your case, you
probably need to develop the code further, but the important point is that the viewport
can be adjusted in the onViewPortChanged event so that it is a square.
Regards
Peter Kwan |
Re: How to Set the Same X and Y Grid Scale on a Chart? |
Posted by Fabio on Jan-13-2016 08:58 |
|
Hi Peter,
Thanks for your opportune support.
Regarding my first issue about square grid lines with the same scale, the premise is that the plot area width and height be the same. Since the dialog is resizable, I enforce a square plot area; and then, I set the grid lines square:
int square = ((xyChart->getWidth()-120) < (xyChart->getHeight()-100)) ?
(xyChart->getWidth()-120) : (xyChart->getHeight()-100);
xyChart->setPlotArea(50, 60,
square, square, // Square plot area
-1, -1, -1,
ChartDialog::Silver, ChartDialog::Silver)->
set4QBgColor(ChartDialog::GrayLight, ChartDialog::GrayDark,
ChartDialog::GrayLight, ChartDialog::GrayDark,
ChartDialog::Black);
// Set grid lines to geometrically form squares
xyChart->xAxis()->setLinearScale(0, 100, 10, 5);
xyChart->yAxis()->setLinearScale(-30, 70, 10, 5);
However, the chart continues behaving as before. The grid behavior we are looking for is a square with the same scale as shown in the attached image.
Regarding my second issue about "dragging" a rectangle for zooming in the mini chart, I decided to disable "drag to zoom" in the mini chart as:
// Disable "drag to zoom" in mini chart
viewPort->setDragBorderToResize(false);
viewPort->setDragOutsideToSelect(false);
Thus resolving my second issue.
Again, my first issue is outstanding.
Thanks in advance,
Fabio
|
Re: How to Set the Same X and Y Grid Scale on a Chart? |
Posted by Peter Kwan on Jan-14-2016 02:34 |
|
Hi Fabio,
I have attached a modified XY Zooming and Scrolling sample code for your reference, To
try it, simply copy it to the qtdemo\\xyzoomscroll sample code subdirectory to replace the
existing file there. Then you can compile and run the sample as usual.
For the code suggested in my last message, it is used to illustrate that if the plot area is
1:1 (a square), and the full axis range is also 1:1, and the viewport is also 1:1, then the
resulting axis scale should be 1:1.
The axis scale used in the code in my last message is 0 to 100 for the x-axis, and -30 to
70 for the y-axis, which is 1:1 (both axes are 100 units in length). If used in the
xyzoomscroll sample code, the full range is taken as the initial axis scale, and it will be
1:1 too. The viewport is initially 1:1 in the sample code, and would stay as 1:1 if you do
not allow the user to drag a rectangle for zooming.
In your real code, the code structure would probably be somewhat different. For example,
the full range may be is configured using other methods. What is important is that your
code would need to ensure the full range is always 1:1 (that is, the length of the full x
range is the same as that of the full y range), and that the viewport is always 1:1 (if the
viewport is initially 1:1, and the user is using the mouse wheel or the "zoom bar" for
zooming, it should stay as 1:1).
If the above still cannot solve the problem, is it possible to modify the sample code to
reproduce the problem. This would help me to diagnose the problem.
Regards
Peter Kwan
|
Re: How to Set the Same X and Y Grid Scale on a Chart? |
Posted by Fabio on Jan-14-2016 04:36 |
|
Hi Peter,
My code was not enforcing the chart viewer's full ranges X and Y to 1:1. I added some logic to calculate and enforce the same ranges for X and Y as follows:
// Find minimum and maximum view port values
double xMinValue = (minLonDeltas < 0.0) ? minLonDeltas * 1.1 :
minLonDeltas * 0.9;
double xMaxValue = (maxLonDeltas < 0.0) ? maxLonDeltas * 0.9 :
maxLonDeltas * 1.1;
double yMinValue = (minLatDeltas < 0.0) ? minLatDeltas * 1.1 :
minLatDeltas * 0.9;
double yMaxValue = (maxLatDeltas < 0.0) ? maxLatDeltas * 0.9 :
maxLatDeltas * 1.1;
// Adjust minimum range to make it equal to maximum range
double xRange = xMaxValue - xMinValue;
double yRange = yMaxValue - yMinValue;
if (xRange < yRange) {
xMinValue -= (yRange - xRange) / 2;
xMaxValue += (yRange - xRange) / 2;
} else { // yRange <= xRange
yMinValue -= (xRange - yRange) / 2;
yMaxValue += (xRange - yRange) / 2;
}
chartViewer->updateFullRangeH("x", xMinValue, xMaxValue,
Chart::ScrollWithMax);
chartViewer->updateFullRangeV("y", yMinValue, yMaxValue,
Chart::ScrollWithMax);
This finally resolved fully my issue.
I greatly appreciate your support,
Fabio |
|