Kstars

skymesh.cpp
1 /*
2  SPDX-FileCopyrightText: 2007 James B. Bowlin <[email protected]>
3 
4  SPDX-License-Identifier: GPL-2.0-or-later
5 */
6 
7 #include "skymesh.h"
8 
9 #include "kstarsdata.h"
10 #ifndef KSTARS_LITE
11 #include "skymap.h"
12 #endif
13 #include "htmesh/MeshIterator.h"
14 #include "htmesh/MeshBuffer.h"
15 #include "projections/projector.h"
16 #include "skyobjects/starobject.h"
17 
18 #include <QPainter>
19 #include <QPolygonF>
20 #include <QPointF>
21 
22 QMap<int, SkyMesh *> SkyMesh::pinstances;
23 int SkyMesh::defaultLevel = -1;
24 
26 {
27  SkyMesh *newInstance = pinstances.value(level, nullptr);
28  if (newInstance != nullptr)
29  return newInstance;
30 
31  newInstance = new SkyMesh(level);
32  pinstances.insert(level, newInstance);
33  if (defaultLevel < 0)
34  defaultLevel = newInstance->level();
35 
36  return newInstance;
37 }
38 
40 {
41  return pinstances.value(defaultLevel, nullptr);
42 }
43 
45 {
46  return pinstances.value(level, nullptr);
47 }
48 
49 SkyMesh::SkyMesh(int level)
50  : HTMesh(level, level, NUM_MESH_BUF), m_drawID(0), m_KSNumbers(0)
51 {
52  errLimit = HTMesh::size() / 4;
53  m_inDraw = false;
54 }
55 
56 void SkyMesh::aperture(SkyPoint *p0, double radius, MeshBufNum_t bufNum)
57 {
58  KStarsData *data = KStarsData::Instance();
59  // FIXME: simple copying leads to incorrect results because RA0 && dec0 are both zero sometimes
60  SkyPoint p1(p0->ra(), p0->dec());
61  long double now = data->updateNum()->julianDay();
62  p1.catalogueCoord(now);
63 
64  if (radius == 1.0)
65  {
66 #ifndef KSTARS_LITE
67  printf("\n ra0 = %8.4f dec0 = %8.4f\n", p0->ra().Degrees(), p0->dec().Degrees());
68  printf(" ra1 = %8.4f dec1 = %8.4f\n", p1.ra().Degrees(), p1.dec().Degrees());
69 #endif
70  SkyPoint p2 = p1;
71  p2.updateCoordsNow(data->updateNum());
72 
73 #ifndef KSTARS_LITE
74  printf(" ra2 = %8.4f dec2 = %8.4f\n", p2.ra().Degrees(), p2.dec().Degrees());
75  printf("p0 - p1 = %6.4f degrees\n", p0->angularDistanceTo(&p1).Degrees());
76  printf("p0 - p2 = %6.4f degrees\n", p0->angularDistanceTo(&p2).Degrees());
77 #endif
78  }
79 
80  HTMesh::intersect(p1.ra().Degrees(), p1.dec().Degrees(), radius, (BufNum)bufNum);
81  m_drawID++;
82 // if (m_inDraw && bufNum != DRAW_BUF)
83 // printf("Warning: overlapping buffer: %d\n", bufNum);
84 }
85 
86 Trixel SkyMesh::index(const SkyPoint *p)
87 {
88  return HTMesh::index(p->ra0().Degrees(), p->dec0().Degrees());
89 }
90 
92 {
93  double ra, dec;
94  star->getIndexCoords(&m_KSNumbers, &ra, &dec);
95  return HTMesh::index(ra, dec);
96 }
97 
99 {
100  double ra1, ra2, dec1, dec2;
101  star1->getIndexCoords(&m_KSNumbers, &ra1, &dec1);
102  star2->getIndexCoords(&m_KSNumbers, &ra2, &dec2);
103  HTMesh::intersect(ra1, dec1, ra2, dec2);
104 }
105 
106 void SkyMesh::index(const SkyPoint *p, double radius, MeshBufNum_t bufNum)
107 {
108  HTMesh::intersect(p->ra().Degrees(), p->dec().Degrees(), radius, (BufNum)bufNum);
109 // if (m_inDraw && bufNum != DRAW_BUF)
110 // printf("Warning: overlapping buffer: %d\n", bufNum);
111 }
112 
113 void SkyMesh::index(const SkyPoint *p1, const SkyPoint *p2)
114 {
115  HTMesh::intersect(p1->ra0().Degrees(), p1->dec0().Degrees(), p2->ra0().Degrees(), p2->dec0().Degrees());
116 }
117 
118 void SkyMesh::index(const SkyPoint *p1, const SkyPoint *p2, const SkyPoint *p3)
119 {
120  HTMesh::intersect(p1->ra0().Degrees(), p1->dec0().Degrees(), p2->ra0().Degrees(), p2->dec0().Degrees(),
121  p3->ra0().Degrees(), p3->dec0().Degrees());
122 }
123 
124 void SkyMesh::index(const SkyPoint *p1, const SkyPoint *p2, const SkyPoint *p3, const SkyPoint *p4)
125 {
126  HTMesh::intersect(p1->ra0().Degrees(), p1->dec0().Degrees(), p2->ra0().Degrees(), p2->dec0().Degrees(),
127  p3->ra0().Degrees(), p3->dec0().Degrees(), p4->ra0().Degrees(), p4->dec0().Degrees());
128 }
129 
130 void SkyMesh::index(const QPointF &p1, const QPointF &p2, const QPointF &p3)
131 {
132  HTMesh::intersect(p1.x() * 15.0, p1.y(), p2.x() * 15.0, p2.y(), p3.x() * 15.0, p3.y());
133 }
134 
135 void SkyMesh::index(const QPointF &p1, const QPointF &p2, const QPointF &p3, const QPointF &p4)
136 {
137  HTMesh::intersect(p1.x() * 15.0, p1.y(), p2.x() * 15.0, p2.y(), p3.x() * 15.0, p3.y(), p4.x() * 15.0, p4.y());
138 }
139 
141 {
142  return indexLine(points, nullptr);
143 }
144 
146 {
147  SkyPoint *pThis, *pLast;
148 
149  indexHash.clear();
150 
151  if (points->isEmpty())
152  return indexHash;
153 
154  pLast = points->at(0).get();
155  for (int i = 1; i < points->size(); i++)
156  {
157  pThis = points->at(i).get();
158 
159  indexStar((StarObject *)pThis, (StarObject *)pLast);
160  MeshIterator region(this);
161 
162  while (region.hasNext())
163  {
164  indexHash[region.next()] = true;
165  }
166  pLast = pThis;
167  }
168 
169  //printf("indexStarLine %d -> %d\n", points->size(), indexHash.size() );
170  return indexHash;
171 }
172 
174 {
175  SkyPoint *pThis, *pLast;
176 
177  indexHash.clear();
178 
179  if (points->isEmpty())
180  return indexHash;
181 
182  pLast = points->at(0).get();
183  for (int i = 1; i < points->size(); i++)
184  {
185  pThis = points->at(i).get();
186 
187  if (skip != nullptr && skip->contains(i))
188  {
189  pLast = pThis;
190  continue;
191  }
192 
193  index(pThis, pLast);
194  MeshIterator region(this);
195 
196  if (region.size() > errLimit)
197  {
198  printf("\nSkyMesh::indexLine: too many trixels: %d\n", region.size());
199  printf(" ra1 = %f;\n", pThis->ra0().Degrees());
200  printf(" ra2 = %f;\n", pLast->ra0().Degrees());
201  printf(" dec1 = %f;\n", pThis->dec0().Degrees());
202  printf(" dec2 = %f;\n", pLast->dec0().Degrees());
203  HTMesh::setDebug(10);
204  index(pThis, pLast);
205  HTMesh::setDebug(0);
206  }
207 
208  // This was used to track down a bug in my HTMesh code. The bug was caught
209  // and fixed but I've left this debugging code in for now. -jbb
210 
211  else
212  {
213  while (region.hasNext())
214  {
215  indexHash[region.next()] = true;
216  }
217  }
218  pLast = pThis;
219  }
220  return indexHash;
221 }
222 
223 // ----- Create HTMesh Index for Polygons -----
224 // Create (mostly) 4-point polygons that cover the mw polygon and
225 // all share the same first vertex. Use indexHash to eliminate
226 // the many duplicate indices that are generated with this procedure.
227 // There are probably faster and better ways to do this.
228 
230 {
231  indexHash.clear();
232 
233  if (points->size() < 3)
234  return indexHash;
235 
236  SkyPoint *startP = points->first().get();
237 
238  int end = points->size() - 2; // 1) size - 1 -> last index,
239  // 2) minimum of 2 points
240 
241  for (int p = 1; p <= end; p += 2)
242  {
243  if (p == end)
244  {
245  index(startP, points->at(p).get(), points->at(p + 1).get());
246  }
247  else
248  {
249  index(startP, points->at(p).get(), points->at(p + 1).get(), points->at(p + 2).get());
250  }
251 
252  MeshIterator region(this);
253 
254  if (region.size() > errLimit)
255  {
256  printf("\nSkyMesh::indexPoly: too many trixels: %d\n", region.size());
257 
258  printf(" ra1 = %f;\n", startP->ra0().Degrees());
259  printf(" ra2 = %f;\n", points->at(p)->ra0().Degrees());
260  printf(" ra3 = %f;\n", points->at(p + 1)->ra0().Degrees());
261  if (p < end)
262  printf(" ra4 = %f;\n", points->at(p + 2)->ra0().Degrees());
263 
264  printf(" dec1 = %f;\n", startP->dec0().Degrees());
265  printf(" dec2 = %f;\n", points->at(p)->dec0().Degrees());
266  printf(" dec3 = %f;\n", points->at(p + 1)->dec0().Degrees());
267  if (p < end)
268  printf(" dec4 = %f;\n", points->at(p + 2)->dec0().Degrees());
269 
270  printf("\n");
271  }
272  while (region.hasNext())
273  {
274  indexHash[region.next()] = true;
275  }
276  }
277  return indexHash;
278 }
279 
281 {
282  indexHash.clear();
283 
284  if (points->size() < 3)
285  return indexHash;
286 
287  const QPointF startP = points->first();
288 
289  int end = points->size() - 2; // 1) size - 1 -> last index,
290  // 2) minimum of 2 points
291  for (int p = 1; p <= end; p += 2)
292  {
293  if (p == end)
294  {
295  index(startP, points->at(p), points->at(p + 1));
296  }
297  else
298  {
299  index(startP, points->at(p), points->at(p + 1), points->at(p + 2));
300  }
301 
302  MeshIterator region(this);
303 
304  if (region.size() > errLimit)
305  {
306  printf("\nSkyMesh::indexPoly: too many trixels: %d\n", region.size());
307 
308  printf(" ra1 = %f;\n", startP.x());
309  printf(" ra2 = %f;\n", points->at(p).x());
310  printf(" ra3 = %f;\n", points->at(p + 1).x());
311  if (p < end)
312  printf(" ra4 = %f;\n", points->at(p + 2).x());
313 
314  printf(" dec1 = %f;\n", startP.y());
315  printf(" dec2 = %f;\n", points->at(p).y());
316  printf(" dec3 = %f;\n", points->at(p + 1).y());
317  if (p < end)
318  printf(" dec4 = %f;\n", points->at(p + 2).y());
319 
320  printf("\n");
321  }
322  while (region.hasNext())
323  {
324  indexHash[region.next()] = true;
325  }
326  }
327  return indexHash;
328 }
329 
330 // NOTE: SkyMesh::draw() is primarily used for debugging purposes, to
331 // show the trixels to enable visualizing them. Thus, it is not
332 // necessary that this be compatible with GL unless we abandon the
333 // QPainter some day, or the need arises to use this for some other
334 // purpose. -- asimha
335 void SkyMesh::draw(QPainter &psky, MeshBufNum_t bufNum)
336 {
337 #ifndef KSTARS_LITE
338  SkyMap *map = SkyMap::Instance();
339  KStarsData *data = KStarsData::Instance();
340 
341  double r1, d1, r2, d2, r3, d3;
342 
343  MeshIterator region(this, bufNum);
344  while (region.hasNext())
345  {
346  Trixel trixel = region.next();
347  vertices(trixel, &r1, &d1, &r2, &d2, &r3, &d3);
348  SkyPoint s1(r1 / 15.0, d1);
349  SkyPoint s2(r2 / 15.0, d2);
350  SkyPoint s3(r3 / 15.0, d3);
351  s1.EquatorialToHorizontal(data->lst(), data->geo()->lat());
352  s2.EquatorialToHorizontal(data->lst(), data->geo()->lat());
353  s3.EquatorialToHorizontal(data->lst(), data->geo()->lat());
354  QPointF q1 = map->projector()->toScreen(&s1);
355  QPointF q2 = map->projector()->toScreen(&s2);
356  QPointF q3 = map->projector()->toScreen(&s3);
357  psky.drawLine(q1, q2);
358  psky.drawLine(q2, q3);
359  psky.drawLine(q3, q1);
360  // Draw the name of the trixel
361  QString TrixelNumberString;
362  TrixelNumberString.setNum(trixel);
363  psky.drawText((q1 + q2 + q3) / 3.0, TrixelNumberString);
364  }
365 #else
366  Q_UNUSED(psky);
367  Q_UNUSED(bufNum);
368 #endif
369 }
370 
371 const SkyRegion &SkyMesh::skyRegion(const SkyPoint &_p1, const SkyPoint &_p2)
372 {
373  std::shared_ptr<SkyPoint> p1(new SkyPoint(_p1));
374  std::shared_ptr<SkyPoint> p2(new SkyPoint(_p2));
375  std::shared_ptr<SkyPoint> p3(new SkyPoint(p1->ra(), p2->dec()));
376  std::shared_ptr<SkyPoint> p4(new SkyPoint(p2->ra(), p1->dec()));
377  SkyList skylist;
378 
379  skylist.push_back(p1);
380  skylist.push_back(p2);
381  skylist.push_back(p3);
382  skylist.push_back(p4);
383  return indexPoly(&skylist);
384 }
bool isEmpty() const const
const T value(const Key &key, const T &defaultValue) const const
Stores dms coordinates for a point in the sky. for converting between coordinate systems.
Definition: skypoint.h:44
bool getIndexCoords(const KSNumbers *num, CachingDms &ra, CachingDms &dec)
Fills ra and dec with the coordinates of the star with the proper motion correction but without preci...
Definition: starobject.cpp:290
void aperture(SkyPoint *center, double radius, MeshBufNum_t bufNum=DRAW_BUF)
finds the set of trixels that cover the circular aperture specified after first performing a reverse ...
Definition: skymesh.cpp:56
void draw(QPainter &psky, MeshBufNum_t bufNum=DRAW_BUF)
Draws the outline of all the trixels in the specified buffer.
Definition: skymesh.cpp:335
void push_back(const T &value)
void clear()
CachingDms * lst()
Definition: kstarsdata.h:223
void intersect(double ra, double dec, double radius, BufNum bufNum=0)
NOTE: The intersect() routines below are all used to find the trixels needed to cover a geometric obj...
Definition: HTMesh.cpp:104
const IndexHash & indexStarLine(SkyList *points)
Fills a hash with all the trixels needed to cover all the line segments in the SkyList where each Sky...
Definition: skymesh.cpp:145
T & first()
void EquatorialToHorizontal(const CachingDms *LST, const CachingDms *lat)
Determine the (Altitude, Azimuth) coordinates of the SkyPoint from its (RA, Dec) coordinates,...
Definition: skypoint.cpp:77
void drawText(const QPointF &position, const QString &text)
Definition: HTMesh.h:56
int size() const
returns the number of trixels stored
Definition: MeshIterator.h:35
QMap::iterator insert(const Key &key, const T &value)
void setDebug(int debug)
sets the debug level which is used to print out intermediate results in the line intersection routine...
Definition: HTMesh.h:127
QString & setNum(short n, int base)
const CachingDms & dec() const
Definition: skypoint.h:269
const CachingDms * lat() const
Definition: geolocation.h:70
Trixel indexStar(StarObject *star)
returns the trixel that contains the star at the set time with proper motion taken into account but n...
Definition: skymesh.cpp:91
subclass of SkyObject specialized for stars.
Definition: starobject.h:32
const T & at(int i) const const
GeoLocation * geo()
Definition: kstarsdata.h:229
long double julianDay() const
Definition: ksnumbers.h:91
Trixel index(double ra, double dec) const
returns the index of the trixel that contains the specified point.
Definition: HTMesh.cpp:72
int size() const
returns the total number of trixels in the HTM.
Definition: HTMesh.h:118
virtual void updateCoordsNow(const KSNumbers *num)
updateCoordsNow Shortcut for updateCoords( const KSNumbers *num, false, nullptr, nullptr,...
Definition: skypoint.h:382
int level() const
returns the mesh level.
Definition: HTMesh.h:122
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:229
dms angularDistanceTo(const SkyPoint *sp, double *const positionAngle=nullptr) const
Computes the angular distance between two SkyObjects.
Definition: skypoint.cpp:899
bool hasNext() const
true if there are more trixel to iterate over.
Definition: MeshIterator.h:27
static SkyMesh * Instance()
returns the default instance of SkyMesh or null if it has not yet been created.
Definition: skymesh.cpp:39
const SkyRegion & skyRegion(const SkyPoint &p1, const SkyPoint &p2)
returns the sky region needed to cover the rectangle defined by two SkyPoints p1 and p2
Definition: skymesh.cpp:371
qreal x() const const
qreal y() const const
const CachingDms & ra() const
Definition: skypoint.h:263
const CachingDms & dec0() const
Definition: skypoint.h:257
const double & Degrees() const
Definition: dms.h:141
Canvas widget for displaying the sky bitmap; also handles user interaction events.
Definition: skymap.h:52
void drawLine(const QLineF &line)
const CachingDms & ra0() const
Definition: skypoint.h:251
int size() const const
const IndexHash & indexLine(SkyList *points)
fills a QHash with the trixel indices needed to cover all the line segments specified in the QVector<...
Definition: skymesh.cpp:140
bool contains(const Key &key) const const
Trixel index(const SkyPoint *p)
returns the index of the trixel containing p.
Definition: skymesh.cpp:86
static SkyMesh * Create(int level)
creates the single instance of SkyMesh.
Definition: skymesh.cpp:25
SkyPoint catalogueCoord(long double jdf)
Computes the J2000.0 catalogue coordinates for this SkyPoint using the epoch removing aberration,...
Definition: skypoint.cpp:710
Trixel next() const
returns the next trixel
Definition: MeshIterator.h:31
This file is part of the KDE documentation.
Documentation copyright © 1996-2022 The KDE developers.
Generated on Tue Aug 9 2022 04:06:07 by doxygen 1.8.17 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.