Kstars

constellationboundarylines.cpp
1 /*
2  SPDX-FileCopyrightText: 2005 Jason Harris <[email protected]>
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 
25 ConstellationBoundaryLines::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 
142 bool 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 
151 void ConstellationBoundaryLines::preDraw(SkyPainter *skyp)
152 {
153  QColor color = KStarsData::Instance()->colorScheme()->colorNamed("CBoundColor");
154  skyp->setPen(QPen(QBrush(color), 1, Qt::SolidLine));
155 }
156 
157 void 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 
173 void 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 
195 PolyList *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 
205  QHash<PolyList *, bool> polyHash;
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 
266 QString 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 }
int toInt(bool *ok, int base) const const
bool containsPoint(const QPointF &point, Qt::FillRule fillRule) const const
Stores dms coordinates for a point in the sky. for converting between coordinate systems.
Definition: skypoint.h:44
QStringRef midRef(int position, int n) const const
bool open(const QString &fname)
opens the file fname from the QStandardPaths::AppLocalDataLocation directory and uses that file for t...
CachingDms * lst()
Definition: kstarsdata.h:223
virtual void setPen(const QPen &pen)=0
Set the pen of the painter.
QStringView level(QStringView ifopt)
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).
QHash::iterator insert(const Key &key, const T &value)
int size() const const
OddEvenFill
QString i18n(const char *text, const TYPE &arg...)
const CachingDms & dec() const
Definition: skypoint.h:269
const CachingDms * lat() const
Definition: geolocation.h:70
double toDouble(bool *ok) const const
QHash::const_iterator constBegin() const const
QHash::const_iterator constEnd() const const
bool hasMoreLines() const
Definition: ksfilereader.h:100
ColorScheme * colorScheme()
Definition: kstarsdata.h:171
GeoLocation * geo()
Definition: kstarsdata.h:229
int toInt(bool *ok, int base) const const
QTextStream & dec(QTextStream &stream)
Draws things on the sky, without regard to backend.
Definition: skypainter.h:37
void showProgress()
emits progress reports when required and updates bookkeeping for when to send the next report.
static SkyMesh * Instance()
returns the default instance of SkyMesh or null if it has not yet been created.
Definition: skymesh.cpp:39
const CachingDms & ra() const
Definition: skypoint.h:263
QString arg(qlonglong a, int fieldWidth, int base, QChar fillChar) const const
const double & Degrees() const
Definition: dms.h:141
QString readLine()
increments the line number and returns the next line from the file as a QString.
Definition: ksfilereader.h:105
const QChar at(int position) const const
QString i18nc(const char *context, const char *text, const TYPE &arg...)
SolidLine
QString mid(int position, int n) const const
QColor colorNamed(const QString &name) const
Retrieve a color by name.
Definition: colorscheme.cpp:86
int lineNumber() const
returns the current line number
Definition: ksfilereader.h:112
double Hours() const
Definition: dms.h:168
void appendPoly(const std::shared_ptr< LineList > &lineList)
Typically called from within a subclasses constructors.
This file is part of the KDE documentation.
Documentation copyright © 1996-2022 The KDE developers.
Generated on Fri Aug 12 2022 04:00:53 by doxygen 1.8.17 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.