UTM2LL converts Universal Transverse Mercator (UTM) East/North coordinates to latitude/longitude.
LL2UTM converts latitude/longitude coordinates to UTM.
Both functions are using precise formula (millimeter precision), possible userdefined datum (WGS84 is the default), and are all vectorized (no loop in the code). It means that huge matrix of points, like an entire DEM grid, can be converted very fast.
Example (needs readhgt.m author's function):
X = readhgt(36:38,12:15,'merge','crop',[36.5,38.5,12.2,16],'plot');
[lon,lat] = meshgrid(X.lon,X.lat);
[x,y,zone] = ll2utm(lat,lon); % do the job!
z = double(X.z); z(z==32768  z<0) = NaN;
figure
pcolor(x,y,z); shading flat; hold on
contour(x,y,z,[0,0],'w')
hold off; axis equal; axis tight
xlabel('East (m)'); ylabel('North (m)')
title(sprintf('Sicily  UTM zone %d WGS84',zone))
loads SRTM full resolution DEM of Sicily in lat/lon (a 2400x4500 grid), converts it to UTM and plots the result with pcolor and contour. To make a regular UTM grid, you may interpolate x and y with griddata function.
See "doc ll2utm" and "doc utm2ll" for syntax and help.
François Beauducel (2020). LL2UTM and UTM2LL (https://www.mathworks.com/matlabcentral/fileexchange/45699ll2utmandutm2ll), MATLAB Central File Exchange. Retrieved .
1.9.0.0   utm2ll: fix an issue when input arguments are matrices


1.8.0.1  repack 

1.8.0.0  ll2utm : adds a check for latitude values input argument 

1.7.0.0  packaging problem. 

1.6.0.0  Following the comment of Frederic Christen (thanks!), ZONE input argument can be scalar, vector or matrix in both ll2utm and utm2ll. Bug corrected for negative ZONE multiple outputs in southern hemisphere. 

1.5.0.0  LL2UTM: adds possibility to force the UTM zone (thanks to Mathieu's suggestion). 

1.4.0.0   adds single output argument (ll2utm and utm2ll)


1.3.0.0  minor update. 

1.2.0.0  adds an example of ll2utm use. 

1.1.0.0  minor update of description. 
Inspired by: utm2deg
Create scripts with code, output, and formatted text in a single executable document.
Amazing function, and precise as well! Perfect for what I need!
Hi,
Seems like there is still a bug while using inputs that are matrices for utm2ll.
Size function in line 158 uses the 1D vector form of the matrix inputs (X and Y), so I had to change that part.
Thank you François. Your code actually helps me on changing the latitude and longitude into UTM coordinate!
I spent such a long time with this problem, and thank to your code, I get the right result! Thank you
Hi,
I'm currently attempting to run a model in a location which is within a range of +/ 2 degrees latitude of the equator. Is there any way to get around having to separate the data into 15N and 15S utm zones?
Dear Alan,
This error occurs when you enter a latitude absolute value greater than 90 (probably you switched latitude and longitude in the input arguments ?). The fix you suggest avoids the error but the result is certainly wrong... The correct syntax is ll2utm(latitude,longitude).
François.
When I ran this function, it threw
"Error using complex
Real input A must be numeric, real, and full.
Error in ll2utm (line 160)
z = complex(atan(sinh(L)./cos(l1  L0)),log(tan(pi/4 + asin(sin(l1 
L0)./cosh(L))/2)));"
The problem is that the two quantities in complex are themselves complex (although the imaginary part is 0). Replacing this line with
z = complex(real(atan(sinh(L)./cos(l1  L0))),real(log(tan(pi/4 + asin(sin(l1  L0)./cosh(L))/2))));
fixes the problem
Thank you very much for your work. Much appreciated!
hox I can convert grid sinusoidal to latitude longitude using matlab
Again, for those who might find it interesting, although I am not in the field of GIS, I tweaked line 115 of utm2ll from:
L0 = (6*abs(f)  183)/D0;
to
L0 = (6*f  183)/D0;
and it worked perfectly. Here's an example:
utm2ll( 463385.25 ,3095579.99 , 28) % Yes, I am using utm28
ans =
27.9848503065749 15.3723407898456
Confirmed the result with:
http://www.engineeringtoolbox.com/utmlatitudelongituded_1370.html
Hi Francois
Used your scripts for plotting pedestrian path recorded in Latitude and Longitude. Used it for converting to local Cartesian coordinates. worked very good. Thanks a lot!
Thanks for this. It will be very useful. ll2utm works fine, however utm2ll works for scalars and vectors but fails for matrices in the version I am using: 9.0.0.341360 (R2016a)
[lat,lon]=utm2ll(xx,yy,12);
Operands to the  and && operators must be convertible to logical scalar values.
Error in utm2ll (line 135)
while any(isnan(p0)  abs(p  p0) > eps) && n < maxiter
Could you please add GDA94?
Hello and thank you for your work.
I tried to use ll2utm with Mars latitude, longitude. I've seen that there is the possibility to create "DATUM" as a 2element vector.
For Mars the vector is this one: [3396.9, 0.00589].
Using this vector I have this error: "Error using complex
Real input A must be numeric, real, and full.
Error in ll2utm (line 160)
z = complex(atan(sinh(L)./cos(l1  L0)),log(tan(pi/4 + asin(sin(l1  L0)./cosh(L))/2)));"
How can I use this code for Mars lat, lon?
Thank's.
Hello and thank you for your work,
In order for this to be true in the south Hemisphere:
[lat,lon]=utm2ll(e,n,z);
[e,n,z]=ll2utm(lat,lon,z);
I modified ll2utm so its zone input (z) is a positive value. (around line 147)
% UTM zone automatic setting
if isempty(zone)
F0 = round((l1*D0 + 183)/6);
else
F0 = abs(zone); %MB add abs
end
instead of
if isempty(zone)
F0 = round((l1*D0 + 183)/6);
else
F0 = zone; %MB add abs
end
Merci encore...
Marc
Hi, Frederic,
I tried to use ll2utm.m, and found that the output doesn't change even though I use different datum. See below:
[a,b,c]=ll2utm(31.810108412085388,1.039358695918168e+02)
a = 6.007219987931314e+05
b = 3.519881013316354e+06
c = 13
[a,b,c]=ll2utm(31.810108412085388,1.039358695918168e+02,'nad27')
a = 6.007241362545381e+05
b = 3.519694086015768e+06
c = 13
[a,b,c]=ll2utm(31.810108412085388,1.039358695918168e+02,'clk66')
a = 6.007241362545381e+05
b = 3.519694086015768e+06
c = 13
Any idea? Thanks,
Rongmao
Hi, thanks a lot for these codes. FYI, when I use utm2ll with easting and northing matrices, I get these errors  whether I input the zone as a scalar, a vector or a matrix:
________________________________________
Operands to the  and && operators must be convertible to logical scalar values.
Error in utm2ll (line 135)
while any(isnan(p0)  abs(p  p0) > eps) && n < maxiter
________________________________________
Operands to the  and && operators must be convertible to logical scalar values.
Error in utm2ll (line 80)
if ~isnumeric(f)  any(f ~= round(f))  (~isscalar(f) && any(size(f) ~= size(x)))
Best regards,
S
Regarding utm2ll.m:
Why has the ZONE to be a scalar when X and Y can be scalars, vectors or a matrix?
Hi. In the vectorized version of ll2utm.m, I don't get negative zones for coordinates in the southern hemisphere. Should the code in line #172 be:
f = F0.*sign(lat);
instead of
f = F0;
Best regards
Frederic
Sorry, my comment relates to ll2utm.m (not utm2ll.m).
Hi Francois, thanks a lot for these functions, very useful and very fast. I was wondering if there could be a way to force the UTM zone. I am using many datasets that are in UTM 22 N for example, and I would like to be able to do:
[x,y] = ll2utm(lat,lon,22);
Because otherwise my x and y are potentially different zones. Thanks !
Mathieu
This vectorized version of lat/lon vs UTM coordinates conversion may help users to deal with huge grids like digital elevation models, where others functions fail or take infinite time.