File indexing completed on 2022-10-04 13:46:50

0001 /*
0002     SPDX-FileCopyrightText: 2003, 2004, 2005, 2006 Carsten Niehaus <cniehaus@kde.org>
0003     SPDX-License-Identifier: GPL-2.0-or-later
0004 */
0005 
0006 #include "orbitswidget.h"
0007 
0008 #include "kalziumdataobject.h"
0009 #include "kalziumutils.h"
0010 
0011 // QT-Includes
0012 #include <QPainter>
0013 #include <QVBoxLayout>
0014 
0015 #include <KLocalizedString>
0016 
0017 #include <cmath>
0018 
0019 static QStringList hulllist;
0020 
0021 /**
0022  * @return the delta of the x-coordinate
0023  * @param r is the radius of the circle
0024  * @param angle is the n'st circle out of num
0025  * @param num is the number of circles
0026  */
0027 inline static double translateToDX(double r, double angle, int num)
0028 {
0029     const double t = 2 * M_PI * angle / num;
0030     return r * sin(t);
0031 }
0032 
0033 /**
0034  * @return the delta of the y-coordinate
0035  * @param r is the radius of the circle
0036  * @param angle is the n'st circle out of num
0037  * @param num is the number of circles
0038  */
0039 inline static double translateToDY(double r, double angle, int num)
0040 {
0041     const double t = 2 * M_PI * angle / num;
0042     return r * cos(t);
0043 }
0044 
0045 OrbitsWidget::OrbitsWidget(QWidget *parent)
0046     : QWidget(parent)
0047     , m_electronConf(new QLabel(this))
0048 {
0049     m_electronConf->setIndent(20);
0050     auto layout = new QVBoxLayout(m_electronConf);
0051     setLayout(layout);
0052 
0053     if (hulllist.count() == 0) {
0054         hulllist.append(QStringLiteral("1"));
0055         hulllist.append(QStringLiteral("2")); // Helium
0056         hulllist.append(QStringLiteral("2 1"));
0057         hulllist.append(QStringLiteral("2 2"));
0058         hulllist.append(QStringLiteral("2 3"));
0059         hulllist.append(QStringLiteral("2 4"));
0060         hulllist.append(QStringLiteral("2 5"));
0061         hulllist.append(QStringLiteral("2 6"));
0062         hulllist.append(QStringLiteral("2 7"));
0063         hulllist.append(QStringLiteral("2 8")); // Neon
0064         hulllist.append(QStringLiteral("2 8 1"));
0065         hulllist.append(QStringLiteral("2 8 2"));
0066         hulllist.append(QStringLiteral("2 8 3"));
0067         hulllist.append(QStringLiteral("2 8 4"));
0068         hulllist.append(QStringLiteral("2 8 5"));
0069         hulllist.append(QStringLiteral("2 8 6"));
0070         hulllist.append(QStringLiteral("2 8 7"));
0071         hulllist.append(QStringLiteral("2 8 8")); // Argon
0072         hulllist.append(QStringLiteral("2 8 8 1"));
0073         hulllist.append(QStringLiteral("2 8 8 2")); // Calcium
0074         hulllist.append(QStringLiteral("2 8 9 2"));
0075         hulllist.append(QStringLiteral("2 8 10 2"));
0076         hulllist.append(QStringLiteral("2 8 11 2"));
0077         hulllist.append(QStringLiteral("2 8 13 1"));
0078         hulllist.append(QStringLiteral("2 8 13 2")); // Manganese
0079         hulllist.append(QStringLiteral("2 8 14 2"));
0080         hulllist.append(QStringLiteral("2 8 15 2"));
0081         hulllist.append(QStringLiteral("2 8 16 2"));
0082         hulllist.append(QStringLiteral("2 8 18 1")); // Copper
0083         hulllist.append(QStringLiteral("2 8 18 2"));
0084         hulllist.append(QStringLiteral("2 8 18 3"));
0085         hulllist.append(QStringLiteral("2 8 18 4"));
0086         hulllist.append(QStringLiteral("2 8 18 5"));
0087         hulllist.append(QStringLiteral("2 8 18 6"));
0088         hulllist.append(QStringLiteral("2 8 18 7"));
0089         hulllist.append(QStringLiteral("2 8 18 8")); // Krypton
0090         hulllist.append(QStringLiteral("2 8 18 8 1"));
0091         hulllist.append(QStringLiteral("2 8 18 8 2")); // Rubidium
0092         hulllist.append(QStringLiteral("2 8 18 9 2"));
0093         hulllist.append(QStringLiteral("2 8 18 10 2")); // Zirconium
0094         hulllist.append(QStringLiteral("2 8 18 12 1"));
0095         hulllist.append(QStringLiteral("2 8 18 13 1"));
0096         hulllist.append(QStringLiteral("2 8 18 14 1")); // Techneticum
0097         hulllist.append(QStringLiteral("2 8 18 15 1"));
0098         hulllist.append(QStringLiteral("2 8 18 16 1"));
0099         hulllist.append(QStringLiteral("2 8 18 18")); // Palladium
0100         hulllist.append(QStringLiteral("2 8 18 18 1"));
0101         hulllist.append(QStringLiteral("2 8 18 18 2"));
0102         hulllist.append(QStringLiteral("2 8 18 18 3")); // Indium
0103         hulllist.append(QStringLiteral("2 8 18 18 4"));
0104         hulllist.append(QStringLiteral("2 8 18 18 5"));
0105         hulllist.append(QStringLiteral("2 8 18 18 6"));
0106         hulllist.append(QStringLiteral("2 8 18 18 7"));
0107         hulllist.append(QStringLiteral("2 8 18 18 8")); // Xenon
0108         hulllist.append(QStringLiteral("2 8 18 18 8 1")); // Caesium
0109         hulllist.append(QStringLiteral("2 8 18 18 8 2")); // Barium
0110         hulllist.append(QStringLiteral("2 8 18 18 9 2"));
0111         hulllist.append(QStringLiteral("2 8 18 20 8 2")); // Cerium
0112         hulllist.append(QStringLiteral("2 8 18 21 8 2"));
0113         hulllist.append(QStringLiteral("2 8 18 22 8 2"));
0114         hulllist.append(QStringLiteral("2 8 18 23 8 2"));
0115         hulllist.append(QStringLiteral("2 8 18 24 8 2"));
0116         hulllist.append(QStringLiteral("2 8 18 25 8 2"));
0117         hulllist.append(QStringLiteral("2 8 18 25 9 2")); // Gadolinium
0118         hulllist.append(QStringLiteral("2 8 18 27 8 2")); // Terbium
0119         hulllist.append(QStringLiteral("2 8 18 28 8 2"));
0120         hulllist.append(QStringLiteral("2 8 18 29 8 2"));
0121         hulllist.append(QStringLiteral("2 8 18 30 8 2"));
0122         hulllist.append(QStringLiteral("2 8 18 31 8 2"));
0123         hulllist.append(QStringLiteral("2 8 18 32 8 2")); // Ytterbium
0124         hulllist.append(QStringLiteral("2 8 18 32 9 2")); // Lutetium
0125         hulllist.append(QStringLiteral("2 8 18 32 10 2")); // Hafnium
0126         hulllist.append(QStringLiteral("2 8 18 32 11 2"));
0127         hulllist.append(QStringLiteral("2 8 18 32 12 2"));
0128         hulllist.append(QStringLiteral("2 8 18 32 13 2"));
0129         hulllist.append(QStringLiteral("2 8 18 32 14 2"));
0130         hulllist.append(QStringLiteral("2 8 18 32 15 2")); // Irdium
0131         hulllist.append(QStringLiteral("2 8 18 32 17 1"));
0132         hulllist.append(QStringLiteral("2 8 18 32 18 1"));
0133         hulllist.append(QStringLiteral("2 8 18 32 18 2")); // Mercury
0134         hulllist.append(QStringLiteral("2 8 18 32 18 3"));
0135         hulllist.append(QStringLiteral("2 8 18 32 18 4"));
0136         hulllist.append(QStringLiteral("2 8 18 32 18 5"));
0137         hulllist.append(QStringLiteral("2 8 18 32 18 6"));
0138         hulllist.append(QStringLiteral("2 8 18 32 18 7"));
0139         hulllist.append(QStringLiteral("2 8 18 32 18 8")); // Radon
0140         hulllist.append(QStringLiteral("2 8 18 32 18 8 1")); // Francium
0141         hulllist.append(QStringLiteral("2 8 18 32 18 8 2")); // Radium
0142         hulllist.append(QStringLiteral("2 8 18 32 18 9 2")); // Actinium
0143         hulllist.append(QStringLiteral("2 8 18 32 20 8 2")); // Thorium
0144         hulllist.append(QStringLiteral("2 8 18 32 21 8 2"));
0145         hulllist.append(QStringLiteral("2 8 18 32 22 8 2")); // Uran
0146         hulllist.append(QStringLiteral("2 8 18 32 23 8 2"));
0147         hulllist.append(QStringLiteral("2 8 18 32 24 8 2")); // Plutonium
0148         hulllist.append(QStringLiteral("2 8 18 32 25 8 2"));
0149         hulllist.append(QStringLiteral("2 8 18 32 26 8 2")); // Cm
0150         hulllist.append(QStringLiteral("2 8 18 32 27 8 2"));
0151         hulllist.append(QStringLiteral("2 8 18 32 28 8 2")); // Cf
0152         hulllist.append(QStringLiteral("2 8 18 32 29 8 2"));
0153         hulllist.append(QStringLiteral("2 8 18 32 30 8 2")); // Fm
0154         hulllist.append(QStringLiteral("2 8 18 32 31 8 2"));
0155         hulllist.append(QStringLiteral("2 8 18 32 32 8 2")); // Nobelium
0156         hulllist.append(QStringLiteral("2 8 18 32 32 9 2")); // Lawrencium
0157         hulllist.append(QStringLiteral("2 8 18 32 32 10 2"));
0158         hulllist.append(QStringLiteral("2 8 18 32 32 11 2")); // Dubnium (105)
0159         hulllist.append(QStringLiteral("2 8 18 32 32 12 2"));
0160         hulllist.append(QStringLiteral("2 8 18 32 32 13 2")); // Bohrium
0161         hulllist.append(QStringLiteral("2 8 18 32 32 14 2"));
0162         hulllist.append(QStringLiteral("2 8 18 32 32 15 2")); // Mt
0163         hulllist.append(QStringLiteral("2 8 18 32 32 16 2")); // Darmstadtium
0164         hulllist.append(QStringLiteral("2 8 18 32 32 17 2")); // Roentgenium
0165     }
0166 }
0167 
0168 void OrbitsWidget::setElementNumber(int num)
0169 {
0170     Elemno = num;
0171 
0172     numOfElectrons.clear();
0173     QString o;
0174     if ((Elemno > 0) && (Elemno <= hulllist.count())) {
0175         o = hulllist[Elemno - 1];
0176     }
0177 
0178     foreach (const QString &str, o.split(' ', Qt::SkipEmptyParts))
0179         numOfElectrons.append(str.toInt());
0180 
0181     m_electronConf->setMinimumWidth(width());
0182     // setting the electronic configuration in the label.
0183     m_electronConf->setText(KalziumUtils::prettyUnit(KalziumDataObject::instance()->element(Elemno), ChemicalDataObject::electronicConfiguration));
0184     update();
0185 }
0186 
0187 void OrbitsWidget::paintEvent(QPaintEvent *)
0188 {
0189     QPainter DC;
0190     DC.begin(this);
0191     DC.setRenderHint(QPainter::Antialiasing, true);
0192 
0193     int min_size = qMin(width(), height());
0194     int min_delta = min_size / 10;
0195 
0196     const int num = numOfElectrons.count();
0197     if (num == 0) {
0198         DC.drawText(QPoint(width() / 3, height() / 3), i18n("Unknown Electron Distribution"));
0199         return; // no orbits, do nothing
0200     }
0201 
0202     // make sure the biggest orbit fits in the widget
0203     // diameter
0204     int d = min_size - 2 * min_delta;
0205 
0206     // the radius of the current orbit
0207     int r = d / 2;
0208 
0209     // the radius of an 'electron'
0210     int r_electron = r / 20;
0211 
0212     // difference to the previous circle
0213     int ddx = r / num;
0214 
0215     QList<int>::Iterator it = numOfElectrons.end();
0216     --it;
0217 
0218     for (int i = 0; i < num; ++i) {
0219         int mx = min_delta + ddx * i; // the x-coordinate for the current circle
0220         int my = min_delta + ddx * i; // the y-coordinate for the current circle
0221 
0222         DC.setBrush(Qt::NoBrush);
0223         DC.setPen(Qt::black);
0224 
0225         // draw the big ellipses in concentric circles
0226         DC.drawEllipse(mx, my, d, d);
0227 
0228         DC.setPen(Qt::NoPen);
0229 
0230         for (int e = 0; e < *it; ++e) {
0231             int x = (int)translateToDX(d / 2.0, (double)e, *it);
0232             int y = (int)translateToDY(d / 2.0, (double)e, *it);
0233 
0234             // Creating a gradient for the current electron.
0235             QRadialGradient grad(QPointF(x + mx + d / 2 - r_electron / 2, y + my + d / 2 - r_electron / 2), r_electron);
0236             grad.setColorAt(0, Qt::white);
0237             grad.setColorAt(0.2, Qt::yellow);
0238             grad.setColorAt(1, QColor(Qt::yellow).darker());
0239             DC.setBrush(QBrush(grad));
0240 
0241             DC.drawEllipse(x + mx + d / 2 - r_electron, y + my + d / 2 - r_electron, 2 * r_electron, 2 * r_electron);
0242         }
0243         --it;
0244         d -= 2 * ddx;
0245     }
0246 }