From 3a1546e14297c53abf1d50724e80709e533cea7b Mon Sep 17 00:00:00 2001
From: Mauco03 <marco.gaibotti@skywarder.eu>
Date: Mon, 24 Mar 2025 22:56:07 +0100
Subject: [PATCH] [handle-value-conversion] Fixed wind model

---
 classes/misc/Wind.m | 146 +++++++++++++++++++++++++++++++++-----------
 1 file changed, 111 insertions(+), 35 deletions(-)

diff --git a/classes/misc/Wind.m b/classes/misc/Wind.m
index 3adff25..e8aa811 100644
--- a/classes/misc/Wind.m
+++ b/classes/misc/Wind.m
@@ -9,31 +9,111 @@ classdef Wind < Config
 %               - mission: Mission, mission object
 %               - varIn: (optional) config source. Alternative to config.m
 %               file
-    properties
+    properties(Dependent)
         altitudes               (1, :)
 
         magnitudeDistribution   (1, :) ... 
-            {mustBeMember(magnitudeDistribution, {'u', 'g'})} = 'u'         % [-] Magnitude distrubution: uniform, gaussian
+            {mustBeMember(magnitudeDistribution, {'u', 'g'})}   % [-] Magnitude distrubution: uniform (default), gaussian
         azimuthDistribution     (1, :) ...
-            {mustBeMember(azimuthDistribution, {'u', 'g'})} = 'u'           % [-] Azimuth   distrubution: uniform, gaussian
+            {mustBeMember(azimuthDistribution, {'u', 'g'})}     % [-] Azimuth   distrubution: uniform (default), gaussian
         elevationDistribution   (1, :) ... 
-            {mustBeMember(elevationDistribution, {'u', 'g'})} = 'u'         % [-] Elevation distrubution: uniform, gaussian
-        magnitudeParameters     (2, :)                                      % [m/s] Distribution parameters: [min; max], [mu; sigma]
-        azimuthParameters       (2, :)                                      % [deg] Distribution parameters: [min; max], [mu; sigma]
-        elevationParameters     (2, :)                                      % [deg] Distribution parameters: [min; max], [mu; sigma]
+            {mustBeMember(elevationDistribution, {'u', 'g'})}   % [-] Elevation distrubution: uniform (default), gaussian
+        
+        magnitudeParameters     (2, :)                          % [m/s] Distribution parameters: [min; max], [mu; sigma]
+        azimuthParameters       (2, :)                          % [deg] Distribution parameters: [min; max], [mu; sigma]
+        elevationParameters     (2, :)                          % [deg] Distribution parameters: [min; max], [mu; sigma]
     end
     
+    properties(Access = private)
+        ALTITUDES
+        
+        MAGNITUDE_DISTRIBUTION  = ''
+        AZIMUTH_DISTRIBUTION    = ''
+        ELEVATION_DISTRIBUTION  = ''
+
+        MAGNITUDE_PARAMETERS    = []
+        AZIMUTH_PARAMETERS      = []
+        ELEVATION_PARAMETERS    = []
+    end
+
     properties(SetAccess = private)
         azimuth
         elevation
         magnitude
     end
     
+    properties(Access = private)
+        checks                  (1, 3)  logical                 % true if #[magnitude, azimuth, elevation] == #altitudes
+    end
+
     properties(Constant, Access = protected)
         configName = 'windConfig.m'
         variableName = 'windCustom'
     end
 
+    methods % Getters / Setters
+        function obj = set.altitudes(obj, value)
+            if length(value) ~= length(obj.ALTITUDES)
+                obj.ALTITUDES = value;
+                obj.magnitude = obj.updateDistribution(obj.MAGNITUDE_DISTRIBUTION, obj.MAGNITUDE_PARAMETERS);
+                obj.azimuth   = obj.updateDistribution(obj.AZIMUTH_DISTRIBUTION, obj.AZIMUTH_PARAMETERS);
+                obj.elevation = obj.updateDistribution(obj.ELEVATION_DISTRIBUTION, obj.ELEVATION_PARAMETERS);
+            else
+                obj.ALTITUDES = value;
+            end
+
+            obj.checks(1) = length(obj.magnitude) == length(obj.ALTITUDES);
+            obj.checks(2) = length(obj.azimuth) == length(obj.ALTITUDES);
+            obj.checks(3) = length(obj.elevation) == length(obj.ALTITUDES);
+        end
+
+        function obj = set.magnitudeDistribution(obj, value)
+            obj.MAGNITUDE_DISTRIBUTION = value;
+            obj.magnitude = obj.updateDistribution(value, obj.MAGNITUDE_PARAMETERS);
+            obj.checks(1) = length(obj.magnitude) == length(obj.ALTITUDES); 
+        end
+
+        function obj = set.magnitudeParameters(obj, value)
+            obj.MAGNITUDE_PARAMETERS = value;
+            obj.magnitude = obj.updateDistribution(obj.MAGNITUDE_DISTRIBUTION, value);
+            obj.checks(1) = length(obj.magnitude) == length(obj.ALTITUDES);
+        end
+
+        function obj = set.azimuthDistribution(obj, value)
+            obj.AZIMUTH_DISTRIBUTION = value;
+            obj.azimuth = obj.updateDistribution(value, obj.AZIMUTH_PARAMETERS);
+            obj.checks(2) = length(obj.azimuth) == length(obj.ALTITUDES); 
+        end
+
+        function obj = set.azimuthParameters(obj, value)
+            obj.AZIMUTH_PARAMETERS = value;
+            obj.azimuth = obj.updateDistribution(obj.AZIMUTH_DISTRIBUTION, value);
+            obj.checks(2) = length(obj.azimuth) == length(obj.ALTITUDES); 
+        end
+
+        function obj = set.elevationDistribution(obj, value)
+            obj.ELEVATION_DISTRIBUTION = value;
+            obj.elevation = obj.updateDistribution(value, obj.ELEVATION_PARAMETERS);
+            obj.checks(3) = length(obj.elevation) == length(obj.ALTITUDES); 
+        end
+
+        function obj = set.elevationParameters(obj, value)
+            obj.ELEVATION_PARAMETERS = value;
+            obj.elevation = obj.updateDistribution(obj.ELEVATION_DISTRIBUTION, value);
+            obj.checks(3) = length(obj.elevation) == length(obj.ALTITUDES); 
+        end
+
+        function value = get.altitudes(obj), value = obj.ALTITUDES; end
+
+        function value = get.magnitudeDistribution(obj), value = obj.MAGNITUDE_DISTRIBUTION; end
+        function value = get.azimuthDistribution(obj), value = obj.AZIMUTH_DISTRIBUTION; end
+        function value = get.elevationDistribution(obj), value = obj.ELEVATION_DISTRIBUTION; end
+            
+        function value = get.magnitudeParameters(obj), value = obj.MAGNITUDE_PARAMETERS; end
+        function value = get.azimuthParameters(obj), value = obj.AZIMUTH_PARAMETERS; end
+        function value = get.elevationParameters(obj), value = obj.ELEVATION_PARAMETERS; end
+    end
+
     methods
         function obj = Wind(mission, varIn)
             arguments(Input)
@@ -41,10 +121,14 @@ classdef Wind < Config
                 varIn = []
             end
             obj@Config(mission, varIn);
-            obj = obj.updateAll();
         end
 
         function [uw, vw, ww] = getVels(obj, z)
+            if ~all(obj.checks)
+                error(['Parameters and distributions must be the same ' ...
+                    'size as altitudes or scalar']);
+            end
+
             if isscalar(obj.altitudes)
                 uw = round( - obj.magnitude * cos(obj.azimuth) * cos(obj.elevation), 6);
                 vw = round( - obj.magnitude * sin(obj.azimuth) * cos(obj.elevation), 6);
@@ -53,36 +137,38 @@ classdef Wind < Config
                 mag = interpLinear(obj.altitudes, obj.magnitude, z, true);
                 az = interpLinear(obj.altitudes, obj.azimuth, z, true);
                 el = interpLinear(obj.altitudes, obj.elevation, z, true);
-                
+
                 uw = round( - mag * cos(az) * cos(el), 6);
                 vw = round( - mag * sin(az) * cos(el), 6);
                 ww = round( - mag * (-sin(el)), 6);
             end
         end
-
-        function obj = updateAll(obj)
-            obj = obj.updateElevation();
-
-            obj.magnitude = obj.updateDistribution(obj.magnitudeDistribution, ...
-                obj.magnitudeParameters);
-
-            obj.azimuth = obj.updateDistribution(obj.azimuthDistribution, ...
-                obj.azimuthParameters);
-
-            obj.elevation = obj.updateDistribution(obj.elevationDistribution, ...
-                obj.elevationParameters);
-        end
     end
 
     methods(Access = private)
         function vec = updateDistribution(obj, dist, parameters)
-            s = length(obj.altitudes);
-            vec = nan(1,s);
+            s = length(obj.ALTITUDES);
+            vec = [];
+ 
+            dist = string(dist);
+            lDist = length(dist);
+            lPara = width(parameters);
+
+            if lDist == 0, dist = "u"; lDist = 1; end
+            if lPara == 0, parameters = [0; 0]; lPara = 1; end
+
+            if lDist == 1, dist = repmat(dist, 1, s); lDist = s; end
+            if lPara == 1, parameters = repmat(parameters, 1, s); lPara = s; end
+
+            if lDist ~= s, return; end
+            if lPara ~= s, return; end
+            
             isUniform = strcmp(dist, "u");
 
             uniformDist = @(val1, val2) rand(1)*(val2 - val1) + val1;
             gaussianDist = @(mean, sigma) normrnd(mean, sigma, 1);
 
+            vec = nan(1,s);
             for i = 1:s
                 if isUniform(i)
                     vec(i) = uniformDist(parameters(1,i), parameters(2,i));
@@ -91,15 +177,5 @@ classdef Wind < Config
                 end
             end
         end
-
-        function obj = updateElevation(obj)
-            if any(size(obj.elevationDistribution) ~= size(obj.azimuthDistribution))
-                obj.elevationDistribution = repmat("u", size(obj.azimuthDistribution));
-            end
-
-            if isempty(obj.elevationParameters) && ~isempty(obj.azimuthParameters)
-                obj.elevationParameters = zeros(size(obj.azimuthParameters));
-            end
-        end
     end
-end
+end
\ No newline at end of file
-- 
GitLab