File indexing completed on 2024-04-28 11:25:32
0001 /* 0002 SPDX-FileCopyrightText: 2004-2005 Pablo de Vicente <p.devicentea@wanadoo.es> 0003 0004 SPDX-License-Identifier: GPL-2.0-or-later 0005 */ 0006 0007 #include "modcalcplanets.h" 0008 0009 #include "geolocation.h" 0010 #include "kstarsdata.h" 0011 #include "ksnotification.h" 0012 #include "dialogs/locationdialog.h" 0013 #include "skyobjects/ksmoon.h" 0014 #include "skyobjects/kssun.h" 0015 0016 modCalcPlanets::modCalcPlanets(QWidget *parentSplit) : QFrame(parentSplit) 0017 { 0018 setupUi(this); 0019 0020 KStarsDateTime dt(KStarsDateTime::currentDateTime()); 0021 0022 DateTimeBox->setDateTime(dt); 0023 DateBoxBatch->setDate(dt.date()); 0024 UTBoxBatch->setTime(dt.time()); 0025 0026 geoPlace = KStarsData::Instance()->geo(); 0027 LocationButton->setText(geoPlace->fullName()); 0028 0029 RABox->setUnits(dmsBox::HOURS); 0030 0031 // signals and slots connections 0032 connect(PlanetComboBox, SIGNAL(activated(int)), this, SLOT(slotComputePosition())); 0033 connect(DateTimeBox, SIGNAL(dateTimeChanged(QDateTime)), this, SLOT(slotComputePosition())); 0034 connect(LocationButton, SIGNAL(clicked()), this, SLOT(slotLocation())); 0035 0036 connect(UTCheckBatch, SIGNAL(clicked()), this, SLOT(slotUtCheckedBatch())); 0037 connect(DateCheckBatch, SIGNAL(clicked()), this, SLOT(slotDateCheckedBatch())); 0038 connect(LatCheckBatch, SIGNAL(clicked()), this, SLOT(slotLatCheckedBatch())); 0039 connect(LongCheckBatch, SIGNAL(clicked()), this, SLOT(slotLongCheckedBatch())); 0040 connect(PlanetCheckBatch, SIGNAL(clicked()), this, SLOT(slotPlanetsCheckedBatch())); 0041 0042 slotComputePosition(); 0043 show(); 0044 } 0045 0046 void modCalcPlanets::slotLocation() 0047 { 0048 QPointer<LocationDialog> ld = new LocationDialog(this); 0049 0050 if (ld->exec() == QDialog::Accepted) 0051 { 0052 geoPlace = ld->selectedCity(); 0053 LocationButton->setText(geoPlace->fullName()); 0054 slotComputePosition(); 0055 } 0056 delete ld; 0057 } 0058 0059 void modCalcPlanets::slotComputePosition() 0060 { 0061 KStarsDateTime dt(DateTimeBox->dateTime()); 0062 long double julianDay = dt.djd(); 0063 KSNumbers num(julianDay); 0064 CachingDms LST(geoPlace->GSTtoLST(dt.gst())); 0065 0066 // Earth 0067 KSPlanet Earth(i18n("Earth")); 0068 Earth.findPosition(&num); 0069 0070 // Earth is special case! 0071 if (PlanetComboBox->currentIndex() == 2) 0072 { 0073 showCoordinates(Earth); 0074 return; 0075 } 0076 0077 // Pointer to hold planet data. Pointer is used since it has to 0078 // hold objects of different type. It's safe to use new/delete 0079 // because exceptions are disallowed. 0080 std::unique_ptr<KSPlanetBase> p; 0081 0082 switch (PlanetComboBox->currentIndex()) 0083 { 0084 case 0: 0085 p.reset(new KSPlanet(KSPlanetBase::MERCURY)); 0086 break; 0087 case 1: 0088 p.reset(new KSPlanet(KSPlanetBase::VENUS)); 0089 break; 0090 case 3: 0091 p.reset(new KSPlanet(KSPlanetBase::MARS)); 0092 break; 0093 case 4: 0094 p.reset(new KSPlanet(KSPlanetBase::JUPITER)); 0095 break; 0096 case 5: 0097 p.reset(new KSPlanet(KSPlanetBase::SATURN)); 0098 break; 0099 case 6: 0100 p.reset(new KSPlanet(KSPlanetBase::URANUS)); 0101 break; 0102 case 7: 0103 p.reset(new KSPlanet(KSPlanetBase::NEPTUNE)); 0104 break; 0105 /*case 8: 0106 p.reset(new KSPluto(); break;*/ 0107 case 8: 0108 p.reset(new KSMoon()); 0109 break; 0110 case 9: 0111 p.reset(new KSSun()); 0112 p->setRsun(0.0); 0113 break; 0114 } 0115 if (p.get() == nullptr) 0116 return; 0117 0118 // Show data. 0119 p->findPosition(&num, geoPlace->lat(), &LST, &Earth); 0120 p->EquatorialToHorizontal(&LST, geoPlace->lat()); 0121 showCoordinates(*p); 0122 } 0123 0124 void modCalcPlanets::showCoordinates(const KSPlanetBase &ksp) 0125 { 0126 showHeliocentricEclipticCoords(ksp.helEcLong(), ksp.helEcLat(), ksp.rsun()); 0127 showGeocentricEclipticCoords(ksp.ecLong(), ksp.ecLat(), ksp.rearth()); 0128 showEquatorialCoords(ksp.ra(), ksp.dec()); 0129 showTopocentricCoords(ksp.az(), ksp.alt()); 0130 } 0131 0132 void modCalcPlanets::showHeliocentricEclipticCoords(const dms &hLong, const dms &hLat, double dist) 0133 { 0134 HelioLongBox->show(hLong); 0135 HelioLatBox->show(hLat); 0136 HelioDistBox->setText(QLocale().toString(dist, 6)); 0137 } 0138 0139 void modCalcPlanets::showGeocentricEclipticCoords(const dms &eLong, const dms &eLat, double dist) 0140 { 0141 GeoLongBox->show(eLong); 0142 GeoLatBox->show(eLat); 0143 GeoDistBox->setText(QLocale().toString(dist, 6)); 0144 } 0145 0146 void modCalcPlanets::showEquatorialCoords(const dms &ra, const dms &dec) 0147 { 0148 RABox->show(ra); 0149 DecBox->show(dec); 0150 } 0151 0152 void modCalcPlanets::showTopocentricCoords(const dms &az, const dms &el) 0153 { 0154 AzBox->show(az); 0155 AltBox->show(el); 0156 } 0157 0158 void modCalcPlanets::slotPlanetsCheckedBatch() 0159 { 0160 PlanetComboBoxBatch->setEnabled(!PlanetCheckBatch->isChecked()); 0161 } 0162 0163 void modCalcPlanets::slotUtCheckedBatch() 0164 { 0165 UTBoxBatch->setEnabled(!UTCheckBatch->isChecked()); 0166 } 0167 0168 void modCalcPlanets::slotDateCheckedBatch() 0169 { 0170 DateBoxBatch->setEnabled(!DateCheckBatch->isChecked()); 0171 } 0172 0173 void modCalcPlanets::slotLongCheckedBatch() 0174 { 0175 LongBoxBatch->setEnabled(!LongCheckBatch->isChecked()); 0176 } 0177 0178 void modCalcPlanets::slotLatCheckedBatch() 0179 { 0180 LatBoxBatch->setEnabled(!LatCheckBatch->isChecked()); 0181 } 0182 0183 void modCalcPlanets::slotRunBatch() 0184 { 0185 const QString inputFileName = InputFileBoxBatch->url().toLocalFile(); 0186 0187 // We open the input file and read its content 0188 0189 if (QFile::exists(inputFileName)) 0190 { 0191 QFile f(inputFileName); 0192 if (!f.open(QIODevice::ReadOnly)) 0193 { 0194 QString message = i18n("Could not open file %1.", f.fileName()); 0195 KSNotification::sorry(message, i18n("Could Not Open File")); 0196 return; 0197 } 0198 0199 QTextStream istream(&f); 0200 processLines(istream); 0201 f.close(); 0202 } 0203 else 0204 { 0205 QString message = i18n("Invalid file: %1", inputFileName); 0206 KSNotification::sorry(message, i18n("Invalid file")); 0207 InputFileBoxBatch->setUrl(QUrl()); 0208 } 0209 } 0210 0211 unsigned int modCalcPlanets::requiredBatchFields() 0212 { 0213 unsigned int i = 0; 0214 0215 if (PlanetCheckBatch->isChecked()) 0216 i++; 0217 if (UTCheckBatch->isChecked()) 0218 i++; 0219 if (DateCheckBatch->isChecked()) 0220 i++; 0221 if (LongCheckBatch->isChecked()) 0222 i++; 0223 if (LatCheckBatch->isChecked()) 0224 i++; 0225 0226 return i; 0227 } 0228 0229 void modCalcPlanets::processLines(QTextStream &istream) 0230 { 0231 // we open the output file 0232 0233 const QString outputFileName = OutputFileBoxBatch->url().toLocalFile(); 0234 QFile fOut(outputFileName); 0235 fOut.open(QIODevice::WriteOnly); 0236 QTextStream ostream(&fOut); 0237 bool lineIsValid = true; 0238 0239 QChar space = ' '; 0240 QString planetB; 0241 unsigned int i = 0, nline = 0; 0242 QTime utB; 0243 QDate dtB; 0244 CachingDms longB, latB, hlongB, hlatB, glongB, glatB, raB, decB, azmB, altB; 0245 double rSunB(0.0), rEarthB(0.0); 0246 0247 //Initialize planet names 0248 QString pn; 0249 QStringList pNames, pNamesi18n; 0250 pNames << "Mercury" 0251 << "Venus" 0252 << "Earth" 0253 << "Mars" 0254 << "Jupiter" 0255 << "Saturn" 0256 << "Uranus" 0257 << "Neptune" /* << "Pluto" */ 0258 << "Sun" 0259 << "Moon"; 0260 pNamesi18n << i18n("Mercury") << i18n("Venus") << i18n("Earth") << i18n("Mars") << i18n("Jupiter") << i18n("Saturn") 0261 << i18n("Uranus") << i18n("Neptune") /* << i18nc("Asteroid name (optional)", "Pluto") */ 0262 << i18n("Sun") << i18n("Moon"); 0263 0264 ///Parse the input file 0265 int numberOfRequiredFields = requiredBatchFields(); 0266 while (!istream.atEnd()) 0267 { 0268 QString lineToWrite; 0269 QString line = istream.readLine(); 0270 line = line.trimmed(); 0271 0272 //Go through the line, looking for parameters 0273 0274 QStringList fields = line.split(' '); 0275 0276 if (fields.count() != numberOfRequiredFields) 0277 { 0278 lineIsValid = false; 0279 qWarning() << i18n("Incorrect number of fields in line %1: ", nline) 0280 << i18n("Present fields %1. ", fields.count()) 0281 << i18n("Required fields %1. ", numberOfRequiredFields); 0282 nline++; 0283 continue; 0284 } 0285 0286 i = 0; 0287 if (PlanetCheckBatch->isChecked()) 0288 { 0289 planetB = fields[i]; 0290 int j = pNamesi18n.indexOf(planetB); 0291 if (j == -1) 0292 { 0293 qWarning() << i18n("Unknown planet ") << fields[i] << i18n(" in line %1: ", nline); 0294 continue; 0295 } 0296 pn = pNames.at(j); //untranslated planet name 0297 i++; 0298 } 0299 else 0300 { 0301 planetB = PlanetComboBoxBatch->currentText(); 0302 } 0303 if (AllRadioBatch->isChecked() || PlanetCheckBatch->isChecked()) 0304 { 0305 lineToWrite = planetB; 0306 lineToWrite += space; 0307 } 0308 0309 // Read Ut and write in ostream if corresponds 0310 if (UTCheckBatch->isChecked()) 0311 { 0312 utB = QTime::fromString(fields[i]); 0313 if (!utB.isValid()) 0314 { 0315 qWarning() << i18n("Line %1 contains an invalid time", nline); 0316 lineIsValid = false; 0317 nline++; 0318 continue; 0319 } 0320 i++; 0321 } 0322 else 0323 { 0324 utB = UTBoxBatch->time(); 0325 } 0326 if (AllRadioBatch->isChecked() || UTCheckBatch->isChecked()) 0327 lineToWrite += QLocale().toString(utB).append(space); 0328 0329 // Read date and write in ostream if corresponds 0330 if (DateCheckBatch->isChecked()) 0331 { 0332 dtB = QDate::fromString(fields[i], Qt::ISODate); 0333 if (!dtB.isValid()) 0334 { 0335 qWarning() << i18n("Line %1 contains an invalid date: ", nline) << fields[i]; 0336 lineIsValid = false; 0337 nline++; 0338 continue; 0339 } 0340 i++; 0341 } 0342 else 0343 { 0344 dtB = DateBoxBatch->date(); 0345 } 0346 if (AllRadioBatch->isChecked() || DateCheckBatch->isChecked()) 0347 lineToWrite += QLocale().toString(dtB, QLocale::LongFormat).append(space); 0348 0349 // Read Longitude and write in ostream if corresponds 0350 0351 if (LongCheckBatch->isChecked()) 0352 { 0353 longB = CachingDms::fromString(fields[i], true); 0354 i++; 0355 } 0356 else 0357 { 0358 longB = LongBoxBatch->createDms(); 0359 } 0360 if (AllRadioBatch->isChecked() || LongCheckBatch->isChecked()) 0361 lineToWrite += longB.toDMSString() + space; 0362 0363 // Read Latitude 0364 if (LatCheckBatch->isChecked()) 0365 { 0366 latB = CachingDms::fromString(fields[i], true); 0367 i++; 0368 } 0369 else 0370 { 0371 latB = LatBoxBatch->createDms(); 0372 } 0373 if (AllRadioBatch->isChecked() || LatCheckBatch->isChecked()) 0374 lineToWrite += latB.toDMSString() + space; 0375 0376 KStarsDateTime edt(dtB, utB); 0377 CachingDms LST = edt.gst() + longB; 0378 0379 KSNumbers num(edt.djd()); 0380 KSPlanet Earth(i18n("Earth")); 0381 Earth.findPosition(&num); 0382 0383 // FIXME: allocate new object for every iteration is probably not wisest idea. 0384 KSPlanetBase *kspb = nullptr; 0385 /*if ( pn == "Pluto" ) { 0386 kspb = new KSPluto(); 0387 } else*/ 0388 if (pn == i18n("Sun")) 0389 { 0390 kspb = new KSSun(); 0391 } 0392 else if (pn == i18n("Moon")) 0393 { 0394 kspb = new KSMoon(); 0395 } 0396 else 0397 { 0398 kspb = new KSPlanet(i18n(pn.toLocal8Bit()), QString(), Qt::white, 1.0); 0399 } 0400 kspb->findPosition(&num, &latB, &LST, &Earth); 0401 kspb->EquatorialToHorizontal(&LST, &latB); 0402 0403 // Heliocentric Ecl. coords. 0404 hlongB = kspb->helEcLong(); 0405 hlatB = kspb->helEcLat(); 0406 rSunB = kspb->rsun(); 0407 // Geocentric Ecl. coords. 0408 glongB = kspb->ecLong(); 0409 glatB = kspb->ecLat(); 0410 rEarthB = kspb->rearth(); 0411 // Equatorial coords. 0412 decB = kspb->dec(); 0413 raB = kspb->ra(); 0414 // Topocentric Coords. 0415 azmB = kspb->az(); 0416 altB = kspb->alt(); 0417 0418 ostream << lineToWrite; 0419 0420 if (HelioEclCheckBatch->isChecked()) 0421 ostream << hlongB.toDMSString() << space << hlatB.toDMSString() << space << rSunB << space; 0422 if (GeoEclCheckBatch->isChecked()) 0423 ostream << glongB.toDMSString() << space << glatB.toDMSString() << space << rEarthB << space; 0424 if (EquatorialCheckBatch->isChecked()) 0425 ostream << raB.toHMSString() << space << decB.toDMSString() << space; 0426 if (HorizontalCheckBatch->isChecked()) 0427 ostream << azmB.toDMSString() << space << altB.toDMSString() << space; 0428 ostream << '\n'; 0429 0430 // Delete object 0431 delete kspb; 0432 0433 nline++; 0434 } 0435 0436 if (!lineIsValid) 0437 { 0438 QString message = i18n("Errors found while parsing some lines in the input file"); 0439 KSNotification::sorry(message, i18n("Errors in lines")); 0440 } 0441 0442 fOut.close(); 0443 }