Warning, file /education/kstars/kstars/skymapdrawabstract.cpp was not indexed or was modified since last indexation (in which case cross-reference links may be missing, inaccurate or erroneous).
0001 /* 0002 SPDX-FileCopyrightText: 2001 Jason Harris <jharris@30doradus.org> 0003 0004 SPDX-License-Identifier: GPL-2.0-or-later 0005 */ 0006 0007 // This file implements the class SkyMapDrawAbstract, and is almost 0008 // identical to the older skymapdraw.cpp file, written by Jason 0009 // Harris. Essentially, skymapdraw.cpp was renamed and modified. 0010 // -- asimha (2011) 0011 0012 #include <QPainter> 0013 #include <QPixmap> 0014 0015 #include "skymapdrawabstract.h" 0016 #include "skymap.h" 0017 #include "Options.h" 0018 #include "fov.h" 0019 #include "kstars.h" 0020 #include "kstarsdata.h" 0021 #include "ksnumbers.h" 0022 #include "ksutils.h" 0023 #include "skyobjects/skyobject.h" 0024 #include "skyobjects/catalogobject.h" 0025 #include "catalogsdb.h" 0026 #include "skyobjects/starobject.h" 0027 #include "skyobjects/ksplanetbase.h" 0028 #include "simclock.h" 0029 #include "observinglist.h" 0030 #include "skycomponents/constellationboundarylines.h" 0031 #include "skycomponents/skylabeler.h" 0032 #include "skycomponents/skymapcomposite.h" 0033 #include "skyqpainter.h" 0034 #include "projections/projector.h" 0035 #include "projections/lambertprojector.h" 0036 0037 #include <config-kstars.h> 0038 0039 #ifdef HAVE_INDI 0040 #include <basedevice.h> 0041 #include "indi/indilistener.h" 0042 #include "indi/driverinfo.h" 0043 #include "indi/indistd.h" 0044 #include "indi/indimount.h" 0045 #endif 0046 0047 bool SkyMapDrawAbstract::m_DrawLock = false; 0048 0049 SkyMapDrawAbstract::SkyMapDrawAbstract(SkyMap *sm) : m_KStarsData(KStarsData::Instance()), m_SkyMap(sm) 0050 { 0051 //m_fpstime.start(); 0052 //m_framecount = 0; 0053 } 0054 0055 void SkyMapDrawAbstract::drawOverlays(QPainter &p, bool drawFov) 0056 { 0057 if (!KStars::Instance()) 0058 return; 0059 0060 //draw labels 0061 SkyLabeler::Instance()->draw(p); 0062 0063 if (drawFov) 0064 { 0065 //draw FOV symbol 0066 foreach (FOV *fov, m_KStarsData->getVisibleFOVs()) 0067 { 0068 if (fov->lockCelestialPole()) 0069 { 0070 SkyPoint centerSkyPoint = SkyMap::Instance()->projector()->fromScreen(p.viewport().center(), KStarsData::Instance()->lst(), 0071 KStarsData::Instance()->geo()->lat()); 0072 QPointF screenSkyPoint = p.viewport().center(); 0073 double northRotation = SkyMap::Instance()->projector()->findNorthPA(¢erSkyPoint, screenSkyPoint.x(), 0074 screenSkyPoint.y()); 0075 fov->setCenter(centerSkyPoint); 0076 fov->setNorthPA(northRotation); 0077 } 0078 fov->draw(p, Options::zoomFactor()); 0079 } 0080 } 0081 0082 drawSolverFOV(p); 0083 0084 drawTelescopeSymbols(p); 0085 0086 drawZoomBox(p); 0087 0088 // FIXME: Maybe we should take care of this differently. Maybe 0089 // drawOverlays should remain in SkyMap, since it just calls 0090 // certain drawing functions which are implemented in 0091 // SkyMapDrawAbstract. Really, it doesn't draw anything on its 0092 // own. 0093 if (m_SkyMap->rulerMode) 0094 { 0095 m_SkyMap->updateAngleRuler(); 0096 drawAngleRuler(p); 0097 } 0098 } 0099 0100 void SkyMapDrawAbstract::drawAngleRuler(QPainter &p) 0101 { 0102 //FIXME use sky painter. 0103 p.setPen(QPen(m_KStarsData->colorScheme()->colorNamed("AngularRuler"), 3.0, Qt::DotLine)); 0104 p.drawLine( 0105 m_SkyMap->m_proj->toScreen(m_SkyMap->AngularRuler.point( 0106 0)), // FIXME: More ugliness. m_proj should probably be a single-instance class, or we should have our own instance etc. 0107 m_SkyMap->m_proj->toScreen(m_SkyMap->AngularRuler.point( 0108 1))); // FIXME: Again, AngularRuler should be something better -- maybe a class in itself. After all it's used for more than one thing after we integrate the StarHop feature. 0109 } 0110 0111 void SkyMapDrawAbstract::drawZoomBox(QPainter &p) 0112 { 0113 //draw the manual zoom-box, if it exists 0114 if (m_SkyMap->ZoomRect.isValid()) 0115 { 0116 p.setPen(QPen(Qt::white, 1.0, Qt::DotLine)); 0117 p.drawRect(m_SkyMap->ZoomRect.x(), m_SkyMap->ZoomRect.y(), m_SkyMap->ZoomRect.width(), 0118 m_SkyMap->ZoomRect.height()); 0119 } 0120 } 0121 0122 void SkyMapDrawAbstract::drawObjectLabels(QList<SkyObject *> &labelObjects) 0123 { 0124 bool checkSlewing = 0125 (m_SkyMap->slewing || (m_SkyMap->clockSlewing && m_KStarsData->clock()->isActive())) && Options::hideOnSlew(); 0126 if (checkSlewing && Options::hideLabels()) 0127 return; 0128 0129 SkyLabeler *skyLabeler = SkyLabeler::Instance(); 0130 skyLabeler->resetFont(); // use the zoom dependent font 0131 0132 skyLabeler->setPen(m_KStarsData->colorScheme()->colorNamed("UserLabelColor")); 0133 0134 bool drawPlanets = Options::showSolarSystem() && !(checkSlewing && Options::hidePlanets()); 0135 bool drawComets = drawPlanets && Options::showComets(); 0136 bool drawAsteroids = drawPlanets && Options::showAsteroids(); 0137 bool drawOther = Options::showDeepSky() && Options::showOther() && !(checkSlewing && Options::hideOther()); 0138 bool drawStars = Options::showStars(); 0139 bool hideFaintStars = checkSlewing && Options::hideStars(); 0140 0141 //Attach a label to the centered object 0142 if (m_SkyMap->focusObject() != nullptr && Options::useAutoLabel()) 0143 { 0144 QPointF o = 0145 m_SkyMap->m_proj->toScreen(m_SkyMap->focusObject()); // FIXME: Same thing. m_proj should be accessible here. 0146 skyLabeler->drawNameLabel(m_SkyMap->focusObject(), o); 0147 } 0148 0149 foreach (SkyObject *obj, labelObjects) 0150 { 0151 //Only draw an attached label if the object is being drawn to the map 0152 //reproducing logic from other draw funcs here...not an optimal solution 0153 if (obj->type() == SkyObject::STAR || obj->type() == SkyObject::CATALOG_STAR || 0154 obj->type() == SkyObject::MULT_STAR) 0155 { 0156 if (!drawStars) 0157 continue; 0158 // if ( obj->mag() > Options::magLimitDrawStar() ) continue; 0159 if (hideFaintStars && obj->mag() > Options::magLimitHideStar()) 0160 continue; 0161 } 0162 if (obj->type() == SkyObject::PLANET) 0163 { 0164 if (!drawPlanets) 0165 continue; 0166 if (obj->name() == i18n("Sun") && !Options::showSun()) 0167 continue; 0168 if (obj->name() == i18n("Mercury") && !Options::showMercury()) 0169 continue; 0170 if (obj->name() == i18n("Venus") && !Options::showVenus()) 0171 continue; 0172 if (obj->name() == i18n("Moon") && !Options::showMoon()) 0173 continue; 0174 if (obj->name() == i18n("Mars") && !Options::showMars()) 0175 continue; 0176 if (obj->name() == i18n("Jupiter") && !Options::showJupiter()) 0177 continue; 0178 if (obj->name() == i18n("Saturn") && !Options::showSaturn()) 0179 continue; 0180 if (obj->name() == i18n("Uranus") && !Options::showUranus()) 0181 continue; 0182 if (obj->name() == i18n("Neptune") && !Options::showNeptune()) 0183 continue; 0184 //if ( obj->name() == i18n( "Pluto" ) && ! Options::showPluto() ) continue; 0185 } 0186 if ((obj->type() >= SkyObject::OPEN_CLUSTER && obj->type() <= SkyObject::GALAXY) || 0187 (obj->type() >= SkyObject::ASTERISM && obj->type() <= SkyObject::QUASAR) || 0188 (obj->type() == SkyObject::RADIO_SOURCE)) 0189 { 0190 if (((CatalogObject *)obj)->getCatalog().id == -1 && !drawOther) 0191 continue; 0192 } 0193 if (obj->type() == SkyObject::COMET && !drawComets) 0194 continue; 0195 if (obj->type() == SkyObject::ASTEROID && !drawAsteroids) 0196 continue; 0197 0198 if (!m_SkyMap->m_proj->checkVisibility(obj)) 0199 continue; // FIXME: m_proj should be a member of this class. 0200 QPointF o = m_SkyMap->m_proj->toScreen(obj); 0201 if (!m_SkyMap->m_proj->onScreen(o)) 0202 continue; 0203 0204 skyLabeler->drawNameLabel(obj, o); 0205 } 0206 0207 skyLabeler->useStdFont(); // use the StdFont for the guides. 0208 } 0209 0210 void SkyMapDrawAbstract::drawSolverFOV(QPainter &psky) 0211 { 0212 Q_UNUSED(psky) 0213 0214 #ifdef HAVE_INDI 0215 0216 for (auto oneFOV : KStarsData::Instance()->getTransientFOVs()) 0217 { 0218 QVariant visible = oneFOV->property("visible"); 0219 if (visible.isNull() || visible.toBool() == false) 0220 continue; 0221 0222 if (oneFOV->objectName() == "sensor_fov") 0223 { 0224 oneFOV->setColor(KStars::Instance()->data()->colorScheme()->colorNamed("SensorFOVColor").name()); 0225 SkyPoint centerSkyPoint = SkyMap::Instance()->projector()->fromScreen(psky.viewport().center(), 0226 KStarsData::Instance()->lst(), KStarsData::Instance()->geo()->lat()); 0227 QPointF screenSkyPoint = psky.viewport().center(); 0228 double northRotation = SkyMap::Instance()->projector()->findNorthPA(¢erSkyPoint, screenSkyPoint.x(), 0229 screenSkyPoint.y()); 0230 oneFOV->setCenter(centerSkyPoint); 0231 oneFOV->setNorthPA(northRotation); 0232 oneFOV->draw(psky, Options::zoomFactor()); 0233 } 0234 else if (oneFOV->objectName() == "solver_fov") 0235 { 0236 bool isVisible = false; 0237 SkyPoint p = oneFOV->center(); 0238 if (std::isnan(p.ra().Degrees())) 0239 continue; 0240 0241 p.EquatorialToHorizontal(KStarsData::Instance()->lst(), KStarsData::Instance()->geo()->lat()); 0242 QPointF point = SkyMap::Instance()->projector()->toScreen(&p, true, &isVisible); 0243 double northRotation = SkyMap::Instance()->projector()->findNorthPA(&p, point.x(), point.y()); 0244 oneFOV->setNorthPA(northRotation); 0245 oneFOV->draw(psky, Options::zoomFactor()); 0246 } 0247 } 0248 #endif 0249 } 0250 0251 void SkyMapDrawAbstract::drawTelescopeSymbols(QPainter &psky) 0252 { 0253 Q_UNUSED(psky) 0254 0255 #ifdef HAVE_INDI 0256 if (!Options::showTargetCrosshair()) 0257 return; 0258 0259 if (INDIListener::Instance()->size() == 0) 0260 return; 0261 SkyPoint indi_sp; 0262 0263 psky.setPen(QPen(QColor(m_KStarsData->colorScheme()->colorNamed("TargetColor")))); 0264 psky.setBrush(Qt::NoBrush); 0265 float pxperdegree = Options::zoomFactor() / 57.3; 0266 0267 for (auto &oneDevice : INDIListener::devices()) 0268 { 0269 if (!(oneDevice->getDriverInterface() & INDI::BaseDevice::TELESCOPE_INTERFACE) || oneDevice->isConnected() == false) 0270 continue; 0271 0272 auto mount = oneDevice->getMount(); 0273 if (!mount) 0274 continue; 0275 0276 auto coordNP = mount->currentCoordinates(); 0277 0278 QPointF P = m_SkyMap->m_proj->toScreen(&coordNP); 0279 if (Options::useAntialias()) 0280 { 0281 float s1 = 0.5 * pxperdegree; 0282 float s2 = pxperdegree; 0283 float s3 = 2.0 * pxperdegree; 0284 0285 float x0 = P.x(); 0286 float y0 = P.y(); 0287 float x1 = x0 - 0.5 * s1; 0288 float y1 = y0 - 0.5 * s1; 0289 float x2 = x0 - 0.5 * s2; 0290 float y2 = y0 - 0.5 * s2; 0291 float x3 = x0 - 0.5 * s3; 0292 float y3 = y0 - 0.5 * s3; 0293 0294 //Draw radial lines 0295 psky.drawLine(QPointF(x1, y0), QPointF(x3, y0)); 0296 psky.drawLine(QPointF(x0 + s2, y0), QPointF(x0 + 0.5 * s1, y0)); 0297 psky.drawLine(QPointF(x0, y1), QPointF(x0, y3)); 0298 psky.drawLine(QPointF(x0, y0 + 0.5 * s1), QPointF(x0, y0 + s2)); 0299 //Draw circles at 0.5 & 1 degrees 0300 psky.drawEllipse(QRectF(x1, y1, s1, s1)); 0301 psky.drawEllipse(QRectF(x2, y2, s2, s2)); 0302 0303 psky.drawText(QPointF(x0 + s2 + 2., y0), mount->getDeviceName()); 0304 } 0305 else 0306 { 0307 int s1 = int(0.5 * pxperdegree); 0308 int s2 = int(pxperdegree); 0309 int s3 = int(2.0 * pxperdegree); 0310 0311 int x0 = int(P.x()); 0312 int y0 = int(P.y()); 0313 int x1 = x0 - s1 / 2; 0314 int y1 = y0 - s1 / 2; 0315 int x2 = x0 - s2 / 2; 0316 int y2 = y0 - s2 / 2; 0317 int x3 = x0 - s3 / 2; 0318 int y3 = y0 - s3 / 2; 0319 0320 //Draw radial lines 0321 psky.drawLine(QPoint(x1, y0), QPoint(x3, y0)); 0322 psky.drawLine(QPoint(x0 + s2, y0), QPoint(x0 + s1 / 2, y0)); 0323 psky.drawLine(QPoint(x0, y1), QPoint(x0, y3)); 0324 psky.drawLine(QPoint(x0, y0 + s1 / 2), QPoint(x0, y0 + s2)); 0325 //Draw circles at 0.5 & 1 degrees 0326 psky.drawEllipse(QRect(x1, y1, s1, s1)); 0327 psky.drawEllipse(QRect(x2, y2, s2, s2)); 0328 0329 psky.drawText(QPoint(x0 + s2 + 2, y0), mount->getDeviceName()); 0330 } 0331 } 0332 #endif 0333 } 0334 0335 void SkyMapDrawAbstract::exportSkyImage(QPaintDevice *pd, bool scale) 0336 { 0337 SkyQPainter p(m_SkyMap, pd); 0338 p.begin(); 0339 p.setRenderHint(QPainter::SmoothPixmapTransform, true); 0340 0341 exportSkyImage(&p, scale); 0342 0343 p.end(); 0344 } 0345 0346 void SkyMapDrawAbstract::exportSkyImage(SkyQPainter *painter, bool scale) 0347 { 0348 bool vectorStarState; 0349 vectorStarState = painter->getVectorStars(); 0350 painter->setVectorStars( 0351 true); // Since we are exporting an image, we may use vector stars without worrying about time 0352 painter->setRenderHint(QPainter::Antialiasing, Options::useAntialias()); 0353 0354 if (scale) 0355 { 0356 //scale sky image to fit paint device 0357 qDebug() << Q_FUNC_INFO << "Scaling true while exporting Sky Image"; 0358 double xscale = double(painter->device()->width()) / double(m_SkyMap->width()); 0359 double yscale = double(painter->device()->height()) / double(m_SkyMap->height()); 0360 double scale = qMin(xscale, yscale); 0361 qDebug() << Q_FUNC_INFO << "xscale: " << xscale << "yscale: " << yscale << "chosen scale: " << scale; 0362 painter->scale(scale, scale); 0363 } 0364 0365 painter->drawSkyBackground(); 0366 m_KStarsData->skyComposite()->draw(painter); 0367 drawOverlays(*painter); 0368 painter->setVectorStars(vectorStarState); // Restore the state of the painter 0369 } 0370 0371 /* JM 2016-05-03: Not needed since we're not using OpenGL for now 0372 * void SkyMapDrawAbstract::calculateFPS() 0373 { 0374 if(m_framecount == 25) { 0375 //float sec = m_fpstime.elapsed()/1000.; 0376 // qDebug() << Q_FUNC_INFO << "FPS " << m_framecount/sec; 0377 m_framecount = 0; 0378 m_fpstime.restart(); 0379 } 0380 ++m_framecount; 0381 }*/ 0382 0383 void SkyMapDrawAbstract::setDrawLock(bool state) 0384 { 0385 m_DrawLock = state; 0386 }