//! Make the first screen position correspond to the second (useful for mouse dragging) void StelMovementMgr::dragView(int x1, int y1, int x2, int y2) { if (dragTimeMode) { core->setTimeRate(0); Vec3d v1, v2; const StelProjectorP prj = core->getProjection(StelCore::FrameEquinoxEqu); prj->unProject(x2,y2, v2); prj->unProject(x1,y1, v1); v1[2]=0; v1.normalize(); v2[2]=0; v2.normalize(); double angle = (v2^v1)[2]; double deltaDay = angle/(2.*M_PI)*core->getLocalSiderealDayLength(); core->setJD(core->getJD()+deltaDay); addTimeDragPoint(x2, y2); } else { Vec3d tempvec1, tempvec2; const StelProjectorP prj = core->getProjection(StelCore::FrameJ2000); prj->unProject(x2,y2, tempvec2); prj->unProject(x1,y1, tempvec1); double az1, alt1, az2, alt2; StelUtils::rectToSphe(&az1, &alt1, j2000ToMountFrame(tempvec1)); StelUtils::rectToSphe(&az2, &alt2, j2000ToMountFrame(tempvec2)); panView(az2-az1, alt1-alt2); } setFlagTracking(false); setFlagLockEquPos(false); }
void PointerCoordinates::draw(StelCore *core) { if (!isEnabled()) return; const StelProjectorP prj = core->getProjection(StelCore::FrameJ2000, StelCore::RefractionAuto); StelPainter sPainter(prj); sPainter.setColor(textColor[0], textColor[1], textColor[2], 1.f); font.setPixelSize(getFontSize()); sPainter.setFont(font); QPoint p = QCursor::pos(); // get screen coordinates of mouse cursor Vec3d mousePosition; float wh = prj->getViewportWidth()/2; // get half of width of the screen float hh = prj->getViewportHeight()/2; // get half of height of the screen float mx = p.x()-wh; // point 0 in center of the screen, axis X directed to right float my = p.y()-hh; // point 0 in center of the screen, axis Y directed to bottom // calculate position of mouse cursor via position of center of the screen (and invert axis Y) prj->unProject(prj->getViewportPosX()+wh+mx, prj->getViewportPosY()+hh+1-my, mousePosition); double dec_j2000, ra_j2000; StelUtils::rectToSphe(&ra_j2000,&dec_j2000,mousePosition); // Calculate RA/DE (J2000.0) and show it... QString coordsText = QString("%1/%2").arg(StelUtils::radToHmsStr(ra_j2000, true)).arg(StelUtils::radToDmsStr(dec_j2000, true)); sPainter.drawText(getCoordinatesPlace(coordsText).first, getCoordinatesPlace(coordsText).second, coordsText); }
/************************************************************************* Find in a "clever" way an object from its equatorial position *************************************************************************/ StelObjectP StelObjectMgr::cleverFind(const StelCore* core, int x, int y) const { Vec3d v; const StelProjectorP prj = core->getProjection(StelCore::FrameJ2000); if (prj->unProject(x,y,v)) { // Nick Fedoseev patch: improve click match for refracted coordinates Vec3d win; prj->project(v,win); float dx = x - win.v[0]; float dy = y - win.v[1]; prj->unProject(x+dx, y+dy, v); return cleverFind(core, v); } return StelObjectP(); }
void AngleMeasure::handleMouseClicks(class QMouseEvent* event) { if (!flagShowAngleMeasure) { event->setAccepted(false); return; } if (event->type()==QEvent::MouseButtonPress && event->button()==Qt::LeftButton) { const StelProjectorP prj = StelApp::getInstance().getCore()->getProjection(StelCore::FrameEquinoxEqu); prj->unProject(event->x(),event->y(),startPoint); // first click reset the line... only draw it after we've dragged a little. if (!dragging) { lineVisible = false; endPoint = startPoint; } else lineVisible = true; dragging = true; calculateEnds(); event->setAccepted(true); return; } else if (event->type()==QEvent::MouseButtonRelease && event->button()==Qt::LeftButton) { dragging = false; calculateEnds(); event->setAccepted(true); return; } else if (event->type()==QEvent::MouseButtonPress && event->button()==Qt::RightButton) { const StelProjectorP prj = StelApp::getInstance().getCore()->getProjection(StelCore::FrameEquinoxEqu); prj->unProject(event->x(),event->y(),endPoint); calculateEnds(); event->setAccepted(true); return; } event->setAccepted(false); }
bool AngleMeasure::handleMouseMoves(int x, int y, Qt::MouseButtons) { if (dragging) { const StelProjectorP prj = StelApp::getInstance().getCore()->getProjection(StelCore::FrameEquinoxEqu); prj->unProject(x,y,endPoint); { // Nick Fedoseev patch: improve click match Vec3d win; prj->project(endPoint,win); float dx = x - win.v[0]; float dy = y - win.v[1]; prj->unProject(x+dx, y+dy, endPoint); } const StelProjectorP prjHor = StelApp::getInstance().getCore()->getProjection(StelCore::FrameAltAz, StelCore::RefractionOff); prjHor->unProject(x,y,endPointHor); calculateEnds(); lineVisible = true; return true; } else return false; }
bool AngleMeasure::handleMouseMoves(int x, int y, Qt::MouseButtons) { if (dragging) { const StelProjectorP prj = StelApp::getInstance().getCore()->getProjection(StelCore::FrameEquinoxEqu); prj->unProject(x,y,endPoint); calculateEnds(); lineVisible = true; return true; } else return false; }
void SlewDialog::getCenterInfo() { StelCore *core = StelApp::getInstance().getCore(); const StelProjectorP projector = core->getProjection(StelCore::FrameEquinoxEqu); Vec3d centerPosition; Vec2f center = projector->getViewportCenter(); projector->unProject(center[0], center[1], centerPosition); double dec_j2000 = 0; double ra_j2000 = 0; StelUtils::rectToSphe(&ra_j2000,&dec_j2000,core->equinoxEquToJ2000(centerPosition)); ui->spinBoxRA->setRadians(ra_j2000); ui->spinBoxDec->setRadians(dec_j2000); }
void AngleMeasure::handleMouseClicks(class QMouseEvent* event) { if (!flagShowAngleMeasure) { event->setAccepted(false); return; } if (event->type()==QEvent::MouseButtonPress && event->button()==Qt::LeftButton) { const StelProjectorP prj = StelApp::getInstance().getCore()->getProjection(StelCore::FrameEquinoxEqu); prj->unProject(event->x(),event->y(),startPoint); { // Nick Fedoseev patch: improve click match Vec3d win; prj->project(startPoint,win); float dx = event->x() - win.v[0]; float dy = event->y() - win.v[1]; prj->unProject(event->x()+dx, event->y()+dy, startPoint); } const StelProjectorP prjHor = StelApp::getInstance().getCore()->getProjection(StelCore::FrameAltAz, StelCore::RefractionOff); prjHor->unProject(event->x(),event->y(),startPointHor); // first click reset the line... only draw it after we've dragged a little. if (!dragging) { lineVisible = false; endPoint = startPoint; endPointHor=startPointHor; } else lineVisible = true; dragging = true; calculateEnds(); event->setAccepted(true); return; } else if (event->type()==QEvent::MouseButtonRelease && event->button()==Qt::LeftButton) { dragging = false; calculateEnds(); event->setAccepted(true); return; } else if (event->type()==QEvent::MouseButtonPress && event->button()==Qt::RightButton) { const StelProjectorP prj = StelApp::getInstance().getCore()->getProjection(StelCore::FrameEquinoxEqu); prj->unProject(event->x(),event->y(),endPoint); { // Nick Fedoseev patch: improve click match Vec3d win; prj->project(endPoint,win); float dx = event->x() - win.v[0]; float dy = event->y() - win.v[1]; prj->unProject(event->x()+dx, event->y()+dy, endPoint); } const StelProjectorP prjHor = StelApp::getInstance().getCore()->getProjection(StelCore::FrameAltAz, StelCore::RefractionOff); prjHor->unProject(event->x(),event->y(),endPointHor); calculateEnds(); event->setAccepted(true); return; } event->setAccepted(false); }
void PointerCoordinates::draw(StelCore *core) { if (!isEnabled()) return; const StelProjectorP prj = core->getProjection(StelCore::FrameJ2000, StelCore::RefractionAuto); StelPainter sPainter(prj); sPainter.setColor(textColor[0], textColor[1], textColor[2], 1.f); font.setPixelSize(getFontSize()); sPainter.setFont(font); QPoint p = StelMainView::getInstance().getMousePos(); // get screen coordinates of mouse cursor Vec3d mousePosition; float wh = prj->getViewportWidth()/2.; // get half of width of the screen float hh = prj->getViewportHeight()/2.; // get half of height of the screen float mx = p.x()-wh; // point 0 in center of the screen, axis X directed to right float my = p.y()-hh; // point 0 in center of the screen, axis Y directed to bottom // calculate position of mouse cursor via position of center of the screen (and invert axis Y) // If coordinates are invalid, don't draw them. bool coordsValid=false; coordsValid = prj->unProject(prj->getViewportPosX()+wh+mx, prj->getViewportPosY()+hh+1-my, mousePosition); { // Nick Fedoseev patch Vec3d win; prj->project(mousePosition,win); float dx = prj->getViewportPosX()+wh+mx - win.v[0]; float dy = prj->getViewportPosY()+hh+1-my - win.v[1]; coordsValid = prj->unProject(prj->getViewportPosX()+wh+mx+dx, prj->getViewportPosY()+hh+1-my+dy, mousePosition); } if (!coordsValid) return; bool withDecimalDegree = StelApp::getInstance().getFlagShowDecimalDegrees(); bool useSouthAzimuth = StelApp::getInstance().getFlagSouthAzimuthUsage(); QString coordsSystem, cxt, cyt; double cx, cy; switch (getCurrentCoordinateSystem()) { case RaDecJ2000: { StelUtils::rectToSphe(&cx,&cy,mousePosition); // Calculate RA/DE (J2000.0) and show it... coordsSystem = qc_("RA/Dec (J2000.0)", "abbreviated in the plugin"); if (withDecimalDegree) { cxt = StelUtils::radToDecDegStr(cx, 5, false, true); cyt = StelUtils::radToDecDegStr(cy); } else { cxt = StelUtils::radToHmsStr(cx, true); cyt = StelUtils::radToDmsStr(cy, true); } break; } case RaDec: { StelUtils::rectToSphe(&cx,&cy,core->j2000ToEquinoxEqu(mousePosition)); // Calculate RA/DE and show it... coordsSystem = qc_("RA/Dec", "abbreviated in the plugin"); if (withDecimalDegree) { cxt = StelUtils::radToDecDegStr(cx, 5, false, true); cyt = StelUtils::radToDecDegStr(cy); } else { cxt = StelUtils::radToHmsStr(cx, true); cyt = StelUtils::radToDmsStr(cy, true); } break; } case AltAzi: { StelUtils::rectToSphe(&cy,&cx,core->j2000ToAltAz(mousePosition, StelCore::RefractionAuto)); float direction = 3.; // N is zero, E is 90 degrees if (useSouthAzimuth) direction = 2.; cy = direction*M_PI - cy; if (cy > M_PI*2) cy -= M_PI*2; coordsSystem = qc_("Az/Alt", "abbreviated in the plugin"); if (withDecimalDegree) { cxt = StelUtils::radToDecDegStr(cy); cyt = StelUtils::radToDecDegStr(cx); } else { cxt = StelUtils::radToDmsStr(cy); cyt = StelUtils::radToDmsStr(cx); } break; } case Galactic: { StelUtils::rectToSphe(&cx,&cy,core->j2000ToGalactic(mousePosition)); // Calculate galactic position and show it... coordsSystem = qc_("Gal. Long/Lat", "abbreviated in the plugin"); if (withDecimalDegree) { cxt = StelUtils::radToDecDegStr(cx); cyt = StelUtils::radToDecDegStr(cy); } else { cxt = StelUtils::radToDmsStr(cx, true); cyt = StelUtils::radToDmsStr(cy, true); } break; } case Ecliptic: { double lambda, beta; StelUtils::rectToSphe(&cx,&cy,core->j2000ToEquinoxEqu(mousePosition)); StelUtils::equToEcl(cx, cy, core->getCurrentPlanet()->getRotObliquity(core->getJDE()), &lambda, &beta); // Calculate ecliptic position and show it... if (lambda<0) lambda+=2.0*M_PI; coordsSystem = qc_("Ecl. Long/Lat", "abbreviated in the plugin"); if (withDecimalDegree) { cxt = StelUtils::radToDecDegStr(lambda); cyt = StelUtils::radToDecDegStr(beta); } else { cxt = StelUtils::radToDmsStr(lambda, true); cyt = StelUtils::radToDmsStr(beta, true); } break; } case EclipticJ2000: { double lambda, beta; StelUtils::rectToSphe(&cx,&cy, mousePosition); StelUtils::equToEcl(cx, cy, core->getCurrentPlanet()->getRotObliquity(2451545.0), &lambda, &beta); // Calculate ecliptic position and show it... if (lambda<0) lambda+=2.0*M_PI; coordsSystem = qc_("Ecl. Long/Lat (J2000.0)", "abbreviated in the plugin"); if (withDecimalDegree) { cxt = StelUtils::radToDecDegStr(lambda); cyt = StelUtils::radToDecDegStr(beta); } else { cxt = StelUtils::radToDmsStr(lambda, true); cyt = StelUtils::radToDmsStr(beta, true); } break; } case HourAngle: { Vec3d v = core->j2000ToAltAz(mousePosition, StelCore::RefractionAuto); StelUtils::rectToSphe(&cx,&cy,Mat4d::zrotation(-core->getLocalSiderealTime())*core->altAzToEquinoxEqu(v, StelCore::RefractionOff)); cx = 2.*M_PI-cx; coordsSystem = qc_("HA/Dec", "abbreviated in the plugin"); if (withDecimalDegree) { double ha_sidereal = cx*12/M_PI; if (ha_sidereal>24.) ha_sidereal -= 24.; cxt = QString("%1h").arg(ha_sidereal, 0, 'f', 5); cyt = StelUtils::radToDecDegStr(cy); } else { cxt = StelUtils::radToHmsStr(cx); cyt = StelUtils::radToDmsStr(cy); } break; } } QString coordsText = QString("%1: %2/%3").arg(coordsSystem).arg(cxt).arg(cyt); sPainter.drawText(getCoordinatesPlace(coordsText).first, getCoordinatesPlace(coordsText).second, coordsText); }
//! Draw the sky grid in the current frame void SkyGrid::draw(const StelCore* core) const { const StelProjectorP prj = core->getProjection(frameType, frameType!=StelCore::FrameAltAz ? StelCore::RefractionAuto : StelCore::RefractionOff); if (!fader.getInterstate()) return; bool withDecimalDegree = dynamic_cast<StelGui*>(StelApp::getInstance().getGui())->getFlagShowDecimalDegrees(); // Look for all meridians and parallels intersecting with the disk bounding the viewport // Check whether the pole are in the viewport bool northPoleInViewport = false; bool southPoleInViewport = false; Vec3f win; if (prj->project(Vec3f(0,0,1), win) && prj->checkInViewport(win)) northPoleInViewport = true; if (prj->project(Vec3f(0,0,-1), win) && prj->checkInViewport(win)) southPoleInViewport = true; // Get the longitude and latitude resolution at the center of the viewport Vec3d centerV; prj->unProject(prj->getViewportPosX()+prj->getViewportWidth()/2, prj->getViewportPosY()+prj->getViewportHeight()/2+1, centerV); double lon2, lat2; StelUtils::rectToSphe(&lon2, &lat2, centerV); const double gridStepParallelRad = M_PI/180.*getClosestResolutionDMS(prj->getPixelPerRadAtCenter()); double gridStepMeridianRad; if (northPoleInViewport || southPoleInViewport) gridStepMeridianRad = (frameType==StelCore::FrameAltAz || frameType==StelCore::FrameGalactic) ? M_PI/180.* 10. : M_PI/180.* 15.; else { const double closetResLon = (frameType==StelCore::FrameAltAz || frameType==StelCore::FrameGalactic) ? getClosestResolutionDMS(prj->getPixelPerRadAtCenter()*std::cos(lat2)) : getClosestResolutionHMS(prj->getPixelPerRadAtCenter()*std::cos(lat2)); gridStepMeridianRad = M_PI/180.* ((northPoleInViewport || southPoleInViewport) ? 15. : closetResLon); } // Get the bounding halfspace const SphericalCap& viewPortSphericalCap = prj->getBoundingCap(); // Compute the first grid starting point. This point is close to the center of the screen // and lays at the intersection of a meridien and a parallel lon2 = gridStepMeridianRad*((int)(lon2/gridStepMeridianRad+0.5)); lat2 = gridStepParallelRad*((int)(lat2/gridStepParallelRad+0.5)); Vec3d firstPoint; StelUtils::spheToRect(lon2, lat2, firstPoint); firstPoint.normalize(); // Q_ASSERT(viewPortSphericalCap.contains(firstPoint)); // Initialize a painter and set openGL state StelPainter sPainter(prj); glEnable(GL_BLEND); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // Normal transparency mode Vec4f textColor(color[0], color[1], color[2], 0); sPainter.setColor(color[0],color[1],color[2], fader.getInterstate()); textColor*=2; textColor[3]=fader.getInterstate(); sPainter.setFont(font); ViewportEdgeIntersectCallbackData userData(&sPainter); userData.textColor = textColor; userData.frameType = frameType; ///////////////////////////////////////////////// // Draw all the meridians (great circles) SphericalCap meridianSphericalCap(Vec3d(1,0,0), 0); Mat4d rotLon = Mat4d::zrotation(gridStepMeridianRad); Vec3d fpt = firstPoint; Vec3d p1, p2; int maxNbIter = (int)(M_PI/gridStepMeridianRad); int i; for (i=0; i<maxNbIter; ++i) { StelUtils::rectToSphe(&lon2, &lat2, fpt); userData.raAngle = lon2; meridianSphericalCap.n = fpt^Vec3d(0,0,1); meridianSphericalCap.n.normalize(); if (!SphericalCap::intersectionPoints(viewPortSphericalCap, meridianSphericalCap, p1, p2)) { if (viewPortSphericalCap.d<meridianSphericalCap.d && viewPortSphericalCap.contains(meridianSphericalCap.n)) { // The meridian is fully included in the viewport, draw it in 3 sub-arcs to avoid length > 180. const Mat4d& rotLon120 = Mat4d::rotation(meridianSphericalCap.n, 120.*M_PI/180.); Vec3d rotFpt=fpt; rotFpt.transfo4d(rotLon120); Vec3d rotFpt2=rotFpt; rotFpt2.transfo4d(rotLon120); sPainter.drawGreatCircleArc(fpt, rotFpt, NULL, viewportEdgeIntersectCallback, &userData); sPainter.drawGreatCircleArc(rotFpt, rotFpt2, NULL, viewportEdgeIntersectCallback, &userData); sPainter.drawGreatCircleArc(rotFpt2, fpt, NULL, viewportEdgeIntersectCallback, &userData); fpt.transfo4d(rotLon); continue; } else break; } Vec3d middlePoint = p1+p2; middlePoint.normalize(); if (!viewPortSphericalCap.contains(middlePoint)) middlePoint*=-1.; // Draw the arc in 2 sub-arcs to avoid lengths > 180 deg sPainter.drawGreatCircleArc(p1, middlePoint, NULL, viewportEdgeIntersectCallback, &userData); sPainter.drawGreatCircleArc(p2, middlePoint, NULL, viewportEdgeIntersectCallback, &userData); fpt.transfo4d(rotLon); } if (i!=maxNbIter) { rotLon = Mat4d::zrotation(-gridStepMeridianRad); fpt = firstPoint; fpt.transfo4d(rotLon); for (int j=0; j<maxNbIter-i; ++j) { StelUtils::rectToSphe(&lon2, &lat2, fpt); userData.raAngle = lon2; meridianSphericalCap.n = fpt^Vec3d(0,0,1); meridianSphericalCap.n.normalize(); if (!SphericalCap::intersectionPoints(viewPortSphericalCap, meridianSphericalCap, p1, p2)) break; Vec3d middlePoint = p1+p2; middlePoint.normalize(); if (!viewPortSphericalCap.contains(middlePoint)) middlePoint*=-1; sPainter.drawGreatCircleArc(p1, middlePoint, NULL, viewportEdgeIntersectCallback, &userData); sPainter.drawGreatCircleArc(p2, middlePoint, NULL, viewportEdgeIntersectCallback, &userData); fpt.transfo4d(rotLon); } } ///////////////////////////////////////////////// // Draw all the parallels (small circles) SphericalCap parallelSphericalCap(Vec3d(0,0,1), 0); rotLon = Mat4d::rotation(firstPoint^Vec3d(0,0,1), gridStepParallelRad); fpt = firstPoint; maxNbIter = (int)(M_PI/gridStepParallelRad)-1; for (i=0; i<maxNbIter; ++i) { StelUtils::rectToSphe(&lon2, &lat2, fpt); if (withDecimalDegree) userData.text = StelUtils::radToDecDegStr(lat2); else userData.text = StelUtils::radToDmsStrAdapt(lat2); parallelSphericalCap.d = fpt[2]; if (parallelSphericalCap.d>0.9999999) break; const Vec3d rotCenter(0,0,parallelSphericalCap.d); if (!SphericalCap::intersectionPoints(viewPortSphericalCap, parallelSphericalCap, p1, p2)) { if ((viewPortSphericalCap.d<parallelSphericalCap.d && viewPortSphericalCap.contains(parallelSphericalCap.n)) || (viewPortSphericalCap.d<-parallelSphericalCap.d && viewPortSphericalCap.contains(-parallelSphericalCap.n))) { // The parallel is fully included in the viewport, draw it in 3 sub-arcs to avoid lengths >= 180 deg static const Mat4d rotLon120 = Mat4d::zrotation(120.*M_PI/180.); Vec3d rotFpt=fpt; rotFpt.transfo4d(rotLon120); Vec3d rotFpt2=rotFpt; rotFpt2.transfo4d(rotLon120); sPainter.drawSmallCircleArc(fpt, rotFpt, rotCenter, viewportEdgeIntersectCallback, &userData); sPainter.drawSmallCircleArc(rotFpt, rotFpt2, rotCenter, viewportEdgeIntersectCallback, &userData); sPainter.drawSmallCircleArc(rotFpt2, fpt, rotCenter, viewportEdgeIntersectCallback, &userData); fpt.transfo4d(rotLon); continue; } else break; } // Draw the arc in 2 sub-arcs to avoid lengths > 180 deg Vec3d middlePoint = p1-rotCenter+p2-rotCenter; middlePoint.normalize(); middlePoint*=(p1-rotCenter).length(); middlePoint+=rotCenter; if (!viewPortSphericalCap.contains(middlePoint)) { middlePoint-=rotCenter; middlePoint*=-1.; middlePoint+=rotCenter; } sPainter.drawSmallCircleArc(p1, middlePoint, rotCenter, viewportEdgeIntersectCallback, &userData); sPainter.drawSmallCircleArc(p2, middlePoint, rotCenter, viewportEdgeIntersectCallback, &userData); fpt.transfo4d(rotLon); } if (i!=maxNbIter) { rotLon = Mat4d::rotation(firstPoint^Vec3d(0,0,1), -gridStepParallelRad); fpt = firstPoint; fpt.transfo4d(rotLon); for (int j=0; j<maxNbIter-i; ++j) { StelUtils::rectToSphe(&lon2, &lat2, fpt); if (withDecimalDegree) userData.text = StelUtils::radToDecDegStr(lat2); else userData.text = StelUtils::radToDmsStrAdapt(lat2); parallelSphericalCap.d = fpt[2]; const Vec3d rotCenter(0,0,parallelSphericalCap.d); if (!SphericalCap::intersectionPoints(viewPortSphericalCap, parallelSphericalCap, p1, p2)) { if ((viewPortSphericalCap.d<parallelSphericalCap.d && viewPortSphericalCap.contains(parallelSphericalCap.n)) || (viewPortSphericalCap.d<-parallelSphericalCap.d && viewPortSphericalCap.contains(-parallelSphericalCap.n))) { // The parallel is fully included in the viewport, draw it in 3 sub-arcs to avoid lengths >= 180 deg static const Mat4d rotLon120 = Mat4d::zrotation(120.*M_PI/180.); Vec3d rotFpt=fpt; rotFpt.transfo4d(rotLon120); Vec3d rotFpt2=rotFpt; rotFpt2.transfo4d(rotLon120); sPainter.drawSmallCircleArc(fpt, rotFpt, rotCenter, viewportEdgeIntersectCallback, &userData); sPainter.drawSmallCircleArc(rotFpt, rotFpt2, rotCenter, viewportEdgeIntersectCallback, &userData); sPainter.drawSmallCircleArc(rotFpt2, fpt, rotCenter, viewportEdgeIntersectCallback, &userData); fpt.transfo4d(rotLon); continue; } else break; } // Draw the arc in 2 sub-arcs to avoid lengths > 180 deg Vec3d middlePoint = p1-rotCenter+p2-rotCenter; middlePoint.normalize(); middlePoint*=(p1-rotCenter).length(); middlePoint+=rotCenter; if (!viewPortSphericalCap.contains(middlePoint)) { middlePoint-=rotCenter; middlePoint*=-1.; middlePoint+=rotCenter; } sPainter.drawSmallCircleArc(p1, middlePoint, rotCenter, viewportEdgeIntersectCallback, &userData); sPainter.drawSmallCircleArc(p2, middlePoint, rotCenter, viewportEdgeIntersectCallback, &userData); fpt.transfo4d(rotLon); } } }
void Atmosphere::computeColor (double JD, Vec3d sunPos, Vec3d moonPos, float moonPhase, StelCore* core, float eclipseFac, float latitude, float altitude, float temperature, float relativeHumidity) { // We lazily initialize vertex buffer at the first draw, // so we can only call this after that. // We also need a renderer reference (again lazily from draw()) to // construct index buffers as they might change at every call to computeColor(). if(NULL == renderer) {return;} const StelProjectorP prj = core->getProjection(StelCore::FrameAltAz, StelCore::RefractionOff); if (viewport != prj->getViewport()) { // The viewport changed: update the number of points in the grid updateGrid(prj); } eclipseFactor = eclipseFac; if(eclipseFac < 0.0001f) eclipseFactor = 0.0001f; // No need to calculate if not visible if (!fader.getInterstate()) { averageLuminance = 0.001f + lightPollutionLuminance; return; } // Calculate the atmosphere RGB for each point of the grid if (myisnan(sunPos.length())) sunPos.set(0.,0.,-1.*AU); if (myisnan(moonPos.length())) moonPos.set(0.,0.,-1.*AU); sunPos.normalize(); moonPos.normalize(); float sun_pos[3]; sun_pos[0] = sunPos[0]; sun_pos[1] = sunPos[1]; sun_pos[2] = sunPos[2]; float moon_pos[3]; moon_pos[0] = moonPos[0]; moon_pos[1] = moonPos[1]; moon_pos[2] = moonPos[2]; sky.setParamsv(sun_pos, 5.f); skyb.setLocation(latitude * M_PI/180., altitude, temperature, relativeHumidity); skyb.setSunMoon(moon_pos[2], sun_pos[2]); // Calculate the date from the julian day. int year, month, day; StelUtils::getDateFromJulianDay(JD, &year, &month, &day); skyb.setDate(year, month, moonPhase); // Variables used to compute the average sky luminance double sum_lum = 0.; Vec3d point(1., 0., 0.); skylightStruct2 b2; float lumi; vertexGrid->unlock(); // Compute the sky color for every point above the ground for (int i=0; i<(1+skyResolutionX)*(1+skyResolutionY); ++i) { const Vec2f position = vertexGrid->getVertex(i).position; prj->unProject(position[0], position[1], point); Q_ASSERT(fabs(point.lengthSquared()-1.0) < 1e-10); if (point[2]<=0) { point[2] = -point[2]; // The sky below the ground is the symmetric of the one above : // it looks nice and gives proper values for brightness estimation } // Use the Skybright.cpp 's models for brightness which gives better results. lumi = skyb.getLuminance(moon_pos[0]*point[0]+moon_pos[1]*point[1]+moon_pos[2]*point[2], sun_pos[0]*point[0]+sun_pos[1]*point[1]+sun_pos[2]*point[2], point[2]); lumi *= eclipseFactor; // Add star background luminance lumi += 0.0001; // Multiply by the input scale of the ToneConverter (is not done automatically by the xyYtoRGB method called later) //lumi*=eye->getInputScale(); // Add the light pollution luminance AFTER the scaling to avoid scaling it because it is the cause // of the scaling itself lumi += lightPollutionLuminance; // Store for later statistics sum_lum+=lumi; Q_ASSERT_X(NULL != vertexGrid, Q_FUNC_INFO, "Vertex buffer not initialized when setting colors"); // Now need to compute the xy part of the color component // This is done in a GLSL shader if possible if(NULL != shader) { // Store the back projected position + luminance in the input color to the shader const Vec4f color = Vec4f(point[0], point[1], point[2], lumi); vertexGrid->setVertex(i, Vertex(position, color)); continue; } // Shaderless fallback if (lumi > 0.01) { // Use the Skylight model for the color b2.pos[0] = point[0]; b2.pos[1] = point[1]; b2.pos[2] = point[2]; sky.getxyYValuev(b2); } else { // Too dark to see atmosphere color, don't bother computing it b2.color[0] = 0.25; b2.color[1] = 0.25; } const Vec4f color = Vec4f(b2.color[0], b2.color[1], lumi, 1.0f); vertexGrid->setVertex(i, Vertex(position, color)); } vertexGrid->lock(); // Update average luminance averageLuminance = sum_lum/((1+skyResolutionX)*(1+skyResolutionY)); }