//! 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 SkyLine::draw(StelCore *core) const { if (!fader.getInterstate()) return; StelProjectorP prj = core->getProjection(frameType, frameType!=StelCore::FrameAltAz ? StelCore::RefractionAuto : StelCore::RefractionOff); // Get the bounding halfspace const SphericalCap& viewPortSphericalCap = prj->getBoundingCap(); // Initialize a painter and set openGL state StelPainter sPainter(prj); sPainter.setColor(color[0], color[1], color[2], fader.getInterstate()); glEnable(GL_BLEND); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // Normal transparency mode Vec4f textColor(color[0], color[1], color[2], 0); textColor[3]=fader.getInterstate(); ViewportEdgeIntersectCallbackData userData(&sPainter); sPainter.setFont(font); userData.textColor = textColor; userData.text = label; ///////////////////////////////////////////////// // Draw the line SphericalCap meridianSphericalCap(Vec3d(0,0,1), 0); Vec3d fpt(1,0,0); if (line_type==MERIDIAN) { meridianSphericalCap.n.set(0,1,0); } Vec3d p1, p2; if (!SphericalCap::intersectionPoints(viewPortSphericalCap, meridianSphericalCap, p1, p2)) { if ((viewPortSphericalCap.d<meridianSphericalCap.d && viewPortSphericalCap.contains(meridianSphericalCap.n)) || (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); return; } else return; } 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); // // Johannes: use a big radius as a dirty workaround for the bug that the // // ecliptic line is not drawn around the observer, but around the sun: // const Vec3d vv(1000000,0,0); }
void SkyLine::draw(StelCore *core) const { if (!fader.getInterstate()) return; StelProjectorP prj = core->getProjection(frameType, frameType!=StelCore::FrameAltAz ? StelCore::RefractionAuto : StelCore::RefractionOff); // Get the bounding halfspace const SphericalCap& viewPortSphericalCap = prj->getBoundingCap(); // Initialize a painter and set openGL state StelPainter sPainter(prj); sPainter.setColor(color[0], color[1], color[2], fader.getInterstate()); glEnable(GL_BLEND); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // Normal transparency mode #ifdef GL_LINE_SMOOTH if (QOpenGLContext::currentContext()->format().renderableType()==QSurfaceFormat::OpenGL) glEnable(GL_LINE_SMOOTH); #endif Vec4f textColor(color[0], color[1], color[2], 0); textColor[3]=fader.getInterstate(); ViewportEdgeIntersectCallbackData userData(&sPainter); sPainter.setFont(font); userData.textColor = textColor; userData.text = label; ///////////////////////////////////////////////// // Draw the line // Precession circles are Small Circles, all others are Great Circles. if (line_type==PRECESSIONCIRCLE_N || line_type==PRECESSIONCIRCLE_S) { const double lat=(line_type==PRECESSIONCIRCLE_S ? -1.0 : 1.0) * (M_PI/2.0-getPrecessionAngleVondrakCurrentEpsilonA()); SphericalCap declinationCap(Vec3d(0,0,1), std::sin(lat)); const Vec3d rotCenter(0,0,declinationCap.d); Vec3d p1, p2; if (!SphericalCap::intersectionPoints(viewPortSphericalCap, declinationCap, p1, p2)) { if ((viewPortSphericalCap.d<declinationCap.d && viewPortSphericalCap.contains(declinationCap.n)) || (viewPortSphericalCap.d<-declinationCap.d && viewPortSphericalCap.contains(-declinationCap.n))) { // The line is fully included in the viewport, draw it in 3 sub-arcs to avoid length > 180. Vec3d pt1; Vec3d pt2; Vec3d pt3; const double lon1=0.0; const double lon2=120.0*M_PI/180.0; const double lon3=240.0*M_PI/180.0; StelUtils::spheToRect(lon1, lat, pt1); pt1.normalize(); StelUtils::spheToRect(lon2, lat, pt2); pt2.normalize(); StelUtils::spheToRect(lon3, lat, pt3); pt3.normalize(); sPainter.drawSmallCircleArc(pt1, pt2, rotCenter, viewportEdgeIntersectCallback, &userData); sPainter.drawSmallCircleArc(pt2, pt3, rotCenter, viewportEdgeIntersectCallback, &userData); sPainter.drawSmallCircleArc(pt3, pt1, rotCenter, viewportEdgeIntersectCallback, &userData); #ifdef GL_LINE_SMOOTH if (QOpenGLContext::currentContext()->format().renderableType()==QSurfaceFormat::OpenGL) glDisable(GL_LINE_SMOOTH); #endif glDisable(GL_BLEND); return; } else { #ifdef GL_LINE_SMOOTH if (QOpenGLContext::currentContext()->format().renderableType()==QSurfaceFormat::OpenGL) glDisable(GL_LINE_SMOOTH); #endif glDisable(GL_BLEND); return; } } // 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); // OpenGL ES 2.0 doesn't have GL_LINE_SMOOTH #ifdef GL_LINE_SMOOTH if (QOpenGLContext::currentContext()->format().renderableType()==QSurfaceFormat::OpenGL) glDisable(GL_LINE_SMOOTH); #endif glDisable(GL_BLEND); return; } // All the other "lines" are Great Circles SphericalCap meridianSphericalCap(Vec3d(0,0,1), 0); Vec3d fpt(1,0,0); if ((line_type==MERIDIAN) || (line_type==COLURE_1)) { meridianSphericalCap.n.set(0,1,0); } if ((line_type==PRIME_VERTICAL) || (line_type==COLURE_2)) { meridianSphericalCap.n.set(1,0,0); fpt.set(0,0,1); } if (line_type==LONGITUDE) { Vec3d coord; double lambda, beta; StelUtils::rectToSphe(&lambda, &beta, core->getCurrentPlanet()->getHeliocentricEclipticPos()); StelUtils::spheToRect(lambda + M_PI/2., 0., coord); meridianSphericalCap.n.set(coord[0],coord[1],coord[2]); fpt.set(0,0,1); } Vec3d p1, p2; if (!SphericalCap::intersectionPoints(viewPortSphericalCap, meridianSphericalCap, p1, p2)) { if ((viewPortSphericalCap.d<meridianSphericalCap.d && viewPortSphericalCap.contains(meridianSphericalCap.n)) || (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); return; } else return; } 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); // OpenGL ES 2.0 doesn't have GL_LINE_SMOOTH #ifdef GL_LINE_SMOOTH if (QOpenGLContext::currentContext()->format().renderableType()==QSurfaceFormat::OpenGL) glDisable(GL_LINE_SMOOTH); #endif glDisable(GL_BLEND); // // Johannes: use a big radius as a dirty workaround for the bug that the // // ecliptic line is not drawn around the observer, but around the sun: // const Vec3d vv(1000000,0,0); }