Satellite.cpp   Satellite.cpp 
skipping to change at line 50 skipping to change at line 50
#include <QVector3D> #include <QVector3D>
#include <QMatrix4x4> #include <QMatrix4x4>
#include "gsatellite/gTime.hpp" #include "gsatellite/gTime.hpp"
#include "gsatellite/stdsat.h" #include "gsatellite/stdsat.h"
#include <cmath> #include <cmath>
#define sqr(a) ((a)*(a)) #define sqr(a) ((a)*(a))
const QString Satellite::SATELLITE_TYPE = QStringLiteral("Satellite");
// static data members - will be initialised in the Satallites class (the S telObjectMgr) // static data members - will be initialised in the Satallites class (the S telObjectMgr)
StelTextureSP Satellite::hintTexture; StelTextureSP Satellite::hintTexture;
float Satellite::showLabels = true; bool Satellite::showLabels = true;
float Satellite::hintBrightness = 0.f; float Satellite::hintBrightness = 0.f;
float Satellite::hintScale = 1.f; float Satellite::hintScale = 1.f;
SphericalCap Satellite::viewportHalfspace = SphericalCap(); SphericalCap Satellite::viewportHalfspace = SphericalCap();
int Satellite::orbitLineSegments = 90; int Satellite::orbitLineSegments = 90;
int Satellite::orbitLineFadeSegments = 4; int Satellite::orbitLineFadeSegments = 4;
int Satellite::orbitLineSegmentDuration = 20; int Satellite::orbitLineSegmentDuration = 20;
bool Satellite::orbitLinesFlag = true; bool Satellite::orbitLinesFlag = true;
bool Satellite::realisticModeFlag = false; bool Satellite::realisticModeFlag = false;
Vec3f Satellite::invisibleSatelliteColor = Vec3f(0.2f,0.2f,0.2f); Vec3f Satellite::invisibleSatelliteColor = Vec3f(0.2f,0.2f,0.2f);
double Satellite::timeRateLimit = 1.0; // one JD per second by default
#ifdef IRIDIUM_SAT_TEXT_DEBUG #ifdef IRIDIUM_SAT_TEXT_DEBUG
QString Satellite::myText = ""; QString Satellite::myText = "";
#endif #endif
double Satellite::sunReflAngle = 180.; double Satellite::sunReflAngle = 180.;
double Satellite::timeShift = 0.; //double Satellite::timeShift = 0.;
Satellite::Satellite(const QString& identifier, const QVariantMap& map) Satellite::Satellite(const QString& identifier, const QVariantMap& map)
: initialized(false) : initialized(false)
, displayed(true) , displayed(true)
, orbitDisplayed(false) , orbitDisplayed(false)
, userDefined(false) , userDefined(false)
, newlyAdded(false) , newlyAdded(false)
, orbitValid(false) , orbitValid(false)
, jdLaunchYearJan1(0) , jdLaunchYearJan1(0)
, stdMag(99.) , stdMag(99.)
, status(StatusUnknown) , status(StatusUnknown)
, height(0.) , height(0.)
, range(0.) , range(0.)
, rangeRate(0.) , rangeRate(0.)
, hintColor(0.0,0.0,0.0) , hintColor(0.0,0.0,0.0)
, lastUpdated() , lastUpdated()
, pSatWrapper(NULL) , pSatWrapper(Q_NULLPTR)
, visibility(0) , visibility(gSatWrapper::UNKNOWN)
, phaseAngle(0.) , phaseAngle(0.)
, lastEpochCompForOrbit(0.) , lastEpochCompForOrbit(0.)
, epochTime(0.) , epochTime(0.)
{ {
// return initialized if the mandatory fields are not present // return initialized if the mandatory fields are not present
if (identifier.isEmpty()) if (identifier.isEmpty())
return; return;
if (!map.contains("name") || !map.contains("tle1") || !map.contains( "tle2")) if (!map.contains("name") || !map.contains("tle1") || !map.contains( "tle2"))
return; return;
skipping to change at line 172 skipping to change at line 176
lastUpdated = QDateTime::fromString(dateString, Qt::ISODate) ; lastUpdated = QDateTime::fromString(dateString, Qt::ISODate) ;
orbitValid = true; orbitValid = true;
initialized = true; initialized = true;
update(0.); update(0.);
} }
Satellite::~Satellite() Satellite::~Satellite()
{ {
if (pSatWrapper != NULL) if (pSatWrapper != Q_NULLPTR)
{ {
delete pSatWrapper; delete pSatWrapper;
pSatWrapper = NULL; pSatWrapper = Q_NULLPTR;
} }
} }
// TODO: REMOVE THIS FUNCTION! It is used for string formatting only. // TODO: REMOVE THIS FUNCTION! It is used for string formatting only.
double Satellite::roundToDp(float n, int dp) double Satellite::roundToDp(float n, int dp)
{ {
// round n to dp decimal places // round n to dp decimal places
return floor(n * pow(10., dp) + .5) / pow(10., dp); return floor(n * pow(10., dp) + .5) / pow(10., dp);
} }
skipping to change at line 276 skipping to change at line 280
catalogNumbers = QString("%1: %2; %3: %4") catalogNumbers = QString("%1: %2; %3: %4")
.arg(q_("Catalog #")) .arg(q_("Catalog #"))
.arg(id) .arg(id)
.arg(q_("International Designator") ) .arg(q_("International Designator") )
.arg(internationalDesignator); .arg(internationalDesignator);
oss << catalogNumbers << "<br/><br/>"; oss << catalogNumbers << "<br/><br/>";
} }
if (flags & ObjectType) if (flags & ObjectType)
{ {
oss << q_("Type: <b>%1</b>").arg(q_("artificial satellite")) << "<br/>"; oss << q_("Type: <b>%1</b>").arg(q_("artificial satellite")) << "<br/>";
} }
if ((flags & Magnitude) && (stdMag!=99.f)) if ((flags & Magnitude) && (stdMag!=99.f))
{ {
float mag = getVMagnitude(core); float mag = getVMagnitude(core);
if (core->getSkyDrawer()->getFlagHasAtmosphere()) if (core->getSkyDrawer()->getFlagHasAtmosphere())
oss << q_("Approx. magnitude: <b>%1</b> (extincted t o: <b>%2</b>)").arg(QString::number(mag, 'f', 2), oss << q_("Approx. magnitude: <b>%1</b> (extincted t o: <b>%2</b>)").arg(QString::number(mag, 'f', 2),
QString::number(getVMagnitudeWithExtinction(core), 'f', 2)) << "<br>"; QString::number(getVMagnitudeWithExtinction(core), 'f', 2)) << "<br>";
else else
oss << q_("Approx. magnitude: <b>%1</b>").arg(QStrin g::number(mag, 'f', 2)) << "<br/>"; oss << q_("Approx. magnitude: <b>%1</b>").arg(QStrin g::number(mag, 'f', 2)) << "<br/>";
skipping to change at line 298 skipping to change at line 302
#ifdef IRIDIUM_SAT_TEXT_DEBUG #ifdef IRIDIUM_SAT_TEXT_DEBUG
oss << myText << "<br/>"; oss << myText << "<br/>";
#endif #endif
} }
// Ra/Dec etc. // Ra/Dec etc.
oss << getPositionInfoString(core, flags); oss << getPositionInfoString(core, flags);
if (flags & Extra) if (flags & Extra)
{ {
oss << "<br/>";
// TRANSLATORS: Slant range: distance between the satellite and the observer // TRANSLATORS: Slant range: distance between the satellite and the observer
oss << QString(q_("Range (km): %1")).arg(range, 5, 'f', 2); oss << QString(q_("Range (km): %1")).arg(range, 5, 'f', 2);
oss << "<br/>"; oss << "<br/>";
// TRANSLATORS: Rate at which the distance changes // TRANSLATORS: Rate at which the distance changes
oss << QString(q_("Range rate (km/s): %1")).arg(rangeRate, 5 , 'f', 3); oss << QString(q_("Range rate (km/s): %1")).arg(rangeRate, 5 , 'f', 3);
oss << "<br/>"; oss << "<br/>";
// TRANSLATORS: Satellite altitude // TRANSLATORS: Satellite altitude
oss << QString(q_("Altitude (km): %1")).arg(height, 5, 'f', 2); oss << QString(q_("Altitude (km): %1")).arg(height, 5, 'f', 2);
oss << "<br/>"; oss << "<br/>";
// TRANSLATORS: %1 and %3 are numbers, %2 and %4 - degree si gns. // TRANSLATORS: %1 and %3 are numbers, %2 and %4 - degree si gns.
oss << QString(q_("SubPoint (Lat./Long.): %1%2/%3%4")) oss << QString(q_("SubPoint (Lat./Long.): %1%2/%3%4"))
.arg(latLongSubPointPosition[0], 5, 'f', 2) .arg(latLongSubPointPosition[0], 5, 'f', 2)
.arg(QChar(0x00B0)) .arg(QChar(0x00B0))
.arg(latLongSubPointPosition[1], 5, 'f', 3) .arg(latLongSubPointPosition[1], 5, 'f', 3)
.arg(QChar(0x00B0)); .arg(QChar(0x00B0));
oss << "<br/><br/>"; oss << "<br/>";
//TODO: This one can be done better //TODO: This one can be done better
const char* xyz = "<b>X:</b> %1, <b>Y:</b> %2, <b>Z:</b> %3" ; const char* xyz = "<b>X:</b> %1, <b>Y:</b> %2, <b>Z:</b> %3" ;
QString temeCoords = QString(xyz) QString temeCoords = QString(xyz)
.arg(position[0], 5, 'f', 2) .arg(position[0], 5, 'f', 2)
.arg(position[1], 5, 'f', 2) .arg(position[1], 5, 'f', 2)
.arg(position[2], 5, 'f', 2); .arg(position[2], 5, 'f', 2);
// TRANSLATORS: TEME is an Earth-centered inertial coordinat e system // TRANSLATORS: TEME is an Earth-centered inertial coordinat e system
oss << QString(q_("TEME coordinates (km): %1")).arg(temeCoor ds); oss << QString(q_("TEME coordinates (km): %1")).arg(temeCoor ds);
oss << "<br/>"; oss << "<br/>";
skipping to change at line 342 skipping to change at line 345
oss << "<br/>"; oss << "<br/>";
if (sunReflAngle>0) if (sunReflAngle>0)
{ // Iridium { // Iridium
oss << QString(q_("Sun reflection angle: %1%2")) oss << QString(q_("Sun reflection angle: %1%2"))
.arg(sunReflAngle,0,'f',1) .arg(sunReflAngle,0,'f',1)
.arg(QChar(0x00B0)); // Degree sign .arg(QChar(0x00B0)); // Degree sign
oss << "<br/>"; oss << "<br/>";
} }
// Groups of the artificial satellites
QStringList groupList;
foreach(const QString &g, groups)
groupList << q_(g);
if (!groupList.isEmpty())
{
QString group = q_("Group");
if (groups.count()>1)
group = q_("Groups");
oss << QString("%1: %2").arg(group, groupList.join("
, ")) << "<br/>";
}
if (status!=StatusUnknown) if (status!=StatusUnknown)
oss << QString(q_("Operational status: %1")).arg(get OperationalStatus()) << "<br/>"; oss << QString(q_("Operational status: %1")).arg(get OperationalStatus()) << "<br/>";
//Visibility: Full text //Visibility: Full text
//TODO: Move to a more prominent place. //TODO: Move to a more prominent place.
switch (visibility) switch (visibility)
{ {
case RADAR_SUN: case gSatWrapper::RADAR_SUN:
oss << q_("The satellite and the observer ar e in sunlight.") << "<br/>"; oss << q_("The satellite and the observer ar e in sunlight.") << "<br/>";
break; break;
case VISIBLE: case gSatWrapper::VISIBLE:
oss << q_("The satellite is visible.") << "< br/>"; oss << q_("The satellite is visible.") << "< br/>";
break; break;
case RADAR_NIGHT: case gSatWrapper::RADAR_NIGHT:
oss << q_("The satellite is eclipsed.") << " <br/>"; oss << q_("The satellite is eclipsed.") << " <br/>";
break; break;
case NOT_VISIBLE: case gSatWrapper::NOT_VISIBLE:
oss << q_("The satellite is not visible") << "<br/>"; oss << q_("The satellite is not visible") << "<br/>";
break; break;
default: default:
break; break;
} }
if (comms.size() > 0) if (comms.size() > 0)
{ {
foreach(const CommLink &c, comms) foreach(const CommLink &c, comms)
{ {
skipping to change at line 403 skipping to change at line 420
postProcessInfoString(str, flags); postProcessInfoString(str, flags);
return str; return str;
} }
QVariantMap Satellite::getInfoMap(const StelCore *core) const QVariantMap Satellite::getInfoMap(const StelCore *core) const
{ {
QVariantMap map = StelObject::getInfoMap(core); QVariantMap map = StelObject::getInfoMap(core);
map.insert("description", QString(description).replace("\n", " - ")) ; map.insert("description", QString(description).replace("\n", " - ")) ;
map.insert("catalog", id); map.insert("catalog", id);
map.insert("tle1", tleElements.first.data());
map.insert("tle2", tleElements.second.data());
if (!internationalDesignator.isEmpty()) if (!internationalDesignator.isEmpty())
map.insert("international-designator", internationalDesignat or); map.insert("international-designator", internationalDesignat or);
if (stdMag==99.f) // replace whatever has been computed if (stdMag==99.f) // replace whatever has been computed
{ {
map.insert("vmag", "?"); map.insert("vmag", "?");
map.insert("vmage", "?"); map.insert("vmage", "?");
} }
map.insert("range", range); map.insert("range", range);
skipping to change at line 433 skipping to change at line 453
if (sunReflAngle>0) if (sunReflAngle>0)
{ // Iridium { // Iridium
map.insert("sun-reflection-angle", sunReflAngle); map.insert("sun-reflection-angle", sunReflAngle);
} }
map.insert("operational-status", getOperationalStatus()); map.insert("operational-status", getOperationalStatus());
//TODO: Move to a more prominent place. //TODO: Move to a more prominent place.
QString visibilityState; QString visibilityState;
switch (visibility) switch (visibility)
{ {
case RADAR_SUN: case gSatWrapper::RADAR_SUN:
visibilityState = "The satellite and the observer ar e in sunlight."; visibilityState = "The satellite and the observer ar e in sunlight.";
break; break;
case VISIBLE: case gSatWrapper::VISIBLE:
visibilityState = "The satellite is visible."; visibilityState = "The satellite is visible.";
break; break;
case RADAR_NIGHT: case gSatWrapper::RADAR_NIGHT:
visibilityState = "The satellite is eclipsed."; visibilityState = "The satellite is eclipsed.";
break; break;
case NOT_VISIBLE: case gSatWrapper::NOT_VISIBLE:
visibilityState = "The satellite is not visible"; visibilityState = "The satellite is not visible.";
break; break;
default: default:
break; break;
} }
map.insert("visibility", visibilityState); map.insert("visibility", visibilityState);
if (comms.size() > 0) if (comms.size() > 0)
{ {
foreach(const CommLink &c, comms) foreach(const CommLink &c, comms)
{ {
double dop = getDoppler(c.frequency); double dop = getDoppler(c.frequency);
skipping to change at line 498 skipping to change at line 518
return hintColor; return hintColor;
} }
float Satellite::getVMagnitude(const StelCore* core) const float Satellite::getVMagnitude(const StelCore* core) const
{ {
Q_UNUSED(core); Q_UNUSED(core);
float vmag = 7.f; // Optimistic value of magnitude for artificial sa tellite without data for standard magnitude float vmag = 7.f; // Optimistic value of magnitude for artificial sa tellite without data for standard magnitude
if (!realisticModeFlag) if (!realisticModeFlag)
vmag = 5.0; vmag = 5.0;
if (realisticModeFlag && visibility != VISIBLE) if (realisticModeFlag && visibility != gSatWrapper::VISIBLE)
vmag = 17.f; // Artificial satellite is invisible and 17 is hypothetical value of magnitude vmag = 17.f; // Artificial satellite is invisible and 17 is hypothetical value of magnitude
if (stdMag!=99.f) if (stdMag!=99.f)
{ {
sunReflAngle = -1.; sunReflAngle = -1.;
// OK, artificial satellite has value for standard magnitude // OK, artificial satellite has value for standard magnitude
if (visibility==VISIBLE) if (visibility==gSatWrapper::VISIBLE)
{ {
// Calculation of approx. visual magnitude for artif icial satellites // Calculation of approx. visual magnitude for artif icial satellites
// described here: http://www.prismnet.com/~mmccants /tles/mccdesc.html // described here: http://www.prismnet.com/~mmccants /tles/mccdesc.html
double fracil = calculateIlluminatedFraction(); double fracil = calculateIlluminatedFraction();
if (fracil==0) if (fracil==0)
fracil = 0.000001; fracil = 0.000001;
if (pSatWrapper && name.startsWith("IRIDIUM")) if (pSatWrapper && name.startsWith("IRIDIUM"))
{ {
#ifdef IRIDIUM_SAT_TEXT_DEBUG #ifdef IRIDIUM_SAT_TEXT_DEBUG
myText = ""; myText = "";
skipping to change at line 542 skipping to change at line 562
// position, velocity are known // position, velocity are known
QVector3D Vx(velocity.data()[0],velocity.dat a()[1],velocity.data()[2]); Vx.normalize(); QVector3D Vx(velocity.data()[0],velocity.dat a()[1],velocity.data()[2]); Vx.normalize();
#ifdef IRIDIUM_SAT_TEXT_DEBUG #ifdef IRIDIUM_SAT_TEXT_DEBUG
myText += "Vx = " + QString("[%1 %2 %3]") myText += "Vx = " + QString("[%1 %2 %3]")
.arg(Vx.x()) .arg(Vx.x())
.arg(Vx.y()) .arg(Vx.y())
.arg(Vx.z()) .arg(Vx.z())
+ "<br>\n"; + "<br>\n";
#endif #endif
QVector3D SatPos(position.data()[0],position .data()[1],position.data()[2]); //QVector3D SatPos(position.data()[0],positi on.data()[1],position.data()[2]);
Vec3d vy = (position^velocity); Vec3d vy = (position^velocity);
QVector3D Vy(vy.data()[0],vy.data()[1],vy.da ta()[2]); Vy.normalize(); QVector3D Vy(vy.data()[0],vy.data()[1],vy.da ta()[2]); Vy.normalize();
#ifdef IRIDIUM_SAT_TEXT_DEBUG #ifdef IRIDIUM_SAT_TEXT_DEBUG
myText += "Vy = " + QString("[%1 %2 %3]") myText += "Vy = " + QString("[%1 %2 %3]")
.arg(Vy.x()) .arg(Vy.x())
.arg(Vy.y()) .arg(Vy.y())
.arg(Vy.z()) .arg(Vy.z())
+ "<br>\n"; + "<br>\n";
#endif #endif
skipping to change at line 581 skipping to change at line 601
.arg(Vx0.z()) .arg(Vx0.z())
+ "<br>\n"; + "<br>\n";
#endif #endif
QMatrix4x4 m[3]; QMatrix4x4 m[3];
//m[2] = m[1] = m[0]; //m[2] = m[1] = m[0];
m[0].rotate(0, Vz); m[0].rotate(0, Vz);
m[1].rotate(120, Vz); m[1].rotate(120, Vz);
m[2].rotate(-120, Vz); m[2].rotate(-120, Vz);
QVector3D mirror; StelLocation loc = StelApp::getInstance().
getCore()->getCurrentLocation();
const double radLatitude = loc.latitude
* KDEG2RAD;
const double theta = pSatWrapper->
getEpoch().toThetaLMST(loc.longitude * KDEG2RAD);
const double sinRadLatitude=sin(radLatitude)
;
const double cosRadLatitude=cos(radLatitude)
;
const double sinTheta=sin(theta);
const double cosTheta=cos(theta);
Vec3d observerECIPos;
Vec3d observerECIVel;
pSatWrapper->calcObserverECIPosition(observe
rECIPos, observerECIVel);
#ifdef IRIDIUM_SAT_TEXT_DEBUG
myText += "ObsPos = " + observerECIPos.toStr
ing() + " (" + observerECIPos.toStringLonLat() + ")<br>\n";
myText += "ObsVel = " + observerECIVel.toStr
ing() + " (" + observerECIVel.toStringLonLat() + ")<br>\n";
#endif
sunReflAngle = 180.; sunReflAngle = 180.;
QVector3D mirror;
for (int i = 0; i<3; i++) for (int i = 0; i<3; i++)
{ {
mirror = m[i].mapVector(Vx0); mirror = m[i].mapVector(Vx0);
mirror.normalize(); mirror.normalize();
#ifdef IRIDIUM_SAT_TEXT_DEBUG #ifdef IRIDIUM_SAT_TEXT_DEBUG
myText += "mirror = " + QString("[%1 %2 %3]") myText += "mirror = " + QString("[%1 %2 %3]")
.arg(mirror.x()) .arg(mirror.x())
.arg(mirror.y()) .arg(mirror.y())
.arg(mirror.z()) .arg(mirror.z())
+ "<br>\n"; + "<br>\n";
#endif #endif
// reflection R = 2*(V dot N)*N - V // reflection R = 2*(V dot N)*N - V
QVector3D rsun = 2*QVector3D::dotPr oduct(sun,mirror)*mirror - sun; QVector3D rsun = 2*QVector3D::dotPr oduct(sun,mirror)*mirror - sun;
rsun = -rsun; rsun = -rsun;
Vec3d rSun(rsun.x(),rsun.y(),rsun.z( )); Vec3d rSun(rsun.x(),rsun.y(),rsun.z( ));
#ifdef IRIDIUM_SAT_TEXT_DEBUG #ifdef IRIDIUM_SAT_TEXT_DEBUG
myText += "rSun = " + rSun.toString( ) + "<br>\n"; myText += "rSun = " + rSun.toString( ) + "<br>\n";
#endif #endif
///////////////////////////////////////////////////////////////////////////
/////////////////////////
StelLocation loc = StelApp::getIns
tance().getCore()->getCurrentLocation();
Vec3d topoRSunPos;
Vec3d observerECIPos;
Vec3d observerECIVel;
double radLatitude = loc.latitud
e * KDEG2RAD;
double theta = pSatWrapper
->getEpoch().toThetaLMST(loc.longitude * KDEG2RAD);
pSatWrapper->calcObserverECIPosition
(observerECIPos, observerECIVel);
#ifdef IRIDIUM_SAT_TEXT_DEBUG
myText += "ObsPos = " + observerECIP
os.toString() + " (" + observerECIPos.toStringLonLat() + ")<br>\n";
myText += "ObsVel = " + observerECIV
el.toString() + " (" + observerECIVel.toStringLonLat() + ")<br>\n";
#endif
//Vec3d satECIPos = getTEMEPos(); //Vec3d satECIPos = getTEMEPos();
Vec3d slantRange = rSun - observerEC IPos; Vec3d slantRange = rSun - observerEC IPos;
Vec3d topoRSunPos;
//top_s //top_s
topoRSunPos[0] = (sin(radLatitude) * topoRSunPos[0] = (sinRadLatitude * c
cos(theta) * slantRange[0] osTheta * slantRange[0]
+ sin(radLatitude) * + sinRadLatitude * s
sin(theta) * slantRange[1] inTheta * slantRange[1]
- cos(radLatitude) * - cosRadLatitude * s
slantRange[2]); lantRange[2]);
//top_e //top_e
topoRSunPos[1] = ((-1.0) * sin(theta topoRSunPos[1] = ((-1.0) * sinTheta
) * slantRange[0] * slantRange[0]
+ cos(theta) * slant + cosTheta * slantRa
Range[1]); nge[1]);
//top_z //top_z
topoRSunPos[2] = (cos(radLatitude) * topoRSunPos[2] = (cosRadLatitude * c
cos(theta) * slantRange[0] osTheta * slantRange[0]
+ cos(radLatitude) * + cosRadLatitude * s
sin(theta) * slantRange[1] inTheta * slantRange[1]
+ sin(radLatitude) * + sinRadLatitude * s
slantRange[2]); lantRange[2]);
#ifdef IRIDIUM_SAT_TEXT_DEBUG #ifdef IRIDIUM_SAT_TEXT_DEBUG
myText += "SunRefl = " + topoRSunPos .toString() + " (" + topoRSunPos.toStringLonLat() + ")<br>\n"; myText += "SunRefl = " + topoRSunPos .toString() + " (" + topoRSunPos.toStringLonLat() + ")<br>\n";
#endif #endif
sunReflAngle = qMin(elAzPosition.ang le(topoRSunPos) * KRAD2DEG, sunReflAngle) ; sunReflAngle = qMin(elAzPosition.ang le(topoRSunPos) * KRAD2DEG, sunReflAngle) ;
#ifdef IRIDIUM_SAT_TEXT_DEBUG #ifdef IRIDIUM_SAT_TEXT_DEBUG
myText += QString("Angle = %1").arg( QString::number(sunReflAngle, 'f', 1)) + "<br>"; myText += QString("Angle = %1").arg( QString::number(sunReflAngle, 'f', 1)) + "<br>";
#endif #endif
/////////////////////////////////////////////////////////////////////////// ///////////////////////// /////////////////////////////////////////////////////////////////////////// /////////////////////////
} }
skipping to change at line 725 skipping to change at line 744
double Satellite::getAngularSize(const StelCore*) const double Satellite::getAngularSize(const StelCore*) const
{ {
return 0.00001; return 0.00001;
} }
void Satellite::setNewTleElements(const QString& tle1, const QString& tle2) void Satellite::setNewTleElements(const QString& tle1, const QString& tle2)
{ {
if (pSatWrapper) if (pSatWrapper)
{ {
gSatWrapper *old = pSatWrapper; gSatWrapper *old = pSatWrapper;
pSatWrapper = NULL; pSatWrapper = Q_NULLPTR;
delete old; delete old;
} }
tleElements.first.clear(); tleElements.first.clear();
tleElements.first.append(tle1); tleElements.first.append(tle1);
tleElements.second.clear(); tleElements.second.clear();
tleElements.second.append(tle2); tleElements.second.append(tle2);
pSatWrapper = new gSatWrapper(id, tle1, tle2); pSatWrapper = new gSatWrapper(id, tle1, tle2);
orbitPoints.clear(); orbitPoints.clear();
visibilityPoints.clear(); visibilityPoints.clear();
parseInternationalDesignator(tle1); parseInternationalDesignator(tle1);
} }
void Satellite::update(double) void Satellite::update(double)
{ {
if (pSatWrapper && orbitValid) if (pSatWrapper && orbitValid)
{ {
StelCore* core = StelApp::getInstance().getCore(); StelCore* core = StelApp::getInstance().getCore();
epochTime = core->getJD() + timeShift; // We have "true" JD from core, satellites don't need JDE! epochTime = core->getJD(); // + timeShift; // We have "true" JD (UTC) from core, satellites don't need JDE!
pSatWrapper->setEpoch(epochTime); pSatWrapper->setEpoch(epochTime);
position = pSatWrapper->getTEMEPos(); position = pSatWrapper->getTEMEPos();
velocity = pSatWrapper->getTEMEVel(); velocity = pSatWrapper->getTEMEVel();
latLongSubPointPosition = pSatWrapper->getSubPoint(); latLongSubPointPosition = pSatWrapper->getSubPoint();
height = latLongSubPointPosition[2]; // km height = latLongSubPointPosition[2]; // km
if (height <= 50.0) if (height <= 150.0)
{ {
// The orbit is no longer valid. Causes include ver y out of date // The orbit is no longer valid. Causes include ver y out of date
// TLE, system date and time out of a reasonable ran ge, and orbital // TLE, system date and time out of a reasonable ran ge, and orbital
// degradation and re-entry of a satellite. In any of these cases // degradation and re-entry of a satellite. In any of these cases
// we might end up with a problem - usually a crash of Stellarium // we might end up with a problem - usually a crash of Stellarium
// because of a div/0 or something. To prevent this , we turn off // because of a div/0 or something. To prevent this , we turn off
// the satellite when the computed height is 50km. ( We can assume bogus at 250km or so...) // the satellite when the computed height is 150km. (We can assume bogus at 250km or so...)
qWarning() << "Satellite has invalid orbit:" << name << id; qWarning() << "Satellite has invalid orbit:" << name << id;
orbitValid = false; orbitValid = false;
displayed = false; // It shouldn't be displayed! displayed = false; // It shouldn't be displayed!
return; return;
} }
elAzPosition = pSatWrapper->getAltAz(); elAzPosition = pSatWrapper->getAltAz();
elAzPosition.normalize(); elAzPosition.normalize();
pSatWrapper->getSlantRange(range, rangeRate); pSatWrapper->getSlantRange(range, rangeRate);
skipping to change at line 793 skipping to change at line 812
result = -f*((rangeRate*1000.0)/SPEED_OF_LIGHT); result = -f*((rangeRate*1000.0)/SPEED_OF_LIGHT);
return result/1000000; return result/1000000;
} }
void Satellite::recalculateOrbitLines(void) void Satellite::recalculateOrbitLines(void)
{ {
orbitPoints.clear(); orbitPoints.clear();
visibilityPoints.clear(); visibilityPoints.clear();
} }
SatFlags Satellite::getFlags() SatFlags Satellite::getFlags() const
{ {
// There's also a faster, but less readable way: treating them as ui nt. // There's also a faster, but less readable way: treating them as ui nt.
SatFlags flags; SatFlags flags;
if (displayed) if (displayed)
flags |= SatDisplayed; flags |= SatDisplayed;
else else
flags |= SatNotDisplayed; flags |= SatNotDisplayed;
if (orbitDisplayed) if (orbitDisplayed)
flags |= SatOrbit; flags |= SatOrbit;
if (userDefined) if (userDefined)
skipping to change at line 824 skipping to change at line 843
displayed = flags.testFlag(SatDisplayed); displayed = flags.testFlag(SatDisplayed);
orbitDisplayed = flags.testFlag(SatOrbit); orbitDisplayed = flags.testFlag(SatOrbit);
userDefined = flags.testFlag(SatUser); userDefined = flags.testFlag(SatUser);
} }
void Satellite::parseInternationalDesignator(const QString& tle1) void Satellite::parseInternationalDesignator(const QString& tle1)
{ {
Q_ASSERT(!tle1.isEmpty()); Q_ASSERT(!tle1.isEmpty());
// The designator is encoded as columns 10-17 on the first line. // The designator is encoded as columns 10-17 on the first line.
QString rawString = tle1.mid(9, 8); QString rawString = tle1.mid(9, 6);
//TODO: Use a regular expression? //TODO: Use a regular expression?
bool ok; bool ok;
int year = rawString.left(2).toInt(&ok); int year = rawString.left(2).toInt(&ok);
if (!rawString.isEmpty() && ok) if (!rawString.isEmpty() && ok)
{ {
// Y2K bug :) I wonder what NORAD will do in 2057. :) // Y2K bug :) I wonder what NORAD will do in 2057. :)
if (year < 57) if (year < 57)
year += 2000; year += 2000;
else else
year += 1900; year += 1900;
skipping to change at line 860 skipping to change at line 879
if (comp > 0) if (comp > 0)
return false; return false;
// If the names are the same, compare IDs, i.e. NORAD numbers. // If the names are the same, compare IDs, i.e. NORAD numbers.
if (id < another.id) if (id < another.id)
return true; return true;
else else
return false; return false;
} }
void Satellite::draw(StelCore* core, StelPainter& painter, float) void Satellite::draw(StelCore* core, StelPainter& painter)
{ {
if (core->getJD()<jdLaunchYearJan1 || !displayed) // Separated because first test should be very fast.
if (!displayed)
return;
// 1) Do not show satellites before Space Era begins!
// 2) Do not show satellites when time rate is over limit (JD/sec)!
if (core->getJD()<jdLaunchYearJan1 || qAbs(core->getTimeRate())>=tim
eRateLimit)
return; return;
XYZ = getJ2000EquatorialPos(core); XYZ = getJ2000EquatorialPos(core);
StelSkyDrawer* sd = core->getSkyDrawer(); StelSkyDrawer* sd = core->getSkyDrawer();
Vec3f drawColor = invisibleSatelliteColor; Vec3f drawColor = (visibility == gSatWrapper::VISIBLE) ? hintColor :
if (visibility == VISIBLE) // Use hintColor for visible satellites o invisibleSatelliteColor; // Use hintColor for visible satellites only
nly
drawColor = hintColor;
painter.setColor(drawColor[0], drawColor[1], drawColor[2], hintBrigh tness); painter.setColor(drawColor[0], drawColor[1], drawColor[2], hintBrigh tness);
StelProjectorP prj = core->getProjection(StelCore::FrameJ2000, StelC Vec3d win;
ore::RefractionAuto); if (painter.getProjector()->projectCheck(XYZ, win))
Vec3d xy;
if (prj->projectCheck(XYZ,xy))
{ {
if (realisticModeFlag) if (realisticModeFlag)
{ {
double mag = getVMagnitude(core); double mag = getVMagnitude(core);
RCMag rcMag; RCMag rcMag;
Vec3f color = Vec3f(1.f,1.f,1.f); Vec3f color = Vec3f(1.f,1.f,1.f);
StelProjectorP origP = painter.getProjector(); // Sa //StelProjectorP origP = painter.getProjector(); //
ve projector state Save projector state
painter.setProjector(prj); //painter.setProjector(prj);
// Draw the satellite // Draw the satellite
sd->preDrawPointSource(&painter); sd->preDrawPointSource(&painter);
if (mag <= sd->getLimitMagnitude()) if (mag <= sd->getLimitMagnitude())
{ {
sd->computeRCMag(mag, &rcMag); sd->computeRCMag(mag, &rcMag);
sd->drawPointSource(&painter, Vec3f(XYZ[0],X YZ[1],XYZ[2]), rcMag, color, true); sd->drawPointSource(&painter, Vec3f(XYZ[0],X YZ[1],XYZ[2]), rcMag, color, true);
} }
sd->postDrawPointSource(&painter); sd->postDrawPointSource(&painter);
float txtMag = mag; float txtMag = mag;
if (visibility != VISIBLE) if (visibility != gSatWrapper::VISIBLE)
{ {
txtMag = mag - 10.f; // Oops... Artificial s atellite is invisible, but let's make the label visible txtMag = mag - 10.f; // Oops... Artificial s atellite is invisible, but let's make the label visible
painter.setColor(invisibleSatelliteColor[0], invisibleSatelliteColor[1], invisibleSatelliteColor[2], 1.f); painter.setColor(invisibleSatelliteColor[0], invisibleSatelliteColor[1], invisibleSatelliteColor[2], 1.f);
} }
else else
painter.setColor(color[0], color[1], color[2 ], 1.f); painter.setColor(color[0], color[1], color[2 ], 1.f);
// Draw the label of the satellite when it enabled // Draw the label of the satellite when it enabled
if (txtMag <= sd->getLimitMagnitude() && Satellite:: showLabels) if (txtMag <= sd->getLimitMagnitude() && Satellite:: showLabels)
painter.drawText(XYZ, name, 0, 10, 10, false ); painter.drawText(XYZ, name, 0, 10, 10, false );
painter.setProjector(origP); // Restrore projector s tate
} }
else else
{ {
if (Satellite::showLabels) if (Satellite::showLabels)
painter.drawText(xy[0], xy[1], name, 0, 10, 10, false); painter.drawText(XYZ, name, 0, 10, 10, false );
painter.setBlending(true, GL_ONE, GL_ONE); painter.setBlending(true, GL_ONE, GL_ONE);
Satellite::hintTexture->bind(); Satellite::hintTexture->bind();
painter.drawSprite2dMode(xy[0], xy[1], 11); painter.drawSprite2dMode(XYZ, 11);
} }
} }
if (orbitDisplayed && Satellite::orbitLinesFlag && orbitValid) drawO
rbit(painter); if (orbitDisplayed && Satellite::orbitLinesFlag && orbitValid)
drawOrbit(core, painter);
} }
void Satellite::drawOrbit(StelPainter& painter) void Satellite::drawOrbit(StelCore *core, StelPainter& painter)
{ {
Vec3d position, onscreen; Vec3d position, onscreen;
Vec3f drawColor; Vec3f drawColor;
int size = orbitPoints.size(); int size = orbitPoints.size();
QList<Vec3d>::iterator it= orbitPoints.begin();
it++;
QVector<Vec3d> vertexArray; QVector<Vec3d> vertexArray;
QVector<Vec4f> colorArray; QVector<Vec4f> colorArray;
StelProjectorP prj = painter.getProjector(); StelProjectorP prj = painter.getProjector();
vertexArray.resize(size); vertexArray.resize(size);
colorArray.resize(size); colorArray.resize(size);
painter.enableClientStates(true, false, false);
//Rest of points //Rest of points
for (int i=1; i<size; i++) for (int i=1; i<size; i++)
{ {
position.set(it->operator [](0), it->operator [](1), it->ope position = core->altAzToJ2000(orbitPoints[i].toVec3d());
rator [](2));
it++;
position.normalize(); position.normalize();
if (prj->project(position, onscreen)) // check position on t he screen if (prj->project(position, onscreen)) // check position on t he screen
{ {
vertexArray.append(position); vertexArray.append(position);
drawColor = invisibleSatelliteColor; drawColor = (visibilityPoints[i] == gSatWrapper::VIS
if (visibilityPoints[i] == VISIBLE) IBLE) ? orbitColor : invisibleSatelliteColor;
drawColor = orbitColor;
colorArray.append(Vec4f(drawColor[0], drawColor[1], drawColor[2], hintBrightness * calculateOrbitSegmentIntensity(i))); colorArray.append(Vec4f(drawColor[0], drawColor[1], drawColor[2], hintBrightness * calculateOrbitSegmentIntensity(i)));
} }
} }
painter.drawPath(vertexArray, colorArray); painter.drawPath(vertexArray, colorArray); // (does client state swi
painter.enableClientStates(false); tching as needed internally)
} }
float Satellite::calculateOrbitSegmentIntensity(int segNum) float Satellite::calculateOrbitSegmentIntensity(int segNum)
{ {
int endDist = (orbitLineSegments/2) - abs(segNum-1 - (orbitLineSegme nts/2) % orbitLineSegments); int endDist = (orbitLineSegments/2) - abs(segNum-1 - (orbitLineSegme nts/2) % orbitLineSegments);
if (endDist > orbitLineFadeSegments) if (endDist > orbitLineFadeSegments)
{ {
return 1.0; return 1.0;
} }
else else
 End of changes. 52 change blocks. 
101 lines changed or deleted 117 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/