//! 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);
}
Exemple #5
0
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;
}
Exemple #7
0
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);
}
Exemple #8
0
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));
}