View Raw SPL
/*****************************************************************************
* *
* CART2SPH.SPL Copyright (C) 2022 DSP Development Corporation *
* All Rights Reserved *
* *
* Author: Randy Race *
* *
* Synopsis: Spherical coordinates to XYZ *
* *
* Revisions: 15 May 2022 RRR Creation *
* *
*****************************************************************************/
#if @HELP_CART2SPH
CART2SPH
Purpose: Convert Cartesian XYZ coordinates to spherical coordinates.
Syntax: CART2SPH(x, y, z, "degrees")
x - A real or series, the X coordinate.
y - A real or series, the Y coordinate.
z - A real or series, the Z coordinate.
"degrees" - Optional. A string, if "degrees", all output angles
are in degrees. If "radians" or not specified, the
output angles are in radians.
Alternate Syntax:
CART2SPH(xyzcoords, "degrees")
xyzcoords - A 3 column series, where X is the first column,
Y the second column and Z the third column.
"degrees" - Optional. A string, if "degrees", all output angles
are in degrees. If "radians" or not specified, the
output angles are in radians.
Returns: A three column series where the first column is azimuth, the
second column is elevation and the third column is the radius.
(az, el, r) = CART2SPH(x, y, z) returns the spherical coordinates
as separate series.
Example:
W1: cart2sph(1.0, 1.0, sqrt(2))
W1 == {{0.785398, 0.785398, 2}}
W1 transforms the XYZ coordinate with an X of 1 unit, a
Y of 1 unit and Z of sqrt(2) to a spherical coordinate.
The result is a 1x3 array where the azimuth value is pi/4
radians, the elevation value is pi/4 radians and the
radius is 2 units.
Example:
W1: cart2sph(1.0, 1.0, sqrt(2), "degrees")
W1 == {{45, 45, 2}}
Same as above except azimuth and elevation are in degrees.
Example:
W2: {{1.0, 1.0, sqrt(2)}}
W3: cart2sph(w2, "degrees")
W3 == {{45, 45, 2}}
Same as above except the input Cartesian coordinates are
contained in a single 3 column series.
Example:
W4: {{1.0, 1.0, sqrt(2)}}
(az, el, r) = cart2sph(w4, "degrees");
az == {45}
el == {45}
r == {2}
Same as above except the output spherical coordinates are
contained in three separate variables.
Example:
W1: {{1.0, 1.0, sqrt(2)}}
W2: cart2sph(w1)
W3: sph2cart(w2)
W3 == {{1.0, 1.0, 1.414214}}
Demonstrates that CART2SPH and SPH2CART are inverse functions.
Remarks:
CART2SPH transforms Cartesian XYZ coordinates to azimuth,
elevation and radius spherical coordinates.
AZIMUTH (az) is measured counterclockwise from the positive X
axis in the X-Y plane. AZIMUTH is in radians unless
"degrees" is specified. AZIMUTH varies from 0 to 2*pi radians
or 0 to 360 degrees.
ELEVATION (el) is measured from the X-Y plane. ELEVATION is in
radians unless "degrees" is specified. ELEVATION varies from
-pi/2 to pi/2 radians or -90 to 90 degrees.
RADIUS (r) is the length of the 3D vector.
If "degrees" is specified, the output AZIMUTH and ELEVATION
angles are in degrees. If "radians" or not specified, AZIMUTH
and ELEVATION are in radians.
See Also:
Sph2cart
#endif
/* XYZ coords to spherical */
cart2sph(argv)
{
local az, el, r;
/* parse args */
(x, y, z, dflag) = cart2sph_parse_args(__FUNC__, argv);
/* sub-expression */
xy2 = x*x + y*y;
/* transformation */
az = atan2(y, x);
el = atan2(z, sqrt(xy2));
r = sqrt(xy2 + z*z);
if (dflag == "degrees")
{
az *= 180 / pi;
el *= 180 / pi;
}
if (outargc <= 1)
{
/* force series for ravel */
az = {az};
el = {el};
r = {r};
}
/* add comments */
if (isarray(az))
{
setcomment(az, "Azimuth");
}
if (isarray(el))
{
setcomment(el, "Elevation");
}
if (isarray(r))
{
setcomment(r, "Radius");
}
/* output */
if (outargc > 1)
{
return(az, el, r);
}
else
{
return(ravel(az, el, r));
}
}
/* parse args */
cart2sph_parse_args(func, argv)
{
local x, y, z, dflag;
x = y = z = dflag = {};
loop (j = 1..(argc - 1))
{
if (isarray(getargv(j)) || isscalar(getargv(j)))
{
if (isempty(x))
{
x = getargv(j);
}
else if (isempty(y))
{
y = getargv(j);
}
else if (isempty(z))
{
z = getargv(j);
}
else
{
error(sprintf("%s - too many input arguments", func));
}
}
else if (isstring(getargv(j)))
{
if (isempty(dflag))
{
dflag = tolower(getargv(j));
}
}
}
if (isempty(x))
{
error(sprintf("%s - input XYZ required", func));
}
else if (numcols(x) == 3)
{
/* x, y, z three column input */
z = col(x, 3);
y = col(x, 2);
x = col(x, 1);
}
if (isempty(dflag))
{
dflag = "radians";
}
if (not(dflag == "radians" || dflag == "degrees"))
{
error(sprintf('%s - unknown flag "%s"', func, dflag));
}
return(x, y, z, dflag);
}