4
$\begingroup$

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.

enter image description here

$\endgroup$
  • 1
    $\begingroup$ 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? $\endgroup$ – user1118321 Oct 6 '17 at 2:57
  • 2
    $\begingroup$ 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. $\endgroup$ – Alan Wolfe Oct 6 '17 at 16:35
  • $\begingroup$ 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? $\endgroup$ – ali Oct 6 '17 at 20:34
  • 1
    $\begingroup$ 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. $\endgroup$ – Alan Wolfe Oct 6 '17 at 21:02
2
$\begingroup$

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:

enter image description here

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:

enter image description here

$\endgroup$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.