Kstars

altvstime.cpp
1/*
2 SPDX-FileCopyrightText: 2002-2003 Pablo de Vicente <vicente@oan.es>
3
4 SPDX-License-Identifier: GPL-2.0-or-later
5*/
6
7#include "altvstime.h"
8
9#include "avtplotwidget.h"
10#include "dms.h"
11#include "ksalmanac.h"
12#include "kstarsdata.h"
13#include "kstarsdatetime.h"
14#include "ksnumbers.h"
15#include "simclock.h"
16#include "kssun.h"
17#include "dialogs/finddialog.h"
18#include "dialogs/locationdialog.h"
19#include "geolocation.h"
20#include "skyobjects/skypoint.h"
21#include "skyobjects/skyobject.h"
22#include "skyobjects/starobject.h"
23
24#include <KLocalizedString>
25#include <kplotwidget.h>
26
27#include <QVBoxLayout>
28#include <QFrame>
29#include <QDialog>
30#include <QPainter>
31#include <QtPrintSupport/QPrinter>
32#include <QtPrintSupport/QPrintDialog>
33
34#include "kstars_debug.h"
35
36AltVsTimeUI::AltVsTimeUI(QWidget *p) : QFrame(p)
37{
38 setupUi(this);
39}
40
42{
43#ifdef Q_OS_OSX
45#endif
46
47 setWindowTitle(i18nc("@title:window", "Altitude vs. Time"));
48
49 setModal(false);
50
53 topLayout->setContentsMargins(0, 0, 0, 0);
54 avtUI = new AltVsTimeUI(this);
55
56 // Layers for setting up the plot's priority: the current curve should be above the other curves.
57 // The Rise/Set/Transit markers should be on top, with highest priority.
58 avtUI->View->addLayer("currentCurveLayer", avtUI->View->layer("main"), QCustomPlot::limAbove);
59 avtUI->View->addLayer("markersLayer", avtUI->View->layer("currentCurveLayer"), QCustomPlot::limAbove);
60
61 // Set up the Graph Window:
62 avtUI->View->setBackground(QBrush(QColor(0, 0, 0)));
63 avtUI->View->xAxis->grid()->setVisible(false);
64 avtUI->View->yAxis->grid()->setVisible(false);
67 avtUI->View->xAxis->setBasePen(axisPen);
68 avtUI->View->xAxis->setTickPen(axisPen);
69 avtUI->View->xAxis->setSubTickPen(axisPen);
70 avtUI->View->xAxis->setTickLabelColor(axisColor);
71 avtUI->View->xAxis->setLabelColor(axisColor);
72
73 avtUI->View->xAxis2->setBasePen(axisPen);
74 avtUI->View->xAxis2->setTickPen(axisPen);
75 avtUI->View->xAxis2->setSubTickPen(axisPen);
76 avtUI->View->xAxis2->setTickLabelColor(axisColor);
77 avtUI->View->xAxis2->setLabelColor(axisColor);
78
79 avtUI->View->yAxis->setBasePen(axisPen);
80 avtUI->View->yAxis->setTickPen(axisPen);
81 avtUI->View->yAxis->setSubTickPen(axisPen);
82 avtUI->View->yAxis->setTickLabelColor(axisColor);
83 avtUI->View->yAxis->setLabelColor(axisColor);
84
85 avtUI->View->yAxis2->setBasePen(axisPen);
86 avtUI->View->yAxis2->setTickPen(axisPen);
87 avtUI->View->yAxis2->setSubTickPen(axisPen);
88 avtUI->View->yAxis2->setTickLabelColor(axisColor);
89 avtUI->View->yAxis2->setLabelColor(axisColor);
90
91 // give the axis some labels:
92 avtUI->View->xAxis2->setLabel(i18n("Local Sidereal Time"));
93 avtUI->View->xAxis2->setVisible(true);
94 avtUI->View->yAxis2->setVisible(true);
95 avtUI->View->yAxis2->setTickLength(0, 0);
96 avtUI->View->xAxis->setLabel(i18n("Local Time"));
97 avtUI->View->yAxis->setLabel(i18n("Altitude"));
98 avtUI->View->xAxis->setRange(43200, 129600);
99 avtUI->View->xAxis2->setRange(61200, 147600);
100
101 // configure the bottom axis to show time instead of number:
103 xAxisTimeTicker->setTimeFormat("%h:%m");
104 xAxisTimeTicker->setTickCount(12);
106 xAxisTimeTicker->setTickOrigin(Qt::UTC);
107 avtUI->View->xAxis->setTicker(xAxisTimeTicker);
108
109 // configure the top axis to show time instead of number:
111 xAxis2TimeTicker->setTimeFormat("%h:%m");
112 xAxis2TimeTicker->setTickCount(12);
114 xAxis2TimeTicker->setTickOrigin(Qt::UTC);
115 avtUI->View->xAxis2->setTicker(xAxis2TimeTicker);
116
117 // set up the Zoom/Pan features for the Top X Axis
118 avtUI->View->axisRect()->setRangeDragAxes(avtUI->View->xAxis2, avtUI->View->yAxis);
119 avtUI->View->axisRect()->setRangeZoomAxes(avtUI->View->xAxis2, avtUI->View->yAxis);
120
121 // set up the margins, for a nice view
122 avtUI->View->axisRect()->setAutoMargins(QCP::msBottom | QCP::msLeft | QCP::msTop);
123 avtUI->View->axisRect()->setMargins(QMargins(0, 0, 7, 0));
124
125 // set up the interaction set:
126 avtUI->View->setInteraction(QCP::iRangeZoom, true);
127 avtUI->View->setInteraction(QCP::iRangeDrag, true);
128
129 // set up the selection tolerance for checking if a certain graph is or not selected:
130 avtUI->View->setSelectionTolerance(5);
131
132 // draw the gradient:
133 drawGradient();
134
135 // set up the background image:
136 background = new QCPItemPixmap(avtUI->View);
137 background->setPixmap(*gradient);
138 background->topLeft->setType(QCPItemPosition::ptPlotCoords);
139 background->bottomRight->setType(QCPItemPosition::ptPlotCoords);
140 background->setScaled(true, Qt::IgnoreAspectRatio);
141 background->setLayer("background");
142 background->setVisible(true);
143
144 avtUI->raBox->setUnits(dmsBox::HOURS);
145 avtUI->decBox->setUnits(dmsBox::DEGREES);
146
147 //FIXME:
148 //Doesn't make sense to manually adjust long/lat unless we can modify TZ also
149 avtUI->longBox->setReadOnly(true);
150 avtUI->latBox->setReadOnly(true);
151
152 topLayout->addWidget(avtUI);
153
155 topLayout->addWidget(buttonBox);
156 connect(buttonBox, SIGNAL(rejected()), this, SLOT(reject()));
157
158 QPushButton *printB = new QPushButton(QIcon::fromTheme("document-print"), i18n("&Print..."));
159 printB->setToolTip(i18n("Print the Altitude vs. time plot"));
161 connect(printB, SIGNAL(clicked()), this, SLOT(slotPrint()));
162
163 geo = KStarsData::Instance()->geo();
164
165 DayOffset = 0;
166 // set up the initial minimum and maximum altitude
167 minAlt = 0;
168 maxAlt = 0;
170 if (getDate().time().hour() > 12)
171 DayOffset = 1;
172
173 avtUI->longBox->show(geo->lng());
174 avtUI->latBox->show(geo->lat());
175
177 setLSTLimits();
178 setDawnDusk();
179
180 connect(avtUI->View->yAxis, SIGNAL(rangeChanged(QCPRange)), this, SLOT(onYRangeChanged(QCPRange)));
181 connect(avtUI->View->xAxis2, SIGNAL(rangeChanged(QCPRange)), this, SLOT(onXRangeChanged(QCPRange)));
182 connect(avtUI->View, SIGNAL(plottableClick(QCPAbstractPlottable*, int, QMouseEvent*)), this,
184 connect(avtUI->View, SIGNAL(mouseMove(QMouseEvent*)), this, SLOT(mouseOverLine(QMouseEvent*)));
185
186 connect(avtUI->browseButton, SIGNAL(clicked()), this, SLOT(slotBrowseObject()));
187 connect(avtUI->cityButton, SIGNAL(clicked()), this, SLOT(slotChooseCity()));
188 connect(avtUI->updateButton, SIGNAL(clicked()), this, SLOT(slotUpdateDateLoc()));
189 connect(avtUI->clearButton, SIGNAL(clicked()), this, SLOT(slotClear()));
190 connect(avtUI->addButton, SIGNAL(clicked()), this, SLOT(slotAddSource()));
191 connect(avtUI->nameBox, SIGNAL(returnPressed()), this, SLOT(slotAddSource()));
192 connect(avtUI->raBox, SIGNAL(returnPressed()), this, SLOT(slotAddSource()));
193 connect(avtUI->decBox, SIGNAL(returnPressed()), this, SLOT(slotAddSource()));
194 connect(avtUI->clearFieldsButton, SIGNAL(clicked()), this, SLOT(slotClearBoxes()));
195 connect(avtUI->longBox, SIGNAL(returnPressed()), this, SLOT(slotAdvanceFocus()));
196 connect(avtUI->latBox, SIGNAL(returnPressed()), this, SLOT(slotAdvanceFocus()));
197 connect(avtUI->PlotList, SIGNAL(currentRowChanged(int)), this, SLOT(slotHighlight(int)));
198 connect(avtUI->computeButton, SIGNAL(clicked()), this, SLOT(slotComputeAltitudeByTime()));
199 connect(avtUI->riseButton, SIGNAL(clicked()), this, SLOT(slotMarkRiseTime()));
200 connect(avtUI->setButton, SIGNAL(clicked()), this, SLOT(slotMarkSetTime()));
201 connect(avtUI->transitButton, SIGNAL(clicked()), this, SLOT(slotMarkTransitTime()));
202
203 // Set up the Rise/Set/Transit buttons' icons:
204
205 QPixmap redButton(100, 100);
207 QPainter p;
208 p.begin(&redButton);
210 QPen pen(Qt::red, 2);
211 p.setPen(pen);
212 QBrush brush(Qt::red);
213 p.setBrush(brush);
214 p.drawEllipse(15, 15, 80, 80);
215 p.end();
216
217 QPixmap blueButton(100, 100);
219 QPainter p1;
220 p1.begin(&blueButton);
222 QPen pen1(Qt::blue, 2);
223 p1.setPen(pen1);
225 p1.setBrush(brush1);
226 p1.drawEllipse(15, 15, 80, 80);
227 p1.end();
228
229 QPixmap greenButton(100, 100);
231 QPainter p2;
232 p2.begin(&greenButton);
234 QPen pen2(Qt::green, 2);
235 p2.setPen(pen2);
237 p2.setBrush(brush2);
238 p2.drawEllipse(15, 15, 80, 80);
239 p2.end();
240
241 avtUI->riseButton->setIcon(QIcon(redButton));
242 avtUI->setButton->setIcon(QIcon(blueButton));
243 avtUI->transitButton->setIcon(QIcon(greenButton));
244
245 setMouseTracking(true);
246}
247
249{
250 //WARNING: need to delete deleteList items!
251}
253{
254
255 SkyObject *obj = KStarsData::Instance()->objectNamed(avtUI->nameBox->text());
256 if (!obj)
257 {
258 QString name = FindDialog::processSearchText(avtUI->nameBox->text());
259 obj = KStarsData::Instance()->objectNamed(name);
260 }
261 if (obj)
262 {
263 //An object with the current name exists. If the object is not already
264 //in the avt list, add it.
265 bool found = false;
266 foreach (SkyObject *o, pList)
267 {
268 //if ( o->name() == obj->name() ) {
269 if (getObjectName(o, false) == getObjectName(obj, false))
270 {
271 found = true;
272 break;
273 }
274 }
275 if (!found)
276 processObject(obj);
277 }
278 else
279 {
280 //Object with the current name doesn't exist. It's possible that the
281 //user is trying to add a custom object. Assume this is the case if
282 //the RA and Dec fields are filled in.
283
284 if (!avtUI->nameBox->text().isEmpty() && !avtUI->raBox->text().isEmpty() && !avtUI->decBox->text().isEmpty())
285 {
286 bool okRA, okDec;
287 dms newRA = avtUI->raBox->createDms(&okRA);
288 dms newDec = avtUI->decBox->createDms(&okDec);
289 if (!okRA || !okDec)
290 return;
291
292 //If the epochName is blank (or any non-double), we assume J2000
293 //Otherwise, precess to J2000.
295 dt.setFromEpoch(getEpoch(avtUI->epochName->text()));
296 long double jd = dt.djd();
297 if (jd != J2000)
298 {
300 //ptest.precessFromAnyEpoch(jd, J2000);
301 ptest.catalogueCoord(jd);
302 newRA.setH(ptest.ra().Hours());
303 newDec.setD(ptest.dec().Degrees());
304 }
305
306 //make sure the coords do not already exist from another object
307 bool found = false;
308 foreach (SkyObject *p, pList)
309 {
310 //within an arcsecond?
311 if (fabs(newRA.Degrees() - p->ra().Degrees()) < 0.0003 &&
312 fabs(newDec.Degrees() - p->dec().Degrees()) < 0.0003)
313 {
314 found = true;
315 break;
316 }
317 }
318 if (!found)
319 {
320 SkyObject *obj = new SkyObject(8, newRA, newDec, 1.0, avtUI->nameBox->text());
321 deleteList.append(obj); //this object will be deleted when window is destroyed
322 processObject(obj);
323 }
324 }
325
326 //If the Ra and Dec boxes are filled, but the name field is empty,
327 //move input focus to nameBox. If either coordinate box is empty,
328 //move focus there
329 if (avtUI->nameBox->text().isEmpty())
330 {
331 avtUI->nameBox->QWidget::setFocus();
332 }
333 if (avtUI->raBox->text().isEmpty())
334 {
335 avtUI->raBox->QWidget::setFocus();
336 }
337 else
338 {
339 if (avtUI->decBox->text().isEmpty())
340 avtUI->decBox->QWidget::setFocus();
341 }
342 }
343
344 avtUI->View->update();
345}
346
347//Use find dialog to choose an object
349{
350 if (FindDialog::Instance()->exec() == QDialog::Accepted)
351 {
352 SkyObject *o = FindDialog::Instance()->targetObject();
353 processObject(o);
354 }
355
356 avtUI->View->update();
357 avtUI->View->replot();
358}
359
361{
362 if (!o)
363 return;
364
365 KSNumbers *num = new KSNumbers(getDate().djd());
366 KSNumbers *oldNum = nullptr;
367
368 //If the object is in the solar system, recompute its position for the given epochLabel
369 KStarsData *data = KStarsData::Instance();
370 if (o->isSolarSystem())
371 {
372 oldNum = new KSNumbers(data->ut().djd());
373 o->updateCoords(num, true, geo->lat(), data->lst(), true);
374 }
375
376 //precess coords to target epoch
377 o->updateCoordsNow(num);
378
379 // vector used for computing the points needed for drawing the graph
380 QVector<double> y(100), t(100);
381
382 //If this point is not in list already, add it to list
383 bool found(false);
384 foreach (SkyObject *p, pList)
385 {
386 if (o->ra().Degrees() == p->ra().Degrees() && o->dec().Degrees() == p->dec().Degrees())
387 {
388 found = true;
389 break;
390 }
391 }
392 if (found && !forceAdd)
393 {
394 qCWarning(KSTARS) << "This point is already displayed; It will not be duplicated.";
395 }
396 else
397 {
398 pList.append(o);
399
400 // make sure existing curves are thin and red:
401
402 for (int i = 0; i < avtUI->View->graphCount(); i++)
403 {
404 if (avtUI->View->graph(i)->pen().color() == Qt::white)
405 {
406 avtUI->View->graph(i)->setPen(QPen(Qt::red, 2));
407 }
408 }
409
410 // SET up the curve's name
411 avtUI->View->addGraph()->setName(o->name());
412
413 // compute the current graph:
414 // time range: 24h
415
416 int offset = 3;
417 for (double h = -12.0, i = 0; h <= 12.0; h += 0.25, i++)
418 {
419 y[i] = findAltitude(o, h);
420 if (y[i] > maxAlt)
421 maxAlt = y[i];
422 if (y[i] < minAlt)
423 minAlt = y[i];
424 t[i] = i * 900 + 43200;
425 avtUI->View->graph(avtUI->View->graphCount() - 1)->addData(t[i], y[i]);
426 }
427 avtUI->View->graph(avtUI->View->graphCount() - 1)->setPen(QPen(Qt::white, 3));
428
429 // Go into initial state: without Zoom/Pan
430 avtUI->View->xAxis->setRange(43200, 129600);
431 avtUI->View->xAxis2->setRange(61200, 147600);
432 if (abs(minAlt) > maxAlt)
433 maxAlt = abs(minAlt);
434 else
435 minAlt = -maxAlt;
436
437 avtUI->View->yAxis->setRange(minAlt - offset, maxAlt + offset);
438
439 // Update background coordinates:
440 background->topLeft->setCoords(avtUI->View->xAxis->range().lower, avtUI->View->yAxis->range().upper);
441 background->bottomRight->setCoords(avtUI->View->xAxis->range().upper, avtUI->View->yAxis->range().lower);
442
443 avtUI->View->replot();
444
445 avtUI->PlotList->addItem(getObjectName(o));
446 avtUI->PlotList->setCurrentRow(avtUI->PlotList->count() - 1);
447 avtUI->raBox->show(o->ra());
448 avtUI->decBox->show(o->dec());
449 avtUI->nameBox->setText(getObjectName(o));
450
451 //Set epochName to epoch shown in date tab
452 avtUI->epochName->setText(QString().setNum(getDate().epoch()));
453 }
454 //qCDebug() << "Currently, there are " << avtUI->View->graphCount() << " objects displayed.";
455
456 //restore original position
457 if (o->isSolarSystem())
458 {
459 o->updateCoords(oldNum, true, data->geo()->lat(), data->lst(), true);
460 delete oldNum;
461 }
462 o->EquatorialToHorizontal(data->lst(), data->geo()->lat());
463 delete num;
464}
465
466double AltVsTime::findAltitude(SkyPoint *p, double hour)
467{
468 hour += 24.0 * DayOffset;
469
470 //getDate converts the user-entered local time to UT
471 KStarsDateTime ut = getDate().addSecs(hour * 3600.0);
472
473 CachingDms LST = geo->GSTtoLST(ut.gst());
474 p->EquatorialToHorizontal(&LST, geo->lat());
475 return p->alt().Degrees();
476}
477
479{
480 if (row < 0)
481 return;
482
483 int rowIndex = 0;
484 //highlight the curve of the selected object
485 for (int i = 0; i < avtUI->View->graphCount(); i++)
486 {
487 if (i == row)
488 rowIndex = row;
489 else
490 {
491 avtUI->View->graph(i)->setPen(QPen(Qt::red, 2));
492 avtUI->View->graph(i)->setLayer("main");
493 }
494 }
495 avtUI->View->graph(rowIndex)->setPen(QPen(Qt::white, 3));
496 avtUI->View->graph(rowIndex)->setLayer("currentCurveLayer");
497 avtUI->View->update();
498 avtUI->View->replot();
499
500 if (row >= 0 && row < pList.size())
501 {
502 SkyObject *p = pList.at(row);
503 avtUI->raBox->show(p->ra());
504 avtUI->decBox->show(p->dec());
505 avtUI->nameBox->setText(avtUI->PlotList->currentItem()->text());
506 }
507
508 SkyObject *selectedObject = KStarsData::Instance()->objectNamed(avtUI->nameBox->text());
509 const KStarsDateTime &ut = KStarsData::Instance()->ut();
510 if (selectedObject)
511 {
512 QTime rt = selectedObject->riseSetTime(ut, geo, true); //true = use rise time
513 if (rt.isValid() == false)
514 {
515 avtUI->riseButton->setEnabled(false);
516 avtUI->setButton->setEnabled(false);
517 }
518 else
519 {
520 avtUI->riseButton->setEnabled(true);
521 avtUI->setButton->setEnabled(true);
522 }
523 }
524}
525
527{
528 QCPRange aux = avtUI->View->xAxis2->range();
529 avtUI->View->xAxis->setRange(aux -= 18000);
530 avtUI->View->xAxis2->setRange(range.bounded(61200, 147600));
531 // if ZOOM is detected then remove the gold lines that indicate current position:
532 if (avtUI->View->xAxis->range().size() != 86400)
533 {
534 // Refresh the background:
535 background->setScaled(false);
536 background->setScaled(true, Qt::IgnoreAspectRatio);
537 background->setPixmap(*gradient);
538
539 avtUI->View->update();
540 avtUI->View->replot();
541 }
542}
543
545{
546 int offset = 3;
547 avtUI->View->yAxis->setRange(range.bounded(minAlt - offset, maxAlt + offset));
548}
549
551{
552 //Do we need this?
553 Q_UNUSED(dataIndex);
554
555 if (event->button() == Qt::RightButton)
556 {
558 if (plottable)
559 {
560 double x = avtUI->View->xAxis->pixelToCoord(event->localPos().x());
561 double y = avtUI->View->yAxis->pixelToCoord(event->localPos().y());
562
563 QCPGraph *graph = qobject_cast<QCPGraph *>(plottable);
564
565 if (graph)
566 {
567 double yValue = y;
568 double xValue = x;
569
570 // Compute time value:
571 QTime localTime(0, 0, 0, 0);
572 QTime localSiderealTime(5, 0, 0, 0);
573
574 localTime = localTime.addSecs(int(xValue));
575 localSiderealTime = localSiderealTime.addSecs(int(xValue));
576
578 QToolTip::showText(event->globalPos(),
579 i18n("<table>"
580 "<tr>"
581 "<th colspan=\"2\">%1</th>"
582 "</tr>"
583 "<tr>"
584 "<td>LST: </td>"
585 "<td>%3</td>"
586 "</tr>"
587 "<tr>"
588 "<td>LT: </td>"
589 "<td>%2</td>"
590 "</tr>"
591 "<tr>"
592 "<td>Altitude: </td>"
593 "<td>%4</td>"
594 "</tr>"
595 "</table>",
596 graph->name().isEmpty() ? "???" : graph->name(),
597 localTime.toString(),
598 localSiderealTime.toString(),
599 QString::number(yValue, 'f', 2) + ' ' + QChar(176)),
600 avtUI->View, avtUI->View->rect());
601 }
602 }
603 }
604}
605
606//move input focus to the next logical widget
608{
609 if (sender()->objectName() == QString("nameBox"))
610 avtUI->addButton->setFocus();
611 if (sender()->objectName() == QString("raBox"))
612 avtUI->decBox->setFocus();
613 if (sender()->objectName() == QString("decbox"))
614 avtUI->addButton->setFocus();
615 if (sender()->objectName() == QString("longBox"))
616 avtUI->latBox->setFocus();
617 if (sender()->objectName() == QString("latBox"))
618 avtUI->updateButton->setFocus();
619}
620
622{
623 pList.clear();
624 //Need to delete the pointers in deleteList
625 while (!deleteList.isEmpty())
626 delete deleteList.takeFirst();
627
628 avtUI->PlotList->clear();
629 avtUI->nameBox->clear();
630 avtUI->raBox->clear();
631 avtUI->decBox->clear();
632 avtUI->epochName->clear();
633 // remove all graphs from the plot:
634 avtUI->View->clearGraphs();
635 // we remove all the dots (rise/set/transit) from the chart
636 // without removing the background image
637 int indexItem = 0, noItems = avtUI->View->itemCount();
638 QCPAbstractItem *item;
639 QCPItemPixmap *background;
640 // remove every item at a time:
641 while (noItems > 1 && indexItem < noItems)
642 {
643 // test if the current item is the background:
644 item = avtUI->View->item(indexItem);
645 background = qobject_cast<QCPItemPixmap *>(item);
646 if (background)
647 indexItem++;
648 else
649 {
650 // if not, then remove this item:
651 avtUI->View->removeItem(indexItem);
652 noItems--;
653 }
654 }
655 // update & replot the chart:
656 avtUI->View->update();
657 avtUI->View->replot();
658}
659
661{
662 avtUI->nameBox->clear();
663 avtUI->raBox->clear();
664 avtUI->decBox->clear();
665 avtUI->epochName->clear();
666}
667
669{
670 if (avtUI->PlotList->currentRow() < 0)
671 return;
672
673 SkyObject *selectedObject = pList.at(avtUI->PlotList->currentRow());
674 if (selectedObject == nullptr)
675 {
676 if (avtUI->PlotList->currentItem())
677 qCWarning(KSTARS) << "slotComputeAltitudeByTime: Unable to find" << avtUI->PlotList->currentItem()->text();
678 else
679 {
680 qCWarning(KSTARS) << "slotComputeAltitudeByTime: Unable to find item";
681 }
682 return;
683 }
684
685 // Get Local Date & Time
686 KStarsDateTime lt = KStarsDateTime(avtUI->DateWidget->date(), avtUI->timeSpin->time(), Qt::LocalTime);
687 // Convert to UT
688 KStarsDateTime ut = geo->LTtoUT(lt);
689 // Get LST from GST
690 CachingDms LST = geo->GSTtoLST(ut.gst());
691 SkyObject *tempObject = selectedObject->clone();
692 // Update coords
693 KSNumbers num(ut.djd());
694 tempObject->updateCoords(&num, true, geo->lat(), &LST);
695 // Find Horizontal coordinates from LST & Latitude
696 selectedObject->EquatorialToHorizontal(&LST, geo->lat());
697
698 // Set altitude
699 avtUI->altitudeBox->setText(selectedObject->altRefracted().toDMSString(true));
700
701 delete (tempObject);
702}
703
705{
706 if (avtUI->PlotList->currentRow() < 0)
707 return;
708
709 const KStarsDateTime &ut = KStarsData::Instance()->ut();
710 SkyObject *selectedObject = pList.at(avtUI->PlotList->currentRow());
711 if (selectedObject == nullptr)
712 {
713 qCWarning(KSTARS) << "Mark Rise Time: Unable to find" << avtUI->PlotList->currentItem()->text();
714 return;
715 }
716
718 // check if at least one graph exists in the plot
719 if (avtUI->View->graphCount() > 0)
720 {
721 double time = 0;
722 double hours, minutes;
723
724 QCPGraph *selectedGraph = avtUI->View->graph(avtUI->PlotList->currentRow());
725
726 QTime rt = selectedObject->riseSetTime(ut, geo, true); //true = use rise time
727 // mark the Rise time with a solid red circle
728 if (rt.isValid() && selectedGraph)
729 {
730 hours = rt.hour();
731 minutes = rt.minute();
732 if (hours < 12)
733 hours += 24;
734 time = hours * 3600 + minutes * 60;
735 riseTimeTracer = new QCPItemTracer(avtUI->View);
736 riseTimeTracer->setLayer("markersLayer");
737 riseTimeTracer->setGraph(selectedGraph);
738 riseTimeTracer->setInterpolating(true);
740 riseTimeTracer->setPen(QPen(Qt::red));
741 riseTimeTracer->setBrush(Qt::red);
742 riseTimeTracer->setSize(10);
743 riseTimeTracer->setGraphKey(time);
744 riseTimeTracer->setVisible(true);
745 avtUI->View->update();
746 avtUI->View->replot();
747 }
748 }
749}
750
752{
753 if (avtUI->PlotList->currentRow() < 0)
754 return;
755
756 const KStarsDateTime &ut = KStarsData::Instance()->ut();
757 SkyObject *selectedObject = pList.at(avtUI->PlotList->currentRow());
758 if (selectedObject == nullptr)
759 {
760 qCWarning(KSTARS) << "Mark Set Time: Unable to find" << avtUI->PlotList->currentItem()->text();
761 return;
762 }
764 // check if at least one graph exists in the plot
765 if (avtUI->View->graphCount() > 0)
766 {
767 double time = 0;
768 double hours, minutes;
769
770 QCPGraph *selectedGraph = avtUI->View->graph(avtUI->PlotList->currentRow());
771
772 QTime rt = selectedObject->riseSetTime(ut, geo, true); //true = use rise time
773 //If set time is before rise time, use set time for tomorrow
774 QTime st = selectedObject->riseSetTime(ut, geo, false); //false = use set time
775 if (st < rt)
776 st = selectedObject->riseSetTime(ut.addDays(1), geo, false); //false = use set time
777 // mark the Set time with a solid blue circle
778 if (rt.isValid())
779 {
780 hours = st.hour();
781 minutes = st.minute();
782 if (hours < 12)
783 hours += 24;
784 time = hours * 3600 + minutes * 60;
785 setTimeTracer = new QCPItemTracer(avtUI->View);
786 setTimeTracer->setLayer("markersLayer");
787 setTimeTracer->setGraph(selectedGraph);
788 setTimeTracer->setInterpolating(true);
790 setTimeTracer->setPen(QPen(Qt::blue));
791 setTimeTracer->setBrush(Qt::blue);
792 setTimeTracer->setSize(10);
793 setTimeTracer->setGraphKey(time);
794 setTimeTracer->setVisible(true);
795 avtUI->View->update();
796 avtUI->View->replot();
797 }
798 }
799}
800
802{
803 if (avtUI->PlotList->currentRow() < 0)
804 return;
805
806 const KStarsDateTime &ut = KStarsData::Instance()->ut();
807 SkyObject *selectedObject = pList.at(avtUI->PlotList->currentRow());
808 if (selectedObject == nullptr)
809 {
810 qCWarning(KSTARS) << "Mark Transit Time: Unable to find" << avtUI->PlotList->currentItem()->text();
811 return;
812 }
814 // check if at least one graph exists in the plot
815 if (avtUI->View->graphCount() > 0)
816 {
817 double time = 0;
818 double hours, minutes;
819
820 QCPGraph *selectedGraph = avtUI->View->graph(avtUI->PlotList->currentRow());
821
822 QTime rt = selectedObject->riseSetTime(ut, geo, true); //true = use rise time
823 //If transit time is before rise time, use transit time for tomorrow
824 QTime tt = selectedObject->transitTime(ut, geo);
825
826 if (tt < rt)
827 tt = selectedObject->transitTime(ut.addDays(1), geo);
828 // mark the Transit time with a solid green circle
829 hours = tt.hour();
830 minutes = tt.minute();
831 if (hours < 12)
832 hours += 24;
833 time = hours * 3600 + minutes * 60;
834 transitTimeTracer = new QCPItemTracer(avtUI->View);
835 transitTimeTracer->setLayer("markersLayer");
837 transitTimeTracer->setInterpolating(true);
840 transitTimeTracer->setBrush(Qt::green);
841 transitTimeTracer->setSize(10);
842 transitTimeTracer->setGraphKey(time);
843 transitTimeTracer->setVisible(true);
844 avtUI->View->update();
845 avtUI->View->replot();
846 }
847}
848
850{
851 //Determine the time of sunset and sunrise for the desired date and location
852 //expressed as doubles, the fraction of a full day.
853
854 /* KSAlmanac ksal(getDate(), geo); */
855
856 /* ... */
857}
858
859//FIXME
860/*
861void AltVsTime::mouseOverLine(QMouseEvent *event){
862 // Get the mouse position's coordinates relative to axes:
863 double x = avtUI->View->xAxis->pixelToCoord(event->pos().x());
864 double y = avtUI->View->yAxis->pixelToCoord(event->pos().y());
865 // Save the actual values:
866 double yValue = y;
867 double xValue = x;
868 // The offset used for the Y axis: top/bottom
869 int offset = 3;
870 // Compute the Y axis maximum value:
871 int yAxisMaxValue = maxAlt + offset;
872 // Compute the X axis minimum and maximum values:
873 int xAxisMinValue = 43200;
874 int xAxisMaxValue = 129600;
875 // Ignore the upper and left margins:
876 y = yAxisMaxValue - y;
877 x -= xAxisMinValue;
878 // We make a copy to gradient background in order to have one set of lines at a time:
879 // Otherwise, the chart would have been covered by lines
880 QPixmap copy = gradient->copy(gradient->rect());
881 // If ZOOM is not active, then draw the gold lines that indicate current mouse pisition:
882 if(avtUI->View->xAxis->range().size() == 86400){
883 QPainter p;
884
885 p.begin(&copy);
886 p.setPen( QPen( QBrush("gold"), 2, Qt::SolidLine ) );
887
888 // Get the gradient background's width and height:
889 int pW = gradient->rect().width();
890 int pH = gradient->rect().height();
891
892 // Compute the real coordinates within the chart:
893 y = (y*pH/2)/yAxisMaxValue;
894 x = (x*pW)/(xAxisMaxValue-xAxisMinValue);
895
896 // Draw the horizontal line (altitude):
897 p.drawLine( QLineF( 0.5, y, avtUI->View->rect().width()-0.5,y ) );
898 // Draw the altitude value:
899 p.setPen( QPen( QBrush("gold"), 3, Qt::SolidLine ) );
900 p.drawText( 25, y + 15, QString::number(yValue,'f',2) + QChar(176) );
901 p.setPen( QPen( QBrush("gold"), 1, Qt::SolidLine ) );
902 // Draw the vertical line (time):
903 p.drawLine( QLineF( x, 0.5, x, avtUI->View->rect().height()-0.5 ) );
904 // Compute and draw the time value:
905 QTime localTime(0,0,0,0);
906 localTime = localTime.addSecs(int(xValue));
907 p.save();
908 p.translate( x + 10, pH - 20 );
909 p.rotate(-90);
910 p.setPen( QPen( QBrush("gold"), 3, Qt::SolidLine ) );
911 p.drawText( 5, 5, QLocale().toString( localTime, QLocale::ShortFormat ) ); // short format necessary to avoid false time-zone labeling
912 p.restore();
913 p.end();
914 }
915 // Refresh the background:
916 background->setScaled(false);
917 background->setScaled(true, Qt::IgnoreAspectRatio);
918 background->setPixmap(copy);
919
920 avtUI->View->update();
921 avtUI->View->replot();
922}
923*/
924
926{
927 double x = avtUI->View->xAxis->pixelToCoord(event->localPos().x());
928 double y = avtUI->View->yAxis->pixelToCoord(event->localPos().y());
929 QCPAbstractPlottable *abstractGraph = avtUI->View->plottableAt(event->pos(), false);
931
932 if (x > avtUI->View->xAxis->range().lower && x < avtUI->View->xAxis->range().upper)
933 if (y > avtUI->View->yAxis->range().lower && y < avtUI->View->yAxis->range().upper)
934 {
935 if (graph)
936 {
937 double yValue = y;
938 double xValue = x;
939
940 // Compute time value:
941 QTime localTime(0, 0, 0, 0);
942 QTime localSiderealTime(5, 0, 0, 0);
943
944 localTime = localTime.addSecs(int(xValue));
945 localSiderealTime = localSiderealTime.addSecs(int(xValue));
946
948 QToolTip::showText(event->globalPos(),
949 i18n("<table>"
950 "<tr>"
951 "<th colspan=\"2\">%1</th>"
952 "</tr>"
953 "<tr>"
954 "<td>LST: </td>"
955 "<td>%3</td>"
956 "</tr>"
957 "<tr>"
958 "<td>LT: </td>"
959 "<td>%2</td>"
960 "</tr>"
961 "<tr>"
962 "<td>Altitude: </td>"
963 "<td>%4</td>"
964 "</tr>"
965 "</table>",
966 graph->name().isEmpty() ? "???" : graph->name(),
967 localTime.toString(), localSiderealTime.toString(),
968 QString::number(yValue, 'f', 2) + ' ' + QChar(176)),
969 avtUI->View, avtUI->View->rect());
970 }
971 else
973 }
974
975 avtUI->View->update();
976 avtUI->View->replot();
977}
978
980{
981 KStarsData *data = KStarsData::Instance();
983 KSNumbers *num = new KSNumbers(today.djd());
984 KSNumbers *oldNum = nullptr;
985 CachingDms LST = geo->GSTtoLST(today.gst());
986
987 //First determine time of sunset and sunrise
989 // Determine dawn/dusk time and min/max sun elevation
990 setDawnDusk();
991
992 for (int i = 0; i < pList.count(); ++i)
993 {
994 SkyObject *o = pList.at(i);
995 if (o)
996 {
997 //If the object is in the solar system, recompute its position for the given date
998 if (o->isSolarSystem())
999 {
1000 oldNum = new KSNumbers(data->ut().djd());
1001 o->updateCoords(num, true, geo->lat(), &LST, true);
1002 }
1003
1004 //precess coords to target epoch
1005 o->updateCoordsNow(num);
1006
1007 //update pList entry
1008 pList.replace(i, o);
1009
1010 // We are creating a new data set (time, altitude) for the new date:
1013 // compute the new graph values:
1014 // time range: 24h
1015 int offset = 3;
1016 for (double h = -12.0, i = 0; h <= 12.0; h += 0.25, i++)
1017 {
1020 if (point_altitudeValue > maxAlt)
1021 maxAlt = point_altitudeValue;
1022 if (point_altitudeValue < minAlt)
1023 minAlt = point_altitudeValue;
1024 point_timeValue = i * 900 + 43200;
1025 time_dataSet.push_back(point_timeValue);
1026 }
1027
1028 // Replace graph data set:
1029 avtUI->View->graph(i)->setData(time_dataSet, altitude_dataSet);
1030
1031 // Go into initial state: without Zoom/Pan
1032 avtUI->View->xAxis->setRange(43200, 129600);
1033 avtUI->View->xAxis2->setRange(61200, 147600);
1034
1035 // Center the altitude axis in 0 value:
1036 if (abs(minAlt) > maxAlt)
1037 maxAlt = abs(minAlt);
1038 else
1039 minAlt = -maxAlt;
1040 avtUI->View->yAxis->setRange(minAlt - offset, maxAlt + offset);
1041
1042 // Update background coordinates:
1043 background->topLeft->setCoords(avtUI->View->xAxis->range().lower, avtUI->View->yAxis->range().upper);
1044 background->bottomRight->setCoords(avtUI->View->xAxis->range().upper, avtUI->View->yAxis->range().lower);
1045
1046 // Redraw the plot:
1047 avtUI->View->replot();
1048
1049 //restore original position
1050 if (o->isSolarSystem())
1051 {
1052 o->updateCoords(oldNum, true, data->geo()->lat(), data->lst());
1053 delete oldNum;
1054 oldNum = nullptr;
1055 }
1056 o->EquatorialToHorizontal(data->lst(), data->geo()->lat());
1057 }
1058 else //assume unfound object is a custom object
1059 {
1060 pList.at(i)->updateCoordsNow(num); //precess to desired epoch
1061
1062 // We are creating a new data set (time, altitude) for the new date:
1065 // compute the new graph values:
1066 // time range: 24h
1067 int offset = 3;
1068 for (double h = -12.0, i = 0; h <= 12.0; h += 0.25, i++)
1069 {
1070 point_altitudeValue = findAltitude(pList.at(i), h);
1072 if (point_altitudeValue > maxAlt)
1073 maxAlt = point_altitudeValue;
1074 if (point_altitudeValue < minAlt)
1075 minAlt = point_altitudeValue;
1076 point_timeValue = i * 900 + 43200;
1077 time_dataSet.push_back(point_timeValue);
1078 }
1079
1080 // Replace graph data set:
1081 avtUI->View->graph(i)->setData(time_dataSet, altitude_dataSet);
1082
1083 // Go into initial state: without Zoom/Pan
1084 avtUI->View->xAxis->setRange(43200, 129600);
1085 avtUI->View->xAxis2->setRange(61200, 147600);
1086
1087 // Center the altitude axis in 0 value:
1088 if (abs(minAlt) > maxAlt)
1089 maxAlt = abs(minAlt);
1090 else
1091 minAlt = -maxAlt;
1092 avtUI->View->yAxis->setRange(minAlt - offset, maxAlt + offset);
1093
1094 // Update background coordinates:
1095 background->topLeft->setCoords(avtUI->View->xAxis->range().lower, avtUI->View->yAxis->range().upper);
1096 background->bottomRight->setCoords(avtUI->View->xAxis->range().upper, avtUI->View->yAxis->range().lower);
1097
1098 // Redraw the plot:
1099 avtUI->View->replot();
1100 }
1101 }
1102
1103 if (getDate().time().hour() > 12)
1104 DayOffset = 1;
1105 else
1106 DayOffset = 0;
1107
1108 setLSTLimits();
1109 slotHighlight(avtUI->PlotList->currentRow());
1110 avtUI->View->update();
1111
1112 delete num;
1113}
1114
1116{
1118 if (ld->exec() == QDialog::Accepted)
1119 {
1120 GeoLocation *newGeo = ld->selectedCity();
1121 if (newGeo)
1122 {
1123 geo = newGeo;
1124 avtUI->latBox->show(geo->lat());
1125 avtUI->longBox->show(geo->lng());
1126 }
1127 }
1128 delete ld;
1129}
1130
1131// FIXME: should we remove this method?
1133{
1134 /*
1135 //UT at noon on target date
1136 KStarsDateTime ut = getDate().addSecs(((double)DayOffset + 0.5)*86400.);
1137
1138 dms lst = geo->GSTtoLST(ut.gst());
1139 double h1 = lst.Hours();
1140 if(h1 > 12.0)
1141 h1 -= 24.0;
1142 double h2 = h1 + 24.0;
1143 avtUI->View->setSecondaryLimits(h1, h2, -90.0, 90.0);
1144 */
1145}
1146
1148{
1150 if (dt.time() > QTime(12, 0, 0))
1151 dt = dt.addDays(1);
1152 avtUI->DateWidget->setDate(dt.date());
1153}
1154
1155void AltVsTime::drawGradient()
1156{
1157 // Things needed for Gradient:
1159 GeoLocation *geoLoc = KStarsData::Instance()->geo();
1160 QDateTime midnight = QDateTime(dtt.date(), QTime());
1162
1163 // Variables needed for Gradient:
1164 double SunRise, SunSet, Dawn, Dusk, SunMinAlt, SunMaxAlt;
1165 double MoonRise, MoonSet, MoonIllum;
1166
1167 KSAlmanac ksal(utt, geoLoc);
1168
1169 // Get the values:
1170 SunRise = ksal.getSunRise();
1171 SunSet = ksal.getSunSet();
1172 SunMaxAlt = ksal.getSunMaxAlt();
1173 SunMinAlt = ksal.getSunMinAlt();
1174 MoonRise = ksal.getMoonRise();
1175 MoonSet = ksal.getMoonSet();
1176 MoonIllum = ksal.getMoonIllum();
1177 Dawn = ksal.getDawnAstronomicalTwilight();
1178 Dusk = ksal.getDuskAstronomicalTwilight();
1179
1180 gradient = new QPixmap(avtUI->View->rect().width(), avtUI->View->rect().height());
1181
1182 QPainter p;
1183
1184 p.begin(gradient);
1186 p.setRenderHint(QPainter::Antialiasing, kPW->antialiasing());
1187 p.fillRect(gradient->rect(), kPW->backgroundColor());
1188
1189 p.setClipRect(gradient->rect());
1190 p.setClipping(true);
1191
1192 int pW = gradient->rect().width();
1193 int pH = gradient->rect().height();
1194
1195 QColor SkyColor(0, 100, 200);
1196 // TODO
1197 // if( Options::darkAppColors() )
1198 // SkyColor = QColor( 200, 0, 0 ); // use something red, visible through a red filter
1199
1200 // Draw gradient representing lunar interference in the sky
1201 if (MoonIllum > 0.01) // do this only if Moon illumination is reasonable so it's important
1202 {
1203 int moonrise = int(pW * (0.5 + MoonRise));
1204 int moonset = int(pW * (MoonSet - 0.5));
1205 if (moonset < 0)
1206 moonset += pW;
1207 if (moonrise > pW)
1208 moonrise -= pW;
1209 int moonalpha = int(10 + MoonIllum * 130);
1210 int fadewidth =
1211 pW *
1212 0.01; // pW * fraction of day to fade the moon brightness over (0.01 corresponds to roughly 15 minutes, 0.007 to 10 minutes), both before and after actual set.
1213 QColor MoonColor(255, 255, 255, moonalpha);
1214
1215 if (moonset < moonrise)
1216 {
1219 grad.setColorAt(0, MoonColor);
1220 grad.setColorAt(1, Qt::transparent);
1221 p.fillRect(QRectF(0.0, 0.0, moonset + fadewidth, pH),
1222 grad); // gradient should be padded until moonset - fadewidth (see QLinearGradient docs)
1223 grad.setStart(QPointF(moonrise + fadewidth, 0.0));
1224 grad.setFinalStop(QPointF(moonrise - fadewidth, 0.0));
1226 }
1227 else
1228 {
1229 qreal opacity = p.opacity();
1230 p.setOpacity(opacity / 4);
1234 grad.setColorAt(0, MoonColor);
1235 grad.setColorAt(1, Qt::transparent);
1236 p.fillRect(QRectF(0.0, 0.0, moonrise + fadewidth, pH), grad);
1237 grad.setStart(QPointF(moonset - fadewidth, 0.0));
1238 grad.setFinalStop(QPointF(moonset + fadewidth, 0.0));
1239 p.fillRect(QRectF(moonset - fadewidth, 0.0, pW - moonset, pH), grad);
1240 p.setOpacity(opacity);
1241 }
1242 }
1243
1244 //draw daytime sky if the Sun rises for the current date/location
1245 if (SunMaxAlt > -18.0)
1246 {
1247 //Display centered on midnight, so need to modulate dawn/dusk by 0.5
1248 int rise = int(pW * (0.5 + SunRise));
1249 int set = int(pW * (SunSet - 0.5));
1250 int da = int(pW * (0.5 + Dawn));
1251 int du = int(pW * (Dusk - 0.5));
1252
1253 if (SunMinAlt > 0.0)
1254 {
1255 // The sun never set and the sky is always blue
1256 p.fillRect(rect(), SkyColor);
1257 }
1258 else if (SunMaxAlt < 0.0 && SunMinAlt < -18.0)
1259 {
1260 // The sun never rise but the sky is not completely dark
1262
1264 gradStartColor.setAlpha((1 - (SunMaxAlt / -18.0)) * 255);
1265
1266 grad.setColorAt(0, gradStartColor);
1267 grad.setColorAt(1, Qt::transparent);
1268 p.fillRect(QRectF(0.0, 0.0, du, pH), grad);
1269 grad.setStart(QPointF(pW, 0.0));
1270 grad.setFinalStop(QPointF(da, 0.0));
1271 p.fillRect(QRectF(da, 0.0, pW, pH), grad);
1272 }
1273 else if (SunMaxAlt < 0.0 && SunMinAlt > -18.0)
1274 {
1275 // The sun never rise but the sky is NEVER completely dark
1277
1279 gradStartEndColor.setAlpha((1 - (SunMaxAlt / -18.0)) * 255);
1281 gradMidColor.setAlpha((1 - (SunMinAlt / -18.0)) * 255);
1282
1283 grad.setColorAt(0, gradStartEndColor);
1284 grad.setColorAt(0.5, gradMidColor);
1285 grad.setColorAt(1, gradStartEndColor);
1286 p.fillRect(QRectF(0.0, 0.0, pW, pH), grad);
1287 }
1288 else if (Dawn < 0.0)
1289 {
1290 // The sun sets and rises but the sky is never completely dark
1291 p.fillRect(0, 0, set, int(0.5 * pH), SkyColor);
1292 p.fillRect(rise, 0, pW, int(0.5 * pH), SkyColor);
1293
1295
1297 gradMidColor.setAlpha((1 - (SunMinAlt / -18.0)) * 255);
1298
1299 grad.setColorAt(0, SkyColor);
1300 grad.setColorAt(0.5, gradMidColor);
1301 grad.setColorAt(1, SkyColor);
1302 p.fillRect(QRectF(set, 0.0, rise - set, pH), grad);
1303 }
1304 else
1305 {
1306 p.fillRect(0, 0, set, pH, SkyColor);
1307 p.fillRect(rise, 0, pW, pH, SkyColor);
1308
1310 grad.setColorAt(0, SkyColor);
1311 grad.setColorAt(
1312 1,
1313 Qt::transparent); // FIXME?: The sky appears black well before the actual end of twilight if the gradient is too slow (eg: latitudes above arctic circle)
1314 p.fillRect(QRectF(set, 0.0, du - set, pH), grad);
1315
1316 grad.setStart(QPointF(rise, 0.0));
1317 grad.setFinalStop(QPointF(da, 0.0));
1318 p.fillRect(QRectF(da, 0.0, rise - da, pH), grad);
1319 }
1320 }
1321
1322 p.fillRect(0, int(0.5 * pH), pW, int(0.5 * pH), KStarsData::Instance()->colorScheme()->colorNamed("HorzColor"));
1323
1324 p.setClipping(false);
1325
1326 // Add vertical line indicating "now"
1327 // Convert the current system clock time to the TZ corresponding to geo
1328 QTime t = geoLoc->UTtoLT(KStarsDateTime::currentDateTimeUtc()).time();
1329 double x = 12.0 + t.hour() + t.minute() / 60.0 + t.second() / 3600.0;
1330
1331 while (x > 24.0)
1332 x -= 24.0;
1333
1334 // Convert to screen pixel coords
1335 int ix = int(x * pW / 24.0);
1336
1337 p.setPen(QPen(QBrush("white"), 2.0, Qt::DotLine));
1338 p.drawLine(ix, 0, ix, pH);
1339
1340 QFont largeFont = p.font();
1341
1342 largeFont.setPointSize(largeFont.pointSize() + 1);
1343 // Label this vertical line with the current time
1344 p.save();
1345 p.setFont(largeFont);
1346 p.translate(ix + 15, pH - 20);
1347 p.rotate(-90);
1348 // Short format necessary to avoid false time-zone labeling
1350 p.restore();
1351 p.end();
1352}
1353
1355{
1356 //convert midnight local time to UT:
1357 QDateTime lt(avtUI->DateWidget->date(), QTime());
1358 return geo->LTtoUT(KStarsDateTime(lt));
1359}
1360
1362{
1363 //If Epoch field not a double, assume J2000
1364 bool ok;
1365 double epoch = eName.toDouble(&ok);
1366 if (!ok)
1367 {
1368 qCWarning(KSTARS) << "Invalid Epoch. Assuming 2000.0.";
1369 return 2000.0;
1370 }
1371 return epoch;
1372}
1373
1374void AltVsTime::setDawnDusk()
1375{
1376 /* TODO */
1377
1378 /*
1379 KSAlmanac almanac(getDate(), geo);
1380
1381 avtUI->View->setDawnDuskTimes(almanac.getDawnAstronomicalTwilight(), almanac.getDuskAstronomicalTwilight());
1382 avtUI->View->setMinMaxSunAlt(almanac.getSunMinAlt(), almanac.getSunMaxAlt());
1383 */
1384
1385 /* ... */
1386}
1387
1389{
1390 QPainter p; // Our painter object
1391 QPrinter printer; // Our printer object
1392 QString str_legend; // Text legend
1393 int text_height = 200; // Height of legend text zone in points
1394 QSize plot_size; // Initial plot widget size
1395 QFont plot_font; // Initial plot widget font
1396 int plot_font_size; // Initial plot widget font size
1397
1398 // Set printer resolution to 300 dpi
1399 printer.setResolution(300);
1400
1401 // Open print dialog
1402 //QPointer<QPrintDialog> dialog( KdePrint::createPrintDialog( &printer, this ) );
1403 //QPointer<QPrintDialog> dialog( &printer, this );
1404 QPrintDialog dialog(&printer, this);
1405 dialog.setWindowTitle(i18nc("@title:window", "Print elevation vs time plot"));
1406 if (dialog.exec() == QDialog::Accepted)
1407 {
1408 // Change mouse cursor
1410
1411 // Save plot widget font
1412 plot_font = avtUI->View->font();
1413 // Save plot widget font size
1414 plot_font_size = plot_font.pointSize();
1415 // Save calendar widget size
1416 plot_size = avtUI->View->size();
1417
1418 // Set text legend
1419 str_legend = i18n("Elevation vs. Time Plot");
1420 str_legend += '\n';
1421 str_legend += geo->fullName();
1422 str_legend += " - ";
1423 str_legend += avtUI->DateWidget->date().toString("dd/MM/yyyy");
1424
1425 // Create a rectangle for legend text zone
1426 QRect text_rect(0, 0, printer.width(), text_height);
1427
1428 // Increase plot widget font size so it looks good in 300 dpi
1429 plot_font.setPointSize(plot_font_size * 2.5);
1430 avtUI->View->setFont(plot_font);
1431 // Increase plot widget size to fit the entire page
1432 avtUI->View->resize(printer.width(), printer.height() - text_height);
1433
1434 // Create a pixmap and render plot widget into it
1435 QPixmap pixmap(avtUI->View->size());
1436 avtUI->View->render(&pixmap);
1437
1438 // Begin painting on printer
1439 p.begin(&printer);
1440 // Draw legend
1442 // Draw plot widget
1443 p.drawPixmap(0, text_height, pixmap);
1444 // Ending painting
1445 p.end();
1446
1447 // Restore plot widget font size
1448 plot_font.setPointSize(plot_font_size);
1449 avtUI->View->setFont(plot_font);
1450 // Restore calendar widget size
1451 avtUI->View->resize(plot_size);
1452
1453 // Restore mouse cursor
1455 }
1456 //delete dialog;
1457}
1458
1460{
1462 if (o->name() == "star")
1463 {
1464 StarObject *s = (StarObject *)o;
1465
1466 // JM: Enable HD Index stars to be added to the observing list.
1467 if (s->getHDIndex() != 0)
1469 }
1470 else
1471 finalObjectName = translated ? o->translatedName() : o->name();
1472
1473 return finalObjectName;
1474}
AltVsTime(QWidget *parent=nullptr)
Constructor.
Definition altvstime.cpp:41
void slotAddSource()
Add an object to the list of displayed objects, according to the data entered in the edit boxes.
void slotHighlight(int)
Update the plot to highlight the altitude curve of the objects which is highlighted in the listbox.
double findAltitude(SkyPoint *p, double hour)
Determine the altitude coordinate of a SkyPoint, given an hour of the day.
void slotPrint()
Print plot widget.
void slotMarkSetTime()
Mark the set time on the curve.
void showCurrentDate()
Set the AltVsTime Date according to the current Date in the KStars main window.
void setLSTLimits()
Determine the limits for the sideral time axis, using the sidereal time at midnight for the current d...
void plotMousePress(QCPAbstractPlottable *abstractPlottable, int dataIndex, QMouseEvent *event)
Show information from the curve as a tooltip.
void slotBrowseObject()
Launch the Find Object window to select a new object for the list of displayed objects.
void slotClearBoxes()
Clear the edit boxes for specifying a new object.
void slotChooseCity()
Launch the Location dialog to choose a new location.
void slotMarkTransitTime()
Mark the transit time on the curve.
KStarsDateTime getDate()
double getEpoch(const QString &eName)
Parse a string as an epoch number.
void mouseOverLine(QMouseEvent *event)
Draw the white vertical line on click.
void onXRangeChanged(const QCPRange &range)
Update the X axis on Zoom and Drag.
void computeSunRiseSetTimes()
Determine the time of sunset and sunrise for the current date and location settings.
void slotUpdateDateLoc()
Update the plot to reflec new Date and Location settings.
void slotClear()
Clear the list of displayed objects.
void processObject(SkyObject *o, bool forceAdd=false)
Add a SkyObject to the display.
void slotMarkRiseTime()
Mark the rise time on the curve.
~AltVsTime() override
Destructor.
void onYRangeChanged(const QCPRange &range)
Update the Y axis on Zoom and Drag.
void slotAdvanceFocus()
Move input keyboard focus to the next logical widget.
void slotComputeAltitudeByTime()
Compute the altitude for a certain time.
QString getObjectName(const SkyObject *o, bool translated=true)
get object name.
a dms subclass that caches its sine and cosine values every time the angle is changed.
Definition cachingdms.h:19
Contains all relevant information for specifying a location on Earth: City Name, State/Province name,...
Definition geolocation.h:28
QString fullName() const
const CachingDms * lat() const
Definition geolocation.h:70
const CachingDms * lng() const
Definition geolocation.h:64
A class that implements methods to find sun rise, sun set, twilight begin / end times,...
Definition ksalmanac.h:27
There are several time-dependent values used in position calculations, that are not specific to an ob...
Definition ksnumbers.h:43
KStarsData is the backbone of KStars.
Definition kstarsdata.h:72
CachingDms * lst()
Definition kstarsdata.h:224
const KStarsDateTime & ut() const
Definition kstarsdata.h:157
GeoLocation * geo()
Definition kstarsdata.h:230
Extension of QDateTime for KStars KStarsDateTime can represent the date/time as a Julian Day,...
KStarsDateTime addDays(int nd) const
Modify the Date/Time by adding a number of days.
KStarsDateTime addSecs(double s) const
bool setFromEpoch(double e, EpochType type)
Set the Date/Time from an epoch value, represented as a double.
static KStarsDateTime currentDateTimeUtc()
static KStarsDateTime currentDateTime()
long double djd() const
Dialog for changing the geographic location of the observer.
The abstract base class for all items in a plot.
The abstract base class for all data representing objects in a plot.
Specialized axis ticker for time spans in units of milliseconds to days.
@ tssReadability
A nicely readable tick step is prioritized over matching the requested number of ticks (see setTickCo...
A plottable representing a graph in a plot.
An arbitrary pixmap.
void setPixmap(const QPixmap &pixmap)
void setScaled(bool scaled, Qt::AspectRatioMode aspectRatioMode=Qt::KeepAspectRatio, Qt::TransformationMode transformationMode=Qt::SmoothTransformation)
void setType(PositionType type)
void setCoords(double key, double value)
@ ptPlotCoords
Dynamic positioning at a plot coordinate defined by two axes (see setAxes).
Item that sticks to QCPGraph data points.
@ tsCircle
A circle.
void setVisible(bool on)
Q_SLOT bool setLayer(QCPLayer *layer)
Represents the range an axis is encompassing.
QCPRange bounded(double lowerBound, double upperBound) const
@ limAbove
Layer is inserted above other layer.
Provides all necessary information about an object in the sky: its coordinates, name(s),...
Definition skyobject.h:42
virtual SkyObject * clone() const
Create copy of object.
Definition skyobject.cpp:50
QString translatedName() const
Definition skyobject.h:148
virtual QString name(void) const
Definition skyobject.h:145
bool isSolarSystem() const
Definition skyobject.h:217
QTime transitTime(const KStarsDateTime &dt, const GeoLocation *geo) const
The same iteration technique described in riseSetTime() is used here.
QTime riseSetTime(const KStarsDateTime &dt, const GeoLocation *geo, bool rst, bool exact=true) const
Determine the time at which the point will rise or set.
Definition skyobject.cpp:93
The sky coordinates of a point in the sky.
Definition skypoint.h:45
const CachingDms & dec() const
Definition skypoint.h:269
virtual void updateCoordsNow(const KSNumbers *num)
updateCoordsNow Shortcut for updateCoords( const KSNumbers *num, false, nullptr, nullptr,...
Definition skypoint.h:382
const CachingDms & ra() const
Definition skypoint.h:263
dms altRefracted() const
void EquatorialToHorizontal(const CachingDms *LST, const CachingDms *lat)
Determine the (Altitude, Azimuth) coordinates of the SkyPoint from its (RA, Dec) coordinates,...
Definition skypoint.cpp:77
virtual void updateCoords(const KSNumbers *num, bool includePlanets=true, const CachingDms *lat=nullptr, const CachingDms *LST=nullptr, bool forceRecompute=false)
Determine the current coordinates (RA, Dec) from the catalog coordinates (RA0, Dec0),...
Definition skypoint.cpp:582
const dms & alt() const
Definition skypoint.h:281
This is a subclass of SkyObject.
Definition starobject.h:33
int getHDIndex() const
Definition starobject.h:248
An angle, stored as degrees, but expressible in many ways.
Definition dms.h:38
const QString toDMSString(const bool forceSign=false, const bool machineReadable=false, const bool highPrecision=false) const
Definition dms.cpp:287
QString i18nc(const char *context, const char *text, const TYPE &arg...)
QString i18n(const char *text, const TYPE &arg...)
char * toString(const EngineQuery &query)
@ iRangeDrag
0x001 Axis ranges are draggable (see QCPAxisRect::setRangeDrag, QCPAxisRect::setRangeDragAxes)
@ iRangeZoom
0x002 Axis ranges are zoomable with the mouse wheel (see QCPAxisRect::setRangeZoom,...
@ msBottom
0x08 bottom margin
@ msTop
0x04 top margin
@ msLeft
0x01 left margin
QDate date() const const
QTime time() const const
virtual int exec()
void setModal(bool modal)
virtual void reject()
void rejected()
QPushButton * addButton(StandardButton button)
void restoreOverrideCursor()
void setOverrideCursor(const QCursor &cursor)
QIcon fromTheme(const QString &name)
void append(QList< T > &&value)
const_reference at(qsizetype i) const const
void clear()
qsizetype count() const const
bool isEmpty() const const
void replace(qsizetype i, parameter_type value)
qsizetype size() const const
value_type takeFirst()
QMetaObject::Connection connect(const QObject *sender, PointerToMemberFunction signal, Functor functor)
QObject * sender() const const
int height() const const
int width() const const
bool begin(QPaintDevice *device)
void drawEllipse(const QPoint &center, int rx, int ry)
void drawLine(const QLine &line)
void drawPixmap(const QPoint &point, const QPixmap &pixmap)
void drawText(const QPoint &position, const QString &text)
bool end()
void fillRect(const QRect &rectangle, QGradient::Preset preset)
const QFont & font() const const
qreal opacity() const const
void restore()
void rotate(qreal angle)
void save()
void setBrush(Qt::BrushStyle style)
void setClipRect(const QRect &rectangle, Qt::ClipOperation operation)
void setClipping(bool enable)
void setFont(const QFont &font)
void setOpacity(qreal opacity)
void setPen(Qt::PenStyle style)
void setRenderHint(RenderHint hint, bool on)
void translate(const QPoint &offset)
QRect rect() const const
virtual int exec() override
void setResolution(int dpi)
int height() const const
int width() const const
QString arg(Args &&... args) const const
bool isEmpty() const const
QString number(double n, char format, int precision)
AlignLeft
IgnoreAspectRatio
WaitCursor
RightButton
int hour() const const
int minute() const const
int second() const const
void hideText()
void showText(const QPoint &pos, const QString &text, QWidget *w, const QRect &rect, int msecDisplayTime)
void setEnabled(bool)
virtual bool event(QEvent *event) override
void lower()
void setMouseTracking(bool enable)
void render(QPaintDevice *target, const QPoint &targetOffset, const QRegion &sourceRegion, RenderFlags renderFlags)
void setFocus()
void setLayout(QLayout *layout)
void show()
void update()
virtual void setVisible(bool visible)
void setWindowFlags(Qt::WindowFlags type)
void setWindowTitle(const QString &)
This file is part of the KDE documentation.
Documentation copyright © 1996-2024 The KDE developers.
Generated on Tue Mar 26 2024 11:19:04 by doxygen 1.10.0 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.