Mercurial > octave
comparison scripts/general/cart2sph.m @ 28171:a23da76e0693
Matlab compatibility fixes for coordinate transform functions (bug #57794).
* cart2pol.m, cart2sph.m, pol2cart.m, sph2cart.m: Modified to allow row or
column vector inputs, remove full matrix single output argument option, and
clarified coordinate definitions in help text.
* lightangle.m, surfl.m: Fix existing instances where single output was used
and a matrix was expected.
* NEWS: Added coordinate transform changes to Matlab compatibility section.
author | Nicholas R. Jankowski <jankowskin@asme.org> |
---|---|
date | Sun, 16 Feb 2020 20:19:05 -0500 |
parents | a4268efb7334 |
children | 90fea9cc9caa |
comparison
equal
deleted
inserted
replaced
28170:5e49ba5bdcc1 | 28171:a23da76e0693 |
---|---|
24 ######################################################################## | 24 ######################################################################## |
25 | 25 |
26 ## -*- texinfo -*- | 26 ## -*- texinfo -*- |
27 ## @deftypefn {} {[@var{theta}, @var{phi}, @var{r}] =} cart2sph (@var{x}, @var{y}, @var{z}) | 27 ## @deftypefn {} {[@var{theta}, @var{phi}, @var{r}] =} cart2sph (@var{x}, @var{y}, @var{z}) |
28 ## @deftypefnx {} {[@var{theta}, @var{phi}, @var{r}] =} cart2sph (@var{C}) | 28 ## @deftypefnx {} {[@var{theta}, @var{phi}, @var{r}] =} cart2sph (@var{C}) |
29 ## @deftypefnx {} {@var{S} =} cart2sph (@dots{}) | |
30 ## Transform Cartesian coordinates to spherical coordinates. | 29 ## Transform Cartesian coordinates to spherical coordinates. |
31 ## | 30 ## |
32 ## The inputs @var{x}, @var{y}, and @var{z} must be the same shape, or scalar. | 31 ## The inputs @var{x}, @var{y}, and @var{z} must be the same shape, or scalar. |
33 ## If called with a single matrix argument then each row of @var{C} represents | 32 ## If called with a single matrix argument then each row of @var{C} must |
34 ## the Cartesian coordinate (@var{x}, @var{y}, @var{z}). | 33 ## represent a Cartesian coordinate triplet (@var{x}, @var{y}, @var{z}). |
35 ## | 34 ## |
36 ## @var{theta} describes the angle relative to the positive x-axis. | 35 ## The outputs @var{theta}, @var{phi}, @var{r} match the shape of the inputs. |
37 ## | 36 ## For a matrix input @var{C} the outputs will be column vectors with rows |
38 ## @var{phi} is the angle relative to the xy-plane. | 37 ## corresponding to the rows of the input matrix. |
38 ## | |
39 ## @var{theta} describes the azimuth angle relative to the positive x-axis | |
40 ## measured in the xy-plane. | |
41 ## | |
42 ## @var{phi} is the elevation angle measured relative to the xy-plane. | |
39 ## | 43 ## |
40 ## @var{r} is the distance to the origin @w{(0, 0, 0)}. | 44 ## @var{r} is the distance to the origin @w{(0, 0, 0)}. |
41 ## | 45 ## |
42 ## If only a single return argument is requested then return a matrix @var{S} | 46 ## The coordinate transformation is computed using: |
43 ## where each row represents one spherical coordinate | 47 ## |
44 ## (@var{theta}, @var{phi}, @var{r}). | 48 ## @tex |
49 ## $$ \theta = \arctan \left ({y \over x} \right ) $$ | |
50 ## $$ \phi = \arctan \left ( {z \over {\sqrt{x^2+y^2}}} \right ) $$ | |
51 ## $$ r = \sqrt{x^2 + y^2 + z^2} $$ | |
52 ## @end tex | |
53 ## @ifnottex | |
54 ## | |
55 ## @example | |
56 ## @group | |
57 ## @var{theta} = arctan (@var{y} / @var{x}) | |
58 ## @var{phi} = arctan (@var{z} / sqrt (@var{x}^2 + @var{y}^2)) | |
59 ## @var{r} = sqrt (@var{x}^2 + @var{y}^2 + @var{z}^2) | |
60 ## @end group | |
61 ## @end example | |
62 ## | |
63 ## @end ifnottex | |
64 ## | |
65 ## @c FIXME: Remove this note in Octave 9.1 (two releases after 7.1). | |
66 ## Note: For @sc{matlab} compatibility, this function no longer returns a full | |
67 ## coordinate matrix when called with a single return argument. | |
45 ## @seealso{sph2cart, cart2pol, pol2cart} | 68 ## @seealso{sph2cart, cart2pol, pol2cart} |
46 ## @end deftypefn | 69 ## @end deftypefn |
47 | 70 |
48 function [theta, phi, r] = cart2sph (x, y, z) | 71 function [theta, phi, r] = cart2sph (x, y, z) |
49 | 72 |
50 if (nargin != 1 && nargin != 3) | 73 if (nargin != 1 && nargin != 3) |
51 print_usage (); | 74 print_usage (); |
52 endif | 75 endif |
53 | 76 |
54 if (nargin == 1) | 77 if (nargin == 1) |
55 if (! (isnumeric (x) && ismatrix (x) && columns (x) == 3)) | 78 if (! (isnumeric (x) && ismatrix (x))) |
56 error ("cart2sph: matrix input must have 3 columns [X, Y, Z]"); | 79 error ("cart2sph: matrix input C must be a 2-D numeric array"); |
57 endif | 80 elseif (columns (x) != 3 && numel (x) != 3) |
58 z = x(:,3); | 81 error ("cart2sph: matrix input C must be a 3-element vector or 3-column array"); |
59 y = x(:,2); | 82 endif |
60 x = x(:,1); | 83 |
84 if (numel (x) == 3) | |
85 z = x(3); | |
86 y = x(2); | |
87 x = x(1); | |
88 else | |
89 z = x(:,3); | |
90 y = x(:,2); | |
91 x = x(:,1); | |
92 endif | |
93 | |
61 else | 94 else |
62 if (! isnumeric (x) || ! isnumeric (y) || ! isnumeric (z)) | 95 if (! (isnumeric (x) && isnumeric (y) && isnumeric (z))) |
63 error ("cart2sph: X, Y, Z must be numeric arrays of the same size, or scalar"); | 96 error ("cart2sph: X, Y, Z must be numeric arrays or scalars"); |
64 endif | 97 endif |
65 [err, x, y, z] = common_size (x, y, z); | 98 [err, x, y, z] = common_size (x, y, z); |
66 if (err) | 99 if (err) |
67 error ("cart2sph: X, Y, Z must be numeric arrays of the same size, or scalar"); | 100 error ("cart2sph: X, Y, Z must be the same size or scalars"); |
68 endif | 101 endif |
69 endif | 102 endif |
70 | 103 |
71 theta = atan2 (y, x); | 104 theta = atan2 (y, x); |
72 phi = atan2 (z, sqrt (x .^ 2 + y .^ 2)); | 105 phi = atan2 (z, sqrt (x .^ 2 + y .^ 2)); |
73 r = sqrt (x .^ 2 + y .^ 2 + z .^ 2); | 106 r = sqrt (x .^ 2 + y .^ 2 + z .^ 2); |
74 | 107 |
75 if (nargout <= 1) | |
76 theta = [theta(:), phi(:), r(:)]; | |
77 endif | |
78 | |
79 endfunction | 108 endfunction |
80 | 109 |
81 | 110 |
82 %!test | 111 %!test |
83 %! x = [0, 1, 2]; | 112 %! x = [0, 1, 2]; |
87 %! assert (t, [0, pi/4, pi/4], eps); | 116 %! assert (t, [0, pi/4, pi/4], eps); |
88 %! assert (p, [0, 1, 1]*atan (sqrt (0.5)), eps); | 117 %! assert (p, [0, 1, 1]*atan (sqrt (0.5)), eps); |
89 %! assert (r, [0, 1, 2]*sqrt (3), eps); | 118 %! assert (r, [0, 1, 2]*sqrt (3), eps); |
90 | 119 |
91 %!test | 120 %!test |
121 %! x = [0; 1; 2]; | |
122 %! y = [0; 1; 2]; | |
123 %! z = [0; 1; 2]; | |
124 %! [t, p, r] = cart2sph (x, y, z); | |
125 %! assert (t, [0; pi/4; pi/4], eps); | |
126 %! assert (p, [0; 1; 1] * atan (sqrt (0.5)), eps); | |
127 %! assert (r, [0; 1; 2] * sqrt (3), eps); | |
128 | |
129 %!test | |
92 %! x = 0; | 130 %! x = 0; |
93 %! y = [0, 1, 2]; | 131 %! y = [0, 1, 2]; |
94 %! z = [0, 1, 2]; | 132 %! z = [0, 1, 2]; |
95 %! S = cart2sph (x, y, z); | 133 %! [t, p, r] = cart2sph (x, y, z); |
96 %! assert (S(:,1), [0; 1; 1] * pi/2, eps); | 134 %! assert (t, [0, 1, 1] * pi/2, eps); |
97 %! assert (S(:,2), [0; 1; 1] * pi/4, eps); | 135 %! assert (p, [0, 1, 1] * pi/4, eps); |
98 %! assert (S(:,3), [0; 1; 2] * sqrt (2), eps); | 136 %! assert (r, [0, 1, 2] * sqrt (2), eps); |
99 | 137 |
100 %!test | 138 %!test |
101 %! x = [0, 1, 2]; | 139 %! x = [0, 1, 2]; |
102 %! y = 0; | 140 %! y = 0; |
103 %! z = [0, 1, 2]; | 141 %! z = [0, 1, 2]; |
104 %! [t, p, r] = cart2sph (x, y, z); | 142 %! [t, p, r] = cart2sph (x, y, z); |
105 %! assert (t, [0, 0, 0]); | 143 %! assert (t, [0, 0, 0]); |
106 %! assert (p, [0, 1, 1] * pi/4); | 144 %! assert (p, [0, 1, 1] * pi/4, eps); |
107 %! assert (r, [0, 1, 2] * sqrt (2)); | 145 %! assert (r, [0, 1, 2] * sqrt (2), eps); |
108 | 146 |
109 %!test | 147 %!test |
110 %! x = [0, 1, 2]; | 148 %! x = [0, 1, 2]; |
111 %! y = [0, 1, 2]; | 149 %! y = [0, 1, 2]; |
112 %! z = 0; | 150 %! z = 0; |
113 %! [t, p, r] = cart2sph (x, y, z); | 151 %! [t, p, r] = cart2sph (x, y, z); |
114 %! assert (t, [0, 1, 1] * pi/4); | 152 %! assert (t, [0, 1, 1] * pi/4, eps); |
115 %! assert (p, [0, 0, 0]); | 153 %! assert (p, [0, 0, 0]); |
116 %! assert (r, [0, 1, 2] * sqrt (2)); | 154 %! assert (r, [0, 1, 2] * sqrt (2), eps); |
117 | 155 |
118 %!test | 156 %!test |
119 %! x = 0; | 157 %! x = 0; |
120 %! y = 0; | 158 %! y = 0; |
121 %! z = [0, 1, 2]; | 159 %! z = [0, 1, 2]; |
122 %! [t, p, r] = cart2sph (x, y, z); | 160 %! [t, p, r] = cart2sph (x, y, z); |
123 %! assert (t, [0, 0, 0]); | 161 %! assert (t, [0, 0, 0]); |
124 %! assert (p, [0, 1, 1] * pi/2); | 162 %! assert (p, [0, 1, 1] * pi/2, eps); |
125 %! assert (r, [0, 1, 2]); | 163 %! assert (r, [0, 1, 2]); |
126 | 164 |
127 %!test | 165 %!test |
128 %! C = [0, 0, 0; 1, 0, 1; 2, 0, 2]; | 166 %! C = [0, 0, 0; 1, 0, 1; 2, 0, 2]; |
129 %! S = [0, 0, 0; 0, pi/4, sqrt(2); 0, pi/4, 2*sqrt(2)]; | 167 %! [t, p, r] = cart2sph (C); |
130 %! assert (cart2sph (C), S, eps); | 168 %! assert (t, [0; 0; 0]); |
169 %! assert (p, [0; 1; 1] * pi/4, eps); | |
170 %! assert (r, [0; 1; 2] * sqrt (2), eps); | |
171 | |
172 %!test | |
173 %! C = [0, 0, 0; 1, 0, 1; 2, 0, 2; 1, 0, 1]; | |
174 %! [t, p, r] = cart2sph (C); | |
175 %! assert (t, [0; 0; 0; 0]); | |
176 %! assert (p, [0; 1; 1; 1] * pi/4, eps); | |
177 %! assert (r, [0; 1; 2; 1] * sqrt (2), eps); | |
131 | 178 |
132 %!test | 179 %!test |
133 %! [x, y, z] = meshgrid ([0, 1], [0, 1], [0, 1]); | 180 %! [x, y, z] = meshgrid ([0, 1], [0, 1], [0, 1]); |
134 %! [t, p, r] = cart2sph (x, y, z); | 181 %! [t, p, r] = cart2sph (x, y, z); |
135 %! T(:, :, 1) = [0, 0; pi/2, pi/4]; | 182 %! T(:, :, 1) = [0, 0; pi/2, pi/4]; |
143 | 190 |
144 ## Test input validation | 191 ## Test input validation |
145 %!error cart2sph () | 192 %!error cart2sph () |
146 %!error cart2sph (1,2) | 193 %!error cart2sph (1,2) |
147 %!error cart2sph (1,2,3,4) | 194 %!error cart2sph (1,2,3,4) |
148 %!error <matrix input must have 3 columns> cart2sph ({1,2,3}) | 195 %!error <matrix input C must be a 2-D numeric array> cart2sph ({1,2,3}) |
149 %!error <matrix input must have 3 columns> cart2sph (ones (3,3,2)) | 196 %!error <matrix input C must be a 2-D numeric array> cart2sph (ones (3,3,2)) |
150 %!error <matrix input must have 3 columns> cart2sph ([1,2,3,4]) | 197 %!error <matrix input C must be a 3-element> cart2sph ([1,2,3,4]) |
151 %!error <numeric arrays of the same size> cart2sph ({1,2,3}, [1,2,3], [1,2,3]) | 198 %!error <matrix input C must be a 3-element> cart2sph ([1,2,3,4; 1,2,3,4; 1,2,3,4]) |
152 %!error <numeric arrays of the same size> cart2sph ([1,2,3], {1,2,3}, [1,2,3]) | 199 %!error <must be numeric arrays or scalars> cart2sph ({1,2,3}, [1,2,3], [1,2,3]) |
153 %!error <numeric arrays of the same size> cart2sph ([1,2,3], [1,2,3], {1,2,3}) | 200 %!error <must be numeric arrays or scalars> cart2sph ([1,2,3], {1,2,3}, [1,2,3]) |
154 %!error <numeric arrays of the same size> cart2sph (ones (3,3,3), 1, ones (3,2,3)) | 201 %!error <must be numeric arrays or scalars> cart2sph ([1,2,3], [1,2,3], {1,2,3}) |
155 %!error <numeric arrays of the same size> cart2sph (ones (3,3,3), ones (3,2,3), 1) | 202 %!error <must be the same size or scalars> cart2sph ([1,2,3], [1,2,3], [1,2,3]') |
203 %!error <must be the same size or scalars> cart2sph (ones (3,3,3), 1, ones (3,2,3)) | |
204 %!error <must be the same size or scalars> cart2sph (ones (3,3,3), ones (3,2,3), 1) |