Kstars

projector.cpp
1/*
2 SPDX-FileCopyrightText: 2010 Henry de Valence <hdevalence@gmail.com>
3
4 SPDX-License-Identifier: GPL-2.0-or-later
5*/
6
7#include "projector.h"
8
9#include "ksutils.h"
10#ifdef KSTARS_LITE
11#include "skymaplite.h"
12#endif
13#include "skycomponents/skylabeler.h"
14
15namespace
16{
17void toXYZ(const SkyPoint *p, double *x, double *y, double *z)
18{
19 double sinRa, sinDec, cosRa, cosDec;
20
21 p->ra().SinCos(sinRa, cosRa);
22 p->dec().SinCos(sinDec, cosDec);
23 *x = cosDec * cosRa;
24 *y = cosDec * sinRa;
25 *z = sinDec;
26}
27}
28
29SkyPoint Projector::pointAt(double az)
30{
31 SkyPoint p;
32 p.setAz(az);
33 p.setAlt(0.0);
34 p.HorizontalToEquatorial(KStarsData::Instance()->lst(), KStarsData::Instance()->geo()->lat());
35 return p;
36}
37
39{
40 m_data = KStarsData::Instance();
42 // Force clip polygon update
44}
45
47{
48 m_vp = p;
49
50 /** Precompute cached values */
51 //Find Sin/Cos for focus point
52 m_sinY0 = 0;
53 m_cosY0 = 0;
54 if (m_vp.useAltAz)
55 {
56 // N.B. We explicitly check useRefraction and not use
57 // SkyPoint::altRefracted() here because it could be different
58 // from Options::useRefraction() in some future use-case
59 // --asimha
60 SkyPoint::refract(m_vp.focus->alt(), m_vp.useRefraction).SinCos(m_sinY0, m_cosY0);
61 }
62 else
63 {
64 m_vp.focus->dec().SinCos(m_sinY0, m_cosY0);
65 }
66
67 double currentFOV = m_fov;
68 //Find FOV in radians
69 m_fov = sqrt(m_vp.width * m_vp.width + m_vp.height * m_vp.height) / (2 * m_vp.zoomFactor * dms::DegToRad);
70 //Set checkVisibility variables
71 double Ymax;
72 m_xrange = 1.2 * m_fov / m_cosY0;
73 if (m_vp.useAltAz)
74 {
75 Ymax = fabs(SkyPoint::refract(m_vp.focus->alt().Degrees(), m_vp.useRefraction)) + m_fov;
76 }
77 else
78 {
79 Ymax = fabs(m_vp.focus->dec().Degrees()) + m_fov;
80 }
81 m_isPoleVisible = (Ymax >= 90.0);
82
83 // Only update clipping polygon if there is an FOV change
84 if (currentFOV != m_fov)
86}
87
88double Projector::fov() const
89{
90 return m_fov;
91}
92
93QPointF Projector::toScreen(const SkyPoint *o, bool oRefract, bool *onVisibleHemisphere) const
94{
95 return KSUtils::vecToPoint(toScreenVec(o, oRefract, onVisibleHemisphere));
96}
97
98bool Projector::onScreen(const QPointF &p) const
99{
100 return (0 <= p.x() && p.x() <= m_vp.width && 0 <= p.y() && p.y() <= m_vp.height);
101}
102
103bool Projector::onScreen(const Eigen::Vector2f &p) const
104{
105 return onScreen(QPointF(p.x(), p.y()));
106}
107
108QPointF Projector::clipLine(SkyPoint *p1, SkyPoint *p2) const
109{
110 return KSUtils::vecToPoint(clipLineVec(p1, p2));
111}
112
113Eigen::Vector2f Projector::clipLineVec(SkyPoint *p1, SkyPoint *p2) const
114{
115 /* ASSUMES p1 was not clipped but p2 was.
116 * Return the QPoint that barely clips in the line twixt p1 and p2.
117 */
118 //TODO: iteration = ceil( 0.5*log2( w^2 + h^2) )??
119 // also possibly rewrite this
120 // --hdevalence
121 int iteration = 15; // For "perfect" clipping:
122 // 2^iterations should be >= max pixels/line
123 bool isVisible = true; // so we start at midpoint
124 SkyPoint mid;
125 Eigen::Vector2f oMid;
126 double x, y, z, dx, dy, dz, ra, dec;
127 int newx, newy, oldx, oldy;
128 oldx = oldy = -10000; // any old value that is not the first omid
129
130 toXYZ(p1, &x, &y, &z);
131 // -jbb printf("\np1: %6.4f %6.4f %6.4f\n", x, y, z);
132
133 toXYZ(p2, &dx, &dy, &dz);
134
135 // -jbb printf("p2: %6.4f %6.4f %6.4f\n", dx, dy, dz);
136 dx -= x;
137 dy -= y;
138 dz -= z;
139 // Successive approximation to point on line that just clips.
140 while (iteration-- > 0)
141 {
142 dx *= .5;
143 dy *= .5;
144 dz *= .5;
145 if (!isVisible) // move back toward visible p1
146 {
147 x -= dx;
148 y -= dy;
149 z -= dz;
150 }
151 else // move out toward clipped p2
152 {
153 x += dx;
154 y += dy;
155 z += dz;
156 }
157
158 // -jbb printf(" : %6.4f %6.4f %6.4f\n", x, y, z);
159 // [x, y, z] => [ra, dec]
160 ra = atan2(y, x);
161 dec = asin(z / sqrt(x * x + y * y + z * z));
162
163 mid = SkyPoint(ra * 12. / dms::PI, dec * 180. / dms::PI);
164 mid.EquatorialToHorizontal(m_data->lst(), m_data->geo()->lat());
165
166 oMid = toScreenVec(&mid, false, &isVisible);
167 //AND the result with checkVisibility to clip things going below horizon
168 isVisible &= checkVisibility(&mid);
169 newx = (int)oMid.x();
170 newy = (int)oMid.y();
171
172 // -jbb printf("new x/y: %4d %4d", newx, newy);
173 if ((oldx == newx) && (oldy == newy))
174 {
175 break;
176 }
177 oldx = newx;
178 oldy = newy;
179 }
180 return oMid;
181}
182
183bool Projector::checkVisibility(const SkyPoint *p) const
184{
185 //TODO deal with alternate projections
186 //not clear how this depends on projection
187 //FIXME do these heuristics actually work?
188
189 double dX, dY;
190
191 //Skip objects below the horizon if the ground is drawn
192 /* Is the cost of this conversion actually less than drawing it anyways?
193 * EquatorialToHorizontal takes 3 SinCos calls -- so 6 trig calls if not using GNU exts.
194 */
195 /*
196 if( m_vp.fillGround ) {
197 if( !m_vp.useAltAz )
198 p->EquatorialToHorizontal( m_data->lst(), m_data->geo()->lat() );
199 if( p->alt().Degrees() < -1.0 ) return false;
200 }
201 */ //Here we hope that the point has already been 'synchronized'
202 if (m_vp.fillGround /*&& m_vp.useAltAz*/ && p->alt().Degrees() <= SkyPoint::altCrit)
203 return false;
204
205 if (m_vp.useAltAz)
206 {
207 /** To avoid calculating refraction, we just use the unrefracted
208 altitude and add a 2-degree 'safety factor' */
209 dY = fabs(p->alt().Degrees() - m_vp.focus->alt().Degrees()) - 2.;
210 }
211 else
212 {
213 dY = fabs(p->dec().Degrees() - m_vp.focus->dec().Degrees());
214 }
215 if (m_isPoleVisible)
216 dY *= 0.75; //increase effective FOV when pole visible.
217 if (dY > m_fov)
218 return false;
219 if (m_isPoleVisible)
220 return true;
221
222 if (m_vp.useAltAz)
223 {
224 dX = fabs(p->az().Degrees() - m_vp.focus->az().Degrees());
225 }
226 else
227 {
228 dX = fabs(p->ra().Degrees() - m_vp.focus->ra().Degrees());
229 }
230 if (dX > 180.0)
231 dX = 360.0 - dX; // take shorter distance around sky
232
233 return dX < m_xrange;
234}
235
236double Projector::findNorthPA(const SkyPoint *o, float x, float y) const
237{
238 //Find position angle of North using a test point displaced to the north
239 //displace by 100/zoomFactor radians (so distance is always 100 pixels)
240 //this is 5730/zoomFactor degrees
241
242 // N.B. It is not sufficient to find the angle at the center of
243 // the screen, and the angle of the NCP can vary drastically
244 // across the screen (e.g. when pointed towards the NCP)
245
246 KStarsData *data = KStarsData::Instance();
247 double newDec = o->dec().Degrees() + 5730.0 / m_vp.zoomFactor;
248 if (newDec > 90.0)
249 newDec = 90.0;
250 SkyPoint test(o->ra().Hours(), newDec);
251 if (m_vp.useAltAz)
252 test.EquatorialToHorizontal(data->lst(), data->geo()->lat());
253 Eigen::Vector2f t = toScreenVec(&test);
254 float dx = t.x() - x;
255 float dy = y - t.y(); //backwards because QWidget Y-axis increases to the bottom (FIXME: Check)
256 // float dx = dx_ * m_vp.rotationAngle.cos() - dy_ * m_vp.rotationAngle.sin();
257 // float dy = dx_ * m_vp.rotationAngle.sin() + dy_ * m_vp.rotationAngle.cos();
258 float north;
259 if (dy)
260 {
261 north = atan2f(dx, dy) * 180.0 / dms::PI;
262 }
263 else
264 {
265 north = (dx > 0.0 ? -90.0 : 90.0);
266 }
267
268 return north;
269}
270
271double Projector::findPA(const SkyObject *o, float x, float y) const
272{
273 return (findNorthPA(o, x, y) + (m_vp.mirror ? -o->pa() : o->pa()));
274}
275
276double Projector::findZenithPA(const SkyPoint *o, float x, float y) const
277{
278 //Find position angle of North using a test point displaced to the north
279 //displace by 100/zoomFactor radians (so distance is always 100 pixels)
280 //this is 5730/zoomFactor degrees
281
282 // N.B. It is not sufficient to find the angle at the center of
283 // the screen, and the angle of the zenith can vary drastically
284 // across the screen (e.g. when pointed towards the zenith)
285
286 KStarsData *data = KStarsData::Instance();
287 double newAlt = o->alt().Degrees() + 5730.0 / m_vp.zoomFactor;
288 if (newAlt > 90.0)
289 newAlt = 90.0;
290 SkyPoint test;
291 test.setAlt(newAlt);
292 test.setAz(o->az().Degrees());
293 if (!m_vp.useAltAz)
294 test.HorizontalToEquatorial(data->lst(), data->geo()->lat());
295 Eigen::Vector2f t = toScreenVec(&test);
296 float dx = t.x() - x;
297 float dy = y - t.y(); //backwards because QWidget Y-axis increases to the bottom (FIXME: Check)
298 // float dx = dx_ * m_vp.rotationAngle.cos() - dy_ * m_vp.rotationAngle.sin();
299 // float dy = dx_ * m_vp.rotationAngle.sin() + dy_ * m_vp.rotationAngle.cos();
300 float zenith;
301 if (dy)
302 {
303 zenith = atan2f(dx, dy) * 180.0 / dms::PI;
304 }
305 else
306 {
307 zenith = (dx > 0.0 ? -90.0 : 90.0);
308 }
309
310 return zenith;
311}
312
313QVector<Eigen::Vector2f> Projector::groundPoly(SkyPoint *labelpoint, bool *drawLabel) const
314{
316
317 static const QString horizonLabel = i18n("Horizon");
318 float marginLeft, marginRight, marginTop, marginBot;
319 SkyLabeler::Instance()->getMargins(horizonLabel, &marginLeft, &marginRight, &marginTop, &marginBot);
320
321 //daz is 1/2 the width of the sky in degrees
322 double daz = 90.;
323 if (m_vp.useAltAz && m_vp.rotationAngle.reduce().Degrees() == 0.0)
324 {
325 daz = 0.5 * m_vp.width / (dms::DegToRad * m_vp.zoomFactor); //center to edge, in degrees
326 if (type() == Projector::Orthographic)
327 {
328 daz = daz * 1.4;
329 }
330 daz = qMin(qreal(90.0), daz);
331 }
332
333 double faz = m_vp.focus->az().Degrees();
334 double az1 = faz - daz;
335 double az2 = faz + daz;
336
337 bool allGround = true;
338 bool allSky = true;
339
340 bool inverted = ((m_vp.rotationAngle + 90.0_deg).reduce().Degrees() > 180.);
341
342 double inc = 1.0;
343 //Add points along horizon
344 for (double az = az1; az <= az2 + inc; az += inc)
345 {
346 SkyPoint p = pointAt(az);
347 bool visible = false;
348 Eigen::Vector2f o = toScreenVec(&p, false, &visible);
349 if (visible)
350 {
351 ground.append(o);
352 //Set the label point if this point is onscreen
353 if (labelpoint && o.x() < marginRight && o.y() > marginTop && o.y() < marginBot)
354 *labelpoint = p;
355
356 if (o.y() > 0.)
357 (inverted ? allSky : allGround) = false;
358 if (o.y() < m_vp.height)
359 (inverted ? allGround : allSky) = false;
360 }
361 }
362
363 if (allSky)
364 {
365 if (drawLabel)
366 *drawLabel = false;
368 }
369
370 if (allGround)
371 {
372 ground.clear();
373 ground.append(Eigen::Vector2f(-10., -10.));
374 ground.append(Eigen::Vector2f(m_vp.width + 10., -10.));
375 ground.append(Eigen::Vector2f(m_vp.width + 10., m_vp.height + 10.));
376 ground.append(Eigen::Vector2f(-10., m_vp.height + 10.));
377 if (drawLabel)
378 *drawLabel = false;
379 return ground;
380 }
381
382 if (m_vp.mirror)
383 std::reverse(ground.begin(), ground.end());
384
385 //In Gnomonic projection, or if sufficiently zoomed in, we can complete
386 //the ground polygon by simply adding offscreen points
387 //FIXME: not just gnomonic
388 if (daz < 25.0 || type() == Projector::Gnomonic)
389 {
390 const float completion_height = (inverted ?
391 -10.f : m_vp.height + 10.f);
392 ground.append(Eigen::Vector2f(m_vp.width + 10.f, ground.last().y()));
393 ground.append(Eigen::Vector2f(m_vp.width + 10.f, completion_height));
394 ground.append(Eigen::Vector2f(-10.f, completion_height));
395 ground.append(Eigen::Vector2f(-10.f, ground.first().y()));
396 }
397 else
398 {
399 double r = m_vp.zoomFactor * radius();
400 double t1 =
401 atan2(-1. * (ground.last().y() - 0.5 * m_vp.height), ground.last().x() - 0.5 * m_vp.width) / dms::DegToRad;
402 double t2 = t1 - 180.;
403 for (double t = t1; t >= t2; t -= inc) //step along circumference
404 {
405 dms a(t);
406 double sa(0.), ca(0.);
407 a.SinCos(sa, ca);
408 ground.append(Eigen::Vector2f(0.5 * m_vp.width + r * ca, 0.5 * m_vp.height - r * sa));
409 }
410 }
411
412 if (drawLabel)
413 *drawLabel = true;
414 return ground;
415}
416
418{
419 m_clipPolygon.clear();
420
421 double r = m_vp.zoomFactor * radius();
422 double t1 = 0;
423 double t2 = 360;
424 double inc = 1.0;
425 for (double t = t1; t <= t2; t += inc)
426 {
427 //step along circumference
428 dms a(t);
429 double sa(0.), ca(0.);
430 a.SinCos(sa, ca);
431 m_clipPolygon << QPointF(0.5 * m_vp.width + r * ca, 0.5 * m_vp.height - r * sa);
432 }
433}
434
436{
437 return m_clipPolygon;
438}
439
441{
442 //r0 is the angular size of the sky horizon, in radians
443 double r0 = radius();
444 //If the zoom is high enough, all points are usable
445 //The center-to-corner distance, in radians
446 double r = 0.5 * 1.41421356 * m_vp.width / m_vp.zoomFactor;
447 if (r < r0)
448 return false;
449 //At low zoom, we have to determine whether the point is beyond the sky horizon
450 //Convert pixel position to x and y offsets in radians
451
452 // N.B. Technically, rotation does not affect the dx² + dy²
453 // metric, but we use the derst method for uniformity; this
454 // function is not perf critical
455 auto p_ = derst(p.x(), p.y());
456 double dx = p_[0], dy = p_[1];
457 return (dx * dx + dy * dy) > r0 * r0;
458}
459
460SkyPoint Projector::fromScreen(const QPointF &p, dms *LST, const dms *lat, bool onlyAltAz) const
461{
462 dms c;
463 double sinc, cosc;
464 /** N.B. We don't cache these sin/cos values in the inverse
465 * projection because it causes 'shaking' when moving the sky.
466 */
467 double sinY0, cosY0;
468 //Convert pixel position to x and y offsets in radians
469 auto p_ = derst(p.x(), p.y());
470 double dx = p_[0], dy = p_[1];
471
472 double r = sqrt(dx * dx + dy * dy);
473 c.setRadians(projectionL(r));
474 c.SinCos(sinc, cosc);
475
476 if (m_vp.useAltAz)
477 {
478 dx = -1.0 * dx; //Azimuth goes in opposite direction compared to RA
479 SkyPoint::refract(m_vp.focus->alt(), m_vp.useRefraction).SinCos(sinY0, cosY0);
480 }
481 else
482 {
483 m_vp.focus->dec().SinCos(sinY0, cosY0);
484 }
485
486 double Y = asin(cosc * sinY0 + (r == 0 ? 0 : (dy * sinc * cosY0) / r));
487 double atop = dx * sinc;
488 double abot = r * cosY0 * cosc - dy * sinY0 * sinc;
489 double A = atan2(atop, abot);
490
491 SkyPoint result;
492 if (m_vp.useAltAz)
493 {
494 dms alt, az;
495 alt.setRadians(Y);
496 az.setRadians(A + m_vp.focus->az().radians());
497 if (m_vp.useRefraction)
498 alt = SkyPoint::unrefract(alt);
499 result.setAlt(alt);
500 result.setAz(az);
501 if (onlyAltAz)
502 return result;
503 result.HorizontalToEquatorial(LST, lat);
504 }
505 else
506 {
507 dms ra, dec;
508 dec.setRadians(Y);
509 ra.setRadians(A + m_vp.focus->ra().radians());
510 result.set(ra.reduce(), dec);
511 result.EquatorialToHorizontal(LST, lat);
512 }
513
514 return result;
515}
516
517Eigen::Vector2f Projector::toScreenVec(const SkyPoint *o, bool oRefract, bool *onVisibleHemisphere) const
518{
519 double Y, dX;
520 double sindX, cosdX, sinY, cosY;
521
522 oRefract &= m_vp.useRefraction;
523 if (m_vp.useAltAz)
524 {
525 if (oRefract)
526 Y = SkyPoint::refract(o->alt()).radians(); //account for atmospheric refraction
527 else
528 Y = o->alt().radians();
529 dX = m_vp.focus->az().radians() - o->az().radians();
530 }
531 else
532 {
533 dX = o->ra().radians() - m_vp.focus->ra().radians();
534 Y = o->dec().radians();
535 }
536
537 if (!(std::isfinite(Y) && std::isfinite(dX)))
538 {
539 return Eigen::Vector2f(0, 0);
540
541 // JM: Enable this again later when trying to find a solution for it
542 // As it is now creating too much noise in the log file.
543 /*
544 qDebug() << Q_FUNC_INFO << "Assert in Projector::toScreenVec failed!";
545 qDebug() << Q_FUNC_INFO << "using AltAz?" << m_vp.useAltAz << " Refract? " << oRefract;
546 const SkyObject *obj;
547 qDebug() << Q_FUNC_INFO << "Point supplied has RA0 = " << o->ra0().toHMSString() << " Dec0 = " << o->dec0().toDMSString() << "; alt = " << o->alt().toDMSString() << "; az = " << o->az().toDMSString();
548 if ( (obj = dynamic_cast<const SkyObject *>(o) ) ) {
549 qDebug() << Q_FUNC_INFO << "Point is object with name = " << obj->name() << " longname = " << obj->longname();
550 }
551 qDebug() << Q_FUNC_INFO << "dX = " << dX << " and isfinite(dX) is" << std::isfinite(dX);
552 qDebug() << Q_FUNC_INFO << "Y = " << Y << " and isfinite(Y) is" << std::isfinite(Y);
553
554 //Q_ASSERT( false );
555 */
556 }
557
558 dX = KSUtils::reduceAngle(dX, -dms::PI, dms::PI);
559
560 //Convert dX, Y coords to screen pixel coords, using GNU extension if available
561#ifdef HAVE_SINCOS
562 sincos(dX, &sindX, &cosdX);
563 sincos(Y, &sinY, &cosY);
564#else
565 sindX = sin(dX);
566 cosdX = cos(dX);
567 sinY = sin(Y);
568 cosY = cos(Y);
569#endif
570
571 //c is the cosine of the angular distance from the center
572 double c = m_sinY0 * sinY + m_cosY0 * cosY * cosdX;
573
574 //If c is less than 0.0, then the "field angle" (angular distance from the focus)
575 //is more than 90 degrees. This is on the "back side" of the celestial sphere
576 //and should not be drawn.
577 if (onVisibleHemisphere)
578 *onVisibleHemisphere =
579 (c >
580 cosMaxFieldAngle()); // TODO: Isn't it more efficient to bypass the final calculation below if the object is not visible?
581
582 double k = projectionK(c);
583
584 auto p = rst(k * cosY * sindX, k * (m_cosY0 * sinY - m_sinY0 * cosY * cosdX));
585
586#ifdef KSTARS_LITE
587 double skyRotation = SkyMapLite::Instance()->getSkyRotation();
588 // FIXME: Port above to change the m_vp.rotationAngle, or
589 // deprecate it
590 Q_ASSERT(false);
591#endif
592 return p;
593}
const CachingDms * lat() const
Definition geolocation.h:70
KStarsData is the backbone of KStars.
Definition kstarsdata.h:74
CachingDms * lst()
Definition kstarsdata.h:226
GeoLocation * geo()
Definition kstarsdata.h:232
Eigen::Vector2f derst(double x, double y) const
Transform screen (x, y) to projector (x, y) accounting for scale, rotation.
Definition projector.h:336
virtual double cosMaxFieldAngle() const
This function returns the cosine of the maximum field angle, i.e., the maximum angular distance from ...
Definition projector.h:299
virtual SkyPoint fromScreen(const QPointF &p, dms *LST, const dms *lat, bool onlyAltAz=false) const
Determine RA, Dec coordinates of the pixel at (dx, dy), which are the screen pixel coordinate offsets...
QPointF toScreen(const SkyPoint *o, bool oRefract=true, bool *onVisibleHemisphere=nullptr) const
This is exactly the same as toScreenVec but it returns a QPointF.
Definition projector.cpp:93
Eigen::Vector2f rst(double x, double y) const
Transform proj (x, y) to screen (x, y) accounting for scale and rotation.
Definition projector.h:314
virtual double projectionK(double x) const
This function handles some of the projection-specific code.
Definition projector.h:280
double findZenithPA(const SkyPoint *o, float x, float y) const
Determine the on-screen angle of a SkyPoint with respect to Zenith.
double findPA(const SkyObject *o, float x, float y) const
Determine the on-screen position angle of a SkyObject.
virtual bool unusablePoint(const QPointF &p) const
Check if the current point on screen is a valid point on the sky.
bool onScreen(const QPointF &p) const
Check whether the projected point is on-screen.
Definition projector.cpp:98
virtual Eigen::Vector2f toScreenVec(const SkyPoint *o, bool oRefract=true, bool *onVisibleHemisphere=nullptr) const
Given the coordinates of the SkyPoint argument, determine the pixel coordinates in the SkyMap.
Eigen::Vector2f clipLineVec(SkyPoint *p1, SkyPoint *p2) const
ASSUMES *p1 did not clip but *p2 did.
double findNorthPA(const SkyPoint *o, float x, float y) const
Determine the on-screen position angle of a SkyPont with recept with NCP.
virtual QPolygonF clipPoly() const
void setViewParams(const ViewParams &p)
Update cached values for projector.
Definition projector.cpp:46
static SkyPoint pointAt(double az)
Helper function for drawing ground.
Definition projector.cpp:29
double fov() const
Return the FOV of this projection.
Definition projector.cpp:88
bool checkVisibility(const SkyPoint *p) const
Determine if the skypoint p is likely to be visible in the display window.
virtual QVector< Eigen::Vector2f > groundPoly(SkyPoint *labelpoint=nullptr, bool *drawLabel=nullptr) const
Get the ground polygon.
virtual double projectionL(double x) const
This function handles some of the projection-specific code.
Definition projector.h:289
virtual double radius() const
Get the radius of this projection's sky circle.
Definition projector.h:271
QPointF clipLine(SkyPoint *p1, SkyPoint *p2) const
ASSUMES *p1 did not clip but *p2 did.
virtual Q_INVOKABLE Projection type() const =0
Return the type of this projection.
Projector(const ViewParams &p)
Constructor.
Definition projector.cpp:38
virtual void updateClipPoly()
updateClipPoly calculate the clipping polygen given the current FOV.
void getMargins(const QString &text, float *left, float *right, float *top, float *bot)
sets four margins for help in keeping labels entirely on the screen.
Provides all necessary information about an object in the sky: its coordinates, name(s),...
Definition skyobject.h:42
virtual double pa() const
Definition skyobject.h:213
The sky coordinates of a point in the sky.
Definition skypoint.h:45
static double refract(const double alt, bool conditional=true)
Apply refraction correction to altitude, depending on conditional.
static const double altCrit
Critical height for atmospheric refraction corrections.
Definition skypoint.h:727
const CachingDms & dec() const
Definition skypoint.h:269
const CachingDms & ra() const
Definition skypoint.h:263
static double unrefract(const double alt, bool conditional=true)
Remove refraction correction, depending on conditional.
This is just a container that holds information needed to do projections.
Definition projector.h:37
bool fillGround
If the ground is filled, then points below horizon are invisible.
Definition projector.h:44
static constexpr double PI
PI is a const static member; it's public so that it can be used anywhere, as long as dms....
Definition dms.h:385
static constexpr double DegToRad
DegToRad is a const static member equal to the number of radians in one degree (dms::PI/180....
Definition dms.h:390
QString i18n(const char *text, const TYPE &arg...)
void append(QList< T > &&value)
iterator begin()
void clear()
iterator end()
T & first()
T & last()
qreal x() const const
qreal y() const const
This file is part of the KDE documentation.
Documentation copyright © 1996-2024 The KDE developers.
Generated on Fri Dec 6 2024 12:09:53 by doxygen 1.12.0 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.