File indexing completed on 2024-04-28 03:44:25

0001 /*
0002     SPDX-FileCopyrightText: 2016 Artem Fedoskin <afedoskin3@gmail.com>
0003     SPDX-License-Identifier: GPL-2.0-or-later
0004 */
0005 
0006 #include "dsosymbolnode.h"
0007 
0008 #include "deepskyobject.h"
0009 #include "Options.h"
0010 #include "nodes/ellipsenode.h"
0011 
0012 #include <QSGFlatColorMaterial>
0013 
0014 void SymbolNode::updateSymbol(float x, float y, float e, float size)
0015 {
0016     zoom  = Options::zoomFactor();
0017     x     = 0;
0018     y     = 0;
0019     isize = int(size);
0020 
0021     dx1 = -0.5 * size;
0022     dx2 = 0.5 * size;
0023     dy1 = -1.0 * e * size / 2.;
0024     dy2 = e * size / 2.;
0025     x1  = x + dx1;
0026     x2  = x + dx2;
0027     y1  = y + dy1;
0028     y2  = y + dy2;
0029 
0030     dxa = -size / 4.;
0031     dxb = size / 4.;
0032     dya = -1.0 * e * size / 4.;
0033     dyb = e * size / 4.;
0034     xa  = x + dxa;
0035     xb  = x + dxb;
0036     ya  = y + dya;
0037     yb  = y + dyb;
0038 }
0039 
0040 StarSymbol::StarSymbol(const QColor &color) : m_ellipse(new EllipseNode(color))
0041 {
0042     appendChildNode(m_ellipse);
0043 }
0044 
0045 void StarSymbol::updateSymbol(float x, float y, float e, float size)
0046 {
0047     SymbolNode::updateSymbol(x, y, e, size);
0048     if (size < 2.)
0049         size = 2.;
0050     if (Options::useAntialias())
0051         m_ellipse->updateGeometry(0, 0, size, e * size, false);
0052     else
0053         m_ellipse->updateGeometry(0, 0, int(size / 2), int(size / 2), false);
0054 }
0055 
0056 AsterismSymbol::AsterismSymbol(const QColor &color)
0057 {
0058     e1 = new EllipseNode(color);
0059     e2 = new EllipseNode(color);
0060     e3 = new EllipseNode(color);
0061     e4 = new EllipseNode(color);
0062     e5 = new EllipseNode(color);
0063     e6 = new EllipseNode(color);
0064     e7 = new EllipseNode(color);
0065     e8 = new EllipseNode(color);
0066     appendChildNode(e1);
0067     appendChildNode(e2);
0068     appendChildNode(e3);
0069     appendChildNode(e4);
0070     appendChildNode(e5);
0071     appendChildNode(e6);
0072     appendChildNode(e7);
0073     appendChildNode(e8);
0074 }
0075 
0076 void AsterismSymbol::updateSymbol(float x, float y, float e, float size)
0077 {
0078     SymbolNode::updateSymbol(x, y, e, size);
0079     psize = 2.;
0080     if (size > 50.)
0081         psize *= 2.;
0082     if (size > 100.)
0083         psize *= 2.;
0084 
0085     e1->updateGeometry(xa, y1, psize, psize, true);
0086     e2->updateGeometry(xb, y1, psize, psize, true);
0087     e3->updateGeometry(xa, y2, psize, psize, true);
0088     e4->updateGeometry(xb, y2, psize, psize, true);
0089     e5->updateGeometry(x1, ya, psize, psize, true);
0090     e6->updateGeometry(x1, yb, psize, psize, true);
0091     e7->updateGeometry(x2, ya, psize, psize, true);
0092     e8->updateGeometry(x2, yb, psize, psize, true);
0093 }
0094 
0095 GlobularClusterSymbol::GlobularClusterSymbol(const QColor &color) : e1(new EllipseNode(color))
0096 {
0097     appendChildNode(e1);
0098 
0099     lines = new QSGGeometryNode;
0100     appendChildNode(lines);
0101 
0102     QSGGeometry *geometry = new QSGGeometry(QSGGeometry::defaultAttributes_Point2D(), 0);
0103     geometry->setDrawingMode(GL_LINES);
0104     geometry->allocate(4);
0105 
0106     lines->setGeometry(geometry);
0107     lines->setFlag(QSGNode::OwnsGeometry);
0108 
0109     QSGFlatColorMaterial *material = new QSGFlatColorMaterial;
0110     material->setColor(color);
0111     lines->setOpaqueMaterial(material);
0112     lines->setFlag(QSGNode::OwnsMaterial);
0113 }
0114 
0115 void GlobularClusterSymbol::updateSymbol(float x, float y, float e, float size)
0116 {
0117     SymbolNode::updateSymbol(x, y, e, size);
0118 
0119     if (size < 2.)
0120         size = 2.;
0121     e1->updateGeometry(0, 0, size, e * size, false);
0122 
0123     QSGGeometry::Point2D *vertex = lines->geometry()->vertexDataAsPoint2D();
0124     //First line
0125     vertex[0].set(dx1, 0);
0126     vertex[1].set(dx2, 0);
0127 
0128     //Second line
0129     vertex[2].set(0, dy1);
0130     vertex[3].set(0, dy2);
0131 
0132     lines->markDirty(QSGNode::DirtyGeometry);
0133 }
0134 
0135 DarkNebulaSymbol::DarkNebulaSymbol(const QColor &color)
0136 {
0137     lines = new QSGGeometryNode;
0138     appendChildNode(lines);
0139 
0140     QSGGeometry *geometry = new QSGGeometry(QSGGeometry::defaultAttributes_Point2D(), 0);
0141     geometry->setDrawingMode(GL_LINES);
0142     geometry->allocate(8);
0143 
0144     lines->setGeometry(geometry);
0145     lines->setFlag(QSGNode::OwnsGeometry);
0146 
0147     QSGFlatColorMaterial *material = new QSGFlatColorMaterial;
0148     material->setColor(color);
0149     lines->setOpaqueMaterial(material);
0150     lines->setFlag(QSGNode::OwnsMaterial);
0151 }
0152 
0153 void DarkNebulaSymbol::updateSymbol(float x, float y, float e, float size)
0154 {
0155     SymbolNode::updateSymbol(x, y, e, size);
0156 
0157     QSGGeometry::Point2D *vertex = lines->geometry()->vertexDataAsPoint2D();
0158     //First line
0159     vertex[0].set(dx1, dy1);
0160     vertex[1].set(dx2, dy1);
0161 
0162     //Second line
0163     vertex[2].set(dx2, dy1);
0164     vertex[3].set(dx2, dy2);
0165 
0166     //Third line
0167     vertex[4].set(dx2, dy2);
0168     vertex[5].set(dx1, dy2);
0169 
0170     //Fourth line
0171     vertex[6].set(dx1, dy2);
0172     vertex[7].set(dx1, dy1);
0173 
0174     lines->markDirty(QSGNode::DirtyGeometry);
0175 }
0176 
0177 PlanetaryNebulaSymbol::PlanetaryNebulaSymbol(const QColor &color)
0178 {
0179     e1 = new EllipseNode(color);
0180     appendChildNode(e1);
0181 
0182     lines = new QSGGeometryNode;
0183     appendChildNode(lines);
0184 
0185     QSGGeometry *geometry = new QSGGeometry(QSGGeometry::defaultAttributes_Point2D(), 0);
0186     geometry->setDrawingMode(GL_LINES);
0187     geometry->allocate(8);
0188 
0189     lines->setGeometry(geometry);
0190     lines->setFlag(QSGNode::OwnsGeometry);
0191 
0192     QSGFlatColorMaterial *material = new QSGFlatColorMaterial;
0193     material->setColor(color);
0194     lines->setOpaqueMaterial(material);
0195     lines->setFlag(QSGNode::OwnsMaterial);
0196 }
0197 
0198 void PlanetaryNebulaSymbol::updateSymbol(float x, float y, float e, float size)
0199 {
0200     SymbolNode::updateSymbol(x, y, e, size);
0201 
0202     if (size < 2.)
0203         size = 2.;
0204 
0205     e1->updateGeometry(0, 0, size, e * size, false);
0206 
0207     QSGGeometry::Point2D *vertex = lines->geometry()->vertexDataAsPoint2D();
0208     //First line
0209     vertex[0].set(0., dy1);
0210     vertex[1].set(0., dy1 - e * size / 2.);
0211 
0212     //Second line
0213     vertex[2].set(0., dy2);
0214     vertex[3].set(0., dy2 + e * size / 2.);
0215 
0216     //Third line
0217     vertex[4].set(dx1, 0.);
0218     vertex[5].set(dx1 - size / 2., 0.);
0219 
0220     //Fourth line
0221     vertex[6].set(dx2, 0.);
0222     vertex[7].set(dx2 + size / 2., 0.);
0223 
0224     lines->markDirty(QSGNode::DirtyGeometry);
0225 }
0226 
0227 SupernovaRemnantSymbol::SupernovaRemnantSymbol(const QColor &color)
0228 {
0229     lines = new QSGGeometryNode;
0230     appendChildNode(lines);
0231 
0232     QSGGeometry *geometry = new QSGGeometry(QSGGeometry::defaultAttributes_Point2D(), 0);
0233     geometry->setDrawingMode(GL_LINES);
0234     geometry->allocate(8);
0235 
0236     lines->setGeometry(geometry);
0237     lines->setFlag(QSGNode::OwnsGeometry);
0238 
0239     QSGFlatColorMaterial *material = new QSGFlatColorMaterial;
0240     material->setColor(color);
0241     lines->setOpaqueMaterial(material);
0242     lines->setFlag(QSGNode::OwnsMaterial);
0243 }
0244 
0245 void SupernovaRemnantSymbol::updateSymbol(float x, float y, float e, float size)
0246 {
0247     SymbolNode::updateSymbol(x, y, e, size);
0248 
0249     QSGGeometry::Point2D *vertex = lines->geometry()->vertexDataAsPoint2D();
0250 
0251     //First line
0252     vertex[0].set(0., dy1);
0253     vertex[1].set(dx2, 0.);
0254 
0255     //Second line
0256     vertex[2].set(dx2, 0.);
0257     vertex[3].set(0., dy2);
0258 
0259     //Third line
0260     vertex[4].set(0., dy2);
0261     vertex[5].set(dx1, 0.);
0262 
0263     //Fourth line
0264     vertex[6].set(dx1, 0.);
0265     vertex[7].set(0., dy1);
0266 
0267     lines->markDirty(QSGNode::DirtyGeometry);
0268 }
0269 
0270 GalaxySymbol::GalaxySymbol(const QColor &color) : e1(new EllipseNode(color))
0271 {
0272     appendChildNode(e1);
0273 }
0274 
0275 void GalaxySymbol::updateSymbol(float x, float y, float e, float size)
0276 {
0277     SymbolNode::updateSymbol(x, y, e, size);
0278 
0279     if (size < 1. && zoom > 20 * MINZOOM)
0280         size = 3.; //force ellipse above zoomFactor 20
0281     if (size < 1. && zoom > 5 * MINZOOM)
0282         size = 1.; //force points above zoomFactor 5
0283     if (size > 2.)
0284     {
0285         e1->updateGeometry(0, 0, size, e * size, false);
0286     }
0287     else if (size > 0.)
0288     {
0289         e1->updateGeometry(0, 0, 1, 1, false);
0290     }
0291 }
0292 
0293 GalaxyClusterSymbol::GalaxyClusterSymbol(const QColor &color) : lines(new QSGGeometryNode)
0294 {
0295     QSGGeometry *geometry = new QSGGeometry(QSGGeometry::defaultAttributes_Point2D(), 0);
0296     geometry->setDrawingMode(GL_LINES);
0297     geometry->allocate(32);
0298 
0299     lines->setGeometry(geometry);
0300     lines->setFlag(QSGNode::OwnsGeometry);
0301 
0302     QSGFlatColorMaterial *material = new QSGFlatColorMaterial;
0303     material->setColor(color);
0304     lines->setOpaqueMaterial(material);
0305     lines->setFlag(QSGNode::OwnsMaterial);
0306 
0307     appendChildNode(lines);
0308 }
0309 
0310 void GalaxyClusterSymbol::updateSymbol(float x, float y, float e, float size)
0311 {
0312     SymbolNode::updateSymbol(x, y, e, size);
0313 
0314     psize = 1.;
0315     if (size > 50.)
0316         psize *= 2.;
0317 
0318     QSGGeometry::Point2D *vertex = lines->geometry()->vertexDataAsPoint2D();
0319 
0320     vertex[0].set(xa - psize, y1);
0321     vertex[1].set(xa + psize, y1);
0322     vertex[2].set(xa, y1 - psize);
0323     vertex[3].set(xa, y1 + psize);
0324     vertex[4].set(xb - psize, y1);
0325     vertex[5].set(xb + psize, y1);
0326     vertex[6].set(xb, y1 - psize);
0327     vertex[7].set(xb, y1 + psize);
0328     vertex[8].set(xa - psize, y2);
0329     vertex[9].set(xa + psize, y2);
0330     vertex[10].set(xa, y2 - psize);
0331     vertex[11].set(xa, y2 + psize);
0332     vertex[12].set(xb - psize, y2);
0333     vertex[13].set(xb + psize, y2);
0334     vertex[14].set(xb, y2 - psize);
0335     vertex[15].set(xb, y2 + psize);
0336     vertex[16].set(x1 - psize, ya);
0337     vertex[17].set(x1 + psize, ya);
0338     vertex[18].set(x1, ya - psize);
0339     vertex[19].set(x1, ya + psize);
0340     vertex[20].set(x1 - psize, yb);
0341     vertex[21].set(x1 + psize, yb);
0342     vertex[22].set(x1, yb - psize);
0343     vertex[23].set(x1, yb + psize);
0344     vertex[24].set(x2 - psize, ya);
0345     vertex[25].set(x2 + psize, ya);
0346     vertex[26].set(x2, ya - psize);
0347     vertex[27].set(x2, ya + psize);
0348     vertex[28].set(x2 - psize, yb);
0349     vertex[29].set(x2 + psize, yb);
0350     vertex[30].set(x2, yb - psize);
0351     vertex[31].set(x2, yb + psize);
0352 
0353     lines->markDirty(QSGNode::DirtyGeometry);
0354 }
0355 
0356 DSOSymbolNode::DSOSymbolNode(DeepSkyObject *skyObject, const QColor &color)
0357     : m_color(color), m_dso(skyObject)
0358 {
0359 }
0360 
0361 void DSOSymbolNode::initSymbol()
0362 {
0363     if (!m_symbol)
0364     {
0365         int type = m_dso->type();
0366         switch (type)
0367         {
0368             case 0:
0369             case 1:
0370                 //catalog star
0371                 m_symbol = new StarSymbol(m_color);
0372                 break;
0373             case 3:  //Open cluster; draw circle of points
0374             case 13: // Asterism
0375                 m_symbol = new AsterismSymbol(m_color);
0376                 break;
0377             case 4: //Globular Cluster
0378                 m_symbol = new GlobularClusterSymbol(m_color);
0379                 m_rotate = true;
0380                 break;
0381             case 5:  //Gaseous Nebula
0382             case 15: // Dark Nebula
0383                 m_symbol = new DarkNebulaSymbol(m_color);
0384                 m_rotate = true;
0385                 break;
0386             case 6: //Planetary Nebula
0387                 m_symbol = new PlanetaryNebulaSymbol(m_color);
0388                 m_rotate = true;
0389                 break;
0390             case 7: //Supernova remnant
0391                 m_symbol = new SupernovaRemnantSymbol(m_color);
0392                 m_rotate = true;
0393                 break;
0394             case 8:  //Galaxy
0395             case 16: // Quasar
0396                 m_symbol = new GalaxySymbol(m_color);
0397                 m_rotate = true;
0398                 break;
0399             case 14: // Galaxy cluster - draw a circle of + marks
0400                 m_symbol = new GalaxyClusterSymbol(m_color);
0401                 m_rotate = true;
0402                 break;
0403             default:
0404                 break;
0405         }
0406         if (m_symbol)
0407             addChildNode(m_symbol);
0408     }
0409 }
0410 
0411 void DSOSymbolNode::changePos(const QPointF &pos, float positionangle)
0412 {
0413     QMatrix4x4 m(1, 0, 0, pos.x(), 0, 1, 0, pos.y(), 0, 0, 1, 0, 0, 0, 0, 1);
0414     //FIXME: this is probably incorrect (inherited from drawDeepSkyImage())
0415     if (m_rotate)
0416     {
0417         m.rotate(positionangle, 0, 0, 1);
0418     }
0419 
0420     setMatrix(m);
0421     markDirty(QSGNode::DirtyMatrix);
0422 }
0423 
0424 void DSOSymbolNode::update(float size, const QPointF &pos, float positionangle)
0425 {
0426     initSymbol();
0427 
0428     if (m_symbol)
0429     {
0430         m_symbol->updateSymbol(pos.x(), pos.y(), m_dso->e(), size);
0431         show();
0432         changePos(pos, positionangle);
0433     }
0434     else
0435     {
0436         qDebug() << "Symbol for object " << m_dso->name() << " wasn't created. Check DSOSymbolNode::initSymbol()";
0437     }
0438 }