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();
54 }
55
56 // now open the file that contains the points
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 {
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}
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...
QString readLine()
increments the line number and returns the next line from the file as a QString.
bool hasMoreLines() const
KStarsData is the backbone of KStars.
Definition kstarsdata.h:72
CachingDms * lst()
Definition kstarsdata.h:224
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
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
QString i18nc(const char *context, const char *text, const TYPE &arg...)
QString i18n(const char *text, const TYPE &arg...)
QStringView level(QStringView ifopt)
const_iterator constBegin() const const
const_iterator constEnd() const const
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
OddEvenFill
SolidLine
QTextStream & dec(QTextStream &stream)
This file is part of the KDE documentation.
Documentation copyright © 1996-2024 The KDE developers.
Generated on Tue Mar 26 2024 11:19:04 by doxygen 1.10.0 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.