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 }