File indexing completed on 2024-03-24 03:47:02
0001 /* 0002 SPDX-FileCopyrightText: 2016 Artem Fedoskin <afedoskin3@gmail.com> 0003 SPDX-License-Identifier: GPL-2.0-or-later 0004 */ 0005 0006 #include "deepskyitem.h" 0007 0008 #include "deepskyobject.h" 0009 #include "deepstaritem.h" 0010 #include "labelsitem.h" 0011 #include "Options.h" 0012 #include "rootnode.h" 0013 #include "skymesh.h" 0014 #include "starblockfactory.h" 0015 #include "starcomponent.h" 0016 #include "htmesh/MeshIterator.h" 0017 #include "projections/projector.h" 0018 #include "skynodes/deepskynode.h" 0019 #include "skynodes/dsosymbolnode.h" 0020 0021 DSOIndexNode::DSOIndexNode(DeepSkyIndex *index, LabelsItem::label_t labelType, QString color) 0022 : m_index(index), m_trixels(new QSGNode), m_labelType(labelType), schemeColor(color) 0023 { 0024 appendChildNode(m_trixels); 0025 } 0026 0027 void DSOIndexNode::hide() 0028 { 0029 SkyOpacityNode::hide(); 0030 SkyMapLite::Instance()->rootNode()->labelsItem()->hideLabels(m_labelType); 0031 } 0032 0033 void DSOIndexNode::show() 0034 { 0035 SkyOpacityNode::show(); 0036 SkyMapLite::Instance()->rootNode()->labelsItem()->showLabels(m_labelType); 0037 } 0038 0039 DSOTrixelNode::DSOTrixelNode(Trixel trixelID) : TrixelNode(trixelID) 0040 { 0041 } 0042 0043 void DSOTrixelNode::deleteAllChildNodes() 0044 { 0045 QLinkedList<QPair<SkyObject *, SkyNode *>>::iterator i = m_nodes.begin(); 0046 0047 while (i != m_nodes.end()) 0048 { 0049 DeepSkyNode *node = static_cast<DeepSkyNode *>((*i).second); 0050 if (node) 0051 { 0052 node->parent()->removeChildNode(node); 0053 delete node->symbol(); 0054 delete node; 0055 0056 *i = QPair<SkyObject *, SkyNode *>((*i).first, 0); 0057 } 0058 ++i; 0059 } 0060 } 0061 0062 DeepSkyItem::DeepSkyItem(DeepSkyComponent *dsoComp, RootNode *rootNode) 0063 : SkyItem(LabelsItem::label_t::DEEP_SKY_LABEL, rootNode), m_dsoComp(dsoComp), m_skyMesh(SkyMesh::Instance()) 0064 { 0065 0066 m_other = new DSOIndexNode(&(m_dsoComp->m_OtherIndex), LabelsItem::label_t::DSO_OTHER_LABEL, "NGCColor"); 0067 appendChildNode(m_other); 0068 0069 QSGNode *n = firstChild(); 0070 0071 while (n != 0) 0072 { 0073 DSOIndexNode *indexNode = static_cast<DSOIndexNode *>(n); 0074 DeepSkyIndex *index = indexNode->m_index; 0075 0076 QMap<int, DeepSkyList *> result; 0077 QHashIterator<int, DeepSkyList *> it(*index); 0078 0079 while (it.hasNext()) 0080 { 0081 it.next(); 0082 result.insert(it.key(), it.value()); 0083 } 0084 0085 QMap<int, DeepSkyList *>::const_iterator i = result.constBegin(); 0086 0087 while (i != result.constEnd()) 0088 { 0089 DeepSkyList *dsoList = i.value(); 0090 0091 DSOTrixelNode *trixel = new DSOTrixelNode(i.key()); 0092 trixel->m_labels = rootNode->labelsItem()->addTrixel(indexNode->m_labelType, i.key()); 0093 0094 indexNode->m_trixels->appendChildNode(trixel); 0095 QSGNode *symbols = new QSGNode; 0096 0097 for (int c = 0; c < dsoList->size(); ++c) 0098 { 0099 DeepSkyObject *dso = dsoList->at(c); 0100 trixel->m_nodes.append(QPair<SkyObject *, SkyNode *>(dso, 0)); 0101 } 0102 0103 trixel->m_symbols = symbols; 0104 trixel->appendChildNode(symbols); 0105 0106 ++i; 0107 } 0108 n = n->nextSibling(); 0109 } 0110 } 0111 0112 void DeepSkyItem::update() 0113 { 0114 if (!m_dsoComp->selected()) 0115 { 0116 hide(); 0117 return; 0118 } 0119 show(); 0120 0121 bool drawFlag; 0122 0123 MeshIterator region(m_skyMesh, DRAW_BUF); 0124 0125 drawFlag = Options::showMessier() && !(Options::hideOnSlew() && Options::hideMessier() && SkyMapLite::IsSlewing()); 0126 0127 updateDeepSkyNode(m_other, drawFlag, ®ion); 0128 } 0129 0130 void DeepSkyItem::updateDeepSkyNode(DSOIndexNode *indexNode, bool drawObject, MeshIterator *region, bool drawImage) 0131 { 0132 if (!(drawObject || drawImage)) 0133 { 0134 indexNode->hide(); 0135 return; 0136 } 0137 0138 indexNode->show(); 0139 0140 SkyMapLite *map = SkyMapLite::Instance(); 0141 const Projector *projector = map->projector(); 0142 KStarsData *data = KStarsData::Instance(); 0143 0144 UpdateID updateID = data->updateID(); 0145 UpdateID updateNumID = data->updateNumID(); 0146 0147 QColor schemeColor = data->colorScheme()->colorNamed(indexNode->schemeColor); 0148 0149 bool m_hideLabels = (map->isSlewing() && Options::hideOnSlew()) || 0150 !(Options::showDeepSkyMagnitudes() || Options::showDeepSkyNames()); 0151 0152 double maglim = Options::magLimitDrawDeepSky(); 0153 bool showUnknownMagObjects = Options::showUnknownMagObjects(); 0154 0155 //adjust maglimit for ZoomLevel 0156 double lgmin = log10(MINZOOM); 0157 double lgmax = log10(MAXZOOM); 0158 double lgz = log10(Options::zoomFactor()); 0159 if (lgz <= 0.75 * lgmax) 0160 maglim -= (Options::magLimitDrawDeepSky() - Options::magLimitDrawDeepSkyZoomOut()) * (0.75 * lgmax - lgz) / 0161 (0.75 * lgmax - lgmin); 0162 0163 double labelMagLim = Options::deepSkyLabelDensity(); 0164 labelMagLim += (Options::magLimitDrawDeepSky() - labelMagLim) * (lgz - lgmin) / (lgmax - lgmin); 0165 if (labelMagLim > Options::magLimitDrawDeepSky()) 0166 labelMagLim = Options::magLimitDrawDeepSky(); 0167 0168 int regionID = 0; 0169 if (region->hasNext()) 0170 { 0171 regionID = region->next(); 0172 } 0173 0174 DSOTrixelNode *trixel = static_cast<DSOTrixelNode *>(indexNode->m_trixels->firstChild()); 0175 double delLim = SkyMapLite::deleteLimit(); 0176 0177 /*Unlike DeepStarItem and StarItem where all trixels are set, in DeepSkyItem number of trixels is different 0178 across the catalogs. We are comparing trixelID and regionID to hide trixels that are not visible and skip 0179 regionIDs that are not present in this catalog*/ 0180 while (trixel != 0) 0181 { 0182 //Hide all trixels that has smaller trixelID than the next visible trixel 0183 if (trixel->trixelID() < regionID) 0184 { 0185 trixel->hide(); 0186 trixel->m_labels->hide(); 0187 0188 if (trixel->hideCount() > delLim) 0189 { 0190 trixel->deleteAllChildNodes(); 0191 } 0192 } 0193 else if (trixel->trixelID() > regionID) 0194 { 0195 /*Keep iterating over regionID if current trixel's trixelID is larger than regionID. If there are no more 0196 visible regions then hide/delete remaining trixels*/ 0197 if (region->hasNext()) 0198 { 0199 regionID = region->next(); 0200 } 0201 else 0202 { 0203 while (trixel != 0) 0204 { 0205 trixel->hide(); 0206 trixel->m_labels->hide(); 0207 0208 if (trixel->hideCount() > delLim) 0209 { 0210 trixel->deleteAllChildNodes(); 0211 } 0212 trixel = static_cast<DSOTrixelNode *>(trixel->nextSibling()); 0213 } 0214 break; 0215 } 0216 continue; 0217 } 0218 else //Current trixelID is equal to regionID meaning that current trixel is visible 0219 { 0220 trixel->show(); 0221 trixel->m_labels->show(); 0222 0223 if (region->hasNext()) 0224 { 0225 regionID = region->next(); 0226 } 0227 0228 QLinkedList<QPair<SkyObject *, SkyNode *>>::iterator i = (&trixel->m_nodes)->begin(); 0229 0230 while (i != (&trixel->m_nodes)->end()) 0231 { 0232 DeepSkyObject *dsoObj = static_cast<DeepSkyObject *>((*i).first); 0233 DeepSkyNode *dsoNode = static_cast<DeepSkyNode *>((*i).second); 0234 0235 if (dsoObj->updateID != updateID) 0236 { 0237 dsoObj->updateID = updateID; 0238 if (dsoObj->updateNumID != updateNumID) 0239 { 0240 dsoObj->updateCoords(data->updateNum()); 0241 } 0242 dsoObj->EquatorialToHorizontal(data->lst(), data->geo()->lat()); 0243 } 0244 0245 float mag = dsoObj->mag(); 0246 float size = dsoObj->a() * dms::PI * Options::zoomFactor() / 10800.0; 0247 0248 //only draw objects if flags set, it's bigger than 1 pixel (unless 0249 //zoom > 2000.), and it's brighter than maglim (unless mag is 0250 //undefined (=99.9) 0251 bool sizeCriterion = (size > 1.0 || Options::zoomFactor() > 2000.); 0252 bool magCriterion = (mag < (float)maglim) || (showUnknownMagObjects && (std::isnan(mag) || mag > FAINTEST_MAGNITUDE)); 0253 0254 bool drawLabel = false; 0255 0256 if (!(m_hideLabels || mag > labelMagLim)) 0257 drawLabel = true; 0258 0259 if (dsoNode) 0260 { 0261 //Delete particular DSONode if its hideCount is larger than the limit 0262 if (dsoNode->hideCount() > delLim) 0263 { 0264 trixel->removeChildNode(dsoNode); 0265 0266 delete dsoNode->symbol(); 0267 delete dsoNode; 0268 0269 *i = QPair<SkyObject *, SkyNode *>((*i).first, 0); 0270 } 0271 else 0272 { 0273 if (sizeCriterion && magCriterion) 0274 { 0275 dsoNode->setColor(schemeColor, trixel); 0276 dsoNode->update(drawImage, drawLabel); 0277 } 0278 else 0279 { 0280 dsoNode->hide(); 0281 } 0282 } 0283 } 0284 else 0285 { 0286 if (sizeCriterion && magCriterion && projector->checkVisibility(dsoObj)) 0287 { 0288 QPointF pos; 0289 0290 bool visible = false; 0291 pos = projector->toScreen(dsoObj, true, &visible); 0292 if (visible && projector->onScreen(pos)) 0293 { 0294 //Create new DeepSkyNode and its symbol if it is currently visible 0295 DSOSymbolNode *dsoSymbol = new DSOSymbolNode(dsoObj, schemeColor); 0296 trixel->m_symbols->appendChildNode(dsoSymbol); 0297 0298 DeepSkyNode *dsoNode = 0299 new DeepSkyNode(dsoObj, dsoSymbol, indexNode->m_labelType, trixel->trixelID()); 0300 trixel->appendChildNode(dsoNode); 0301 0302 *i = QPair<SkyObject *, SkyNode *>((*i).first, static_cast<SkyNode *>(dsoNode)); 0303 dsoNode->update(drawImage, drawLabel, pos); 0304 } 0305 } 0306 } 0307 ++i; 0308 } 0309 } 0310 trixel = static_cast<DSOTrixelNode *>(trixel->nextSibling()); 0311 } 0312 0313 region->reset(); 0314 }