meanangle.m 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107
  1. function ANGLEMEAN = meanangle(ANGLES,LIMITS,DIM)
  2. % MEANANGLE Calculates the mean angle, correcting for angle discontinuities
  3. % ANGLEMEAN = MEANANGLE(ANGLES,LIMITS,DIM) calculates the mean angle of the
  4. % input vector/matrix ANGLES taking into account discontinuities. If DIM is
  5. % specified, the mean over dimension DIM is taken. ANGLES can be up to 2D.
  6. %
  7. % Synopsis: ANGLEMEAN = MEANANGLE(ANGLES,LIMITS,DIM)
  8. % Input: ANGLES : Input vector or matrix of angles (in degrees). Up
  9. % to two dimensions.
  10. % LIMITS : Definition of angles: [-180 180] or [0 360] degrees.
  11. % DIM : Dimension over which to operate.
  12. % Output: ANGLEMEAN: Mean of ANGLES (in degrees).
  13. %
  14. % Pascal de Theije, v2.0, 13 April 2005
  15. % Copyright (c) 2005, TNO-D&V
  16. % All Rights Reserved
  17. %
  18. % Check if input angles match with specified angle limits.
  19. %
  20. if ~isempty(find((ANGLES<min(LIMITS))|(ANGLES>max(LIMITS))))
  21. disp('meanangle.m: Input angles do not match with limits.')
  22. return
  23. end
  24. % If the dimension is not specified, operate over the first dimension.
  25. if (nargin == 2)
  26. DIM = 1;
  27. end
  28. %
  29. % Transpose matrix, if necessary, so that all operations have to be done
  30. % over the second dimension.
  31. %
  32. if (DIM == 1)
  33. ANGLES = ANGLES.';
  34. end
  35. %
  36. % In order to find the best estimate of the mean angle, calculate the
  37. % in-product of an arbitrary vector [a b] and all specified angles, and find
  38. % that direction that gives the highest inproduct. The in-product is given by
  39. % [a b].*[sum(cos(ANGLES)) sum(sin(ANGLES))]. The derivative of this w.r.t.
  40. % 'a' is set to zero, which gives the solution a=sqrt(C^2/(C^2+S^2)).
  41. %
  42. C = sum(cos(ANGLES*pi/180),2);
  43. S = sum(sin(ANGLES*pi/180),2);
  44. CS = C.^2 + S.^2;
  45. % Calculate vector that gives highest inproduct.
  46. a = sqrt(C.^2./CS);
  47. b = sqrt(S.^2./CS);
  48. %
  49. % From the way 'a' and 'b' are solved, they can be either positive or negative,
  50. % while in practice only one of these combinations is the true one. Find the
  51. % combination of 'a' and 'b' that gives the lowest in-product. This angle
  52. % is used to 'split' the angle circle.
  53. %
  54. temp = (C.*a)*[-1 1 -1 1] + (S.*b)*[-1 -1 1 1];
  55. [dummy,ind] = max(temp,[],2);
  56. ind2 = find(ind==1 | ind==3);
  57. a(ind2) = -a(ind2);
  58. ind2 = find(ind==1 | ind==2);
  59. b(ind2) = -b(ind2);
  60. %
  61. % Find angle that should be used to 'split' the angle circle.
  62. %
  63. cut_angle = atan2(b,a) * 180 / pi;
  64. %
  65. % Split the angle circle at 'cut_angle'.
  66. %
  67. ANGLES = ang180(ANGLES - cut_angle*ones(1,size(ANGLES,2)));
  68. % Then take 'normal' mean.
  69. ANGLEMEAN = mean(ANGLES,2);
  70. % Undo splitting angle circle.
  71. ANGLEMEAN = ang180(ANGLEMEAN + cut_angle);
  72. %
  73. % Transform output to angles between 0 and 360 degrees, if necessary.
  74. %
  75. if (LIMITS == [0 360])
  76. ind = find(ANGLEMEAN < 0);
  77. ANGLEMEAN(ind) = ANGLEMEAN(ind) + 360;
  78. end
  79. %
  80. % Transpose matrix, if necessary.
  81. %
  82. if (DIM == 1)
  83. ANGLEMEAN = ANGLEMEAN.';
  84. end
  85. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  86. function Y = ANG180(X);
  87. % ANG180 Unwraps the input angle to an angle between -180 and 180 degrees.
  88. %
  89. % Pascal de Theije, v1.0, 24 February 1999
  90. % Copyright (c) 2003, TNO-FEL
  91. % All Rights Reserved
  92. Y = mod(X-(1e-10)-180,360) - 180 + (1e-10);
  93. % The term 1e-10 is to set an input of -180 to 180.