SolarSystem.cpp   SolarSystem.cpp 
/* /*
* Stellarium * Stellarium
* Copyright (C) 2002 Fabien Chereau * Copyright (C) 2002 Fabien Chereau
* Copyright (C) 2010 Bogdan Marinov
* *
* This program is free software; you can redistribute it and/or * This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License * modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2 * as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version. * of the License, or (at your option) any later version.
* *
* This program is distributed in the hope that it will be useful, * This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of * but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details. * GNU General Public License for more details.
skipping to change at line 36 skipping to change at line 37
#include "StelApp.hpp" #include "StelApp.hpp"
#include "StelCore.hpp" #include "StelCore.hpp"
#include "StelTextureMgr.hpp" #include "StelTextureMgr.hpp"
#include "StelObjectMgr.hpp" #include "StelObjectMgr.hpp"
#include "StelLocaleMgr.hpp" #include "StelLocaleMgr.hpp"
#include "StelSkyCultureMgr.hpp" #include "StelSkyCultureMgr.hpp"
#include "StelFileMgr.hpp" #include "StelFileMgr.hpp"
#include "StelModuleMgr.hpp" #include "StelModuleMgr.hpp"
#include "StelIniParser.hpp" #include "StelIniParser.hpp"
#include "Planet.hpp" #include "Planet.hpp"
#include "MinorPlanet.hpp"
#include "Comet.hpp"
#include "StelNavigator.hpp" #include "StelNavigator.hpp"
#include "StelSkyDrawer.hpp" #include "StelSkyDrawer.hpp"
#include "StelUtils.hpp" #include "StelUtils.hpp"
#include "StelPainter.hpp" #include "StelPainter.hpp"
#include "TrailGroup.hpp" #include "TrailGroup.hpp"
#include <functional> #include <functional>
#include <algorithm> #include <algorithm>
#include <QTextStream> #include <QTextStream>
skipping to change at line 197 skipping to change at line 200
} }
void cometOrbitPosFunc(double jd,double xyz[3], void* userDataPtr) void cometOrbitPosFunc(double jd,double xyz[3], void* userDataPtr)
{ {
static_cast<CometOrbit*>(userDataPtr)->positionAtTimevInVSOP87Coordi nates(jd, xyz); static_cast<CometOrbit*>(userDataPtr)->positionAtTimevInVSOP87Coordi nates(jd, xyz);
} }
// Init and load the solar system data // Init and load the solar system data
void SolarSystem::loadPlanets() void SolarSystem::loadPlanets()
{ {
qDebug() << "Loading Solar System data ..."; qDebug() << "Loading Solar System data ...";
QString iniFile; QStringList solarSystemFiles;
try try
{ {
iniFile = StelFileMgr::findFile("data/ssystem.ini"); solarSystemFiles = StelFileMgr::findFileInAllPaths("data/ssy stem.ini");
} }
catch(std::runtime_error& e) catch(std::runtime_error& e)
{ {
qWarning() << "ERROR while loading ssysyem.ini (unable to fi nd data/ssystem.ini): " << e.what() << endl; qWarning() << "ERROR while loading ssysyem.ini (unable to fi nd data/ssystem.ini): " << e.what() << endl;
return; return;
} }
QSettings pd(iniFile, StelIniFormat);
foreach (const QString& solarSystemFile, solarSystemFiles)
{
if (loadPlanets(solarSystemFile))
break;
else
{
sun.clear();
moon.clear();
earth.clear();
foreach (PlanetP p, systemPlanets)
{
p->satellites.clear();
p.clear();
}
systemPlanets.clear();
//Memory leak? What's the proper way of cleaning sha
red pointers?
//If the file is in the user data directory, rename
it:
if (solarSystemFile.contains(StelFileMgr::getUserDir
()))
{
QString newName = QString("%1/data/ssystem-%
2.ini").arg(StelFileMgr::getUserDir()).arg(QDateTime::currentDateTime().toS
tring("yyyyMMddThhmmss"));
if (QFile::rename(solarSystemFile, newName))
qWarning() << "Invalid Solar System
file" << solarSystemFile << "has been renamed to" << newName;
else
{
qWarning() << "Invalid Solar System
file" << solarSystemFile << "cannot be removed!";
qWarning() << "Please either delete
it, rename it or move it elsewhere.";
}
}
}
}
}
bool SolarSystem::loadPlanets(const QString& filePath)
{
QSettings pd(filePath, StelIniFormat);
if (pd.status() != QSettings::NoError) if (pd.status() != QSettings::NoError)
{ {
qWarning() << "ERROR while parsing ssysyem.ini file"; qWarning() << "ERROR while parsing" << filePath;
return; return false;
} }
// QSettings does not allow us to say that the sections of the file // QSettings does not allow us to say that the sections of the file
// will be listed in the same order as in the file like the old // will be listed in the same order as in the file like the old
// InitParser used to so we can no longer assume that. // InitParser used to so we can no longer assume that.
// //
// This means we must first decide what order to read the sections // This means we must first decide what order to read the sections
// of the file in (each section contains one planet) to avoid settin g // of the file in (each section contains one planet) to avoid settin g
// the parent Planet* to one which has not yet been created. // the parent Planet* to one which has not yet been created.
// //
skipping to change at line 312 skipping to change at line 352
{ {
if (p->getEnglishName()==strParent) if (p->getEnglishName()==strParent)
{ {
parent = p; parent = p;
break; break;
} }
} }
if (parent.isNull()) if (parent.isNull())
{ {
qWarning() << "ERROR : can't find parent sol ar system body for " << englishName; qWarning() << "ERROR : can't find parent sol ar system body for " << englishName;
abort(); //abort();
continue; continue;
} }
} }
const QString funcName = pd.value(secname+"/coord_func").toS tring(); const QString funcName = pd.value(secname+"/coord_func").toS tring();
posFuncType posfunc=NULL; posFuncType posfunc=NULL;
void* userDataPtr=NULL; void* userDataPtr=NULL;
OsulatingFunctType *osculatingFunc = 0; OsulatingFunctType *osculatingFunc = 0;
bool closeOrbit = pd.value(secname+"/closeOrbit", true).toBo ol(); bool closeOrbit = pd.value(secname+"/closeOrbit", true).toBo ol();
skipping to change at line 336 skipping to change at line 376
const double epoch = pd.value(secname+"/orbit_Epoch" ,J2000).toDouble(); const double epoch = pd.value(secname+"/orbit_Epoch" ,J2000).toDouble();
const double eccentricity = pd.value(secname+"/orbit _Eccentricity").toDouble(); const double eccentricity = pd.value(secname+"/orbit _Eccentricity").toDouble();
if (eccentricity >= 1.0) closeOrbit = false; if (eccentricity >= 1.0) closeOrbit = false;
double pericenterDistance = pd.value(secname+"/orbit _PericenterDistance",-1e100).toDouble(); double pericenterDistance = pd.value(secname+"/orbit _PericenterDistance",-1e100).toDouble();
double semi_major_axis; double semi_major_axis;
if (pericenterDistance <= 0.0) { if (pericenterDistance <= 0.0) {
semi_major_axis = pd.value(secname+"/orbit_S emiMajorAxis",-1e100).toDouble(); semi_major_axis = pd.value(secname+"/orbit_S emiMajorAxis",-1e100).toDouble();
if (semi_major_axis <= -1e100) { if (semi_major_axis <= -1e100) {
qDebug() << "ERROR: " << englishName qDebug() << "ERROR: " << englishName
<< ": you must provide orbit _PericenterDistance or orbit_SemiMajorAxis"; << ": you must provide orbit _PericenterDistance or orbit_SemiMajorAxis";
abort(); //abort();
continue;
} else { } else {
semi_major_axis /= AU; semi_major_axis /= AU;
Q_ASSERT(eccentricity != 1.0); // pa rabolic orbits have no semi_major_axis Q_ASSERT(eccentricity != 1.0); // pa rabolic orbits have no semi_major_axis
pericenterDistance = semi_major_axis * (1.0-eccentricity); pericenterDistance = semi_major_axis * (1.0-eccentricity);
} }
} else { } else {
pericenterDistance /= AU; pericenterDistance /= AU;
semi_major_axis = (eccentricity == 1.0) semi_major_axis = (eccentricity == 1.0)
? 0.0 // par abolic orbits have no semi_major_axis ? 0.0 // par abolic orbits have no semi_major_axis
: pericenter Distance / (1.0-eccentricity); : pericenter Distance / (1.0-eccentricity);
skipping to change at line 443 skipping to change at line 484
// orbit_MeanAnomaly,orbit_Inclination,orbit_ArgOfPe ricenter,orbit_AscendingNode: given in degrees // orbit_MeanAnomaly,orbit_Inclination,orbit_ArgOfPe ricenter,orbit_AscendingNode: given in degrees
const double eccentricity = pd.value(secname+"/orbit _Eccentricity",0.0).toDouble(); const double eccentricity = pd.value(secname+"/orbit _Eccentricity",0.0).toDouble();
if (eccentricity >= 1.0) closeOrbit = false; if (eccentricity >= 1.0) closeOrbit = false;
double pericenterDistance = pd.value(secname+"/orbit _PericenterDistance",-1e100).toDouble(); double pericenterDistance = pd.value(secname+"/orbit _PericenterDistance",-1e100).toDouble();
double semi_major_axis; double semi_major_axis;
if (pericenterDistance <= 0.0) { if (pericenterDistance <= 0.0) {
semi_major_axis = pd.value(secname+"/orbit_S emiMajorAxis",-1e100).toDouble(); semi_major_axis = pd.value(secname+"/orbit_S emiMajorAxis",-1e100).toDouble();
if (semi_major_axis <= -1e100) { if (semi_major_axis <= -1e100) {
qWarning() << "ERROR: " << englishNa me qWarning() << "ERROR: " << englishNa me
<< ": you must provide orbit _PericenterDistance or orbit_SemiMajorAxis"; << ": you must provide orbit _PericenterDistance or orbit_SemiMajorAxis";
abort(); //abort();
continue;
} else { } else {
Q_ASSERT(eccentricity != 1.0); // pa rabolic orbits have no semi_major_axis Q_ASSERT(eccentricity != 1.0); // pa rabolic orbits have no semi_major_axis
pericenterDistance = semi_major_axis * (1.0-eccentricity); pericenterDistance = semi_major_axis * (1.0-eccentricity);
} }
} else { } else {
semi_major_axis = (eccentricity == 1.0) semi_major_axis = (eccentricity == 1.0)
? 0.0 // par abolic orbits have no semi_major_axis ? 0.0 // par abolic orbits have no semi_major_axis
: pericenter Distance / (1.0-eccentricity); : pericenter Distance / (1.0-eccentricity);
} }
double meanMotion = pd.value(secname+"/orbit_MeanMot ion",-1e100).toDouble(); double meanMotion = pd.value(secname+"/orbit_MeanMot ion",-1e100).toDouble();
skipping to change at line 485 skipping to change at line 527
meanMotion *= (M_PI/180.0); meanMotion *= (M_PI/180.0);
} }
double time_at_pericenter = pd.value(secname+"/orbit _TimeAtPericenter",-1e100).toDouble(); double time_at_pericenter = pd.value(secname+"/orbit _TimeAtPericenter",-1e100).toDouble();
if (time_at_pericenter <= -1e100) { if (time_at_pericenter <= -1e100) {
const double epoch = pd.value(secname+"/orbi t_Epoch",-1e100).toDouble(); const double epoch = pd.value(secname+"/orbi t_Epoch",-1e100).toDouble();
double mean_anomaly = pd.value(secname+"/orb it_MeanAnomaly",-1e100).toDouble(); double mean_anomaly = pd.value(secname+"/orb it_MeanAnomaly",-1e100).toDouble();
if (epoch <= -1e100 || mean_anomaly <= -1e10 0) { if (epoch <= -1e100 || mean_anomaly <= -1e10 0) {
qWarning() << "ERROR: " << englishNa me qWarning() << "ERROR: " << englishNa me
<< ": when you do not provid e orbit_TimeAtPericenter, you must provide both " << ": when you do not provid e orbit_TimeAtPericenter, you must provide both "
<< "orbit_Epoch and orbit_Me anAnomaly"; << "orbit_Epoch and orbit_Me anAnomaly";
abort(); //abort();
continue;
} else { } else {
mean_anomaly *= (M_PI/180.0); mean_anomaly *= (M_PI/180.0);
time_at_pericenter = epoch - mean_an omaly / meanMotion; time_at_pericenter = epoch - mean_an omaly / meanMotion;
} }
} }
const double inclination = pd.value(secname+"/orbit_ Inclination").toDouble()*(M_PI/180.0); const double inclination = pd.value(secname+"/orbit_ Inclination").toDouble()*(M_PI/180.0);
const double arg_of_pericenter = pd.value(secname+"/ orbit_ArgOfPericenter").toDouble()*(M_PI/180.0); const double arg_of_pericenter = pd.value(secname+"/ orbit_ArgOfPericenter").toDouble()*(M_PI/180.0);
const double ascending_node = pd.value(secname+"/orb it_AscendingNode").toDouble()*(M_PI/180.0); const double ascending_node = pd.value(secname+"/orb it_AscendingNode").toDouble()*(M_PI/180.0);
const double parentRotObliquity = parent->getParent( ) const double parentRotObliquity = parent->getParent( )
? parent->getRotObliquity() ? parent->getRotObliquity()
skipping to change at line 641 skipping to change at line 684
if (funcName=="pluto_special") if (funcName=="pluto_special")
posfunc = &get_pluto_helio_coordsv; posfunc = &get_pluto_helio_coordsv;
if (posfunc==NULL) if (posfunc==NULL)
{ {
qWarning() << "ERROR : can't find posfunc " << funcN ame << " for " << englishName; qWarning() << "ERROR : can't find posfunc " << funcN ame << " for " << englishName;
exit(-1); exit(-1);
} }
// Create the Planet and add it to the list // Create the Solar System body and add it to the list
PlanetP p(new Planet(englishName, QString type = pd.value(secname+"/type").toString();
pd.value(secname+"/lighting").toBool PlanetP p;
(), if (type == "asteroid")
pd.value(secname+"/radius").toDouble {
()/AU, p = PlanetP(new MinorPlanet(englishName,
pd.value(secname+"/oblateness", 0.0) pd.value(secname+"/lighting").toBool(
.toDouble(), ),
StelUtils::strToVec3f(pd.value(secna pd.value(secname+"/radius").toDouble(
me+"/color").toString()), )/AU,
pd.value(secname+"/albedo").toFloat( pd.value(secname+"/oblateness", 0.0).
), toDouble(),
pd.value(secname+"/tex_map").toStrin StelUtils::strToVec3f(pd.value(secnam
g(), e+"/color").toString()),
posfunc, pd.value(secname+"/albedo").toFloat()
userDataPtr, ,
osculatingFunc, pd.value(secname+"/tex_map").toString
closeOrbit, (),
pd.value(secname+"/hidden", 0).toBoo posfunc,
l(), userDataPtr,
pd.value(secname+"/atmosphere", fals osculatingFunc,
e).toBool())); closeOrbit,
pd.value(secname+"/hidden", 0).toBool
()));
QSharedPointer<MinorPlanet> mp = p.dynamicCast<Mino
rPlanet>();
//Number
int minorPlanetNumber = pd.value(secname+"/minor_pla
net_number", 0).toInt();
if (minorPlanetNumber)
{
mp->setMinorPlanetNumber(minorPlanetNumber);
}
//Provisional designation
QString provisionalDesignation = pd.value(secname+"/
provisional_designation").toString();
if (!provisionalDesignation.isEmpty())
{
mp->setProvisionalDesignation(provisionalDes
ignation);
}
//H-G magnitude system
double magnitude = pd.value(secname+"/absolute_magni
tude", -99).toDouble();
double slope = pd.value(secname+"/slope_parameter",
0.15).toDouble();
if (magnitude > -99)
{
if (slope >= 0 && slope <= 1)
{
mp->setAbsoluteMagnitudeAndSlope(mag
nitude, slope);
}
else
{
mp->setAbsoluteMagnitudeAndSlope(mag
nitude, 0.15);
}
}
}
else if (type == "comet")
{
p = PlanetP(new Comet(englishName,
pd.value(secname+"/lighting").toBool(
),
pd.value(secname+"/radius").toDouble(
)/AU,
pd.value(secname+"/oblateness", 0.0).
toDouble(),
StelUtils::strToVec3f(pd.value(secnam
e+"/color").toString()),
pd.value(secname+"/albedo").toFloat()
,
pd.value(secname+"/tex_map").toString
(),
posfunc,
userDataPtr,
osculatingFunc,
closeOrbit,
pd.value(secname+"/hidden", 0).toBool
()));
QSharedPointer<Comet> mp = p.dynamicCast<Comet>();
//g,k magnitude system
double magnitude = pd.value(secname+"/absolute_magni
tude", -99).toDouble();
double slope = pd.value(secname+"/slope_parameter",
4.0).toDouble();
if (magnitude > -99)
{
if (slope >= 0 && slope <= 20)
{
mp->setAbsoluteMagnitudeAndSlope(mag
nitude, slope);
}
else
{
mp->setAbsoluteMagnitudeAndSlope(mag
nitude, 4.0);
}
}
}
else
{
p = PlanetP(new Planet(englishName,
pd.value(secname+"/lighting").toBool(
),
pd.value(secname+"/radius").toDouble(
)/AU,
pd.value(secname+"/oblateness", 0.0).
toDouble(),
StelUtils::strToVec3f(pd.value(secnam
e+"/color").toString()),
pd.value(secname+"/albedo").toFloat()
,
pd.value(secname+"/tex_map").toString
(),
posfunc,
userDataPtr,
osculatingFunc,
closeOrbit,
pd.value(secname+"/hidden", 0).toBool
(),
pd.value(secname+"/atmosphere", false
).toBool()));
}
if (!parent.isNull()) if (!parent.isNull())
{ {
parent->satellites.append(p); parent->satellites.append(p);
p->parent = parent; p->parent = parent;
} }
if (secname=="earth") earth = p; if (secname=="earth") earth = p;
if (secname=="sun") sun = p; if (secname=="sun") sun = p;
if (secname=="moon") moon = p; if (secname=="moon") moon = p;
double rotObliquity = pd.value(secname+"/rot_obliquity",0.). toDouble()*(M_PI/180.0); double rotObliquity = pd.value(secname+"/rot_obliquity",0.). toDouble()*(M_PI/180.0);
skipping to change at line 710 skipping to change at line 840
const double rMin = pd.value(secname+"/ring_inner_si ze").toDouble()/AU; const double rMin = pd.value(secname+"/ring_inner_si ze").toDouble()/AU;
const double rMax = pd.value(secname+"/ring_outer_si ze").toDouble()/AU; const double rMax = pd.value(secname+"/ring_outer_si ze").toDouble()/AU;
Ring *r = new Ring(rMin,rMax,pd.value(secname+"/tex_ ring").toString()); Ring *r = new Ring(rMin,rMax,pd.value(secname+"/tex_ ring").toString());
p->setRings(r); p->setRings(r);
} }
systemPlanets.push_back(p); systemPlanets.push_back(p);
readOk++; readOk++;
} }
if (systemPlanets.isEmpty())
{
qWarning() << "No Solar System objects loaded from" << fileP
ath;
return false;
}
// special case: load earth shadow texture // special case: load earth shadow texture
Planet::texEarthShadow = StelApp::getInstance().getTextureManager(). createTexture("textures/earth-shadow.png"); Planet::texEarthShadow = StelApp::getInstance().getTextureManager(). createTexture("textures/earth-shadow.png");
qDebug() << "Loaded" << readOk << "/" << totalPlanets << "planet orb qDebug() << "Loaded" << readOk << "/" << totalPlanets << "planet orb
its"; its from" << filePath;
return true;
} }
// Compute the position for every elements of the solar system. // Compute the position for every elements of the solar system.
// The order is not important since the position is computed relatively to the mother body // The order is not important since the position is computed relatively to the mother body
void SolarSystem::computePositions(double date, const Vec3d& observerPos) void SolarSystem::computePositions(double date, const Vec3d& observerPos)
{ {
if (flagLightTravelTime) if (flagLightTravelTime)
{ {
foreach (PlanetP p, systemPlanets) foreach (PlanetP p, systemPlanets)
{ {
skipping to change at line 800 skipping to change at line 937
sort(systemPlanets.begin(),systemPlanets.end(),biggerDistance()); sort(systemPlanets.begin(),systemPlanets.end(),biggerDistance());
if (trailFader.getInterstate()>0.0000001f) if (trailFader.getInterstate()>0.0000001f)
{ {
StelPainter* sPainter = new StelPainter(core->getProjection2 d()); StelPainter* sPainter = new StelPainter(core->getProjection2 d());
allTrails->setOpacity(trailFader.getInterstate()); allTrails->setOpacity(trailFader.getInterstate());
allTrails->draw(core, sPainter); allTrails->draw(core, sPainter);
delete sPainter; delete sPainter;
} }
// Make some voodoo to determine when labels should be displayed
float maxMagLabel = (core->getSkyDrawer()->getLimitMagnitude()<5.f ?
core->getSkyDrawer()->getLimitMagnitude() :
5.f+(core->getSkyDrawer()->getLimitMagnitude()-5.f)*
1.2f) +(labelsAmount-3.f)*1.2f;
// Draw the elements // Draw the elements
float maxMagLabel=core->getSkyDrawer()->getLimitMagnitude()*0.80f+(l abelsAmount*1.2f)-2.f;
foreach (const PlanetP& p, systemPlanets) foreach (const PlanetP& p, systemPlanets)
{ {
p->draw(core, maxMagLabel, planetNameFont); p->draw(core, maxMagLabel, planetNameFont);
} }
if (GETSTELMODULE(StelObjectMgr)->getFlagSelectedObjectPointer()) if (GETSTELMODULE(StelObjectMgr)->getFlagSelectedObjectPointer())
drawPointer(core); drawPointer(core);
} }
void SolarSystem::setStelStyle(const QString& section) void SolarSystem::setStelStyle(const QString& section)
skipping to change at line 908 skipping to change at line 1048
{ {
result.append(qSharedPointerCast<StelObject>(p)); result.append(qSharedPointerCast<StelObject>(p));
} }
} }
return result; return result;
} }
// Update i18 names from english names according to passed translator // Update i18 names from english names according to passed translator
void SolarSystem::updateI18n() void SolarSystem::updateI18n()
{ {
StelTranslator& trans = StelApp::getInstance().getLocaleMgr().getSky Translator(); StelTranslator& trans = StelApp::getInstance().getLocaleMgr().getApp StelTranslator();
foreach (PlanetP p, systemPlanets) foreach (PlanetP p, systemPlanets)
p->translateName(trans); p->translateName(trans);
} }
QString SolarSystem::getPlanetHashString(void) QString SolarSystem::getPlanetHashString(void)
{ {
QString str; QString str;
QTextStream oss(&str); QTextStream oss(&str);
foreach (const PlanetP& p, systemPlanets) foreach (const PlanetP& p, systemPlanets)
{ {
skipping to change at line 1121 skipping to change at line 1261
} }
// Get the list of all the planet english names // Get the list of all the planet english names
QStringList SolarSystem::getAllPlanetEnglishNames() const QStringList SolarSystem::getAllPlanetEnglishNames() const
{ {
QStringList res; QStringList res;
foreach (const PlanetP& p, systemPlanets) foreach (const PlanetP& p, systemPlanets)
res.append(p->englishName); res.append(p->englishName);
return res; return res;
} }
void SolarSystem::reloadPlanets()
{
//Save flag states
bool flagScaleMoon = getFlagMoonScale();
float moonScale = getMoonScale();
bool flagPlanets = getFlagPlanets();
bool flagHints = getFlagHints();
bool flagLabels = getFlagLabels();
bool flagOrbits = getFlagOrbits();
//Unload all Solar System objects
selected.clear();//Release the selected one
foreach (Orbit* orb, orbits)
{
delete orb;
orb = NULL;
}
orbits.clear();
sun.clear();
moon.clear();
earth.clear();
Planet::texEarthShadow.clear(); //Loaded in loadPlanets()
delete allTrails;
allTrails = NULL;
foreach (PlanetP p, systemPlanets)
{
p->satellites.clear();
p.clear();
}
systemPlanets.clear();
//Memory leak? What's the proper way of cleaning shared pointers?
//Re-load the ssystem.ini file
loadPlanets();
computePositions(StelUtils::getJDFromSystem());
setSelected("");
recreateTrails();
//Restore flag states
setFlagMoonScale(flagScaleMoon);
setMoonScale(moonScale);
setFlagPlanets(flagPlanets);
setFlagHints(flagHints);
setFlagLabels(flagLabels);
setFlagOrbits(flagOrbits);
//Restore translations
updateI18n();
}
 End of changes. 17 change blocks. 
35 lines changed or deleted 212 lines changed or added

This html diff was produced by rfcdiff 1.41. The latest version is available from http://tools.ietf.org/tools/rfcdiff/