1 /*
2 * Stellarium
3 * Copyright (C) 2002 Fabien Chereau
4 * Copyright (C) 2011 Alexander Wolf
5 * Copyright (C) 2015 Georg Zotti
6 *
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License
9 * as published by the Free Software Foundation; either version 2
10 * of the License, or (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin Street, Suite 500, Boston, MA 02110-1335, USA.
20 */
21
22 // class used to manage groups of Nebulas
23
24 #include "StelApp.hpp"
25 #include "NebulaList.hpp"
26 #include "NebulaMgr.hpp"
27 #include "Nebula.hpp"
28 #include "StelTexture.hpp"
29 #include "StelUtils.hpp"
30 #include "StelSkyDrawer.hpp"
31 #include "StelTranslator.hpp"
32 #include "StelTextureMgr.hpp"
33 #include "StelObjectMgr.hpp"
34 #include "StelLocaleMgr.hpp"
35 #include "StelSkyCultureMgr.hpp"
36 #include "StelFileMgr.hpp"
37 #include "StelModuleMgr.hpp"
38 #include "StelCore.hpp"
39 #include "StelSkyImageTile.hpp"
40 #include "StelPainter.hpp"
41 #include "RefractionExtinction.hpp"
42 #include "StelActionMgr.hpp"
43
44 #include <algorithm>
45 #include <vector>
46 #include <QDebug>
47 #include <QFile>
48 #include <QSettings>
49 #include <QString>
50 #include <QStringList>
51 #include <QRegularExpression>
52 #include <QDir>
53 #include <QMessageBox>
54
55 // Define version of valid Stellarium DSO Catalog
56 // This number must be incremented each time the content or file format of the stars catalogs change
57 static const QString StellariumDSOCatalogVersion = "3.13";
58
setLabelsColor(const Vec3f & c)59 void NebulaMgr::setLabelsColor(const Vec3f& c) {Nebula::labelColor = c; emit labelsColorChanged(c);}
getLabelsColor(void) const60 const Vec3f NebulaMgr::getLabelsColor(void) const {return Nebula::labelColor;}
setCirclesColor(const Vec3f & c)61 void NebulaMgr::setCirclesColor(const Vec3f& c) {Nebula::hintColorMap.insert(Nebula::NebUnknown, c); emit circlesColorChanged(c); }
getCirclesColor(void) const62 const Vec3f NebulaMgr::getCirclesColor(void) const {return Nebula::hintColorMap.value(Nebula::NebUnknown);}
setRegionsColor(const Vec3f & c)63 void NebulaMgr::setRegionsColor(const Vec3f& c) {Nebula::hintColorMap.insert(Nebula::NebRegion, c); emit regionsColorChanged(c); }
getRegionsColor(void) const64 const Vec3f NebulaMgr::getRegionsColor(void) const {return Nebula::hintColorMap.value(Nebula::NebRegion);}
setGalaxyColor(const Vec3f & c)65 void NebulaMgr::setGalaxyColor(const Vec3f& c) {Nebula::hintColorMap.insert(Nebula::NebGx, c); Nebula::hintColorMap.insert(Nebula::NebPartOfGx, c); emit galaxiesColorChanged(c); }
getGalaxyColor(void) const66 const Vec3f NebulaMgr::getGalaxyColor(void) const {return Nebula::hintColorMap.value(Nebula::NebGx);}
setRadioGalaxyColor(const Vec3f & c)67 void NebulaMgr::setRadioGalaxyColor(const Vec3f& c) {Nebula::hintColorMap.insert(Nebula::NebRGx, c); emit radioGalaxiesColorChanged(c); }
getRadioGalaxyColor(void) const68 const Vec3f NebulaMgr::getRadioGalaxyColor(void) const {return Nebula::hintColorMap.value(Nebula::NebRGx);}
setActiveGalaxyColor(const Vec3f & c)69 void NebulaMgr::setActiveGalaxyColor(const Vec3f& c) {Nebula::hintColorMap.insert(Nebula::NebAGx, c); emit activeGalaxiesColorChanged(c); }
getActiveGalaxyColor(void) const70 const Vec3f NebulaMgr::getActiveGalaxyColor(void) const {return Nebula::hintColorMap.value(Nebula::NebAGx);}
setInteractingGalaxyColor(const Vec3f & c)71 void NebulaMgr::setInteractingGalaxyColor(const Vec3f& c) {Nebula::hintColorMap.insert(Nebula::NebIGx, c); emit interactingGalaxiesColorChanged(c); }
getInteractingGalaxyColor(void) const72 const Vec3f NebulaMgr::getInteractingGalaxyColor(void) const {return Nebula::hintColorMap.value(Nebula::NebIGx);}
setQuasarColor(const Vec3f & c)73 void NebulaMgr::setQuasarColor(const Vec3f& c) {Nebula::hintColorMap.insert(Nebula::NebQSO, c); emit quasarsColorChanged(c); }
getQuasarColor(void) const74 const Vec3f NebulaMgr::getQuasarColor(void) const {return Nebula::hintColorMap.value(Nebula::NebQSO);}
setNebulaColor(const Vec3f & c)75 void NebulaMgr::setNebulaColor(const Vec3f& c) {Nebula::hintColorMap.insert(Nebula::NebN, c); emit nebulaeColorChanged(c); }
getNebulaColor(void) const76 const Vec3f NebulaMgr::getNebulaColor(void) const {return Nebula::hintColorMap.value(Nebula::NebN);}
setPlanetaryNebulaColor(const Vec3f & c)77 void NebulaMgr::setPlanetaryNebulaColor(const Vec3f& c) {Nebula::hintColorMap.insert(Nebula::NebPn, c); emit planetaryNebulaeColorChanged(c);}
getPlanetaryNebulaColor(void) const78 const Vec3f NebulaMgr::getPlanetaryNebulaColor(void) const {return Nebula::hintColorMap.value(Nebula::NebPn);}
setReflectionNebulaColor(const Vec3f & c)79 void NebulaMgr::setReflectionNebulaColor(const Vec3f& c) {Nebula::hintColorMap.insert(Nebula::NebRn, c); emit reflectionNebulaeColorChanged(c);}
getReflectionNebulaColor(void) const80 const Vec3f NebulaMgr::getReflectionNebulaColor(void) const {return Nebula::hintColorMap.value(Nebula::NebRn);}
setBipolarNebulaColor(const Vec3f & c)81 void NebulaMgr::setBipolarNebulaColor(const Vec3f& c) {Nebula::hintColorMap.insert(Nebula::NebBn, c); emit bipolarNebulaeColorChanged(c);}
getBipolarNebulaColor(void) const82 const Vec3f NebulaMgr::getBipolarNebulaColor(void) const {return Nebula::hintColorMap.value(Nebula::NebBn);}
setEmissionNebulaColor(const Vec3f & c)83 void NebulaMgr::setEmissionNebulaColor(const Vec3f& c) {Nebula::hintColorMap.insert(Nebula::NebEn, c); emit emissionNebulaeColorChanged(c);}
getEmissionNebulaColor(void) const84 const Vec3f NebulaMgr::getEmissionNebulaColor(void) const {return Nebula::hintColorMap.value(Nebula::NebEn);}
setDarkNebulaColor(const Vec3f & c)85 void NebulaMgr::setDarkNebulaColor(const Vec3f& c) {Nebula::hintColorMap.insert(Nebula::NebDn, c); emit darkNebulaeColorChanged(c);}
getDarkNebulaColor(void) const86 const Vec3f NebulaMgr::getDarkNebulaColor(void) const {return Nebula::hintColorMap.value(Nebula::NebDn);}
setHydrogenRegionColor(const Vec3f & c)87 void NebulaMgr::setHydrogenRegionColor(const Vec3f& c) {Nebula::hintColorMap.insert(Nebula::NebHII, c); emit hydrogenRegionsColorChanged(c);}
getHydrogenRegionColor(void) const88 const Vec3f NebulaMgr::getHydrogenRegionColor(void) const {return Nebula::hintColorMap.value(Nebula::NebHII);}
setSupernovaRemnantColor(const Vec3f & c)89 void NebulaMgr::setSupernovaRemnantColor(const Vec3f& c) {Nebula::hintColorMap.insert(Nebula::NebSNR, c); emit supernovaRemnantsColorChanged(c);}
getSupernovaRemnantColor(void) const90 const Vec3f NebulaMgr::getSupernovaRemnantColor(void) const {return Nebula::hintColorMap.value(Nebula::NebSNR);}
setSupernovaCandidateColor(const Vec3f & c)91 void NebulaMgr::setSupernovaCandidateColor(const Vec3f& c) {Nebula::hintColorMap.insert(Nebula::NebSNC, c); emit supernovaCandidatesColorChanged(c);}
getSupernovaCandidateColor(void) const92 const Vec3f NebulaMgr::getSupernovaCandidateColor(void) const {return Nebula::hintColorMap.value(Nebula::NebSNC);}
setSupernovaRemnantCandidateColor(const Vec3f & c)93 void NebulaMgr::setSupernovaRemnantCandidateColor(const Vec3f& c) {Nebula::hintColorMap.insert(Nebula::NebSNRC, c); emit supernovaRemnantCandidatesColorChanged(c);}
getSupernovaRemnantCandidateColor(void) const94 const Vec3f NebulaMgr::getSupernovaRemnantCandidateColor(void) const {return Nebula::hintColorMap.value(Nebula::NebSNRC);}
setInterstellarMatterColor(const Vec3f & c)95 void NebulaMgr::setInterstellarMatterColor(const Vec3f& c) {Nebula::hintColorMap.insert(Nebula::NebISM, c); emit interstellarMatterColorChanged(c);}
getInterstellarMatterColor(void) const96 const Vec3f NebulaMgr::getInterstellarMatterColor(void) const {return Nebula::hintColorMap.value(Nebula::NebISM);}
setClusterWithNebulosityColor(const Vec3f & c)97 void NebulaMgr::setClusterWithNebulosityColor(const Vec3f& c) {Nebula::hintColorMap.insert(Nebula::NebCn, c); emit clusterWithNebulosityColorChanged(c);}
getClusterWithNebulosityColor(void) const98 const Vec3f NebulaMgr::getClusterWithNebulosityColor(void) const {return Nebula::hintColorMap.value(Nebula::NebCn);}
setClusterColor(const Vec3f & c)99 void NebulaMgr::setClusterColor(const Vec3f& c) {Nebula::hintColorMap.insert(Nebula::NebCl, c); emit clustersColorChanged(c);}
getClusterColor(void) const100 const Vec3f NebulaMgr::getClusterColor(void) const {return Nebula::hintColorMap.value(Nebula::NebCl);}
setOpenClusterColor(const Vec3f & c)101 void NebulaMgr::setOpenClusterColor(const Vec3f& c) {Nebula::hintColorMap.insert(Nebula::NebOc, c); emit openClustersColorChanged(c);}
getOpenClusterColor(void) const102 const Vec3f NebulaMgr::getOpenClusterColor(void) const {return Nebula::hintColorMap.value(Nebula::NebOc);}
setGlobularClusterColor(const Vec3f & c)103 void NebulaMgr::setGlobularClusterColor(const Vec3f& c) {Nebula::hintColorMap.insert(Nebula::NebGc, c); emit globularClustersColorChanged(c);}
getGlobularClusterColor(void) const104 const Vec3f NebulaMgr::getGlobularClusterColor(void) const {return Nebula::hintColorMap.value(Nebula::NebGc);}
setStellarAssociationColor(const Vec3f & c)105 void NebulaMgr::setStellarAssociationColor(const Vec3f& c) {Nebula::hintColorMap.insert(Nebula::NebSA, c); emit stellarAssociationsColorChanged(c);}
getStellarAssociationColor(void) const106 const Vec3f NebulaMgr::getStellarAssociationColor(void) const {return Nebula::hintColorMap.value(Nebula::NebSA);}
setStarCloudColor(const Vec3f & c)107 void NebulaMgr::setStarCloudColor(const Vec3f& c) {Nebula::hintColorMap.insert(Nebula::NebSC, c); emit starCloudsColorChanged(c);}
getStarCloudColor(void) const108 const Vec3f NebulaMgr::getStarCloudColor(void) const {return Nebula::hintColorMap.value(Nebula::NebSC);}
setEmissionObjectColor(const Vec3f & c)109 void NebulaMgr::setEmissionObjectColor(const Vec3f& c) {Nebula::hintColorMap.insert(Nebula::NebEMO, c); emit emissionObjectsColorChanged(c);}
getEmissionObjectColor(void) const110 const Vec3f NebulaMgr::getEmissionObjectColor(void) const {return Nebula::hintColorMap.value(Nebula::NebEMO);}
setBlLacObjectColor(const Vec3f & c)111 void NebulaMgr::setBlLacObjectColor(const Vec3f& c) {Nebula::hintColorMap.insert(Nebula::NebBLL, c); emit blLacObjectsColorChanged(c);}
getBlLacObjectColor(void) const112 const Vec3f NebulaMgr::getBlLacObjectColor(void) const {return Nebula::hintColorMap.value(Nebula::NebBLL);}
setBlazarColor(const Vec3f & c)113 void NebulaMgr::setBlazarColor(const Vec3f& c) {Nebula::hintColorMap.insert(Nebula::NebBLA, c); emit blazarsColorChanged(c);}
getBlazarColor(void) const114 const Vec3f NebulaMgr::getBlazarColor(void) const {return Nebula::hintColorMap.value(Nebula::NebBLA);}
setMolecularCloudColor(const Vec3f & c)115 void NebulaMgr::setMolecularCloudColor(const Vec3f& c) {Nebula::hintColorMap.insert(Nebula::NebMolCld, c); emit molecularCloudsColorChanged(c);}
getMolecularCloudColor(void) const116 const Vec3f NebulaMgr::getMolecularCloudColor(void) const {return Nebula::hintColorMap.value(Nebula::NebMolCld);}
setYoungStellarObjectColor(const Vec3f & c)117 void NebulaMgr::setYoungStellarObjectColor(const Vec3f& c) {Nebula::hintColorMap.insert(Nebula::NebYSO, c); emit youngStellarObjectsColorChanged(c);}
getYoungStellarObjectColor(void) const118 const Vec3f NebulaMgr::getYoungStellarObjectColor(void) const {return Nebula::hintColorMap.value(Nebula::NebYSO);}
setPossibleQuasarColor(const Vec3f & c)119 void NebulaMgr::setPossibleQuasarColor(const Vec3f& c) {Nebula::hintColorMap.insert(Nebula::NebPossQSO, c); emit possibleQuasarsColorChanged(c);}
getPossibleQuasarColor(void) const120 const Vec3f NebulaMgr::getPossibleQuasarColor(void) const {return Nebula::hintColorMap.value(Nebula::NebPossQSO);}
setPossiblePlanetaryNebulaColor(const Vec3f & c)121 void NebulaMgr::setPossiblePlanetaryNebulaColor(const Vec3f& c) {Nebula::hintColorMap.insert(Nebula::NebPossPN, c); emit possiblePlanetaryNebulaeColorChanged(c);}
getPossiblePlanetaryNebulaColor(void) const122 const Vec3f NebulaMgr::getPossiblePlanetaryNebulaColor(void) const {return Nebula::hintColorMap.value(Nebula::NebPossPN);}
setProtoplanetaryNebulaColor(const Vec3f & c)123 void NebulaMgr::setProtoplanetaryNebulaColor(const Vec3f& c) {Nebula::hintColorMap.insert(Nebula::NebPPN, c); emit protoplanetaryNebulaeColorChanged(c);}
getProtoplanetaryNebulaColor(void) const124 const Vec3f NebulaMgr::getProtoplanetaryNebulaColor(void) const {return Nebula::hintColorMap.value(Nebula::NebPPN);}
setStarColor(const Vec3f & c)125 void NebulaMgr::setStarColor(const Vec3f& c) {Nebula::hintColorMap.insert(Nebula::NebStar, c); emit starsColorChanged(c);}
getStarColor(void) const126 const Vec3f NebulaMgr::getStarColor(void) const {return Nebula::hintColorMap.value(Nebula::NebStar);}
setSymbioticStarColor(const Vec3f & c)127 void NebulaMgr::setSymbioticStarColor(const Vec3f& c) {Nebula::hintColorMap.insert(Nebula::NebSymbioticStar, c); emit symbioticStarsColorChanged(c);}
getSymbioticStarColor(void) const128 const Vec3f NebulaMgr::getSymbioticStarColor(void) const {return Nebula::hintColorMap.value(Nebula::NebSymbioticStar);}
setEmissionLineStarColor(const Vec3f & c)129 void NebulaMgr::setEmissionLineStarColor(const Vec3f& c) {Nebula::hintColorMap.insert(Nebula::NebEmissionLineStar, c); emit emissionLineStarsColorChanged(c);}
getEmissionLineStarColor(void) const130 const Vec3f NebulaMgr::getEmissionLineStarColor(void) const {return Nebula::hintColorMap.value(Nebula::NebEmissionLineStar);}
setGalaxyClusterColor(const Vec3f & c)131 void NebulaMgr::setGalaxyClusterColor(const Vec3f& c) {Nebula::hintColorMap.insert(Nebula::NebGxCl, c); emit galaxyClustersColorChanged(c);}
getGalaxyClusterColor(void) const132 const Vec3f NebulaMgr::getGalaxyClusterColor(void) const {return Nebula::hintColorMap.value(Nebula::NebGxCl);}
setHintsProportional(const bool proportional)133 void NebulaMgr::setHintsProportional(const bool proportional) {if(Nebula::drawHintProportional!=proportional){ Nebula::drawHintProportional=proportional; emit hintsProportionalChanged(proportional);}}
getHintsProportional(void) const134 bool NebulaMgr::getHintsProportional(void) const {return Nebula::drawHintProportional;}
setDesignationUsage(const bool flag)135 void NebulaMgr::setDesignationUsage(const bool flag) {if(Nebula::designationUsage!=flag){ Nebula::designationUsage=flag; emit designationUsageChanged(flag);}}
getDesignationUsage(void) const136 bool NebulaMgr::getDesignationUsage(void) const {return Nebula::designationUsage; }
setFlagOutlines(const bool flag)137 void NebulaMgr::setFlagOutlines(const bool flag) {if(Nebula::flagUseOutlines!=flag){ Nebula::flagUseOutlines=flag; emit flagOutlinesDisplayedChanged(flag);}}
getFlagOutlines(void) const138 bool NebulaMgr::getFlagOutlines(void) const {return Nebula::flagUseOutlines;}
setFlagAdditionalNames(const bool flag)139 void NebulaMgr::setFlagAdditionalNames(const bool flag) {if(Nebula::flagShowAdditionalNames!=flag){ Nebula::flagShowAdditionalNames=flag; emit flagAdditionalNamesDisplayedChanged(flag);}}
getFlagAdditionalNames(void) const140 bool NebulaMgr::getFlagAdditionalNames(void) const {return Nebula::flagShowAdditionalNames;}
141
NebulaMgr(void)142 NebulaMgr::NebulaMgr(void) : StelObjectModule()
143 , nebGrid(200)
144 , hintsAmount(0)
145 , labelsAmount(0)
146 , flagConverter(false)
147 , flagDecimalCoordinates(true)
148 {
149 setObjectName("NebulaMgr");
150 }
151
~NebulaMgr()152 NebulaMgr::~NebulaMgr()
153 {
154 Nebula::texCircle = StelTextureSP();
155 Nebula::texCircleLarge = StelTextureSP();
156 Nebula::texRegion = StelTextureSP();
157 Nebula::texGalaxy = StelTextureSP();
158 Nebula::texGalaxyLarge = StelTextureSP();
159 Nebula::texOpenCluster = StelTextureSP();
160 Nebula::texOpenClusterLarge = StelTextureSP();
161 Nebula::texOpenClusterXLarge = StelTextureSP();
162 Nebula::texGlobularCluster = StelTextureSP();
163 Nebula::texGlobularClusterLarge = StelTextureSP();
164 Nebula::texPlanetaryNebula = StelTextureSP();
165 Nebula::texDiffuseNebula = StelTextureSP();
166 Nebula::texDiffuseNebulaLarge = StelTextureSP();
167 Nebula::texDiffuseNebulaXLarge = StelTextureSP();
168 Nebula::texDarkNebula = StelTextureSP();
169 Nebula::texDarkNebulaLarge = StelTextureSP();
170 Nebula::texOpenClusterWithNebulosity = StelTextureSP();
171 Nebula::texOpenClusterWithNebulosityLarge = StelTextureSP();
172 }
173
174 /*************************************************************************
175 Reimplementation of the getCallOrder method
176 *************************************************************************/
getCallOrder(StelModuleActionName actionName) const177 double NebulaMgr::getCallOrder(StelModuleActionName actionName) const
178 {
179 if (actionName==StelModule::ActionDraw)
180 return StelApp::getInstance().getModuleMgr().getModule("MilkyWay")->getCallOrder(actionName)+10;
181 return 0;
182 }
183
184 // read from stream
init()185 void NebulaMgr::init()
186 {
187 QSettings* conf = StelApp::getInstance().getSettings();
188 Q_ASSERT(conf);
189
190 Nebula::buildTypeStringMap();
191 nebulaFont.setPixelSize(StelApp::getInstance().getScreenFontSize());
192 connect(&StelApp::getInstance(), SIGNAL(screenFontSizeChanged(int)), SLOT(setFontSizeFromApp(int)));
193 // Load circle texture
194 Nebula::texCircle = StelApp::getInstance().getTextureManager().createTexture(StelFileMgr::getInstallationDir()+"/textures/neb.png");
195 // Load circle texture for large DSO
196 Nebula::texCircleLarge = StelApp::getInstance().getTextureManager().createTexture(StelFileMgr::getInstallationDir()+"/textures/neb_lrg.png");
197 // Load dashed shape texture
198 Nebula::texRegion = StelApp::getInstance().getTextureManager().createTexture(StelFileMgr::getInstallationDir()+"/textures/neb_reg.png");
199 // Load ellipse texture
200 Nebula::texGalaxy = StelApp::getInstance().getTextureManager().createTexture(StelFileMgr::getInstallationDir()+"/textures/neb_gal.png");
201 // Load ellipse texture for large galaxies
202 Nebula::texGalaxyLarge = StelApp::getInstance().getTextureManager().createTexture(StelFileMgr::getInstallationDir()+"/textures/neb_gal_lrg.png");
203 // Load open cluster marker texture
204 Nebula::texOpenCluster = StelApp::getInstance().getTextureManager().createTexture(StelFileMgr::getInstallationDir()+"/textures/neb_ocl.png");
205 // Load open cluster marker texture for large objects
206 Nebula::texOpenClusterLarge = StelApp::getInstance().getTextureManager().createTexture(StelFileMgr::getInstallationDir()+"/textures/neb_ocl_lrg.png");
207 // Load open cluster marker texture for extra large objects
208 Nebula::texOpenClusterXLarge = StelApp::getInstance().getTextureManager().createTexture(StelFileMgr::getInstallationDir()+"/textures/neb_ocl_xlrg.png");
209 // Load globular cluster marker texture
210 Nebula::texGlobularCluster = StelApp::getInstance().getTextureManager().createTexture(StelFileMgr::getInstallationDir()+"/textures/neb_gcl.png");
211 // Load globular cluster marker texture for large GCls
212 Nebula::texGlobularClusterLarge = StelApp::getInstance().getTextureManager().createTexture(StelFileMgr::getInstallationDir()+"/textures/neb_gcl_lrg.png");
213 // Load planetary nebula marker texture
214 Nebula::texPlanetaryNebula = StelApp::getInstance().getTextureManager().createTexture(StelFileMgr::getInstallationDir()+"/textures/neb_pnb.png");
215 // Load diffuse nebula marker texture
216 Nebula::texDiffuseNebula = StelApp::getInstance().getTextureManager().createTexture(StelFileMgr::getInstallationDir()+"/textures/neb_dif.png");
217 // Load diffuse nebula marker texture for large DSO
218 Nebula::texDiffuseNebulaLarge = StelApp::getInstance().getTextureManager().createTexture(StelFileMgr::getInstallationDir()+"/textures/neb_dif_lrg.png");
219 // Load diffuse nebula marker texture for extra large DSO
220 Nebula::texDiffuseNebulaXLarge = StelApp::getInstance().getTextureManager().createTexture(StelFileMgr::getInstallationDir()+"/textures/neb_dif_xlrg.png");
221 // Load dark nebula marker texture
222 Nebula::texDarkNebula = StelApp::getInstance().getTextureManager().createTexture(StelFileMgr::getInstallationDir()+"/textures/neb_drk.png");
223 // Load dark nebula marker texture for large DSO
224 Nebula::texDarkNebulaLarge = StelApp::getInstance().getTextureManager().createTexture(StelFileMgr::getInstallationDir()+"/textures/neb_drk_lrg.png");
225 // Load Ocl/Nebula marker texture
226 Nebula::texOpenClusterWithNebulosity = StelApp::getInstance().getTextureManager().createTexture(StelFileMgr::getInstallationDir()+"/textures/neb_ocln.png");
227 // Load Ocl/Nebula marker texture for large objects
228 Nebula::texOpenClusterWithNebulosityLarge = StelApp::getInstance().getTextureManager().createTexture(StelFileMgr::getInstallationDir()+"/textures/neb_ocln_lrg.png");
229 // Load pointer texture
230 texPointer = StelApp::getInstance().getTextureManager().createTexture(StelFileMgr::getInstallationDir()+"/textures/pointeur5.png");
231
232 setFlagShow(conf->value("astro/flag_nebula",true).toBool());
233 setFlagHints(conf->value("astro/flag_nebula_name",false).toBool());
234 setHintsAmount(conf->value("astro/nebula_hints_amount", 3.0).toDouble());
235 setLabelsAmount(conf->value("astro/nebula_labels_amount", 3.0).toDouble());
236 setHintsProportional(conf->value("astro/flag_nebula_hints_proportional", false).toBool());
237 setFlagOutlines(conf->value("astro/flag_dso_outlines_usage", false).toBool());
238 setFlagAdditionalNames(conf->value("astro/flag_dso_additional_names",true).toBool());
239 setDesignationUsage(conf->value("astro/flag_dso_designation_usage", false).toBool());
240 setFlagSurfaceBrightnessUsage(conf->value("astro/flag_surface_brightness_usage", false).toBool());
241 setFlagSurfaceBrightnessArcsecUsage(conf->value("gui/flag_surface_brightness_arcsec", false).toBool());
242 setFlagSurfaceBrightnessShortNotationUsage(conf->value("gui/flag_surface_brightness_short", false).toBool());
243
244 setFlagSizeLimitsUsage(conf->value("astro/flag_size_limits_usage", false).toBool());
245 setMinSizeLimit(conf->value("astro/size_limit_min", 1.0).toDouble());
246 setMaxSizeLimit(conf->value("astro/size_limit_max", 600.0).toDouble());
247
248 // Load colors from config file
249 // Upgrade config keys
250 if (conf->contains("color/nebula_label_color"))
251 {
252 conf->setValue("color/dso_label_color", conf->value("color/nebula_label_color", "0.4,0.3,0.5").toString());
253 conf->remove("color/nebula_label_color");
254 }
255 if (conf->contains("color/nebula_circle_color"))
256 {
257 conf->setValue("color/dso_circle_color", conf->value("color/nebula_circle_color", "0.8,0.8,0.1").toString());
258 conf->remove("color/nebula_circle_color");
259 }
260 if (conf->contains("color/nebula_galaxy_color"))
261 {
262 conf->setValue("color/dso_galaxy_color", conf->value("color/nebula_galaxy_color", "1.0,0.2,0.2").toString());
263 conf->remove("color/nebula_galaxy_color");
264 }
265 if (conf->contains("color/nebula_radioglx_color"))
266 {
267 conf->setValue("color/dso_radio_galaxy_color", conf->value("color/nebula_radioglx_color", "0.3,0.3,0.3").toString());
268 conf->remove("color/nebula_radioglx_color");
269 }
270 if (conf->contains("color/nebula_activeglx_color"))
271 {
272 conf->setValue("color/dso_active_galaxy_color", conf->value("color/nebula_activeglx_color", "1.0,0.5,0.2").toString());
273 conf->remove("color/nebula_activeglx_color");
274 }
275 if (conf->contains("color/nebula_intglx_color"))
276 {
277 conf->setValue("color/dso_interacting_galaxy_color", conf->value("color/nebula_intglx_color", "0.2,0.5,1.0").toString());
278 conf->remove("color/nebula_intglx_color");
279 }
280 if (conf->contains("color/nebula_brightneb_color"))
281 {
282 conf->setValue("color/dso_nebula_color", conf->value("color/nebula_brightneb_color", "0.1,1.0,0.1").toString());
283 conf->remove("color/nebula_brightneb_color");
284 }
285 if (conf->contains("color/nebula_darkneb_color"))
286 {
287 conf->setValue("color/dso_dark_nebula_color", conf->value("color/nebula_darkneb_color", "0.3,0.3,0.3").toString());
288 conf->remove("color/nebula_darkneb_color");
289 }
290 if (conf->contains("color/nebula_hregion_color"))
291 {
292 conf->setValue("color/dso_hydrogen_region_color", conf->value("color/nebula_hregion_color", "0.1,1.0,0.1").toString());
293 conf->remove("color/nebula_hregion_color");
294 }
295 if (conf->contains("color/nebula_snr_color"))
296 {
297 conf->setValue("color/dso_supernova_remnant_color", conf->value("color/nebula_snr_color", "0.1,1.0,0.1").toString());
298 conf->remove("color/nebula_snr_color");
299 }
300 if (conf->contains("color/nebula_cluster_color"))
301 {
302 conf->setValue("color/dso_cluster_color", conf->value("color/nebula_cluster_color", "0.8,0.8,0.1").toString());
303 conf->remove("color/nebula_cluster_color");
304 }
305
306 // Set colors for markers
307 setLabelsColor(Vec3f(conf->value("color/dso_label_color", "0.2,0.6,0.7").toString()));
308 setCirclesColor(Vec3f(conf->value("color/dso_circle_color", "1.0,0.7,0.2").toString()));
309 setRegionsColor(Vec3f(conf->value("color/dso_region_color", "0.7,0.7,0.2").toString()));
310
311 QString defaultGalaxyColor = conf->value("color/dso_galaxy_color", "1.0,0.2,0.2").toString();
312 setGalaxyColor( Vec3f(defaultGalaxyColor));
313 setRadioGalaxyColor( Vec3f(conf->value("color/dso_radio_galaxy_color", "0.3,0.3,0.3").toString()));
314 setActiveGalaxyColor( Vec3f(conf->value("color/dso_active_galaxy_color", "1.0,0.5,0.2").toString()));
315 setInteractingGalaxyColor(Vec3f(conf->value("color/dso_interacting_galaxy_color", "0.2,0.5,1.0").toString()));
316 setGalaxyClusterColor( Vec3f(conf->value("color/dso_galaxy_cluster_color", "0.2,0.8,1.0").toString()));
317 setQuasarColor( Vec3f(conf->value("color/dso_quasar_color", defaultGalaxyColor).toString()));
318 setPossibleQuasarColor( Vec3f(conf->value("color/dso_possible_quasar_color", defaultGalaxyColor).toString()));
319 setBlLacObjectColor( Vec3f(conf->value("color/dso_bl_lac_color", defaultGalaxyColor).toString()));
320 setBlazarColor( Vec3f(conf->value("color/dso_blazar_color", defaultGalaxyColor).toString()));
321
322 QString defaultNebulaColor = conf->value("color/dso_nebula_color", "0.1,1.0,0.1").toString();
323 setNebulaColor( Vec3f(defaultNebulaColor));
324 setPlanetaryNebulaColor( Vec3f(conf->value("color/dso_planetary_nebula_color", defaultNebulaColor).toString()));
325 setReflectionNebulaColor( Vec3f(conf->value("color/dso_reflection_nebula_color", defaultNebulaColor).toString()));
326 setBipolarNebulaColor( Vec3f(conf->value("color/dso_bipolar_nebula_color", defaultNebulaColor).toString()));
327 setEmissionNebulaColor( Vec3f(conf->value("color/dso_emission_nebula_color", defaultNebulaColor).toString()));
328 setDarkNebulaColor( Vec3f(conf->value("color/dso_dark_nebula_color", "0.3,0.3,0.3").toString()));
329 setHydrogenRegionColor( Vec3f(conf->value("color/dso_hydrogen_region_color", defaultNebulaColor).toString()));
330 setSupernovaRemnantColor( Vec3f(conf->value("color/dso_supernova_remnant_color", defaultNebulaColor).toString()));
331 setSupernovaCandidateColor( Vec3f(conf->value("color/dso_supernova_candidate_color", defaultNebulaColor).toString()));
332 setSupernovaRemnantCandidateColor(Vec3f(conf->value("color/dso_supernova_remnant_cand_color", defaultNebulaColor).toString()));
333 setInterstellarMatterColor( Vec3f(conf->value("color/dso_interstellar_matter_color", defaultNebulaColor).toString()));
334 setClusterWithNebulosityColor( Vec3f(conf->value("color/dso_cluster_with_nebulosity_color", defaultNebulaColor).toString()));
335 setMolecularCloudColor( Vec3f(conf->value("color/dso_molecular_cloud_color", defaultNebulaColor).toString()));
336 setPossiblePlanetaryNebulaColor( Vec3f(conf->value("color/dso_possible_planetary_nebula_color", defaultNebulaColor).toString()));
337 setProtoplanetaryNebulaColor( Vec3f(conf->value("color/dso_protoplanetary_nebula_color", defaultNebulaColor).toString()));
338
339 QString defaultClusterColor = conf->value("color/dso_cluster_color", "1.0,1.0,0.1").toString();
340 setClusterColor( Vec3f(defaultClusterColor));
341 setOpenClusterColor( Vec3f(conf->value("color/dso_open_cluster_color", defaultClusterColor).toString()));
342 setGlobularClusterColor( Vec3f(conf->value("color/dso_globular_cluster_color", defaultClusterColor).toString()));
343 setStellarAssociationColor(Vec3f(conf->value("color/dso_stellar_association_color", defaultClusterColor).toString()));
344 setStarCloudColor( Vec3f(conf->value("color/dso_star_cloud_color", defaultClusterColor).toString()));
345
346 QString defaultStellarColor = conf->value("color/dso_star_color", "1.0,0.7,0.2").toString();
347 setStarColor( Vec3f(defaultStellarColor));
348 setSymbioticStarColor( Vec3f(conf->value("color/dso_symbiotic_star_color", defaultStellarColor).toString()));
349 setEmissionLineStarColor( Vec3f(conf->value("color/dso_emission_star_color", defaultStellarColor).toString()));
350 setEmissionObjectColor( Vec3f(conf->value("color/dso_emission_object_color", defaultStellarColor).toString()));
351 setYoungStellarObjectColor(Vec3f(conf->value("color/dso_young_stellar_object_color", defaultStellarColor).toString()));
352
353 // for DSO convertor (for developers!)
354 flagConverter = conf->value("devel/convert_dso_catalog", false).toBool();
355 flagDecimalCoordinates = conf->value("devel/convert_dso_decimal_coord", true).toBool();
356
357 setFlagUseTypeFilters(conf->value("astro/flag_use_type_filter", false).toBool());
358
359 Nebula::CatalogGroup catalogFilters = Nebula::CatalogGroup(Q_NULLPTR);
360
361 conf->beginGroup("dso_catalog_filters");
362 if (conf->value("flag_show_ngc", true).toBool())
363 catalogFilters |= Nebula::CatNGC;
364 if (conf->value("flag_show_ic", true).toBool())
365 catalogFilters |= Nebula::CatIC;
366 if (conf->value("flag_show_m", true).toBool())
367 catalogFilters |= Nebula::CatM;
368 if (conf->value("flag_show_c", false).toBool())
369 catalogFilters |= Nebula::CatC;
370 if (conf->value("flag_show_b", false).toBool())
371 catalogFilters |= Nebula::CatB;
372 if (conf->value("flag_show_sh2", false).toBool())
373 catalogFilters |= Nebula::CatSh2;
374 if (conf->value("flag_show_vdb", false).toBool())
375 catalogFilters |= Nebula::CatVdB;
376 if (conf->value("flag_show_lbn", false).toBool())
377 catalogFilters |= Nebula::CatLBN;
378 if (conf->value("flag_show_ldn", false).toBool())
379 catalogFilters |= Nebula::CatLDN;
380 if (conf->value("flag_show_rcw", false).toBool())
381 catalogFilters |= Nebula::CatRCW;
382 if (conf->value("flag_show_cr", false).toBool())
383 catalogFilters |= Nebula::CatCr;
384 if (conf->value("flag_show_mel", false).toBool())
385 catalogFilters |= Nebula::CatMel;
386 if (conf->value("flag_show_pgc", false).toBool())
387 catalogFilters |= Nebula::CatPGC;
388 if (conf->value("flag_show_ced", false).toBool())
389 catalogFilters |= Nebula::CatCed;
390 if (conf->value("flag_show_ugc", false).toBool())
391 catalogFilters |= Nebula::CatUGC;
392 if (conf->value("flag_show_arp", false).toBool())
393 catalogFilters |= Nebula::CatArp;
394 if (conf->value("flag_show_vv", false).toBool())
395 catalogFilters |= Nebula::CatVV;
396 if (conf->value("flag_show_pk", false).toBool())
397 catalogFilters |= Nebula::CatPK;
398 if (conf->value("flag_show_png", false).toBool())
399 catalogFilters |= Nebula::CatPNG;
400 if (conf->value("flag_show_snrg", false).toBool())
401 catalogFilters |= Nebula::CatSNRG;
402 if (conf->value("flag_show_aco", false).toBool())
403 catalogFilters |= Nebula::CatACO;
404 if (conf->value("flag_show_hcg", false).toBool())
405 catalogFilters |= Nebula::CatHCG;
406 if (conf->value("flag_show_eso", false).toBool())
407 catalogFilters |= Nebula::CatESO;
408 if (conf->value("flag_show_vdbh", false).toBool())
409 catalogFilters |= Nebula::CatVdBH;
410 if (conf->value("flag_show_dwb", false).toBool())
411 catalogFilters |= Nebula::CatDWB;
412 if (conf->value("flag_show_tr", false).toBool())
413 catalogFilters |= Nebula::CatTr;
414 if (conf->value("flag_show_st", false).toBool())
415 catalogFilters |= Nebula::CatSt;
416 if (conf->value("flag_show_ru", false).toBool())
417 catalogFilters |= Nebula::CatRu;
418 if (conf->value("flag_show_vdbha", false).toBool())
419 catalogFilters |= Nebula::CatVdBHa;
420 if (conf->value("flag_show_other", true).toBool())
421 catalogFilters |= Nebula::CatOther;
422 conf->endGroup();
423
424 // NB: nebula set loaded inside setter of catalog filter
425 setCatalogFilters(catalogFilters);
426
427 Nebula::TypeGroup typeFilters = Nebula::TypeGroup(Q_NULLPTR);
428
429 conf->beginGroup("dso_type_filters");
430 if (conf->value("flag_show_galaxies", true).toBool())
431 typeFilters |= Nebula::TypeGalaxies;
432 if (conf->value("flag_show_active_galaxies", true).toBool())
433 typeFilters |= Nebula::TypeActiveGalaxies;
434 if (conf->value("flag_show_interacting_galaxies", true).toBool())
435 typeFilters |= Nebula::TypeInteractingGalaxies;
436 if (conf->value("flag_show_open_clusters", true).toBool())
437 typeFilters |= Nebula::TypeOpenStarClusters;
438 if (conf->value("flag_show_globular_clusters", true).toBool())
439 typeFilters |= Nebula::TypeGlobularStarClusters;
440 if (conf->value("flag_show_bright_nebulae", true).toBool())
441 typeFilters |= Nebula::TypeBrightNebulae;
442 if (conf->value("flag_show_dark_nebulae", true).toBool())
443 typeFilters |= Nebula::TypeDarkNebulae;
444 if (conf->value("flag_show_planetary_nebulae", true).toBool())
445 typeFilters |= Nebula::TypePlanetaryNebulae;
446 if (conf->value("flag_show_hydrogen_regions", true).toBool())
447 typeFilters |= Nebula::TypeHydrogenRegions;
448 if (conf->value("flag_show_supernova_remnants", true).toBool())
449 typeFilters |= Nebula::TypeSupernovaRemnants;
450 if (conf->value("flag_show_galaxy_clusters", true).toBool())
451 typeFilters |= Nebula::TypeGalaxyClusters;
452 if (conf->value("flag_show_other", true).toBool())
453 typeFilters |= Nebula::TypeOther;
454 conf->endGroup();
455
456 setTypeFilters(typeFilters);
457
458 // TODO: mechanism to specify which sets get loaded at start time.
459 // candidate methods:
460 // 1. config file option (list of sets to load at startup)
461 // 2. load all
462 // 3. flag in nebula_textures.fab (yuk)
463 // 4. info.ini file in each set containing a "load at startup" item
464 // For now (0.9.0), just load the default set
465 loadNebulaSet("default");
466
467 updateI18n();
468
469 StelApp *app = &StelApp::getInstance();
470 connect(app, SIGNAL(languageChanged()), this, SLOT(updateI18n()));
471 connect(&app->getSkyCultureMgr(), SIGNAL(currentSkyCultureChanged(QString)), this, SLOT(updateSkyCulture(const QString&)));
472 GETSTELMODULE(StelObjectMgr)->registerStelObjectMgr(this);
473
474 addAction("actionShow_Nebulas", N_("Display Options"), N_("Deep-sky objects"), "flagHintDisplayed", "D", "N");
475 addAction("actionSet_Nebula_TypeFilterUsage", N_("Display Options"), N_("Toggle DSO type filter"), "flagTypeFiltersUsage");
476 }
477
478 struct DrawNebulaFuncObject
479 {
DrawNebulaFuncObjectDrawNebulaFuncObject480 DrawNebulaFuncObject(float amaxMagHints, float amaxMagLabels, StelPainter* p, StelCore* aCore, bool acheckMaxMagHints)
481 : maxMagHints(amaxMagHints)
482 , maxMagLabels(amaxMagLabels)
483 , sPainter(p)
484 , core(aCore)
485 , checkMaxMagHints(acheckMaxMagHints)
486 {
487 angularSizeLimit = 5.f/sPainter->getProjector()->getPixelPerRadAtCenter()*M_180_PIf;
488 }
operator ()DrawNebulaFuncObject489 void operator()(StelRegionObject* obj)
490 {
491 if (checkMaxMagHints)
492 return;
493
494 Nebula* n = static_cast<Nebula*>(obj);
495 float mag = n->vMag;
496 if (mag>90.f)
497 mag = n->bMag;
498
499 StelSkyDrawer *drawer = core->getSkyDrawer();
500 // filter out DSOs which are too dim to be seen (e.g. for bino observers)
501 if ((drawer->getFlagNebulaMagnitudeLimit()) && (mag > static_cast<float>(drawer->getCustomNebulaMagnitudeLimit())))
502 return;
503
504 if (!n->objectInDisplayedCatalog())
505 return;
506
507 if (!n->objectInAllowedSizeRangeLimits())
508 return;
509
510 if (n->majorAxisSize>angularSizeLimit || n->majorAxisSize==0.f || mag <= maxMagHints)
511 {
512 sPainter->getProjector()->project(n->getJ2000EquatorialPos(core),n->XY);
513 n->drawLabel(*sPainter, maxMagLabels);
514 n->drawHints(*sPainter, maxMagHints, core);
515 n->drawOutlines(*sPainter, maxMagHints);
516 }
517 }
518 float maxMagHints;
519 float maxMagLabels;
520 StelPainter* sPainter;
521 StelCore* core;
522 float angularSizeLimit;
523 bool checkMaxMagHints;
524 };
525
setCatalogFilters(Nebula::CatalogGroup cflags)526 void NebulaMgr::setCatalogFilters(Nebula::CatalogGroup cflags)
527 {
528 if(static_cast<int>(cflags) != static_cast<int>(Nebula::catalogFilters))
529 {
530 Nebula::catalogFilters = cflags;
531 emit catalogFiltersChanged(cflags);
532 }
533 }
534
setTypeFilters(Nebula::TypeGroup tflags)535 void NebulaMgr::setTypeFilters(Nebula::TypeGroup tflags)
536 {
537 if(static_cast<int>(tflags) != static_cast<int>(Nebula::typeFilters))
538 {
539 Nebula::typeFilters = tflags;
540 emit typeFiltersChanged(tflags);
541 }
542 }
543
setFlagSurfaceBrightnessUsage(const bool usage)544 void NebulaMgr::setFlagSurfaceBrightnessUsage(const bool usage)
545 {
546 if (usage!=Nebula::surfaceBrightnessUsage)
547 {
548 Nebula::surfaceBrightnessUsage=usage;
549 emit flagSurfaceBrightnessUsageChanged(usage);
550 }
551 }
552
getFlagSurfaceBrightnessUsage(void) const553 bool NebulaMgr::getFlagSurfaceBrightnessUsage(void) const
554 {
555 return Nebula::surfaceBrightnessUsage;
556 }
557
setFlagSurfaceBrightnessArcsecUsage(const bool usage)558 void NebulaMgr::setFlagSurfaceBrightnessArcsecUsage(const bool usage)
559 {
560 if (usage!=Nebula::flagUseArcsecSurfaceBrightness)
561 {
562 Nebula::flagUseArcsecSurfaceBrightness=usage;
563 emit flagSurfaceBrightnessArcsecUsageChanged(usage);
564 }
565 }
566
getFlagSurfaceBrightnessArcsecUsage(void) const567 bool NebulaMgr::getFlagSurfaceBrightnessArcsecUsage(void) const
568 {
569 return Nebula::flagUseArcsecSurfaceBrightness;
570 }
571
setFlagSurfaceBrightnessShortNotationUsage(const bool usage)572 void NebulaMgr::setFlagSurfaceBrightnessShortNotationUsage(const bool usage)
573 {
574 if (usage!=Nebula::flagUseShortNotationSurfaceBrightness)
575 {
576 Nebula::flagUseShortNotationSurfaceBrightness=usage;
577 emit flagSurfaceBrightnessShortNotationUsageChanged(usage);
578 }
579 }
580
getFlagSurfaceBrightnessShortNotationUsage(void) const581 bool NebulaMgr::getFlagSurfaceBrightnessShortNotationUsage(void) const
582 {
583 return Nebula::flagUseShortNotationSurfaceBrightness;
584 }
585
setFlagSizeLimitsUsage(const bool usage)586 void NebulaMgr::setFlagSizeLimitsUsage(const bool usage)
587 {
588 if (usage!=Nebula::flagUseSizeLimits)
589 {
590 Nebula::flagUseSizeLimits=usage;
591 emit flagSizeLimitsUsageChanged(usage);
592 }
593 }
594
getFlagSizeLimitsUsage(void) const595 bool NebulaMgr::getFlagSizeLimitsUsage(void) const
596 {
597 return Nebula::flagUseSizeLimits;
598 }
599
setFlagUseTypeFilters(const bool b)600 void NebulaMgr::setFlagUseTypeFilters(const bool b)
601 {
602 if (Nebula::flagUseTypeFilters!=b)
603 {
604 Nebula::flagUseTypeFilters=b;
605 emit flagUseTypeFiltersChanged(b);
606 }
607 }
608
getFlagUseTypeFilters(void) const609 bool NebulaMgr::getFlagUseTypeFilters(void) const
610 {
611 return Nebula::flagUseTypeFilters;
612 }
613
setLabelsAmount(double a)614 void NebulaMgr::setLabelsAmount(double a)
615 {
616 if((a-labelsAmount) != 0.)
617 {
618 labelsAmount=a;
619 emit labelsAmountChanged(a);
620 }
621 }
622
getLabelsAmount(void) const623 double NebulaMgr::getLabelsAmount(void) const
624 {
625 return labelsAmount;
626 }
627
setHintsAmount(double f)628 void NebulaMgr::setHintsAmount(double f)
629 {
630 if((hintsAmount-f) != 0.)
631 {
632 hintsAmount = f;
633 emit hintsAmountChanged(f);
634 }
635 }
636
getHintsAmount(void) const637 double NebulaMgr::getHintsAmount(void) const
638 {
639 return hintsAmount;
640 }
641
setMinSizeLimit(double s)642 void NebulaMgr::setMinSizeLimit(double s)
643 {
644 if((Nebula::minSizeLimit-s) != 0.)
645 {
646 Nebula::minSizeLimit = s;
647 emit minSizeLimitChanged(s);
648 }
649 }
650
getMinSizeLimit() const651 double NebulaMgr::getMinSizeLimit() const
652 {
653 return Nebula::minSizeLimit;
654 }
655
setMaxSizeLimit(double s)656 void NebulaMgr::setMaxSizeLimit(double s)
657 {
658 if((Nebula::maxSizeLimit-s) != 0.)
659 {
660 Nebula::maxSizeLimit = s;
661 emit maxSizeLimitChanged(s);
662 }
663 }
664
getMaxSizeLimit() const665 double NebulaMgr::getMaxSizeLimit() const
666 {
667 return Nebula::maxSizeLimit;
668 }
669
computeMaxMagHint(const StelSkyDrawer * skyDrawer) const670 float NebulaMgr::computeMaxMagHint(const StelSkyDrawer* skyDrawer) const
671 {
672 return skyDrawer->getLimitMagnitude()*1.2f-2.f+static_cast<float>(hintsAmount *1.)-2.f;
673 }
674
675 // Draw all the Nebulae
draw(StelCore * core)676 void NebulaMgr::draw(StelCore* core)
677 {
678 const StelProjectorP prj = core->getProjection(StelCore::FrameJ2000);
679 StelPainter sPainter(prj);
680
681 StelSkyDrawer* skyDrawer = core->getSkyDrawer();
682
683 Nebula::hintsBrightness = hintsFader.getInterstate()*flagShow.getInterstate();
684
685 sPainter.setBlending(true, GL_ONE, GL_ONE);
686
687 // Use a 4 degree margin (esp. for wide outlines)
688 const float margin = 4.f*M_PI_180f*prj->getPixelPerRadAtCenter();
689 const SphericalRegionP& p = prj->getViewportConvexPolygon(margin, margin);
690
691 // Print all the nebulae of all the selected zones
692 float maxMagHints = computeMaxMagHint(skyDrawer);
693 float maxMagLabels = skyDrawer->getLimitMagnitude()-2.f+static_cast<float>(labelsAmount*1.2)-2.f;
694 sPainter.setFont(nebulaFont);
695 DrawNebulaFuncObject func(maxMagHints, maxMagLabels, &sPainter, core, hintsFader.getInterstate()<=0.f);
696 nebGrid.processIntersectingPointInRegions(p.data(), func);
697
698 if (GETSTELMODULE(StelObjectMgr)->getFlagSelectedObjectPointer())
699 drawPointer(core, sPainter);
700 }
701
drawPointer(const StelCore * core,StelPainter & sPainter)702 void NebulaMgr::drawPointer(const StelCore* core, StelPainter& sPainter)
703 {
704 const StelProjectorP prj = core->getProjection(StelCore::FrameJ2000);
705
706 const QList<StelObjectP> newSelected = GETSTELMODULE(StelObjectMgr)->getSelectedObject("Nebula");
707 if (!newSelected.empty())
708 {
709 const StelObjectP obj = newSelected[0];
710 Vec3d pos=obj->getJ2000EquatorialPos(core);
711
712 // Compute 2D pos and return if outside screen
713 if (!prj->projectInPlace(pos)) return;
714 sPainter.setColor(0.4f,0.5f,0.8f);
715
716 texPointer->bind();
717
718 sPainter.setBlending(true);
719
720 // Size on screen
721 float size = static_cast<float>(obj->getAngularSize(core))*M_PI_180f*prj->getPixelPerRadAtCenter();
722 if (size>120.f) // avoid oversized marker
723 size = 120.f;
724
725 if (Nebula::drawHintProportional)
726 size*=1.2f;
727 size+=20.f + 10.f*std::sin(3.f * static_cast<float>(StelApp::getInstance().getAnimationTime()));
728 sPainter.drawSprite2dMode(static_cast<float>(pos[0])-size*0.5f, static_cast<float>(pos[1])-size*0.5f, 10, 90);
729 sPainter.drawSprite2dMode(static_cast<float>(pos[0])-size*0.5f, static_cast<float>(pos[1])+size*0.5f, 10, 0);
730 sPainter.drawSprite2dMode(static_cast<float>(pos[0])+size*0.5f, static_cast<float>(pos[1])+size*0.5f, 10, -90);
731 sPainter.drawSprite2dMode(static_cast<float>(pos[0])+size*0.5f, static_cast<float>(pos[1])-size*0.5f, 10, -180);
732 }
733 }
734
735 // Search by name
search(const QString & name)736 NebulaP NebulaMgr::search(const QString& name)
737 {
738 QString uname = name.toUpper();
739
740 for (const auto& n : dsoArray)
741 {
742 QString testName = n->getEnglishName().toUpper();
743 if (testName==uname) return n;
744 }
745
746 return searchByDesignation(uname);
747 }
748
loadNebulaSet(const QString & setName)749 void NebulaMgr::loadNebulaSet(const QString& setName)
750 {
751 QString srcCatalogPath = StelFileMgr::findFile("nebulae/" + setName + "/catalog.txt");
752 QString dsoCatalogPath = StelFileMgr::findFile("nebulae/" + setName + "/catalog-" + StellariumDSOCatalogVersion + ".dat");
753 if (dsoCatalogPath.isEmpty()) // Extended edition is not exist, let's try find standard edition
754 dsoCatalogPath = StelFileMgr::findFile("nebulae/" + setName + "/catalog.dat");
755 QString dsoOutlinesPath = StelFileMgr::findFile("nebulae/" + setName + "/outlines.dat");
756
757 dsoArray.clear();
758 dsoIndex.clear();
759 nebGrid.clear();
760
761 if (flagConverter)
762 {
763 if (!srcCatalogPath.isEmpty())
764 convertDSOCatalog(srcCatalogPath, StelFileMgr::findFile("nebulae/" + setName + "/catalog.pack", StelFileMgr::New), flagDecimalCoordinates);
765 else
766 qWarning() << "ERROR convert catalogue, because source data set does not exist for " << setName;
767 }
768
769 if (dsoCatalogPath.isEmpty())
770 {
771 qWarning() << "ERROR while loading deep-sky catalog data set " << setName;
772 return;
773 }
774
775 loadDSOCatalog(dsoCatalogPath);
776
777 if (!dsoOutlinesPath.isEmpty())
778 loadDSOOutlines(dsoOutlinesPath);
779 }
780
781 // Look for a nebula by XYZ coords
search(const Vec3d & apos)782 NebulaP NebulaMgr::search(const Vec3d& apos)
783 {
784 Vec3d pos(apos);
785 pos.normalize();
786 NebulaP plusProche;
787 double anglePlusProche=0.0;
788 for (const auto& n : dsoArray)
789 {
790 if (n->XYZ*pos>anglePlusProche)
791 {
792 anglePlusProche=n->XYZ*pos;
793 plusProche=n;
794 }
795 }
796 if (anglePlusProche>0.999) // object within ~2.5 degrees
797 {
798 return plusProche;
799 }
800 else return NebulaP();
801 }
802
803
searchAround(const Vec3d & av,double limitFov,const StelCore *) const804 QList<StelObjectP> NebulaMgr::searchAround(const Vec3d& av, double limitFov, const StelCore*) const
805 {
806 QList<StelObjectP> result;
807 if (!getFlagShow())
808 return result;
809
810 Vec3d v(av);
811 v.normalize();
812 const double cosLimFov = cos(limitFov * M_PI/180.);
813 Vec3d equPos;
814 for (const auto& n : dsoArray)
815 {
816 equPos = n->XYZ;
817 equPos.normalize();
818 if (equPos*v >= cosLimFov)
819 {
820 result.push_back(qSharedPointerCast<StelObject>(n));
821 }
822 }
823 return result;
824 }
825
searchDSO(unsigned int DSO) const826 NebulaP NebulaMgr::searchDSO(unsigned int DSO) const
827 {
828 if (dsoIndex.contains(DSO))
829 return dsoIndex[DSO];
830 return NebulaP();
831 }
832
833
searchM(unsigned int M) const834 NebulaP NebulaMgr::searchM(unsigned int M) const
835 {
836 for (const auto& n : dsoArray)
837 if (n->M_nb == M)
838 return n;
839 return NebulaP();
840 }
841
searchNGC(unsigned int NGC) const842 NebulaP NebulaMgr::searchNGC(unsigned int NGC) const
843 {
844 for (const auto& n : dsoArray)
845 if (n->NGC_nb == NGC)
846 return n;
847 return NebulaP();
848 }
849
searchIC(unsigned int IC) const850 NebulaP NebulaMgr::searchIC(unsigned int IC) const
851 {
852 for (const auto& n : dsoArray)
853 if (n->IC_nb == IC)
854 return n;
855 return NebulaP();
856 }
857
searchC(unsigned int C) const858 NebulaP NebulaMgr::searchC(unsigned int C) const
859 {
860 for (const auto& n : dsoArray)
861 if (n->C_nb == C)
862 return n;
863 return NebulaP();
864 }
865
searchB(unsigned int B) const866 NebulaP NebulaMgr::searchB(unsigned int B) const
867 {
868 for (const auto& n : dsoArray)
869 if (n->B_nb == B)
870 return n;
871 return NebulaP();
872 }
873
searchSh2(unsigned int Sh2) const874 NebulaP NebulaMgr::searchSh2(unsigned int Sh2) const
875 {
876 for (const auto& n : dsoArray)
877 if (n->Sh2_nb == Sh2)
878 return n;
879 return NebulaP();
880 }
881
searchVdB(unsigned int VdB) const882 NebulaP NebulaMgr::searchVdB(unsigned int VdB) const
883 {
884 for (const auto& n : dsoArray)
885 if (n->VdB_nb == VdB)
886 return n;
887 return NebulaP();
888 }
889
searchVdBHa(unsigned int VdBHa) const890 NebulaP NebulaMgr::searchVdBHa(unsigned int VdBHa) const
891 {
892 for (const auto& n : dsoArray)
893 if (n->VdBHa_nb == VdBHa)
894 return n;
895 return NebulaP();
896 }
897
searchRCW(unsigned int RCW) const898 NebulaP NebulaMgr::searchRCW(unsigned int RCW) const
899 {
900 for (const auto& n : dsoArray)
901 if (n->RCW_nb == RCW)
902 return n;
903 return NebulaP();
904 }
905
searchLDN(unsigned int LDN) const906 NebulaP NebulaMgr::searchLDN(unsigned int LDN) const
907 {
908 for (const auto& n : dsoArray)
909 if (n->LDN_nb == LDN)
910 return n;
911 return NebulaP();
912 }
913
searchLBN(unsigned int LBN) const914 NebulaP NebulaMgr::searchLBN(unsigned int LBN) const
915 {
916 for (const auto& n : dsoArray)
917 if (n->LBN_nb == LBN)
918 return n;
919 return NebulaP();
920 }
921
searchCr(unsigned int Cr) const922 NebulaP NebulaMgr::searchCr(unsigned int Cr) const
923 {
924 for (const auto& n : dsoArray)
925 if (n->Cr_nb == Cr)
926 return n;
927 return NebulaP();
928 }
929
searchMel(unsigned int Mel) const930 NebulaP NebulaMgr::searchMel(unsigned int Mel) const
931 {
932 for (const auto& n : dsoArray)
933 if (n->Mel_nb == Mel)
934 return n;
935 return NebulaP();
936 }
937
searchPGC(unsigned int PGC) const938 NebulaP NebulaMgr::searchPGC(unsigned int PGC) const
939 {
940 for (const auto& n : dsoArray)
941 if (n->PGC_nb == PGC)
942 return n;
943 return NebulaP();
944 }
945
searchUGC(unsigned int UGC) const946 NebulaP NebulaMgr::searchUGC(unsigned int UGC) const
947 {
948 for (const auto& n : dsoArray)
949 if (n->UGC_nb == UGC)
950 return n;
951 return NebulaP();
952 }
953
searchCed(QString Ced) const954 NebulaP NebulaMgr::searchCed(QString Ced) const
955 {
956 for (const auto& n : dsoArray)
957 if (n->Ced_nb.trimmed().toUpper() == Ced.trimmed().toUpper())
958 return n;
959 return NebulaP();
960 }
961
searchArp(unsigned int Arp) const962 NebulaP NebulaMgr::searchArp(unsigned int Arp) const
963 {
964 for (const auto& n : dsoArray)
965 if (n->Arp_nb == Arp)
966 return n;
967 return NebulaP();
968 }
969
searchVV(unsigned int VV) const970 NebulaP NebulaMgr::searchVV(unsigned int VV) const
971 {
972 for (const auto& n : dsoArray)
973 if (n->VV_nb == VV)
974 return n;
975 return NebulaP();
976 }
977
searchPK(QString PK) const978 NebulaP NebulaMgr::searchPK(QString PK) const
979 {
980 for (const auto& n : dsoArray)
981 if (n->PK_nb.trimmed().toUpper() == PK.trimmed().toUpper())
982 return n;
983 return NebulaP();
984 }
985
searchPNG(QString PNG) const986 NebulaP NebulaMgr::searchPNG(QString PNG) const
987 {
988 for (const auto& n : dsoArray)
989 if (n->PNG_nb.trimmed().toUpper() == PNG.trimmed().toUpper())
990 return n;
991 return NebulaP();
992 }
993
searchSNRG(QString SNRG) const994 NebulaP NebulaMgr::searchSNRG(QString SNRG) const
995 {
996 for (const auto& n : dsoArray)
997 if (n->SNRG_nb.trimmed().toUpper() == SNRG.trimmed().toUpper())
998 return n;
999 return NebulaP();
1000 }
1001
searchACO(QString ACO) const1002 NebulaP NebulaMgr::searchACO(QString ACO) const
1003 {
1004 for (const auto& n : dsoArray)
1005 if (n->ACO_nb.trimmed().toUpper() == ACO.trimmed().toUpper())
1006 return n;
1007 return NebulaP();
1008 }
1009
searchHCG(QString HCG) const1010 NebulaP NebulaMgr::searchHCG(QString HCG) const
1011 {
1012 for (const auto& n : dsoArray)
1013 if (n->HCG_nb.trimmed().toUpper() == HCG.trimmed().toUpper())
1014 return n;
1015 return NebulaP();
1016 }
1017
searchESO(QString ESO) const1018 NebulaP NebulaMgr::searchESO(QString ESO) const
1019 {
1020 for (const auto& n : dsoArray)
1021 if (n->ESO_nb.trimmed().toUpper() == ESO.trimmed().toUpper())
1022 return n;
1023 return NebulaP();
1024 }
1025
searchVdBH(QString VdBH) const1026 NebulaP NebulaMgr::searchVdBH(QString VdBH) const
1027 {
1028 for (const auto& n : dsoArray)
1029 if (n->VdBH_nb.trimmed().toUpper() == VdBH.trimmed().toUpper())
1030 return n;
1031 return NebulaP();
1032 }
1033
searchDWB(unsigned int DWB) const1034 NebulaP NebulaMgr::searchDWB(unsigned int DWB) const
1035 {
1036 for (const auto& n : dsoArray)
1037 if (n->DWB_nb == DWB)
1038 return n;
1039 return NebulaP();
1040 }
1041
searchTr(unsigned int Tr) const1042 NebulaP NebulaMgr::searchTr(unsigned int Tr) const
1043 {
1044 for (const auto& n : dsoArray)
1045 if (n->Tr_nb == Tr)
1046 return n;
1047 return NebulaP();
1048 }
1049
searchSt(unsigned int St) const1050 NebulaP NebulaMgr::searchSt(unsigned int St) const
1051 {
1052 for (const auto& n : dsoArray)
1053 if (n->St_nb == St)
1054 return n;
1055 return NebulaP();
1056 }
1057
searchRu(unsigned int Ru) const1058 NebulaP NebulaMgr::searchRu(unsigned int Ru) const
1059 {
1060 for (const auto& n : dsoArray)
1061 if (n->Ru_nb == Ru)
1062 return n;
1063 return NebulaP();
1064 }
1065
getLatestSelectedDSODesignation() const1066 QString NebulaMgr::getLatestSelectedDSODesignation() const
1067 {
1068 QString result = "";
1069
1070 const QList<StelObjectP> selected = GETSTELMODULE(StelObjectMgr)->getSelectedObject("Nebula");
1071 if (!selected.empty())
1072 {
1073 for (const auto& n : dsoArray)
1074 if (n==selected[0])
1075 result = n->getDSODesignation(); // Get designation for latest selected DSO
1076 }
1077
1078 return result;
1079 }
1080
getLatestSelectedDSODesignationWIC() const1081 QString NebulaMgr::getLatestSelectedDSODesignationWIC() const
1082 {
1083 QString result = "";
1084
1085 const QList<StelObjectP> selected = GETSTELMODULE(StelObjectMgr)->getSelectedObject("Nebula");
1086 if (!selected.empty())
1087 {
1088 for (const auto& n : dsoArray)
1089 if (n==selected[0])
1090 result = n->getDSODesignationWIC(); // Get designation for latest selected DSO
1091 }
1092
1093 return result;
1094 }
1095
convertDSOCatalog(const QString & in,const QString & out,bool decimal=false)1096 void NebulaMgr::convertDSOCatalog(const QString &in, const QString &out, bool decimal=false)
1097 {
1098 QFile dsoIn(in);
1099 if (!dsoIn.open(QIODevice::ReadOnly | QIODevice::Text))
1100 return;
1101
1102 QFile dsoOut(out);
1103 if (!dsoOut.open(QIODevice::WriteOnly))
1104 {
1105 qDebug() << "Error converting DSO data! Cannot open file" << QDir::toNativeSeparators(out);
1106 return;
1107 }
1108
1109 int totalRecords=0;
1110 QString record;
1111 while (!dsoIn.atEnd())
1112 {
1113 dsoIn.readLine();
1114 ++totalRecords;
1115 }
1116
1117 // rewind the file to the start
1118 dsoIn.seek(0);
1119
1120 QDataStream dsoOutStream(&dsoOut);
1121 dsoOutStream.setVersion(QDataStream::Qt_5_2);
1122
1123 int id, orientationAngle, NGC, IC, M, C, B, Sh2, VdB, RCW, LDN, LBN, Cr, Mel, PGC, UGC, Arp, VV, DWB, Tr, St, Ru, VdBHa;
1124 float raRad, decRad, bMag, vMag, majorAxisSize, minorAxisSize, dist, distErr, z, zErr, plx, plxErr;
1125 QString oType, mType, Ced, PK, PNG, SNRG, ACO, HCG, ESO, VdBH, ra, dec;
1126 Nebula::NebulaType nType;
1127
1128 int readOk = 0; // how many records weree rad without problems
1129 while (!dsoIn.atEnd())
1130 {
1131 record = QString::fromUtf8(dsoIn.readLine());
1132
1133 QRegularExpression version("ersion\\s+([\\d\\.]+)\\s+(\\w+)");
1134 QRegularExpressionMatch versionMatch;
1135 int vp = record.indexOf(version, 0, &versionMatch);
1136 if (vp!=-1) // Version of catalog, a first line!
1137 dsoOutStream << versionMatch.captured(1).trimmed() << versionMatch.captured(2).trimmed();
1138
1139 // skip comments
1140 if (record.startsWith("//") || record.startsWith("#"))
1141 {
1142 --totalRecords;
1143 continue;
1144 }
1145
1146 if (!record.isEmpty())
1147 {
1148 #if (QT_VERSION>=QT_VERSION_CHECK(5, 14, 0))
1149 QStringList list=record.split("\t", Qt::KeepEmptyParts);
1150 #else
1151 QStringList list=record.split("\t", QString::KeepEmptyParts);
1152 #endif
1153
1154 id = list.at(0).toInt(); // ID (inner identification number)
1155 ra = list.at(1).trimmed();
1156 dec = list.at(2).trimmed();
1157 bMag = list.at(3).toFloat(); // B magnitude
1158 vMag = list.at(4).toFloat(); // V magnitude
1159 oType = list.at(5).trimmed(); // Object type
1160 mType = list.at(6).trimmed(); // Morphological type of object
1161 majorAxisSize = list.at(7).toFloat(); // major axis size (arcmin)
1162 minorAxisSize = list.at(8).toFloat(); // minor axis size (arcmin)
1163 orientationAngle = list.at(9).toInt(); // orientation angle (degrees)
1164 z = list.at(10).toFloat(); // redshift
1165 zErr = list.at(11).toFloat(); // error of redshift
1166 plx = list.at(12).toFloat(); // parallax (mas)
1167 plxErr = list.at(13).toFloat(); // error of parallax (mas)
1168 dist = list.at(14).toFloat(); // distance (Mpc for galaxies, kpc for other objects)
1169 distErr = list.at(15).toFloat(); // distance error (Mpc for galaxies, kpc for other objects)
1170 // -----------------------------------------------
1171 // cross-identification data
1172 // -----------------------------------------------
1173 NGC = list.at(16).toInt(); // NGC number
1174 IC = list.at(17).toInt(); // IC number
1175 M = list.at(18).toInt(); // M number
1176 C = list.at(19).toInt(); // C number
1177 B = list.at(20).toInt(); // B number
1178 Sh2 = list.at(21).toInt(); // Sh2 number
1179 VdB = list.at(22).toInt(); // VdB number
1180 RCW = list.at(23).toInt(); // RCW number
1181 LDN = list.at(24).toInt(); // LDN number
1182 LBN = list.at(25).toInt(); // LBN number
1183 Cr = list.at(26).toInt(); // Cr number (alias: Col)
1184 Mel = list.at(27).toInt(); // Mel number
1185 PGC = list.at(28).toInt(); // PGC number (subset)
1186 UGC = list.at(29).toInt(); // UGC number (subset)
1187 Ced = list.at(30).trimmed(); // Ced number
1188 Arp = list.at(31).toInt(); // Arp number
1189 VV = list.at(32).toInt(); // VV number
1190 PK = list.at(33).trimmed(); // PK number
1191 PNG = list.at(34).trimmed(); // PN G number
1192 SNRG = list.at(35).trimmed(); // SNR G number
1193 ACO = list.at(36).trimmed(); // ACO number
1194 HCG = list.at(37).trimmed(); // HCG number
1195 ESO = list.at(38).trimmed(); // ESO number
1196 VdBH = list.at(39).trimmed(); // VdBH number
1197 DWB = list.at(40).toInt(); // DWB number
1198 Tr = list.at(41).toInt(); // Tr number
1199 St = list.at(42).toInt(); // St number
1200 Ru = list.at(43).toInt(); // Ru number
1201 VdBHa = list.at(44).toInt(); // VdB-Ha number
1202
1203 if (decimal)
1204 {
1205 // Convert from deg to rad
1206 raRad = ra.toFloat() *M_PI_180f;
1207 decRad = dec.toFloat()*M_PI_180f;
1208 }
1209 else
1210 {
1211 QStringList raLst;
1212 if (ra.contains(":"))
1213 raLst = ra.split(":");
1214 else
1215 raLst = ra.split(" ");
1216
1217 QStringList decLst;
1218 if (dec.contains(":"))
1219 decLst = dec.split(":");
1220 else
1221 decLst = dec.split(" ");
1222
1223 raRad = raLst.at(0).toFloat() + raLst.at(1).toFloat()/60.f + raLst.at(2).toFloat()/3600.f;
1224 decRad = qAbs(decLst.at(0).toFloat()) + decLst.at(1).toFloat()/60.f + decLst.at(2).toFloat()/3600.f;
1225 if (dec.startsWith("-")) decRad *= -1.f;
1226
1227 raRad *= M_PIf/12.f; // Convert from hours to rad
1228 decRad *= M_PIf/180.f; // Convert from deg to rad
1229 }
1230
1231 majorAxisSize /= 60.f; // Convert from arcmin to degrees
1232 minorAxisSize /= 60.f; // Convert from arcmin to degrees
1233
1234 // Warning: Hyades and LMC has visual magnitude less than 1.0 (0.5^m and 0.9^m)
1235 if (bMag <= 0.f) bMag = 99.f;
1236 if (vMag <= 0.f) vMag = 99.f;
1237 // TODO: The map could be sorted by probability (number of total objects). More common objects at start...
1238 static const QMap<QString, Nebula::NebulaType> oTypesMap = {
1239 { "G" , Nebula::NebGx },
1240 { "GX" , Nebula::NebGx },
1241 { "GC" , Nebula::NebGc },
1242 { "OC" , Nebula::NebOc },
1243 { "NB" , Nebula::NebN },
1244 { "PN" , Nebula::NebPn },
1245 { "DN" , Nebula::NebDn },
1246 { "RN" , Nebula::NebRn },
1247 { "C+N" , Nebula::NebCn },
1248 { "RNE" , Nebula::NebRn },
1249 { "HII" , Nebula::NebHII },
1250 { "SNR" , Nebula::NebSNR },
1251 { "BN" , Nebula::NebBn },
1252 { "EN" , Nebula::NebEn },
1253 { "SA" , Nebula::NebSA },
1254 { "SC" , Nebula::NebSC },
1255 { "CL" , Nebula::NebCl },
1256 { "IG" , Nebula::NebIGx },
1257 { "RG" , Nebula::NebRGx },
1258 { "AGX" , Nebula::NebAGx },
1259 { "QSO" , Nebula::NebQSO },
1260 { "ISM" , Nebula::NebISM },
1261 { "EMO" , Nebula::NebEMO },
1262 { "GNE" , Nebula::NebHII },
1263 { "RAD" , Nebula::NebISM },
1264 { "LIN" , Nebula::NebAGx },// LINER-type active galaxies
1265 { "BLL" , Nebula::NebBLL },
1266 { "BLA" , Nebula::NebBLA },
1267 { "MOC" , Nebula::NebMolCld },
1268 { "YSO" , Nebula::NebYSO },
1269 { "Q?" , Nebula::NebPossQSO },
1270 { "PN?" , Nebula::NebPossPN },
1271 { "*" , Nebula::NebStar},
1272 { "SFR" , Nebula::NebMolCld },
1273 { "IR" , Nebula::NebDn },
1274 { "**" , Nebula::NebStar},
1275 { "MUL" , Nebula::NebStar},
1276 { "PPN" , Nebula::NebPPN },
1277 { "GIG" , Nebula::NebIGx },
1278 { "OPC" , Nebula::NebOc },
1279 { "MGR" , Nebula::NebSA },
1280 { "IG2" , Nebula::NebIGx },
1281 { "IG3" , Nebula::NebIGx },
1282 { "SY*" , Nebula::NebSymbioticStar},
1283 { "PA*" , Nebula::NebPPN },
1284 { "CV*" , Nebula::NebStar},
1285 { "Y*?" , Nebula::NebYSO },
1286 { "CGB" , Nebula::NebISM },
1287 { "SNRG", Nebula::NebSNR },
1288 { "Y*O" , Nebula::NebYSO },
1289 { "SR*" , Nebula::NebStar},
1290 { "EM*" , Nebula::NebEmissionLineStar },
1291 { "AB*" , Nebula::NebStar },
1292 { "MI*" , Nebula::NebStar },
1293 { "MI?" , Nebula::NebStar },
1294 { "TT*" , Nebula::NebStar },
1295 { "WR*" , Nebula::NebStar },
1296 { "C*" , Nebula::NebEmissionLineStar },
1297 { "WD*" , Nebula::NebStar },
1298 { "EL*" , Nebula::NebStar },
1299 { "NL*" , Nebula::NebStar },
1300 { "NO*" , Nebula::NebStar },
1301 { "HS*" , Nebula::NebStar },
1302 { "LP*" , Nebula::NebStar },
1303 { "OH*" , Nebula::NebStar },
1304 { "S?R" , Nebula::NebStar },
1305 { "IR*" , Nebula::NebStar },
1306 { "POC" , Nebula::NebMolCld },
1307 { "PNB" , Nebula::NebPn },
1308 { "GXCL", Nebula::NebGxCl },
1309 { "AL*" , Nebula::NebStar },
1310 { "PR*" , Nebula::NebStar },
1311 { "RS*" , Nebula::NebStar },
1312 { "S*B" , Nebula::NebStar },
1313 { "SN?" , Nebula::NebSNC },
1314 { "SR?" , Nebula::NebSNRC },
1315 { "DNE" , Nebula::NebDn },
1316 { "RG*" , Nebula::NebStar },
1317 { "PSR" , Nebula::NebSNR },
1318 { "HH" , Nebula::NebISM },
1319 { "V*" , Nebula::NebStar },
1320 { "*IN" , Nebula::NebCn },
1321 { "SN*" , Nebula::NebStar },
1322 { "PA?" , Nebula::NebPPN },
1323 { "BUB" , Nebula::NebISM },
1324 { "CLG" , Nebula::NebGxCl },
1325 { "POG" , Nebula::NebPartOfGx },
1326 { "CGG" , Nebula::NebGxCl },
1327 { "SCG" , Nebula::NebGxCl },
1328 { "REG" , Nebula::NebRegion },
1329 { "?" , Nebula::NebUnknown }
1330 };
1331
1332 nType=oTypesMap.value(oType.toUpper(), Nebula::NebUnknown);
1333 if (nType == Nebula::NebUnknown)
1334 qDebug() << "Record with ID" << id <<"has unknown type of object:" << oType;
1335
1336 ++readOk;
1337
1338 dsoOutStream << id << raRad << decRad << bMag << vMag << static_cast<unsigned int>(nType) << mType << majorAxisSize << minorAxisSize
1339 << orientationAngle << z << zErr << plx << plxErr << dist << distErr << NGC << IC << M << C
1340 << B << Sh2 << VdB << RCW << LDN << LBN << Cr << Mel << PGC << UGC << Ced << Arp << VV << PK
1341 << PNG << SNRG << ACO << HCG << ESO << VdBH << DWB << Tr << St << Ru << VdBHa;
1342 }
1343 }
1344 dsoIn.close();
1345 dsoOut.flush();
1346 dsoOut.close();
1347 qDebug() << "Converted" << readOk << "/" << totalRecords << "DSO records";
1348 qDebug() << "[...] Please use 'gzip -nc catalog.pack > catalog.dat' to pack the catalog.";
1349 }
1350
loadDSOCatalog(const QString & filename)1351 bool NebulaMgr::loadDSOCatalog(const QString &filename)
1352 {
1353 QFile in(filename);
1354 if (!in.open(QIODevice::ReadOnly))
1355 return false;
1356
1357 qDebug() << "Loading DSO data ...";
1358
1359 // Let's begin use gzipped data
1360 QDataStream ins(StelUtils::uncompress(in.readAll()));
1361 ins.setVersion(QDataStream::Qt_5_2);
1362
1363 QString version = "", edition= "";
1364 int totalRecords=0;
1365 while (!ins.atEnd())
1366 {
1367 if (totalRecords==0) // Read the version of catalog
1368 {
1369 ins >> version >> edition;
1370 if (version.isEmpty())
1371 version = "3.1"; // The first version of extended edition of the catalog
1372 if (edition.isEmpty())
1373 edition = "unknown";
1374 qDebug() << "[...]" << QString("Stellarium DSO Catalog, version %1 (%2 edition)").arg(version).arg(edition);
1375 if (StelUtils::compareVersions(version, StellariumDSOCatalogVersion)!=0)
1376 {
1377 ++totalRecords;
1378 qDebug() << "WARNING: Mismatch of DSO catalog version (" << version << ")! The expected version is" << StellariumDSOCatalogVersion;
1379 qDebug() << " See section 5.5 of the User Guide and install the right version of the catalog!";
1380 QMessageBox::warning(Q_NULLPTR, q_("Attention!"), QString("%1. %2: %3 - %4: %5. %6").arg(q_("DSO catalog version mismatch"), q_("Found"), version, q_("Expected"), StellariumDSOCatalogVersion, q_("See Logfile for instructions.")), QMessageBox::Ok);
1381 break;
1382 }
1383 }
1384 else
1385 {
1386 // Create a new Nebula record
1387 NebulaP e = NebulaP(new Nebula);
1388 e->readDSO(ins);
1389
1390 dsoArray.append(e);
1391 nebGrid.insert(qSharedPointerCast<StelRegionObject>(e));
1392 if (e->DSO_nb!=0)
1393 dsoIndex.insert(e->DSO_nb, e);
1394 }
1395 ++totalRecords;
1396 }
1397 in.close();
1398 qDebug() << "Loaded" << --totalRecords << "DSO records";
1399 return true;
1400 }
1401
loadDSONames(const QString & filename)1402 bool NebulaMgr::loadDSONames(const QString &filename)
1403 {
1404 qDebug() << "Loading DSO name data ...";
1405 QFile dsoNameFile(filename);
1406 if (!dsoNameFile.open(QIODevice::ReadOnly | QIODevice::Text))
1407 {
1408 qWarning() << "DSO name data file" << QDir::toNativeSeparators(filename) << "not found.";
1409 return false;
1410 }
1411
1412 // Read the names of the deep-sky objects
1413 QString name, record, ref, cdes;
1414 QStringList nodata;
1415 nodata.clear();
1416 int totalRecords=0;
1417 int lineNumber=0;
1418 int readOk=0;
1419 unsigned int nb;
1420 NebulaP e;
1421 QRegularExpression commentRx("^(\\s*#.*|\\s*)$");
1422 while (!dsoNameFile.atEnd())
1423 {
1424 record = QString::fromUtf8(dsoNameFile.readLine());
1425 lineNumber++;
1426 if (commentRx.match(record).hasMatch())
1427 continue;
1428
1429 totalRecords++;
1430
1431 // bytes 1 - 5, designator for catalogue (prefix)
1432 ref = record.left(5).trimmed();
1433 // bytes 6 -20, identificator for object in the catalog
1434 cdes = record.mid(5, 15).trimmed().toUpper();
1435 // bytes 21-80, proper name of the object (translatable)
1436 name = record.mid(21).trimmed(); // Let gets the name with trimmed whitespaces
1437
1438 nb = cdes.toUInt();
1439
1440 static const QStringList catalogs = {
1441 "IC", "M", "C", "CR", "MEL", "B", "SH2", "VDB", "RCW", "LDN",
1442 "LBN", "NGC", "PGC", "UGC", "CED", "ARP", "VV", "PK", "PNG", "SNRG",
1443 "ACO", "HCG", "ESO", "VDBH", "DWB", "TR", "ST", "RU", "DBHA"};
1444
1445 switch (catalogs.indexOf(ref.toUpper()))
1446 {
1447 case 0:
1448 e = searchIC(nb);
1449 break;
1450 case 1:
1451 e = searchM(nb);
1452 break;
1453 case 2:
1454 e = searchC(nb);
1455 break;
1456 case 3:
1457 e = searchCr(nb);
1458 break;
1459 case 4:
1460 e = searchMel(nb);
1461 break;
1462 case 5:
1463 e = searchB(nb);
1464 break;
1465 case 6:
1466 e = searchSh2(nb);
1467 break;
1468 case 7:
1469 e = searchVdB(nb);
1470 break;
1471 case 8:
1472 e = searchRCW(nb);
1473 break;
1474 case 9:
1475 e = searchLDN(nb);
1476 break;
1477 case 10:
1478 e = searchLBN(nb);
1479 break;
1480 case 11:
1481 e = searchNGC(nb);
1482 break;
1483 case 12:
1484 e = searchPGC(nb);
1485 break;
1486 case 13:
1487 e = searchUGC(nb);
1488 break;
1489 case 14:
1490 e = searchCed(cdes);
1491 break;
1492 case 15:
1493 e = searchArp(nb);
1494 break;
1495 case 16:
1496 e = searchVV(nb);
1497 break;
1498 case 17:
1499 e = searchPK(cdes);
1500 break;
1501 case 18:
1502 e = searchPNG(cdes);
1503 break;
1504 case 19:
1505 e = searchSNRG(cdes);
1506 break;
1507 case 20:
1508 e = searchACO(cdes);
1509 break;
1510 case 21:
1511 e = searchHCG(cdes);
1512 break;
1513 case 22:
1514 e = searchESO(cdes);
1515 break;
1516 case 23:
1517 e = searchVdBH(cdes);
1518 break;
1519 case 24:
1520 e = searchDWB(nb);
1521 break;
1522 case 25:
1523 e = searchTr(nb);
1524 break;
1525 case 26:
1526 e = searchSt(nb);
1527 break;
1528 case 27:
1529 e = searchRu(nb);
1530 break;
1531 case 28:
1532 e = searchVdBHa(nb);
1533 break;
1534 default:
1535 e = searchDSO(nb);
1536 break;
1537 }
1538
1539 if (!e.isNull())
1540 {
1541 QRegularExpression transRx("_[(]\"(.*)\"[)](\\s*#.*)?"); // optional comments after name.
1542 QRegularExpressionMatch transMatch=transRx.match(name);
1543 if (transMatch.hasMatch())
1544 {
1545 QString propName = transMatch.captured(1).trimmed();
1546 QString currName = e->getEnglishName();
1547 if (currName.isEmpty())
1548 e->setProperName(propName);
1549 else if (currName!=propName)
1550 e->addNameAlias(propName);
1551 }
1552 readOk++;
1553 }
1554 else
1555 nodata.append(QString("%1 %2").arg(ref.trimmed(), cdes.trimmed()));
1556 }
1557 dsoNameFile.close();
1558 qDebug() << "Loaded" << readOk << "/" << totalRecords << "DSO name records successfully";
1559
1560 int err = nodata.size();
1561 if (err>0)
1562 qDebug() << "WARNING - No position data for" << err << "objects:" << nodata.join(", ");
1563
1564 return true;
1565 }
1566
loadDSOOutlines(const QString & filename)1567 bool NebulaMgr::loadDSOOutlines(const QString &filename)
1568 {
1569 qDebug() << "Loading DSO outline data ...";
1570 QFile dsoOutlineFile(filename);
1571 if (!dsoOutlineFile.open(QIODevice::ReadOnly | QIODevice::Text))
1572 {
1573 qWarning() << "DSO outline data file" << QDir::toNativeSeparators(filename) << "not found.";
1574 return false;
1575 }
1576
1577 double RA, DE;
1578 int i, readOk = 0;
1579 Vec3d XYZ;
1580 std::vector<Vec3d> *points = Q_NULLPTR;
1581 typedef QPair<double, double> coords;
1582 coords point, fpoint;
1583 QList<coords> outline;
1584 QString record, command, dso;
1585 NebulaP e;
1586 // Read the outlines data of the DSO
1587 QRegularExpression commentRx("^(\\s*#.*|\\s*)$");
1588 while (!dsoOutlineFile.atEnd())
1589 {
1590 record = QString::fromUtf8(dsoOutlineFile.readLine());
1591 if (commentRx.match(record).hasMatch())
1592 continue;
1593
1594 // bytes 1 - 8, RA
1595 RA = record.left(8).toDouble();
1596 // bytes 9 -18, DE
1597 DE = record.mid(9, 10).toDouble();
1598 // bytes 19-25, command
1599 command = record.mid(19, 7).trimmed();
1600 // bytes 26, designation of DSO
1601 dso = record.mid(26).trimmed();
1602
1603 RA*=M_PI/12.; // Convert from hours to rad
1604 DE*=M_PI/180.; // Convert from deg to rad
1605
1606 if (command.contains("start", Qt::CaseInsensitive))
1607 {
1608 outline.clear();
1609 e = search(dso);
1610 if (e.isNull()) // maybe this is inner number of DSO
1611 e = searchDSO(dso.toUInt());
1612
1613 point.first = RA;
1614 point.second = DE;
1615 outline.append(point);
1616 fpoint = point;
1617 }
1618
1619 if (command.contains("vertex", Qt::CaseInsensitive))
1620 {
1621 point.first = RA;
1622 point.second = DE;
1623 outline.append(point);
1624 }
1625
1626 if (command.contains("end", Qt::CaseInsensitive))
1627 {
1628 point.first = RA;
1629 point.second = DE;
1630 outline.append(point);
1631 outline.append(fpoint);
1632
1633 if (!e.isNull())
1634 {
1635 points = new std::vector<Vec3d>;
1636 for (i = 0; i < outline.size(); i++)
1637 {
1638 // Calc the Cartesian coord with RA and DE
1639 point = outline.at(i);
1640 StelUtils::spheToRect(point.first, point.second, XYZ);
1641 points->push_back(XYZ);
1642 }
1643
1644 e->outlineSegments.push_back(points);
1645 }
1646 readOk++;
1647 }
1648 }
1649 dsoOutlineFile.close();
1650 qDebug() << "Loaded" << readOk << "DSO outline records successfully";
1651 return true;
1652 }
1653
updateSkyCulture(const QString & skyCultureDir)1654 void NebulaMgr::updateSkyCulture(const QString& skyCultureDir)
1655 {
1656 QString namesFile = StelFileMgr::findFile("skycultures/" + skyCultureDir + "/dso_names.fab");
1657
1658 for (const auto& n : qAsConst(dsoArray))
1659 n->removeAllNames();
1660
1661 if (namesFile.isEmpty())
1662 {
1663 QString setName = "default";
1664 QString dsoNamesPath = StelFileMgr::findFile("nebulae/" + setName + "/names.dat");
1665 if (dsoNamesPath.isEmpty())
1666 {
1667 qWarning() << "ERROR while loading deep-sky names data set " << setName;
1668 return;
1669 }
1670 loadDSONames(dsoNamesPath);
1671 }
1672 else
1673 {
1674 // Open file
1675 QFile dsoNamesFile(namesFile);
1676 if (!dsoNamesFile.open(QIODevice::ReadOnly | QIODevice::Text))
1677 {
1678 qDebug() << "Cannot open file" << QDir::toNativeSeparators(namesFile);
1679 return;
1680 }
1681
1682 // Now parse the file
1683 // lines to ignore which start with a # or are empty
1684 QRegularExpression commentRx("^(\\s*#.*|\\s*)$");
1685
1686 // lines which look like records - we use the RE to extract the fields
1687 // which will be available in recMatch.capturedTexts()
1688 QRegularExpression recRx("^\\s*([\\w\\s]+)\\s*\\|[_]*[(]\"(.*)\"[)]\\s*([\\,\\d\\s]*)\\n");
1689
1690 QString record, dsoId, nativeName;
1691 int totalRecords=0;
1692 int readOk=0;
1693 int lineNumber=0;
1694 while (!dsoNamesFile.atEnd())
1695 {
1696 record = QString::fromUtf8(dsoNamesFile.readLine());
1697 lineNumber++;
1698
1699 // Skip comments
1700 if (commentRx.match(record).hasMatch())
1701 continue;
1702
1703 totalRecords++;
1704
1705 QRegularExpressionMatch recMatch=recRx.match(record);
1706 if (!recMatch.hasMatch())
1707 {
1708 qWarning() << "ERROR - cannot parse record at line" << lineNumber << "in native deep-sky object names file" << QDir::toNativeSeparators(namesFile);
1709 }
1710 else
1711 {
1712 dsoId = recMatch.captured(1).trimmed();
1713 nativeName = recMatch.captured(2).trimmed(); // Use translatable text
1714 NebulaP e = search(dsoId);
1715 QString currentName = e->getEnglishName();
1716 if (currentName.isEmpty()) // Set native name of DSO
1717 e->setProperName(nativeName);
1718 else if (currentName!=nativeName) // Add traditional (well-known?) name of DSO as alias
1719 e->addNameAlias(nativeName);
1720 readOk++;
1721 }
1722 }
1723 dsoNamesFile.close();
1724 qDebug() << "Loaded" << readOk << "/" << totalRecords << "native names of deep-sky objects";
1725 }
1726
1727 updateI18n();
1728 }
1729
updateI18n()1730 void NebulaMgr::updateI18n()
1731 {
1732 Nebula::buildTypeStringMap();
1733 const StelTranslator& trans = StelApp::getInstance().getLocaleMgr().getSkyTranslator();
1734 for (const auto& n : dsoArray)
1735 n->translateName(trans);
1736 }
1737
1738
1739 //! Return the matching Nebula object's pointer if exists or an "empty" StelObjectP
searchByNameI18n(const QString & nameI18n) const1740 StelObjectP NebulaMgr::searchByNameI18n(const QString& nameI18n) const
1741 {
1742 QString objw = nameI18n.toUpper();
1743
1744 // Search by common names
1745 for (const auto& n : dsoArray)
1746 {
1747 QString objwcap = n->nameI18.toUpper();
1748 if (objwcap==objw)
1749 return qSharedPointerCast<StelObject>(n);
1750 }
1751
1752 // Search by aliases of common names
1753 for (const auto& n : dsoArray)
1754 {
1755 for (auto objwcapa : n->nameI18Aliases)
1756 {
1757 if (objwcapa.toUpper()==objw)
1758 return qSharedPointerCast<StelObject>(n);
1759 }
1760 }
1761
1762 // Search by designation
1763 NebulaP n = searchByDesignation(objw);
1764 return qSharedPointerCast<StelObject>(n);
1765 }
1766
1767
1768 //! Return the matching Nebula object's pointer if exists or an "empty" StelObjectP
searchByName(const QString & name) const1769 StelObjectP NebulaMgr::searchByName(const QString& name) const
1770 {
1771 QString objw = name.toUpper();
1772
1773 // Search by common names
1774 for (const auto& n : dsoArray)
1775 {
1776 QString objwcap = n->englishName.toUpper();
1777 if (objwcap==objw)
1778 return qSharedPointerCast<StelObject>(n);
1779 }
1780
1781 if (getFlagAdditionalNames())
1782 {
1783 // Search by aliases of common names
1784 for (const auto& n : dsoArray)
1785 {
1786 for (auto objwcapa : n->englishAliases)
1787 {
1788 if (objwcapa.toUpper()==objw)
1789 return qSharedPointerCast<StelObject>(n);
1790 }
1791 }
1792 }
1793
1794 // Search by designation
1795 NebulaP n = searchByDesignation(objw);
1796 return qSharedPointerCast<StelObject>(n);
1797 }
1798
1799 //! Return the matching Nebula object's pointer if exists or Q_NULLPTR
1800 //! TODO Decide whether empty StelObjectP or Q_NULLPTR is the better return type and select the same for both.
searchByDesignation(const QString & designation) const1801 NebulaP NebulaMgr::searchByDesignation(const QString &designation) const
1802 {
1803 NebulaP n;
1804 QString uname = designation.toUpper();
1805 // If no match found, try search by catalog reference
1806 static QRegularExpression catNumRx("^(M|NGC|IC|C|B|VDB|RCW|LDN|LBN|CR|MEL|PGC|UGC|ARP|VV|DWB|TR|TRUMPLER|ST|STOCK|RU|RUPRECHT|VDB-HA)\\s*(\\d+)$");
1807 QRegularExpressionMatch catNumMatch=catNumRx.match(uname);
1808 if (catNumMatch.hasMatch())
1809 {
1810 QString cat = catNumMatch.captured(1);
1811 unsigned int num = catNumMatch.captured(2).toUInt();
1812 if (cat == "M") n = searchM(num);
1813 if (cat == "NGC") n = searchNGC(num);
1814 if (cat == "IC") n = searchIC(num);
1815 if (cat == "C") n = searchC(num);
1816 if (cat == "B") n = searchB(num);
1817 if (cat == "VDB-HA") n = searchVdBHa(num);
1818 if (cat == "VDB") n = searchVdB(num);
1819 if (cat == "RCW") n = searchRCW(num);
1820 if (cat == "LDN") n = searchLDN(num);
1821 if (cat == "LBN") n = searchLBN(num);
1822 if (cat == "CR") n = searchCr(num);
1823 if (cat == "MEL") n = searchMel(num);
1824 if (cat == "PGC") n = searchPGC(num);
1825 if (cat == "UGC") n = searchUGC(num);
1826 if (cat == "ARP") n = searchArp(num);
1827 if (cat == "VV") n = searchVV(num);
1828 if (cat == "DWB") n = searchDWB(num);
1829 if (cat == "TR" || cat == "TRUMPLER") n = searchTr(num);
1830 if (cat == "ST" || cat == "STOCK") n = searchSt(num);
1831 if (cat == "RU" || cat == "RUPRECHT") n = searchRu(num);
1832 }
1833 static QRegularExpression dCatNumRx("^(SH)\\s*\\d-\\s*(\\d+)$");
1834 QRegularExpressionMatch dCatNumMatch=dCatNumRx.match(uname);
1835 if (dCatNumMatch.hasMatch())
1836 {
1837 QString dcat = dCatNumMatch.captured(1);
1838 unsigned int dnum = dCatNumMatch.captured(2).toUInt();
1839
1840 if (dcat == "SH") n = searchSh2(dnum);
1841 }
1842 static QRegularExpression sCatNumRx("^(CED|PK|ACO|ABELL|HCG|ESO|VDBH)\\s*(.+)$");
1843 QRegularExpressionMatch sCatNumMatch=sCatNumRx.match(uname);
1844 if (sCatNumMatch.hasMatch())
1845 {
1846 QString cat = sCatNumMatch.captured(1);
1847 QString num = sCatNumMatch.captured(2).trimmed();
1848
1849 if (cat == "CED") n = searchCed(num);
1850 if (cat == "PK") n = searchPK(num);
1851 if (cat == "ACO" || cat == "ABELL") n = searchACO(num);
1852 if (cat == "HCG") n = searchHCG(num);
1853 if (cat == "ESO") n = searchESO(num);
1854 if (cat == "VDBH") n = searchVdBH(num);
1855 }
1856 static QRegularExpression gCatNumRx("^(PN|SNR)\\s*G(.+)$");
1857 QRegularExpressionMatch gCatNumMatch=gCatNumRx.match(uname);
1858 if (gCatNumMatch.hasMatch())
1859 {
1860 QString cat = gCatNumMatch.captured(1);
1861 QString num = gCatNumMatch.captured(2).trimmed();
1862
1863 if (cat == "PN") n = searchPNG(num);
1864 if (cat == "SNR") n = searchSNRG(num);
1865 }
1866
1867 return n;
1868 }
1869
1870 //! Find and return the list of at most maxNbItem objects auto-completing the passed object name
listMatchingObjects(const QString & objPrefix,int maxNbItem,bool useStartOfWords) const1871 QStringList NebulaMgr::listMatchingObjects(const QString& objPrefix, int maxNbItem, bool useStartOfWords) const
1872 {
1873 QStringList result;
1874 if (maxNbItem <= 0)
1875 return result;
1876
1877 QString objw = objPrefix.toUpper();
1878
1879 // Search by Messier objects number (possible formats are "M31" or "M 31")
1880 if (objw.size()>=1 && objw.left(1)=="M" && objw.left(3)!="MEL")
1881 {
1882 for (const auto& n : dsoArray)
1883 {
1884 if (n->M_nb==0) continue;
1885 QString constw = QString("M%1").arg(n->M_nb);
1886 QString constws = constw.mid(0, objw.size());
1887 if (constws.toUpper()==objw)
1888 {
1889 result << constws;
1890 continue; // Prevent adding both forms for name
1891 }
1892 constw = QString("M %1").arg(n->M_nb);
1893 constws = constw.mid(0, objw.size());
1894 if (constws.toUpper()==objw)
1895 result << constw;
1896 }
1897 }
1898
1899 // Search by Melotte objects number (possible formats are "Mel31" or "Mel 31")
1900 if (objw.size()>=1 && objw.left(3)=="MEL")
1901 {
1902 for (const auto& n : dsoArray)
1903 {
1904 if (n->Mel_nb==0) continue;
1905 QString constw = QString("Mel%1").arg(n->Mel_nb);
1906 QString constws = constw.mid(0, objw.size());
1907 QString constws2 = QString("Melotte%1").arg(n->Mel_nb).mid(0, objw.size());
1908 if (constws.toUpper()==objw || constws2.toUpper()==objw)
1909 {
1910 result << constws;
1911 continue; // Prevent adding both forms for name
1912 }
1913 constw = QString("Mel %1").arg(n->Mel_nb);
1914 constws = constw.mid(0, objw.size());
1915 constws2 = QString("Melotte %1").arg(n->Mel_nb).mid(0, objw.size());
1916 if (constws.toUpper()==objw || constws2.toUpper()==objw)
1917 result << constw;
1918 }
1919 }
1920
1921 // Search by IC objects number (possible formats are "IC466" or "IC 466")
1922 if (objw.size()>=1 && objw.left(2)=="IC")
1923 {
1924 for (const auto& n : dsoArray)
1925 {
1926 if (n->IC_nb==0) continue;
1927 QString constw = QString("IC%1").arg(n->IC_nb);
1928 QString constws = constw.mid(0, objw.size());
1929 if (constws.toUpper()==objw)
1930 {
1931 result << constws;
1932 continue; // Prevent adding both forms for name
1933 }
1934 constw = QString("IC %1").arg(n->IC_nb);
1935 constws = constw.mid(0, objw.size());
1936 if (constws.toUpper()==objw)
1937 result << constw;
1938 }
1939 }
1940
1941 // Search by NGC numbers (possible formats are "NGC31" or "NGC 31")
1942 for (const auto& n : dsoArray)
1943 {
1944 if (n->NGC_nb==0) continue;
1945 QString constw = QString("NGC%1").arg(n->NGC_nb);
1946 QString constws = constw.mid(0, objw.size());
1947 if (constws.toUpper()==objw)
1948 {
1949 result << constws;
1950 continue;
1951 }
1952 constw = QString("NGC %1").arg(n->NGC_nb);
1953 constws = constw.mid(0, objw.size());
1954 if (constws.toUpper()==objw)
1955 result << constw;
1956 }
1957
1958 // Search by PGC object numbers (possible formats are "PGC31" or "PGC 31")
1959 if (objw.size()>=1 && objw.left(3)=="PGC")
1960 {
1961 for (const auto& n : dsoArray)
1962 {
1963 if (n->PGC_nb==0) continue;
1964 QString constw = QString("PGC%1").arg(n->PGC_nb);
1965 QString constws = constw.mid(0, objw.size());
1966 if (constws.toUpper()==objw)
1967 {
1968 result << constws; // Prevent adding both forms for name
1969 continue;
1970 }
1971 constw = QString("PGC %1").arg(n->PGC_nb);
1972 constws = constw.mid(0, objw.size());
1973 if (constws.toUpper()==objw)
1974 result << constw;
1975 }
1976 }
1977
1978 // Search by UGC object numbers (possible formats are "UGC31" or "UGC 31")
1979 if (objw.size()>=1 && objw.left(3)=="UGC")
1980 {
1981 for (const auto& n : dsoArray)
1982 {
1983 if (n->UGC_nb==0) continue;
1984 QString constw = QString("UGC%1").arg(n->UGC_nb);
1985 QString constws = constw.mid(0, objw.size());
1986 if (constws.toUpper()==objw)
1987 {
1988 result << constws;
1989 continue; // Prevent adding both forms for name
1990 }
1991 constw = QString("UGC %1").arg(n->UGC_nb);
1992 constws = constw.mid(0, objw.size());
1993 if (constws.toUpper()==objw)
1994 result << constw;
1995 }
1996 }
1997
1998 // Search by Caldwell objects number (possible formats are "C31" or "C 31")
1999 if (objw.size()>=1 && objw.left(1)=="C" && objw.left(2)!="CR" && objw.left(2)!="CE")
2000 {
2001 for (const auto& n : dsoArray)
2002 {
2003 if (n->C_nb==0) continue;
2004 QString constw = QString("C%1").arg(n->C_nb);
2005 QString constws = constw.mid(0, objw.size());
2006 if (constws.toUpper()==objw)
2007 {
2008 result << constws;
2009 continue; // Prevent adding both forms for name
2010 }
2011 constw = QString("C %1").arg(n->C_nb);
2012 constws = constw.mid(0, objw.size());
2013 if (constws.toUpper()==objw)
2014 result << constw;
2015 }
2016 }
2017
2018 // Search by Collinder objects number (possible formats are "Cr31" or "Cr 31")
2019 if (objw.size()>=1 && (objw.left(2)=="CR" || objw.left(9)=="COLLINDER"))
2020 {
2021 for (const auto& n : dsoArray)
2022 {
2023 if (n->Cr_nb==0) continue;
2024 QString constw = QString("Cr%1").arg(n->Cr_nb);
2025 QString constws = constw.mid(0, objw.size());
2026 QString constws2 = QString("Collinder%1").arg(n->Cr_nb).mid(0, objw.size());
2027 if (constws.toUpper()==objw || constws2.toUpper()==objw)
2028 {
2029 result << constws;
2030 continue; // Prevent adding both forms for name
2031 }
2032 constw = QString("Cr %1").arg(n->Cr_nb);
2033 constws = constw.mid(0, objw.size());
2034 constws2 = QString("Collinder %1").arg(n->Cr_nb).mid(0, objw.size());
2035 if (constws.toUpper()==objw || constws2.toUpper()==objw)
2036 result << constw;
2037 }
2038 }
2039
2040 // Search by Ced objects number (possible formats are "Ced31" or "Ced 31")
2041 if (objw.size()>=1 && objw.left(3)=="CED")
2042 {
2043 for (const auto& n : dsoArray)
2044 {
2045 if (n->Ced_nb.isEmpty()) continue;
2046 QString constw = QString("Ced%1").arg(n->Ced_nb.trimmed());
2047 QString constws = constw.mid(0, objw.size());
2048 if (constws.toUpper()==objw)
2049 {
2050 result << constws;
2051 continue; // Prevent adding both forms for name
2052 }
2053 constw = QString("Ced %1").arg(n->Ced_nb.trimmed());
2054 constws = constw.mid(0, objw.size());
2055 if (constws.toUpper()==objw)
2056 result << constw;
2057 }
2058 }
2059
2060 // Search by Barnard objects number (possible formats are "B31" or "B 31")
2061 if (objw.size()>=1 && objw.left(1)=="B")
2062 {
2063 for (const auto& n : dsoArray)
2064 {
2065 if (n->B_nb==0) continue;
2066 QString constw = QString("B%1").arg(n->B_nb);
2067 QString constws = constw.mid(0, objw.size());
2068 if (constws.toUpper()==objw)
2069 {
2070 result << constws;
2071 continue; // Prevent adding both forms for name
2072 }
2073 constw = QString("B %1").arg(n->B_nb);
2074 constws = constw.mid(0, objw.size());
2075 if (constws.toUpper()==objw)
2076 result << constw;
2077 }
2078 }
2079
2080 // Search by Sharpless objects number (possible formats are "Sh2-31" or "Sh 2-31")
2081 if (objw.size()>=1 && objw.left(2)=="SH")
2082 {
2083 for (const auto& n : dsoArray)
2084 {
2085 if (n->Sh2_nb==0) continue;
2086 QString constw = QString("SH2-%1").arg(n->Sh2_nb);
2087 QString constws = constw.mid(0, objw.size());
2088 if (constws.toUpper()==objw)
2089 {
2090 result << constws;
2091 continue; // Prevent adding both forms for name
2092 }
2093 constw = QString("SH 2-%1").arg(n->Sh2_nb);
2094 constws = constw.mid(0, objw.size());
2095 if (constws.toUpper()==objw)
2096 result << constw;
2097 }
2098 }
2099
2100 // Search by van den Bergh objects number (possible formats are "vdB31" or "vdB 31")
2101 if (objw.size()>=1 && objw.left(3)=="VDB" && objw.left(6)!="VDB-HA" && objw.left(4)!="VDBH")
2102 {
2103 for (const auto& n : dsoArray)
2104 {
2105 if (n->VdB_nb==0) continue;
2106 QString constw = QString("vdB%1").arg(n->VdB_nb);
2107 QString constws = constw.mid(0, objw.size());
2108 if (constws.toUpper()==objw)
2109 {
2110 result << constws;
2111 continue; // Prevent adding both forms for name
2112 }
2113 constw = QString("vdB %1").arg(n->VdB_nb);
2114 constws = constw.mid(0, objw.size());
2115 if (constws.toUpper()==objw)
2116 result << constw;
2117 }
2118 }
2119
2120 // Search by RCW objects number (possible formats are "RCW31" or "RCW 31")
2121 if (objw.size()>=1 && objw.left(3)=="RCW")
2122 {
2123 for (const auto& n : dsoArray)
2124 {
2125 if (n->RCW_nb==0) continue;
2126 QString constw = QString("RCW%1").arg(n->RCW_nb);
2127 QString constws = constw.mid(0, objw.size());
2128 if (constws.toUpper()==objw)
2129 {
2130 result << constws;
2131 continue; // Prevent adding both forms for name
2132 }
2133 constw = QString("RCW %1").arg(n->RCW_nb);
2134 constws = constw.mid(0, objw.size());
2135 if (constws.toUpper()==objw)
2136 result << constw;
2137 }
2138 }
2139
2140 // Search by LDN objects number (possible formats are "LDN31" or "LDN 31")
2141 if (objw.size()>=1 && objw.left(3)=="LDN")
2142 {
2143 for (const auto& n : dsoArray)
2144 {
2145 if (n->LDN_nb==0) continue;
2146 QString constw = QString("LDN%1").arg(n->LDN_nb);
2147 QString constws = constw.mid(0, objw.size());
2148 if (constws.toUpper()==objw)
2149 {
2150 result << constws;
2151 continue; // Prevent adding both forms for name
2152 }
2153 constw = QString("LDN %1").arg(n->LDN_nb);
2154 constws = constw.mid(0, objw.size());
2155 if (constws.toUpper()==objw)
2156 result << constw;
2157 }
2158 }
2159
2160 // Search by LBN objects number (possible formats are "LBN31" or "LBN 31")
2161 if (objw.size()>=1 && objw.left(3)=="LBN")
2162 {
2163 for (const auto& n : dsoArray)
2164 {
2165 if (n->LBN_nb==0) continue;
2166 QString constw = QString("LBN%1").arg(n->LBN_nb);
2167 QString constws = constw.mid(0, objw.size());
2168 if (constws.toUpper()==objw)
2169 {
2170 result << constws;
2171 continue; // Prevent adding both forms for name
2172 }
2173 constw = QString("LBN %1").arg(n->LBN_nb);
2174 constws = constw.mid(0, objw.size());
2175 if (constws.toUpper()==objw)
2176 result << constw;
2177 }
2178 }
2179
2180 // Search by Arp objects number
2181 if (objw.size()>=1 && objw.left(3)=="ARP")
2182 {
2183 for (const auto& n : dsoArray)
2184 {
2185 if (n->Arp_nb==0) continue;
2186 QString constw = QString("Arp%1").arg(n->Arp_nb);
2187 QString constws = constw.mid(0, objw.size());
2188 if (constws.toUpper()==objw)
2189 {
2190 result << constws;
2191 continue; // Prevent adding both forms for name
2192 }
2193 constw = QString("Arp %1").arg(n->Arp_nb);
2194 constws = constw.mid(0, objw.size());
2195 if (constws.toUpper()==objw)
2196 result << constw;
2197 }
2198 }
2199
2200 // Search by VV objects number
2201 if (objw.size()>=1 && objw.left(2)=="VV")
2202 {
2203 for (const auto& n : dsoArray)
2204 {
2205 if (n->VV_nb==0) continue;
2206 QString constw = QString("VV%1").arg(n->VV_nb);
2207 QString constws = constw.mid(0, objw.size());
2208 if (constws.toUpper()==objw)
2209 {
2210 result << constws;
2211 continue; // Prevent adding both forms for name
2212 }
2213 constw = QString("VV %1").arg(n->VV_nb);
2214 constws = constw.mid(0, objw.size());
2215 if (constws.toUpper()==objw)
2216 result << constw;
2217 }
2218 }
2219
2220 // Search by PK objects number
2221 if (objw.size()>=1 && objw.left(2)=="PK")
2222 {
2223 for (const auto& n : dsoArray)
2224 {
2225 if (n->PK_nb.isEmpty()) continue;
2226 QString constw = QString("PK%1").arg(n->PK_nb.trimmed());
2227 QString constws = constw.mid(0, objw.size());
2228 if (constws.toUpper()==objw)
2229 {
2230 result << constws;
2231 continue; // Prevent adding both forms for name
2232 }
2233 constw = QString("PK %1").arg(n->PK_nb.trimmed());
2234 constws = constw.mid(0, objw.size());
2235 if (constws.toUpper()==objw)
2236 result << constw;
2237 }
2238 }
2239
2240 // Search by PN G objects number
2241 if (objw.size()>=1 && objw.left(2)=="PN")
2242 {
2243 for (const auto& n : dsoArray)
2244 {
2245 if (n->PNG_nb.isEmpty()) continue;
2246 QString constw = QString("PNG%1").arg(n->PNG_nb.trimmed());
2247 QString constws = constw.mid(0, objw.size());
2248 if (constws.toUpper()==objw)
2249 {
2250 result << constws;
2251 continue; // Prevent adding both forms for name
2252 }
2253 constw = QString("PN G%1").arg(n->PNG_nb.trimmed());
2254 constws = constw.mid(0, objw.size());
2255 if (constws.toUpper()==objw)
2256 result << constw;
2257 }
2258 }
2259
2260 // Search by SNR G objects number
2261 if (objw.size()>=1 && objw.left(3)=="SNR")
2262 {
2263 for (const auto& n : dsoArray)
2264 {
2265 if (n->SNRG_nb.isEmpty()) continue;
2266 QString constw = QString("SNRG%1").arg(n->SNRG_nb.trimmed());
2267 QString constws = constw.mid(0, objw.size());
2268 if (constws.toUpper()==objw)
2269 {
2270 result << constws;
2271 continue; // Prevent adding both forms for name
2272 }
2273 constw = QString("SNR G%1").arg(n->SNRG_nb.trimmed());
2274 constws = constw.mid(0, objw.size());
2275 if (constws.toUpper()==objw)
2276 result << constw;
2277 }
2278 }
2279
2280 // Search by ACO (Abell) objects number
2281 if (objw.size()>=1 && (objw.left(5)=="ABELL" || objw.left(3)=="ACO"))
2282 {
2283 for (const auto& n : dsoArray)
2284 {
2285 if (n->ACO_nb.isEmpty()) continue;
2286 QString constw = QString("Abell%1").arg(n->ACO_nb.trimmed());
2287 QString constws = constw.mid(0, objw.size());
2288 QString constws2 = QString("ACO%1").arg(n->ACO_nb.trimmed()).mid(0, objw.size());
2289 if (constws.toUpper()==objw || constws2.toUpper()==objw)
2290 {
2291 result << constws;
2292 continue; // Prevent adding both forms for name
2293 }
2294 constw = QString("Abell %1").arg(n->ACO_nb.trimmed());
2295 constws = constw.mid(0, objw.size());
2296 constws2 = QString("ACO %1").arg(n->ACO_nb.trimmed()).mid(0, objw.size());
2297 if (constws.toUpper()==objw || constws2.toUpper()==objw)
2298 result << constw;
2299 }
2300 }
2301
2302 // Search by HCG objects number
2303 if (objw.size()>=1 && objw.left(3)=="HCG")
2304 {
2305 for (const auto& n : dsoArray)
2306 {
2307 if (n->HCG_nb.isEmpty()) continue;
2308 QString constw = QString("HCG%1").arg(n->HCG_nb.trimmed());
2309 QString constws = constw.mid(0, objw.size());
2310 if (constws.toUpper()==objw)
2311 {
2312 result << constws;
2313 continue; // Prevent adding both forms for name
2314 }
2315 constw = QString("HCG %1").arg(n->HCG_nb.trimmed());
2316 constws = constw.mid(0, objw.size());
2317 if (constws.toUpper()==objw)
2318 result << constw;
2319 }
2320 }
2321
2322 // Search by ESO objects number
2323 if (objw.size()>=1 && objw.left(3)=="ESO")
2324 {
2325 for (const auto& n : dsoArray)
2326 {
2327 if (n->ESO_nb.isEmpty()) continue;
2328 QString constw = QString("ESO%1").arg(n->ESO_nb.trimmed());
2329 QString constws = constw.mid(0, objw.size());
2330 if (constws.toUpper()==objw)
2331 {
2332 result << constws;
2333 continue; // Prevent adding both forms for name
2334 }
2335 constw = QString("ESO %1").arg(n->ESO_nb.trimmed());
2336 constws = constw.mid(0, objw.size());
2337 if (constws.toUpper()==objw)
2338 result << constw;
2339 }
2340 }
2341
2342 // Search by VdBH objects number
2343 if (objw.size()>=1 && objw.left(4)=="VDBH")
2344 {
2345 for (const auto& n : dsoArray)
2346 {
2347 if (n->VdBH_nb.isEmpty()) continue;
2348 QString constw = QString("vdBH%1").arg(n->VdBH_nb.trimmed());
2349 QString constws = constw.mid(0, objw.size());
2350 if (constws.toUpper()==objw)
2351 {
2352 result << constws;
2353 continue; // Prevent adding both forms for name
2354 }
2355 constw = QString("vdBH %1").arg(n->VdBH_nb.trimmed());
2356 constws = constw.mid(0, objw.size());
2357 if (constws.toUpper()==objw)
2358 result << constw;
2359 }
2360 }
2361
2362 // Search by DWB objects number
2363 if (objw.size()>=1 && objw.left(3)=="DWB")
2364 {
2365 for (const auto& n : dsoArray)
2366 {
2367 if (n->DWB_nb==0) continue;
2368 QString constw = QString("DWB%1").arg(n->DWB_nb);
2369 QString constws = constw.mid(0, objw.size());
2370 if (constws.toUpper()==objw)
2371 {
2372 result << constws;
2373 continue; // Prevent adding both forms for name
2374 }
2375 constw = QString("DWB %1").arg(n->DWB_nb);
2376 constws = constw.mid(0, objw.size());
2377 if (constws.toUpper()==objw)
2378 result << constw;
2379 }
2380 }
2381
2382 // Search by Tr (Trumpler) objects number
2383 if (objw.size()>=1 && (objw.left(8)=="TRUMPLER" || objw.left(2)=="TR"))
2384 {
2385 for (const auto& n : dsoArray)
2386 {
2387 if (n->Tr_nb==0) continue;
2388 QString constw = QString("Tr%1").arg(n->Tr_nb);
2389 QString constws = constw.mid(0, objw.size());
2390 QString constws2 = QString("Trumpler%1").arg(n->Tr_nb).mid(0, objw.size());
2391 if (constws.toUpper()==objw || constws2.toUpper()==objw)
2392 {
2393 result << constws;
2394 continue; // Prevent adding both forms for name
2395 }
2396 constw = QString("Tr %1").arg(n->Tr_nb);
2397 constws = constw.mid(0, objw.size());
2398 constws2 = QString("Trumpler %1").arg(n->Tr_nb).mid(0, objw.size());
2399 if (constws.toUpper()==objw || constws2.toUpper()==objw)
2400 result << constw;
2401 }
2402 }
2403
2404 // Search by St (Stock) objects number
2405 if (objw.size()>=1 && (objw.left(5)=="STOCK" || objw.left(2)=="ST"))
2406 {
2407 for (const auto& n : dsoArray)
2408 {
2409 if (n->St_nb==0) continue;
2410 QString constw = QString("St%1").arg(n->St_nb);
2411 QString constws = constw.mid(0, objw.size());
2412 QString constws2 = QString("Stock%1").arg(n->St_nb).mid(0, objw.size());
2413 if (constws.toUpper()==objw || constws2.toUpper()==objw)
2414 {
2415 result << constws;
2416 continue; // Prevent adding both forms for name
2417 }
2418 constw = QString("St %1").arg(n->St_nb);
2419 constws = constw.mid(0, objw.size());
2420 constws2 = QString("Stock %1").arg(n->St_nb).mid(0, objw.size());
2421 if (constws.toUpper()==objw || constws2.toUpper()==objw)
2422 result << constw;
2423 }
2424 }
2425
2426 // Search by Ru (Ruprecht) objects number
2427 if (objw.size()>=1 && (objw.left(8)=="RUPRECHT" || objw.left(2)=="RU"))
2428 {
2429 for (const auto& n : dsoArray)
2430 {
2431 if (n->Ru_nb==0) continue;
2432 QString constw = QString("Ru%1").arg(n->Ru_nb);
2433 QString constws = constw.mid(0, objw.size());
2434 QString constws2 = QString("Ruprecht%1").arg(n->Ru_nb).mid(0, objw.size());
2435 if (constws.toUpper()==objw || constws2.toUpper()==objw)
2436 {
2437 result << constws;
2438 continue; // Prevent adding both forms for name
2439 }
2440 constw = QString("Ru %1").arg(n->Ru_nb);
2441 constws = constw.mid(0, objw.size());
2442 constws2 = QString("Ruprecht %1").arg(n->Ru_nb).mid(0, objw.size());
2443 if (constws.toUpper()==objw || constws2.toUpper()==objw)
2444 result << constw;
2445 }
2446 }
2447
2448 // Search by van den Bergh-Hagen Catalogue objects number
2449 if (objw.size()>=1 && objw.left(6)=="VDB-HA")
2450 {
2451 for (const auto& n : dsoArray)
2452 {
2453 if (n->VdBHa_nb==0) continue;
2454 QString constw = QString("vdB-Ha%1").arg(n->VdBHa_nb);
2455 QString constws = constw.mid(0, objw.size());
2456 if (constws.toUpper()==objw)
2457 {
2458 result << constws;
2459 continue; // Prevent adding both forms for name
2460 }
2461 constw = QString("vdB-Ha %1").arg(n->VdBHa_nb);
2462 constws = constw.mid(0, objw.size());
2463 if (constws.toUpper()==objw)
2464 result << constw;
2465 }
2466 }
2467
2468 // Search by common names and aliases
2469 QStringList names;
2470 for (const auto& n : dsoArray)
2471 {
2472 names.append(n->nameI18);
2473 names.append(n->englishName);
2474 if (getFlagAdditionalNames())
2475 {
2476 QStringList nameList = n->nameI18Aliases;
2477 for (const auto &name : nameList)
2478 names.append(name);
2479
2480 nameList = n->englishAliases;
2481 for (const auto &name : nameList)
2482 names.append(name);
2483 }
2484 }
2485
2486 QString fullMatch = "";
2487 for (const auto& name : qAsConst(names))
2488 {
2489 if (!matchObjectName(name, objPrefix, useStartOfWords))
2490 continue;
2491
2492 if (name==objPrefix)
2493 fullMatch = name;
2494 else
2495 result.append(name);
2496 }
2497
2498 result.sort();
2499 if (!fullMatch.isEmpty())
2500 result.prepend(fullMatch);
2501
2502 if (result.size() > maxNbItem)
2503 result.erase(result.begin() + maxNbItem, result.end());
2504
2505 return result;
2506 }
2507
listAllObjects(bool inEnglish) const2508 QStringList NebulaMgr::listAllObjects(bool inEnglish) const
2509 {
2510 QStringList result;
2511 for (const auto& n : dsoArray)
2512 {
2513 if (!n->getEnglishName().isEmpty())
2514 {
2515 if (inEnglish)
2516 result << n->getEnglishName();
2517 else
2518 result << n->getNameI18n();
2519 }
2520 }
2521 return result;
2522 }
2523
listAllObjectsByType(const QString & objType,bool inEnglish) const2524 QStringList NebulaMgr::listAllObjectsByType(const QString &objType, bool inEnglish) const
2525 {
2526 QStringList result;
2527 int type = objType.toInt();
2528 switch (type)
2529 {
2530 case 0: // Bright galaxies?
2531 for (const auto& n : dsoArray)
2532 {
2533 if (n->nType==type && qMin(n->vMag, n->bMag)<=10.f)
2534 {
2535 if (!n->getEnglishName().isEmpty())
2536 {
2537 if (inEnglish)
2538 result << n->getEnglishName();
2539 else
2540 result << n->getNameI18n();
2541 }
2542 else
2543 result << n->getDSODesignationWIC();
2544 }
2545 }
2546 break;
2547 case 100: // Messier Catalogue?
2548 for (const auto& n : getDeepSkyObjectsByType(objType))
2549 result << QString("M%1").arg(n->M_nb);
2550 break;
2551 case 101: // Caldwell Catalogue?
2552 for (const auto& n : getDeepSkyObjectsByType(objType))
2553 result << QString("C%1").arg(n->C_nb);
2554 break;
2555 case 102: // Barnard Catalogue?
2556 for (const auto& n : getDeepSkyObjectsByType(objType))
2557 result << QString("B %1").arg(n->B_nb);
2558 break;
2559 case 103: // Sharpless Catalogue?
2560 for (const auto& n : getDeepSkyObjectsByType(objType))
2561 result << QString("SH 2-%1").arg(n->Sh2_nb);
2562 break;
2563 case 104: // van den Bergh Catalogue
2564 for (const auto& n : getDeepSkyObjectsByType(objType))
2565 result << QString("vdB %1").arg(n->VdB_nb);
2566 break;
2567 case 105: // RCW Catalogue
2568 for (const auto& n : getDeepSkyObjectsByType(objType))
2569 result << QString("RCW %1").arg(n->RCW_nb);
2570 break;
2571 case 106: // Collinder Catalogue
2572 for (const auto& n : getDeepSkyObjectsByType(objType))
2573 result << QString("Cr %1").arg(n->Cr_nb);
2574 break;
2575 case 107: // Melotte Catalogue
2576 for (const auto& n : getDeepSkyObjectsByType(objType))
2577 result << QString("Mel %1").arg(n->Mel_nb);
2578 break;
2579 case 108: // New General Catalogue
2580 for (const auto& n : getDeepSkyObjectsByType(objType))
2581 result << QString("NGC %1").arg(n->NGC_nb);
2582 break;
2583 case 109: // Index Catalogue
2584 for (const auto& n : getDeepSkyObjectsByType(objType))
2585 result << QString("IC %1").arg(n->IC_nb);
2586 break;
2587 case 110: // Lynds' Catalogue of Bright Nebulae
2588 for (const auto& n : getDeepSkyObjectsByType(objType))
2589 result << QString("LBN %1").arg(n->LBN_nb);
2590 break;
2591 case 111: // Lynds' Catalogue of Dark Nebulae
2592 for (const auto& n : getDeepSkyObjectsByType(objType))
2593 result << QString("LDN %1").arg(n->LDN_nb);
2594 break;
2595 case 114: // Cederblad Catalog
2596 for (const auto& n : getDeepSkyObjectsByType(objType))
2597 result << QString("Ced %1").arg(n->Ced_nb);
2598 break;
2599 case 115: // Atlas of Peculiar Galaxies (Arp)
2600 for (const auto& n : getDeepSkyObjectsByType(objType))
2601 result << QString("Arp %1").arg(n->Arp_nb);
2602 break;
2603 case 116: // The Catalogue of Interacting Galaxies by Vorontsov-Velyaminov (VV)
2604 for (const auto& n : getDeepSkyObjectsByType(objType))
2605 result << QString("VV %1").arg(n->VV_nb);
2606 break;
2607 case 117: // Catalogue of Galactic Planetary Nebulae (PK)
2608 for (const auto& n : getDeepSkyObjectsByType(objType))
2609 result << QString("PK %1").arg(n->PK_nb);
2610 break;
2611 case 118: // Strasbourg-ESO Catalogue of Galactic Planetary Nebulae by Acker et. al. (PN G)
2612 for (const auto& n : getDeepSkyObjectsByType(objType))
2613 result << QString("PN G%1").arg(n->PNG_nb);
2614 break;
2615 case 119: // A catalogue of Galactic supernova remnants by Green (SNR G)
2616 for (const auto& n : getDeepSkyObjectsByType(objType))
2617 result << QString("SNR G%1").arg(n->SNRG_nb);
2618 break;
2619 case 120: // A Catalog of Rich Clusters of Galaxies by Abell et. al. (Abell (ACO))
2620 for (const auto& n : getDeepSkyObjectsByType(objType))
2621 result << QString("Abell %1").arg(n->ACO_nb);
2622 break;
2623 case 121: // Hickson Compact Group by Hickson et. al. (HCG)
2624 for (const auto& n : getDeepSkyObjectsByType(objType))
2625 result << QString("HCG %1").arg(n->HCG_nb);
2626 break;
2627 case 122: // ESO/Uppsala Survey of the ESO(B) Atlas (ESO)
2628 for (const auto& n : getDeepSkyObjectsByType(objType))
2629 result << QString("ESO %1").arg(n->ESO_nb);
2630 break;
2631 case 123: // Catalogue of southern stars embedded in nebulosity (vdBH)
2632 for (const auto& n : getDeepSkyObjectsByType(objType))
2633 result << QString("vdBH %1").arg(n->VdBH_nb);
2634 break;
2635 case 124: // Catalogue and distances of optically visible H II regions (DWB)
2636 for (const auto& n : getDeepSkyObjectsByType(objType))
2637 result << QString("DWB %1").arg(n->DWB_nb);
2638 break;
2639 case 125: // Trumpler Catalogue (Tr)
2640 for (const auto& n : getDeepSkyObjectsByType(objType))
2641 result << QString("Tr %1").arg(n->Tr_nb);
2642 break;
2643 case 126: // Stock Catalogue (St)
2644 for (const auto& n : getDeepSkyObjectsByType(objType))
2645 result << QString("St %1").arg(n->St_nb);
2646 break;
2647 case 127: // Ruprecht Catalogue (Ru)
2648 for (const auto& n : getDeepSkyObjectsByType(objType))
2649 result << QString("Ru %1").arg(n->Ru_nb);
2650 break;
2651 case 128: // van den Bergh-Hagen Catalogue (VdB-Ha)
2652 for (const auto& n : getDeepSkyObjectsByType(objType))
2653 result << QString("vdB-Ha %1").arg(n->VdBHa_nb);
2654 break;
2655 case 150: // Dwarf galaxies [see NebulaList.hpp]
2656 {
2657 for (unsigned int i = 0; i < sizeof(DWARF_GALAXIES) / sizeof(DWARF_GALAXIES[0]); i++)
2658 result << QString("PGC %1").arg(DWARF_GALAXIES[i]);
2659 break;
2660 }
2661 case 151: // Herschel 400 Catalogue [see NebulaList.hpp]
2662 {
2663 for (unsigned int i = 0; i < sizeof(H400_LIST) / sizeof(H400_LIST[0]); i++)
2664 result << QString("NGC %1").arg(H400_LIST[i]);
2665 break;
2666 }
2667 case 152: // Jack Bennett's deep sky catalogue [see NebulaList.hpp]
2668 {
2669 for (unsigned int i = 0; i < sizeof(BENNETT_LIST) / sizeof(BENNETT_LIST[0]); i++)
2670 result << QString("NGC %1").arg(BENNETT_LIST[i]);
2671 result << "Mel 105" << "IC 1459";
2672 break;
2673 }
2674 case 153: // James Dunlop's deep sky catalogue [see NebulaList.hpp]
2675 {
2676 for (unsigned int i = 0; i < sizeof(DUNLOP_LIST) / sizeof(DUNLOP_LIST[0]); i++)
2677 result << QString("NGC %1").arg(DUNLOP_LIST[i]);
2678 break;
2679 }
2680 default:
2681 {
2682 for (const auto& n : dsoArray)
2683 {
2684 if (n->nType==type)
2685 {
2686 if (!n->getEnglishName().isEmpty())
2687 {
2688 if (inEnglish)
2689 result << n->getEnglishName();
2690 else
2691 result << n->getNameI18n();
2692 }
2693 else
2694 result << n->getDSODesignationWIC();
2695 }
2696 }
2697 break;
2698 }
2699 }
2700
2701 result.removeDuplicates();
2702 return result;
2703 }
2704
getDeepSkyObjectsByType(const QString & objType) const2705 QList<NebulaP> NebulaMgr::getDeepSkyObjectsByType(const QString &objType) const
2706 {
2707 QList<NebulaP> dso;
2708 int type = objType.toInt();
2709 switch (type)
2710 {
2711 case 100: // Messier Catalogue?
2712 for (const auto& n : dsoArray)
2713 {
2714 if (n->M_nb>0)
2715 dso.append(n);
2716 }
2717 break;
2718 case 101: // Caldwell Catalogue?
2719 for (const auto& n : dsoArray)
2720 {
2721 if (n->C_nb>0)
2722 dso.append(n);
2723 }
2724 break;
2725 case 102: // Barnard Catalogue?
2726 for (const auto& n : dsoArray)
2727 {
2728 if (n->B_nb>0)
2729 dso.append(n);
2730 }
2731 break;
2732 case 103: // Sharpless Catalogue?
2733 for (const auto& n : dsoArray)
2734 {
2735 if (n->Sh2_nb>0)
2736 dso.append(n);
2737 }
2738 break;
2739 case 104: // van den Bergh Catalogue
2740 for (const auto& n : dsoArray)
2741 {
2742 if (n->VdB_nb>0)
2743 dso.append(n);
2744 }
2745 break;
2746 case 105: // RCW Catalogue
2747 for (const auto& n : dsoArray)
2748 {
2749 if (n->RCW_nb>0)
2750 dso.append(n);
2751 }
2752 break;
2753 case 106: // Collinder Catalogue
2754 for (const auto& n : dsoArray)
2755 {
2756 if (n->Cr_nb>0)
2757 dso.append(n);
2758 }
2759 break;
2760 case 107: // Melotte Catalogue
2761 for (const auto& n : dsoArray)
2762 {
2763 if (n->Mel_nb>0)
2764 dso.append(n);
2765 }
2766 break;
2767 case 108: // New General Catalogue
2768 for (const auto& n : dsoArray)
2769 {
2770 if (n->NGC_nb>0)
2771 dso.append(n);
2772 }
2773 break;
2774 case 109: // Index Catalogue
2775 for (const auto& n : dsoArray)
2776 {
2777 if (n->IC_nb>0)
2778 dso.append(n);
2779 }
2780 break;
2781 case 110: // Lynds' Catalogue of Bright Nebulae
2782 for (const auto& n : dsoArray)
2783 {
2784 if (n->LBN_nb>0)
2785 dso.append(n);
2786 }
2787 break;
2788 case 111: // Lynds' Catalogue of Dark Nebulae
2789 for (const auto& n : dsoArray)
2790 {
2791 if (n->LDN_nb>0)
2792 dso.append(n);
2793 }
2794 break;
2795 case 112: // Principal Galaxy Catalog
2796 for (const auto& n : dsoArray)
2797 {
2798 if (n->PGC_nb>0)
2799 dso.append(n);
2800 }
2801 break;
2802 case 113: // The Uppsala General Catalogue of Galaxies
2803 for (const auto& n : dsoArray)
2804 {
2805 if (n->UGC_nb>0)
2806 dso.append(n);
2807 }
2808 break;
2809 case 114: // Cederblad Catalog
2810 for (const auto& n : dsoArray)
2811 {
2812 if (!n->Ced_nb.isEmpty())
2813 dso.append(n);
2814 }
2815 break;
2816 case 115: // Atlas of Peculiar Galaxies (Arp)
2817 for (const auto& n : dsoArray)
2818 {
2819 if (n->Arp_nb>0)
2820 dso.append(n);
2821 }
2822 break;
2823 case 116: // The Catalogue of Interacting Galaxies by Vorontsov-Velyaminov (VV)
2824 for (const auto& n : dsoArray)
2825 {
2826 if (n->VV_nb>0)
2827 dso.append(n);
2828 }
2829 break;
2830 case 117: // Catalogue of Galactic Planetary Nebulae (PK)
2831 for (const auto& n : dsoArray)
2832 {
2833 if (!n->PK_nb.isEmpty())
2834 dso.append(n);
2835 }
2836 break;
2837 case 118: // Strasbourg-ESO Catalogue of Galactic Planetary Nebulae by Acker et. al. (PN G)
2838 for (const auto& n : dsoArray)
2839 {
2840 if (!n->PNG_nb.isEmpty())
2841 dso.append(n);
2842 }
2843 break;
2844 case 119: // A catalogue of Galactic supernova remnants by Green (SNR G)
2845 for (const auto& n : dsoArray)
2846 {
2847 if (!n->SNRG_nb.isEmpty())
2848 dso.append(n);
2849 }
2850 break;
2851 case 120: // A Catalog of Rich Clusters of Galaxies by Abell et. al. (ACO)
2852 for (const auto& n : dsoArray)
2853 {
2854 if (!n->ACO_nb.isEmpty())
2855 dso.append(n);
2856 }
2857 break;
2858 case 121: // Hickson Compact Group by Hickson et. al. (HCG)
2859 for (const auto& n : dsoArray)
2860 {
2861 if (!n->HCG_nb.isEmpty())
2862 dso.append(n);
2863 }
2864 break;
2865 case 122: // ESO/Uppsala Survey of the ESO(B) Atlas (ESO)
2866 for (const auto& n : dsoArray)
2867 {
2868 if (!n->ESO_nb.isEmpty())
2869 dso.append(n);
2870 }
2871 break;
2872 case 123: // Catalogue of southern stars embedded in nebulosity (VdBH)
2873 for (const auto& n : dsoArray)
2874 {
2875 if (!n->VdBH_nb.isEmpty())
2876 dso.append(n);
2877 }
2878 break;
2879 case 124: // Catalogue and distances of optically visible H II regions (DWB)
2880 for (const auto& n : dsoArray)
2881 {
2882 if (n->DWB_nb > 0)
2883 dso.append(n);
2884 }
2885 break;
2886 case 125: // Trumpler Catalogue (Tr)
2887 for (const auto& n : dsoArray)
2888 {
2889 if (n->Tr_nb > 0)
2890 dso.append(n);
2891 }
2892 break;
2893 case 126: // Stock Catalogue (St)
2894 for (const auto& n : dsoArray)
2895 {
2896 if (n->St_nb > 0)
2897 dso.append(n);
2898 }
2899 break;
2900 case 127: // Ruprecht Catalogue (Ru)
2901 for (const auto& n : dsoArray)
2902 {
2903 if (n->Ru_nb > 0)
2904 dso.append(n);
2905 }
2906 break;
2907 case 128: // van den Bergh-Hagen Catalogue (VdB-Ha)
2908 for (const auto& n : dsoArray)
2909 {
2910 if (n->VdBHa_nb > 0)
2911 dso.append(n);
2912 }
2913 break;
2914 case 150: // Dwarf galaxies [see NebulaList.hpp]
2915 {
2916 NebulaP ds;
2917 for (unsigned int i = 0; i < sizeof(DWARF_GALAXIES) / sizeof(DWARF_GALAXIES[0]); i++)
2918 {
2919 ds = searchPGC(DWARF_GALAXIES[i]);
2920 if (!ds.isNull())
2921 dso.append(ds);
2922 }
2923 break;
2924 }
2925 case 151: // Herschel 400 Catalogue [see NebulaList.hpp]
2926 {
2927 NebulaP ds;
2928 for (unsigned int i = 0; i < sizeof(H400_LIST) / sizeof(H400_LIST[0]); i++)
2929 {
2930 ds = searchNGC(H400_LIST[i]);
2931 if (!ds.isNull())
2932 dso.append(ds);
2933 }
2934 break;
2935 }
2936 case 152: // Jack Bennett's deep sky catalogue [see NebulaList.hpp]
2937 {
2938 NebulaP ds;
2939 for (unsigned int i = 0; i < sizeof(BENNETT_LIST) / sizeof(BENNETT_LIST[0]); i++)
2940 {
2941 ds = searchNGC(BENNETT_LIST[i]);
2942 if (!ds.isNull())
2943 dso.append(ds);
2944 }
2945 ds = searchMel(105);
2946 if (!ds.isNull())
2947 dso.append(ds);
2948 ds = searchIC(1459);
2949 if (!ds.isNull())
2950 dso.append(ds);
2951 break;
2952 }
2953 case 153: // James Dunlop's deep sky catalogue [see NebulaList.hpp]
2954 {
2955 NebulaP ds;
2956 for (unsigned int i = 0; i < sizeof(DUNLOP_LIST) / sizeof(DUNLOP_LIST[0]); i++)
2957 {
2958 ds = searchNGC(DUNLOP_LIST[i]);
2959 if (!ds.isNull())
2960 dso.append(ds);
2961 }
2962 break;
2963 }
2964 default:
2965 {
2966 for (const auto& n : dsoArray)
2967 {
2968 if (n->nType==type)
2969 dso.append(n);
2970 }
2971 break;
2972 }
2973 }
2974
2975 return dso;
2976 }
2977