10

I need to modify a QPolarChart to create a Satellite SkyPlot.

For this, I need to reverse the radial axis (elevation axis) so that 90 is placed on the origin and 0 on the outer ring.

In the list of members for QValueAxis I found the method setReverse, which seems to do what I need.

However, doing setReverse(true) on the elevation axis does not flip the axis as I was expecting.

How can I reverse the axis then?

Polar Chart

This is the minimal code required to run this example:

#include <QtWidgets/QApplication>
#include <QtWidgets/QMainWindow>
#include <QtCharts/QChartView>
#include <QtCharts/QPolarChart>
#include <QtCharts/QValueAxis>
#include <QScatterSeries>

QT_CHARTS_USE_NAMESPACE

int main(int argc, char *argv[])
{
    QApplication app(argc, argv);

    QtCharts::QPolarChart *chart = new QtCharts::QPolarChart();
    chart->legend()->hide();

    QScatterSeries *series = new QScatterSeries();
    for (int i = 0; i < 360; i += 10) {
        series->append(i, i);
    }
    chart->addSeries(series);

    QValueAxis *azimuthAxis = new QValueAxis();
    azimuthAxis->setRange(0, 360);
    azimuthAxis->setTickCount(9);
    azimuthAxis->setLabelFormat("%d");
    azimuthAxis->setLabelsVisible(true);
    chart->addAxis(azimuthAxis, QPolarChart::PolarOrientationAngular);

    QValueAxis *elevationAxis = new QValueAxis();
    elevationAxis->setRange(0, 90);
    elevationAxis->setTickCount(7);
    elevationAxis->setLabelFormat("%d");
    elevationAxis->setLabelsVisible(true);
    elevationAxis->setReverse(true); // <-- REVERSE THE AXIS
    chart->addAxis(elevationAxis, QPolarChart::PolarOrientationRadial);

    QtCharts::QChartView *chartView = new QtCharts::QChartView();
    chartView->setChart(chart);
    chartView->setRenderHint(QPainter::Antialiasing);

    QMainWindow window;
    window.setCentralWidget(chartView);
    window.resize(800, 600);
    window.show();

    return app.exec();
}

UPDATE:

After reading Damien's comment:

You may check with isReverse if the command setReverse was taken into account

I made the test by putting qDebug() << elevationAxis->isReverse(); immediately before and immediately after elevationAxis->setReverse(true);, and it prints out false and true, respectively.

qDebug() << elevationAxis->isReverse(); // <-- Prints out "false"
elevationAxis->setReverse(true);        // <-- REVERSE THE AXIS
qDebug() << elevationAxis->isReverse(); // <-- Prints out "true"

So the reverse property is indeed changed. However, this change is not reflected visually in the axis.

The documentation for the reverse property reads:

This property holds whether a reverse axis is used.

By default, the value is false.

The reverse axis is supported with a line, spline, and scatter series, as well as an area series with a cartesian chart. All axes of the same orientation attached to the same series must be reversed if one is reversed or the behavior is undefined.

A polar chart is certainly NOT a cartesian chart, so that might be the root of the problem.

codeaviator
  • 2,545
  • 17
  • 42
  • Then try https://qwtpolar.sourceforge.io/class_qwt_polar_plot.html#details with which – sirop Apr 16 '19 at 08:56
  • with https://qwt.sourceforge.io/class_qwt_scale_engine.html#details: "The scales at the axes can be explicitely set (QwtScaleDiv) , or are calculated from the plot items, using algorithms (QwtScaleEngine) which can be configured separately for each axis." and QwtScaleEngine::Attribute::Inverted. Sorry for proposing a different lib, but I could not see that QtCharts is the right choice. – sirop Apr 16 '19 at 09:13
  • 1
    You may check with `isReverse` if the command `setReverse` was taken into account – Damien May 14 '19 at 08:37
  • 1
    @Damien I've just made the test by putting `qDebug() << elevationAxis->isReverse();` immediately before and immediately after `elevationAxis->setReverse(true);` and it prints out `false` and `true`, respectively. So the `reverse` property is indeed changed. However, this change is not reflected in the axis. – codeaviator May 14 '19 at 10:57
  • 1
    This is not a cartesian chart but that warning was only for area series and this is not your case (scatter series) so it should work. The second notice says that all axes related to the same series must be reversed (I tried it but it still does not work). I couldn't find the problem for now. – Fareanor May 14 '19 at 12:51

1 Answers1

5

I couldn't make the setReversed(true) work whatever the way I tried to do it.

So I found another solution: Do it manually.

I printed the series in reversed way:

QScatterSeries *series = new QScatterSeries();
for (int i = 0; i < 360; i += 10) {
    series->append(i, MAX_ELEVATION - i);
}

MAX_ELEVATION equals to 90.

Then I reversed the labels names. For that I had to replace QValueAxis by its derived QCategoryAxis.


The full code

#include <QtWidgets/QApplication>
#include <QtWidgets/QMainWindow>
#include <QtCharts/QChartView>
#include <QtCharts/QPolarChart>
#include <QtCharts/QValueAxis>
#include <QScatterSeries>
#include <QtCharts/QCategoryAxis>

QT_CHARTS_USE_NAMESPACE

#define MAX_ELEVATION 90

int main(int argc, char *argv[])
{
    QApplication app(argc, argv);

    QtCharts::QPolarChart *chart = new QtCharts::QPolarChart();
    chart->legend()->hide();

    QScatterSeries *series = new QScatterSeries();
    for (int i = 0; i < 360; i += 10) {
        series->append(i, MAX_ELEVATION - i);
    }
    chart->addSeries(series);

    QValueAxis *azimuthAxis = new QValueAxis();
    azimuthAxis->setRange(0, 360);
    azimuthAxis->setTickCount(9);
    azimuthAxis->setLabelFormat("%d");
    azimuthAxis->setLabelsVisible(true);
    chart->addAxis(azimuthAxis, QPolarChart::PolarOrientationAngular);

    /*
    QValueAxis *elevationAxis = new QValueAxis();
    elevationAxis->setRange(0, 90);
    elevationAxis->setTickCount(7);
    elevationAxis->setLabelFormat("%d");
    elevationAxis->setLabelsVisible(true);
    elevationAxis->setReverse(true); // <-- REVERSE THE AXIS
    chart->addAxis(elevationAxis, QPolarChart::PolarOrientationRadial);
    */

    QCategoryAxis *elevationAxis = new QCategoryAxis;
    elevationAxis->setRange(0, MAX_ELEVATION);
    for(unsigned int i = 0; i <= MAX_ELEVATION; i += 15)
        elevationAxis->append(QString::number(MAX_ELEVATION-i), i);
    elevationAxis->setLabelsPosition(QCategoryAxis::AxisLabelsPositionOnValue);
    elevationAxis->setLabelsVisible(true);
    chart->addAxis(elevationAxis, QPolarChart::PolarOrientationRadial);


    QtCharts::QChartView *chartView = new QtCharts::QChartView();
    chartView->setChart(chart);
    chartView->setRenderHint(QPainter::Antialiasing);

    QMainWindow window;
    window.setCentralWidget(chartView);
    window.resize(800, 600);
    window.show();

    return app.exec();
}

It is equivalent to what setReversed(true) should do. It will display your series exactly the way you want without modifying anything of the way the data are computed.

Here you can see what it looks like: Display

It worked successfully for me.

Hope it can help.

Fareanor
  • 5,900
  • 2
  • 11
  • 37