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
23#include <QHash>
24
25ConstellationBoundaryLines::ConstellationBoundaryLines(SkyComposite *parent)
26 : NoPrecessIndex(parent, i18n("Constellation Boundaries"))
27{
28 m_skyMesh = SkyMesh::Instance();
29 m_polyIndexCnt = 0;
30 for (int i = 0; i < m_skyMesh->size(); i++)
31 {
32 m_polyIndex.append(std::shared_ptr<PolyListList>(new PolyListList()));
33 }
34
35 KStarsData *data = KStarsData::Instance();
36 int verbose = 0; // -1 => create cbounds-$x.idx on stdout
37 // 0 => normal
38 const char *fname = "cbounds.dat";
39 int flag = 0;
40 double ra, dec = 0, lastRa, lastDec;
41 std::shared_ptr<LineList> lineList;
42 std::shared_ptr<PolyList> polyList;
43 bool ok = false;
44
45 intro();
46
47 // Open the .idx file and skip past the first line
48 KSFileReader idxReader, *idxFile = nullptr;
49 QString idxFname = QString("cbounds-%1.idx").arg(SkyMesh::Instance()->level());
50 if (idxReader.open(idxFname))
51 {
52 idxReader.readLine();
53 idxFile = &idxReader;
54 }
55
56 // now open the file that contains the points
57 KSFileReader fileReader;
58 if (!fileReader.open(fname))
59 return;
60
61 fileReader.setProgress(i18n("Loading Constellation Boundaries"), 13124, 10);
62
63 lastRa = lastDec = -1000.0;
64
65 while (fileReader.hasMoreLines())
66 {
67 QString line = fileReader.readLine();
68 fileReader.showProgress();
69
70 if (line.at(0) == '#')
71 continue; // ignore comments
72 if (line.at(0) == ':') // :constellation line
73 {
74 if (lineList.get())
75 appendLine(lineList);
76 lineList.reset();
77
78 if (polyList.get())
79 appendPoly(polyList, idxFile, verbose);
80 QString cName = line.mid(1);
81 polyList.reset(new PolyList(cName));
82 if (verbose == -1)
83 printf(":\n");
84 lastRa = lastDec = -1000.0;
85 continue;
86 }
87
88 // read in the data from the line
89 ra = line.midRef(0, 12).toDouble(&ok);
90 if (ok)
91 dec = line.midRef(13, 12).toDouble(&ok);
92 if (ok)
93 flag = line.midRef(26, 1).toInt(&ok);
94 if (!ok)
95 {
96 fprintf(stderr, "%s: conversion error on line: %d\n", fname, fileReader.lineNumber());
97 continue;
98 }
99
100 if (ra == lastRa && dec == lastDec)
101 {
102 fprintf(stderr, "%s: tossing dupe on line %4d: (%f, %f)\n", fname, fileReader.lineNumber(), ra, dec);
103 continue;
104 }
105
106 // always add the point to the boundary (and toss dupes)
107
108 // By the time we come here, we should have polyList. Else we aren't doing good
109 Q_ASSERT(polyList); // Is this the right fix?
110
111 polyList->append(QPointF(ra, dec));
112 if (ra < 0)
113 polyList->setWrapRA(true);
114
115 if (flag)
116 {
117 if (!lineList.get())
118 lineList.reset(new LineList());
119
120 std::shared_ptr<SkyPoint> point(new SkyPoint(ra, dec));
121
122 point->EquatorialToHorizontal(data->lst(), data->geo()->lat());
123 lineList->append(std::move(point));
124 lastRa = ra;
125 lastDec = dec;
126 }
127 else
128 {
129 if (lineList.get())
130 appendLine(lineList);
131 lineList.reset();
132 lastRa = lastDec = -1000.0;
133 }
134 }
135
136 if (lineList.get())
137 appendLine(lineList);
138 if (polyList.get())
139 appendPoly(polyList, idxFile, verbose);
140}
141
142bool ConstellationBoundaryLines::selected()
143{
144#ifndef KSTARS_LITE
145 return Options::showCBounds() && !(Options::hideOnSlew() && Options::hideCBounds() && SkyMap::IsSlewing());
146#else
147 return Options::showCBounds() && !(Options::hideOnSlew() && Options::hideCBounds() && SkyMapLite::IsSlewing());
148#endif
149}
150
151void ConstellationBoundaryLines::preDraw(SkyPainter *skyp)
152{
153 QColor color = KStarsData::Instance()->colorScheme()->colorNamed("CBoundColor");
154 skyp->setPen(QPen(QBrush(color), 1, Qt::SolidLine));
155}
156
157void ConstellationBoundaryLines::appendPoly(std::shared_ptr<PolyList> &polyList, KSFileReader *file, int debug)
158{
159 if (!file || debug == -1)
160 return appendPoly(polyList, debug);
161
162 while (file->hasMoreLines())
163 {
164 QString line = file->readLine();
165 if (line.at(0) == ':')
166 return;
167 Trixel trixel = line.toInt();
168
169 m_polyIndex[trixel]->append(polyList);
170 }
171}
172
173void ConstellationBoundaryLines::appendPoly(const std::shared_ptr<PolyList> &polyList, int debug)
174{
175 if (debug >= 0 && debug < m_skyMesh->debug())
176 debug = m_skyMesh->debug();
177
178 const IndexHash &indexHash = m_skyMesh->indexPoly(polyList->poly());
179 IndexHash::const_iterator iter = indexHash.constBegin();
180 while (iter != indexHash.constEnd())
181 {
182 Trixel trixel = iter.key();
183 iter++;
184
185 if (debug == -1)
186 printf("%d\n", trixel);
187
188 m_polyIndex[trixel]->append(polyList);
189 }
190
191 if (debug > 9)
192 printf("PolyList: %3d: %d\n", ++m_polyIndexCnt, indexHash.size());
193}
194
195PolyList *ConstellationBoundaryLines::ContainingPoly(const SkyPoint *p) const
196{
197 //printf("called ContainingPoly(p)\n");
198
199 // we save the pointers in a hash because most often there is only one
200 // constellation and we can avoid doing the expensive boundary calculations
201 // and just return it if we know it is unique. We can avoid this minor
202 // complication entirely if we use index(p) instead of aperture(p, r)
203 // because index(p) always returns a single trixel index.
204
207
208 //printf("\n");
209
210 // the boundaries don't precess so we use index() not aperture()
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 QPointF point(p->ra().Hours(), p->dec().Degrees());
235 QPointF wrapPoint(p->ra().Hours() - 24.0, p->dec().Degrees());
236 bool wrapRA = p->ra().Hours() > 12.0;
237
238 while (iter != polyHash.constEnd())
239 {
240 PolyList *polyList = iter.key();
241 iter++;
242
243 //qDebug() << Q_FUNC_INFO << QString("checking %1 boundary\n").arg( polyList->name() );
244
245 const QPolygonF *poly = polyList->poly();
246 if (wrapRA && polyList->wrapRA())
247 {
248 if (poly->containsPoint(wrapPoint, Qt::OddEvenFill))
249 return polyList;
250 }
251 else
252 {
253 if (poly->containsPoint(point, Qt::OddEvenFill))
254 return polyList;
255 }
256 }
257
258 return nullptr;
259}
260
261//-------------------------------------------------------------------
262// The routines for providing public access to the boundary index
263// start here. (Some of them may not be needed (or working)).
264//-------------------------------------------------------------------
265
266QString ConstellationBoundaryLines::constellationName(const SkyPoint *p) const
267{
268 PolyList *polyList = ContainingPoly(p);
269 if (polyList)
270 {
271 return (Options::useLocalConstellNames() ?
272 i18nc("Constellation name (optional)", polyList->name().toUpper().toLocal8Bit().data()) :
273 polyList->name());
274 }
275 return i18n("Unknown");
276}
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:72
CachingDms * lst()
Definition kstarsdata.h:224
ColorScheme * colorScheme()
Definition kstarsdata.h:172
GeoLocation * geo()
Definition kstarsdata.h:230
QString name() const
retrieve name of object
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 & dec() const
Definition skypoint.h:269
const CachingDms & ra() const
Definition skypoint.h:263
double Hours() const
Definition dms.h:168
const double & Degrees() const
Definition dms.h:141
QString i18nc(const char *context, const char *text, const TYPE &arg...)
QString i18n(const char *text, const TYPE &arg...)
QStringView level(QStringView ifopt)
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 Fri Jul 26 2024 11:59:52 by doxygen 1.11.0 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.