88from math import (sin , cos , atan2 , radians , degrees ,
99 sqrt , cosh , sinh , tan , atan , log )
1010import datetime
11- from geodepy .constants import utm , grs80
11+ import warnings
12+ from geodepy .constants import utm , isg , grs80 , ans
1213from geodepy .angles import (DECAngle , HPAngle , GONAngle , DMSAngle , DDMAngle ,
1314 dec2hp , dec2hpa , dec2gon , dec2gona ,
1415 dec2dms , dec2ddm ,
1920 dd2sec , angular_typecheck )
2021
2122
22- # Universal Transverse Mercator Projection Parameters
23- # TODO: Add this part into functions: geo2grid, grid2geo, psfandgridconv
24- proj = utm
25-
26-
2723def polar2rect (r , theta ):
2824 """
2925 Converts point in polar coordinates to corresponding rectangular coordinates
@@ -240,7 +236,7 @@ def beta_coeff(ellipsoid):
240236 return b2 , b4 , b6 , b8 , b10 , b12 , b14 , b16
241237
242238
243- def psfandgridconv (xi1 , eta1 , lat , lon , cm , conf_lat , ellipsoid = grs80 ):
239+ def psfandgridconv (xi1 , eta1 , lat , lon , cm , conf_lat , ellipsoid = grs80 , prj = utm ):
244240 """
245241 Calculates Point Scale Factor and Grid Convergence. Used in convert.geo2grid
246242 and convert.grid2geo
@@ -270,7 +266,7 @@ def psfandgridconv(xi1, eta1, lat, lon, cm, conf_lat, ellipsoid=grs80):
270266 p += 2 * r * a [r - 1 ] * cos (2 * r * xi1 ) * cosh (2 * r * eta1 )
271267 q += 2 * r * a [r - 1 ] * sin (2 * r * xi1 ) * sinh (2 * r * eta1 )
272268 q = - q
273- psf = (float (proj .cmscale )
269+ psf = (float (prj .cmscale )
274270 * (A / ellipsoid .semimaj )
275271 * sqrt (q ** 2 + p ** 2 )
276272 * ((sqrt (1 + (tan (lat )** 2 ))
@@ -289,7 +285,7 @@ def psfandgridconv(xi1, eta1, lat, lon, cm, conf_lat, ellipsoid=grs80):
289285 return psf , grid_conv
290286
291287
292- def geo2grid (lat , lon , zone = 0 , ellipsoid = grs80 ):
288+ def geo2grid (lat , lon , zone = 0 , ellipsoid = grs80 , prj = utm ):
293289 """
294290 Takes a geographic co-ordinate (latitude, longitude) and returns its
295291 corresponding Hemisphere, Zone and Projection Easting and Northing, Point
@@ -314,23 +310,40 @@ def geo2grid(lat, lon, zone=0, ellipsoid=grs80):
314310 lon = angular_typecheck (lon )
315311 # Input Validation - UTM Extents and Values
316312 zone = int (zone )
317- if zone < 0 or zone > 60 :
318- raise ValueError ('Invalid Zone - Zones from 1 to 60' )
313+ if prj == isg :
314+ if zone not in (0 , 541 , 542 , 543 , 551 , 552 , 553 , 561 , 562 , 563 , 572 ):
315+ raise ValueError ('Invalid Zone - Choose from 541, 542, 543, 551, 552, 553, 561, 562, 563, 572' )
316+ else :
317+ if zone < 0 or zone > 60 :
318+ raise ValueError ('Invalid Zone - Zones from 1 to 60' )
319319
320320 if lat < - 80 or lat > 84 :
321321 raise ValueError ('Invalid Latitude - Latitudes from -80 to +84' )
322322
323323 if lon < - 180 or lon > 180 :
324324 raise ValueError ('Invalid Longitude - Longitudes from -180 to +180' )
325325
326+ if prj == isg and ellipsoid != ans :
327+ warnings .warn (message = 'ISG projection should be used with ANS ellipsoid' , category = UserWarning )
328+
326329 A = rect_radius (ellipsoid )
327330 a = alpha_coeff (ellipsoid )
328331 lat = radians (lat )
329332 # Calculate Zone
330333 if zone == 0 :
331- zone = int ((float (lon ) - (
332- proj .initialcm - (1.5 * proj .zonewidth ))) / proj .zonewidth )
333- cm = float (zone * proj .zonewidth ) + (proj .initialcm - proj .zonewidth )
334+ if prj == isg :
335+ amgzone = (float (lon ) - (prj .initialcm - (4.5 * prj .zonewidth ))) / (prj .zonewidth * 3 )
336+ subzone = int ((amgzone - int (amgzone )) * 3 + 1 )
337+ amgzone = int (amgzone )
338+ zone = int (f'{ amgzone } { subzone } ' )
339+ else :
340+ zone = int ((float (lon ) - (prj .initialcm - (1.5 * prj .zonewidth ))) / prj .zonewidth )
341+ if prj == isg :
342+ amgzone = int (str (zone )[:2 ])
343+ subzone = int (str (zone )[2 ])
344+ cm = float ((amgzone - 1 ) * prj .zonewidth * 3 + prj .initialcm + (subzone - 2 ) * prj .zonewidth )
345+ else :
346+ cm = float (zone * prj .zonewidth + prj .initialcm - prj .zonewidth )
334347
335348 # Conformal Latitude
336349 sigx = (ellipsoid .ecc1 * tan (lat )) / sqrt (1 + (tan (lat ) ** 2 ))
@@ -357,14 +370,14 @@ def geo2grid(lat, lon, zone=0, ellipsoid=grs80):
357370 y = A * xi
358371
359372 # Hemisphere-dependent UTM Projection Co-ordinates
360- east = proj .cmscale * x + proj .falseeast
373+ east = prj .cmscale * x + prj .falseeast
361374 if y < 0 :
362375 hemisphere = 'South'
363- north = proj .cmscale * y + proj .falsenorth
376+ north = prj .cmscale * y + prj .falsenorth
364377 else :
365378 hemisphere = 'North'
366379 falsenorth = 0
367- north = proj .cmscale * y + falsenorth
380+ north = prj .cmscale * y + falsenorth
368381
369382 # Point Scale Factor and Grid Convergence
370383 psf , grid_conv = psfandgridconv (xi1 , eta1 , degrees (lat ), lon , cm , conf_lat )
@@ -375,7 +388,7 @@ def geo2grid(lat, lon, zone=0, ellipsoid=grs80):
375388 round (psf , 8 ), grid_conv )
376389
377390
378- def grid2geo (zone , east , north , hemisphere = 'south' , ellipsoid = grs80 ):
391+ def grid2geo (zone , east , north , hemisphere = 'south' , ellipsoid = grs80 , prj = utm ):
379392 """
380393 Takes a Transverse Mercator grid co-ordinate (Zone, Easting, Northing,
381394 Hemisphere) and returns its corresponding Geographic Latitude and Longitude,
@@ -393,8 +406,12 @@ def grid2geo(zone, east, north, hemisphere='south', ellipsoid=grs80):
393406 """
394407 # Input Validation - UTM Extents and Values
395408 zone = int (zone )
396- if zone < 0 or zone > 60 :
397- raise ValueError ('Invalid Zone - Zones from 1 to 60' )
409+ if prj == isg :
410+ if zone not in (541 , 542 , 543 , 551 , 552 , 553 , 561 , 562 , 563 , 572 ):
411+ raise ValueError ('Invalid Zone - Choose from 541, 542, 543, 551, 552, 553, 561, 562, 563, 572' )
412+ else :
413+ if zone < 0 or zone > 60 :
414+ raise ValueError ('Invalid Zone - Zones from 1 to 60' )
398415
399416 if east < - 2830000 or east > 3830000 :
400417 raise ValueError ('Invalid Easting - Must be within'
@@ -407,15 +424,18 @@ def grid2geo(zone, east, north, hemisphere='south', ellipsoid=grs80):
407424 if h != 'north' and h != 'south' :
408425 raise ValueError ('Invalid Hemisphere - String, either North or South' )
409426
427+ if prj == isg and ellipsoid != ans :
428+ warnings .warn (message = 'ISG projection should be used with ANS ellipsoid' , category = UserWarning )
429+
410430 A = rect_radius (ellipsoid )
411431 b = beta_coeff (ellipsoid )
412432 # Transverse Mercator Co-ordinates
413- x = (east - float (proj .falseeast )) / float (proj .cmscale )
433+ x = (east - float (prj .falseeast )) / float (prj .cmscale )
414434 if hemisphere .lower () == 'north' :
415- y = - (north / float (proj .cmscale ))
435+ y = - (north / float (prj .cmscale ))
416436 hemisign = - 1
417437 else :
418- y = (north - float (proj .falsenorth )) / float (proj .cmscale )
438+ y = (north - float (prj .falsenorth )) / float (prj .cmscale )
419439 hemisign = 1
420440
421441 # Transverse Mercator Ratios
@@ -463,7 +483,12 @@ def f1tn(tn, ecc1, ecc1sq):
463483 lat = degrees (atan (t ))
464484
465485 # Compute Longitude
466- cm = float ((zone * proj .zonewidth ) + proj .initialcm - proj .zonewidth )
486+ if prj == isg :
487+ amgzone = int (str (zone )[:2 ])
488+ subzone = int (str (zone )[2 ])
489+ cm = float ((amgzone - 1 ) * prj .zonewidth * 3 + prj .initialcm + (subzone - 2 ) * prj .zonewidth )
490+ else :
491+ cm = float ((zone * prj .zonewidth ) + prj .initialcm - prj .zonewidth )
467492 long_diff = degrees (atan (sinh (eta1 ) / cos (xi1 )))
468493 long = cm + long_diff
469494
0 commit comments