[Bf-extensions-cvs] [085bc978] master: Sun Position: refactor and cleanup sun calculations

Damien Picard noreply at git.blender.org
Sun Jan 8 02:53:07 CET 2023


Commit: 085bc978b7b0bc7135a63b2fdbf824976b36ce63
Author: Damien Picard
Date:   Sat Jan 7 21:18:13 2023 +0100
Branches: master
https://developer.blender.org/rBA085bc978b7b0bc7135a63b2fdbf824976b36ce63

Sun Position: refactor and cleanup sun calculations

===================================================================

M	sun_position/sun_calc.py

===================================================================

diff --git a/sun_position/sun_calc.py b/sun_position/sun_calc.py
index b1ae46dd..fc4e0452 100644
--- a/sun_position/sun_calc.py
+++ b/sun_position/sun_calc.py
@@ -2,32 +2,30 @@
 
 import bpy
 from bpy.app.handlers import persistent
-from mathutils import Euler
+from mathutils import Euler, Vector
 import math
 from math import degrees, radians, pi
 import datetime
 from .geo import parse_position
 
 
-class SunClass:
+class SunInfo:
     """
-    SunClass is used for storing intermediate sun calculations.
+    Store intermediate sun calculations
     """
-    class TazEl:
+    class TAzEl:
         time = 0.0
         azimuth = 0.0
         elevation = 0.0
 
     class CLAMP:
-        elevation = 0.0
         azimuth = 0.0
+        elevation = 0.0
         az_start_sun = 0.0
         az_start_env = 0.0
 
-    sunrise = TazEl()
-    sunset = TazEl()
-    solar_noon = TazEl()
-    rise_set_ok = False
+    sunrise = TAzEl()
+    sunset = TAzEl()
 
     bind = CLAMP()
     bind_to_sun = False
@@ -47,14 +45,14 @@ class SunClass:
     sun_distance = 0.0
     use_daylight_savings = False
 
-
-sun = SunClass()
+sun = SunInfo()
 
 
 def sun_update(self, context):
     update_time(context)
     move_sun(context)
 
+
 def parse_coordinates(self, context):
     error_message = "ERROR: Could not parse coordinates"
     sun_props = context.scene.sun_pos_properties
@@ -71,15 +69,10 @@ def parse_coordinates(self, context):
     if sun_props.co_parser not in {'', error_message}:
         sun_props.co_parser = ''
 
- at persistent
-def sun_handler(scene):
-    update_time(bpy.context)
-    move_sun(bpy.context)
-
 
 def move_sun(context):
     """
-    Cycle through all the selected objects and call set_sun_position and
+    Cycle through all the selected objects and call set_sun_location and
     set_sun_rotations to place them in the sky
     """
     addon_prefs = context.preferences.addons[__package__].preferences
@@ -101,11 +94,12 @@ def move_sun(context):
             env_tex.texture_mapping.rotation.z = az
 
         if sun_props.sun_object:
-            sun.theta = math.pi / 2 - sun_props.hdr_elevation
-            sun.phi = -sun_props.hdr_azimuth
+            theta = math.pi / 2 - sun_props.hdr_elevation
+            phi = -sun_props.hdr_azimuth
 
             obj = sun_props.sun_object
-            set_sun_position(obj, sun_props.sun_distance)
+            obj.location = get_sun_vector(theta, phi) * sun_props.sun_distance
+
             rotation_euler = Euler((sun_props.hdr_elevation - pi/2,
                                     0, -sun_props.hdr_azimuth))
 
@@ -124,28 +118,28 @@ def move_sun(context):
         calc_sunrise_sunset(rise=True)
         calc_sunrise_sunset(rise=False)
 
-    get_sun_position(local_time, sun_props.latitude, sun_props.longitude,
-            north_offset, zone, sun_props.month, sun_props.day, sun_props.year,
-            sun_props.sun_distance)
+    az_north, theta, phi, azimuth, elevation = get_sun_coordinates(
+        local_time, sun_props.latitude, sun_props.longitude,
+        north_offset, zone, sun_props.month, sun_props.day, sun_props.year,
+        sun_props.sun_distance)
+    sun.azimuth = azimuth
+    sun.elevation = elevation
 
     if sun_props.sky_texture:
         sky_node = bpy.context.scene.world.node_tree.nodes.get(sun_props.sky_texture)
         if sky_node is not None and sky_node.type == "TEX_SKY":
-            locX = math.sin(sun.phi) * math.sin(-sun.theta)
-            locY = math.sin(sun.theta) * math.cos(sun.phi)
-            locZ = math.cos(sun.theta)
             sky_node.texture_mapping.rotation.z = 0.0
-            sky_node.sun_direction = locX, locY, locZ
-            sky_node.sun_elevation = math.radians(sun.elevation)
-            sky_node.sun_rotation = math.radians(sun.az_north)
+            sky_node.sun_direction = get_sun_vector(theta, phi)
+            sky_node.sun_elevation = math.radians(elevation)
+            sky_node.sun_rotation = math.radians(az_north)
 
     # Sun object
     if (sun_props.sun_object is not None
             and sun_props.sun_object.name in context.view_layer.objects):
         obj = sun_props.sun_object
-        set_sun_position(obj, sun_props.sun_distance)
-        rotation_euler = Euler((math.radians(sun.elevation - 90), 0,
-                                math.radians(-sun.az_north)))
+        obj.location = get_sun_vector(theta, phi) * sun_props.sun_distance
+        rotation_euler = Euler((math.radians(elevation - 90), 0,
+                                math.radians(-az_north)))
         set_sun_rotations(obj, rotation_euler)
 
     # Sun collection
@@ -161,15 +155,16 @@ def move_sun(context):
                 time_increment = sun_props.time_spread
 
             for obj in sun_objects:
-                get_sun_position(local_time, sun_props.latitude,
-                                 sun_props.longitude, north_offset, zone,
-                                 sun_props.month, sun_props.day,
-                                 sun_props.year, sun_props.sun_distance)
-                set_sun_position(obj, sun_props.sun_distance)
+                az_north, theta, phi, azimuth, elevation = get_sun_coordinates(
+                    local_time, sun_props.latitude,
+                    sun_props.longitude, north_offset, zone,
+                    sun_props.month, sun_props.day,
+                    sun_props.year, sun_props.sun_distance)
+                obj.location = get_sun_vector(theta, phi) * sun_props.sun_distance
                 local_time -= time_increment
                 obj.rotation_euler = (
-                    (math.radians(sun.elevation - 90), 0,
-                     math.radians(-sun.az_north)))
+                    (math.radians(elevation - 90), 0,
+                     math.radians(-az_north)))
         else:
             # Analemma
             day_increment = 365 / object_count
@@ -177,43 +172,61 @@ def move_sun(context):
             for obj in sun_objects:
                 dt = (datetime.date(sun_props.year, 1, 1) +
                       datetime.timedelta(day - 1))
-                get_sun_position(local_time, sun_props.latitude,
-                                 sun_props.longitude, north_offset, zone,
-                                 dt.month, dt.day, sun_props.year,
-                                 sun_props.sun_distance)
-                set_sun_position(obj, sun_props.sun_distance)
+                az_north, theta, phi, azimuth, elevation = get_sun_coordinates(
+                    local_time, sun_props.latitude,
+                    sun_props.longitude, north_offset, zone,
+                    dt.month, dt.day, sun_props.year,
+                    sun_props.sun_distance)
+                obj.location = get_sun_vector(theta, phi) * sun_props.sun_distance
                 day -= day_increment
                 obj.rotation_euler = (
-                    (math.radians(sun.elevation - 90), 0,
-                     math.radians(-sun.az_north)))
+                    (math.radians(elevation - 90), 0,
+                     math.radians(-az_north)))
+
+
+def day_of_year_to_month_day(year, day_of_year):
+    dt = (datetime.date(year, 1, 1) + datetime.timedelta(day_of_year - 1))
+    return dt.day, dt.month
+
+def month_day_to_day_of_year(year, month, day):
+    dt = datetime.date(year, month, day)
+    return dt.timetuple().tm_yday
+
 
 def update_time(context):
     sun_props = context.scene.sun_pos_properties
 
     if sun_props.use_day_of_year:
-        dt = (datetime.date(sun_props.year, 1, 1) +
-              datetime.timedelta(sun_props.day_of_year - 1))
-        sun.day = dt.day
-        sun.month = dt.month
+        day, month = day_of_year_to_month_day(sun_props.year,
+                                              sun_props.day_of_year)
+        sun.day = day
+        sun.month = month
         sun.day_of_year = sun_props.day_of_year
-        if sun_props.day != dt.day:
-            sun_props.day = dt.day
-        if sun_props.month != dt.month:
-            sun_props.month = dt.month
+        if sun_props.day != day:
+            sun_props.day = day
+        if sun_props.month != month:
+            sun_props.month = month
     else:
-        dt = datetime.date(sun_props.year, sun_props.month, sun_props.day)
-        day_of_year = dt.timetuple().tm_yday
-        if sun_props.day_of_year != day_of_year:
-            sun_props.day_of_year = day_of_year
+        day_of_year = month_day_to_day_of_year(
+            sun_props.year, sun_props.month, sun_props.day)
         sun.day = sun_props.day
         sun.month = sun_props.month
         sun.day_of_year = day_of_year
+        if sun_props.day_of_year != day_of_year:
+            sun_props.day_of_year = day_of_year
+
     sun.year = sun_props.year
     sun.longitude = sun_props.longitude
     sun.latitude = sun_props.latitude
     sun.UTC_zone = sun_props.UTC_zone
 
 
+ at persistent
+def sun_handler(scene):
+    update_time(bpy.context)
+    move_sun(bpy.context)
+
+
 def format_time(the_time, daylight_savings, longitude, UTC_zone=None):
     if UTC_zone is not None:
         if daylight_savings:
@@ -256,8 +269,8 @@ def format_lat_long(lat_long, is_latitude):
     return hh + "° " + mm + "' " + ss + '"' + coord_tag
 
 
-def get_sun_position(local_time, latitude, longitude, north_offset,
-                   utc_zone, month, day, year, distance):
+def get_sun_coordinates(local_time, latitude, longitude, north_offset,
+                        utc_zone, month, day, year, distance):
     """
     Calculate the actual position of the sun based on input parameters.
 
@@ -276,10 +289,10 @@ def get_sun_position(local_time, latitude, longitude, north_offset,
     addon_prefs = bpy.context.preferences.addons[__package__].preferences
     sun_props = bpy.context.scene.sun_pos_properties
 
-    longitude *= -1                 # for internal calculations
-    utc_time = local_time + utc_zone   # Set Greenwich Meridian Time
+    longitude *= -1                   # for internal calculations
+    utc_time = local_time + utc_zone  # Set Greenwich Meridian Time
 
-    if latitude > 89.93:            # Latitude 90 and -90 gives
+    if latitude > 89.93:           # Latitude 90 and -90 gives
         latitude = 

@@ Diff output truncated at 10240 characters. @@



More information about the Bf-extensions-cvs mailing list