Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Threaded planet computation (and a few more speedups) #3847

Merged
merged 32 commits into from
Sep 16, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
32 commits
Select commit Hold shift + click to select a range
f06ff1f
Handle std::execution issues with Clang/LLVM
gzotti Aug 9, 2024
b33736a
Add mutex for thread safety while reading data file
gzotti Jul 23, 2024
f40f243
Let solar system objects be updated concurrently
gzotti Jul 23, 2024
6faf529
Concurrent VSOP87, finally!
gzotti Jul 23, 2024
9afa86e
Allow playing with thread pool size
gzotti Jul 23, 2024
bc65461
Use just a few threads and split computation
gzotti Jul 25, 2024
a9c0c80
Add tiny circles as optional markers for minor bodies
gzotti Jul 26, 2024
6f8840d
Optimisation for terrestrial observers.
gzotti Jul 26, 2024
7d9deb2
Allow manual configuration of extra thread count
gzotti Jul 26, 2024
3e77189
Re-use StelPainter
gzotti Jul 27, 2024
b137c93
Allow batch drawing of asteroid and comet markers.
gzotti Aug 4, 2024
cc7945d
Avoid duplicate computations
gzotti Aug 6, 2024
3d2b83a
Further avoidance of repeated longish calls
gzotti Aug 6, 2024
86bc71c
Test again for culled-by-magnitude objects
gzotti Aug 6, 2024
fafe88a
Add a mag threshold for the markers.
gzotti Aug 13, 2024
b916df8
Allow selection of minor body when marker is plotted
gzotti Aug 13, 2024
a4dacaa
Make magnitude for minor bodies heliocentric if observed from an obse…
gzotti Aug 14, 2024
2f9605d
SUG: update these changes
gzotti Aug 14, 2024
4ff4aa6
Simplify SolarSystem::computePosition
10110111 Aug 22, 2024
66cbb5b
Avoid costly triple timezone lookup per frame
gzotti Aug 23, 2024
620154c
Compute transformation matrices in the computePositions threaded loop
10110111 Aug 23, 2024
00e26e3
Two string comparisons less per SSO
gzotti Aug 23, 2024
48a569b
Use StelObserver as argument
gzotti Aug 24, 2024
2c9963d
Add core as argument
gzotti Aug 24, 2024
a4dcab4
Reactivate blockwise manual thread assignment
gzotti Aug 24, 2024
248ba99
Improve marker mag threshold setting
gzotti Aug 25, 2024
5700684
Fix missing old-fashioned storing of new settings
gzotti Aug 27, 2024
93a011e
Rename button and action for minor body markers
gzotti Aug 27, 2024
b69962f
SUG: update details, new GUI figures
gzotti Aug 27, 2024
edf0407
Fix crash
gzotti Sep 11, 2024
9c8a757
Restore all 4 solutions for comparison
gzotti Sep 15, 2024
320b184
Restore transformation matrix application in the conservative solutions
gzotti Sep 15, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -1058,6 +1058,11 @@ IF(NOT FROM_CHARS_WORKS)
ADD_DEFINITIONS(-DUSE_FAST_FLOAT)
ENDIF()

include("cmake/Check-std_execution.cmake")
IF(STD_EXECUTION_KNOWN)
ADD_DEFINITIONS(-DSTD_EXECUTION_KNOWN)
ENDIF()

########### Top level include directories ###########
# This will be used for all compilations in sub-directories
INCLUDE_DIRECTORIES(
Expand Down
7 changes: 7 additions & 0 deletions cmake/Check-std_execution.cmake
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
message(STATUS "Checking that std::execution::par is supported by the C++ library")
try_compile(STD_EXECUTION_KNOWN "${CMAKE_BINARY_DIR}" "${CMAKE_CURRENT_LIST_DIR}/check-std_execution.cpp")
if(STD_EXECUTION_KNOWN)
message(STATUS "Checking that std::execution::par is supported by the C++ library - yes")
else()
message(STATUS "Checking that std::execution::par is supported by the C++ library - NO")
endif()
13 changes: 13 additions & 0 deletions cmake/check-std_execution.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
#include <array>
#include <execution>
#include <numeric>


const std::array<double, 4>a = {{0., 1., 2., 3.}};

int main()
{
double res = std::reduce(std::execution::par,
a.begin(), a.end(), 0.0, std::plus<>());
return 0;
}
26 changes: 26 additions & 0 deletions guide/ch_interface.tex
Original file line number Diff line number Diff line change
Expand Up @@ -391,6 +391,20 @@ \subsection{The Tools Tab}
from touch-enabled devices like smartphones.
\end{description}

\paragraph{Multithreading} \label{sec:gui:configuration:tools:threads}
For every frame, the positions of all planets and minor bodies of the Solar system are computed.
Most of the other time between frame updates is needed for the actual frame drawing,
and waiting for the next frame cycle if you have deliberately set a low frame rate (useful to conserve energy; see below).
If you have many thousands of solar system objects and a moderately new computer,
you may feel that Stellarium becomes slow (few frames/second) but see that mostly only one core of your CPU seems to be busy.
You can try\newFeature{24.3} to distribute the computation of solar system bodies to more CPU cores.
But take note, thread synchronization (combining all results ahead of drawing) takes its time,
so it pays off only when your solar system is really large.
With more than 1000 objects, we recommend starting with 1 additional thread.
Even with 25.000 objects, assigning more than 4 additional threads on a 20-core CPU does not show any further gain.
Frame drawing is still performed by the main thread, and too many objects still slow down the program.
Just try out what works best on your system.

\paragraph{Framerate intent} \label{sec:gui:configuration:tools:fps} The pace of screen updates (frames per second, FPS) depends on several factors:
CPU speed, graphics card speed, screen size, number of displayed objects and grids, etc.
As is common for interactive programs, the main program thread runs on a single core also on a multicore system.
Expand Down Expand Up @@ -679,6 +693,18 @@ \subsection{The Solar System Objects (SSO) Tab}
in the sky, which can be nice for didactic purposes or demonstrations.
\item[Planets] will increase the apparent size of major planets.
\end{description}
\item[Mark minor bodies] Show\newFeature{24.3} a little circle at the location of every minor body (comet,
asteroid, \ldots), down to the configured visual magnitude.
The marks are shown regardless of sky brightness, even in daytime. Also, in this mode, markers for objects
with highly outdated orbital elements are still plotted (see \ref{sec:plugins:SolarSystemEditor}
and Appendix~\ref{sec:ssystem.ini:minor}).
This is useful to show the distribution of asteroids and comets on the sky,
or especially when viewed from the Solar System Observer (see \ref{sec:gui:location:observers}).

From the ``Observer'' viewpoints, the visual magnitude for minor bodies is computed as seen from the Sun,
so that objects in inferior conjunction ae not dimmed down and filtered away by effects of phase angle,
and comet tails are better visible.

\item[Show orbits] adds a rendition of the orbit or trajectory of an SSO.
For efficiency, orbits are not displayed when the object is not inside the screen,
unless you set the ``permanently'' option. You can further fine-tune the selection
Expand Down
Binary file modified guide/pictures/config_dialog_tools_tab.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified guide/pictures/view_dialog_sso_tab.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
3 changes: 2 additions & 1 deletion plugins/NavStars/src/gui/NavStarsWindow.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -199,7 +199,8 @@ void NavStarsWindow::populateToday()
astronomicalTwilightDuration = StelUtils::hoursToHmsStr(duration, true);

// fill the data
ui->labelToday->setText(localeMgr->getPrintableDateLocal(core->getJD()));
const double JD=core->getJD();
ui->labelToday->setText(localeMgr->getPrintableDateLocal(JD, core->getUTCOffset(JD)));
ui->labelDayBegin->setText(dayBegin);
ui->labelDayEnd->setText(dayEnd);
ui->labelDayDuration->setText(dayDuration);
Expand Down
8 changes: 4 additions & 4 deletions plugins/Novae/src/Nova.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@
#include "StelCore.hpp"
#include "StelUtils.hpp"
#include "StelTranslator.hpp"
#include "StelModuleMgr.hpp"
//#include "StelModuleMgr.hpp"
#include "StelSkyDrawer.hpp"
#include "StelLocaleMgr.hpp"
#include "StelPainter.hpp"
Expand Down Expand Up @@ -130,9 +130,9 @@ QString Nova::getDesignation() const
return designation;
}

QString Nova::getMaxBrightnessDate(const double JD) const
QString Nova::getMaxBrightnessDate(const StelCore *core, const double JD) const
{
return StelApp::getInstance().getLocaleMgr().getPrintableDateLocal(JD);
return StelApp::getInstance().getLocaleMgr().getPrintableDateLocal(JD, core->getUTCOffset(JD));
}

QString Nova::getInfoString(const StelCore* core, const InfoStringGroup& flags) const
Expand All @@ -157,7 +157,7 @@ QString Nova::getInfoString(const StelCore* core, const InfoStringGroup& flags)

if (flags&Extra)
{
oss << QString("%1: %2").arg(q_("Maximum brightness"), getMaxBrightnessDate(peakJD)) << "<br />";
oss << QString("%1: %2").arg(q_("Maximum brightness"), getMaxBrightnessDate(core, peakJD)) << "<br />";
if (distance>0)
{
//TRANSLATORS: Unit of measure for distance - Light Years
Expand Down
2 changes: 1 addition & 1 deletion plugins/Novae/src/Nova.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -118,7 +118,7 @@ class Nova : public StelObject

static bool syncShowLabels;

QString getMaxBrightnessDate(const double JD) const;
QString getMaxBrightnessDate(const StelCore *core, const double JD) const;
};

#endif // NOVA_HPP
51 changes: 28 additions & 23 deletions plugins/Observability/src/Observability.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -766,12 +766,13 @@ void Observability::updateSunData(StelCore* core)
nDays = (year==sameYear)?366:365;

// Compute Earth's position throughout the year:
const StelObserver *obs=core->getCurrentObserver();
Vec3d pos, sunPos;
for (int i=0; i<nDays; i++)
{
yearJD[i].first = Jan1stJD + i;
yearJD[i].second = yearJD[i].first+core->computeDeltaT(yearJD[i].first)/86400.0;
myEarth->computePosition(yearJD[i].second, Vec3d(0.));
myEarth->computePosition(obs, yearJD[i].second, Vec3d(0.));
myEarth->computeTransMatrix(yearJD[i].first, yearJD[i].second);
pos = myEarth->getHeliocentricEclipticPos();
sunPos = core->j2000ToEquinoxEqu((StelCore::matVsop87ToJ2000)*(-pos), StelCore::RefractionOff);
Expand All @@ -780,7 +781,7 @@ void Observability::updateSunData(StelCore* core)
}

//Return the Earth to its current time:
myEarth->computePosition(myJD.second, Vec3d(0.));
myEarth->computePosition(obs, myJD.second, Vec3d(0.));
myEarth->computeTransMatrix(myJD.first, myJD.second);
}
///////////////////////////////////////////////////
Expand Down Expand Up @@ -989,16 +990,17 @@ void Observability::getSunMoonCoords(StelCore *core, QPair<double, double> JD,
double &eclLon, bool getBack)
//, Vec3d &AltAzVector)
{
const StelObserver *obs=core->getCurrentObserver();
if (getBack) // Return the Moon and Earth to their current position:
{
myEarth->computePosition(JD.second, Vec3d(0.));
myEarth->computePosition(obs, JD.second, Vec3d(0.));
myEarth->computeTransMatrix(JD.first, JD.second);
myMoon->computePosition(JD.second, Vec3d(0.));
myMoon->computePosition(obs, JD.second, Vec3d(0.));
myMoon->computeTransMatrix(JD.first, JD.second);
}
else // Compute coordinates:
{
myEarth->computePosition(JD.second, Vec3d(0.));
myEarth->computePosition(obs, JD.second, Vec3d(0.));
myEarth->computeTransMatrix(JD.first, JD.second);
Vec3d earthPos = myEarth->getHeliocentricEclipticPos();
double curSidT;
Expand All @@ -1011,7 +1013,7 @@ void Observability::getSunMoonCoords(StelCore *core, QPair<double, double> JD,
curSidT = myEarth->getSiderealTime(JD.first, JD.second)/Rad2Deg;
RotObserver = (Mat4d::zrotation(curSidT))*ObserverLoc;
LocTrans = (StelCore::matVsop87ToJ2000)*(Mat4d::translation(-earthPos));
myMoon->computePosition(JD.second, Vec3d(0.));
myMoon->computePosition(obs, JD.second, Vec3d(0.));
myMoon->computeTransMatrix(JD.first, JD.second);
Vec3d moonPos = myMoon->getHeliocentricEclipticPos();
sunPos = (core->j2000ToEquinoxEqu(LocTrans*moonPos, StelCore::RefractionOff))-RotObserver;
Expand All @@ -1028,16 +1030,17 @@ void Observability::getSunMoonCoords(StelCore *core, QPair<double, double> JD,
// getBack controls whether Earth and Moon must be returned to their original positions after computation.
void Observability::getMoonDistance(StelCore *core, QPair<double, double> JD, double &distance, bool getBack)
{
const StelObserver *obs=core->getCurrentObserver();
if (getBack) // Return the Moon and Earth to their current position:
{
myEarth->computePosition(JD.second, Vec3d(0.));
myEarth->computePosition(obs, JD.second, Vec3d(0.));
myEarth->computeTransMatrix(JD.first, JD.second);
myMoon->computePosition(JD.second, Vec3d(0.));
myMoon->computePosition(obs, JD.second, Vec3d(0.));
myMoon->computeTransMatrix(JD.first, JD.second);
}
else
{ // Compute coordinates:
myEarth->computePosition(JD.second, Vec3d(0.));
myEarth->computePosition(obs, JD.second, Vec3d(0.));
myEarth->computeTransMatrix(JD.first, JD.second);
Vec3d earthPos = myEarth->getHeliocentricEclipticPos();
// double curSidT;
Expand All @@ -1050,7 +1053,7 @@ void Observability::getMoonDistance(StelCore *core, QPair<double, double> JD, do
// curSidT = myEarth->getSiderealTime(JD)/Rad2Deg;
// RotObserver = (Mat4d::zrotation(curSidT))*ObserverLoc;
LocTrans = (StelCore::matVsop87ToJ2000)*(Mat4d::translation(-earthPos));
myMoon->computePosition(JD.second, Vec3d(0.));
myMoon->computePosition(obs, JD.second, Vec3d(0.));
myMoon->computeTransMatrix(JD.first, JD.second);
Pos1 = myMoon->getHeliocentricEclipticPos();
Pos2 = core->j2000ToEquinoxEqu(LocTrans*Pos1, StelCore::RefractionOff); //-RotObserver;
Expand All @@ -1066,20 +1069,21 @@ void Observability::getMoonDistance(StelCore *core, QPair<double, double> JD, do
// Get the Coords of a planet:
void Observability::getPlanetCoords(StelCore *core, QPair<double, double> JD, double &RA, double &Dec, bool getBack)
{
const StelObserver *obs=core->getCurrentObserver();
if (getBack)
{
// Return the planet to its current time:
myPlanet->computePosition(JD.second, Vec3d(0.));
myPlanet->computePosition(obs, JD.second, Vec3d(0.));
myPlanet->computeTransMatrix(JD.first, JD.second);
myEarth->computePosition(JD.second, Vec3d(0.));
myEarth->computePosition(obs, JD.second, Vec3d(0.));
myEarth->computeTransMatrix(JD.first, JD.second);
} else
{
// Compute planet's position:
myPlanet->computePosition(JD.second, Vec3d(0.));
myPlanet->computePosition(obs, JD.second, Vec3d(0.));
myPlanet->computeTransMatrix(JD.first, JD.second);
Pos1 = myPlanet->getHeliocentricEclipticPos();
myEarth->computePosition(JD.second, Vec3d(0.));
myEarth->computePosition(obs, JD.second, Vec3d(0.));
myEarth->computeTransMatrix(JD.first, JD.second);
Pos2 = myEarth->getHeliocentricEclipticPos();
LocTrans = (StelCore::matVsop87ToJ2000)*(Mat4d::translation(-Pos2));
Expand All @@ -1102,14 +1106,15 @@ bool Observability::calculateSolarSystemEvents(StelCore* core, int bodyType)
hHoriz = calculateHourAngle(mylat, refractedHorizonAlt, selDec);
bool raises = hHoriz > 0.0;

const StelObserver *obs=core->getCurrentObserver();

// Only recompute ephemeris from second to second (at least)
// or if the source has changed (i.e., Sun <-> Moon). This saves resources:
if (qAbs(myJD.first-lastJDMoon)>StelCore::JD_SECOND || lastType!=bodyType || souChanged)
{
lastType = bodyType;

myEarth->computePosition(myJD.second, Vec3d(0.));
myEarth->computePosition(obs, myJD.second, Vec3d(0.));
myEarth->computeTransMatrix(myJD.first, myJD.second);
Vec3d earthPos = myEarth->getHeliocentricEclipticPos();

Expand All @@ -1122,14 +1127,14 @@ bool Observability::calculateSolarSystemEvents(StelCore* core, int bodyType)
curSidT = myEarth->getSiderealTime(myJD.first, myJD.second)/Rad2Deg;
RotObserver = (Mat4d::zrotation(curSidT))*ObserverLoc;
LocTrans = (StelCore::matVsop87ToJ2000)*(Mat4d::translation(-earthPos));
myMoon->computePosition(myJD.second, Vec3d(0.));
myMoon->computePosition(obs, myJD.second, Vec3d(0.));
myMoon->computeTransMatrix(myJD.first, myJD.second);
Pos1 = myMoon->getHeliocentricEclipticPos();
Pos2 = (core->j2000ToEquinoxEqu(LocTrans*Pos1, StelCore::RefractionOff))-RotObserver;
}
else // Planet position
{
myPlanet->computePosition(myJD.second, Vec3d(0.));
myPlanet->computePosition(obs, myJD.second, Vec3d(0.));
myPlanet->computeTransMatrix(myJD.first, myJD.second);
Pos1 = myPlanet->getHeliocentricEclipticPos();
LocTrans = (StelCore::matVsop87ToJ2000)*(Mat4d::translation(-earthPos));
Expand Down Expand Up @@ -1901,20 +1906,20 @@ QString Observability::getReportAsJson() {
QString report = QString("{ ");
if ((isMoon(objectSelection) && show_FullMoon) || (!isSun(objectSelection) && !isMoon(objectSelection) && shouldShowYear()))
{
report += QString("\"%1\": \"%2\", ").arg("title").arg(msgThisYear);
report += QString("\"title\": \"%1\", ").arg(msgThisYear);
if (show_Best_Night || show_FullMoon)
{
report += QString("\"%1\": \"%2\", ").arg("bestNight").arg(lineBestNight);
report += QString("\"bestNight\": \"%1\", ").arg(lineBestNight);
}
if (show_Good_Nights)
{
report += QString("\"%1\": \"%2\", ").arg("observableRange").arg(lineObservableRange);
report += QString("\"observableRange\": \"%1\", ").arg(lineObservableRange);
}
if (show_AcroCos)
{
report += QString("\"%1\": \"%2\", ").arg("acronychal").arg(lineAcro);
report += QString("\"%1\": \"%2\", ").arg("cosmic").arg(lineCosm);
report += QString("\"%1\": \"%2\" ").arg("heliacal").arg(lineHeli);
report += QString("\"acronychal\": \"%1\", ").arg(lineAcro);
report += QString("\"cosmic\": \"%1\", ").arg(lineCosm);
report += QString("\"heliacal\": \"%1\" ").arg(lineHeli);
}
}
report += QString("}");
Expand Down
2 changes: 1 addition & 1 deletion plugins/RemoteControl/src/MainService.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -140,7 +140,7 @@ void MainService::get(const QByteArray& operation, const APIParameters &paramete
QString localIso = StelUtils::julianDayToISO8601String(jday+gmtShift,true);

//time zone string
QString timeZone = localeMgr->getPrintableTimeZoneLocal(jday);
QString timeZone = localeMgr->getPrintableTimeZoneLocal(jday, core->getUTCOffset(jday));

QJsonObject obj2;
obj2.insert("jday",jday);
Expand Down
6 changes: 3 additions & 3 deletions plugins/Supernovae/src/Supernova.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -109,9 +109,9 @@ QString Supernova::getEnglishName(void) const
return name;
}

QString Supernova::getMaxBrightnessDate(const double JD) const
QString Supernova::getMaxBrightnessDate(const StelCore *core, const double JD) const
{
return StelApp::getInstance().getLocaleMgr().getPrintableDateLocal(JD);
return StelApp::getInstance().getLocaleMgr().getPrintableDateLocal(JD, core->getUTCOffset(JD));
}

QString Supernova::getMagnitudeInfoString(const StelCore *core, const InfoStringGroup& flags, const int decimals) const
Expand Down Expand Up @@ -152,7 +152,7 @@ QString Supernova::getInfoString(const StelCore* core, const InfoStringGroup& fl
if (flags&Extra)
{
oss << QString("%1: %2").arg(q_("Type of supernova"), sntype) << "<br />";
oss << QString("%1: %2").arg(q_("Maximum brightness"), getMaxBrightnessDate(peakJD)) << "<br />";
oss << QString("%1: %2").arg(q_("Maximum brightness"), getMaxBrightnessDate(core, peakJD)) << "<br />";
if (distance>0)
{
//TRANSLATORS: Unit of measure for distance - Light Years
Expand Down
2 changes: 1 addition & 1 deletion plugins/Supernovae/src/Supernova.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -119,7 +119,7 @@ class Supernova : public StelObject

static bool syncShowLabels;

QString getMaxBrightnessDate(const double JD) const;
QString getMaxBrightnessDate(const StelCore *core, const double JD) const;
};

#endif // SUPERNOVA_HPP
5 changes: 3 additions & 2 deletions plugins/TextUserInterface/src/TextUserInterface.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -661,9 +661,10 @@ void TextUserInterface::draw(StelCore* core)
{
double jd = core->getJD();
int text_x = x + xVc*2/3, text_y = y + pixOffset;
const double utcOffsetHrs=core->getUTCOffset(jd);

QString newDate = StelApp::getInstance().getLocaleMgr().getPrintableDateLocal(jd) + " "
+StelApp::getInstance().getLocaleMgr().getPrintableTimeLocal(jd);
QString newDate = StelApp::getInstance().getLocaleMgr().getPrintableDateLocal(jd, utcOffsetHrs) + " "
+StelApp::getInstance().getLocaleMgr().getPrintableTimeLocal(jd, utcOffsetHrs);

if (fovMaskDisk) {
text_x = xVc + fovOffsetY - pixOffset;
Expand Down
12 changes: 6 additions & 6 deletions src/core/SolarEclipseComputer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2005,21 +2005,21 @@ void SolarEclipseComputer::generateKML(const EclipseMapData& data, const QString
stream << "<PolyStyle>\n<color>" << toKMLColorString(eclipseLimitsColor) << "</color>\n</PolyStyle>\n</Style>\n";

{
const auto timeStr = localeMgr->getPrintableTimeLocal(data.greatestEclipse.JD);
const auto timeStr = localeMgr->getPrintableTimeLocal(data.greatestEclipse.JD, core->getUTCOffset(data.greatestEclipse.JD));
stream << "<Placemark>\n<name>"+q_("Greatest eclipse")+" ("+timeStr+")</name>\n<Point>\n<coordinates>";
stream << data.greatestEclipse.longitude << "," << data.greatestEclipse.latitude << ",0.0\n";
stream << "</coordinates>\n</Point>\n</Placemark>\n";
}

{
const auto timeStr = localeMgr->getPrintableTimeLocal(data.firstContactWithEarth.JD);
const auto timeStr = localeMgr->getPrintableTimeLocal(data.firstContactWithEarth.JD, core->getUTCOffset(data.firstContactWithEarth.JD));
stream << "<Placemark>\n<name>"+q_("First contact with Earth")+" ("+timeStr+")</name>\n<Point>\n<coordinates>";
stream << data.firstContactWithEarth.longitude << "," << data.firstContactWithEarth.latitude << ",0.0\n";
stream << "</coordinates>\n</Point>\n</Placemark>\n";
}

{
const auto timeStr = localeMgr->getPrintableTimeLocal(data.lastContactWithEarth.JD);
const auto timeStr = localeMgr->getPrintableTimeLocal(data.lastContactWithEarth.JD, core->getUTCOffset(data.lastContactWithEarth.JD));
stream << "<Placemark>\n<name>"+q_("Last contact with Earth")+" ("+timeStr+")</name>\n<Point>\n<coordinates>";
stream << data.lastContactWithEarth.longitude << "," << data.lastContactWithEarth.latitude << ",0.0\n";
stream << "</coordinates>\n</Point>\n</Placemark>\n";
Expand Down Expand Up @@ -2102,15 +2102,15 @@ void SolarEclipseComputer::generateKML(const EclipseMapData& data, const QString

if(data.centralEclipseStart.JD > 0)
{
const auto timeStr = localeMgr->getPrintableTimeLocal(data.centralEclipseStart.JD);
const auto timeStr = localeMgr->getPrintableTimeLocal(data.centralEclipseStart.JD, core->getUTCOffset(data.centralEclipseStart.JD));
stream << "<Placemark>\n<name>"+q_("Central eclipse begins")+" ("+timeStr+")</name>\n<Point>\n<coordinates>";
stream << data.centralEclipseStart.longitude << "," << data.centralEclipseStart.latitude << ",0.0\n";
stream << "</coordinates>\n</Point>\n</Placemark>\n";
}

if(data.centralEclipseEnd.JD > 0)
{
const auto timeStr = localeMgr->getPrintableTimeLocal(data.centralEclipseEnd.JD);
const auto timeStr = localeMgr->getPrintableTimeLocal(data.centralEclipseEnd.JD, core->getUTCOffset(data.centralEclipseEnd.JD));
stream << "<Placemark>\n<name>"+q_("Central eclipse ends")+" ("+timeStr+")</name>\n<Point>\n<coordinates>";
stream << data.centralEclipseEnd.longitude << "," << data.centralEclipseEnd.latitude << ",0.0\n";
stream << "</coordinates>\n</Point>\n</Placemark>\n";
Expand All @@ -2127,7 +2127,7 @@ void SolarEclipseComputer::generateKML(const EclipseMapData& data, const QString

for(const auto& outline : data.umbraOutlines)
{
const auto timeStr = localeMgr->getPrintableTimeLocal(outline.JD);
const auto timeStr = localeMgr->getPrintableTimeLocal(outline.JD, core->getUTCOffset(outline.JD));
startLinePlaceMark(timeStr, outline.eclipseType);
stream << "<tessellate>1</tessellate>\n<altitudeMode>absoluto</altitudeMode>\n<coordinates>\n";
for(const auto& p : outline.curve)
Expand Down
Loading
Loading