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 <QSGSimpleTextureNode>
0007 #include <QImage>
0008 
0009 #include <QQuickWindow>
0010 #include "skymaplite.h"
0011 #include "ksplanetbase.h"
0012 #include "Options.h"
0013 #include "projections/projector.h"
0014 #include "../rootnode.h"
0015 
0016 #include "planetnode.h"
0017 #include "nodes/pointnode.h"
0018 #include "labelnode.h"
0019 
0020 PlanetNode::PlanetNode(KSPlanetBase *pb, RootNode *parentNode, LabelsItem::label_t labelType)
0021     : SkyNode(pb), m_planetPic(new QSGSimpleTextureNode), m_planetOpacity(new SkyOpacityNode)
0022 {
0023     // Draw them as bright stars of appropriate color instead of images
0024     char spType;
0025     //FIXME: do these need i18n?
0026     if (pb->name() == i18n("Mars"))
0027     {
0028         spType = 'K';
0029     }
0030     else if (pb->name() == i18n("Jupiter") || pb->name() == i18n("Mercury") || pb->name() == i18n("Saturn"))
0031     {
0032         spType = 'F';
0033     }
0034     else
0035     {
0036         spType = 'B';
0037     }
0038 
0039     m_point = new PointNode(parentNode, spType);
0040     appendChildNode(m_point);
0041     appendChildNode(m_planetOpacity);
0042 
0043     //Add planet to opacity node so that we could hide the planet
0044     m_planetOpacity->appendChildNode(m_planetPic);
0045     m_planetPic->setTexture(
0046         SkyMapLite::Instance()->window()->createTextureFromImage(pb->image(), QQuickWindow::TextureCanUseAtlas));
0047     m_planetPic->setOwnsTexture(true);
0048     m_label = parentNode->labelsItem()->addLabel(pb, labelType);
0049 }
0050 
0051 void PlanetNode::update()
0052 {
0053     KSPlanetBase *planet  = static_cast<KSPlanetBase *>(skyObject());
0054     const Projector *proj = projector();
0055 
0056     if (!proj->checkVisibility(planet))
0057     {
0058         hide();
0059         return;
0060     }
0061 
0062     bool visible = false;
0063     QPointF pos  = proj->toScreen(planet, true, &visible);
0064 
0065     if (!visible || !proj->onScreen(pos))
0066     {
0067         hide();
0068         return;
0069     }
0070 
0071     //Set new position of the label
0072     m_label->setLabelPos(pos);
0073 
0074     float fakeStarSize = (10.0 + log10(Options::zoomFactor()) - log10(MINZOOM)) * (10 - planet->mag()) / 10;
0075     if (fakeStarSize > 15.0)
0076         fakeStarSize = 15.0;
0077 
0078     float size = planet->angSize() * dms::PI * Options::zoomFactor() / 10800.0;
0079     if (size < fakeStarSize && planet->name() != "Sun" && planet->name() != "Moon")
0080     {
0081         setPointSize(fakeStarSize);
0082         changePos(pos);
0083         showPoint();
0084     }
0085     else
0086     {
0087         float sizemin = 1.0;
0088         if (planet->name() == "Sun" || planet->name() == "Moon")
0089             sizemin = 8.0;
0090 
0091         float size = planet->angSize() * dms::PI * Options::zoomFactor() / 10800.0;
0092         if (size < sizemin)
0093             size = sizemin;
0094         //Options::showPlanetImages() &&
0095         if (!planet->image().isNull())
0096         {
0097             //Because Saturn has rings, we inflate its image size by a factor 2.5
0098             if (planet->name() == "Saturn")
0099                 size = int(2.5 * size);
0100             // Scale size exponentially so it is visible at large zooms
0101             else if (planet->name() == "Pluto")
0102                 size = int(size * exp(1.5 * size));
0103 
0104             setPlanetPicSize(size);
0105             showPlanetPic();
0106             changePos(pos);
0107         }
0108         else //Otherwise, draw a simple circle. Do we need it?
0109         {
0110             //drawEllipse( pos, size, size );
0111         }
0112     }
0113 }
0114 
0115 void PlanetNode::setPointSize(float size)
0116 {
0117     m_point->setSize(size);
0118 }
0119 
0120 void PlanetNode::setPlanetPicSize(float size)
0121 {
0122     m_planetPic->setRect(QRect(0, 0, size, size));
0123     markDirty(QSGNode::DirtyGeometry);
0124 }
0125 
0126 void PlanetNode::showPoint()
0127 {
0128     m_planetOpacity->hide();
0129     m_point->show();
0130 }
0131 
0132 void PlanetNode::showPlanetPic()
0133 {
0134     m_planetOpacity->show();
0135     m_point->hide();
0136 }
0137 
0138 void PlanetNode::hide()
0139 {
0140     m_planetOpacity->hide();
0141     m_point->hide();
0142     m_label->hide();
0143 }
0144 
0145 void PlanetNode::changePos(QPointF pos)
0146 {
0147     QSizeF size;
0148     //Check the bug with planet
0149     QMatrix4x4 m(1, 0, 0, pos.x(), 0, 1, 0, pos.y(), 0, 0, 1, 0, 0, 0, 0, 1);
0150 
0151     if (m_planetOpacity->visible())
0152     {
0153         size = m_planetPic->rect().size();
0154         //Matrix has to be rotated between assigning x and y and translating it by the half
0155         //of size of the planet. Otherwise the image will don't rotate at all or rotate around
0156         //the top-left corner
0157         m.rotate(projector()->findPA(skyObject(), pos.x(), pos.y()), 0, 0, 1);
0158     }
0159     else
0160     {
0161         size = m_point->size();
0162     }
0163 
0164     m.translate(-0.5 * size.width(), -0.5 * size.height());
0165 
0166     setMatrix(m);
0167     markDirty(QSGNode::DirtyMatrix);
0168 }