1 /*
2 SPDX-FileCopyrightText: 2005 Pablo de Vicente <p.devicente@wanadoo.es>
3
4 SPDX-License-Identifier: GPL-2.0-or-later
5 */
6
7 #include "modcalcvlsr.h"
8
9 #include "dms.h"
10 #include "geolocation.h"
11 #include "ksnumbers.h"
12 #include "kstars.h"
13 #include "ksnotification.h"
14 #include "kstarsdata.h"
15 #include "kstarsdatetime.h"
16 #include "dialogs/locationdialog.h"
17 #include "dialogs/finddialog.h"
18 #include "skyobjects/skypoint.h"
19 #include "widgets/dmsbox.h"
20
21 #include <KLocalizedString>
22
23 #include <QPointer>
24 #include <QFileDialog>
25
modCalcVlsr(QWidget * parentSplit)26 modCalcVlsr::modCalcVlsr(QWidget *parentSplit) : QFrame(parentSplit), velocityFlag(0)
27 {
28 setupUi(this);
29 RA->setDegType(false);
30
31 Date->setDateTime(KStarsDateTime::currentDateTime());
32 initGeo();
33
34 VLSR->setValidator(new QDoubleValidator(VLSR));
35 VHelio->setValidator(new QDoubleValidator(VHelio));
36 VGeo->setValidator(new QDoubleValidator(VGeo));
37 VTopo->setValidator(new QDoubleValidator(VTopo));
38
39 // signals and slots connections
40 connect(Date, SIGNAL(dateTimeChanged(QDateTime)), this, SLOT(slotCompute()));
41 connect(NowButton, SIGNAL(clicked()), this, SLOT(slotNow()));
42 connect(LocationButton, SIGNAL(clicked()), this, SLOT(slotLocation()));
43 connect(ObjectButton, SIGNAL(clicked()), this, SLOT(slotFindObject()));
44 connect(RA, SIGNAL(editingFinished()), this, SLOT(slotCompute()));
45 connect(Dec, SIGNAL(editingFinished()), this, SLOT(slotCompute()));
46 connect(VLSR, SIGNAL(editingFinished()), this, SLOT(slotCompute()));
47 connect(VHelio, SIGNAL(editingFinished()), this, SLOT(slotCompute()));
48 connect(VGeo, SIGNAL(editingFinished()), this, SLOT(slotCompute()));
49 connect(VTopo, SIGNAL(editingFinished()), this, SLOT(slotCompute()));
50
51 connect(RunButtonBatch, SIGNAL(clicked()), this, SLOT(slotRunBatch()));
52
53 show();
54 }
55
initGeo(void)56 void modCalcVlsr::initGeo(void)
57 {
58 geoPlace = KStarsData::Instance()->geo();
59 LocationButton->setText(geoPlace->fullName());
60 }
61
slotNow()62 void modCalcVlsr::slotNow()
63 {
64 Date->setDateTime(KStarsDateTime::currentDateTime());
65 slotCompute();
66 }
67
slotFindObject()68 void modCalcVlsr::slotFindObject()
69 {
70 if (FindDialog::Instance()->exec() == QDialog::Accepted)
71 {
72 SkyObject *o = FindDialog::Instance()->targetObject();
73 RA->showInHours(o->ra0());
74 Dec->showInDegrees(o->dec0());
75 }
76 }
77
slotLocation()78 void modCalcVlsr::slotLocation()
79 {
80 QPointer<LocationDialog> ld(new LocationDialog(this));
81
82 if (ld->exec() == QDialog::Accepted && ld)
83 {
84 GeoLocation *newGeo = ld->selectedCity();
85 if (newGeo)
86 {
87 geoPlace = newGeo;
88 LocationButton->setText(geoPlace->fullName());
89 }
90 }
91 delete ld;
92
93 slotCompute();
94 }
95
slotCompute()96 void modCalcVlsr::slotCompute()
97 {
98 bool ok1(false), ok2(false);
99 SkyPoint sp(RA->createDms(false, &ok1), Dec->createDms(true, &ok2));
100 if (!ok1 || !ok2)
101 return;
102
103 KStarsDateTime dt(Date->dateTime());
104 double vst[3];
105
106 geoPlace->TopocentricVelocity(vst, dt.gst());
107
108 if (sender()->objectName() == "VLSR")
109 velocityFlag = 0;
110 if (sender()->objectName() == "VHelio")
111 velocityFlag = 1;
112 if (sender()->objectName() == "VGeo")
113 velocityFlag = 2;
114 if (sender()->objectName() == "VTopo")
115 velocityFlag = 3;
116
117 switch (velocityFlag)
118 {
119 case 0: //Hold VLSR constant, compute the others
120 {
121 double vlsr = VLSR->text().toDouble();
122 double vhelio = sp.vHeliocentric(vlsr, dt.djd());
123 double vgeo = sp.vGeocentric(vhelio, dt.djd());
124
125 VHelio->setText(QString::number(vhelio));
126 VGeo->setText(QString::number(vgeo));
127 VTopo->setText(QString::number(sp.vTopocentric(vgeo, vst)));
128 break;
129 }
130
131 case 1: //Hold VHelio constant, compute the others
132 {
133 double vhelio = VHelio->text().toDouble();
134 double vlsr = sp.vHelioToVlsr(vhelio, dt.djd());
135 double vgeo = sp.vGeocentric(vhelio, dt.djd());
136
137 VLSR->setText(QString::number(vlsr));
138 VGeo->setText(QString::number(vgeo));
139 VTopo->setText(QString::number(sp.vTopocentric(vgeo, vst)));
140 break;
141 }
142
143 case 2: //Hold VGeo constant, compute the others
144 {
145 double vgeo = VGeo->text().toDouble();
146 double vhelio = sp.vGeoToVHelio(vgeo, dt.djd());
147 double vlsr = sp.vHelioToVlsr(vhelio, dt.djd());
148
149 VLSR->setText(QString::number(vlsr));
150 VHelio->setText(QString::number(vhelio));
151 VTopo->setText(QString::number(sp.vTopocentric(vgeo, vst)));
152 break;
153 }
154
155 case 3: //Hold VTopo constant, compute the others
156 {
157 double vtopo = VTopo->text().toDouble();
158 double vgeo = sp.vTopoToVGeo(vtopo, vst);
159 double vhelio = sp.vGeoToVHelio(vgeo, dt.djd());
160 double vlsr = sp.vHelioToVlsr(vhelio, dt.djd());
161
162 VLSR->setText(QString::number(vlsr));
163 VHelio->setText(QString::number(vhelio));
164 VGeo->setText(QString::number(vgeo));
165 break;
166 }
167
168 default: //oops
169 qDebug() << "Error: do not know which velocity to use for input.";
170 break;
171 }
172 }
173
slotUtChecked()174 void modCalcVlsr::slotUtChecked()
175 {
176 if (UTCheckBatch->isChecked())
177 UTBoxBatch->setEnabled(false);
178 else
179 {
180 UTBoxBatch->setEnabled(true);
181 }
182 }
183
slotDateChecked()184 void modCalcVlsr::slotDateChecked()
185 {
186 if (DateCheckBatch->isChecked())
187 DateBoxBatch->setEnabled(false);
188 else
189 {
190 DateBoxBatch->setEnabled(true);
191 }
192 }
193
slotRaChecked()194 void modCalcVlsr::slotRaChecked()
195 {
196 if (RACheckBatch->isChecked())
197 {
198 RABoxBatch->setEnabled(false);
199 }
200 else
201 {
202 RABoxBatch->setEnabled(true);
203 }
204 }
205
slotDecChecked()206 void modCalcVlsr::slotDecChecked()
207 {
208 if (DecCheckBatch->isChecked())
209 {
210 DecBoxBatch->setEnabled(false);
211 }
212 else
213 {
214 DecBoxBatch->setEnabled(true);
215 }
216 }
217
slotEpochChecked()218 void modCalcVlsr::slotEpochChecked()
219 {
220 if (EpochCheckBatch->isChecked())
221 EpochBoxBatch->setEnabled(false);
222 else
223 EpochBoxBatch->setEnabled(true);
224 }
225
slotLongChecked()226 void modCalcVlsr::slotLongChecked()
227 {
228 if (LongCheckBatch->isChecked())
229 LongitudeBoxBatch->setEnabled(false);
230 else
231 LongitudeBoxBatch->setEnabled(true);
232 }
233
slotLatChecked()234 void modCalcVlsr::slotLatChecked()
235 {
236 if (LatCheckBatch->isChecked())
237 LatitudeBoxBatch->setEnabled(false);
238 else
239 {
240 LatitudeBoxBatch->setEnabled(true);
241 }
242 }
243
slotHeightChecked()244 void modCalcVlsr::slotHeightChecked()
245 {
246 if (ElevationCheckBatch->isChecked())
247 ElevationBoxBatch->setEnabled(false);
248 else
249 {
250 ElevationBoxBatch->setEnabled(true);
251 }
252 }
253
slotVlsrChecked()254 void modCalcVlsr::slotVlsrChecked()
255 {
256 if (InputVelocityCheckBatch->isChecked())
257 InputVelocityBoxBatch->setEnabled(false);
258 else
259 {
260 InputVelocityBoxBatch->setEnabled(true);
261 }
262 }
263
slotInputFile()264 void modCalcVlsr::slotInputFile()
265 {
266 const QString inputFileName = QFileDialog::getOpenFileName(KStars::Instance(), QString(), QString());
267 if (!inputFileName.isEmpty())
268 InputFileBoxBatch->setUrl(QUrl::fromLocalFile(inputFileName));
269 }
270
slotOutputFile()271 void modCalcVlsr::slotOutputFile()
272 {
273 const QString outputFileName = QFileDialog::getSaveFileName();
274 if (!outputFileName.isEmpty())
275 OutputFileBoxBatch->setUrl(QUrl::fromLocalFile(outputFileName));
276 }
277
slotRunBatch()278 void modCalcVlsr::slotRunBatch()
279 {
280 const QString inputFileName = InputFileBoxBatch->url().toLocalFile();
281
282 // We open the input file and read its content
283
284 if (QFile::exists(inputFileName))
285 {
286 QFile f(inputFileName);
287 if (!f.open(QIODevice::ReadOnly))
288 {
289 KSNotification::sorry(i18n("Could not open file %1.", f.fileName()), i18n("Could Not Open File"));
290 return;
291 }
292
293 // processLines(&f);
294 QTextStream istream(&f);
295 processLines(istream);
296 // readFile( istream );
297 f.close();
298 }
299 else
300 {
301 KSNotification::sorry(i18n("Invalid file: %1", inputFileName), i18n("Invalid file"));
302 InputFileBoxBatch->setUrl(QUrl());
303 }
304 }
305
processLines(QTextStream & istream)306 void modCalcVlsr::processLines(QTextStream &istream)
307 {
308 // we open the output file
309
310 // QTextStream istream(&fIn);
311 QString outputFileName;
312 outputFileName = OutputFileBoxBatch->url().toLocalFile();
313 QFile fOut(outputFileName);
314 fOut.open(QIODevice::WriteOnly);
315 QTextStream ostream(&fOut);
316
317 QString line;
318 QChar space = ' ';
319 int i = 0;
320 long double jd0;
321 SkyPoint spB;
322 double sra, cra, sdc, cdc;
323 dms raB, decB, latB, longB;
324 QString epoch0B;
325 double vhB, vgB, vtB, vlsrB, heightB;
326 double vtopo[3];
327 QTime utB;
328 QDate dtB;
329 KStarsDateTime dt0B;
330
331 while (!istream.atEnd())
332 {
333 line = istream.readLine();
334 line = line.trimmed();
335
336 //Go through the line, looking for parameters
337
338 QStringList fields = line.split(' ');
339
340 i = 0;
341
342 // Read Ut and write in ostream if corresponds
343
344 if (UTCheckBatch->isChecked())
345 {
346 utB = QTime::fromString(fields[i]);
347 i++;
348 }
349 else
350 utB = UTBoxBatch->time();
351
352 if (AllRadioBatch->isChecked())
353 ostream << QLocale().toString(utB) << space;
354 else if (UTCheckBatch->isChecked())
355 ostream << QLocale().toString(utB) << space;
356
357 // Read date and write in ostream if corresponds
358
359 if (DateCheckBatch->isChecked())
360 {
361 dtB = QDate::fromString(fields[i]);
362 i++;
363 }
364 else
365 dtB = DateBoxBatch->date();
366 if (AllRadioBatch->isChecked())
367 ostream << QLocale().toString(dtB, QLocale::LongFormat).append(space);
368 else if (DateCheckBatch->isChecked())
369 ostream << QLocale().toString(dtB, QLocale::LongFormat).append(space);
370
371 // Read RA and write in ostream if corresponds
372
373 if (RACheckBatch->isChecked())
374 {
375 raB = dms::fromString(fields[i], false);
376 i++;
377 }
378 else
379 raB = RABoxBatch->createDms(false);
380
381 if (AllRadioBatch->isChecked())
382 ostream << raB.toHMSString() << space;
383 else if (RACheckBatch->isChecked())
384 ostream << raB.toHMSString() << space;
385
386 // Read DEC and write in ostream if corresponds
387
388 if (DecCheckBatch->isChecked())
389 {
390 decB = dms::fromString(fields[i], true);
391 i++;
392 }
393 else
394 decB = DecBoxBatch->createDms();
395
396 if (AllRadioBatch->isChecked())
397 ostream << decB.toDMSString() << space;
398 else if (DecCheckBatch->isChecked())
399 ostream << decB.toDMSString() << space;
400
401 // Read Epoch and write in ostream if corresponds
402
403 if (EpochCheckBatch->isChecked())
404 {
405 epoch0B = fields[i];
406 i++;
407 }
408 else
409 epoch0B = EpochBoxBatch->text();
410
411 if (AllRadioBatch->isChecked())
412 ostream << epoch0B << space;
413 else if (EpochCheckBatch->isChecked())
414 ostream << epoch0B << space;
415
416 // Read vlsr and write in ostream if corresponds
417
418 if (InputVelocityCheckBatch->isChecked())
419 {
420 vlsrB = fields[i].toDouble();
421 i++;
422 }
423 else
424 vlsrB = InputVelocityComboBatch->currentText().toDouble();
425
426 if (AllRadioBatch->isChecked())
427 ostream << vlsrB << space;
428 else if (InputVelocityCheckBatch->isChecked())
429 ostream << vlsrB << space;
430
431 // Read Longitude and write in ostream if corresponds
432
433 if (LongCheckBatch->isChecked())
434 {
435 longB = dms::fromString(fields[i], true);
436 i++;
437 }
438 else
439 longB = LongitudeBoxBatch->createDms(true);
440
441 if (AllRadioBatch->isChecked())
442 ostream << longB.toDMSString() << space;
443 else if (LongCheckBatch->isChecked())
444 ostream << longB.toDMSString() << space;
445
446 // Read Latitude
447
448 if (LatCheckBatch->isChecked())
449 {
450 latB = dms::fromString(fields[i], true);
451 i++;
452 }
453 else
454 latB = LatitudeBoxBatch->createDms(true);
455 if (AllRadioBatch->isChecked())
456 ostream << latB.toDMSString() << space;
457 else if (LatCheckBatch->isChecked())
458 ostream << latB.toDMSString() << space;
459
460 // Read height and write in ostream if corresponds
461
462 if (ElevationCheckBatch->isChecked())
463 {
464 heightB = fields[i].toDouble();
465 i++;
466 }
467 else
468 heightB = ElevationBoxBatch->text().toDouble();
469
470 if (AllRadioBatch->isChecked())
471 ostream << heightB << space;
472 else if (ElevationCheckBatch->isChecked())
473 ostream << heightB << space;
474
475 // We make the first calculations
476
477 spB = SkyPoint(raB, decB);
478 dt0B.setFromEpoch(epoch0B);
479 vhB = spB.vHeliocentric(vlsrB, dt0B.djd());
480 jd0 = KStarsDateTime(dtB, utB).djd();
481 vgB = spB.vGeocentric(vlsrB, jd0);
482 geoPlace->setLong(longB);
483 geoPlace->setLat(latB);
484 geoPlace->setElevation(heightB);
485 dms gsidt = KStarsDateTime(dtB, utB).gst();
486 geoPlace->TopocentricVelocity(vtopo, gsidt);
487 spB.ra().SinCos(sra, cra);
488 spB.dec().SinCos(sdc, cdc);
489 vtB = vgB - (vtopo[0] * cdc * cra + vtopo[1] * cdc * sra + vtopo[2] * sdc);
490
491 ostream << vhB << space << vgB << space << vtB << '\n';
492 }
493
494 fOut.close();
495 }
496