File indexing completed on 2024-04-21 14:46:32

0001 /*
0002     SPDX-FileCopyrightText: 2011 Rafał Kułaga <rl.kulaga@gmail.com>
0003 
0004     SPDX-License-Identifier: GPL-2.0-or-later
0005 */
0006 
0007 #include "simplefovexporter.h"
0008 
0009 #include "kstars.h"
0010 #include "kstarsdata.h"
0011 #include "skymap.h"
0012 #include "skyqpainter.h"
0013 #include "fov.h"
0014 #include "skymapcomposite.h"
0015 #include "kstars/Options.h"
0016 
0017 SimpleFovExporter::SimpleFovExporter()
0018     : m_KSData(KStarsData::Instance()), m_Map(KStars::Instance()->map()), m_StopClock(false), m_OverrideFovShape(false),
0019       m_DrawFovSymbol(false), m_PrevClockState(false), m_PrevSlewing(false), m_PrevPoint(nullptr), m_PrevZoom(0)
0020 {
0021 }
0022 
0023 void SimpleFovExporter::exportFov(SkyPoint *point, FOV *fov, QPaintDevice *pd)
0024 {
0025     saveState(true);
0026     pExportFov(point, fov, pd);
0027     restoreState(true);
0028 }
0029 
0030 void SimpleFovExporter::exportFov(FOV *fov, QPaintDevice *pd)
0031 {
0032     pExportFov(nullptr, fov, pd);
0033 }
0034 
0035 void SimpleFovExporter::exportFov(QPaintDevice *pd)
0036 {
0037     SkyQPainter painter(m_Map, pd);
0038     painter.begin();
0039 
0040     painter.drawSkyBackground();
0041 
0042     // translate painter coordinates - it's necessary to extract only the area of interest (FOV)
0043     int dx = (m_Map->width() - pd->width()) / 2;
0044     int dy = (m_Map->height() - pd->height()) / 2;
0045     painter.translate(-dx, -dy);
0046 
0047     m_KSData->skyComposite()->draw(&painter);
0048     m_Map->getSkyMapDrawAbstract()->drawOverlays(painter, false);
0049 }
0050 
0051 void SimpleFovExporter::exportFov(const QList<SkyPoint *> &points, const QList<FOV *> &fovs,
0052                                   const QList<QPaintDevice *> &pds)
0053 {
0054     Q_ASSERT(points.size() == fovs.size() && fovs.size() == pds.size());
0055 
0056     saveState(true);
0057 
0058     for (int i = 0; i < points.size(); i++)
0059     {
0060         exportFov(points.value(i), fovs.at(i), pds.value(i));
0061     }
0062 
0063     restoreState(true);
0064 }
0065 
0066 void SimpleFovExporter::exportFov(const QList<SkyPoint *> &points, FOV *fov, const QList<QPaintDevice *> &pds)
0067 {
0068     Q_ASSERT(points.size() == pds.size());
0069 
0070     saveState(true);
0071 
0072     for (int i = 0; i < points.size(); i++)
0073     {
0074         exportFov(points.at(i), fov, pds.at(i));
0075     }
0076 
0077     restoreState(true);
0078 }
0079 
0080 void SimpleFovExporter::pExportFov(SkyPoint *point, FOV *fov, QPaintDevice *pd)
0081 {
0082     if (point)
0083     {
0084         // center sky map on selected point
0085         m_Map->setClickedPoint(point);
0086         m_Map->slotCenter();
0087     }
0088 
0089     // this is temporary 'solution' that will be changed during the implementation of printing
0090     // on large paper sizes (>A4), in which case it'll be desirable to export high-res FOV
0091     // representations
0092     if (pd->height() > m_Map->height() || pd->width() > m_Map->width())
0093     {
0094         return;
0095     }
0096 
0097     // calculate zoom factor
0098     double zoom = 0;
0099     QRegion region;
0100     int regionX(0), regionY(0);
0101     double fovSizeX(0), fovSizeY(0);
0102     if (fov->sizeX() > fov->sizeY())
0103     {
0104         zoom = calculateZoomLevel(pd->width(), fov->sizeX());
0105 
0106         // calculate clipping region size
0107         fovSizeX = calculatePixelSize(fov->sizeX(), zoom);
0108         fovSizeY = calculatePixelSize(fov->sizeY(), zoom);
0109         regionX  = 0;
0110         regionY  = 0.5 * (pd->height() - fovSizeY);
0111     }
0112 
0113     else
0114     {
0115         zoom = calculateZoomLevel(pd->height(), fov->sizeY());
0116 
0117         // calculate clipping region size
0118         fovSizeX = calculatePixelSize(fov->sizeX(), zoom);
0119         fovSizeY = calculatePixelSize(fov->sizeY(), zoom);
0120         regionX  = 0.5 * (pd->width() - fovSizeX);
0121         regionY  = 0;
0122     }
0123 
0124     if (fov->shape() == FOV::SQUARE)
0125     {
0126         region = QRegion(regionX, regionY, fovSizeX, fovSizeY, QRegion::Rectangle);
0127     }
0128 
0129     else
0130     {
0131         region = QRegion(regionX, regionY, fovSizeX, fovSizeY, QRegion::Ellipse);
0132     }
0133 
0134     m_Map->setZoomFactor(zoom);
0135 
0136     SkyQPainter painter(m_Map, pd);
0137     painter.begin();
0138 
0139     painter.drawSkyBackground();
0140 
0141     if (!m_OverrideFovShape)
0142     {
0143         painter.setClipRegion(region);
0144     }
0145     // translate painter coordinates - it's necessary to extract only the area of interest (FOV)
0146     int dx = (m_Map->width() - pd->width()) / 2;
0147     int dy = (m_Map->height() - pd->height()) / 2;
0148     painter.translate(-dx, -dy);
0149 
0150     m_KSData->skyComposite()->draw(&painter);
0151     m_Map->getSkyMapDrawAbstract()->drawOverlays(painter, false);
0152 
0153     // reset painter coordinate transform to paint FOV symbol in the center
0154     painter.resetTransform();
0155 
0156     if (m_DrawFovSymbol)
0157     {
0158         fov->draw(painter, zoom);
0159     }
0160 }
0161 
0162 void SimpleFovExporter::saveState(bool savePos)
0163 {
0164     // stop simulation if it's not already stopped
0165     m_PrevClockState = m_KSData->clock()->isActive();
0166     if (m_StopClock && m_PrevClockState)
0167     {
0168         m_KSData->clock()->stop();
0169     }
0170 
0171     // disable useAnimatedSlewing option
0172     m_PrevSlewing = Options::useAnimatedSlewing();
0173     if (m_PrevSlewing)
0174     {
0175         Options::setUseAnimatedSlewing(false);
0176     }
0177 
0178     // save current central point and zoom level
0179     m_PrevPoint = savePos ? m_Map->focusPoint() : nullptr;
0180     m_PrevZoom  = Options::zoomFactor();
0181 }
0182 
0183 void SimpleFovExporter::restoreState(bool restorePos)
0184 {
0185     // restore previous useAnimatedSlewing option
0186     if (m_PrevSlewing)
0187     {
0188         Options::setUseAnimatedSlewing(true);
0189     }
0190 
0191     if (restorePos)
0192     {
0193         // restore previous central point
0194         m_Map->setClickedPoint(m_PrevPoint);
0195         m_Map->slotCenter();
0196     }
0197     // restore previous zoom level
0198     m_Map->setZoomFactor(m_PrevZoom);
0199 
0200     // restore clock state (if it was stopped)
0201     if (m_StopClock && m_PrevClockState)
0202     {
0203         m_KSData->clock()->start();
0204     }
0205 }