Warning, file /education/kstars/kstars/skycomponents/constellationboundarylines.cpp was not indexed or was modified since last indexation (in which case cross-reference links may be missing, inaccurate or erroneous).
0001 /* 0002 SPDX-FileCopyrightText: 2005 Jason Harris <kstars@30doradus.org> 0003 0004 SPDX-License-Identifier: GPL-2.0-or-later 0005 */ 0006 0007 #include "constellationboundarylines.h" 0008 0009 #include "ksfilereader.h" 0010 #include "kstarsdata.h" 0011 #include "linelist.h" 0012 #include "Options.h" 0013 #include "polylist.h" 0014 #ifdef KSTARS_LITE 0015 #include "skymaplite.h" 0016 #else 0017 #include "skymap.h" 0018 #endif 0019 #include "skypainter.h" 0020 #include "htmesh/MeshIterator.h" 0021 #include "skycomponents/skymapcomposite.h" 0022 0023 #include <QHash> 0024 0025 ConstellationBoundaryLines::ConstellationBoundaryLines(SkyComposite *parent) 0026 : NoPrecessIndex(parent, i18n("Constellation Boundaries")) 0027 { 0028 m_skyMesh = SkyMesh::Instance(); 0029 m_polyIndexCnt = 0; 0030 for (int i = 0; i < m_skyMesh->size(); i++) 0031 { 0032 m_polyIndex.append(std::shared_ptr<PolyListList>(new PolyListList())); 0033 } 0034 0035 KStarsData *data = KStarsData::Instance(); 0036 int verbose = 0; // -1 => create cbounds-$x.idx on stdout 0037 // 0 => normal 0038 const char *fname = "cbounds.dat"; 0039 int flag = 0; 0040 double ra, dec = 0, lastRa, lastDec; 0041 std::shared_ptr<LineList> lineList; 0042 std::shared_ptr<PolyList> polyList; 0043 bool ok = false; 0044 0045 intro(); 0046 0047 // Open the .idx file and skip past the first line 0048 KSFileReader idxReader, *idxFile = nullptr; 0049 QString idxFname = QString("cbounds-%1.idx").arg(SkyMesh::Instance()->level()); 0050 if (idxReader.open(idxFname)) 0051 { 0052 idxReader.readLine(); 0053 idxFile = &idxReader; 0054 } 0055 0056 // now open the file that contains the points 0057 KSFileReader fileReader; 0058 if (!fileReader.open(fname)) 0059 return; 0060 0061 fileReader.setProgress(i18n("Loading Constellation Boundaries"), 13124, 10); 0062 0063 lastRa = lastDec = -1000.0; 0064 0065 while (fileReader.hasMoreLines()) 0066 { 0067 QString line = fileReader.readLine(); 0068 fileReader.showProgress(); 0069 0070 if (line.at(0) == '#') 0071 continue; // ignore comments 0072 if (line.at(0) == ':') // :constellation line 0073 { 0074 if (lineList.get()) 0075 appendLine(lineList); 0076 lineList.reset(); 0077 0078 if (polyList.get()) 0079 appendPoly(polyList, idxFile, verbose); 0080 QString cName = line.mid(1); 0081 polyList.reset(new PolyList(cName)); 0082 if (verbose == -1) 0083 printf(":\n"); 0084 lastRa = lastDec = -1000.0; 0085 continue; 0086 } 0087 0088 // read in the data from the line 0089 ra = line.midRef(0, 12).toDouble(&ok); 0090 if (ok) 0091 dec = line.midRef(13, 12).toDouble(&ok); 0092 if (ok) 0093 flag = line.midRef(26, 1).toInt(&ok); 0094 if (!ok) 0095 { 0096 fprintf(stderr, "%s: conversion error on line: %d\n", fname, fileReader.lineNumber()); 0097 continue; 0098 } 0099 0100 if (ra == lastRa && dec == lastDec) 0101 { 0102 fprintf(stderr, "%s: tossing dupe on line %4d: (%f, %f)\n", fname, fileReader.lineNumber(), ra, dec); 0103 continue; 0104 } 0105 0106 // always add the point to the boundary (and toss dupes) 0107 0108 // By the time we come here, we should have polyList. Else we aren't doing good 0109 Q_ASSERT(polyList); // Is this the right fix? 0110 0111 polyList->append(QPointF(ra, dec)); 0112 if (ra < 0) 0113 polyList->setWrapRA(true); 0114 0115 if (flag) 0116 { 0117 if (!lineList.get()) 0118 lineList.reset(new LineList()); 0119 0120 std::shared_ptr<SkyPoint> point(new SkyPoint(ra, dec)); 0121 0122 point->EquatorialToHorizontal(data->lst(), data->geo()->lat()); 0123 lineList->append(std::move(point)); 0124 lastRa = ra; 0125 lastDec = dec; 0126 } 0127 else 0128 { 0129 if (lineList.get()) 0130 appendLine(lineList); 0131 lineList.reset(); 0132 lastRa = lastDec = -1000.0; 0133 } 0134 } 0135 0136 if (lineList.get()) 0137 appendLine(lineList); 0138 if (polyList.get()) 0139 appendPoly(polyList, idxFile, verbose); 0140 } 0141 0142 bool ConstellationBoundaryLines::selected() 0143 { 0144 #ifndef KSTARS_LITE 0145 return Options::showCBounds() && !(Options::hideOnSlew() && Options::hideCBounds() && SkyMap::IsSlewing()); 0146 #else 0147 return Options::showCBounds() && !(Options::hideOnSlew() && Options::hideCBounds() && SkyMapLite::IsSlewing()); 0148 #endif 0149 } 0150 0151 void ConstellationBoundaryLines::preDraw(SkyPainter *skyp) 0152 { 0153 QColor color = KStarsData::Instance()->colorScheme()->colorNamed("CBoundColor"); 0154 skyp->setPen(QPen(QBrush(color), 1, Qt::SolidLine)); 0155 } 0156 0157 void ConstellationBoundaryLines::appendPoly(std::shared_ptr<PolyList> &polyList, KSFileReader *file, int debug) 0158 { 0159 if (!file || debug == -1) 0160 return appendPoly(polyList, debug); 0161 0162 while (file->hasMoreLines()) 0163 { 0164 QString line = file->readLine(); 0165 if (line.at(0) == ':') 0166 return; 0167 Trixel trixel = line.toInt(); 0168 0169 m_polyIndex[trixel]->append(polyList); 0170 } 0171 } 0172 0173 void ConstellationBoundaryLines::appendPoly(const std::shared_ptr<PolyList> &polyList, int debug) 0174 { 0175 if (debug >= 0 && debug < m_skyMesh->debug()) 0176 debug = m_skyMesh->debug(); 0177 0178 const IndexHash &indexHash = m_skyMesh->indexPoly(polyList->poly()); 0179 IndexHash::const_iterator iter = indexHash.constBegin(); 0180 while (iter != indexHash.constEnd()) 0181 { 0182 Trixel trixel = iter.key(); 0183 iter++; 0184 0185 if (debug == -1) 0186 printf("%d\n", trixel); 0187 0188 m_polyIndex[trixel]->append(polyList); 0189 } 0190 0191 if (debug > 9) 0192 printf("PolyList: %3d: %d\n", ++m_polyIndexCnt, indexHash.size()); 0193 } 0194 0195 PolyList *ConstellationBoundaryLines::ContainingPoly(const SkyPoint *p) const 0196 { 0197 //printf("called ContainingPoly(p)\n"); 0198 0199 // we save the pointers in a hash because most often there is only one 0200 // constellation and we can avoid doing the expensive boundary calculations 0201 // and just return it if we know it is unique. We can avoid this minor 0202 // complication entirely if we use index(p) instead of aperture(p, r) 0203 // because index(p) always returns a single trixel index. 0204 0205 QHash<PolyList *, bool> polyHash; 0206 QHash<PolyList *, bool>::const_iterator iter; 0207 0208 //printf("\n"); 0209 0210 // the boundaries don't precess so we use index() not aperture() 0211 m_skyMesh->index(p, 1.0, IN_CONSTELL_BUF); 0212 MeshIterator region(m_skyMesh, IN_CONSTELL_BUF); 0213 while (region.hasNext()) 0214 { 0215 Trixel trixel = region.next(); 0216 //printf("Trixel: %4d %s\n", trixel, m_skyMesh->indexToName( trixel ) ); 0217 0218 std::shared_ptr<PolyListList> polyListList = m_polyIndex[trixel]; 0219 0220 //printf(" size: %d\n", polyListList->size() ); 0221 0222 for (const auto &item : *polyListList) 0223 { 0224 polyHash.insert(item.get(), true); 0225 } 0226 } 0227 0228 iter = polyHash.constBegin(); 0229 0230 // Don't bother with boundaries if there is only one 0231 if (polyHash.size() == 1) 0232 return iter.key(); 0233 0234 QPointF point(p->ra().Hours(), p->dec().Degrees()); 0235 QPointF wrapPoint(p->ra().Hours() - 24.0, p->dec().Degrees()); 0236 bool wrapRA = p->ra().Hours() > 12.0; 0237 0238 while (iter != polyHash.constEnd()) 0239 { 0240 PolyList *polyList = iter.key(); 0241 iter++; 0242 0243 //qDebug() << Q_FUNC_INFO << QString("checking %1 boundary\n").arg( polyList->name() ); 0244 0245 const QPolygonF *poly = polyList->poly(); 0246 if (wrapRA && polyList->wrapRA()) 0247 { 0248 if (poly->containsPoint(wrapPoint, Qt::OddEvenFill)) 0249 return polyList; 0250 } 0251 else 0252 { 0253 if (poly->containsPoint(point, Qt::OddEvenFill)) 0254 return polyList; 0255 } 0256 } 0257 0258 return nullptr; 0259 } 0260 0261 //------------------------------------------------------------------- 0262 // The routines for providing public access to the boundary index 0263 // start here. (Some of them may not be needed (or working)). 0264 //------------------------------------------------------------------- 0265 0266 QString ConstellationBoundaryLines::constellationName(const SkyPoint *p) const 0267 { 0268 PolyList *polyList = ContainingPoly(p); 0269 if (polyList) 0270 { 0271 return (Options::useLocalConstellNames() ? 0272 i18nc("Constellation name (optional)", polyList->name().toUpper().toLocal8Bit().data()) : 0273 polyList->name()); 0274 } 0275 return i18n("Unknown"); 0276 }