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

Message ListMessage List     Post MessagePost Message

  Keep pixel ratio for x and y axis
Posted by Davide on Apr-10-2018 17:42
Attachments:
Hi,

I'm having some problems.
On my chart x and y axis represent metres. Now what I want to do is to keep the pixel ratio between the two axis. For example if 10 metres on the x axis are 100 pixels, also 10 metres on the y axis must be 100 pixels. I also need to keep this ratio while resizing the chart.

Does somebody have a solution for this?

Thanks in advance!
Pixel.PNG

  Re: Keep pixel ratio for x and y axis
Posted by Peter Kwan on Apr-11-2018 03:56
Hi Davide,

By "resizing", I assume you mean the chart can zoom in and out.

For your case, first, you need to create a chart with 1:1 aspect ratio. Then when the user zooms in and out, you need to keep the aspect ratio at 1:1. The exact details depend on your programming language and framework. For example, the details for a web application is different from using C++/MFC or .NET C#/WPF.

In brief, to create a chart with 1:1 aspect ratio, you may:

(a) Specify the axis scale with your own code using Axis.setLinearScale. You can specify the scales so that they are 1:1. If you are using zooming and scrolling, you may set the full range (using setFullRange) so that the axis scale is 1:1.

(b) If you want ChartDirector to auto-scale the chart, ChartDirector will auto-scale based on the data, and it the scale may not be 1:1.  you may create a dummy chart with all the data and call XYChart.layoutAxes. You can then use Axis.getMinValue and Axis.getMaxValue to get the x and y scales. You can then extend the shorter scale to make the two scales 1:1. Then in your real chart, you can use the method in (a) to apply those scales.

When zooming in and out, in the viewport changed event handler, you can adjust the viewport width and height so that they are the same. In this way, the aspect ratio will stays at 1:1 after zooming in and out.

If you need further details, please let me know what is your programming language, whether it is a web or desktop application, and the GUI framework used.

Regards
Peter Kwan

  Re: Keep pixel ratio for x and y axis
Posted by davide on Apr-11-2018 14:58
Thank you Peter for the answer.

I'm sorry, I had to give you more info.
I'm developing with c++ in Qt and for "resize" I don't mean zoom in and out, but, as maybe you can see from the pic, I have a QMdiSubWindow that contains the chart and that is resizable.

I already have controlled the resize event in Qt so that every time the window is resized, the chart is recreated using the new width and height, but i need to keep the aspect ratio of the axis.
I don't think is just something I can do using xAxis.setLinearScale beacuse the width of the chart is not equal to the height of the chart.

I most likely need to know for example 1 pixel of the xAxis corresponds to n metres and 1 pixel of yAxis corresponds to i metres. If i != n it means I have to modify them so that 10 pixel on the x axis represents the same metres of 10 pixels on the y axis.

Hope you understand the problem, if not don't esitate to request more info Peter!
Thank you again!

  Re: Keep pixel ratio for x and y axis
Posted by Peter Kwan on Apr-12-2018 03:12
Hi davide,

As Axis.setLinearScale can set any possible scale, so it should be possible to set the scales so that the y-axis and x-axis has the same unit per pixel.

For example, if you want n meters per pixel, one possible scale is:

c->xAxis()->setLinearScale(0, n * c->getPlotArea()->getWidth());
c->xAxis()->setRounding(false, false);
c->yAxis()->setLinearScale(0, n * c->getPlotArea()->getHeight());
c->yAxis()->setRounding(false, false);

Now both axes has n meters per pixel, no matter what is the width and height of the chart.

Of course, in the real code, you probably need to choose a scale that also contains your data. For example, for a given size, if you need 20 meters per pixel on the x-axis to contain your data, and you need 5 meters per pixel on the y-axis to contain your data,  you can simply use 20 meters per pixel also for both axes (this is equivalent to extending the y-axis scale). In this way, both axes will have the same unit per pixel.

As I am not sure of your chart type and how you preferred the axis scale to be set up, I will just use a scatter layer example in which the initial scale is set up with auto-scaling.


    // The XY data of the first data series
    double dataX0[] = {50, 55, 37, 24, 42, 49, 63, 72, 83, 59};
    double dataY0[] = {36, 28, 25, 23, 38, 30, 38, 50, 60, 33};
    int count = (int)(sizeof(dataX0) / sizeof(dataX0[0]));

    int width = 450;
    int height = 300;

    // dummy chart
    XYChart temp(width, height);
    temp.setPlotArea(55, 25, width - 100, height - 65);
    temp.addScatterLayer(DoubleArray(dataX0, count), DoubleArray(dataY0, count));

    // auto-scaling to determine the initial scale
    temp.layoutAxes();
    double xMin = temp.xAxis()->getMinValue();
    double xMax = temp.xAxis()->getMaxValue();
    double yMin = temp.yAxis()->getMinValue();
    double yMax = temp.yAxis()->getMaxValue();

    // extend either the x or y axis scale to make them the same unit per pixel
    PlotArea *p = temp.getPlotArea();
    double xExtension = p->getWidth() * (yMax - yMin) / p->getHeight() - (xMax - xMin);
    if (xExtension > 0)
    {
        xMax += xExtension / 2;
        xMin -= xExtension / 2;
    }
    else
    {
        double yExtension = p->getHeight() * (xMax - xMin) / p->getWidth() - (yMax - yMin);
        yMax += yExtension / 2;
        yMin -= yExtension / 2;
    }

    // Plot the real chart using the adjusted scale
    XYChart *c = new XYChart(width, height);
    c->setPlotArea(55, 25, width - 100, height - 65, 0xffffff, -1, 0xc0c0c0, 0xc0c0c0, -1);
    c->xAxis()->setLinearScale(xMin, xMax);
    c->xAxis()->setRounding(false, false);
    c->yAxis()->setLinearScale(yMin, yMax);
    c->yAxis()->setRounding(false, false);

    c->addScatterLayer(DoubleArray(dataX0, count), DoubleArray(dataY0, count), "Server AAA",
        Chart::DiamondSymbol, 11, 0x008000);

    viewer->setChart(c).
    delete c;

Hope this can help.

Regards
Peter Kwan

  Re: Keep pixel ratio for x and y axis
Posted by Davide on Apr-12-2018 17:12
Thank you a lot Peter! Your solution was very helpful and I managed to do what I wanted!

Thanks Again,
Davide Salvetti