/* * Copyright (C) 2012 Alexander Wolf * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Suite 500, Boston, MA 02110-1335, USA. */ #include "config.h" #include "Exoplanet.hpp" #include "Exoplanets.hpp" #include "StelObject.hpp" #include "StelPainter.hpp" #include "StelApp.hpp" #include "StelCore.hpp" #include "StelTexture.hpp" #include "StelUtils.hpp" #include "StelTranslator.hpp" #include "StelModuleMgr.hpp" #include "StelSkyDrawer.hpp" #include "StelLocaleMgr.hpp" #include "StarMgr.hpp" #include #include #include #include #include #include StelTextureSP Exoplanet::markerTexture; bool Exoplanet::distributionMode = false; bool Exoplanet::timelineMode = false; bool Exoplanet::habitableMode = false; Vec3f Exoplanet::exoplanetMarkerColor = Vec3f(0.4f,0.9f,0.5f); Vec3f Exoplanet::habitableExoplanetMarkerColor = Vec3f(1.f,0.5f,0.f); Exoplanet::Exoplanet(const QVariantMap& map) : initialized(false), EPCount(0), PHEPCount(0), designation(""), RA(0.), DE(0.), distance(0.), stype(""), smass(0.), smetal(0.), Vmag(99.), sradius(0.), effectiveTemp(0), hasHabitableExoplanets(false) { // return initialized if the mandatory fields are not present if (!map.contains("designation")) return; designation = map.value("designation").toString(); RA = StelUtils::getDecAngle(map.value("RA").toString()); DE = StelUtils::getDecAngle(map.value("DE").toString()); distance = map.value("distance").toFloat(); stype = map.value("stype").toString(); smass = map.value("smass").toFloat(); smetal = map.value("smetal").toFloat(); Vmag = map.value("Vmag", 99.f).toFloat(); sradius = map.value("sradius").toFloat(); effectiveTemp = map.value("effectiveTemp").toInt(); hasHabitableExoplanets = map.value("hasHP", false).toBool(); EPCount=0; PHEPCount=0; if (map.contains("exoplanets")) { foreach(const QVariant &expl, map.value("exoplanets").toList()) { QVariantMap exoplanetMap = expl.toMap(); exoplanetData p; EPCount++; if (exoplanetMap.contains("planetName")) p.planetName = exoplanetMap.value("planetName").toString(); p.period = exoplanetMap.value("period", -1.f).toFloat(); p.mass = exoplanetMap.value("mass", -1.f).toFloat(); p.radius = exoplanetMap.value("radius", -1.f).toFloat(); p.semiAxis = exoplanetMap.value("semiAxis", -1.f).toFloat(); p.eccentricity = exoplanetMap.value("eccentricity", -1.f).toFloat(); p.inclination = exoplanetMap.value("inclination", -1.f).toFloat(); p.angleDistance = exoplanetMap.value("angleDistance", -1.f).toFloat(); p.discovered = exoplanetMap.value("discovered", 0).toInt(); p.hclass = exoplanetMap.value("hclass", "").toString(); if (!p.hclass.isEmpty()) PHEPCount++; p.MSTemp = exoplanetMap.value("MSTemp", -1).toInt(); p.ESI = exoplanetMap.value("ESI", -1).toInt(); exoplanets.append(p); } } initialized = true; } Exoplanet::~Exoplanet() { // } QVariantMap Exoplanet::getMap(void) { QVariantMap map; map["designation"] = designation; map["RA"] = RA; map["DE"] = DE; map["distance"] = distance; map["stype"] = stype; map["smass"] = smass; map["smetal"] = smetal; map["Vmag"] = Vmag; map["sradius"] = sradius; map["effectiveTemp"] = effectiveTemp; map["hasHP"] = hasHabitableExoplanets; QVariantList exoplanetList; foreach(const exoplanetData &p, exoplanets) { QVariantMap explMap; explMap["planetName"] = p.planetName; if (p.mass > -1.f) explMap["mass"] = p.mass; if (p.period > -1.f) explMap["period"] = p.period; if (p.radius > -1.f) explMap["radius"] = p.radius; if (p.semiAxis > -1.f) explMap["semiAxis"] = p.semiAxis; if (p.inclination > -1.f) explMap["inclination"] = p.inclination; if (p.eccentricity > -1.f) explMap["eccentricity"] = p.eccentricity; if (p.angleDistance > -1.f) explMap["angleDistance"] = p.angleDistance; if (p.discovered > 0) explMap["discovered"] = p.discovered; if (!p.hclass.isEmpty()) explMap["hclass"] = p.hclass; if (p.MSTemp > 0) explMap["MSTemp"] = p.MSTemp; if (p.ESI > 0) explMap["ESI"] = p.ESI; exoplanetList << explMap; } map["exoplanets"] = exoplanetList; return map; } float Exoplanet::getSelectPriority(const StelCore *core) const { return StelObject::getSelectPriority(core)-2.f; } QString Exoplanet::getNameI18n(void) const { // Use SkyTranslator for translation star names const StelTranslator& trans = StelApp::getInstance().getLocaleMgr().getSkyTranslator(); return trans.qtranslate(designation); } QString Exoplanet::getInfoString(const StelCore* core, const InfoStringGroup& flags) const { QString str; QTextStream oss(&str); if (flags&Name) { oss << "

" << getNameI18n() << "

"; } if (flags&ObjectType) { oss << q_("Type: %1").arg(q_("planetary system")) << "
"; } if (flags&Magnitude) { if (Vmag<99 && !distributionMode) { if (core->getSkyDrawer()->getFlagHasAtmosphere()) { oss << q_("Magnitude: %1 (extincted to: %2)").arg(QString::number(getVMagnitude(core), 'f', 2), QString::number(getVMagnitudeWithExtinction(core), 'f', 2)) << "
"; } else { oss << q_("Magnitude: %1").arg(QString::number(getVMagnitude(core), 'f', 2)) << "
"; } } } // Ra/Dec etc. oss << getPositionInfoString(core, flags); if (flags&Extra && !stype.isEmpty()) { oss << q_("Spectral Type: %1").arg(stype) << "
"; } if (flags&Distance && distance>0) { oss << q_("Distance: %1 Light Years").arg(QString::number(distance/0.306601, 'f', 2)) << "
"; } if (flags&Extra) { if (smetal!=0) { oss << QString("%1 [Fe/H]: %2").arg(q_("Metallicity")).arg(smetal) << "
"; } if (smass>0) { oss << QString("%1: %2 M%3").arg(q_("Mass")).arg(QString::number(smass, 'f', 3)).arg(q_("Sun")) << "
"; } if (sradius>0) { oss << QString("%1: %2 R%3").arg(q_("Radius")).arg(QString::number(sradius, 'f', 5)).arg(q_("Sun")) << "
"; } if (effectiveTemp>0) { oss << q_("Effective temperature: %1 K").arg(effectiveTemp) << "
"; } if (exoplanets.size() > 0) { QString planetNameLabel = QString("%1").arg(q_("Exoplanet")); QString periodLabel = QString("%1 (%2)").arg(q_("Period")).arg(q_("days")); QString massLabel = QString("%1 (M%2)").arg(q_("Mass")).arg(q_("Jup")); QString radiusLabel = QString("%1 (R%2)").arg(q_("Radius")).arg(q_("Jup")); QString semiAxisLabel = QString("%1 (%2)").arg(q_("Semi-Major Axis")).arg(q_("AU")); QString eccentricityLabel = QString("%1").arg(q_("Eccentricity")); QString inclinationLabel = QString("%1 (%2)").arg(q_("Inclination")).arg(QChar(0x00B0)); QString angleDistanceLabel = QString("%1 (\")").arg(q_("Angle Distance")); QString discoveredLabel = QString("%1").arg(q_("Discovered year")); QString hClassLabel = QString("%1").arg(q_("Habitable class")); //TRANSLATORS: Full phrase is "Mean Surface Temperature" QString meanSurfaceTempLabel = QString("%1 (%2C)").arg(q_("Mean surface temp.")).arg(QChar(0x00B0)); //TRANSLATORS: ESI = Earth Similarity Index QString ESILabel = QString("%1").arg(q_("ESI")); foreach(const exoplanetData &p, exoplanets) { if (!p.planetName.isEmpty()) { planetNameLabel.append("").append(p.planetName).append(""); } else { planetNameLabel.append("—"); } if (p.period > -1.f) { periodLabel.append("").append(QString::number(p.period, 'f', 2)).append(""); } else { periodLabel.append("—"); } if (p.mass > -1.f) { massLabel.append("").append(QString::number(p.mass, 'f', 2)).append(""); } else { massLabel.append("—"); } if (p.radius > -1.f) { radiusLabel.append("").append(QString::number(p.radius, 'f', 1)).append(""); } else { radiusLabel.append("—"); } if (p.eccentricity > -1.f) { eccentricityLabel.append("").append(QString::number(p.eccentricity, 'f', 3)).append(""); } else { eccentricityLabel.append("—"); } if (p.inclination > -1.f) { inclinationLabel.append("").append(QString::number(p.inclination, 'f', 1)).append(""); } else { inclinationLabel.append("—"); } if (p.semiAxis > -1.f) { semiAxisLabel.append("").append(QString::number(p.semiAxis, 'f', 4)).append(""); } else { semiAxisLabel.append("—"); } if (p.angleDistance > -1.f) { angleDistanceLabel.append("").append(QString::number(p.angleDistance, 'f', 6)).append(""); } else { angleDistanceLabel.append("—"); } if (p.discovered > 0) { discoveredLabel.append("").append(QString::number(p.discovered)).append(""); } else { discoveredLabel.append("—"); } if (!p.hclass.isEmpty()) { hClassLabel.append("").append(p.hclass).append(""); } else { hClassLabel.append("—"); } if (p.MSTemp > 0) { meanSurfaceTempLabel.append("").append(QString::number(p.MSTemp - 273.15, 'f', 2)).append(""); } else { meanSurfaceTempLabel.append("—"); } if (p.ESI > 0) { ESILabel.append("").append(QString::number(p.ESI * 0.01, 'f', 2)).append(""); } else { ESILabel.append("—"); } } oss << ""; oss << "" << planetNameLabel << ""; oss << "" << periodLabel << ""; oss << "" << massLabel << ""; oss << "" << radiusLabel << ""; oss << "" << semiAxisLabel << ""; oss << "" << eccentricityLabel << ""; oss << "" << inclinationLabel << ""; oss << "" << angleDistanceLabel << ""; oss << "" << discoveredLabel << ""; if (hasHabitableExoplanets) { oss << "" << hClassLabel << ""; oss << "" << meanSurfaceTempLabel << ""; oss << "" << ESILabel << ""; } oss << "
"; } } postProcessInfoString(str, flags); return str; } Vec3f Exoplanet::getInfoColor(void) const { return Vec3f(1.0, 1.0, 1.0); } float Exoplanet::getVMagnitude(const StelCore* core) const { Q_UNUSED(core); if (distributionMode) { return 4.f; } else { if (Vmag<99) { return Vmag; } else { return 6.f; } } } double Exoplanet::getAngularSize(const StelCore*) const { return 0.0001; } bool Exoplanet::isDiscovered(const StelCore *core) { int year, month, day; QList discovery; // For getting value of new year from midnight at 1 Jan we need increase a value of JD on 0.5. // This hack need for correct display of discovery mode of exoplanets. StelUtils::getDateFromJulianDay(core->getJDay()+0.5, &year, &month, &day); discovery.clear(); foreach(const exoplanetData &p, exoplanets) { if (p.discovered>0) { discovery.append(p.discovered); } } qSort(discovery.begin(),discovery.end()); if (!discovery.isEmpty()) { if (discovery.at(0)<=year && discovery.at(0)>0) { return true; } } return false; } void Exoplanet::update(double deltaTime) { labelsFader.update((int)(deltaTime*1000)); } void Exoplanet::draw(StelCore* core, StelPainter *painter) { bool visible; StelSkyDrawer* sd = core->getSkyDrawer(); StarMgr* smgr = GETSTELMODULE(StarMgr); // It's need for checking displaying of labels for stars Vec3f color = exoplanetMarkerColor; if (hasHabitableExoplanets) color = habitableExoplanetMarkerColor; StelUtils::spheToRect(RA, DE, XYZ); double mag = getVMagnitudeWithExtinction(core); glEnable(GL_BLEND); glBlendFunc(GL_ONE, GL_ONE); painter->setColor(color[0], color[1], color[2], 1); if (timelineMode) { visible = isDiscovered(core); } else { visible = true; } if (habitableMode) { if (!hasHabitableExoplanets) return; } Vec3d win; // Check visibility of exoplanet system if(!visible || !(painter->getProjector()->projectCheck(XYZ, win))) {return;} float mlimit = sd->getLimitMagnitude(); if (mag <= mlimit) { Exoplanet::markerTexture->bind(); float size = getAngularSize(NULL)*M_PI/180.*painter->getProjector()->getPixelPerRadAtCenter(); float shift = 5.f + size/1.6f; painter->drawSprite2dMode(XYZ, distributionMode ? 4.f : 5.f); if (labelsFader.getInterstate()<=0.f && !distributionMode && (mag+1.f)getFlagLabels()) { painter->drawText(XYZ, designation, 0, shift, shift, false); } } }