Calculate USNG Coordinates in Arcade

834
5
Jump to solution
04-15-2020 10:17 AM
JoshSaad
New Contributor III

I'm trying to write an attribute rule to automatically input the USNG coordinates for address points when they're created or modified.  Does anyone know if it's possible, or how to calculate USNG coordinates in Arcade?

1 Solution

Accepted Solutions
FEMAUrbanSearchandRescue
New Contributor II

Great news! Someone from the Esri Defense Team shared the Arcade needed to do this. I just tested in Smart Forms and it works perfectly. 

var x = Geometry($feature).x;
var y = Geometry($feature).y;
var originShift = 2.0 * PI * 6378137.0 / 2.0;
var lat = (y / originShift) * 180.0;
lat = 180.0 / PI * (2.0 * Atan( Exp( lat * PI / 180.0)) - PI / 2.0);
var lon = (x / originShift) * 180.0;
function pad (val) {if (val < 10) {val = '0000' + val} else if (val < 100) {val = '000' + val} else if (val < 1000) {val = '00' + val} else if (val < 10000) {val = '0' + val};return val};
function MGRSString (Lat, Long) {
if (Lat < -80) return 'Too far South' ; if (Lat > 84) return 'Too far North' ;
var c = 1 + Floor((Long+180)/6);
var e = c*6 - 183 ;
var k = Lat*PI/180;
var l = Long*PI/180;
var m = e*PI/180;
var n = Cos(k);
var o = 0.006739496819936062*Pow(n,2);
var p = 40680631590769/(6356752.314*Sqrt(1 + o));
var q = Tan(k);
var r = q*q;
var s = (r*r*r) - Pow (q,6);
var t = l - m;
var u = 1.0 - r + o;
var v = 5.0 - r + 9*o + 4.0*(o*o);
var w = 5.0 - 18.0*r + (r*r) + 14.0*o - 58.0*r*o;
var x = 61.0 - 58.0*r + (r*r) + 270.0*o - 330.0*r*o;
var y = 61.0 - 479.0*r + 179.0*(r*r) - (r*r*r);
var z = 1385.0 - 3111.0*r + 543.0*(r*r) - (r*r*r);
var aa = p*n*t + (p/6.0*Pow (n,3)*u*Pow (t,3)) + (p/120.0*Pow (n,5)*w*Pow (t,5)) + (p/5040.0*Pow (n,7)*y*Pow (t,7));
var ab = 6367449.14570093*(k - (0.00251882794504*Sin (2*k)) + (0.00000264354112*Sin (4*k)) - (0.00000000345262*Sin (6*k)) + (0.000000000004892*Sin (8*k))) + (q/2.0*p*Pow (n,2)*Pow (t,2)) + (q/24.0*p*Pow (n,4)*v*Pow (t,4)) + (q/720.0*p*Pow (n,6)*x*Pow (t,6)) + (q/40320.0*p*Pow (n,8)*z*Pow (t,8));
aa = aa*0.9996 + 500000.0;
ab = ab*0.9996; if (ab < 0.0) ab += 10000000.0;
var split1 = Split('CDEFGHJKLMNPQRSTUVWXX', '');
var ad = split1[Floor(Lat/8 + 10)];
var ae = Floor (aa/100000);
var split2 = Split('ABCDEFGH', '');
var split3 = Split('JKLMNPQR', '');
var split4 = Split('STUVWXYZ', '');
var combinedSplit = [split2, split3, split4];
var af = combinedSplit[(c-1)%3][ae-1];
var ag = Floor (ab/100000)%20;
var split5 = Split('ABCDEFGHJKLMNPQRSTUV', '');
var split6 = Split('FGHJKLMNPQRSTUVABCDE', '');
var combinedSplit2 = [split5, split6];
var ah = combinedSplit2[(c-1)%2][ag];
return [Floor(aa%100000), Floor(ab%100000), c, ad, af, ah]
};
var MGRS = MGRSString(lat,lon);
var aa = pad(MGRS[0]);
var ab = pad(MGRS[1]);
var formatted = MGRS[2] + MGRS[3] + MGRS[4] + MGRS[5] + aa + ab;
return formatted;

FEMAUrbanSearchandRescue_1-1701798982356.png

 

FEMAUrbanSearchandRescue_0-1701798932724.png

 

View solution in original post

5 Replies
PaulDoherty2
Occasional Contributor III

I am also interested in doing this use ArcGIS Field Maps smartforms. @PaulBarker any ideas?

FEMAUrbanSearchandRescue
New Contributor II

@JeffShaner any updates on this? It looks like this topic was tagged as an ArcGIS Pro question but I'd like to have USNG/MGRS added to a field upon entry in Field Maps and Smart Forms, similar to the way it works in QuickCapture as a device variable OR via an Arcade calculation (whatever works). I figured out how to apply lat/long in decimal degrees...

FEMAUrbanSearchandRescue_0-1700505533136.png

...but USNG is a requirement as per FEMAD092-5_dated.pdf (usngi.org)

So I really need to figure this out ASAP as we roll out Field Maps for additional field data collection / editing. 

0 Kudos
FEMAUrbanSearchandRescue
New Contributor II

Another example where USNG/MGRS "stamping" has worked in the past is in Web AppBuilder Smart Editor attribute actions Smart Editor widget—ArcGIS Web AppBuilder | Documentation. As we make the transition to Experience Builder, we are also looking for this functionality, but I am guessing it has to be implemented by the ArcGIS Online Team for Smart Forms first? @Jianxia 

FEMAUrbanSearchandRescue_1-1700506082651.png

@PaulDoherty2 

0 Kudos
FEMAUrbanSearchandRescue
New Contributor II

Great news! Someone from the Esri Defense Team shared the Arcade needed to do this. I just tested in Smart Forms and it works perfectly. 

var x = Geometry($feature).x;
var y = Geometry($feature).y;
var originShift = 2.0 * PI * 6378137.0 / 2.0;
var lat = (y / originShift) * 180.0;
lat = 180.0 / PI * (2.0 * Atan( Exp( lat * PI / 180.0)) - PI / 2.0);
var lon = (x / originShift) * 180.0;
function pad (val) {if (val < 10) {val = '0000' + val} else if (val < 100) {val = '000' + val} else if (val < 1000) {val = '00' + val} else if (val < 10000) {val = '0' + val};return val};
function MGRSString (Lat, Long) {
if (Lat < -80) return 'Too far South' ; if (Lat > 84) return 'Too far North' ;
var c = 1 + Floor((Long+180)/6);
var e = c*6 - 183 ;
var k = Lat*PI/180;
var l = Long*PI/180;
var m = e*PI/180;
var n = Cos(k);
var o = 0.006739496819936062*Pow(n,2);
var p = 40680631590769/(6356752.314*Sqrt(1 + o));
var q = Tan(k);
var r = q*q;
var s = (r*r*r) - Pow (q,6);
var t = l - m;
var u = 1.0 - r + o;
var v = 5.0 - r + 9*o + 4.0*(o*o);
var w = 5.0 - 18.0*r + (r*r) + 14.0*o - 58.0*r*o;
var x = 61.0 - 58.0*r + (r*r) + 270.0*o - 330.0*r*o;
var y = 61.0 - 479.0*r + 179.0*(r*r) - (r*r*r);
var z = 1385.0 - 3111.0*r + 543.0*(r*r) - (r*r*r);
var aa = p*n*t + (p/6.0*Pow (n,3)*u*Pow (t,3)) + (p/120.0*Pow (n,5)*w*Pow (t,5)) + (p/5040.0*Pow (n,7)*y*Pow (t,7));
var ab = 6367449.14570093*(k - (0.00251882794504*Sin (2*k)) + (0.00000264354112*Sin (4*k)) - (0.00000000345262*Sin (6*k)) + (0.000000000004892*Sin (8*k))) + (q/2.0*p*Pow (n,2)*Pow (t,2)) + (q/24.0*p*Pow (n,4)*v*Pow (t,4)) + (q/720.0*p*Pow (n,6)*x*Pow (t,6)) + (q/40320.0*p*Pow (n,8)*z*Pow (t,8));
aa = aa*0.9996 + 500000.0;
ab = ab*0.9996; if (ab < 0.0) ab += 10000000.0;
var split1 = Split('CDEFGHJKLMNPQRSTUVWXX', '');
var ad = split1[Floor(Lat/8 + 10)];
var ae = Floor (aa/100000);
var split2 = Split('ABCDEFGH', '');
var split3 = Split('JKLMNPQR', '');
var split4 = Split('STUVWXYZ', '');
var combinedSplit = [split2, split3, split4];
var af = combinedSplit[(c-1)%3][ae-1];
var ag = Floor (ab/100000)%20;
var split5 = Split('ABCDEFGHJKLMNPQRSTUV', '');
var split6 = Split('FGHJKLMNPQRSTUVABCDE', '');
var combinedSplit2 = [split5, split6];
var ah = combinedSplit2[(c-1)%2][ag];
return [Floor(aa%100000), Floor(ab%100000), c, ad, af, ah]
};
var MGRS = MGRSString(lat,lon);
var aa = pad(MGRS[0]);
var ab = pad(MGRS[1]);
var formatted = MGRS[2] + MGRS[3] + MGRS[4] + MGRS[5] + aa + ab;
return formatted;

FEMAUrbanSearchandRescue_1-1701798982356.png

 

FEMAUrbanSearchandRescue_0-1701798932724.png

 

D_LETE
by
New Contributor

This just solved both of problems in one shot - thanks!

0 Kudos