View Raw SPL
/*****************************************************************************
* *
* SPH2CART.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_SPH2CART
SPH2CART
Purpose: Convert spherical coordinates to Cartesian XYZ form.
Syntax: SPH2CART(az, el, r, "degrees")
az - A real or series, the azimuth in radians or
degrees
el - A real or series, the elevation in radians or
degrees.
r - Optional. A real or series, the radius. Defaults
to 1.0.
"degrees" - Optional. A string, if "degrees", all input angles
are in degrees. If "radians" or not specified, the
input angles are in radians.
Alternate Syntax:
SPH2CART(sphcoords, "degrees")
sphcoords - A 3 column series, where azimuth is the first
column, elevation the second column and radius
the third column.
"degrees" - Optional. A string, if "degrees", all input angles
are in degrees. If "radians" or not specified, the
input angles are in radians.
Returns: A three column series where the first column is X, the second
column is Y and the third column is Z.
(x, y, z) = sph2cart(az, el, r) returns the Cartesian coordinates
as separate series.
Example:
W1: sph2cart(pi/4, pi/4, 1.0)
W1 == {{0.5, 0.5, 0.707107}}
W1 transforms the spherical coordinate with azimuth at
pi/4 degrees, elevation of pi/4 degrees and unit length.
The result is a 1x3 array where the X value is 0.5, the
Y value is 0.5 and the Z values is sqrt(2).
Example:
W1: sph2cart(45, 45, 1.0, "degrees")
W1 == {{0.5, 0.5, 0.707107}}
Same as above except the azimuth and elevation are specified
in degrees.
Example:
W2: {{45, 45, 1.0}}
W3: sph2cart(w2, "degrees")
W3 == {{0.5, 0.5, 0.707107}}
Same as above except the input spherical coordinates are
contained in a single 3 column series.
Example:
W4: {{45, 45, 1.0}}
(x, y, z) = sph2cart(w4, "degrees");
x == {0.5}
y == {0.5}
z == {0.707107}
Same as above except the output Cartesian coordinates are
contained in three separate variables.
Example:
W1: {{pi/4, pi/4, 1.0}}
W2: sph2cart(w1)
W3: cart2sph(w2)
W3 == {{0.785398, 0.785398, 1.0}}
Demonstrates that SPH2CART and CART2SPH are inverse functions.
Remarks:
SPH2CART transforms azimuth, elevation and radius coordinates
to Cartesian XYZ coordinates.
AZIMUTH 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 is measured from the X-Y plane. ELEVATION is in
radians unless "degrees" is specified. ELEVATION varied from
-pi/2 to pi/2 radians or -90 to 90 degrees.
RADIUS is the optional length of the 3D vector. Defaults to
unity.
If "degrees" is specified, the input AZIMUTH and ELEVATION
angles are in degrees. If "radians" or not specifed, AZIMUTH
and ELEVATION are in radians.
See Also:
Cart2sph
#endif
/* spherical coords to XYZ */
sph2cart(argv)
{
local x, y, z;
/* parse args */
(az, el, r, dflag) = sph2cart_parse_args(__FUNC__, argv);
if (dflag == "degrees")
{
az *= pi / 180;
el *= pi / 180;
}
/* transformation */
x = r * cos(el) * cos(az);
y = r * cos(el) * sin(az);
z = r * sin(el);
if (outargc <= 1)
{
/* force series for ravel */
x = {x};
y = {y};
z = {z};
}
/* add comments */
if (isarray(x))
{
setcomment(x, "X");
}
if (isarray(y))
{
setcomment(y, "Y");
}
if (isarray(z))
{
setcomment(z, "Z");
}
/* output */
if (outargc > 1)
{
return(x, y, z);
}
else
{
return(ravel(x, y, z));
}
}
/* parse args */
sph2cart_parse_args(func, argv)
{
local az, el, r, dflag;
az = el = r = dflag = {};
loop (j = 1..(argc - 1))
{
if (isarray(getargv(j)) || isscalar(getargv(j)))
{
if (isempty(az))
{
az = getargv(j);
}
else if (isempty(el))
{
el = getargv(j);
}
else if (isempty(r))
{
r = 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(az))
{
error(sprintf("%s - input azimuth and elevation required", func));
}
else if (numcols(az) == 3)
{
/* az, el, r three column input */
r = col(az, 3);
el = col(az, 2);
az = col(az, 1);
}
else if (isempty(r))
{
r = ones(length(az), 1);
}
if (isempty(dflag))
{
dflag = "radians";
}
if (not(dflag == "radians" || dflag == "degrees"))
{
error(sprintf('%s - unknown flag "%s"', func, dflag));
}
return(az, el, r, dflag);
}