File indexing completed on 2024-04-14 03:42:50

0001 /*
0002     SPDX-FileCopyrightText: 2016 Artem Fedoskin <afedoskin3@gmail.com>
0003     SPDX-License-Identifier: GPL-2.0-or-later
0004 */
0005 
0006 #include "staritem.h"
0007 
0008 #include "deepstaritem.h"
0009 #include "labelsitem.h"
0010 #include "Options.h"
0011 #include "rootnode.h"
0012 #include "skymesh.h"
0013 #include "skyopacitynode.h"
0014 #include "starblockfactory.h"
0015 #include "starcomponent.h"
0016 #include "htmesh/MeshIterator.h"
0017 #include "projections/projector.h"
0018 #include "skynodes/pointsourcenode.h"
0019 #include "skynodes/trixelnode.h"
0020 
0021 #include <QLinkedList>
0022 
0023 StarItem::StarItem(StarComponent *starComp, RootNode *rootNode)
0024     : SkyItem(LabelsItem::label_t::STAR_LABEL, rootNode), m_starComp(starComp), m_stars(new SkyOpacityNode),
0025       m_deepStars(new SkyOpacityNode), m_starLabels(rootNode->labelsItem()->getLabelNode(labelType()))
0026 
0027 {
0028     StarIndex *trixels = m_starComp->m_starIndex.get();
0029 
0030     appendChildNode(m_stars);
0031 
0032     //Test
0033     Options::setShowStarMagnitudes(false);
0034     Options::setShowStarNames(true);
0035 
0036     for (int i = 0; i < trixels->size(); ++i)
0037     {
0038         StarList *skyList  = trixels->at(i);
0039         TrixelNode *trixel = new TrixelNode(i);
0040         m_stars->appendChildNode(trixel);
0041 
0042         for (int c = 0; c < skyList->size(); ++c)
0043         {
0044             StarObject *star = skyList->at(c);
0045             if (star)
0046             {
0047                 trixel->m_nodes.append(QPair<SkyObject *, SkyNode *>(star, 0));
0048             }
0049         }
0050     }
0051 
0052     appendChildNode(m_deepStars);
0053 
0054     QVector<DeepStarComponent *> deepStars = m_starComp->m_DeepStarComponents;
0055     int deepSize                           = deepStars.size();
0056 
0057     for (int i = 0; i < deepSize; ++i)
0058     {
0059         DeepStarItem *deepStar = new DeepStarItem(deepStars[i], rootNode);
0060         rootNode->removeChildNode(deepStar);
0061         m_deepStars->appendChildNode(deepStar);
0062     }
0063 
0064     m_skyMesh          = SkyMesh::Instance();
0065     m_StarBlockFactory = StarBlockFactory::Instance();
0066 }
0067 
0068 void StarItem::update()
0069 {
0070     if (!m_starComp->selected())
0071     {
0072         hide();
0073         return;
0074     }
0075     show();
0076 
0077     SkyMapLite *map  = SkyMapLite::Instance();
0078     KStarsData *data = KStarsData::Instance();
0079 
0080     bool checkSlewing = (map->isSlewing() && Options::hideOnSlew());
0081     bool hideLabel    = checkSlewing || !(Options::showStarMagnitudes() || Options::showStarNames());
0082     if (hideLabel)
0083         hideLabels();
0084 
0085     //shortcuts to inform whether to draw different objects
0086     bool hideFaintStars = checkSlewing && Options::hideStars();
0087     double hideStarsMag = Options::magLimitHideStar();
0088     bool reIndex        = m_starComp->reindex(data->updateNum());
0089 
0090     double lgmin = log10(MINZOOM);
0091     double lgmax = log10(MAXZOOM);
0092     double lgz   = log10(Options::zoomFactor());
0093 
0094     double maglim;
0095     double m_zoomMagLimit; //Check it later. Needed for labels
0096     m_zoomMagLimit = maglim = StarComponent::zoomMagnitudeLimit();
0097     map->setSizeMagLim(m_zoomMagLimit);
0098 
0099     double labelMagLim = Options::starLabelDensity() / 5.0;
0100     labelMagLim += (12.0 - labelMagLim) * (lgz - lgmin) / (lgmax - lgmin);
0101     if (labelMagLim > 8.0)
0102         labelMagLim = 8.0;
0103 
0104     //Calculate sizeMagLim
0105     // Old formula:
0106     //    float sizeMagLim = ( 2.000 + 2.444 * Options::memUsage() / 10.0 ) * ( lgz - lgmin ) + 5.8;
0107 
0108     // Using the maglim to compute the sizes of stars reduces
0109     // discernability between brighter and fainter stars at high zoom
0110     // levels. To fix that, we use an "arbitrary" constant in place of
0111     // the variable star density.
0112     // Not using this formula now.
0113     //    float sizeMagLim = 4.444 * ( lgz - lgmin ) + 5.0;
0114 
0115     /*float sizeMagLim = zoomMagnitudeLimit();
0116     if( sizeMagLim > faintMagnitude() * ( 1 - 1.5/16 ) )
0117         sizeMagLim = faintMagnitude() * ( 1 - 1.5/16 );
0118     skyp->setSizeMagLimit(sizeMagLim);*/
0119 
0120     //Loop for drawing star images
0121 
0122     float radius = map->projector()->fov();
0123     if (radius > 90.0)
0124         radius = 90.0;
0125 
0126     m_skyMesh->inDraw(true);
0127 
0128     SkyPoint *focus = map->focus();
0129     m_skyMesh->aperture(focus, radius + 1.0, DRAW_BUF); // divide by 2 for testing
0130 
0131     MeshIterator region(m_skyMesh, DRAW_BUF);
0132 
0133     // If we are hiding faint stars, then maglim is really the brighter of hideStarsMag and maglim
0134     if (hideFaintStars && maglim > hideStarsMag)
0135         maglim = hideStarsMag;
0136 
0137     m_StarBlockFactory->drawID = m_skyMesh->drawID();
0138 
0139     int regionID = -1;
0140     if (region.hasNext())
0141     {
0142         regionID = region.next();
0143     }
0144 
0145     int trixelID = 0;
0146 
0147     QSGNode *firstTrixel = m_stars->firstChild();
0148     TrixelNode *trixel   = static_cast<TrixelNode *>(firstTrixel);
0149 
0150     QSGNode *firstLabel = m_starLabels->firstChild();
0151     TrixelNode *label   = static_cast<TrixelNode *>(firstLabel);
0152 
0153     StarIndex *index = m_starComp->m_starIndex.get();
0154 
0155     if (reIndex)
0156         rootNode()->labelsItem()->deleteLabels(labelType());
0157 
0158     const Projector *projector = SkyMapLite::Instance()->projector();
0159 
0160     double delLim = SkyMapLite::deleteLimit();
0161 
0162     while (trixel != 0)
0163     {
0164         if (reIndex)
0165         {
0166             StarList *skyList = index->at(trixelID);
0167 
0168             QSGNode *n = trixel->firstChild();
0169 
0170             //Delete nodes
0171             while (n != 0)
0172             {
0173                 QSGNode *c = n;
0174                 n          = n->nextSibling();
0175 
0176                 trixel->removeChildNode(c);
0177                 delete c;
0178             }
0179 
0180             //Delete all pairs that represent stars
0181             trixel->m_nodes.clear();
0182 
0183             for (int c = 0; c < skyList->size(); ++c)
0184             {
0185                 StarObject *star = skyList->at(c);
0186                 if (star)
0187                 {
0188                     //Add new pair with reindexed star
0189                     trixel->m_nodes.append(QPair<SkyObject *, SkyNode *>(star, 0));
0190                 }
0191             }
0192         }
0193 
0194         if (trixelID != regionID)
0195         {
0196             trixel->hide();
0197             label->hide();
0198 
0199             if (trixel->hideCount() > delLim)
0200             {
0201                 trixel->deleteAllChildNodes();
0202             }
0203         }
0204         else
0205         {
0206             trixel->show();
0207             label->show();
0208 
0209             if (region.hasNext())
0210             {
0211                 regionID = region.next();
0212             }
0213 
0214             QLinkedList<QPair<SkyObject *, SkyNode *>> *nodes = &trixel->m_nodes;
0215             QLinkedList<QPair<SkyObject *, SkyNode *>>::iterator i = nodes->begin();
0216             bool hide = false;
0217 
0218             while (i != nodes->end())
0219             {
0220                 bool drawLabel = false;
0221 
0222                 StarObject *starObj = static_cast<StarObject *>((*i).first);
0223                 SkyNode *node       = (*i).second;
0224 
0225                 int mag = starObj->mag();
0226 
0227                 // break loop if maglim is reached
0228                 if (mag > maglim)
0229                     hide = true;
0230                 if (!(hideLabel || mag > labelMagLim))
0231                     drawLabel = true;
0232                 if (starObj->updateID != KStarsData::Instance()->updateID())
0233                     starObj->JITupdate();
0234 
0235                 if (node)
0236                 {
0237                     if (node->hideCount() > delLim || hide)
0238                     {
0239                         trixel->removeChildNode(node);
0240                         delete node;
0241                         *i = QPair<SkyObject *, SkyNode *>((*i).first, 0);
0242                     }
0243                     else
0244                     {
0245                         if (!hide)
0246                         {
0247                             node->update(drawLabel);
0248                         }
0249                         else
0250                         {
0251                             node->hide();
0252                         }
0253                     }
0254                 }
0255                 else
0256                 {
0257                     if (!hide && projector->checkVisibility(starObj))
0258                     {
0259                         QPointF pos;
0260 
0261                         bool visible = false;
0262                         pos          = projector->toScreen(starObj, true, &visible);
0263                         if (visible && projector->onScreen(pos))
0264                         {
0265                             PointSourceNode *point =
0266                                 new PointSourceNode(starObj, rootNode(), LabelsItem::label_t::STAR_LABEL,
0267                                                     starObj->spchar(), starObj->mag(), trixelID);
0268                             trixel->appendChildNode(point);
0269 
0270                             *i = QPair<SkyObject *, SkyNode *>((*i).first, static_cast<SkyNode *>(point));
0271                             point->updatePos(pos, drawLabel);
0272                         }
0273                     }
0274                 }
0275                 ++i;
0276             }
0277         }
0278         trixel = static_cast<TrixelNode *>(trixel->nextSibling());
0279         label  = static_cast<TrixelNode *>(label->nextSibling());
0280 
0281         ++trixelID;
0282     }
0283 
0284     // Draw focusStar if not null
0285     /*if( focusStar ) {
0286         if ( focusStar->updateID != updateID )
0287             focusStar->JITupdate();
0288         float mag = focusStar->mag();
0289         skyp->drawPointSource(focusStar, mag, focusStar->spchar() );
0290     }*/
0291 
0292     // Now draw each of our DeepStarComponents
0293     QSGNode *deep = m_deepStars->firstChild();
0294     while (deep != 0)
0295     {
0296         DeepStarItem *deepStars = static_cast<DeepStarItem *>(deep);
0297         deep                    = deep->nextSibling();
0298         deepStars->update();
0299     }
0300 
0301     QSGNode *n = m_stars->firstChild();
0302     while (n != 0)
0303     {
0304         n = n->nextSibling();
0305     }
0306     m_skyMesh->inDraw(false);
0307 }