[prev in list] [next in list] [prev in thread] [next in thread] 

List:       kstars-devel
Subject:    [education/kstars] kstars: [Needs testing] Major refactoring of refraction corrections that fixes so
From:       Akarsh Simha <null () kde ! org>
Date:       2020-07-06 6:21:17
Message-ID: 20200706062117.0FE741241C81 () leptone ! kde ! org
[Download RAW message or body]

Git commit e3dc576f5e1fc90a76916a346dedabe5ce43cc5e by Akarsh Simha.
Committed on 06/07/2020 at 06:10.
Pushed by asimha into branch 'master'.

[Needs testing] Major refactoring of refraction corrections that fixes some bugs

* Potentially introduces some new bugs and therefore needs extensive testing!! *

Potential bugs in SkyMapLite and Android version!

Summary of changes:

SkyPoint does not have a way of differentiating between refracted (apparent) and
actual altitude. The convention has been that the altitude stored in SkyPoint is
always the actual altitude (without refraction corrections) and the refracted
altitude is calculated whenever it is needed.

The reason this matters is because we sometimes call
SkyPoint::HorizontalToEquatorial, which assumes that the altitude in the
SkyPoint is the actual altitude.

However, SkyMap::focus() actually broke this convention! We saved haphazardly
either the refraction-corrected or un-refracted altitude in SkyPoint.

This patch changes the behavior so that SkyMap::focus() is always interpreted as
unrefracted. SkyMap::setFocusAltAz() similarly assumes that the inputs are
actual and not apparent altitudes.

Things I have tested:
1. Slewing of the sky map by mouse
2. Slewing of the sky map by keys
3. Popup menu and some operations therein that use coordinates (Details, DSS...)
4. Enabling and disabling refraction corrections
5. DBus "setRaDec", "setRaDecJ2000" and "setAltAz" methods

Things I have not tested:

1. SkyMapLite / Android versions [although I've tried to port the changes to
   SkyMapLite, there may be things I've overlooked]

2. Equirectangular projection (which is handled rather differently)

3. Ekos / INDI performance

Overall, I believe the change should actually resolve bugs that we didn't know
existed, because of the HorizontalToEquatorial call on refracted coordinates.

I've also added new convenience methods to SkyPoint (SkyPoint::setAltRefracted)
and a bool argument to SkyPoint::refract / SkyPoint::unrefract that helps
simplify code in many places.

Known problems that still exist:
1. "Set Coordinates Manually" does not work as expected
2. The Alt/Az grid is slightly offset from where it should be (Why???)
3. There are computational issues / instability in rendering the Alt/Az grid at the zenith

Potential new problem? Probably not:
Sometimes, there are inconsistencies in the way DeepStars are handled. I get errors like:

WARNING: Marking block with faint mag =  8.71  after block with faint mag  13.56 in trixel 378
Trixel  0 : ERROR: faintMag of prev block =  9.31 , brightMag of block # 1  =  9.92

But I've been unable to reproduce this "before" the patch, but I haven't tried extensively.

CCMAIL: kstars-devel@kde.org

M  +10   -8    kstars/kstarsactions.cpp
M  +2    -0    kstars/kstarsdata.cpp
M  +5    -6    kstars/projections/equirectangularprojector.cpp
M  +7    -3    kstars/projections/projector.cpp
M  +10   -5    kstars/skymap.cpp
M  +3    -2    kstars/skymap.h
M  +6    -6    kstars/skymapevents.cpp
M  +16   -6    kstars/skymaplite.cpp
M  +3    -2    kstars/skymaplite.h
M  +4    -4    kstars/skymapliteevents.cpp
M  +20   -7    kstars/skyobjects/skypoint.cpp
M  +29   -10   kstars/skyobjects/skypoint.h

https://invent.kde.org/education/kstars/commit/e3dc576f5e1fc90a76916a346dedabe5ce43cc5e

diff --git a/kstars/kstarsactions.cpp b/kstars/kstarsactions.cpp
index 063d893e2..44617b09c 100644
--- a/kstars/kstarsactions.cpp
+++ b/kstars/kstarsactions.cpp
@@ -1409,15 +1409,15 @@ void KStars::slotPointFocus()
     map()->stopTracking();
 
     if (sender() == actionCollection()->action("zenith"))
-        map()->setDestinationAltAz(dms(90.0), map()->focus()->az());
+        map()->setDestinationAltAz(dms(90.0), map()->focus()->az(), Options::useRefraction());
     else if (sender() == actionCollection()->action("north"))
-        map()->setDestinationAltAz(dms(15.0), dms(0.0001));
+        map()->setDestinationAltAz(dms(15.0), dms(0.0001), Options::useRefraction());
     else if (sender() == actionCollection()->action("east"))
-        map()->setDestinationAltAz(dms(15.0), dms(90.0));
+        map()->setDestinationAltAz(dms(15.0), dms(90.0), Options::useRefraction());
     else if (sender() == actionCollection()->action("south"))
-        map()->setDestinationAltAz(dms(15.0), dms(180.0));
+        map()->setDestinationAltAz(dms(15.0), dms(180.0), Options::useRefraction());
     else if (sender() == actionCollection()->action("west"))
-        map()->setDestinationAltAz(dms(15.0), dms(270.0));
+        map()->setDestinationAltAz(dms(15.0), dms(270.0), Options::useRefraction());
 }
 
 void KStars::slotTrack()
@@ -1500,7 +1500,7 @@ void KStars::slotManualFocus()
         data()->setSnapNextFocus();
         if (Options::useAltAz())
         {
-            map()->setDestinationAltAz(focusDialog->point()->alt(), focusDialog->point()->az());
+            map()->setDestinationAltAz(focusDialog->point()->alt(), focusDialog->point()->az(), \
Options::useRefraction());  }
         else
         {
@@ -1574,7 +1574,8 @@ void KStars::slotCoordSys()
                 map()->setFocus(map()->focusObject());
             else //need to recompute focus for unrefracted position
             {
-                map()->setFocusAltAz(SkyPoint::unrefract(map()->focus()->alt()), map()->focus()->az());
+                // FIXME: Changed focus()->alt() to be unrefracted by convention; is this still \
necessary? -- asimha 2020/07/05 +                map()->setFocusAltAz(map()->focus()->alt(), \
                map()->focus()->az());
                 map()->focus()->HorizontalToEquatorial(data()->lst(), data()->geo()->lat());
             }
         }
@@ -1585,7 +1586,8 @@ void KStars::slotCoordSys()
         Options::setUseAltAz(true);
         if (Options::useRefraction())
         {
-            map()->setFocusAltAz(map()->focus()->altRefracted(), map()->focus()->az());
+            // FIXME: Changed focus()->alt() to be unrefracted by convention; is this still necessary? \
-- asimha 2020/07/05 +            map()->setFocusAltAz(map()->focus()->alt(), map()->focus()->az());
         }
         actionCollection()->action("coordsys")->setText(i18n("Switch to star globe view (Equatorial \
&Coordinates)"));  }
diff --git a/kstars/kstarsdata.cpp b/kstars/kstarsdata.cpp
index 8f13fb18e..9319503bc 100644
--- a/kstars/kstarsdata.cpp
+++ b/kstars/kstarsdata.cpp
@@ -964,6 +964,7 @@ bool KStarsData::executeScript(const QString &scriptname, SkyMap *map)
                     az = 335.0;
                 if (az >= 0.0)
                 {
+                    // N.B. unrefract() doesn't matter at 90 degrees
                     map->setFocusAltAz(dms(90.0), map->focus()->az());
                     map->focus()->HorizontalToEquatorial(&LST, geo()->lat());
                     map->setDestination(*map->focus());
@@ -972,6 +973,7 @@ bool KStarsData::executeScript(const QString &scriptname, SkyMap *map)
 
                 if (arg == "z" || arg == "zenith")
                 {
+                    // N.B. unrefract() doesn't matter at 90 degrees
                     map->setFocusAltAz(dms(90.0), map->focus()->az());
                     map->focus()->HorizontalToEquatorial(&LST, geo()->lat());
                     map->setDestination(*map->focus());
diff --git a/kstars/projections/equirectangularprojector.cpp \
b/kstars/projections/equirectangularprojector.cpp index 0d1b3ce65..f211cd46f 100644
--- a/kstars/projections/equirectangularprojector.cpp
+++ b/kstars/projections/equirectangularprojector.cpp
@@ -46,13 +46,12 @@ Vector2f EquirectangularProjector::toScreenVec(const SkyPoint *o, bool oRefract,
     oRefract &= m_vp.useRefraction;
     if (m_vp.useAltAz)
     {
-        if (oRefract)
-            Y = SkyPoint::refract(o->alt()).radians(); //account for atmospheric refraction
-        else
-            Y = o->alt().radians();
+        double Y0;
+        Y = SkyPoint::refract(o->alt(), oRefract).radians(); //account for atmospheric refraction
+        Y0 = SkyPoint::refract(m_vp.focus->alt(), oRefract).radians();
         dX = m_vp.focus->az().reduce().radians() - o->az().reduce().radians();
 
-        p[1] = 0.5 * m_vp.height - m_vp.zoomFactor * (Y - m_vp.focus->alt().radians());
+        p[1] = 0.5 * m_vp.height - m_vp.zoomFactor * (Y - Y0);
     }
     else
     {
@@ -84,7 +83,7 @@ SkyPoint EquirectangularProjector::fromScreen(const QPointF &p, dms *LST, const
         dms az, alt;
         dx = -1.0 * dx; //Azimuth goes in opposite direction compared to RA
         az.setRadians(dx + m_vp.focus->az().radians());
-        alt.setRadians(dy + m_vp.focus->alt().radians());
+        alt.setRadians(dy + SkyPoint::refract(m_vp.focus->alt(), m_vp.useRefraction).radians());
         result.setAz(az.reduce());
         if (m_vp.useRefraction)
             alt = SkyPoint::unrefract(alt);
diff --git a/kstars/projections/projector.cpp b/kstars/projections/projector.cpp
index d23dd004d..a2b7ef065 100644
--- a/kstars/projections/projector.cpp
+++ b/kstars/projections/projector.cpp
@@ -66,7 +66,11 @@ void Projector::setViewParams(const ViewParams &p)
     m_cosY0 = 0;
     if (m_vp.useAltAz)
     {
-        m_vp.focus->alt().SinCos(m_sinY0, m_cosY0);
+        // N.B. We explicitly check useRefraction and not use
+        // SkyPoint::altRefracted() here because it could be different
+        // from Options::useRefraction() in some future use-case
+        // --asimha
+        SkyPoint::refract(m_vp.focus->alt(), m_vp.useRefraction).SinCos(m_sinY0, m_cosY0);
     }
     else
     {
@@ -81,7 +85,7 @@ void Projector::setViewParams(const ViewParams &p)
     m_xrange = 1.2 * m_fov / m_cosY0;
     if (m_vp.useAltAz)
     {
-        Ymax     = fabs(m_vp.focus->alt().Degrees()) + m_fov;
+        Ymax     = fabs(SkyPoint::refract(m_vp.focus->alt().Degrees(), m_vp.useRefraction)) + m_fov;
     }
     else
     {
@@ -431,7 +435,7 @@ SkyPoint Projector::fromScreen(const QPointF &p, dms *LST, const dms *lat) const
     if (m_vp.useAltAz)
     {
         dx = -1.0 * dx; //Azimuth goes in opposite direction compared to RA
-        m_vp.focus->alt().SinCos(sinY0, cosY0);
+        SkyPoint::refract(m_vp.focus->alt(), m_vp.useRefraction).SinCos(sinY0, cosY0);
     }
     else
     {
diff --git a/kstars/skymap.cpp b/kstars/skymap.cpp
index 54c5da504..c7e7b318b 100644
--- a/kstars/skymap.cpp
+++ b/kstars/skymap.cpp
@@ -312,7 +312,7 @@ void SkyMap::slotTransientLabel()
     //(HoverTimer is restarted with every mouseMoveEvent; so if it times
     //out, that means there was no mouse movement for HOVER_INTERVAL msec.)
     if (hasFocus() && !slewing &&
-            !(Options::useAltAz() && Options::showGround() && \
SkyPoint::refract(m_MousePoint.alt()).Degrees() < 0.0)) +            !(Options::useAltAz() && \
Options::showGround() && m_MousePoint.altRefracted().Degrees() < 0.0))  {
         double maxrad = 1000.0 / Options::zoomFactor();
         SkyObject *so = data->skyComposite()->objectNearest(&m_MousePoint, maxrad);
@@ -423,7 +423,7 @@ void SkyMap::slotCenter()
     //update the destination to the selected coordinates
     if (Options::useAltAz())
     {
-        setDestinationAltAz(foc->altRefracted(), foc->az());
+        setDestinationAltAz(foc->alt(), foc->az(), false);
     }
     else
     {
@@ -999,9 +999,14 @@ void SkyMap::setDestination(const dms &ra, const dms &dec)
     emit destinationChanged();
 }
 
-void SkyMap::setDestinationAltAz(const dms &alt, const dms &az)
+void SkyMap::setDestinationAltAz(const dms &alt, const dms &az, bool altIsRefracted)
 {
-    destination()->setAlt(alt);
+    if (altIsRefracted) {
+        // The alt in the SkyPoint is always actual, not apparent
+        destination()->setAlt(SkyPoint::unrefract(alt));
+    } else {
+        destination()->setAlt(alt);
+    }
     destination()->setAz(az);
     destination()->HorizontalToEquatorial(data->lst(), data->geo()->lat());
     emit destinationChanged();
@@ -1024,7 +1029,7 @@ void SkyMap::updateFocus()
         {
             //Tracking any object in Alt/Az mode requires focus updates
             focusObject()->EquatorialToHorizontal(data->lst(), data->geo()->lat());
-            setFocusAltAz(focusObject()->altRefracted(), focusObject()->az());
+            setFocusAltAz(focusObject()->alt(), focusObject()->az());
             focus()->HorizontalToEquatorial(data->lst(), data->geo()->lat());
             setDestination(*focus());
         }
diff --git a/kstars/skymap.h b/kstars/skymap.h
index 9a890b878..b248f1879 100644
--- a/kstars/skymap.h
+++ b/kstars/skymap.h
@@ -168,7 +168,7 @@ class SkyMap : public QGraphicsView
         void setFocus(const dms &ra, const dms &dec);
 
         /** @short sets the focus point of the sky map, using its alt/az coordinates
-                *@param alt the new altitude
+                *@param alt the new altitude (actual, without refraction correction)
                 *@param az the new azimuth
                 */
         void setFocusAltAz(const dms &alt, const dms &az);
@@ -195,8 +195,9 @@ class SkyMap : public QGraphicsView
         /** @short sets the destination point of the sky map, using its alt/az coordinates.
                 *@param alt the new altitude
                 *@param az the new azimuth
+                *@param altIsRefracted set to true if the altitude supplied is apparent
                 */
-        void setDestinationAltAz(const dms &alt, const dms &az);
+        void setDestinationAltAz(const dms &alt, const dms &az, bool altIsRefracted);
 
         /** @short set the FocusPoint; the position that is to be the next Destination.
                 *@param f a pointer to the FocusPoint SkyPoint.
diff --git a/kstars/skymapevents.cpp b/kstars/skymapevents.cpp
index 5dd1ccd0d..612f4f5dc 100644
--- a/kstars/skymapevents.cpp
+++ b/kstars/skymapevents.cpp
@@ -116,7 +116,7 @@ void SkyMap::keyPressEvent(QKeyEvent *e)
         case Qt::Key_Up:
             if (Options::useAltAz())
             {
-                focus()->setAlt(focus()->alt().Degrees() + step * MINZOOM / Options::zoomFactor());
+                focus()->setAltRefracted(focus()->altRefracted().Degrees() + step * MINZOOM / \
Options::zoomFactor());  if (focus()->alt().Degrees() > 90.0)
                     focus()->setAlt(90.0);
                 focus()->HorizontalToEquatorial(data->lst(), data->geo()->lat());
@@ -136,7 +136,7 @@ void SkyMap::keyPressEvent(QKeyEvent *e)
         case Qt::Key_Down:
             if (Options::useAltAz())
             {
-                focus()->setAlt(focus()->alt().Degrees() - step * MINZOOM / Options::zoomFactor());
+                focus()->setAltRefracted(focus()->altRefracted().Degrees() - step * MINZOOM / \
Options::zoomFactor());  if (focus()->alt().Degrees() < -90.0)
                     focus()->setAlt(-90.0);
                 focus()->HorizontalToEquatorial(data->lst(), data->geo()->lat());
@@ -483,7 +483,7 @@ void SkyMap::keyReleaseEvent(QKeyEvent *e)
             slewing = false;
 
             if (Options::useAltAz())
-                setDestinationAltAz(focus()->alt(), focus()->az());
+                setDestinationAltAz(focus()->alt(), focus()->az(), false);
             else
                 setDestination(*focus());
 
@@ -583,10 +583,10 @@ void SkyMap::mouseMoveEvent(QMouseEvent *e)
             m_MousePoint.EquatorialToHorizontal(data->lst(), data->geo()->lat());
             clickedPoint()->EquatorialToHorizontal(data->lst(), data->geo()->lat());
             dms dAz  = m_MousePoint.az() - clickedPoint()->az();
-            dms dAlt = m_MousePoint.alt() - clickedPoint()->alt();
+            dms dAlt = m_MousePoint.altRefracted() - clickedPoint()->altRefracted();
             focus()->setAz(focus()->az().Degrees() - dAz.Degrees()); //move focus in opposite direction
             focus()->setAz(focus()->az().reduce());
-            focus()->setAlt(KSUtils::clamp(focus()->alt().Degrees() - dAlt.Degrees(), -90.0, 90.0));
+            focus()->setAltRefracted(KSUtils::clamp(focus()->altRefracted().Degrees() - dAlt.Degrees(), \
                -90.0, 90.0));
             focus()->HorizontalToEquatorial(data->lst(), data->geo()->lat());
         }
         else
@@ -663,7 +663,7 @@ void SkyMap::mouseReleaseEvent(QMouseEvent *e)
         {
             slewing = false;
             if (Options::useAltAz())
-                setDestinationAltAz(focus()->alt(), focus()->az());
+                setDestinationAltAz(focus()->alt(), focus()->az(), false);
             else
                 setDestination(*focus());
         }
diff --git a/kstars/skymaplite.cpp b/kstars/skymaplite.cpp
index b5f2df39d..28f06be59 100644
--- a/kstars/skymaplite.cpp
+++ b/kstars/skymaplite.cpp
@@ -298,9 +298,14 @@ void SkyMapLite::setDestination(const dms &ra, const dms &dec)
     emit destinationChanged();
 }
 
-void SkyMapLite::setDestinationAltAz(const dms &alt, const dms &az)
+void SkyMapLite::setDestinationAltAz(const dms &alt, const dms &az, bool altIsRefracted)
 {
-    destination()->setAlt(alt);
+    if (altIsRefracted) {
+        // The alt in the SkyPoint is always actual, not apparent
+        destination()->setAlt(SkyPoint::unrefract(alt));
+    } else {
+        destination()->setAlt(alt);
+    }
     destination()->setAz(az);
     destination()->HorizontalToEquatorial(data->lst(), data->geo()->lat());
     emit destinationChanged();
@@ -386,7 +391,7 @@ void SkyMapLite::slotCenter()
     //update the destination to the selected coordinates
     if (Options::useAltAz())
     {
-        setDestinationAltAz(focusPoint()->altRefracted(), focusPoint()->az());
+        setDestinationAltAz(focusPoint()->alt(), focusPoint()->az(), false);
     }
     else
     {
@@ -539,7 +544,7 @@ void SkyMapLite::slotClockSlewing()
         if ( Options::useAltAz() ) {
             //Tracking any object in Alt/Az mode requires focus updates
             focusObject()->EquatorialToHorizontal(data->lst(), data->geo()->lat());
-            setFocusAltAz( focusObject()->altRefracted(), focusObject()->az() );
+            setFocusAltAz( focusObject()->alt(), focusObject()->az() );
             focus()->HorizontalToEquatorial( data->lst(), data->geo()->lat() );
             setDestination( *focus() );
         } else {
@@ -702,7 +707,7 @@ void SkyMapLite::updateFocus()
         {
             //Tracking any object in Alt/Az mode requires focus updates
             focusObject()->EquatorialToHorizontal(data->lst(), data->geo()->lat());
-            setFocusAltAz(focusObject()->altRefracted(), focusObject()->az());
+            setFocusAltAz(focusObject()->alt(), focusObject()->az());
             focus()->HorizontalToEquatorial(data->lst(), data->geo()->lat());
             setDestination(*focus());
         }
@@ -982,7 +987,12 @@ void SkyMapLite::updateAutomaticMode()
 {
 #if defined(Q_OS_ANDROID)
     m_deviceOrientation->getOrientation();
-    setFocusAltAz(dms(m_deviceOrientation->getAltitude()), dms(m_deviceOrientation->getAzimuth()));
+    if (Options::useRefraction() && Options::useAltAz()) {
+        setFocusAltAz(SkyPoint::unrefract(dms(m_deviceOrientation->getAltitude())), \
dms(m_deviceOrientation->getAzimuth())); +    } else {
+        setFocusAltAz(dms(m_deviceOrientation->getAltitude()), dms(m_deviceOrientation->getAzimuth()));
+    }
+
     setSkyRotation(-1 * m_deviceOrientation->getRoll());
 #endif
 }
diff --git a/kstars/skymaplite.h b/kstars/skymaplite.h
index 98a80fda4..9b12da7a1 100644
--- a/kstars/skymaplite.h
+++ b/kstars/skymaplite.h
@@ -178,7 +178,7 @@ class SkyMapLite : public QQuickItem
         void setFocus(const dms &ra, const dms &dec);
 
         /** @short sets the focus point of the sky map, using its alt/az coordinates
-             *@param alt the new altitude
+             *@param alt the new altitude (actual, i.e. without refraction correction)
              *@param az the new azimuth
              */
         void setFocusAltAz(const dms &alt, const dms &az);
@@ -205,8 +205,9 @@ class SkyMapLite : public QQuickItem
         /** @short sets the destination point of the sky map, using its alt/az coordinates.
              *@param alt the new altitude
              *@param az the new azimuth
+             *@param altIsRefracted set to true if the altitude supplied is apparent
              */
-        void setDestinationAltAz(const dms &alt, const dms &az);
+        void setDestinationAltAz(const dms &alt, const dms &az, bool altIsRefracted);
 
         /** @short set the FocusPoint; the position that is to be the next Destination.
              *@param f a pointer to the FocusPoint SkyPoint.
diff --git a/kstars/skymapliteevents.cpp b/kstars/skymapliteevents.cpp
index 81e804243..ca59c5218 100644
--- a/kstars/skymapliteevents.cpp
+++ b/kstars/skymapliteevents.cpp
@@ -135,7 +135,7 @@ void SkyMapLite::mouseReleaseEvent(QMouseEvent *)
         {
             setSlewing(false);
             if (Options::useAltAz())
-                setDestinationAltAz(focus()->alt(), focus()->az());
+                setDestinationAltAz(focus()->alt(), focus()->az(), false);
             else
                 setDestination(*focus());
         }
@@ -230,10 +230,10 @@ void SkyMapLite::mouseMoveEvent(QMouseEvent *e)
             m_MousePoint.EquatorialToHorizontal(data->lst(), data->geo()->lat());
             clickedPoint()->EquatorialToHorizontal(data->lst(), data->geo()->lat());
             dms dAz  = m_MousePoint.az() - clickedPoint()->az();
-            dms dAlt = m_MousePoint.alt() - clickedPoint()->alt();
+            dms dAlt = m_MousePoint.altRefracted() - clickedPoint()->altRefracted();
             focus()->setAz(focus()->az().Degrees() - dAz.Degrees()); //move focus in opposite direction
             focus()->setAz(focus()->az().reduce());
-            focus()->setAlt(KSUtils::clamp(focus()->alt().Degrees() - dAlt.Degrees(), -90.0, 90.0));
+            focus()->setAltRefracted(KSUtils::clamp(focus()->altRefracted().Degrees() - dAlt.Degrees(), \
                -90.0, 90.0));
             focus()->HorizontalToEquatorial(data->lst(), data->geo()->lat());
         }
         else
@@ -396,7 +396,7 @@ void SkyMapLite::touchEvent(QTouchEvent *e)
             {
                 setSlewing(false);
                 if (Options::useAltAz())
-                    setDestinationAltAz(focus()->alt(), focus()->az());
+                    setDestinationAltAz(focus()->alt(), focus()->az(), false);
                 else
                     setDestination(*focus());
             }
diff --git a/kstars/skyobjects/skypoint.cpp b/kstars/skyobjects/skypoint.cpp
index 5a25586c7..4aaa9ec9f 100644
--- a/kstars/skyobjects/skypoint.cpp
+++ b/kstars/skyobjects/skypoint.cpp
@@ -954,10 +954,16 @@ bool SkyPoint::checkCircumpolar(const dms *gLat) const
 
 dms SkyPoint::altRefracted() const
 {
-    if (Options::useRefraction())
-        return refract(Alt);
-    else
-        return Alt;
+    return refract(Alt, Options::useRefraction());
+}
+
+void SkyPoint::setAltRefracted(dms alt_apparent)
+{
+    setAlt(unrefract(alt_apparent, Options::useRefraction()));
+}
+
+void SkyPoint::setAltRefracted(double alt_apparent) {
+    setAlt(unrefract(alt_apparent, Options::useRefraction()));
 }
 
 double SkyPoint::refractionCorr(double alt)
@@ -965,8 +971,11 @@ double SkyPoint::refractionCorr(double alt)
     return 1.02 / tan(dms::DegToRad * (alt + 10.3 / (alt + 5.11))) / 60;
 }
 
-double SkyPoint::refract(const double alt)
+double SkyPoint::refract(const double alt, bool conditional)
 {
+    if (!conditional) {
+        return alt;
+    }
     static double corrCrit = SkyPoint::refractionCorr(SkyPoint::altCrit);
 
     if (alt > SkyPoint::altCrit)
@@ -978,11 +987,15 @@ double SkyPoint::refract(const double alt)
 }
 
 // Found uncorrected value by solving equation. This is OK since
-// unrefract is never called in loops.
+// unrefract is never called in loops with the potential exception of
+// slewing.
 //
 // Convergence is quite fast just a few iterations.
-double SkyPoint::unrefract(const double alt)
+double SkyPoint::unrefract(const double alt, bool conditional)
 {
+    if (!conditional) {
+        return alt;
+    }
     double h0 = alt;
     double h1 =
         alt -
diff --git a/kstars/skyobjects/skypoint.h b/kstars/skyobjects/skypoint.h
index 5f0992bdb..fe881c39d 100644
--- a/kstars/skyobjects/skypoint.h
+++ b/kstars/skyobjects/skypoint.h
@@ -208,6 +208,21 @@ class SkyPoint
             Alt = alt;
         }
 
+    /**
+     * Sets the apparent altitude, checking whether refraction corrections are enabled
+     *
+     * @param alt_apparent Apparent altitude (subject to Options::useRefraction())
+     */
+    void setAltRefracted(dms alt_apparent);
+
+    /**
+     * Overloaded member function, provided for convenience.
+     * It behaves essentially like the above function.
+     *
+     * @param alt_apparent Apparent altitude (subject to Options::useRefraction())
+     */
+    void setAltRefracted(double alt_apparent);
+
         /**
          * Overloaded member function, provided for convenience.
          * It behaves essentially like the above function.
@@ -285,7 +300,7 @@ class SkyPoint
          * Options::useRefraction to determine whether refraction
          * correction should be applied
          */
-        dms altRefracted() const;
+    dms altRefracted() const;
 
         /** @return the JD for the precessed coordinates */
         inline double getLastPrecessJD() const
@@ -646,29 +661,33 @@ class SkyPoint
         static double refractionCorr(double alt);
 
         /**
-         * @short Apply refraction correction to altitude.
+         * @short Apply refraction correction to altitude, depending on conditional
          *
          * @param alt altitude to be corrected, in degrees
-         * @return altitude after refraction correction, in degrees
+         * @param conditional an optional boolean to decide whether to apply the correction or not
+         * @note If conditional is false, this method returns its argument unmodified. This is a \
convenience feature as it is often needed to gate these corrections. +         * @return altitude after \
                refraction correction (if applicable), in degrees
          */
-        static double refract(const double alt);
+    static double refract(const double alt, bool conditional=true);
 
         /**
-         * @short Remove refraction correction.
+         * @short Remove refraction correction, depending on conditional
          *
          * @param alt altitude from which refraction correction must be removed, in degrees
+         * @param conditional an optional boolean to decide whether to undo the correction or not
          * @return altitude without refraction correction, in degrees
+         * @note If conditional is false, this method returns its argument unmodified. This is a \
                convenience feature as it is often needed to gate these corrections.
          */
-        static double unrefract(const double alt);
+    static double unrefract(const double alt, bool conditional=true);
 
         /**
          * @short Apply refraction correction to altitude. Overloaded method using
          * dms provided for convenience
          * @see SkyPoint::refract( const double alt )
          */
-        static inline dms refract(const dms alt)
+    static inline dms refract(const dms alt, bool conditional=true)
         {
-            return dms(refract(alt.Degrees()));
+            return dms(refract(alt.Degrees(), conditional));
         }
 
         /**
@@ -676,9 +695,9 @@ class SkyPoint
          * dms provided for convenience
          * @see SkyPoint::unrefract( const double alt )
          */
-        static inline dms unrefract(const dms alt)
+    static inline dms unrefract(const dms alt, bool conditional=true)
         {
-            return dms(unrefract(alt.Degrees()));
+            return dms(unrefract(alt.Degrees(), conditional));
         }
 
         /**


[prev in list] [next in list] [prev in thread] [next in thread] 

Configure | About | News | Add a list | Sponsored by KoreLogic