# Ray intersection with Sun positions throughout the year

I need to highlight(colour) sun reflections(through the year) off a mirror surface. It was easy having one Sun like in the below image but how about if it is to determine if a ray hits the entire surface that represents sun positions throughout the year.

Update:

Suppose the house surfaces are all mirror, so that from specific angles the viewer might see the reflection of the sun off the house surfaces. this is easy to render an image that simulate this but how about rendering an image that shows the reflection of not just one Sun, in a specific day time, but all the Suns, one for every second throughout the year. It's not efficient to dump in all these Suns into model and intersect them for each surface point. So I need to check if a ray intersects the entire surface that represents the path of the sun throughout the year.

• It's not entirely clear from your description and image what you're asking. Can you clarify? What does the image show? The sun's rays will hit every surface of (the outside of) the house on any given day, most likely. (Unless I suppose if a side is exactly parallel to the path of the sun, or the building is at an extreme latitude.) What do you want to color? Oct 6, 2017 at 2:57
• There's two ways i can think of going about this. The first is that this case is basically a ray vs tube test where the tube follows the 3d path of the sun. Maybe you can look for (or ask for) ray vs "tube" intersections. The second idea is to calculate the closest point on the ray to the path of the sun (the line), and if that is closer than the radius of the sun, count it as a hit, and do whatever else you need to do from there. Oct 6, 2017 at 16:35
• Thanks for your comment. Could you please elaborate the second idea. Couldn't grasb it. Bear in mind that there are not one sun but many. Also regarding the first solution, do you have any idea what the equation would be for the tube like surface?
– ali
Oct 6, 2017 at 20:34
• I don't have any equations in mind for the first thing, no sorry. The second thing is this: the sun is traveling on a path. Imagine that path as a line (it bends around and curves, but it doesn't have any width). If you can find a way to find the closest point on that curve to a line (the line that the ray is part of), you can get the distance from the ray to that path. If it gets closer than the radius of the sun, that means it MUST hit the sun. Then from there need to figure out when / where etc, so more work needed, but it's a start. Oct 6, 2017 at 21:02

## 1 Answer

The function that calculates sun position in the sky takes as input local latitude, longitude and local date time. The output is a vector which is sun position:

Inversing the above means using the ray direction(sun position in the sky) and retrieving back the local date time. If the date time is valid then the ray must hit the sun path throughout the year.

Here is the inverse function of the above:

public DateTime GetLocalDatetime(double haSolar, double vaSolar)
{
double latitude = Helper.ToRadian(Latitude);
double longitude = Helper.ToRadian(Longitude);

double zenithTheta = Helper.PiOver2 - vaSolar;

double sinSolarDeclination = (Math.Cos(Math.PI - haSolar) * Math.Cos(latitude) * Math.Sin(zenithTheta)) + Math.Sin(latitude) * Math.Cos(zenithTheta);
double solarDeclination = Math.Asin(sinSolarDeclination);

double cosH = (Math.Sin(vaSolar) - Math.Sin(latitude) * sinSolarDeclination) / (Math.Cos(latitude) * Math.Cos(solarDeclination));
if (Math.Abs(cosH) > 1) return DateTime.MinValue;

double H = Math.Acos(cosH);
if (haSolar < 0) H *= -1;

double declratio = solarDeclination / Helper.ToRadian(23.45);
if (Math.Abs(declratio) > 1) return DateTime.MinValue;

double beta = Math.Asin(declratio);
int n = (int)Math.Round(beta / Helper.ToRadian(360d / 365d) + 81d, 1);

DateTime localtime = new DateTime(DateTime.Now.Year, 1, 1).AddDays(n - 1);
DateTime solartime = new DateTime(localtime.Year, localtime.Month, localtime.Day, 12, 0, 0);
solartime = solartime.AddMinutes(4 * Helper.ToDegree(H));

double eot = 9.87 * Math.Sin(2d * beta) - 7.53 * Math.Cos(beta) - 1.5 * Math.Sin(beta);
double deltatimezone = 4d * (longitude - (Timezone * 15d));
return solartime.AddMinutes(-(eot + deltatimezone));
}


And the image where each band represent each month in the year: