diff --git a/Utilities/MATLAB/Functions/dblSideSpec.m b/Utilities/MATLAB/Functions/dblSideSpec.m new file mode 100755 index 0000000000000000000000000000000000000000..544dee3638f9ffa2f1da23ad5e80fc906d6c72be --- /dev/null +++ b/Utilities/MATLAB/Functions/dblSideSpec.m @@ -0,0 +1,62 @@ +% -------------------------------------------------- +% Author: Achilles Kappis +% e-mail: axilleaz@protonmail.com +% +% Date: 03/02/2024 (DD/MM/YYYY) +% +% Copyright: MIT +% -------------------------------------------------- +% Functionality: Function to synthesise double-sided spectrum +% from their positive (first in MatLab) half. +% -------------------------------------------------- +% Input arguments +% +% mag [numeric]: The magnitude of the frequency response. It must +% correspond to only the positive frequencies. +% +% phase [numeric]: The phase of the frequency response. It must correspond +% to the positive frequencies only. +% +% nyquistFreq [logical] (Optional): Whether the Nyquist frequency is +% included in the given data ("mag" and +% "phase" arguments). [Default: false]. +% +% -------------------------------------------------- +% Output arguments +% +% FR [numeric]: The double-sided spectrum in Cartesian coordinates +% (z = x + jy). +% +% -------------------------------------------------- +function FR = dblSideSpec(mag, phase, nyquistFreq) + % ==================================================== + % Check for number of arguments + % ==================================================== + narginchk(2, 5); + nargoutchk(0, 1); + + % ==================================================== + % Validate input arguments + % ==================================================== + validateattributes(mag, {'numeric'}, {'nonnegative', 'real', 'nonnan', 'finite', 'nonempty', 'vector'}, mfilename, 'Magnitude', 1); + validateattributes(phase, {'numeric'}, {'real', 'nonnan', 'finite', 'nonempty', 'vector', 'numel', length(mag)}, mfilename, 'Phase', 2); + + if nargin > 2 + validateattributes(nyquistFreq, {'logical'}, {'scalar', 'nonnan', 'nonempty'}, mfilename, 'Nyquist Frequency', 3); + else + nyquistFreq = false; + end + + % ==================================================== + % Mirror the frequency response + % ==================================================== + % Put the frequency response in Cartesian coordinates + [x, y] = pol2cart(phase, mag); + FR = x(:) + 1i * y(:); + + if nyquistFreq + FR = [FR; flip(conj(FR(2:end - 1)))]; + else + FR = [FR; flip(conj(FR(2:end)))]; + end +end \ No newline at end of file diff --git a/Utilities/MATLAB/Functions/intersectThree.m b/Utilities/MATLAB/Functions/intersectThree.m new file mode 100644 index 0000000000000000000000000000000000000000..8c63f830f8193f2859eb4d3949590ed9b2ecd7de --- /dev/null +++ b/Utilities/MATLAB/Functions/intersectThree.m @@ -0,0 +1,74 @@ +%% Find the intersection of three vectors +% -------------------------------------------------- +% Author: Achilles Kappis +% e-mail: axilleaz@protonmail.com +% +% Date: 03/02/2024 (DD/MM/YYYY) +% +% Copyright: MIT +% -------------------------------------------------- +% Functionality: Get the intersection (common values) of three vectors. Can +% provide the indices of the values as an additional output. +% -------------------------------------------------- +% Input +% +% vecOne [any]: The first vector. +% +% vecTwo [any]: The second vector. +% +% vecThree [any] (Optional): The third vector. [Defaul: []]. +% -------------------------------------------------- +% Output +% +% commonVals [any]: The values that are common in all three vectors. The +% values are sorted in non-decreasing order and, if +% repeated, only the first occurence is "registered". +% +% idxOne [numeric]: The indices corresponding to the common values in the +% first vector. +% +% idxTwo [numeric]: The indices corresponding to the common values in the +% second vector. +% +% idxThree [numeric]: The indices corresponding to the common values in the +% third vector. +% -------------------------------------------------- +% Notes +% +% All inputs must be vectors. Matrices are not supported. +% -------------------------------------------------- +function [commonVals, idxOne, idxTwo, idxThree] = intersectThree(vecOne, vecTwo, vecThree) + % ==================================================== + % Check for number of arguments + % ==================================================== + narginchk(2, 3); + nargoutchk(0, 4); + + % ==================================================== + % Validate input arguments + % ==================================================== + validateattributes(vecOne, {'numeric'}, {'vector'}, mfilename, '1st vector', 1); + validateattributes(vecTwo, {'numeric'}, {'vector'}, mfilename, '2nd vector', 2); + + if nargin > 2 + validateattributes(vecThree, {'numeric'}, {'vector'}, mfilename, '3rd vector', 3); + else + vecThree = []; + end + + % ==================================================== + % Calculate intersection + % ==================================================== + [commonVals, idxOne, idxTwo] = intersect(vecOne, vecTwo); % First two vectors + [commonVals, idxTemp, idxThree] = intersect(commonVals, vecThree); % The result with the third vector + + % Get the indices of vecOne and vecTwo that correspond to values + % present in vecThree + if nargout > 1 + idxOne = idxOne(idxTemp); + end + + if nargout > 2 + idxTwo = idxTwo(idxTemp); + end +end \ No newline at end of file diff --git a/Utilities/MATLAB/Functions/isEven.m b/Utilities/MATLAB/Functions/isEven.m new file mode 100755 index 0000000000000000000000000000000000000000..5bb8a20a088a7d1bd1ff21351b1a65aac6d93d43 --- /dev/null +++ b/Utilities/MATLAB/Functions/isEven.m @@ -0,0 +1,42 @@ +%% Determine whether a number is even or not +% -------------------------------------------------- +% Author: Achilles Kappis +% e-mail: axilleaz@protonmail.com +% +% Date: 04/02/2024 (DD/MM/YYYY) +% +% Copyright: MIT +% -------------------------------------------------- +% Functionality: Function to check if a real number is even. +% -------------------------------------------------- +% Input arguments +% +% num [numeric]: The number to check. +% +% -------------------------------------------------- +% Output arguments +% +% result [logical]: True if the number is even, False else. +% +% -------------------------------------------------- +% Notes +% +% -------------------------------------------------- +function result = isEven(num) + % ==================================================== + % Check for number of arguments + % ==================================================== + narginchk(1, 1); + nargoutchk(0, 1); + + % ==================================================== + % Validate arguments + % ==================================================== + % Mandatory arguments + validateattributes(num, "numeric", {'real', 'nonempty'}, mfilename, "Number to test.", 1); + + % ==================================================== + % Perform the check + % ==================================================== + result = mod(num, 2) == 0; +end \ No newline at end of file diff --git a/Utilities/MATLAB/Functions/isOdd.m b/Utilities/MATLAB/Functions/isOdd.m new file mode 100755 index 0000000000000000000000000000000000000000..187c821ada95d5c16d0d92a037b824790375f3fc --- /dev/null +++ b/Utilities/MATLAB/Functions/isOdd.m @@ -0,0 +1,31 @@ +%% Determine whether a number is even or not +% -------------------------------------------------- +% Author: Achilles Kappis +% e-mail: axilleaz@protonmail.com +% +% Date: 04/02/2024 (DD/MM/YYYY) +% +% Copyright: MIT +% -------------------------------------------------- +% Functionality: Function to check if a real number is odd. +% -------------------------------------------------- +% Input arguments +% +% num [numeric]: The number to check. +% +% -------------------------------------------------- +% Output arguments +% +% result [logical]: true if the number is odd, false else. +% +% -------------------------------------------------- +% Notes +% +% Dependencies: - isEven() from the IN-NOVA MATLAB® Utilities. +% -------------------------------------------------- +function result = isOdd(num) + % ==================================================== + % Perform the check + % ==================================================== + result = ~isEven(num); +end \ No newline at end of file diff --git a/Utilities/MATLAB/Functions/pickValProb.m b/Utilities/MATLAB/Functions/pickValProb.m new file mode 100644 index 0000000000000000000000000000000000000000..548b6fcde56b7603f6e61c97a10d7720c26c7500 --- /dev/null +++ b/Utilities/MATLAB/Functions/pickValProb.m @@ -0,0 +1,75 @@ +%% Pick a value based on its probability +% -------------------------------------------------- +% Author: Achilles Kappis +% e-mail: axilleaz@protonmail.com +% +% Date: 03/02/2024 (DD/MM/YYYY) +% +% Copyright: MIT +% -------------------------------------------------- +% Functionality: Pick numbers from an array based on +% their probabilities +% -------------------------------------------------- +% Input +% +% vals [numeric]: This should be a vector holding the values from which to +% pick. +% +% probs [numeric]: These are the probabilities of each element being +% picked. It must be a vector with number of elements +% equal to "vals". Its elements must lie in the range +% [0, 1] and their sum must equal 1 (with a tolerance of +% 1e-3). +% +% nVals [numeric] (Optional): The number of values to return. [Default: 1] +% +% -------------------------------------------------- +% Output +% +% result [numeric]: The picked value(s). +% +% -------------------------------------------------- +% Notes +% +% -------------------------------------------------- +function result = pickValProb(vals, probs, nVals) + % ==================================================== + % Check for number of arguments + % ==================================================== + narginchk(2, 3); + nargoutchk(0, 1); + + % ==================================================== + % Validate input arguments + % ==================================================== + % Validate mandatory arguments + validateattributes(vals, "numeric", {'vector', 'finite', 'nonempty'}, mfilename, "Values from which to pick.", 1); + validateattributes(probs, "numeric", {'numel', numel(vals), 'real', 'vector', 'nonempty', 'nonnan', 'finite', '<=', 1, '>=', 0}, mfilename, "Probability of each number to be picked.", 2); + + % Check that probabilities sum to 1 with a tolerance of 10 * eps + if abs(sum(probs) - 1) > 1e3 * eps + error("pickValProb(): Sum of probabilities must be one (with a tolerance of about 1000 * eps)"); + end + + + % Validate optional arguments + if nargin > 2 + validateattributes(nVals, "numeric", {'scalar', 'finite', 'positive', 'real', 'nonempty', 'nonnan', 'integer'}, mfilename, "Number of values to return.", 3); + else + nVals = 1; + end + + + % ==================================================== + % Pick values + % ==================================================== + % Calculate cumulative probability + P = cumsum(probs(:)/sum(probs)); + + % Generate random values + randIdx = rand(nVals, 1) * ones(1, length(vals)); + + % Get the correct elements + randIdx = sum(P(:).' < randIdx, 2) + 1; + result = vals(randIdx); +end \ No newline at end of file diff --git a/Utilities/MATLAB/Functions/ptsOnSphere.m b/Utilities/MATLAB/Functions/ptsOnSphere.m new file mode 100755 index 0000000000000000000000000000000000000000..e40b7b7549e1140de40b4bf2a04de57e62dc76d3 --- /dev/null +++ b/Utilities/MATLAB/Functions/ptsOnSphere.m @@ -0,0 +1,142 @@ +%% Calculate equispaced positions on a sphere surface +% -------------------------------------------------- +% Author: Achilles Kappis +% e-mail: axilleaz@protonmail.com +% +% Date: 23/02/2024 (DD/MM/YYYY) +% +% Copyright: MIT +% -------------------------------------------------- +% Functionality: Calculate positions of uniformly distributed source on a +% sphere. +% -------------------------------------------------- +% Input arguments +% +% rad [numeric]: The radius of the sphere. +% +% param [numeric]: This is the parameter used for the generation of the +% positions on the sphere and depends on the value of the +% "method" argument. If "method" is "Grid" this argument +% corresponds to the angular distance in degrees, between +% positions on the sphere surface. If "method" is +% "Fibonacci" this argument corresponds to the number of +% points (almost, see next argument). +% +% method [string/char] (Optional): The method to be used to generate the +% points. This argument can be either +% "Grid" or "Fibonacci" and is not case +% sensitive. The "Grid" method generates +% poits of approximately equal angular +% distance, while the "Fibonacci" method +% calculates points on spirals with +% specific features (see "Notes" for more +% information"). The "Fibonacci" method +% always returns an odd number of sources. +% [Default: Grid]. +% +% -------------------------------------------------- +% Output arguments +% +% pts [numeric]: The 3D vectors of the positions. The dimensions of the +% matrix is Nx3 where N is the number of sources and the +% columns represent the coordinates of the vectors [x,y,z]. +% +% -------------------------------------------------- +% Acknowledgements +% +% - The "Grid" method is an adaptation of a function provided by Prof. +% Jordan Cheer of the Institute of Sound and Vibration Research (ISVR), +% University of Southampton. +% +% - The "Fibonacci" method is taken from "Measurement of Areas on a Sphere +% Using Fibonacci and Latitude-Longitude Lattices" by Alvaro Gonzalez. +% +% -------------------------------------------------- +function pts = ptsOnSphere(rad, param, method) + % ==================================================== + % Check for number of arguments + % ==================================================== + narginchk(2, 3); + nargoutchk(0, 1); + + % ==================================================== + % Validate input arguments + % ==================================================== + % Method is needed to evaluate the parameter argument + if nargin > 2 && ~isempty(method) + validateattributes(method, {'char', 'string'}, "scalartext", mfilename, "Method of point calculation", 3); + validatestring(method, ["Grid", "Fibonacci"], mfilename, "Method of point calculation", 3); + else + method = "Grid"; + end + + % Validate mandatory arguments + validateattributes(rad, "numeric", {'scalar', 'finite', 'nonempty', 'nonnan', 'real'}, mfilename, "The radius of the sphere.", 1); + + if strcmpi(method, "Grid") + validateattributes(param, "numeric", {'scalar', 'finite', 'nonempty', 'nonnan', 'positive', 'real'}, mfilename, "The inter-element angular distance", 2); + else + validateattributes(param, "numeric", {'scalar', 'finite', 'nonempty', 'nonnan', 'positive', 'real', 'integer'}, mfilename, "The number of sources minus one", 2); + end + + + % ==================================================== + % Generate positions + % ==================================================== + if strcmpi(method, "Grid") + % Define sensors in the horizontal plane + theta = deg2rad(0:param:360 - param).'; % Angles + + % Angles between the horizontal planes + phi = deg2rad(-90 + param:param:90 - param); + + % Calculate the number of sources on each horizontal plane + nHorSrc = (floor(length(theta) * cos(phi))); + totSrc = sum(nHorSrc); + param = 2 * pi./nHorSrc; % Actual delta theta for the generated points + + % ==================================================== + % Calculate positions + % ==================================================== + % Pre-allocate + azim = zeros(1, totSrc); + elev = zeros(1, totSrc); + + % Go through the angles + cnt = 1; + for idx = 1:length(phi) + azim(1, cnt:cnt + nHorSrc(idx) - 1) = (0:param(idx):2 * pi - param(idx)); + elev(1, cnt:cnt + nHorSrc(idx) - 1) = repmat(phi(idx), 1, nHorSrc(idx)); + cnt = cnt + nHorSrc(idx); + end + + % Convert to Cartesian + [x, y, z] = sph2cart(azim, elev, repmat(rad, 1, totSrc)); + pts = [x(:), y(:), z(:)]; + + % Add two sources on the "poles" + pts = [0, 0, rad; pts; 0,0 , -rad]; + else + % Define some parameters + gRatio = 1.61803398875; % Golden ratio + param = floor(param/2); + + % Pre-allocate + pts = zeros(param, 2); + cnt = 1; + + % Calculate points + for idx = -param:param + elev = asin((2 * idx)/(2 * param + 1)) * 180/pi; + azim = mod(idx, gRatio) * 360/gRatio; + + azim = azim + (360 * azim < -180) - (360 * azim > 180); + + pts(cnt, :) = [azim, elev]; + cnt = cnt + 1; + end + + [ptsX, ptsY, ptsZ] = sph2cart(deg2rad(pts(:, 1)), deg2rad(pts(:, 2)), rad); + pts = [ptsX, ptsY, ptsZ]; + end +end diff --git a/Utilities/MATLAB/Functions/randUniqRows.m b/Utilities/MATLAB/Functions/randUniqRows.m new file mode 100644 index 0000000000000000000000000000000000000000..1c96f956ce7e0cda0b08119cf91a5327c85edbc7 --- /dev/null +++ b/Utilities/MATLAB/Functions/randUniqRows.m @@ -0,0 +1,60 @@ +%% Pick a number of unique rows from a matrix at random +% -------------------------------------------------- +% Author: Achilles Kappis +% e-mail: axilleaz@protonmail.com +% +% Date: 06/02/2024 (DD/MM/YYYY) +% +% Copyright: MIT +% -------------------------------------------------- +% Functionality: Pick a specified number of unique rows from a matrix at +% random. +% -------------------------------------------------- +% Input arguments +% +% mat [numeric]: The matrix from which rows will be picked. Only 2D +% matrices are supported. +% +% nRows [numeric]: The number of unique rows to pick from the matrix. +% +% -------------------------------------------------- +% Output arguments +% +% uniqueRows [numeric]: The unique rows picked from the matrix +% +% -------------------------------------------------- +% Notes +% +% -------------------------------------------------- +function uniqueRows = randUniqRows(mat, nRows) + % ==================================================== + % Check for number of arguments + % ==================================================== + narginchk(2, 2); + nargoutchk(0, 1); + + % ==================================================== + % Validate arguments + % ==================================================== + % Mandatory arguments + validateattributes(mat, "numeric", {'nonempty', '2d'}, mfilename, "Matrix from which to pick rows", 1); + validateattributes(nRows, "numeric", {'scalar', 'nonempty', 'integer', 'positive', 'finite', 'real', 'nonnan'}, mfilename, "Number of unique rows to pick", 2); + + % ==================================================== + % Start working + % ==================================================== + % Get the unique rows of the matrix + uniqueRows = unique(mat, "rows", "stable"); + + % Check number of items asked for against available items + if nRows >= size(uniqueRows, 1) + return; + else + uniqueIdx = []; + while numel(uniqueIdx) < nRows + uniqueIdx = cat(1, uniqueIdx, randi(size(uniqueRows, 1), nRows, 1)); + uniqueIdx = unique(uniqueIdx, "stable"); + end + uniqueRows = uniqueRows(uniqueIdx(1:nRows), :); + end +end \ No newline at end of file diff --git a/Utilities/MATLAB/Functions/rotMat3d.m b/Utilities/MATLAB/Functions/rotMat3d.m new file mode 100644 index 0000000000000000000000000000000000000000..73be7904b056bc0d0dd017855a6dc9e63ca5145e --- /dev/null +++ b/Utilities/MATLAB/Functions/rotMat3d.m @@ -0,0 +1,84 @@ +%% Calculate a 3D rotation matrix +% -------------------------------------------------- +% Author: Achilles Kappis +% e-mail: axilleaz@protonmail.com +% +% Date: 03/02/2024 (DD/MM/YYYY) +% +% Copyright: MIT +% -------------------------------------------------- +% Functionality: Calculate a 3D rotation matrix. +% -------------------------------------------------- +% Input +% +% xAng [numeric]: Rotation angle along the x-axis. +% +% yAng [numeric] (Optional): Rotation angle along the y-axis. [Default: 0]. +% +% zAng [numeric] (Optional) : Rotation angle along the z-axis. +% [Default: 0]. +% -------------------------------------------------- +% Output +% +% rotMat [numeric]: A 3x3 matrix which applies the rotation. +% +% xRotMat[numeric]: A 3x3 matrix which applies the rotation along the +% x-axis. +% +% yRotMat[numeric]: A 3x3 matrix which applies the rotation along the +% y-axis. +% +% zRotMat[numeric]: A 3x3 matrix which applies the rotation along the +% z-axis. +% -------------------------------------------------- +% Notes +% +% -------------------------------------------------- +function [rotMat, xRotMat, yRotMat, zRotMat] = rotMat3d(xAng, yAng, zAng) + % ==================================================== + % Check for number of arguments + % ==================================================== + narginchk(1, 3); + nargoutchk(0, 4); + + % ==================================================== + % Validate input arguments + % ==================================================== + % Mandatory arguments + validateattributes(xAng, "numeric", {'scalar', 'nonnan', 'finite', 'real'}, mfilename, 'Roll angle', 1); + + % Optional arguments + if nargin > 1 + validateattributes(yAng, "numeric", {'scalar', 'nonnan', 'finite', 'real'}, mfilename, 'Pitch angle', 2); + else + yAng = 0; + end + + if nargin > 2 + validateattributes(zAng, "numeric", {'scalar', 'nonnan', 'finite', 'real'}, mfilename, 'Yaw angle', 2); + else + zAng = 0; + end + + + % ==================================================== + % Create respective matrices + % ==================================================== + % Rolling rotation matrix + xRotMat = [1, 0, 0;... + 0, cos(xAng), -sin(xAng);... + 0, sin(xAng), cos(xAng)]; + + % Pitch rotation matrix + yRotMat = [cos(yAng), 0, sin(yAng);... + 0, 1, 0;... + -sin(yAng), 0, cos(yAng)]; + + % Yaw rotation matrix + zRotMat = [cos(zAng), -sin(zAng), 0;... + sin(zAng), cos(zAng), 0;... + 0, 0, 1]; + + % Complete rotation matrix + rotMat = zRotMat * yRotMat * xRotMat; +end diff --git a/Utilities/MATLAB/Functions/rotMat3dDeg.m b/Utilities/MATLAB/Functions/rotMat3dDeg.m new file mode 100644 index 0000000000000000000000000000000000000000..e832ed348f36d2ad0c5e35e734a4534acc81ef56 --- /dev/null +++ b/Utilities/MATLAB/Functions/rotMat3dDeg.m @@ -0,0 +1,85 @@ +%% Calculate a 3D rotation matrix +% -------------------------------------------------- +% Author: Achilles Kappis +% e-mail: axilleaz@protonmail.com +% +% Date: 03/02/2024 (DD/MM/YYYY) +% +% Copyright: MIT +% -------------------------------------------------- +% Functionality: Calculate a 3D rotation matrix. +% -------------------------------------------------- +% Input +% +% xAng [numeric]: Rotation angle along the x-axis in degrees. +% +% yAng [numeric] (Optional): Rotation angle along the y-axis in degrees. +% [Default: 0]. +% +% zAng [numeric] (Optional) : Rotation angle along the z-axis in degrees. +% [Default: 0]. +% -------------------------------------------------- +% Output +% +% rotMat [numeric]: A 3x3 matrix which applies the rotation. +% +% xRotMat[numeric]: A 3x3 matrix which applies the rotation along the +% x-axis. +% +% yRotMat[numeric]: A 3x3 matrix which applies the rotation along the +% y-axis. +% +% zRotMat[numeric]: A 3x3 matrix which applies the rotation along the +% z-axis. +% -------------------------------------------------- +% Notes +% +% -------------------------------------------------- +function [rotMat, xRotMat, yRotMat, zRotMat] = rotMat3dDeg(xAng, yAng, zAng) + % ==================================================== + % Check for number of arguments + % ==================================================== + narginchk(1, 3); + nargoutchk(0, 4); + + % ==================================================== + % Validate input arguments + % ==================================================== + % Mandatory arguments + validateattributes(xAng, "numeric", {'scalar', 'nonnan', 'finite', 'real'}, mfilename, 'Roll angle', 1); + + % Optional arguments + if nargin > 1 + validateattributes(yAng, "numeric", {'scalar', 'nonnan', 'finite', 'real'}, mfilename, 'Pitch angle', 2); + else + yAng = 0; + end + + if nargin > 2 + validateattributes(zAng, "numeric", {'scalar', 'nonnan', 'finite', 'real'}, mfilename, 'Yaw angle', 2); + else + zAng = 0; + end + + + % ==================================================== + % Create respective matrices + % ==================================================== + % Rolling rotation matrix + xRotMat = [1, 0, 0;... + 0, cosd(xAng), -sind(xAng);... + 0, sind(xAng), cosd(xAng)]; + + % Pitch rotation matrix + yRotMat = [cosd(yAng), 0, sind(yAng);... + 0, 1, 0;... + -sind(yAng), 0, cosd(yAng)]; + + % Yaw rotation matrix + zRotMat = [cosd(zAng), -sind(zAng), 0;... + sind(zAng), cosd(zAng), 0;... + 0, 0, 1]; + + % Complete rotation matrix + rotMat = zRotMat * yRotMat * xRotMat; +end \ No newline at end of file diff --git a/Utilities/MATLAB/Functions/stepFunc.m b/Utilities/MATLAB/Functions/stepFunc.m new file mode 100755 index 0000000000000000000000000000000000000000..60d8733c04d79827c2474774992ad552de38b3f2 --- /dev/null +++ b/Utilities/MATLAB/Functions/stepFunc.m @@ -0,0 +1,59 @@ +%% Numerical (simple) Heaviside function +% -------------------------------------------------- +% Author: Achilles Kappis +% e-mail: axilleaz@protonmail.com +% +% Date: 03/02/2024 (DD/MM/YYYY) +% +% Copyright: MIT +% -------------------------------------------------- +% Functionality: A Heaviside (step) function +% -------------------------------------------------- +% Input +% +% x [numeric]: The argument of the function. Multi-dimensional arrays are +% supported. +% +% zeroHalf [logical] (Optional): The way x = 0 is treated. If this argument +% is true, the returned value is 0.5 when +% x = 0, otherwise it is 1. +% [Default: false]. +% +% -------------------------------------------------- +% Output +% result [numeric]: Either 0 or 1 based on whether the argument of the +% function is greater or equal to zero. +% -------------------------------------------------- +% Notes +% +% -------------------------------------------------- +function result = stepFunc(x, zeroHalf) + % ==================================================== + % Check for number of arguments + % ==================================================== + narginchk(1, 2); + nargoutchk(0, 1); + + % ==================================================== + % Validate arguments + % ==================================================== + % Mandatory arguments + validateattributes(x, "numeric", {'real', 'nonempty', 'nonnan', 'finite'}, mfilename, 'Function argument.', 1); + + % Optional arguments + if nargin > 1 + validateattributes(zeroHalf, "logical", {'scalar', 'nonempty', 'nonnan'}, mfilename, "Treatment of x = 0 case.", 2); + else + zeroHalf = false; + end + + + % ==================================================== + % Calculate result + % ==================================================== + if zeroHalf + result = heaviside(x); + else + result = x >= 0; + end +end \ No newline at end of file diff --git a/Utilities/MATLAB/Functions/twoPtDist.m b/Utilities/MATLAB/Functions/twoPtDist.m new file mode 100644 index 0000000000000000000000000000000000000000..b99666c1bf8ff78d8db50a0fb0c10cff7fd02762 --- /dev/null +++ b/Utilities/MATLAB/Functions/twoPtDist.m @@ -0,0 +1,60 @@ +%% Calculate the distance between two points in space +% -------------------------------------------------- +% Author: Achilles Kappis +% e-mail: axilleaz@protonmail.com +% +% Date: 03/02/2024 (DD/MM/YYYY) +% +% Copyright: MIT +% -------------------------------------------------- +% Functionality: Calculate distance between positions in 3D. +% -------------------------------------------------- +% Input arguments +% +% srcPos [numeric]: The 3D position vectors of the starting points. The +% rows represent points and the columns their Cartesian +% coordinates [x,y,z] resulting in an Nx3 matrix with N +% being the number of points. +% +% rcvPos [numeric]: The 3D position vectors of the end points. The rows +% represent points and the columns their Cartesian +% coordinates [x,y,z] resulting in an Nx3 matrix with N +% being the number of points. +% +% -------------------------------------------------- +% Output arguments +% +% dist [numeric]: The distance between each start and end point. The +% dimensions of the argument is MxN with each row +% corresponding to the distance between the mth start point +% and each of the N end points. +% +% -------------------------------------------------- +% Notes +% +% -------------------------------------------------- +function dist = twoPtDist(srcPos, rcvPos) + % ==================================================== + % Check for number of arguments + % ==================================================== + narginchk(2, 2); + nargoutchk(0, 1); + + % ==================================================== + % Validate arguments + % ==================================================== + % Mandatory arguments + validateattributes(srcPos, "numeric", {'ncols', 3, 'nonempty', 'nonnan', 'finite', 'real'}, mfilename, "Start points Cartesian coordinates", 1); + validateattributes(rcvPos, "numeric", {'ncols', 3, 'nonempty', 'nonnan', 'finite', 'real'}, mfilename, "End points Cartesian coordinates", 2); + + % ==================================================== + % Start working + % ==================================================== + % Get number of receivers + nRcv = size(rcvPos, 1); + + % Go through the sources + for idx = nRcv:-1:1 + dist(idx, :) = vecnorm(rcvPos(idx, :) - srcPos, 2, 2); + end +end \ No newline at end of file diff --git a/Utilities/MATLAB/README.md b/Utilities/MATLAB/README.md new file mode 100644 index 0000000000000000000000000000000000000000..76ad1ed498fb9cb7c041d30221ff80e16ba13879 --- /dev/null +++ b/Utilities/MATLAB/README.md @@ -0,0 +1,57 @@ +# Matlab utilities +This project holds the utility codebase used throughout the [IN-NOVA](https://in-nova-horizon.eu/) project. + +Currently, only MATLAB® functions are included. Updates are done on an as-needed basis, and at the moment, there is no plan for in porting to other programming languages or environments. + +Furthermore, templates for MATLAB® functions are provided in the [Templates](https://gitlab.com/in-nova/utilities/matlab/-/tree/main/Templates?ref_type=heads) folder. Additional templates will be added when the need arises. + +The project uses [semantic versioning](https://semver.org/) and the current version is **v0.1.0**. + + +## Dependencies + +All dependencies must be explicitly stated both in the code and the documentation accompanying the utilities. This is essential for all sub-projects using parts of the current codebase to function properly. + +## Support +If you find any bugs, other issues and/or inconsistencies you can [e-mail](mailto::axilleaz@protonmail.com) Achilles Kappis at *<axilleaz@protonmail.com>* or *<A.Kappis@soton.ac.uk>*. More contacts will be added if/when new contributors join the project. + +## Roadmap +The repository will be updated on an as-needed basis. There is no roadmap for this project as the tools that will be needed are known not a priori. + +## Contributing +If you would like to contribute to the project you could do that in various ways, as listed below: + +- Create issues for bugs, improvements and/or features. +- Fix a bug or develop an improvement and/or feature yourself. Clone the repository, create a new branch when done create a merge request. +- Report typos and/or inconsistencies in the documentation. +- Contribute to the documentation and/or the Wiki of the project. +- Create a CI configuration for automated testing, or develop unit tests. +- Port the codebase to other programming languages and/or environments. + +#### Remarks + +Since there is no CI set at the moment to perform automated testing, you are highly encouraged to test your contributions as much as possible and even contribute some unit tests if this aligns with your contributed content. + +To try and maintain a coherent style in the codebase you are encouraged to use the template available in the [Templates](https://gitlab.com/in-nova/utilities/matlab/-/tree/main/Templates?ref_type=heads) folder, although this is not necessary. +Irrespective of style, it is highly advisable to name your variables in a meaningful manner and keep them as short as possible while still communicating their purpose. Comments are highly recommended in your code, especially where they can facilitate a better understanding of the code and the intent of the developer. Over-commented code is better than under-commented code. + + +## Authors and acknowledgment + +#### Authors + +The main contributor is Achilles Kappis. + + +#### Acknowledgments + +- The function `posOnSphere` has been adapted from a MATLAB® function provided by Prof. Jordan Cheer of ISVR - University of Southampton. + + +## License +The project is licensed under the ***MIT License***, which is a rather unrestrictive license, effectively passing the code to the public scope. For more information see the [MIT License](https://mit-license.org/), or the [LICENSE](https://gitlab.com/in-nova/utilities/matlab/-/blob/main/LICENSE) file of the project. + + +#### **Important** + +If you are unable, or do not want to contribute under this license please do **not** contribute to this project at all. All content within the project must be under the same license. \ No newline at end of file