Kstars

constellationboundarylines.cpp
1/*
2 SPDX-FileCopyrightText: 2005 Jason Harris <kstars@30doradus.org>
3
4 SPDX-License-Identifier: GPL-2.0-or-later
5*/
6
7#include "constellationboundarylines.h"
8
9#include "ksfilereader.h"
10#include "kstarsdata.h"
11#include "linelist.h"
12#include "Options.h"
13#include "polylist.h"
14#ifdef KSTARS_LITE
15#include "skymaplite.h"
16#else
17#include "skymap.h"
18#endif
19#include "skypainter.h"
20#include "htmesh/MeshIterator.h"
21#include "skycomponents/skymapcomposite.h"
22#include "skyobjects/starobject.h"
23
24#include <QHash>
25
26ConstellationBoundaryLines::ConstellationBoundaryLines(SkyComposite *parent)
27 : LineListIndex(parent, i18n("Constellation Boundaries"))
28{
29 m_skyMesh = SkyMesh::Instance();
30 m_polyIndexCnt = 0;
31 for (int i = 0; i < m_skyMesh->size(); i++)
32 {
33 m_polyIndex.append(std::shared_ptr<PolyListList>(new PolyListList()));
34 }
35
36 KStarsData *data = KStarsData::Instance();
37 int verbose = 0; // -1 => create cbounds-$x.idx on stdout
38 // 0 => normal
39 const char *fname = "cbounds.dat";
40 int flag = 0;
41 double ra, dec = 0, lastRa, lastDec;
42 std::shared_ptr<LineList> lineList;
43 std::shared_ptr<PolyList> polyList;
44 bool ok = false;
45
46 intro();
47
48 // Open the .idx file and skip past the first line
49 KSFileReader idxReader, *idxFile = nullptr;
50 QString idxFname = QString("cbounds-%1.idx").arg(SkyMesh::Instance()->level());
51 if (idxReader.open(idxFname))
52 {
53 idxReader.readLine();
54 idxFile = &idxReader;
55 }
56
57 // now open the file that contains the points
58 KSFileReader fileReader;
59 if (!fileReader.open(fname))
60 return;
61
62 fileReader.setProgress(i18n("Loading Constellation Boundaries"), 13124, 10);
63
64 lastRa = lastDec = -1000.0;
65
66 while (fileReader.hasMoreLines())
67 {
68 QString line = fileReader.readLine();
69 fileReader.showProgress();
70
71 if (line.at(0) == '#')
72 continue; // ignore comments
73 if (line.at(0) == ':') // :constellation line
74 {
75 if (lineList.get())
76 appendLine(lineList);
77 lineList.reset();
78
79 if (polyList.get())
80 appendPoly(polyList, idxFile, verbose);
81 QString cName = line.mid(1);
82 polyList.reset(new PolyList(cName));
83 if (verbose == -1)
84 printf(":\n");
85 lastRa = lastDec = -1000.0;
86 continue;
87 }
88
89 // read in the data from the line
90 ra = line.mid(0, 12).toDouble(&ok);
91 if (ok)
92 dec = line.mid(13, 12).toDouble(&ok);
93 if (ok)
94 flag = line.mid(26, 1).toInt(&ok);
95 if (!ok)
96 {
97 fprintf(stderr, "%s: conversion error on line: %d\n", fname, fileReader.lineNumber());
98 continue;
99 }
100
101 if (ra == lastRa && dec == lastDec)
102 {
103 fprintf(stderr, "%s: tossing dupe on line %4d: (%f, %f)\n", fname, fileReader.lineNumber(), ra, dec);
104 continue;
105 }
106
107 // always add the point to the boundary (and toss dupes)
108
109 // By the time we come here, we should have polyList. Else we aren't doing good
110 Q_ASSERT(polyList); // Is this the right fix?
111
112 polyList->append(QPointF(ra, dec));
113 if (ra < 0)
114 polyList->setWrapRA(true);
115
116 if (flag)
117 {
118 if (!lineList.get())
119 lineList.reset(new LineList());
120
121 std::shared_ptr<SkyPoint> point(new SkyPoint(ra, dec));
122
123 point->EquatorialToHorizontal(data->lst(), data->geo()->lat());
124 lineList->append(std::move(point));
125 lastRa = ra;
126 lastDec = dec;
127 }
128 else
129 {
130 if (lineList.get())
131 appendLine(lineList);
132 lineList.reset();
133 lastRa = lastDec = -1000.0;
134 }
135 }
136
137 if (lineList.get())
138 appendLine(lineList);
139 if (polyList.get())
140 appendPoly(polyList, idxFile, verbose);
141}
142
143bool ConstellationBoundaryLines::selected()
144{
145#ifndef KSTARS_LITE
146 return Options::showCBounds() && !(Options::hideOnSlew() && Options::hideCBounds() && SkyMap::IsSlewing());
147#else
148 return Options::showCBounds() && !(Options::hideOnSlew() && Options::hideCBounds() && SkyMapLite::IsSlewing());
149#endif
150}
151
152void ConstellationBoundaryLines::preDraw(SkyPainter *skyp)
153{
154 QColor color = KStarsData::Instance()->colorScheme()->colorNamed("CBoundColor");
155 skyp->setPen(QPen(QBrush(color), 1, Qt::SolidLine));
156}
157
158void ConstellationBoundaryLines::appendPoly(std::shared_ptr<PolyList> &polyList, KSFileReader *file, int debug)
159{
160 if (!file || debug == -1)
161 return appendPoly(polyList, debug);
162
163 while (file->hasMoreLines())
164 {
165 QString line = file->readLine();
166 if (line.at(0) == ':')
167 return;
168 Trixel trixel = line.toInt();
169
170 m_polyIndex[trixel]->append(polyList);
171 }
172}
173
174void ConstellationBoundaryLines::appendPoly(const std::shared_ptr<PolyList> &polyList, int debug)
175{
176 if (debug >= 0 && debug < m_skyMesh->debug())
177 debug = m_skyMesh->debug();
178
179 const IndexHash &indexHash = m_skyMesh->indexPoly(polyList->poly());
180 IndexHash::const_iterator iter = indexHash.constBegin();
181 while (iter != indexHash.constEnd())
182 {
183 Trixel trixel = iter.key();
184 iter++;
185
186 if (debug == -1)
187 printf("%d\n", trixel);
188
189 m_polyIndex[trixel]->append(polyList);
190 }
191
192 if (debug > 9)
193 printf("PolyList: %3d: %d\n", ++m_polyIndexCnt, indexHash.size());
194}
195
196PolyList *ConstellationBoundaryLines::ContainingPoly(const SkyPoint *p) const
197{
198 //printf("called ContainingPoly(p)\n");
199
200 // we save the pointers in a hash because most often there is only one
201 // constellation and we can avoid doing the expensive boundary calculations
202 // and just return it if we know it is unique. We can avoid this minor
203 // complication entirely if we use index(p) instead of aperture(p, r)
204 // because index(p) always returns a single trixel index.
205
208
209 //printf("\n");
210
211 m_skyMesh->index(p, 1.0, IN_CONSTELL_BUF);
212 MeshIterator region(m_skyMesh, IN_CONSTELL_BUF);
213 while (region.hasNext())
214 {
215 Trixel trixel = region.next();
216 //printf("Trixel: %4d %s\n", trixel, m_skyMesh->indexToName( trixel ) );
217
218 std::shared_ptr<PolyListList> polyListList = m_polyIndex[trixel];
219
220 //printf(" size: %d\n", polyListList->size() );
221
222 for (const auto &item : *polyListList)
223 {
224 polyHash.insert(item.get(), true);
225 }
226 }
227
228 iter = polyHash.constBegin();
229
230 // Don't bother with boundaries if there is only one
231 if (polyHash.size() == 1)
232 return iter.key();
233
234 // Note: We special case StarObject, because we should really
235 // include the proper motion (i.e. epoch = JNow, equinox = J2000)
236 // when determining the constellation containing the star. This
237 // ensures that rho Aquilae will be reported in Delphinus after
238 // accounting for proper motion. See
239 // https://en.wikipedia.org/wiki/Rho_Aquilae
240 //
241 // However, this way of doing it isn't great, in case the
242 // StarObject got type-sliced down to SkyPoint somewhere along
243 // --asimha
244 double RAH = p->ra0().Hours(), DED = p->dec0().Degrees();
245 const StarObject *star = dynamic_cast<const StarObject*>(p);
246 if (star) {
247 StarObject copy = *star;
248 double RAD = 0;
249 copy.getIndexCoords((star->getLastPrecessJD() - J2000)/365250., &RAD, &DED);
250 RAH = RAD / 15.;
251 }
252 QPointF point(RAH, DED);
253 QPointF wrapPoint(RAH - 24.0, DED);
254 bool wrapRA = RAH > 12.0;
255
256 while (iter != polyHash.constEnd())
257 {
258 PolyList *polyList = iter.key();
259 iter++;
260
261 //qDebug() << Q_FUNC_INFO << QString("checking %1 boundary\n").arg( polyList->name() );
262
263 const QPolygonF *poly = polyList->poly();
264 if (wrapRA && polyList->wrapRA())
265 {
266 if (poly->containsPoint(wrapPoint, Qt::OddEvenFill))
267 return polyList;
268 }
269 else
270 {
271 if (poly->containsPoint(point, Qt::OddEvenFill))
272 return polyList;
273 }
274 }
275
276 return nullptr;
277}
278
279//-------------------------------------------------------------------
280// The routines for providing public access to the boundary index
281// start here. (Some of them may not be needed (or working)).
282//-------------------------------------------------------------------
283
284QString ConstellationBoundaryLines::constellationName(const SkyPoint *p) const
285{
286 PolyList *polyList = ContainingPoly(p);
287 if (polyList)
288 {
289 return (Options::useLocalConstellNames() ?
290 i18nc("Constellation name (optional)", polyList->name().toUpper().toLocal8Bit().data()) :
291 polyList->name());
292 }
293 return i18n("Unknown");
294}
QColor colorNamed(const QString &name) const
Retrieve a color by name.
const CachingDms * lat() const
Definition geolocation.h:70
I totally rewrote this because the earlier scheme of reading all the lines of a file into a buffer be...
int lineNumber() const
returns the current line number
void setProgress(QString label, unsigned int lastLine, unsigned int numUpdates=10)
Prepares this instance to emit progress reports on how much of the file has been read (in percent).
QString readLine()
increments the line number and returns the next line from the file as a QString.
bool hasMoreLines() const
bool open(const QString &fname)
opens the file fname from the QStandardPaths::AppLocalDataLocation directory and uses that file for t...
void showProgress()
emits progress reports when required and updates bookkeeping for when to send the next report.
KStarsData is the backbone of KStars.
Definition kstarsdata.h:74
CachingDms * lst()
Definition kstarsdata.h:226
ColorScheme * colorScheme()
Definition kstarsdata.h:174
GeoLocation * geo()
Definition kstarsdata.h:232
Contains almost all the code needed for indexing and drawing and clipping lines and polygons.
A simple data container used by LineListIndex.
Definition linelist.h:25
MeshIterator is a very lightweight class used to iterate over the result set of an HTMesh intersectio...
SkyComposite is a kind of container class for SkyComponent objects.
static SkyMesh * Instance()
returns the default instance of SkyMesh or null if it has not yet been created.
Definition skymesh.cpp:39
int debug() const
Returns the debug level.
Definition skymesh.h:255
const IndexHash & indexPoly(SkyList *points)
fills a QHash with the trixel indices needed to cover the polygon specified in the QList<SkyPoints*> ...
Definition skymesh.cpp:208
Trixel index(const SkyPoint *p)
returns the index of the trixel containing p.
Definition skymesh.cpp:74
Draws things on the sky, without regard to backend.
Definition skypainter.h:40
virtual void setPen(const QPen &pen)=0
Set the pen of the painter.
The sky coordinates of a point in the sky.
Definition skypoint.h:45
const CachingDms & ra0() const
Definition skypoint.h:251
long double getLastPrecessJD() const
Definition skypoint.h:294
const CachingDms & dec0() const
Definition skypoint.h:257
This is a subclass of SkyObject.
Definition starobject.h:33
QString i18nc(const char *context, const char *text, const TYPE &arg...)
QString i18n(const char *text, const TYPE &arg...)
QStringView level(QStringView ifopt)
const QList< QKeySequence > & copy()
char * data()
const_iterator constBegin() const const
const_iterator constEnd() const const
iterator insert(const Key &key, const T &value)
qsizetype size() const const
bool containsPoint(const QPointF &point, Qt::FillRule fillRule) const const
QString arg(Args &&... args) const const
const QChar at(qsizetype position) const const
QString mid(qsizetype position, qsizetype n) const const
double toDouble(bool *ok) const const
int toInt(bool *ok, int base) const const
QByteArray toLocal8Bit() const const
QString toUpper() const const
OddEvenFill
SolidLine
QTextStream & dec(QTextStream &stream)
This file is part of the KDE documentation.
Documentation copyright © 1996-2024 The KDE developers.
Generated on Mon Nov 18 2024 12:16:41 by doxygen 1.12.0 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.