-
Notifications
You must be signed in to change notification settings - Fork 3
/
Copy pathcassini_fwd.m
80 lines (77 loc) · 2.87 KB
/
cassini_fwd.m
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
function [x, y, azi, rk] = cassini_fwd(lat0, lon0, lat, lon, ellipsoid)
%CASSINI_FWD Forward Cassini-Soldner projection
%
% [x, y] = CASSINI_FWD(lat0, lon0, lat, lon)
% [x, y, azi, rk] = CASSINI_FWD(lat0, lon0, lat, lon, ellipsoid)
%
% performs the forward Cassini-Soldner projection of points (lat,lon) to
% (x,y) using (lat0,lon0) as the center of projection. These input
% arguments can be scalars or arrays of equal size. The ellipsoid vector
% is of the form [a, e], where a is the equatorial radius in meters, e is
% the eccentricity. If ellipsoid is omitted, the WGS84 ellipsoid (more
% precisely, the value returned by defaultellipsoid) is used. projdoc
% defines the projection and gives the restrictions on the allowed ranges
% of the arguments. The inverse projection is given by cassini_inv.
%
% azi and rk give metric properties of the projection at (lat,lon); azi
% is the azimuth of the easting (x) direction and rk is the reciprocal of
% the northing (y) scale. The scale in the easting direction is 1.
%
% lat0, lon0, lat, lon, azi are in degrees. The projected coordinates x,
% y are in meters (more precisely the units used for the equatorial
% radius). rk is dimensionless.
%
% See also PROJDOC, CASSINI_INV, GEODDISTANCE, DEFAULTELLIPSOID,
% FLAT2ECC.
% Copyright (c) Charles Karney (2012-2022) <karney@alum.mit.edu>.
narginchk(4, 5)
if nargin < 5, ellipsoid = defaultellipsoid; end
try
Z = -zeros(size(lat0 + lon0 + lat + lon)); %#ok<SZARLOG>
catch
error('lat0, lon0, lat, lon have incompatible sizes')
end
if length(ellipsoid(:)) ~= 2
error('ellipsoid must be a vector of size 2')
end
degree = pi/180;
f = ecc2flat(ellipsoid(2));
dlon = AngDiff(lon0, lon) + Z;
[s12, azi1, azi2, ~, ~, ~, ~, sig12] = ...
geoddistance(lat, -abs(dlon), lat, abs(dlon), ellipsoid);
sig12 = 0.5 * sig12;
s12 = 0.5 * s12;
c = s12 == 0;
da = AngDiff(azi1, azi2)/2;
s = abs(dlon) <= 90;
azi1(c & s) = 90 - da(c & s);
azi2(c & s) = 90 + da(c & s);
s = ~s;
azi1(c & s) = -90 - da(c & s);
azi2(c & s) = -90 + da(c & s);
c = signbitx(dlon);
azi2(c) = azi1(c);
s12(c) = -s12(c);
sig12(c) = -sig12(c);
x = s12;
azi = AngNormalize(azi2);
[~, ~, ~, ~, ~, ~, rk] = ...
geodreckon(lat, dlon, -sig12, azi, ellipsoid, 1);
[sbet, cbet] = sincosdx(lat);
[sbet, cbet] = norm2((1-f) * sbet, cbet);
[sbet0, cbet0] = sincosdx(lat0);
[sbet0, cbet0] = norm2((1-f) * sbet0, cbet0);
[salp, calp] = sincosdx(azi);
salp0 = salp .* cbet;
calp0 = hypot(calp, salp .* sbet);
sbet1 = calp0;
c = signbitx(lat + Z);
sbet1(c) = -sbet1(c);
cbet1 = abs(salp0);
c = abs(dlon) <= 90;
cbet1(~c) = -cbet1(~c);
sbet01 = sbet1 .* cbet0 - cbet1 .* sbet0;
cbet01 = cbet1 .* cbet0 + sbet1 .* sbet0;
sig01 = atan2(sbet01, cbet01) / degree;
[~, ~, ~, ~, ~, ~, ~, y] = geodreckon(lat0, 0, sig01, 0, ellipsoid, 1);
end