diff options
Diffstat (limited to 'tests/galaxy')
-rw-r--r-- | tests/galaxy/cumulativedistributor.cpp | 143 | ||||
-rw-r--r-- | tests/galaxy/cumulativedistributor.h | 76 | ||||
-rw-r--r-- | tests/galaxy/galaxy.pro | 23 | ||||
-rw-r--r-- | tests/galaxy/galaxydata.cpp | 476 | ||||
-rw-r--r-- | tests/galaxy/galaxydata.h | 114 | ||||
-rw-r--r-- | tests/galaxy/main.cpp | 160 | ||||
-rw-r--r-- | tests/galaxy/star.cpp | 51 | ||||
-rw-r--r-- | tests/galaxy/star.h | 43 |
8 files changed, 1086 insertions, 0 deletions
diff --git a/tests/galaxy/cumulativedistributor.cpp b/tests/galaxy/cumulativedistributor.cpp new file mode 100644 index 00000000..ed5e871f --- /dev/null +++ b/tests/galaxy/cumulativedistributor.cpp @@ -0,0 +1,143 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd +** All rights reserved. +** For any questions to The Qt Company, please use contact form at http://qt.io +** +** This file is part of the Qt Data Visualization module. +** +** Licensees holding valid commercial license for Qt may use this file in +** accordance with the Qt License Agreement provided with the Software +** or, alternatively, in accordance with the terms contained in a written +** agreement between you and The Qt Company. +** +** If you have questions regarding the use of this file, please use +** contact form at http://qt.io +** +****************************************************************************/ + +/* + * Galaxy creation code obtained from http://beltoforion.de/galaxy/galaxy_en.html + * Thanks to Ingo Berg, great work. + * Licensed under a Creative Commons Attribution 3.0 License + * http://creativecommons.org/licenses/by/3.0/ + */ + +#include "cumulativedistributor.h" + +#include <QDebug> + +CumulativeDistributor::CumulativeDistributor() + : m_pDistFun(NULL), + m_vM1(), + m_vY1(), + m_vX1(), + m_vM2(), + m_vY2(), + m_vX2() +{ +} + +CumulativeDistributor::~CumulativeDistributor() +{ +} + +void CumulativeDistributor::setupRealistic(qreal I0, qreal k, qreal a, + qreal RBulge, qreal min, qreal max, + int nSteps) +{ + m_fMin = min; + m_fMax = max; + m_nSteps = nSteps; + + m_I0 = I0; + m_k = k; + m_a = a; + m_RBulge = RBulge; + + m_pDistFun = &CumulativeDistributor::Intensity; + + // build the distribution function + buildCDF(m_nSteps); +} + +void CumulativeDistributor::buildCDF(int nSteps) +{ + qreal h = (m_fMax - m_fMin) / nSteps; + qreal x = 0, y = 0; + + m_vX1.clear(); + m_vY1.clear(); + m_vX2.clear(); + m_vM1.clear(); + m_vM1.clear(); + + // Simpson rule for integration of the distribution function + m_vY1.push_back(0.0); + m_vX1.push_back(0.0); + for (int i = 0; i < nSteps; i += 2) { + x = (i + 2) * h; + y += h/3 * ((this->*m_pDistFun)(m_fMin + i*h) + 4*(this->*m_pDistFun)(m_fMin + (i+1)*h) + (this->*m_pDistFun)(m_fMin + (i+2)*h) ); + + m_vM1.push_back((y - m_vY1.back()) / (2*h)); + m_vX1.push_back(x); + m_vY1.push_back(y); + } + + // normieren + for (int i = 0; i < m_vM1.size(); i++) { + m_vY1[i] /= m_vY1.back(); + m_vM1[i] /= m_vY1.back(); + } + + m_vY2.clear(); + m_vM2.clear(); + m_vY2.push_back(0.0); + + qreal p = 0; + h = 1.0 / nSteps; + for (int i = 1, k = 0; i < nSteps; ++i) { + p = (qreal)i * h; + + for (; m_vY1[k+1] <= p; ++k) { + } + + y = m_vX1[k] + (p - m_vY1[k]) / m_vM1[k]; + + m_vM2.push_back( (y - m_vY2.back()) / h); + m_vX2.push_back(p); + m_vY2.push_back(y); + } +} + +qreal CumulativeDistributor::valFromProp(qreal fVal) +{ + if (fVal < 0.0 || fVal > 1.0) + throw std::runtime_error("out of range"); + + qreal h = 1.0 / m_vY2.size(); + + int i = int(fVal / h); + qreal remainder = fVal - i*h; + + int min = qMin(m_vY2.size(), m_vM2.size()); + if (i >= min) + i = min - 1; + + return (m_vY2[i] + m_vM2[i] * remainder); +} + +qreal CumulativeDistributor::IntensityBulge(qreal R, qreal I0, qreal k) +{ + return I0 * exp(-k * pow(R, 0.25)); +} + +qreal CumulativeDistributor::IntensityDisc(qreal R, qreal I0, qreal a) +{ + return I0 * exp(-R/a); +} + +qreal CumulativeDistributor::Intensity(qreal x) +{ + return (x < m_RBulge) ? IntensityBulge(x, m_I0, m_k) : IntensityDisc(x - m_RBulge, IntensityBulge(m_RBulge, m_I0, m_k), m_a); +} diff --git a/tests/galaxy/cumulativedistributor.h b/tests/galaxy/cumulativedistributor.h new file mode 100644 index 00000000..6e3a2f2c --- /dev/null +++ b/tests/galaxy/cumulativedistributor.h @@ -0,0 +1,76 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd +** All rights reserved. +** For any questions to The Qt Company, please use contact form at http://qt.io +** +** This file is part of the Qt Data Visualization module. +** +** Licensees holding valid commercial license for Qt may use this file in +** accordance with the Qt License Agreement provided with the Software +** or, alternatively, in accordance with the terms contained in a written +** agreement between you and The Qt Company. +** +** If you have questions regarding the use of this file, please use +** contact form at http://qt.io +** +****************************************************************************/ + +/* + * Galaxy creation code obtained from http://beltoforion.de/galaxy/galaxy_en.html + * Thanks to Ingo Berg, great work. + * Licensed under a Creative Commons Attribution 3.0 License + * http://creativecommons.org/licenses/by/3.0/ + */ + +#ifndef CUMULATIVEDISTRIBUTOR_H +#define CUMULATIVEDISTRIBUTOR_H + +#include <QtCore/qglobal.h> +#include <QtGui/QVector2D> +#include <QtCore/QVector> + +class CumulativeDistributor +{ +public: + typedef qreal (CumulativeDistributor::*dist_fun_t)(qreal x); + + CumulativeDistributor(); + virtual ~CumulativeDistributor(); + + qreal PropFromVal(qreal fVal); + qreal ValFromProp(qreal fVal); + + void setupRealistic(qreal I0, qreal k, qreal a, qreal RBulge, qreal min, + qreal max, int nSteps); + qreal valFromProp(qreal fVal); + +private: + dist_fun_t m_pDistFun; + qreal m_fMin; + qreal m_fMax; + qreal m_fWidth; + int m_nSteps; + + // parameters for realistic star distribution + qreal m_I0; + qreal m_k; + qreal m_a; + qreal m_RBulge; + + QVector<qreal> m_vM1; + QVector<qreal> m_vY1; + QVector<qreal> m_vX1; + + QVector<qreal> m_vM2; + QVector<qreal> m_vY2; + QVector<qreal> m_vX2; + + void buildCDF(int nSteps); + + qreal IntensityBulge(qreal R, qreal I0, qreal k); + qreal IntensityDisc(qreal R, qreal I0, qreal a); + qreal Intensity(qreal x); +}; + +#endif // CUMULATIVEDISTRIBUTOR_H diff --git a/tests/galaxy/galaxy.pro b/tests/galaxy/galaxy.pro new file mode 100644 index 00000000..0b602e16 --- /dev/null +++ b/tests/galaxy/galaxy.pro @@ -0,0 +1,23 @@ +android|ios|winrt { + error( "This example is not supported for android, ios, or winrt." ) +} + +!include( ../tests.pri ) { + error( "Couldn't find the tests.pri file!" ) +} + +SOURCES += main.cpp \ + galaxydata.cpp \ + star.cpp \ + cumulativedistributor.cpp + +HEADERS += \ + cumulativedistributor.h \ + galaxydata.h \ + star.h + +QT += widgets + +OTHER_FILES += doc/src/* \ + doc/images/* + diff --git a/tests/galaxy/galaxydata.cpp b/tests/galaxy/galaxydata.cpp new file mode 100644 index 00000000..31a39c1e --- /dev/null +++ b/tests/galaxy/galaxydata.cpp @@ -0,0 +1,476 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd +** All rights reserved. +** For any questions to The Qt Company, please use contact form at http://qt.io +** +** This file is part of the Qt Data Visualization module. +** +** Licensees holding valid commercial license for Qt may use this file in +** accordance with the Qt License Agreement provided with the Software +** or, alternatively, in accordance with the terms contained in a written +** agreement between you and The Qt Company. +** +** If you have questions regarding the use of this file, please use +** contact form at http://qt.io +** +****************************************************************************/ + +/* + * Galaxy creation code obtained from http://beltoforion.de/galaxy/galaxy_en.html + * Thanks to Ingo Berg, great work. + * Licensed under a Creative Commons Attribution 3.0 License + * http://creativecommons.org/licenses/by/3.0/ + */ + +#include "galaxydata.h" +#include "cumulativedistributor.h" +#include "star.h" +#include <QtDataVisualization/qscatterdataproxy.h> +#include <QtDataVisualization/qvalue3daxis.h> +#include <QtDataVisualization/q3dscene.h> +#include <QtDataVisualization/q3dcamera.h> +#include <QtDataVisualization/qscatter3dseries.h> +#include <QtDataVisualization/q3dtheme.h> +#include <QtCore/qmath.h> +#include <QPainter> + +#include <QDebug> + +using namespace QtDataVisualization; + +static const int numOfStars = 70000; +static const int numOfDust = numOfStars / 2; +static const int numOfH2 = 200; +static const qreal rand_max = qreal(RAND_MAX); + +GalaxyData::GalaxyData(Q3DScatter *scatter, + qreal rad, + qreal radCore, + qreal deltaAng, + qreal ex1, + qreal ex2) + : m_graph(scatter), + m_pStars(0), + m_pDust(0), + m_pH2(0), + m_radGalaxy(rad), + m_radCore(radCore), + m_angleOffset(deltaAng), + m_elEx1(ex1), + m_elEx2(ex2), + m_radFarField(m_radGalaxy * 2), + m_filtered(false) +{ + m_graph->activeTheme()->setType(Q3DTheme::ThemeEbony); + m_graph->setShadowQuality(QAbstract3DGraph::ShadowQualitySoftLow); + + m_graph->axisX()->setRange(-25000.0f, 25000.0f); + //m_graph->axisY()->setRange(m_minY, m_minY + m_rangeY); + m_graph->axisZ()->setRange(-25000.0f, 25000.0f); + m_graph->setOptimizationHints(QAbstract3DGraph::OptimizationStatic); + //m_graph->activeTheme()->setType(Q3DTheme::ThemeIsabelle); + m_graph->activeTheme()->setBackgroundColor(QColor(31, 31, 31)); + m_graph->activeTheme()->setWindowColor(QColor(31, 31, 31)); + m_graph->activeTheme()->setLabelBackgroundColor(QColor(31, 31, 31)); + m_graph->activeTheme()->setLabelTextColor(QColor(31, 31, 31)); + + QObject::connect(m_graph, &QAbstract3DGraph::currentFpsChanged, + this, &GalaxyData::handleFpsChange); + m_graph->setMeasureFps(true); + + createSeries(); + createGalaxy(); +} + +GalaxyData::~GalaxyData() +{ + delete m_graph; + if (m_pStars) + delete [] m_pStars; + if (m_pDust) + delete [] m_pDust; + if (m_pH2) + delete [] m_pH2; +} + +void GalaxyData::createGalaxy() +{ + if (m_pStars) + delete [] m_pStars; + m_pStars = new Star[numOfStars]; + + if (m_pDust) + delete [] m_pDust; + m_pDust = new Star[numOfDust]; + + if (m_pH2) + delete [] m_pH2; + m_pH2 = new Star[numOfH2 * 2]; + + + m_minx = 9999.9; + m_maxx = -9999.0; + m_miny = 9999.9; + m_maxy = -9999.0; + + // First star is the black hole at the center + m_pStars[0].m_a = 0; + m_pStars[0].m_b = 0; + m_pStars[0].m_angle = 0; + m_pStars[0].m_theta = 0; + m_pStars[0].m_center = QVector2D(0.0f, 0.0f); + m_pStars[0].calcXY(); + + // second star is at the edge of the core area + m_pStars[1].m_a = m_radCore; + m_pStars[1].m_b = m_radCore * getExcentricity(m_radCore); + m_pStars[1].m_angle = getAngularOffset(m_radCore); + m_pStars[1].m_theta = 0; + m_pStars[1].m_center = QVector2D(0.0f, 0.0f); + m_pStars[1].calcXY(); + checkMinMax(m_pStars[1]); + + // third star is at the edge of the disk + m_pStars[2].m_a = m_radGalaxy; + m_pStars[2].m_b = m_radGalaxy * getExcentricity(m_radGalaxy); + m_pStars[2].m_angle = getAngularOffset(m_radGalaxy); + m_pStars[2].m_theta = 0; + m_pStars[2].m_center = QVector2D(0.0f, 0.0f); + m_pStars[2].calcXY(); + checkMinMax(m_pStars[2]); + + CumulativeDistributor cd; + cd.setupRealistic(1.0, // Maximalintensität + 0.02, // k (bulge) + m_radGalaxy/3.0, // disc skalenlänge + m_radCore, // bulge radius + 0, // start der intensitätskurve + m_radFarField, // ende der intensitätskurve + 1000.0); // Anzahl der stützstellen + + for (int i = 3; i < numOfStars; ++i) { + qreal rad = cd.valFromProp(qreal(qrand()) / rand_max); + + m_pStars[i].m_a = rad; + m_pStars[i].m_b = rad * getExcentricity(rad); + m_pStars[i].m_angle = getAngularOffset(rad); + m_pStars[i].m_theta = 360.0 * ((double)rand() / RAND_MAX); + m_pStars[i].m_center = QVector2D(0.0f, 0.0f); + m_pStars[i].calcXY(); + + checkMinMax(m_pStars[i]); + } + + // Initialize Dust + qreal x, y, rad; + for (int i = 0; i < numOfDust; ++i) + { + x = 2.0 * m_radGalaxy * ((double)rand() / RAND_MAX) - m_radGalaxy; + y = 2.0 * m_radGalaxy * ((double)rand() / RAND_MAX) - m_radGalaxy; + rad = sqrt(x*x + y*y); + + m_pDust[i].m_a = rad; + m_pDust[i].m_b = rad * getExcentricity(rad); + m_pDust[i].m_angle = getAngularOffset(rad); + m_pDust[i].m_theta = 360.0 * ((double)rand() / RAND_MAX); + m_pDust[i].m_center = QVector2D(0.0f, 0.0f); + m_pDust[i].calcXY(); + + checkMinMax(m_pDust[i]); + } + + // Initialize H2 + for (int i = 0; i < numOfH2; ++i) + { + x = 2*(m_radGalaxy) * ((double)rand() / RAND_MAX) - (m_radGalaxy); + y = 2*(m_radGalaxy) * ((double)rand() / RAND_MAX) - (m_radGalaxy); + rad = sqrt(x*x + y*y); + + int k1 = 2*i; + m_pH2[k1].m_a = rad; + m_pH2[k1].m_b = rad * getExcentricity(rad); + m_pH2[k1].m_angle = getAngularOffset(rad); + m_pH2[k1].m_theta = 360.0 * ((double)rand() / RAND_MAX); + m_pH2[k1].m_center = QVector2D(0.0f, 0.0f); + m_pH2[k1].calcXY(); + + int k2 = 2*i + 1; + m_pH2[k2].m_a = rad + 1000.0; + m_pH2[k2].m_b = rad * getExcentricity(rad); + m_pH2[k2].m_angle = m_pH2[k1].m_angle; + m_pH2[k2].m_theta = m_pH2[k1].m_theta; + m_pH2[k2].m_center = m_pH2[k1].m_center; + m_pH2[k2].calcXY(); + } + + qreal max = qMax(m_maxx, m_maxy); + qreal min = -qMin(m_minx, m_miny); + max = qMax(min, max); + m_range = int((max + 500.0) / 1000.0) * 1000; + m_graph->axisX()->setRange(-float(m_range), float(m_range)); + m_graph->axisZ()->setRange(-float(m_range), float(m_range)); + + if (!m_filtered) + createNormalDataView(); + else + createFilteredView(); +} + +void GalaxyData::createSeries() +{ + QScatterDataProxy *proxyNormal = new QScatterDataProxy; + m_normalSeries = new QScatter3DSeries(proxyNormal); + m_normalSeries->setMesh(QAbstract3DSeries::MeshPoint); + m_graph->addSeries(m_normalSeries); + + QScatterDataProxy *proxyDust = new QScatterDataProxy; + m_dustSeries = new QScatter3DSeries(proxyDust); + m_dustSeries->setMesh(QAbstract3DSeries::MeshPoint); + m_graph->addSeries(m_dustSeries); + + QScatterDataProxy *proxyH2 = new QScatterDataProxy; + m_H2Series = new QScatter3DSeries(proxyH2); + m_H2Series->setMesh(QAbstract3DSeries::MeshPoint); + m_graph->addSeries(m_H2Series); + + QScatterDataProxy *proxyFiltered = new QScatterDataProxy; + m_filteredSeries = new QScatter3DSeries(proxyFiltered); + m_filteredSeries->setMesh(QAbstract3DSeries::MeshCube); + m_graph->addSeries(m_filteredSeries); + +} + +void GalaxyData::createNormalDataView() +{ + QScatterDataArray *dataArray = new QScatterDataArray; + dataArray->resize(numOfStars); + QScatterDataItem *ptrToDataArray = &dataArray->first(); + + for (uint i = 0; i < numOfStars; i++) { + ptrToDataArray->setPosition(QVector3D(m_pStars[i].m_pos.x(), + 0.0f, + m_pStars[i].m_pos.y())); + ptrToDataArray++; + } + + m_normalSeries->dataProxy()->resetArray(dataArray); + m_normalSeries->setMesh(QAbstract3DSeries::MeshPoint); + m_normalSeries->setBaseColor(Qt::white); + + dataArray = new QScatterDataArray; + dataArray->resize(numOfDust); + ptrToDataArray = &dataArray->first(); + + for (uint i = 0; i < numOfDust; i++) { + ptrToDataArray->setPosition(QVector3D(m_pDust[i].m_pos.x(), + 0.0f, + m_pDust[i].m_pos.y())); + ptrToDataArray++; + } + + m_dustSeries->dataProxy()->resetArray(dataArray); + m_dustSeries->setMesh(QAbstract3DSeries::MeshPoint); + m_dustSeries->setBaseColor(QColor(131, 111, 255)); + + dataArray = new QScatterDataArray; + dataArray->resize(numOfDust); + ptrToDataArray = &dataArray->first(); + + uint H2Count = numOfH2 * 2; + for (uint i = 0; i < H2Count; i++) { + ptrToDataArray->setPosition(QVector3D(m_pH2[i].m_pos.x(), + 0.0f, + m_pH2[i].m_pos.y())); + ptrToDataArray++; + } + + m_H2Series->dataProxy()->resetArray(dataArray); + m_H2Series->setMesh(QAbstract3DSeries::MeshPoint); + m_H2Series->setBaseColor(Qt::red); +} + +void GalaxyData::createFilteredView() +{ + int steps = (m_range / 1000) * 2; + int tableSize = steps * steps; + int *table = new int[tableSize]; + for (int i = 0; i < tableSize; i++) + table[i] = 0; + qreal add = qreal(m_range); + int max = 0; + + for (uint i = 0; i < numOfStars; i++) { + int x = int(m_pStars[i].m_pos.x() + add) / 1000; + int y = int(m_pStars[i].m_pos.y() + add) / 1000; + table[y * steps + x] = table[y * steps + x] + 1; + + if (max < table[y * steps + x]) + max = table[y * steps + x]; + } + + // Count how many cells have data + int nActiveCell = 0; + for (int i = 0; i < tableSize; i++) { + if (table[i]) + nActiveCell++; + } + + + QScatterDataArray *dataArray = new QScatterDataArray; + dataArray->resize(nActiveCell); + QScatterDataItem *ptrToDataArray = &dataArray->first(); + + for (int y = 0; y < steps; y++) { + for (int x = 0; x < steps; x++) { + if (table[y * steps + x]) { + ptrToDataArray->setPosition(QVector3D(float(x) * 1000.0f - add + 500.0f, + float(table[y * steps + x]), + float(y) * 1000.0f - add + 500.0f)); + ptrToDataArray++; + } + } + } + + m_filteredSeries->dataProxy()->resetArray(dataArray); + m_filteredSeries->setMesh(QAbstract3DSeries::MeshCube); + m_filteredSeries->setItemSize(0.1f); + + m_graph->axisY()->setRange(0.0f, float(max + 1)); + + qDebug() << "max = " << max; +} + +void GalaxyData::checkMinMax(const Star &star) +{ + if (star.m_pos.x() < m_minx) + m_minx = star.m_pos.x(); + if (star.m_pos.x() > m_maxx) + m_maxx = star.m_pos.x(); + if (star.m_pos.y() < m_miny) + m_miny = star.m_pos.y(); + if (star.m_pos.y() > m_maxy) + m_maxy = star.m_pos.y(); +} + +qreal GalaxyData::getExcentricity(qreal r) const +{ + if (r < m_radCore) + { + // Core region of the galaxy. Innermost part is round + // excentricity increasing linear to the border of the core. + return 1 + (r / m_radCore) * (m_elEx1-1); + } else if (r > m_radCore && r <= m_radGalaxy) { + return m_elEx1 + (r - m_radCore) / (m_radGalaxy - m_radCore) * (m_elEx2 - m_elEx1); + } else if (r > m_radGalaxy && r < m_radFarField) { + // excentricity is slowly reduced to 1. + return m_elEx2 + (r - m_radGalaxy) / (m_radFarField - m_radGalaxy) * (1 - m_elEx2); + } else { + return 1.0; + } +} + +qreal GalaxyData::getAngularOffset(qreal rad) const +{ + return rad * m_angleOffset; +} + +void GalaxyData::radiusGalaxyChanged(int value) +{ + m_radGalaxy = qreal(value); + createGalaxy(); +} + +void GalaxyData::radiusCoreChanged(int value) +{ + m_radCore = qreal(value); + createGalaxy(); +} + +void GalaxyData::angleOffsetChanged(int value) +{ + m_angleOffset = qreal(value) / 100000.0; + createGalaxy(); +} + +void GalaxyData::eccentricityInnerChanged(int value) +{ + m_elEx1 = qreal(value) / 100.0; + createGalaxy(); +} + +void GalaxyData::eccentricityOuterChanged(int value) +{ + m_elEx2 = qreal(value) / 100.0; + createGalaxy(); +} + +void GalaxyData::setFilteredEnabled(bool enabled) +{ + m_filtered = enabled; + if (enabled) { + QLinearGradient gr(0, 0, 1, 100); + gr.setColorAt(0.0, Qt::white); + gr.setColorAt(0.04, Qt::green); + gr.setColorAt(0.1, Qt::darkGreen); + gr.setColorAt(1.0, Qt::red); + + m_filteredSeries->setBaseGradient(gr); + m_filteredSeries->setColorStyle(Q3DTheme::ColorStyleRangeGradient); + + m_normalSeries->setVisible(false); + + createFilteredView(); + + m_filteredSeries->setVisible(true); + } else { + m_normalSeries->setColorStyle(Q3DTheme::ColorStyleUniform); + m_graph->axisY()->setRange(-1.0f, 1.0f); + m_normalSeries->setItemSize(0.0f); + + m_filteredSeries->setVisible(false); + + createNormalDataView(); + + m_normalSeries->setVisible(true); + } +} + + +void GalaxyData::setStaticEnabled(bool enabled) +{ + if (enabled) + m_graph->setOptimizationHints(QAbstract3DGraph::OptimizationStatic); + else + m_graph->setOptimizationHints(QAbstract3DGraph::OptimizationDefault); +} + +void GalaxyData::setStarsVisible(bool enabled) +{ + m_normalSeries->setVisible(enabled); +} + +void GalaxyData::setDustVisible(bool enabled) +{ + m_dustSeries->setVisible(enabled); +} + +void GalaxyData::setH2Visible(bool enabled) +{ + m_H2Series->setVisible(enabled); +} + +void GalaxyData::resetValues() +{ + m_radiusGalaxySlider->setValue(15000); + m_radiusCoreSlider->setValue(4000); + m_angleOffsetSlider->setValue(40); + m_eccentricityInnerSlider->setValue(90); + m_eccentricityOuterSlider->setValue(90); +} + +void GalaxyData::handleFpsChange(qreal fps) +{ + static const QString fpsPrefix(QStringLiteral("FPS: ")); + m_fpsLabel->setText(fpsPrefix + QString::number(qRound(fps))); +} diff --git a/tests/galaxy/galaxydata.h b/tests/galaxy/galaxydata.h new file mode 100644 index 00000000..8f084316 --- /dev/null +++ b/tests/galaxy/galaxydata.h @@ -0,0 +1,114 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd +** All rights reserved. +** For any questions to The Qt Company, please use contact form at http://qt.io +** +** This file is part of the Qt Data Visualization module. +** +** Licensees holding valid commercial license for Qt may use this file in +** accordance with the Qt License Agreement provided with the Software +** or, alternatively, in accordance with the terms contained in a written +** agreement between you and The Qt Company. +** +** If you have questions regarding the use of this file, please use +** contact form at http://qt.io +** +****************************************************************************/ + +#ifndef SCATTERDATAMODIFIER_H +#define SCATTERDATAMODIFIER_H + +#include "star.h" + +#include <QtDataVisualization/q3dscatter.h> +#include <QtDataVisualization/qabstract3dseries.h> +#include <QtGui/QFont> +#include <QtWidgets/QSlider> +#include <QtWidgets/QLabel> + +using namespace QtDataVisualization; + +class GalaxyData : public QObject +{ + Q_OBJECT +public: + explicit GalaxyData(Q3DScatter *scatter, + qreal rad = 13000, + qreal radCore = 4000.0, + qreal deltaAng = 0.0004, + qreal ex1 = 0.9, + qreal ex2 = 0.9); + ~GalaxyData(); + + qreal getExcentricity(qreal r) const; + qreal getAngularOffset(qreal rad) const; + + void radiusGalaxyChanged(int value); + void radiusCoreChanged(int value); + void angleOffsetChanged(int value); + void eccentricityInnerChanged(int value); + void eccentricityOuterChanged(int value); + void resetValues(); + void setFilteredEnabled(bool enabled); + void setStaticEnabled(bool enabled); + void setStarsVisible(bool enabled); + void setDustVisible(bool enabled); + void setH2Visible(bool enabled); + inline void setSliders(QSlider *rg, + QSlider *rc, + QSlider *ao, + QSlider *ei, + QSlider *eo) { + m_radiusGalaxySlider = rg; + m_radiusCoreSlider = rc; + m_angleOffsetSlider = ao; + m_eccentricityInnerSlider = ei; + m_eccentricityOuterSlider = eo; + } + void setFpsLabel(QLabel *fpsLabel) { m_fpsLabel = fpsLabel; } + void handleFpsChange(qreal fps); + +private: + void createGalaxy(); + void checkMinMax(const Star &star); + void createNormalDataView(); + void createFilteredView(); + void createSeries(); + qreal value; + +private: + Q3DScatter *m_graph; + QScatter3DSeries *m_normalSeries; + QScatter3DSeries *m_dustSeries; + QScatter3DSeries *m_H2Series; + QScatter3DSeries *m_filteredSeries; + Star *m_pStars; + Star *m_pDust; + Star *m_pH2; + + qreal m_elEx1; // Excentricity of the innermost ellipse + qreal m_elEx2; // Excentricity of the outermost ellipse + + qreal m_angleOffset; // Angular offset per parsec + + qreal m_radCore; // Radius of the inner core + qreal m_radGalaxy; // Radius of the galaxy + qreal m_radFarField; // The radius after which all density waves must have circular shape + + QSlider *m_radiusGalaxySlider; + QSlider *m_radiusCoreSlider; + QSlider *m_angleOffsetSlider; + QSlider *m_eccentricityInnerSlider; + QSlider *m_eccentricityOuterSlider; + QLabel *m_fpsLabel; + + qreal m_minx = 9999.9; + qreal m_maxx = -9999.0; + qreal m_miny = 9999.9; + qreal m_maxy = -9999.0; + int m_range; + bool m_filtered; +}; + +#endif diff --git a/tests/galaxy/main.cpp b/tests/galaxy/main.cpp new file mode 100644 index 00000000..e2ffd002 --- /dev/null +++ b/tests/galaxy/main.cpp @@ -0,0 +1,160 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd +** All rights reserved. +** For any questions to The Qt Company, please use contact form at http://qt.io +** +** This file is part of the Qt Data Visualization module. +** +** Licensees holding valid commercial license for Qt may use this file in +** accordance with the Qt License Agreement provided with the Software +** or, alternatively, in accordance with the terms contained in a written +** agreement between you and The Qt Company. +** +** If you have questions regarding the use of this file, please use +** contact form at http://qt.io +** +****************************************************************************/ + +#include "galaxydata.h" + +#include <QtWidgets/QApplication> +#include <QtWidgets/QWidget> +#include <QtWidgets/QHBoxLayout> +#include <QtWidgets/QVBoxLayout> +#include <QtWidgets/QPushButton> +#include <QtWidgets/QCheckBox> +#include <QtWidgets/QComboBox> +#include <QtWidgets/QFontComboBox> +#include <QtWidgets/QLabel> +#include <QtGui/QScreen> +#include <QtGui/QFontDatabase> + +int main(int argc, char **argv) +{ + //! [0] + QApplication app(argc, argv); + Q3DScatter *graph = new Q3DScatter(); + QWidget *container = QWidget::createWindowContainer(graph); + //! [0] + + QSize screenSize = graph->screen()->size(); + container->setMinimumSize(QSize(screenSize.width() / 2, screenSize.height() / 1.5)); + container->setMaximumSize(screenSize); + container->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding); + container->setFocusPolicy(Qt::StrongFocus); + + QWidget *widget = new QWidget; + QHBoxLayout *hLayout = new QHBoxLayout(widget); + QVBoxLayout *vLayout = new QVBoxLayout(); + hLayout->addWidget(container, 1); + hLayout->addLayout(vLayout); + vLayout->setAlignment(Qt::AlignTop); + + widget->setWindowTitle(QStringLiteral("A Galaxy")); + + QSlider *radiusGalaxySlider = new QSlider(Qt::Horizontal, widget); + radiusGalaxySlider->setMinimum(1000); + radiusGalaxySlider->setMaximum(40000); + radiusGalaxySlider->setValue(15000); + radiusGalaxySlider->setEnabled(true); + + QSlider *radiusCoreSlider = new QSlider(Qt::Horizontal, widget); + radiusCoreSlider->setMinimum(1000); + radiusCoreSlider->setMaximum(30000); + radiusCoreSlider->setValue(4000); + radiusCoreSlider->setEnabled(true); + + QSlider *angleOffsetSlider = new QSlider(Qt::Horizontal, widget); + angleOffsetSlider->setMinimum(10); + angleOffsetSlider->setMaximum(70); + angleOffsetSlider->setValue(40); + angleOffsetSlider->setEnabled(true); + + QSlider *eccentricityInnerSlider = new QSlider(Qt::Horizontal, widget); + eccentricityInnerSlider->setMinimum(10); + eccentricityInnerSlider->setMaximum(200); + eccentricityInnerSlider->setValue(90); + eccentricityInnerSlider->setEnabled(true); + + QSlider *eccentricityOuterSlider = new QSlider(Qt::Horizontal, widget); + eccentricityOuterSlider->setMinimum(10); + eccentricityOuterSlider->setMaximum(200); + eccentricityOuterSlider->setValue(90); + eccentricityOuterSlider->setEnabled(true); + + QCheckBox *staticCheckBox = new QCheckBox(widget); + staticCheckBox->setText(QStringLiteral("Static")); + staticCheckBox->setChecked(false); + + QCheckBox *starsCheckBox = new QCheckBox(widget); + starsCheckBox->setText(QStringLiteral("Stars")); + starsCheckBox->setChecked(true); + + QCheckBox *dustCheckBox = new QCheckBox(widget); + dustCheckBox->setText(QStringLiteral("Dust")); + dustCheckBox->setChecked(true); + + QCheckBox *H2CheckBox = new QCheckBox(widget); + H2CheckBox->setText(QStringLiteral("H2")); + H2CheckBox->setChecked(true); + + QPushButton *resetButton = new QPushButton(widget); + resetButton->setText(QStringLiteral("Reset values")); + + QCheckBox *filteredCheckBox = new QCheckBox(widget); + filteredCheckBox->setText(QStringLiteral("Filtered")); + filteredCheckBox->setChecked(false); + + QLabel *fpsLabel = new QLabel(QStringLiteral("")); + + vLayout->addWidget(new QLabel(QStringLiteral("Galaxy radius"))); + vLayout->addWidget(radiusGalaxySlider); + vLayout->addWidget(new QLabel(QStringLiteral("Core radius"))); + vLayout->addWidget(radiusCoreSlider); + vLayout->addWidget(new QLabel(QStringLiteral("Angle offset"))); + vLayout->addWidget(angleOffsetSlider); + vLayout->addWidget(new QLabel(QStringLiteral("Eccentricity inner"))); + vLayout->addWidget(eccentricityInnerSlider); + vLayout->addWidget(new QLabel(QStringLiteral("Eccentricity outer"))); + vLayout->addWidget(eccentricityOuterSlider); + vLayout->addWidget(staticCheckBox); + vLayout->addWidget(starsCheckBox); + vLayout->addWidget(dustCheckBox); + vLayout->addWidget(H2CheckBox); + vLayout->addWidget(resetButton); + vLayout->addWidget(filteredCheckBox); + vLayout->addWidget(fpsLabel); + + GalaxyData *modifier = new GalaxyData(graph); + + QObject::connect(radiusGalaxySlider, &QSlider::valueChanged, + modifier, &GalaxyData::radiusGalaxyChanged); + QObject::connect(radiusCoreSlider, &QSlider::valueChanged, + modifier, &GalaxyData::radiusCoreChanged); + QObject::connect(angleOffsetSlider, &QSlider::valueChanged, + modifier, &GalaxyData::angleOffsetChanged); + QObject::connect(eccentricityInnerSlider, &QSlider::valueChanged, + modifier, &GalaxyData::eccentricityInnerChanged); + QObject::connect(eccentricityOuterSlider, &QSlider::valueChanged, + modifier, &GalaxyData::eccentricityOuterChanged); + QObject::connect(resetButton, &QPushButton::clicked, + modifier, &GalaxyData::resetValues); + QObject::connect(filteredCheckBox, &QCheckBox::stateChanged, + modifier, &GalaxyData::setFilteredEnabled); + QObject::connect(staticCheckBox, &QCheckBox::stateChanged, + modifier, &GalaxyData::setStaticEnabled); + QObject::connect(starsCheckBox, &QCheckBox::stateChanged, + modifier, &GalaxyData::setStarsVisible); + QObject::connect(dustCheckBox, &QCheckBox::stateChanged, + modifier, &GalaxyData::setDustVisible); + QObject::connect(H2CheckBox, &QCheckBox::stateChanged, + modifier, &GalaxyData::setH2Visible); + + modifier->setSliders(radiusGalaxySlider, radiusCoreSlider, angleOffsetSlider, + eccentricityInnerSlider, eccentricityOuterSlider); + modifier->setFpsLabel(fpsLabel); + + widget->show(); + return app.exec(); +} diff --git a/tests/galaxy/star.cpp b/tests/galaxy/star.cpp new file mode 100644 index 00000000..3a58d511 --- /dev/null +++ b/tests/galaxy/star.cpp @@ -0,0 +1,51 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd +** All rights reserved. +** For any questions to The Qt Company, please use contact form at http://qt.io +** +** This file is part of the Qt Data Visualization module. +** +** Licensees holding valid commercial license for Qt may use this file in +** accordance with the Qt License Agreement provided with the Software +** or, alternatively, in accordance with the terms contained in a written +** agreement between you and The Qt Company. +** +** If you have questions regarding the use of this file, please use +** contact form at http://qt.io +** +****************************************************************************/ + +#include "star.h" + +#include <QtCore/qmath.h> + +static const double DEG_TO_RAD = M_PI / 180.0; + +Star::Star() + : m_theta(0), + m_a(0), + m_b(0), + m_center(QVector2D(0.0f, 0.0f)) +{ +} + +const void Star::calcXY() +{ + qreal &a = m_a; + qreal &b = m_b; + qreal &theta = m_theta; + const QVector2D &p = m_center; + + qreal beta = -m_angle; + qreal alpha = theta * DEG_TO_RAD; + + // temporaries to save cpu time + qreal cosalpha = qCos(alpha); + qreal sinalpha = qSin(alpha); + qreal cosbeta = qCos(beta); + qreal sinbeta = qSin(beta); + + m_pos = QVector2D(p.x() + (a * cosalpha * cosbeta - b * sinalpha * sinbeta), + p.y() + (a * cosalpha * sinbeta + b * sinalpha * cosbeta)); +} diff --git a/tests/galaxy/star.h b/tests/galaxy/star.h new file mode 100644 index 00000000..648441b0 --- /dev/null +++ b/tests/galaxy/star.h @@ -0,0 +1,43 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd +** All rights reserved. +** For any questions to The Qt Company, please use contact form at http://qt.io +** +** This file is part of the Qt Data Visualization module. +** +** Licensees holding valid commercial license for Qt may use this file in +** accordance with the Qt License Agreement provided with the Software +** or, alternatively, in accordance with the terms contained in a written +** agreement between you and The Qt Company. +** +** If you have questions regarding the use of this file, please use +** contact form at http://qt.io +** +****************************************************************************/ + +#ifndef STAR_H +#define STAR_H + +#include <QtCore/qglobal.h> +#include <QtGui/QVector2D> + +class Star +{ +public: + Star(); + const void calcXY(); + + qreal m_theta; // position auf der ellipse +// qreal m_velTheta; // angular velocity + qreal m_angle; // Schräglage der Ellipse + qreal m_a; // kleine halbachse + qreal m_b; // große halbachse +// qreal m_temp; // star temperature +// qreal m_mag; // brightness; + QVector2D m_center; // center of the elliptical orbit +// QVector2D m_vel; // Current velocity (calculated) + QVector2D m_pos; // current position in kartesion koordinates +}; + +#endif // STAR_H |