9#include "mosaictiles.h"
10#include "kstarsdata.h"
18 m_Pen.setColor(
QColor(200, 200, 200, 100));
23 m_TextPen.setWidth(2);
25 m_FocalLength = Options::telescopeFocalLength();
26 m_FocalReducer = Options::telescopeFocalReducer();
27 m_CameraSize.setWidth(Options::cameraWidth());
28 m_CameraSize.setHeight(Options::cameraHeight());
29 m_PixelSize.setWidth(Options::cameraPixelWidth());
30 m_PixelSize.setHeight(Options::cameraPixelHeight());
31 m_PositionAngle = Options::cameraRotation();
34 m_MosaicFOV = m_CameraFOV = calculateCameraFOV();
39MosaicTiles::~MosaicTiles()
43bool MosaicTiles::isValid()
const
45 return m_MosaicFOV.
width() > 0 && m_MosaicFOV.
height() > 0;
48void MosaicTiles::setPositionAngle(
double value)
50 m_PositionAngle = value;
53void MosaicTiles::setOverlap(
double value)
55 m_Overlap = (value < 0) ? 0 : (value > 100) ? 100 : value;
58std::shared_ptr<MosaicTiles::OneTile> MosaicTiles::oneTile(
int row,
int col)
60 int offset = row * m_GridSize.
width() + col;
62 if (offset < 0 || offset >= m_Tiles.
size())
65 return m_Tiles[offset];
68bool MosaicTiles::fromXML(
const QString &filename)
76 LilXML *xmlParser = newLilXML();
77 char errmsg[2048] = {0};
78 XMLEle *root =
nullptr;
82 m_OperationMode = MODE_OPERATION;
89 bool mosaicInfoFound =
false;
92 m_TrackChecked = m_FocusChecked = m_AlignChecked = m_GuideChecked =
false;
96 root = readXMLEle(xmlParser, c, errmsg);
100 for (ep = nextXMLEle(root, 1); ep !=
nullptr; ep = nextXMLEle(root, 0))
102 const char *tag = tagXMLEle(ep);
103 if (!strcmp(tag,
"Mosaic"))
105 mosaicInfoFound =
true;
106 XMLEle *subEP =
nullptr;
107 for (subEP = nextXMLEle(ep, 1); subEP !=
nullptr; subEP = nextXMLEle(ep, 0))
109 const char *subTag = tagXMLEle(subEP);
110 if (!strcmp(subTag,
"Target"))
111 setTargetName(pcdataXMLEle(subEP));
112 else if (!strcmp(subTag,
"Group"))
113 setGroup(pcdataXMLEle(subEP));
114 else if (!strcmp(subTag,
"FinishSequence"))
115 setCompletionCondition(subTag);
116 else if (!strcmp(subTag,
"FinishRepeat"))
117 setCompletionCondition(subTag, pcdataXMLEle(subEP));
118 else if (!strcmp(subTag,
"FinishSLoop"))
119 setCompletionCondition(subTag);
120 else if (!strcmp(subTag,
"Sequence"))
121 setSequenceFile(pcdataXMLEle(subEP));
122 else if (!strcmp(subTag,
"Directory"))
123 setOutputDirectory(pcdataXMLEle(subEP));
124 else if (!strcmp(subTag,
"FocusEveryN"))
125 setFocusEveryN(cLocale.
toInt(pcdataXMLEle(subEP)));
126 else if (!strcmp(subTag,
"AlignEveryN"))
127 setAlignEveryN(cLocale.
toInt(pcdataXMLEle(subEP)));
128 else if (!strcmp(subTag,
"TrackChecked"))
129 m_TrackChecked =
true;
130 else if (!strcmp(subTag,
"FocusChecked"))
131 m_FocusChecked =
true;
132 else if (!strcmp(subTag,
"AlignChecked"))
133 m_AlignChecked =
true;
134 else if (!strcmp(subTag,
"GuideChecked"))
135 m_GuideChecked =
true;
136 else if (!strcmp(subTag,
"Overlap"))
137 setOverlap(cLocale.
toDouble(pcdataXMLEle(subEP)));
138 else if (!strcmp(subTag,
"CenterRA"))
144 else if (!strcmp(subTag,
"CenterDE"))
150 else if (!strcmp(subTag,
"GridW"))
152 else if (!strcmp(subTag,
"GridH"))
154 else if (!strcmp(subTag,
"FOVW"))
156 else if (!strcmp(subTag,
"FOVH"))
158 else if (!strcmp(subTag,
"CameraFOVW"))
160 else if (!strcmp(subTag,
"CameraFOVH"))
164 else if (mosaicInfoFound && !strcmp(tag,
"Job"))
165 processJobInfo(ep, index++);
171 delLilXML(xmlParser);
176 delLilXML(xmlParser);
179 return mosaicInfoFound;
182bool MosaicTiles::processJobInfo(XMLEle *root,
int index)
191 for (ep = nextXMLEle(root, 1); ep !=
nullptr; ep = nextXMLEle(root, 0))
193 newTile.index = index;
194 if (!strcmp(tagXMLEle(ep),
"Coordinates"))
196 subEP = findXMLEle(ep,
"J2000RA");
201 newTile.skyCenter.setRA0(
ra);
203 subEP = findXMLEle(ep,
"J2000DE");
208 newTile.skyCenter.setDec0(de);
211 else if (!strcmp(tagXMLEle(ep),
"TileCenter"))
213 if ((subEP = findXMLEle(ep,
"X")))
214 newTile.center.setX(cLocale.
toDouble(pcdataXMLEle(subEP)));
215 if ((subEP = findXMLEle(ep,
"Y")))
216 newTile.center.setY(cLocale.
toDouble(pcdataXMLEle(subEP)));
217 if ((subEP = findXMLEle(ep,
"Rotation")))
218 newTile.rotation = cLocale.
toDouble(pcdataXMLEle(subEP));
220 else if (!strcmp(tagXMLEle(ep),
"PositionAngle"))
222 m_PositionAngle = cLocale.
toDouble(pcdataXMLEle(ep));
226 newTile.skyCenter.updateCoordsNow(KStarsData::Instance()->updateNum());
244void MosaicTiles::appendTile(
const OneTile &value)
246 m_Tiles.
append(std::make_shared<OneTile>(value));
249void MosaicTiles::appendEmptyTile()
251 m_Tiles.
append(std::make_shared<OneTile>());
254void MosaicTiles::clearTiles()
268 return QSizeF(tileCoord.
x() / 60.0 * toSpherical.width(), tileCoord.
y() / 60.0 * toSpherical.height());
271void MosaicTiles::createTiles(
bool s_shaped)
273 m_SShaped = s_shaped;
277void MosaicTiles::updateTiles()
280 const auto fovW = m_CameraFOV.
width();
281 const auto fovH = m_CameraFOV.
height();
282 const auto gridW = m_GridSize.
width();
283 const auto gridH = m_GridSize.
height();
286 double const xOffset = fovW * (1 - m_Overlap / 100.0);
287 double const yOffset = fovH * (1 - m_Overlap / 100.0);
290 double initX = +(fovW + xOffset * (gridW - 1)) / 2.0 - fovW;
291 double initY = -(fovH + yOffset * (gridH - 1)) / 2.0;
293 double x = initX, y = initY;
302 for (
int col = 0; col < gridW; col++)
304 y = (m_SShaped && (col % 2)) ? (y - yOffset) : initY;
306 for (
int row = 0; row < gridH; row++)
309 QPointF tile_center(pos.x() + (fovW / 2.0), pos.y() + (fovH / 2.0));
312 const auto tileSkyLocation =
QPointF(0, 0) - rotatePoint(tile_center,
QPointF(), m_PositionAngle);
315 const auto tileSkyOffsetScaled = adjustCoordinate(tileSkyLocation);
317 auto adjusted_ra0 = (
ra0().
Degrees() + tileSkyOffsetScaled.width()) / 15.0;
318 auto adjusted_de0 = (
dec0().
Degrees() + tileSkyOffsetScaled.height());
319 SkyPoint sky_center(adjusted_ra0, adjusted_de0);
320 sky_center.apparentCoord(
static_cast<long double>(J2000), KStarsData::Instance()->ut().djd());
322 auto tile_center_ra0 = sky_center.ra0().Degrees();
324 auto rotation = tile_center_ra0 - mosaic_center_ra0;
327 if (abs(rotation) <= 90.0)
329 auto next_index = ++index;
330 MosaicTiles::OneTile tile = {pos, tile_center, sky_center, rotation, next_index};
338 y += (m_SShaped && (col % 2)) ? -yOffset : +yOffset;
345void MosaicTiles::draw(
QPainter *painter)
347 if (m_Tiles.
size() == 0)
350 auto pixelScale = Options::zoomFactor() *
dms::DegToRad / 60.0;
351 const auto fovW = m_CameraFOV.
width() * pixelScale;
352 const auto fovH = m_CameraFOV.
height() * pixelScale;
353 const auto mosaicFOVW = m_MosaicFOV.
width() * pixelScale;
354 const auto mosaicFOVH = m_MosaicFOV.
height() * pixelScale;
355 const auto gridW = m_GridSize.
width();
356 const auto gridH = m_GridSize.
height();
359 QRect const oneRect(-fovW / 2, -fovH / 2, fovW, fovH);
361 auto alphaValue = m_PainterAlpha;
363 if (m_PainterAlphaAuto)
371 if (m_Tiles.
size() > 1)
372 alphaValue = (40 - m_Overlap / 2);
386 for (
int row = 0; row < gridH; row++)
388 for (
int col = 0; col < gridW; col++)
390 auto tile = oneTile(row, col);
395 painter->
translate(tile->center * pixelScale);
396 painter->
rotate(tile->rotation);
409 for (
int row = 0; row < gridH; row++)
411 for (
int col = 0; col < gridW; col++)
413 auto tile = oneTile(row, col);
418 painter->
translate(tile->center * pixelScale);
423 painter->
rotate(tile->rotation);
426 painter->
setPen(m_TextPen);
435 .arg(tile->skyCenter.ra0().toHMSString(), tile->skyCenter.dec0().toDMSString()));
437 .arg(tile->rotation >= 0.01 ?
'+' : tile->rotation <= -0.01 ?
'-' :
'~')
438 .
arg(abs(tile->rotation), 5,
'f', 2));
451 double cosTheta = cos(angleInRadians);
452 double sinTheta = sin(angleInRadians);
456 rotation_point.
setX((cosTheta * (pointToRotate.
x() - centerPoint.
x()) -
457 sinTheta * (pointToRotate.
y() - centerPoint.
y()) + centerPoint.
x()));
458 rotation_point.
setY((sinTheta * (pointToRotate.
x() - centerPoint.
x()) +
459 cosTheta * (pointToRotate.
y() - centerPoint.
y()) + centerPoint.
y()));
461 return rotation_point;
464QSizeF MosaicTiles::calculateTargetMosaicFOV()
const
466 const auto xFOV = m_CameraFOV.
width() * (1 - m_Overlap / 100.0);
467 const auto yFOV = m_CameraFOV.
height() * (1 - m_Overlap / 100.0);
468 return QSizeF(xFOV, yFOV);
471QSize MosaicTiles::mosaicFOVToGrid()
const
474 const auto xFOV = m_CameraFOV.
width() * (1 - m_Overlap / 100.0);
475 const auto yFOV = m_CameraFOV.
height() * (1 - m_Overlap / 100.0);
476 const auto xTiles = 1 + ceil((m_MosaicFOV.
width() - m_CameraFOV.
width()) / xFOV);
477 const auto yTiles = 1 + ceil((m_MosaicFOV.
height() - m_CameraFOV.
height()) / yFOV);
478 return QSize(xTiles, yTiles);
481QSizeF MosaicTiles::calculateCameraFOV()
const
483 auto reducedFocalLength = m_FocalLength * m_FocalReducer;
486 206264.8062470963552 * m_CameraSize.
width() * m_PixelSize.
width() / 60000.0 / reducedFocalLength;
488 206264.8062470963552 * m_CameraSize.
height() * m_PixelSize.
height() / 60000.0 / reducedFocalLength;
489 return QSizeF(fov_x, fov_y);
492void MosaicTiles::syncFOVs()
494 m_CameraFOV = calculateCameraFOV();
495 m_MosaicFOV = calculateTargetMosaicFOV();
void setH(const double &x) override
Sets the angle in hours, supplied as a double.
Provides all necessary information about an object in the sky: its coordinates, name(s),...
The sky coordinates of a point in the sky.
const CachingDms & dec() const
const CachingDms & ra0() const
virtual void updateCoordsNow(const KSNumbers *num)
updateCoordsNow Shortcut for updateCoords( const KSNumbers *num, false, nullptr, nullptr,...
const CachingDms & ra() const
void setRA0(dms r)
Sets RA0, the catalog Right Ascension.
const CachingDms & dec0() const
void setDec0(dms d)
Sets Dec0, the catalog Declination.
An angle, stored as degrees, but expressible in many ways.
virtual void setD(const double &x)
Sets floating-point value of angle, in degrees.
const double & Degrees() const
static constexpr double DegToRad
DegToRad is a const static member equal to the number of radians in one degree (dms::PI/180....
bool open(FILE *fh, OpenMode mode, FileHandleFlags handleFlags)
void setFileName(const QString &name)
void setPointSize(int pointSize)
void append(QList< T > &&value)
qsizetype size() const const
double toDouble(QStringView s, bool *ok) const const
int toInt(QStringView s, bool *ok) const const
const QBrush & brush() const const
void drawRect(const QRect &rectangle)
void drawText(const QPoint &position, const QString &text)
const QFont & font() const const
void setBrush(Qt::BrushStyle style)
void setFont(const QFont &font)
void setPen(Qt::PenStyle style)
void translate(const QPoint &offset)
void setHeight(int height)
qreal height() const const
void setHeight(qreal height)
void setWidth(qreal width)
qreal width() const const
QString arg(Args &&... args) const const