static void solveCometElliptic(comet_t *com, double dt, double &r, double &v) { double a = com->q / (1 - com->e); double n = 0.01720209895/(a * sqrt(a)); double M = n * dt; double E = cAstro.solveKepler(com->e, M); double num = sqrt(1.0 + com->e) * tan(E / 2.0); double den = sqrt(1.0 - com->e); v = 2.0 * atan2(num, den); r = a * (1.0 - com->e * cos(E)); rangeDbl(&v, MPI2); }
static void solveCometParabolic(comet_t *com, double dt, double &r, double &v) { double w = 3.649116245E-2 * (dt) / (com->q * sqrt(com->q)); double s1 = 0.0; double s; do { s = s1; s1 = (2.0 * s * s * s + w) / (3.0 * (s * s + 1.0)); } while (qAbs(s1 - s) > 1.0E-9); s = s1; v = 2.0 * atan(s); r = com->q * (1.0 + s * s); rangeDbl(&v, MPI2); }
static void solveCometHyperbolic(comet_t *com, double dt, double &r, double &v) { double da = com->q / qAbs(1.0 - com->e); double n0 = 0.01720209895 / (da * sqrt(da)); double m = n0 * dt; double U = 0.5; double U0; do { U0 = U ; U = (2 * U0 * (com->e - U0 * (1 - m - log(qAbs(U0))))) / (com->e * (U0 * U0 + 1) - 2 * U0); } while (qAbs(U - U0) > 1E-9); double num = sqrt(com->e * com->e - 1)*(U * U - 1)/(2 * U) ; double den = com->e-(U * U + 1)/(2 * U) ; v = atan2(num, den); r = qAbs(da * ((com->e * (U * U + 1)/(2 * U)) - 1)); rangeDbl(&v, MPI2); }
void SkServer::setRA_Dec(const QString &data) { CMapView *view = m_mainWin->getView(); QStringList args = data.split(","); if (args.count() < 2 || args.count() > 3) { sendData(SKS_INVALID); return; } double ra, dec, fov = CM_UNDEF; if (args.count() >= 2) { ra = D2R(args[0].toDouble()); dec = D2R(args[1].toDouble()); } if (args.count() == 3) { fov = D2R(args[2].toDouble()); } rangeDbl(&ra, R360); dec = CLAMP(dec, -R90, R90); if (fov > CM_UNDEF) { fov = CLAMP(fov, MIN_MAP_FOV, MAX_MAP_FOV); } if (view->m_mapView.epochJ2000 && view->m_mapView.coordType == SMCT_RA_DEC) { precess(&ra, &dec, JD2000, view->m_mapView.jd); } view->centerMap(ra, dec, fov); sendData(SKS_OK); }
void CGrid::renderGrid(int type, SKMATRIX *mat, mapView_t *mapView, CSkPainter *pPainter, bool eqOnly) ////////////////////////////////////////////////////////////////////////////////////////////////////// { double spc; double cx, cy; setSetFont(FONT_GRID, pPainter); trfGetScreenSize(scrWidth, scrHeight); QColor col = g_skSet.map.grid[type].color; pPainter->setPen(col); pPainter->drawRect(clipSize, clipSize, scrWidth - clipSize * 2, scrHeight - clipSize * 2); if (type == SMCT_ECL || type == SMCT_ALT_AZM) { radec_t rd; SKPOINT pt; double sx, sy; trfGetCenter(sx, sy); trfConvScrPtToXY(sx, sy, cx, cy); rd.Ra = cx; rd.Dec = cy; precess(&rd.Ra, &rd.Dec, mapView->jd, JD2000); SKMATRIX matInv; SKMATRIXInverse(&matInv, mat); trfRaDecToPointNoCorrect(&rd, &pt, &matInv); cx = -atan2(pt.w.x, pt.w.z); cy = atan2(-pt.w.y, sqrt(pt.w.x * pt.w.x + pt.w.z * pt.w.z)); rangeDbl(&cx, R360); if (type == SMCT_ALT_AZM) { cy += cAstro.getAtmRef(cy); } } else { double sx, sy; trfGetCenter(sx, sy); trfConvScrPtToXY(sx, sy, cx, cy); if (mapView->coordType == SMCT_RA_DEC && mapView->epochJ2000) { precess(&cx, &cy, mapView->jd, JD2000); } } if (mapView->fov > D2R(45)) spc = 10; else if (mapView->fov > D2R(10)) spc = 5; else if (mapView->fov > D2R(5)) spc = 2; else if (mapView->fov > D2R(1)) spc = 1; else if (mapView->fov > D2R(0.5)) spc = 0.5; else if (mapView->fov > D2R(0.25)) spc = 0.1; else spc = (0.05); mSet.clear(); double spcx = spc; double spcy = spc; if (qAbs(mapView->y) > D2R(80)) { spcx *= 40; } else if (qAbs(mapView->y) > D2R(60)) { spcx *= 5; } else if (qAbs(mapView->y) > D2R(45)) { spcx *= 2; } spcx = CLAMP(spcx, 0.25, 10); spcy = CLAMP(spcy, 0.25, 10); double x = R2D(cx - fmod(cx, D2R(spcx))); double y; if (cy >= 0) { y = R2D(cy - fmod(cy, D2R(spcy))); } else { y = -(R2D(qAbs(cy) - fmod(qAbs(cy), D2R(spcy))) + spcy); if (y < -90) y = -90; } depth = 0; ren = 0; render(type, mat, mapView, pPainter, eqOnly, FROMRA(x), FROMDEC(y), FROMRA(spcx), FROMRA(spcy)); }
static void render(int type, SKMATRIX *mat, mapView_t *mapView, CSkPainter *pPainter, bool eqOnly, int x, int y, int spcx, int spcy) { if (x < 0) { x += 129600000; } else if (x >= 129600000) { x -= 129600000; } if (y < 0 || y > 64800000) { return; } radec_t rd[4]; if (mSet.contains(MAKE_INT64(x, y))) { // already rendered return; } QColor col = g_skSet.map.grid[type].color; QPen pen1 = QPen(col, 1); QPen pen3 = QPen(col, 3); rd[0].Ra = TORA(x); rd[0].Dec = TODEC(y); rd[1].Ra = TORA(x + spcx); rd[1].Dec = TODEC(y); rd[2].Ra = rd[1].Ra; rd[2].Dec = TODEC(y + spcy); rd[3].Ra = TORA(x); rd[3].Dec = rd[2].Dec; double dec = rd[0].Dec; double ra = rd[0].Ra; if (type == SMCT_ALT_AZM) { for (int i = 0; i < 4; i++) { rd[i].Dec -= cAstro.getInvAtmRef(rd[i].Dec); } } if (y + spcy > 64800000 && depth > 0) { return; } if (y + spcy < 00 && depth > 0) { return; } SKPOINT pt[4]; SKPOINT opt[4]; for (int i = 0; i < 4; i++) { trfRaDecToPointNoCorrect(&rd[i], &pt[i], mat); opt[i] = pt[i]; } if (!SKPLANECheckFrustumToPolygon(trfGetFrustum(), pt, 4)) { // out of screen return; } pPainter->setPen(pen1); ren++; if (!eqOnly && trfProjectLine(&pt[0], &pt[3])) { if ((y + spcy < 64800000 && y > 0) || (x == 0 || x == FROMRA(90) || x == FROMRA(180) || x == FROMRA(270))) { pPainter->setClipRect(clipSize, clipSize, scrWidth - clipSize * 2, scrHeight - clipSize * 2); pPainter->drawLine(pt[0].sx, pt[0].sy, pt[3].sx, pt[3].sy); pPainter->setClipping(false); int cx, cy; if (getClipPoint(cx, cy, pt[0].sx, pt[0].sy, pt[3].sx, pt[3].sy)) { QString text; if (g_skSet.map.showGridLabels && g_showLabels) { if (type == SMCT_RA_DEC) { text = getStrRA(ra, true); } else if (type == SMCT_ECL) { text = getStrDeg(ra, true); } else { double value = R360 - ra; rangeDbl(&value, R360); text = getStrDeg(value, true); } drawEdgeAlignTextY(pPainter, cx, cy, text); } } } } else { QPointF fpt[2]; if (eqOnly && y == 32400000 && trfProjectLine(&pt[0], &pt[3], fpt)) { QString text; if (g_skSet.map.showGridLabels && g_showLabels) { if (type == SMCT_RA_DEC) { text = getStrRA(ra, true); } else if (type == SMCT_ECL) { text = getStrDeg(ra, true); } else { double value = R360 - ra; rangeDbl(&value, R360); text = getStrDeg(value, true); } SKVECTOR v; double l = 10; QPointF fpt2[2]; trfProjectLine(&pt[0], &pt[1], fpt2); v.x = fpt2[0].x() - fpt2[1].x(); v.y = fpt2[0].y() - fpt2[1].y(); v.z = 0; SKVecNormalize(&v, &v); pPainter->setClipRect(clipSize, clipSize, scrWidth - clipSize * 2, scrHeight - clipSize * 2); pPainter->setPen(pen1); pPainter->drawLine(fpt[0].x(), fpt[0].y(), fpt[0].x() - v.y * l, fpt[0].y() + v.x * l); pPainter->drawLine(fpt[0].x(), fpt[0].y(), fpt[0].x() + v.y * l, fpt[0].y() - v.x * l); setSetFontColor(FONT_GRID, pPainter); pPainter->renderText(fpt[0].x(), fpt[0].y(), 10, text, RT_BOTTOM); pPainter->setClipping(false); } } } if ((eqOnly && y == 32400000) || !eqOnly) { int cx, cy; if (y == 32400000) { pPainter->setPen(pen3); } else { pPainter->setPen(pen1); } pPainter->setClipRect(clipSize, clipSize, scrWidth - clipSize * 2, scrHeight - clipSize * 2); if (drawInterpolatedLineRD(mat, 5, &rd[0], &rd[1], pPainter, cx, cy)) { pPainter->setClipping(false); if (g_skSet.map.showGridLabels && g_showLabels) { drawEdgeAlignTextX(pPainter, cx, cy, QString("%1").arg(getStrDeg(dec, true))); } } pPainter->setClipping(false); } mSet.insert(MAKE_INT64(x, y)); depth++; render(type, mat, mapView, pPainter, eqOnly, x - spcx, y, spcx, spcy); render(type, mat, mapView, pPainter, eqOnly, x + spcx, y, spcx, spcy); render(type, mat, mapView, pPainter, eqOnly, x, y + spcy, spcx, spcy); render(type, mat, mapView, pPainter, eqOnly, x, y - spcy, spcx, spcy); }
void SkServer::setExtFrame(const QString &data) { QStringList args = data.split(","); if (args.count() != 5) { sendData(SKS_INVALID); return; } double w; double h; double ra, dec; double angle; auto getVal = [this](const QString &str) -> double { QString tmp = str; if (str.endsWith("'")) { tmp.chop(1); return tmp.toDouble() * 60.0; } else if (str.endsWith("\"")) { tmp.chop(1); return tmp.toDouble(); } else { sendData(SKS_INVALID); return -1; } }; w = getVal(args[0]); if (w <= 0) return; h = getVal(args[1]); if (h <= 0) return; angle = args[2].toDouble(); ra = D2R(args[3].toDouble()); dec = D2R(args[4].toDouble()); radec_t rd; rangeDbl(&ra, R360); dec = CLAMP(dec, -R90, R90); CMapView *view = m_mainWin->getView(); if (!view->m_mapView.epochJ2000 && view->m_mapView.coordType == SMCT_RA_DEC) { precess(&ra, &dec, view->m_mapView.jd, JD2000); } rd.Ra = ra; rd.Dec = dec; w /= 3600.0; h /= 3600.0; w = D2R(w); h = D2R(h); g_cDrawing.insertExtFrame(&rd, w, h, angle, tr("External frame field")); sendData(SKS_OK); }
void comRender(CSkPainter *p, mapView_t *view, float maxMag) //////////////////////////////////////////////////////////// { if (tComets.count() == 0) return; int size = g_skSet.map.comet.radius; int lineSize = size * 4; int offsetX = lineSize * sin(D2R(22.5)); int offsetY = lineSize * cos(D2R(22.5)); int offset = lineSize; // TODO: dat asi cAstro do kazdeho vlakna #pragma omp parallel for shared(size, lineSize, offset, offsetX, offsetY) for (int i = 0; i < tComets.count(); i++) { int comaSize = 5; comet_t *a = &tComets[i]; if (!a->selected) continue; if (a->lastJD != view->jd || g_forcedRecalculate) { if (!comSolve(a, view->jd)) continue; // TODO: dat nejak najevo chybu vypoctu a->lastJD = view->jd; } if ((a->orbit.mag > maxMag + g_skSet.map.comet.plusMag) || (a->orbit.mag > g_skSet.map.comet.maxMag)) { continue; } SKPOINT pt; SKPOINT pt1; SKPOINT pt2; radec_t tail = {a->orbit.params[0], a->orbit.params[1]}; trfRaDecToPointCorrectFromTo(&a->orbit.lRD, &pt1, view->jd, JD2000); trfRaDecToPointCorrectFromTo(&tail, &pt2, view->jd, JD2000); if (trfProjectLine(&pt1, &pt2)) { float frac = a->orbit.mag / 10.; frac = 1 - CLAMP(frac, 0, 1); float opacity = LERP(frac, 0.25, 1); double cs = trfGetArcSecToPix(a->orbit.params[2]); if (!g_onPrinterBW) { QImage tailImage = QImage(":/res/comet_tail.png"); QImage comaImage = QImage(":/res/comet_coma.png"); trfRaDecToPointCorrectFromTo(&a->orbit.lRD, &pt1, view->jd, JD2000); trfRaDecToPointCorrectFromTo(&tail, &pt2, view->jd, JD2000); trfProjectLineNoCheck(&pt1, &pt2); double vx = pt1.sy - pt2.sy; double vy = -(pt1.sx - pt2.sx); double d = sqrt(POW2(vx) + POW2(vy)); double dx = pt1.sx - pt2.sx; double dy = pt1.sy - pt2.sy; double d1 = sqrt(POW2(dx) + POW2(dy)); vx /= d; vy /= d; dx /= d1; dy /= d1; double s = d * 0.5 * (tailImage.height() / (double)tailImage.width()); double s1 = d * 0.02; QPoint pts[4]; // tail pts[0] = QPoint((pt1.sx + (vx * s)) + (dx * s1), (pt1.sy + (vy * s)) + (dy * s1)); pts[1] = QPoint((pt1.sx - (vx * s)) + (dx * s1), (pt1.sy - (vy * s)) + (dy * s1)); pts[2] = QPoint(pt2.sx + vx * s, pt2.sy + vy * s); pts[3] = QPoint(pt2.sx - vx * s, pt2.sy - vy * s); #pragma omp critical { scanRender.resetScanPoly(p->image()->width(), p->image()->height()); scanRender.scanLine(pts[0].x(), pts[0].y(), pts[2].x(), pts[2].y(), 0, 0, 1, 0); scanRender.scanLine(pts[2].x(), pts[2].y(), pts[3].x(), pts[3].y(), 1, 0, 1, 1); scanRender.scanLine(pts[3].x(), pts[3].y(), pts[1].x(), pts[1].y(), 1, 1, 0, 1); scanRender.scanLine(pts[1].x(), pts[1].y(), pts[0].x(), pts[0].y(), 0, 1, 0, 0); scanRender.setOpacity(opacity); scanRender.renderPolygonAlpha(p->image(), &tailImage); p->save(); p->setOpacity(opacity); p->setRenderHint(QPainter::SmoothPixmapTransform, scanRender.isBillinearInt()); p->drawImage(QRect(pt1.sx - cs, pt1.sy - cs, cs * 2, cs * 2), comaImage); p->restore(); } } comaSize = qMax(cs, 1.0); } trfRaDecToPointCorrectFromTo(&a->orbit.lRD, &pt, view->jd, JD2000); if (trfProjectPoint(&pt)) { #pragma omp critical { double sunAng = -trfGetPosAngle(a->orbit.lRD.Ra, a->orbit.lRD.Dec, sunOrbit.lRD.Ra, sunOrbit.lRD.Dec); rangeDbl(&sunAng, R360); p->setBrush(QColor(g_skSet.map.comet.color)); p->setPen(g_skSet.map.comet.color); float ang = (float)trfGetAngleToNPole(a->orbit.lRD.Ra, a->orbit.lRD.Dec, view->jd); if (view->flipX + view->flipY == 1) { ang = R2D(R180 - sunAng + ang); } else { ang = R2D(R180 + sunAng + ang); } double sep = anSep(a->orbit.params[0], a->orbit.params[1], a->orbit.lRD.Ra, a->orbit.lRD.Dec); double r2 = trfGetArcSecToPix(R2D(sep) * 3600); if (r2 <= 20) { p->save(); p->translate(pt.sx, pt.sy); p->rotate(ang); p->drawEllipse(QPoint(0, 0), size, size); p->drawLine(0, 0, -offsetX, -offsetY); p->drawLine(0, 0, 0, -offset); p->drawLine(0, 0, offsetX, -offsetY); p->restore(); } else if (g_onPrinterBW) { p->save(); p->translate(pt.sx, pt.sy); p->rotate(ang); p->drawEllipse(QPoint(0, 0), size, size); double r1 = r2 * 0.1; double focus = sqrt(POW2(r2) - POW2(r1)); p->setBrush(Qt::NoBrush); p->drawEllipse(QPointF(0, -focus), r1, r2); p->drawLine(0, 0, -offsetX, -offsetY); p->drawLine(0, 0, 0, -offset); p->drawLine(0, 0, offsetX, -offsetY); p->restore(); } if (g_showLabels) { int align; if (sunAng >= 0 && sunAng < R90) { align = SL_AL_BOTTOM_LEFT; } else if (sunAng >= R90 && sunAng < R180) { align = SL_AL_TOP_LEFT; } else if (sunAng >= R180 && sunAng < R270) { align = SL_AL_TOP_RIGHT; } else { align = SL_AL_BOTTOM_RIGHT; } g_labeling.addLabel(QPoint(pt.sx, pt.sy), comaSize + 2, a->name, FONT_COMET, align, SL_AL_ALL); } addMapObj(pt.sx, pt.sy, MO_COMET, MO_CIRCLE, comaSize + 2, i, (qint64)a, a->orbit.mag); } } } }
static bool comSolve2(comet_t *a, double jdt, bool lightCorrected = true) ///////////////////////////////////////////////////////////////////////// { double R = 0, r = 0, v = 0; double xe = 0; double ye = 0; double ze = 0; double rh[3] = {0,0,0}; // NOTE: komety a asteroidy maji uz deltaT v sobe double t = (jdt - a->perihelionDate); for (int i = 0; i < (lightCorrected ? 2 : 1); i++) { if (a->e < 1.0) { solveCometElliptic(a, t, r, v); } else if (a->e == 1.0) { solveCometParabolic(a, t, r, v); } else { solveCometHyperbolic(a, t, r, v); } //////////////////////////////////////////////// double n = a->w; double p = a->W; // Helio. ecliptic J2000.0 rh[0] = r * ( cos(n) * cos(v + p) - sin(n) * sin(v + p) * cos(a->i)); rh[1] = r * ( sin(n) * cos(v + p) + cos(n) * sin(v + p) * cos(a->i)); rh[2] = r * ( sin(v + p) * sin(a->i)); // helio eqt. J2000.0 a->orbit.hRect[0] = rh[0]; a->orbit.hRect[1] = rh[1]; a->orbit.hRect[2] = rh[2]; a->orbit.hLon = atan2(rh[1], rh[0]); a->orbit.hLat = atan2(rh[2], sqrt(rh[0] * rh[0] + rh[1] * rh[1])); rangeDbl(&a->orbit.hLon, MPI2); // geocentric ecl. J2000.0 double xg = rh[0] + xs; double yg = rh[1] + ys; double zg = rh[2] + zs; // geocentric eq. J2000.0 double ea = cAstro.getEclObl(JD2000); xe = xg; ye = yg * cos(ea) - zg * sin(ea); ze = yg * sin(ea) + zg * cos(ea); a->orbit.r = r; a->orbit.R = sqrt(xg * xg + yg * yg + zg *zg); R = a->orbit.R; a->orbit.light = SECTODAY(a->orbit.R * AU1 / LSPEED); t -= a->orbit.light; } // from skychart sw double D = ((qMax(0.0, 1 - log(a->orbit.r)) / qMax(1.0, a->H - 2.0)) * 30.0 / a->orbit.R) * 60; double L = qMax(0.0, 1. - log(a->orbit.r)) / pow(qMax(1.0, (double)a->H), 1.5); a->orbit.params[2] = D; a->orbit.params[3] = L * AU1; double d = 1 / sqrt(POW2(rh[0]) + POW2(rh[1]) + POW2(rh[2])); double nsx = rh[0] * d; double nsy = rh[1] * d; double nsz = rh[2] * d; double tx = rh[0] + nsx * L; double ty = rh[1] + nsy * L; double tz = rh[2] + nsz * L; tx += xs; ty += ys; tz += zs; double ea = cAstro.getEclObl(JD2000); double txe = tx; double tye = ty * cos(ea) - tz * sin(ea); double tze = ty * sin(ea) + tz * cos(ea); // tail end ra/dec a->orbit.params[0] = atan2(tye, txe); a->orbit.params[1] = atan2(tze, sqrt(txe * txe + tye * tye)); a->orbit.gRD.Ra = atan2(ye, xe); a->orbit.gRD.Dec = atan2(ze, sqrt(xe * xe + ye * ye)); rangeDbl(&a->orbit.gRD.Ra, MPI2); precess(&a->orbit.gRD.Ra, &a->orbit.gRD.Dec, JD2000, jdt); precess(&a->orbit.params[0], &a->orbit.params[1], JD2000, jdt); a->orbit.mag = a->H + 5 * log10(a->orbit.R) + 2.5 * a->G * log10(a->orbit.r); a->orbit.elongation = acos((sunOrbit.r * sunOrbit.r + R * R - r * r) / (2 * sunOrbit.r * R)); if ((sunOrbit.r * sunOrbit.r + R * R - r*r) < 0) { a->orbit.elongation = -a->orbit.elongation; } a->orbit.sx = 0; a->orbit.sy = 0; a->orbit.phase = 1; #pragma omp critical { cAstro.calcParallax(&a->orbit); cAstro.convRD2AARef(a->orbit.lRD.Ra, a->orbit.lRD.Dec, &a->orbit.lAzm, &a->orbit.lAlt); } return(true); }