Kstars

skymaplite.cpp
1/*
2 SPDX-FileCopyrightText: 2016 Artem Fedoskin <afedoskin3@gmail.com>
3 SPDX-License-Identifier: GPL-2.0-or-later
4*/
5
6#include "skymaplite.h"
7#include "kstarsdata.h"
8#include "kstarslite.h"
9
10#include "indi/inditelescopelite.h"
11#include "indi/clientmanagerlite.h"
12#include "kstarslite/skyitems/telescopesymbolsitem.h"
13
14#include "projections/projector.h"
15#include "projections/lambertprojector.h"
16#include "projections/gnomonicprojector.h"
17#include "projections/stereographicprojector.h"
18#include "projections/orthographicprojector.h"
19#include "projections/azimuthalequidistantprojector.h"
20#include "projections/equirectangularprojector.h"
21
22#include "kstarslite/skypointlite.h"
23#include "kstarslite/skyobjectlite.h"
24
25#include "skylabeler.h"
26#include "Options.h"
27#include "skymesh.h"
28
29#include "kstarslite/skyitems/rootnode.h"
30#include "kstarslite/skyitems/skynodes/skynode.h"
31
32#include "ksplanetbase.h"
33#include "ksutils.h"
34
35#include <QSGSimpleRectNode>
36//#include <QSGNode>
37#include <QBitmap>
38#include <QSGTexture>
39#include <QQuickWindow>
40#include <QLinkedList>
41#include <QQmlContext>
42#include <QScreen>
43
44#include "kstarslite/deviceorientation.h"
45
46namespace
47{
48// Draw bitmap for zoom cursor. Width is size of pen to draw with.
49QBitmap zoomCursorBitmap(int width)
50{
51 QBitmap b(32, 32);
52 b.fill(Qt::color0);
53 int mx = 16, my = 16;
54 // Begin drawing
55 QPainter p;
56 p.begin(&b);
57 p.setPen(QPen(Qt::color1, width));
58 p.drawEllipse(mx - 7, my - 7, 14, 14);
59 p.drawLine(mx + 5, my + 5, mx + 11, my + 11);
60 p.end();
61 return b;
62}
63
64// Draw bitmap for default cursor. Width is size of pen to draw with.
65QBitmap defaultCursorBitmap(int width)
66{
67 QBitmap b(32, 32);
68 b.fill(Qt::color0);
69 int mx = 16, my = 16;
70 // Begin drawing
71 QPainter p;
72 p.begin(&b);
73 p.setPen(QPen(Qt::color1, width));
74 // 1. diagonal
75 p.drawLine(mx - 2, my - 2, mx - 8, mx - 8);
76 p.drawLine(mx + 2, my + 2, mx + 8, mx + 8);
77 // 2. diagonal
78 p.drawLine(mx - 2, my + 2, mx - 8, mx + 8);
79 p.drawLine(mx + 2, my - 2, mx + 8, mx - 8);
80 p.end();
81 return b;
82}
83}
84
85SkyMapLite *SkyMapLite::pinstance = nullptr;
86
87RootNode *SkyMapLite::m_rootNode = nullptr;
88
89int SkyMapLite::starColorMode = 0;
90
91SkyMapLite::SkyMapLite()
92 : data(KStarsData::Instance())
93#if defined(Q_OS_ANDROID)
94 ,
95 m_deviceOrientation(new DeviceOrientation(this))
96#endif
97{
98 setAcceptHoverEvents(true);
99 setAcceptedMouseButtons(Qt::AllButtons);
100 setFlag(ItemHasContents, true);
101
102 m_rootNode = nullptr;
103 m_magLim = 2.222 * log10(static_cast<double>(Options::starDensity())) + 0.35;
104
105 setSlewing(false);
106
107 m_ClickedObjectLite = new SkyObjectLite;
108 m_ClickedPointLite = new SkyPointLite;
109
110 qmlRegisterType<SkyObjectLite>("KStarsLite", 1, 0, "SkyObjectLite");
111 qmlRegisterType<SkyPointLite>("KStarsLite", 1, 0, "SkyPointLite");
112
113 m_tapBeganTimer.setSingleShot(true);
114
115 setupProjector();
116
117 // Set pinstance to yourself
118 pinstance = this;
119
120 connect(this, SIGNAL(destinationChanged()), this, SLOT(slewFocus()));
121 connect(KStarsData::Instance(), SIGNAL(skyUpdate(bool)), this, SLOT(slotUpdateSky(bool)));
122
124
125 connect(clientMng, &ClientManagerLite::telescopeAdded,
126 [this](TelescopeLite * newTelescope)
127 {
128 this->m_newTelescopes.append(newTelescope->getDevice());
129 });
130 connect(clientMng, &ClientManagerLite::telescopeRemoved,
131 [this](TelescopeLite * newTelescope)
132 {
133 this->m_delTelescopes.append(newTelescope->getDevice());
134 });
135#if defined(Q_OS_ANDROID)
136 //Automatic mode
137 automaticModeTimer.setInterval(5);
138 connect(&automaticModeTimer, SIGNAL(timeout()), this, SLOT(updateAutomaticMode()));
139 setAutomaticMode(false);
140#endif
141}
142
143QSGNode *SkyMapLite::updatePaintNode(QSGNode *oldNode, UpdatePaintNodeData *updatePaintNodeData)
144{
145 Q_UNUSED(updatePaintNodeData);
146 RootNode *n = static_cast<RootNode *>(oldNode);
147
148 /* This code deletes all nodes that are representing dynamic stars and not needed anymore (under construction) */
149 //qDeleteAll(m_deleteNodes);
150 //m_deleteNodes.clear();
151
152 if (m_loadingFinished && isInitialized)
153 {
154 if (!n)
155 {
156 n = new RootNode();
157 m_rootNode = n;
158 }
159 /** Add or delete telescope crosshairs **/
160 if (m_newTelescopes.count() > 0)
161 {
162 foreach (INDI::BaseDevice *telescope, m_newTelescopes)
163 {
164 n->telescopeSymbolsItem()->addTelescope(telescope);
165 }
166 m_newTelescopes.clear();
167 }
168
169 if (m_delTelescopes.count() > 0)
170 {
171 foreach (INDI::BaseDevice *telescope, m_delTelescopes)
172 {
173 n->telescopeSymbolsItem()->removeTelescope(telescope);
174 }
175 m_delTelescopes.clear();
176 }
177 //Notify RootNode that textures for point node should be recreated
178 n->update(clearTextures);
179 clearTextures = false;
180 }
181
182 //Memory Leaks test
183 /*if(m_loadingFinished) {
184 if(!n) {
185 n = new RootNode();
186 }
187 n->testLeakAdd();
188 n->update();
189 m_loadingFinished = false;
190 } else {
191 if (n) {
192 n->testLeakDelete();
193 }
194 m_loadingFinished = true;
195 }*/
196 return n;
197}
198
200{
201 double lim = (MAXZOOM / MINZOOM) / sqrt(Options::zoomFactor()) / 3; //(MAXZOOM/MINZOOM - Options::zoomFactor())/130;
202 return lim;
203}
204
206{
207 m_deleteNodes.append(skyNode);
208}
209
211{
212 return textureCache[harvardToIndex(spType)][size];
213}
214
216{
217 delete pinstance;
218 pinstance = new SkyMapLite();
219 return pinstance;
220}
221
223{
224 if (parent)
225 {
227 // Whenever the wrapper's(parent) dimensions changed, change SkyMapLite too
230
231 isInitialized = true;
232 }
233
234 resizeItem(); /* Set initial size pf SkyMapLite. Without it on Android SkyMapLite is
235 not displayed until screen orientation is not changed*/
236
237 //Initialize images for stars
239}
240
242{
243 // Delete image cache
244 for (auto &imgCache : imageCache)
245 qDeleteAll(imgCache);
246
247 // Delete textures generated from image cache
248 for (auto &tCache : textureCache)
249 qDeleteAll(tCache);
250}
251
252void SkyMapLite::setFocus(SkyPoint *p)
253{
254 setFocus(p->ra(), p->dec());
255}
256
257void SkyMapLite::setFocus(const dms &ra, const dms &dec)
258{
259 Options::setFocusRA(ra.Hours());
260 Options::setFocusDec(dec.Degrees());
261
262 focus()->set(ra, dec);
263 focus()->EquatorialToHorizontal(data->lst(), data->geo()->lat());
264}
265
266void SkyMapLite::setFocusAltAz(const dms &alt, const dms &az)
267{
268 Options::setFocusRA(focus()->ra().Hours());
269 Options::setFocusDec(focus()->dec().Degrees());
270 focus()->setAlt(alt);
271 focus()->setAz(az);
272 focus()->HorizontalToEquatorial(data->lst(), data->geo()->lat());
273
274 setSlewing(false);
275 forceUpdate(); //need a total update, or slewing with the arrow keys doesn't work.
276}
277
278void SkyMapLite::setDestination(const SkyPoint &p)
279{
280 setDestination(p.ra(), p.dec());
281}
282
283void SkyMapLite::setDestination(const dms &ra, const dms &dec)
284{
285 destination()->set(ra, dec);
286 destination()->EquatorialToHorizontal(data->lst(), data->geo()->lat());
287 emit destinationChanged();
288}
289
290void SkyMapLite::setDestinationAltAz(const dms &alt, const dms &az, bool altIsRefracted)
291{
292 if (altIsRefracted)
293 {
294 // The alt in the SkyPoint is always actual, not apparent
295 destination()->setAlt(SkyPoint::unrefract(alt));
296 }
297 else
298 {
299 destination()->setAlt(alt);
300 }
301 destination()->setAz(az);
302 destination()->HorizontalToEquatorial(data->lst(), data->geo()->lat());
303 emit destinationChanged();
304}
305
307{
308 ClickedPoint = *f;
309 m_ClickedPointLite->setPoint(f);
310}
311
313{
314 ClickedObject = o;
315 m_ClickedObjectLite->setObject(o);
316}
317
319{
320 FocusObject = o;
321 if (FocusObject)
322 Options::setFocusObject(FocusObject->name());
323 else
324 Options::setFocusObject(i18n("nothing"));
325}
326
328{
329 /*KStars* kstars = KStars::Instance();
330 TrailObject* trailObj = dynamic_cast<TrailObject*>( focusObject() );*/
331
333 if (Options::useAltAz())
334 {
335 focusPoint()->updateCoords(data->updateNum(), true, data->geo()->lat(), data->lst(), false);
336 focusPoint()->EquatorialToHorizontal(data->lst(), data->geo()->lat());
337 }
338 else
339 {
340 focusPoint()->updateCoords(data->updateNum(), true, data->geo()->lat(), data->lst(), false);
341 }
342 qDebug() << "Centering on " << focusPoint()->ra().toHMSString() << " " << focusPoint()->dec().toDMSString();
343
344 //clear the planet trail of old focusObject, if it was temporary
345 /*if( trailObj && data->temporaryTrail ) {
346 trailObj->clearTrail();
347 data->temporaryTrail = false;
348 }*/
349
350 //If the requested object is below the opaque horizon, issue a warning message
351 //(unless user is already pointed below the horizon)
352 if (Options::useAltAz() && Options::showGround() && focus()->alt().Degrees() > SkyPoint::altCrit &&
353 focusPoint()->alt().Degrees() <= SkyPoint::altCrit)
354 {
355 QString caption = i18n("Requested Position Below Horizon");
356 QString message = i18n("The requested position is below the horizon.\nWould you like to go there anyway?");
357 /*if ( KMessageBox::warningContinueCancel( this, message, caption,
358 KGuiItem(i18n("Go Anyway")), KGuiItem(i18n("Keep Position")), "dag_focus_below_horiz" )==KMessageBox::Cancel ) {
359 setClickedObject( nullptr );
360 setFocusObject( nullptr );
361 Options::setIsTracking( false );
362
363 return;
364 }*/
365 }
366
367 //set FocusObject before slewing. Otherwise, KStarsData::updateTime() can reset
368 //destination to previous object...
369 setFocusObject(ClickedObject);
370 Options::setIsTracking(true);
371 /*if ( kstars ) {
372 kstars->actionCollection()->action("track_object")->setIcon( QIcon::fromTheme("document-encrypt") );
373 kstars->actionCollection()->action("track_object")->setText( i18n( "Stop &Tracking" ) );
374 }*/
375
376 //If focusObject is a SS body and doesn't already have a trail, set the temporaryTrail
377
378 /*if( Options::useAutoTrail() && trailObj && trailObj->hasTrail() ) {
379 trailObj->addToTrail();
380 data->temporaryTrail = true;
381 }*/
382
383 //update the destination to the selected coordinates
384 if (Options::useAltAz())
385 {
386 setDestinationAltAz(focusPoint()->alt(), focusPoint()->az(), false);
387 }
388 else
389 {
391 }
392
393 focusPoint()->EquatorialToHorizontal(data->lst(), data->geo()->lat());
394
395 //display coordinates in statusBar
397 //showFocusCoords(); //update FocusBox
398 //Lock center so that user could only zoom on touch-enabled devices
399}
400
402{
403 //Don't slew if the mouse button is pressed
404 //Also, no animated slews if the Manual Clock is active
405 //08/2002: added possibility for one-time skipping of slew with snapNextFocus
406 if (!mouseButtonDown)
407 {
408 bool goSlew = (Options::useAnimatedSlewing() && !data->snapNextFocus()) &&
409 !(data->clock()->isManualMode() && data->clock()->isActive());
410 if (goSlew)
411 {
412 double dX, dY;
413 double maxstep = 10.0;
414 if (Options::useAltAz())
415 {
416 dX = destination()->az().Degrees() - focus()->az().Degrees();
417 dY = destination()->alt().Degrees() - focus()->alt().Degrees();
418 }
419 else
420 {
421 dX = destination()->ra().Degrees() - focus()->ra().Degrees();
422 dY = destination()->dec().Degrees() - focus()->dec().Degrees();
423 }
424
425 //switch directions to go the short way around the celestial sphere, if necessary.
426 dX = KSUtils::reduceAngle(dX, -180.0, 180.0);
427
428 double r0 = sqrt(dX * dX + dY * dY);
429 if (r0 < 20.0) //smaller slews have smaller maxstep
430 {
431 maxstep *= (10.0 + 0.5 * r0) / 20.0;
432 }
433 double step = 0.1;
434 double r = r0;
435 while (r > step)
436 {
437 //DEBUG
438 //qDebug() << step << ": " << r << ": " << r0 << endl;
439 double fX = dX / r;
440 double fY = dY / r;
441
442 if (Options::useAltAz())
443 {
444 focus()->setAlt(focus()->alt().Degrees() + fY * step);
445 focus()->setAz(dms(focus()->az().Degrees() + fX * step).reduce());
446 focus()->HorizontalToEquatorial(data->lst(), data->geo()->lat());
447 }
448 else
449 {
450 fX = fX / 15.; //convert RA degrees to hours
451 SkyPoint newFocus(focus()->ra().Hours() + fX * step, focus()->dec().Degrees() + fY * step);
452 setFocus(&newFocus);
453 focus()->EquatorialToHorizontal(data->lst(), data->geo()->lat());
454 }
455
456 setSlewing(true);
457
458 forceUpdate();
459 qApp->processEvents(); //keep up with other stuff
460
461 if (Options::useAltAz())
462 {
463 dX = destination()->az().Degrees() - focus()->az().Degrees();
464 dY = destination()->alt().Degrees() - focus()->alt().Degrees();
465 }
466 else
467 {
468 dX = destination()->ra().Degrees() - focus()->ra().Degrees();
469 dY = destination()->dec().Degrees() - focus()->dec().Degrees();
470 }
471
472 //switch directions to go the short way around the celestial sphere, if necessary.
473 dX = KSUtils::reduceAngle(dX, -180.0, 180.0);
474 r = sqrt(dX * dX + dY * dY);
475
476 //Modify step according to a cosine-shaped profile
477 //centered on the midpoint of the slew
478 //NOTE: don't allow the full range from -PI/2 to PI/2
479 //because the slew will never reach the destination as
480 //the speed approaches zero at the end!
481 double t = dms::PI * (r - 0.5 * r0) / (1.05 * r0);
482 step = cos(t) * maxstep;
483 }
484 }
485
486 //Either useAnimatedSlewing==false, or we have slewed, and are within one step of destination
487 //set focus=destination.
488 if (Options::useAltAz())
489 {
490 setFocusAltAz(destination()->alt(), destination()->az());
491 focus()->HorizontalToEquatorial(data->lst(), data->geo()->lat());
492 }
493 else
494 {
496 focus()->EquatorialToHorizontal(data->lst(), data->geo()->lat());
497 }
498
499 setSlewing(false);
500
501 //Turn off snapNextFocus, we only want it to happen once
502 if (data->snapNextFocus())
503 {
504 data->setSnapNextFocus(false);
505 }
506
507 //Start the HoverTimer. if the user leaves the mouse in place after a slew,
508 //we want to attach a label to the nearest object.
509 if (Options::useHoverLabel())
510 m_HoverTimer.start(HOVER_INTERVAL);
511
512 forceUpdate();
513 }
514}
515
517{
518 //If the current timescale exceeds slewTimeScale, set clockSlewing=true, and stop the clock.
519 if ((fabs(data->clock()->scale()) > Options::slewTimeScale()) ^ clockSlewing)
520 {
521 data->clock()->setManualMode(!clockSlewing);
522 clockSlewing = !clockSlewing;
523 // don't change automatically the DST status
525 if (kstars)
526 kstars->updateTime(false);
527 }
528}
529
530/*void SkyMapLite::updateFocus() {
531 if( slewing )
532 return;
533
534 //Tracking on an object
535 if ( Options::isTracking() && focusObject() != nullptr ) {
536 if ( Options::useAltAz() ) {
537 //Tracking any object in Alt/Az mode requires focus updates
538 focusObject()->EquatorialToHorizontal(data->lst(), data->geo()->lat());
539 setFocusAltAz( focusObject()->alt(), focusObject()->az() );
540 focus()->HorizontalToEquatorial( data->lst(), data->geo()->lat() );
541 setDestination( *focus() );
542 } else {
543 //Tracking in equatorial coords
544 setFocus( focusObject() );
545 focus()->EquatorialToHorizontal( data->lst(), data->geo()->lat() );
546 setDestination( *focus() );
547 }
548
549 //Tracking on empty sky
550 } else if ( Options::isTracking() && focusPoint() != nullptr ) {
551 if ( Options::useAltAz() ) {
552 //Tracking on empty sky in Alt/Az mode
553 setFocus( focusPoint() );
554 focus()->EquatorialToHorizontal( data->lst(), data->geo()->lat() );
555 setDestination( *focus() );
556 }
557
558 // Not tracking and not slewing, let sky drift by
559 // This means that horizontal coordinates are constant.
560 } else {
561 focus()->HorizontalToEquatorial(data->lst(), data->geo()->lat() );
562 }
563}*/
564
566{
567 if (parentItem())
568 {
571 }
572 forceUpdate();
573}
574
576{
577 setZoomFactor(Options::zoomFactor() * DZOOM);
578}
579
581{
582 setZoomFactor(Options::zoomFactor() / DZOOM);
583}
584
586{
587 setZoomFactor(DEFAULTZOOM);
588}
589
591{
592 ClickedPoint = *skyObj;
593 ClickedObject = skyObj;
594 /*if ( Options::useAltAz() ) {
595 setDestinationAltAz( skyObj->altRefracted(), skyObj->az() );
596 } else {
597 setDestination( *skyObj );
598 }*/
599 //Update selected SkyObject (used in FindDialog, DetailDialog)
600 m_ClickedObjectLite->setObject(skyObj);
601 emit objectLiteChanged();
602 slotCenter();
603}
604
605void SkyMapLite::setSkyRotation(double skyRotation)
606{
607 if (m_skyRotation != skyRotation)
608 {
609 m_skyRotation = skyRotation;
610 emit skyRotationChanged(skyRotation);
611
612 if (skyRotation >= 0 && skyRotation < 90)
613 {
614 m_skyMapOrientation = SkyMapOrientation::Top0;
615 }
616 else if (skyRotation >= 90 && skyRotation < 180)
617 {
618 m_skyMapOrientation = SkyMapOrientation::Right90;
619 }
620 else if (skyRotation >= 180 && skyRotation < 270)
621 {
622 m_skyMapOrientation = SkyMapOrientation::Bottom180;
623 }
624 else if (skyRotation >= 270 && skyRotation < 360)
625 {
626 m_skyMapOrientation = SkyMapOrientation::Left270;
627 }
628 }
629}
630
631void SkyMapLite::setZoomFactor(double factor)
632{
633 Options::setZoomFactor(KSUtils::clamp(factor, MINZOOM, MAXZOOM));
634
635 forceUpdate();
636 emit zoomChanged();
637}
638
640{
642
643 // We delay one draw cycle before re-indexing
644 // we MUST ensure CLines do not get re-indexed while we use DRAW_BUF
645 // so we do it here.
646 //m_CLines->reindex( &m_reindexNum );
647 // This queues re-indexing for the next draw cycle
648 //m_reindexNum = KSNumbers( data->updateNum()->julianDay() );
649
650 // This ensures that the JIT updates are synchronized for the entire draw
651 // cycle so the sky moves as a single sheet. May not be needed.
652 data->syncUpdateIDs();
653
654 SkyMesh *m_skyMesh = SkyMesh::Instance(3);
655 if (m_skyMesh)
656 {
657 // prepare the aperture
658 // FIXME_FOV: We may want to rejigger this to allow
659 // wide-angle views --hdevalence
660 double radius = m_proj->fov();
661 if (radius > 180.0)
662 radius = 180.0;
663
664 if (m_skyMesh->inDraw())
665 {
666 printf("Warning: aborting concurrent SkyMapComposite::draw()\n");
667 return;
668 }
669
670 //m_skyMesh->inDraw( true );
671 m_skyMesh->aperture(&Focus, radius + 1.0, DRAW_BUF); // divide by 2 for testing
672
673 // create the no-precess aperture if needed
674 if (Options::showEquatorialGrid() || Options::showHorizontalGrid() || Options::showCBounds() ||
675 Options::showEquator())
676 {
677 m_skyMesh->index(&Focus, radius + 1.0, NO_PRECESS_BUF);
678 }
679 }
680 update();
681}
682
684{
685 Q_UNUSED(now);
686 updateFocus();
687 forceUpdate();
688}
689
691{
692 if (getSlewing())
693 return;
694
695 //Tracking on an object
696 if (Options::isTracking() && focusObject() != nullptr)
697 {
698 if (Options::useAltAz())
699 {
700 //Tracking any object in Alt/Az mode requires focus updates
701 focusObject()->EquatorialToHorizontal(data->lst(), data->geo()->lat());
702 setFocusAltAz(focusObject()->alt(), focusObject()->az());
703 focus()->HorizontalToEquatorial(data->lst(), data->geo()->lat());
705 }
706 else
707 {
708 //Tracking in equatorial coords
710 focus()->EquatorialToHorizontal(data->lst(), data->geo()->lat());
712 }
713
714 //Tracking on empty sky
715 }
716 else if (Options::isTracking() && focusPoint() != nullptr)
717 {
718 if (Options::useAltAz())
719 {
720 //Tracking on empty sky in Alt/Az mode
722 focus()->EquatorialToHorizontal(data->lst(), data->geo()->lat());
724 }
725
726 // Not tracking and not slewing, let sky drift by
727 // This means that horizontal coordinates are constant.
728 }
729 else
730 {
731 focus()->HorizontalToEquatorial(data->lst(), data->geo()->lat());
732 }
733}
734
736{
737 //Update View Parameters for projection
738 ViewParams p;
739 p.focus = focus();
740 p.height = height();
741 p.width = width();
742 p.useAltAz = Options::useAltAz();
743 p.useRefraction = Options::useRefraction();
744 p.zoomFactor = Options::zoomFactor();
745 p.rotationAngle = Options::skyRotation();
746 p.fillGround = Options::showGround();
747
748 //Check if we need a new projector
749 if (m_proj && Options::projection() == m_proj->type())
750 m_proj->setViewParams(p);
751 else
752 {
753 delete m_proj;
754 switch (Options::projection())
755 {
756 case Projector::Gnomonic:
757 m_proj = new GnomonicProjector(p);
758 break;
759 case Projector::Stereographic:
760 m_proj = new StereographicProjector(p);
761 break;
762 case Projector::Orthographic:
763 m_proj = new OrthographicProjector(p);
764 break;
765 case Projector::AzimuthalEquidistant:
766 m_proj = new AzimuthalEquidistantProjector(p);
767 break;
768 case Projector::Equirectangular:
769 m_proj = new EquirectangularProjector(p);
770 break;
771 case Projector::Lambert:
772 default:
773 //TODO: implement other projection classes
774 m_proj = new LambertProjector(p);
775 break;
776 }
777 }
778}
779
780void SkyMapLite::setZoomMouseCursor()
781{
782 mouseMoveCursor = false; // no mousemove cursor
783 QBitmap cursor = zoomCursorBitmap(2);
784 QBitmap mask = zoomCursorBitmap(4);
785 setCursor(QCursor(cursor, mask));
786}
787
788void SkyMapLite::setDefaultMouseCursor()
789{
790 mouseMoveCursor = false; // no mousemove cursor
791 QBitmap cursor = defaultCursorBitmap(2);
792 QBitmap mask = defaultCursorBitmap(3);
793 setCursor(QCursor(cursor, mask));
794}
795
796void SkyMapLite::setMouseMoveCursor()
797{
798 if (mouseButtonDown)
799 {
800 setCursor(Qt::SizeAllCursor); // cursor shape defined in qt
801 mouseMoveCursor = true;
802 }
803}
804
806{
807 return (getSlewing() || (clockSlewing && data->clock()->isActive()));
808}
809
811{
812 // Convert spectral class to numerical index.
813 // If spectral class is invalid return index for white star (A class)
814
815 switch (c)
816 {
817 case 'o':
818 case 'O':
819 return 0;
820 case 'b':
821 case 'B':
822 return 1;
823 case 'a':
824 case 'A':
825 return 2;
826 case 'f':
827 case 'F':
828 return 3;
829 case 'g':
830 case 'G':
831 return 4;
832 case 'k':
833 case 'K':
834 return 5;
835 case 'm':
836 case 'M':
837 return 6;
838 // For unknown spectral class assume A class (white star)
839 default:
840 return 2;
841 }
842}
843
845{
846 return imageCache;
847}
848
850{
851 if (isInitialized)
852 {
853 QFont f;
854
855 if (zoomFont)
856 {
857 f = SkyLabeler::Instance()->drawFont();
858 }
859 else
860 {
861 f = SkyLabeler::Instance()->stdFont();
862 }
863
864 qreal ratio = window()->effectiveDevicePixelRatio();
865
866 QFontMetrics fm(f);
867
868 int width = fm.width(text);
869 int height = fm.height();
870 // double rotation = 0;
871
872 //// switch(m_skyMapOrientation) {
873 //// case(SkyMapOrientation::Top0):
874 //// width = fm.width(text);
875 //// height = fm.height();
876 //// rotation = 0;
877 //// break;
878 //// case(SkyMapOrientation::Right90):
879 //// width = fm.height();
880 //// height = fm.width(text);
881 //// rotation = 90;
882 //// case(SkyMapOrientation::Bottom180):
883 ////// width = ;
884 ////// height = ;
885 //// rotation = 180;
886 //// case(SkyMapOrientation::Left270):
887 ////// width = ;
888 ////// height;
889 //// rotation = 270;
890 //// }
891
892 f.setPointSizeF(f.pointSizeF() * ratio);
893
895
896 label.fill(Qt::transparent);
897
898 m_painter.begin(&label);
899
900 m_painter.setFont(f);
901
902 m_painter.setPen(color);
903
904 // m_painter.drawRect(0,0, label.width(), label.height());
905 // m_painter.rotate(getSkyRotation());
906 m_painter.drawText(0, (height - fm.descent()) * ratio, text);
907
908 m_painter.end();
909
911 return texture;
912 }
913 else
914 {
915 return nullptr;
916 }
917}
918
919void SkyMapLite::addFOVSymbol(const QString &FOVName, bool initialState)
920{
921 m_FOVSymbols.append(FOVName);
922 //Emit signal whenever new value was added
923 emit symbolsFOVChanged(m_FOVSymbols);
924
925 m_FOVSymVisible.append(initialState);
926}
927
929{
930 return m_FOVSymVisible.value(index);
931}
932
933void SkyMapLite::setFOVVisible(int index, bool visible)
934{
935 if (index >= 0 && index < m_FOVSymVisible.size())
936 {
937 m_FOVSymVisible[index] = visible;
938 forceUpdate();
939 }
940}
941
942void SkyMapLite::setSlewing(bool newSlewing)
943{
944 if (m_slewing != newSlewing)
945 {
946 m_slewing = newSlewing;
947 emit slewingChanged(newSlewing);
948 }
949}
950
951void SkyMapLite::setCenterLocked(bool centerLocked)
952{
953 m_centerLocked = centerLocked;
954 emit centerLockedChanged(centerLocked);
955}
956
957void SkyMapLite::setAutomaticMode(bool automaticMode)
958{
959#if defined(Q_OS_ANDROID)
960 if (m_automaticMode != automaticMode)
961 {
962 m_automaticMode = automaticMode;
963 if (automaticMode)
964 {
965 m_deviceOrientation->startSensors();
966 automaticModeTimer.start();
967 }
968 else
969 {
970 automaticModeTimer.stop();
971 m_deviceOrientation->stopSensors();
972 }
973 }
974#else
975 Q_UNUSED(automaticMode);
976#endif
977}
978
980{
981#if defined(Q_OS_ANDROID)
982 m_deviceOrientation->getOrientation();
983 if (Options::useRefraction() && Options::useAltAz())
984 {
985 setFocusAltAz(SkyPoint::unrefract(dms(m_deviceOrientation->getAltitude())), dms(m_deviceOrientation->getAzimuth()));
986 }
987 else
988 {
989 setFocusAltAz(dms(m_deviceOrientation->getAltitude()), dms(m_deviceOrientation->getAzimuth()));
990 }
991
992 setSkyRotation(-1 * m_deviceOrientation->getRoll());
993#endif
994}
995
997{
998 if (isInitialized)
999 {
1000 //Delete all existing pixmaps
1001 if (imageCache.length() != 0)
1002 {
1003 foreach (QVector<QPixmap *> vec, imageCache)
1004 {
1005 qDeleteAll(vec.begin(), vec.end());
1006 }
1007 clearTextures = true;
1008 }
1009
1010 imageCache = QVector<QVector<QPixmap *>>(nSPclasses);
1011
1012 QMap<char, QColor> ColorMap;
1013 const int starColorIntensity = Options::starColorIntensity();
1014
1015 //On high-dpi screens star will look pixelized if don't multiply scaling factor by this ratio
1016 //Check PointNode::setNode() to see how it works
1017 qreal ratio = window()->effectiveDevicePixelRatio();
1018
1019 switch (Options::starColorMode())
1020 {
1021 case 1: // Red stars.
1022 ColorMap.insert('O', QColor::fromRgb(255, 0, 0));
1023 ColorMap.insert('B', QColor::fromRgb(255, 0, 0));
1024 ColorMap.insert('A', QColor::fromRgb(255, 0, 0));
1025 ColorMap.insert('F', QColor::fromRgb(255, 0, 0));
1026 ColorMap.insert('G', QColor::fromRgb(255, 0, 0));
1027 ColorMap.insert('K', QColor::fromRgb(255, 0, 0));
1028 ColorMap.insert('M', QColor::fromRgb(255, 0, 0));
1029 break;
1030 case 2: // Black stars.
1031 ColorMap.insert('O', QColor::fromRgb(0, 0, 0));
1032 ColorMap.insert('B', QColor::fromRgb(0, 0, 0));
1033 ColorMap.insert('A', QColor::fromRgb(0, 0, 0));
1034 ColorMap.insert('F', QColor::fromRgb(0, 0, 0));
1035 ColorMap.insert('G', QColor::fromRgb(0, 0, 0));
1036 ColorMap.insert('K', QColor::fromRgb(0, 0, 0));
1037 ColorMap.insert('M', QColor::fromRgb(0, 0, 0));
1038 break;
1039 case 3: // White stars
1040 ColorMap.insert('O', QColor::fromRgb(255, 255, 255));
1041 ColorMap.insert('B', QColor::fromRgb(255, 255, 255));
1042 ColorMap.insert('A', QColor::fromRgb(255, 255, 255));
1043 ColorMap.insert('F', QColor::fromRgb(255, 255, 255));
1044 ColorMap.insert('G', QColor::fromRgb(255, 255, 255));
1045 ColorMap.insert('K', QColor::fromRgb(255, 255, 255));
1046 ColorMap.insert('M', QColor::fromRgb(255, 255, 255));
1047 case 0: // Real color
1048 default: // And use real color for everything else
1049 ColorMap.insert('O', QColor::fromRgb(0, 0, 255));
1050 ColorMap.insert('B', QColor::fromRgb(0, 200, 255));
1051 ColorMap.insert('A', QColor::fromRgb(0, 255, 255));
1052 ColorMap.insert('F', QColor::fromRgb(200, 255, 100));
1053 ColorMap.insert('G', QColor::fromRgb(255, 255, 0));
1054 ColorMap.insert('K', QColor::fromRgb(255, 100, 0));
1055 ColorMap.insert('M', QColor::fromRgb(255, 0, 0));
1056 }
1057
1058 for (char color : ColorMap.keys())
1059 {
1060 //Add new spectral class
1061
1062 QPixmap BigImage(15, 15);
1063 BigImage.fill(Qt::transparent);
1064
1065 QPainter p;
1066 p.begin(&BigImage);
1067
1068 if (Options::starColorMode() == 0)
1069 {
1070 qreal h, s, v, a;
1072 QColor starColor = ColorMap[color];
1073 starColor.getHsvF(&h, &s, &v, &a);
1074 for (int i = 0; i < 8; i++)
1075 {
1076 for (int j = 0; j < 8; j++)
1077 {
1078 qreal x = i - 7;
1079 qreal y = j - 7;
1080 qreal dist = sqrt(x * x + y * y) / 7.0;
1081 starColor.setHsvF(h, qMin(qreal(1), dist < (10 - starColorIntensity) / 10.0 ? 0 : dist), v,
1082 qMax(qreal(0), dist < (10 - starColorIntensity) / 20.0 ? 1 : 1 - dist));
1083 p.setPen(starColor);
1084 p.drawPoint(i, j);
1085 p.drawPoint((14 - i), j);
1086 p.drawPoint(i, (14 - j));
1087 p.drawPoint((14 - i), (14 - j));
1088 }
1089 }
1090 }
1091 else
1092 {
1094 p.setPen(QPen(ColorMap[color], 2.0));
1095 p.setBrush(p.pen().color());
1096 p.drawEllipse(QRectF(2, 2, 10, 10));
1097 }
1098 p.end();
1099 //[nSPclasses][nStarSizes];
1100 // Cache array slice
1101
1102 QVector<QPixmap *> *pmap = &imageCache[harvardToIndex(color)];
1103 pmap->append(new QPixmap(BigImage));
1104 for (int size = 1; size < nStarSizes; size++)
1105 {
1106 pmap->append(new QPixmap(
1107 BigImage.scaled(size * ratio, size * ratio, Qt::KeepAspectRatio, Qt::SmoothTransformation)));
1108 }
1109 }
1110 //}
1111 starColorMode = Options::starColorMode();
1112 }
1113}
Implememntation of Azimuthal equidistant projection
Implememntation of Equirectangular projection
const CachingDms * lat() const
Definition geolocation.h:70
Implememntation of Gnomonic projection
KStarsData is the backbone of KStars.
Definition kstarsdata.h:74
CachingDms * lst()
Definition kstarsdata.h:226
bool snapNextFocus() const
Definition kstarsdata.h:270
Q_INVOKABLE SimClock * clock()
Definition kstarsdata.h:220
GeoLocation * geo()
Definition kstarsdata.h:232
void setSnapNextFocus(bool b=true)
Disable or re-enable the slewing animation for the next Focus change.
Definition kstarsdata.h:285
This class loads QML files and connects SkyMapLite and KStarsData Unlike KStars class it is not a mai...
Definition kstarslite.h:47
ClientManagerLite * clientManagerLite() const
Definition kstarslite.h:107
void updateTime(const bool automaticDSTchange=true)
Update time-dependent data and (possibly) repaint the sky map.
static KStarsLite * Instance()
Definition kstarslite.h:77
Implememntation of Lambert azimuthal equal-area projection
Implememntation of Orthographic projection
void setViewParams(const ViewParams &p)
Update cached values for projector.
Definition projector.cpp:46
double fov() const
Return the FOV of this projection.
Definition projector.cpp:88
virtual Q_INVOKABLE Projection type() const =0
Return the type of this projection.
A QSGClipNode derived class used as a container for holding pointers to nodes and for clipping.
Definition rootnode.h:60
void update(bool clearTextures=false)
update positions of all child SkyItems
Definition rootnode.cpp:216
double scale() const
Definition simclock.h:51
Q_INVOKABLE bool isActive()
Whether the clock is active or not is a bit complicated by the introduction of "manual mode".
Definition simclock.cpp:128
void setManualMode(bool on=true)
Sets Manual Mode on/off according to the bool argument.
Definition simclock.cpp:66
bool isManualMode() const
Manual Mode is a new (04/2002) addition to the SimClock.
Definition simclock.h:69
This is the main item that displays all SkyItems.
Definition skymaplite.h:59
void setZoomFactor(double factor)
@ Set zoom factor.
Q_INVOKABLE void setAutomaticMode(bool automaticMode)
switch automatic mode on/off according to isOn parameter
void setCenterLocked(bool centerLocked)
sets whether SkyMapLite is centered on an object and locked(olny pinch-to-zoom is available)
static SkyMapLite * createInstance()
Creates instance of SkyMapLite (delete the old one if any)
void slotCenter()
Center the display at the point ClickedPoint.
void updateFocus()
Update the focus position according to current options.
void slewFocus()
Step the Focus point toward the Destination point.
QSGTexture * textToTexture(QString text, QColor color=QColor(255, 255, 255), bool zoomFont=false)
creates QImage from text and converts it to QSGTexture
void symbolsFOVChanged(QStringList)
Emitted when FOVSymbols list was changed (new value appended)
int harvardToIndex(char c)
Returns index for a Harvard spectral classification.
SkyPoint * focus()
Retrieve the Focus point; the position on the sky at the center of the skymap.
Definition skymaplite.h:125
~SkyMapLite()
Destructor.
bool centerLocked
true if SkyMapLite is centered on an object and only pinch-to-zoom needs to be available
Definition skymaplite.h:74
void slotSelectObject(SkyObject *skyObj)
centres skyObj in SkyMap and opens context drawer with skyObj Used in FindDialogLite
void setDestination(const SkyPoint &f)
sets the destination point of the sky map.
void forceUpdate()
Recalculates the positions of objects in the sky, and then repaints the sky map.
void destinationChanged()
Emitted by setDestination(), and connected to slewFocus().
QVector< QVector< QPixmap * > > getImageCache()
returns cache of star images
void setClickedObject(SkyObject *o)
Set the ClickedObject pointer to the argument.
void slotZoomIn()
Zoom in one step.
SkyPoint * focusPoint()
retrieve the FocusPoint position.
Definition skymaplite.h:149
QSGTexture * getCachedTexture(int size, char spType)
returns cached texture from textureCache.
void zoomChanged()
Emitted when zoom level is changed.
void initStarImages()
Initializes images of Stars and puts them in cache (copied from SkyQPainter)
void slewingChanged(bool)
Emitted when SkyMapLite is being slewed or slewing is finished.
void slotClockSlewing()
Checks whether the timestep exceeds a threshold value.
bool getSlewing() const
Proxy method for SkyMapDrawAbstract::drawObjectLabels()
Definition skymaplite.h:422
void setFocusPoint(SkyPoint *f)
set the FocusPoint; the position that is to be the next Destination.
Definition skymaplite.h:204
void objectLiteChanged()
Wrapper of ClickedObject for QML.
void mousePointChanged(SkyPoint *)
Emitted when position under mouse changed.
void slotUpdateSky(bool now)
Update the focus point and call forceUpdate()
Q_INVOKABLE void addFOVSymbol(const QString &FOVName, bool initialState=false)
adds FOV symbol to m_FOVSymbols
void setDestinationAltAz(const dms &alt, const dms &az, bool altIsRefracted)
sets the destination point of the sky map, using its alt/az coordinates.
SkyPoint * destination()
retrieve the Destination position.
Definition skymaplite.h:135
virtual QSGNode * updatePaintNode(QSGNode *oldNode, UpdatePaintNodeData *updatePaintNodeData) override
Updates SkyMapLite by calling RootNode::update(), which in turn initiates update of all child nodes.
SkyPoint * clickedPoint()
Retrieve the ClickedPoint position.
Definition skymaplite.h:217
void slotZoomDefault()
Set default zoom.
void skyRotationChanged(double skyRotation)
Emitted when skyRotation used to rotate coordinates of SkyPoints is changed.
void setClickedPoint(SkyPoint *f)
Set the ClickedPoint to the skypoint given as an argument.
bool isSlewing() const
void initialize(QQuickItem *parent)
Bind size to parent's size and initialize star images.
void setFocusAltAz(const dms &alt, const dms &az)
sets the focus point of the sky map, using its alt/az coordinates
void deleteSkyNode(SkyNode *skyNode)
skyNode will be deleted on the next call to updatePaintNode (currently used only in StarNode(struct i...
void setFocusObject(SkyObject *o)
Set the FocusObject pointer to the argument.
void setupProjector()
Call to set up the projector before update of SkyItems positions begins.
bool isFOVVisible(int index)
void setSlewing(bool newSlewing)
sets whether SkyMapLite is being slewed
Q_INVOKABLE void setFOVVisible(int index, bool visible)
updates visibility of FOV symbol according to visible
SkyObject * focusObject() const
Retrieve the object which is centered in the sky map.
Definition skymaplite.h:252
void resizeItem()
Called whenever wrappers' width or height are changed.
void slotZoomOut()
Zoom out one step.
void setFocus(SkyPoint *f)
sets the central focus point of the sky map.
static double deleteLimit()
return limit of hides for the node to delete it
void updateAutomaticMode()
updates focus of SkyMapLite according to data from DeviceOrientation (Smartphone's sensors)
Provides an interface to the Hierarchical Triangular Mesh (HTM) library written by A.
Definition skymesh.h:74
static SkyMesh * Instance()
returns the default instance of SkyMesh or null if it has not yet been created.
Definition skymesh.cpp:39
void aperture(SkyPoint *center, double radius, MeshBufNum_t bufNum=DRAW_BUF)
finds the set of trixels that cover the circular aperture specified after first performing a reverse ...
Definition skymesh.cpp:56
Trixel index(const SkyPoint *p)
returns the index of the trixel containing p.
Definition skymesh.cpp:74
Provides virtual functions for update of coordinates and nodes hiding.
Definition skynode.h:28
Wrapper for SkyObject to allow access of some of its properties from QML.
void setObject(SkyObject *object)
sets SkyObject that is needed to be wrapped
Provides all necessary information about an object in the sky: its coordinates, name(s),...
Definition skyobject.h:42
virtual QString name(void) const
Definition skyobject.h:146
Wrapper for SkyPoint to allow access of some of its properties from QML.
void setPoint(SkyPoint *point)
sets SkyPoint that is needed to be wrapped
static const double altCrit
Critical height for atmospheric refraction corrections.
Definition skypoint.h:727
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
static double unrefract(const double alt, bool conditional=true)
Remove refraction correction, depending on conditional.
Implememntation of Stereographic projection
device handle controlling telescope.
void addTelescope(INDI::BaseDevice *bd)
Add telescope symbol for device bd.
void removeTelescope(INDI::BaseDevice *bd)
Remove telescope symbol of device bd.
This is just a container that holds information needed to do projections.
Definition projector.h:37
bool fillGround
If the ground is filled, then points below horizon are invisible.
Definition projector.h:44
static constexpr double PI
PI is a const static member; it's public so that it can be used anywhere, as long as dms....
Definition dms.h:385
QString i18n(const char *text, const TYPE &arg...)
QColor fromRgb(QRgb rgb)
void getHsvF(float *h, float *s, float *v, float *a) const const
void setHsvF(float h, float s, float v, float a)
int descent() const const
int height() const const
Format_ARGB32_Premultiplied
void append(QList< T > &&value)
iterator begin()
void clear()
qsizetype count() const const
iterator end()
qsizetype size() const const
T value(qsizetype i) const const
QMetaObject::Connection connect(const QObject *sender, PointerToMemberFunction signal, Functor functor)
bool begin(QPaintDevice *device)
void drawEllipse(const QPoint &center, int rx, int ry)
void drawLine(const QLine &line)
void drawPoint(const QPoint &position)
void drawText(const QPoint &position, const QString &text)
bool end()
const QPen & pen() const const
void setBrush(Qt::BrushStyle style)
void setFont(const QFont &font)
void setPen(Qt::PenStyle style)
void setRenderHint(RenderHint hint, bool on)
QColor color() const const
void fill(const QColor &color)
QPixmap scaled(const QSize &size, Qt::AspectRatioMode aspectRatioMode, Qt::TransformationMode transformMode) const const
QCursor cursor() const const
void heightChanged()
void setCursor(const QCursor &cursor)
QSizeF size() const const
void update()
void widthChanged()
QQuickWindow * window() const const
QSGTexture * createTextureFromImage(const QImage &image) const const
qreal effectiveDevicePixelRatio() const const
QString & fill(QChar ch, qsizetype size)
KeepAspectRatio
SizeAllCursor
AllButtons
SmoothTransformation
QFuture< ArgsType< Signal > > connect(Sender *sender, Signal signal)
void start()
This file is part of the KDE documentation.
Documentation copyright © 1996-2024 The KDE developers.
Generated on Mon Nov 18 2024 12:16:41 by doxygen 1.12.0 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.