## Copyright (c) 2014-2018 Michael Hirsch, Ph.D.
## Copyright (c) 2013, Felipe Geremia Nievinski
##
## Redistribution and use in source and binary forms, with or without 
## modification, are permitted provided that the following conditions are met:
## 1. Redistributions of source code must retain the above copyright notice, 
##    this list of conditions and the following disclaimer.
## 2. Redistributions in binary form must reproduce the above copyright notice, 
##    this list of conditions and the following disclaimer in the documentation 
##    and/or other materials provided with the distribution.
## THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 
## AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, 
## THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
## ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 
## LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 
## CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 
## SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; 
## OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 
## WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
## (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
## SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

## -*- texinfo -*-
## @deftypefn {Function File} {@var{lat1}, @var{lon1}, @var{alt1} =} aer2geodetic (@var{az},@var{el}, @var{slantRange}, @var{lat0}, @var{lon0}, @var{alt0}, @var{spheroid}, @var{angleUnit})
## converts azimuth, elevation, range of target from observer to geodetic coordiantes
## 
## Inputs:
##
## az, el, slantrange: look angles and distance to point under test (degrees, degrees, meters)
##
## lat0, lon0, alt0: ellipsoid geodetic coordinates of observer/reference (degrees, degrees, meters)
##
## spheroid: referenceEllipsoid parameter struct default wgs84
## 
## angleUnit: string for angular units. Default 'd': degrees
##
## Outputs:
##
## lat1,lon1,alt1: geodetic coordinates of test points (degrees, degrees, meters)
##
## Example
## @example
## [x, y, z] = aer2geodetic (33, 70, 1e3, 42, -82, 200)
## x =  42.000
## y = -82.000
## z = -798.71
## @end example
## With radians
## @example
## [x, y, z] = aer2geodetic (pi/6, pi/3, 1e3, pi/4, -pi/2, 200, "wgs84", "radians")
## x =  0.78547
## y = -1.5707
## z =  1066.0
## @end example
## @end deftypefn
function [lat1, lon1, alt1] = aer2geodetic (az, el, slantrange, lat0, lon0, alt0, spheroid = "", angleUnit = "degrees")
  
  if nargin < 6
    print_usage();
  endif  
  
  if (!isnumeric (az) || !isreal (az) || !isnumeric (el) || !isreal (el) ...
    || !isnumeric (slantrange) || !isreal (slantrange) || !isnumeric (lat0) ... 
    || !isreal (lat0) || !isnumeric (lon0) || !isreal (lon0) ||  ...
    !isnumeric (alt0) || !isreal (alt0))
    error ("aer2geodetic.m : numeric values expected");
  endif
  
  if isempty (spheroid)
    E = wgs84Ellipsoid;
  elseif isstruct (spheroid)
    E = spheroid;
  else
    E = referenceEllipsoid (spheroid);
  endif 

  [x, y, z] = aer2ecef (az, el, slantrange, lat0, lon0, alt0, spheroid, angleUnit);
  [lat1, lon1, alt1] = ecef2geodetic (spheroid, x, y, z, angleUnit);

endfunction

%!test
% [lat2, lon2, alt2] = aer2geodetic (33, 70, 1e3, 42, -82, 200);
% assert ([lat2, lon2, alt2], [42.0026; -81.9978; 1.1397e3], 10e-6)
% [lat2, lon2, alt2] = aer2geodetic ( 0.575958653158129, 1.22173047639603, 1e3, 0.733038285837618, -1.43116998663535, 200, "", "rad");
% assert ([lat2, lon2, alt2], [42.0026; -81.9978; 1.1397e3], 10e-6)

%!error <numeric> aer2geodetic("s", 25, 1e3, 0, 0, 0)
%!error <numeric> aer2geodetic(3i, 25, 1e3, 0, 0, 0)
%!error <numeric> aer2geodetic(33, "s", 1e3, 0, 0, 0)
%!error <numeric> aer2geodetic(33, 3i, 1e3, 0, 0, 0)
%!error <numeric> aer2geodetic(33, 25, "s", 0, 0, 0)
%!error <numeric> aer2geodetic(33, 25, 3i, 0, 0, 0)
%!error <numeric> aer2geodetic(33, 25, 1e3, "s", 0, 0)
%!error <numeric> aer2geodetic(33, 25, 1e3, 3i, 0, 0)
%!error <numeric> aer2geodetic(33, 25, 1e3, 0, "s", 0)
%!error <numeric> aer2geodetic(33, 25, 1e3, 0, 3i, 0)
%!error <numeric> aer2geodetic(33, 25, 1e3, 0, 0, "s")
%!error <numeric> aer2geodetic(33, 25, 1e3, 0, 0, 3i)
