Hi S123 Community,
Goal
Output coordinates in New Zealand Trans Mercator (collected through geopoint in the S123 form) via the report template, which would then be sent out automatically to the signee using Integromat.
Context
Field workers will be taking the form offline. They will mark a point where water is, using the geopoint question. I have gotten the basemap offline. So far so good. The field workers are in New Zealand though and require the coordinates to appear in the report in numerical format in NZTM, not as a point in the map and not in WGS84. From what I can tell, there are only select coordinate systems that S123 uses.
Is there any way to output the coordinates in NZTM? I have figured out how to grab the coordinates in WGS84 into the report.
If there's not, does anyone have any work around or suggestions to get to the goal? I've thought about trying to convert from WGS84 to NZTM using calculations in S123, but I am still new to S123 and don't have much experience with projections. I normally would convert via online converters or using tools in Arc, so I don't know the actual manual way of doing it. I prefer not to do it either of these two ways though because we want to have the process automated from signing straight to sending a copy of the form to the signee's inbox.
This post also asks when S123's geopoint feature will use non-WGS84 coordinates.
Solved! Go to Solution.
Hi @elpinguino,
The only way to achieve this in the survey on the device is to use a custom JavaScript function. If you are able to write a JS function that takes the coordinates from the geopoint in WGS84 and then converts to NZTM, you can then store the output in a text field in the survey. This text field can then be displayed in the feature report.
Alternatively you could do the conversion on the feature layer, using a post submission python script or geoprocessing tool, to update additional fields in the feature layer with NZTM coorindates taken from the geometry of that layer.
Regards,
Phil.
Hi @elpinguino,
The only way to achieve this in the survey on the device is to use a custom JavaScript function. If you are able to write a JS function that takes the coordinates from the geopoint in WGS84 and then converts to NZTM, you can then store the output in a text field in the survey. This text field can then be displayed in the feature report.
Alternatively you could do the conversion on the feature layer, using a post submission python script or geoprocessing tool, to update additional fields in the feature layer with NZTM coorindates taken from the geometry of that layer.
Regards,
Phil.
Hi @Anonymous User ,
Thanks for your reply. I think the first option is going to be too hard. Figuring out a formula for how to convert WGS84 to NZTM is beyond me.
The second option you suggest, that's not possible to do in an automated workflow is it? The form would have to be signed, then I'd have to go into the feature layer, run the geoprocess, export the report and then send it off.
Hi @elpinguino,
It may be possible to automate this workflow using webhooks (via Survey123 webhooks or feature service level webhooks) to trigger the needed geoprocesses and and export the report and send it off. You would need to look at ways in your workflow you can automate the geoprocessing part, the rest of the workflow is easy with existing webhooks.
Regards,
Phil.
Hi @elpinguino , few years late to this but in case anyone else needs this i have done it in s123 using javascript. Note: this is for WGS84 to NZTM and is region specific, you can train the function to be more accurate based on your area of need. For example if you only need it for the auckland region you can adjust the constant (commented below). I generated 1000 coordinates in my required area (max that you can copy into LINZ converter) then compared LINZ output to my function output then ran the RMSE test to determine the constant (screenshot provided below of a different conversion i did but paints the picture).
Depending on my sample area this gave me accuracy to the LINZ converter to as little as 1mm.
function getTransformedLat(latitude, longitude) {
const a = 6378137; // Radius of the earth (GRS 1980)
const f = 1 / 298.257222101; // Flattening of the earth (GRS 1980)
const e = Math.sqrt(2 * f - f * f); // Eccentricity
const rad = Math.PI / 180; // Conversion factor from degrees to radians
// Central meridian, scale factor, and false origins
const lon0 = 174.764166666667; // Central meridian in degrees
const lat0 = -36.8797222222222; // Latitude of origin in degrees
const k0 = 0.9999; // Scale factor at the central meridian
const E0 = 400000; // False easting
const N0 = 800000; // False northing
// Convert input coordinates to radians
const latRad = latitude * rad;
const lonRad = longitude * rad;
const lat0Rad = lat0 * rad;
const lon0Rad = lon0 * rad;
// Meridional arc calculation
const n = f / (2 - f);
const A = a * (1 - n + (5/4) * (n*n - n*n*n) + (81/64) * (n*n*n*n - n*n*n*n*n));
const B = (3*a*n/2) * (1 - n + (7/8) * (n*n - n*n*n) + (55/64) * n*n*n*n);
const C = (15*a*n*n/16) * (1 - n + (3/4) * (n*n - n*n*n));
const D = (35*a*n*n*n/48) * (1 - n + (11/16) * n*n);
const E = (315*a*n*n*n*n/512) * (1 - n);
const M = A * (latRad - lat0Rad) -
B * (Math.sin(2*latRad) - Math.sin(2*lat0Rad)) +
C * (Math.sin(4*latRad) - Math.sin(4*lat0Rad)) -
D * (Math.sin(6*latRad) - Math.sin(6*lat0Rad)) +
E * (Math.sin(8*latRad) - Math.sin(8*lat0Rad));
// Calculate the adjustment from the central meridian
const nu = a / Math.sqrt(1 - e * e * Math.sin(latRad) * Math.sin(latRad));
const rho = a * (1 - e * e) / Math.pow(1 - e * e * Math.sin(latRad) * Math.sin(latRad), 1.5);
const t = Math.tan(latRad);
const omega = lonRad - lon0Rad;
// Calculate easting and northing
const term1 = (1/6) * Math.pow(omega, 2) * Math.cos(latRad) * (nu / rho - t * t);
const term2 = (1/120) * Math.pow(omega, 4) * Math.cos(latRad) * (5 - 18 * t * t + t * t * t * t + 14 * (nu / rho) - 58 * t * t * (nu / rho));
const easting = (E0 + k0 * nu * omega * Math.cos(latRad) * (1 + term1 + term2)) - 0.133;
const term3 = (1/2) * Math.pow(omega, 2) * nu * Math.sin(latRad) * Math.cos(latRad);
const term4 = (1/24) * Math.pow(omega, 4) * nu * Math.sin(latRad) * Math.pow(Math.cos(latRad), 3) * (5 - t * t + 9 * (nu / rho) + 4 * Math.pow(nu / rho, 2));
const northing = (N0 + k0 * (M + term3 + term4)) - 1.006;
return northing.toFixed(3)
}
function getTransformedLon(latitude, longitude) {
// WGS84 ellipsoid parameters
const a = 6378137; // Semi-major axis
const f = 1 / 298.257223563; // Flattening (reciprocal)
const e = Math.sqrt(2 * f - f * f); // Eccentricity
const rad = Math.PI / 180; // Conversion factor from degrees to radians
const lon0 = 174.764166666667; // Central meridian in degrees
const lat0 = -36.8797222222222; // Latitude of origin in degrees
const k0 = 0.9999; // Scale factor at the central meridian
const E0 = 400000; // False easting
const N0 = 800000; // False northing
// Convert input coordinates to radians
const latRad = latitude * rad;
const lonRad = longitude * rad;
const lat0Rad = lat0 * rad;
const lon0Rad = lon0 * rad;
// Meridional arc calculation
const n = f / (2 - f);
const A = a * (1 - n + (5/4) * (n*n - n*n*n) + (81/64) * (n*n*n*n - n*n*n*n*n));
const B = (3*a*n/2) * (1 - n + (7/8) * (n*n - n*n*n) + (55/64) * n*n*n*n);
const C = (15*a*n*n/16) * (1 - n + (3/4) * (n*n - n*n*n));
const D = (35*a*n*n*n/48) * (1 - n + (11/16) * n*n);
const E = (315*a*n*n*n*n/512) * (1 - n);
const M = A * (latRad - lat0Rad) -
B * (Math.sin(2*latRad) - Math.sin(2*lat0Rad)) +
C * (Math.sin(4*latRad) - Math.sin(4*lat0Rad)) -
D * (Math.sin(6*latRad) - Math.sin(6*lat0Rad)) +
E * (Math.sin(8*latRad) - Math.sin(8*lat0Rad));
// Calculate the adjustment from the central meridian
const nu = a / Math.sqrt(1 - e * e * Math.sin(latRad) * Math.sin(latRad));
const rho = a * (1 - e * e) / Math.pow(1 - e * e * Math.sin(latRad) * Math.sin(latRad), 1.5);
const t = Math.tan(latRad);
const omega = lonRad - lon0Rad;
// Calculate easting and northing
const term1 = (1/6) * Math.pow(omega, 2) * Math.cos(latRad) * (nu / rho - t * t);
const term2 = (1/120) * Math.pow(omega, 4) * Math.cos(latRad) * (5 - 18 * t * t + t * t * t * t + 14 * (nu / rho) - 58 * t * t * (nu / rho));
const easting = E0 + k0 * nu * omega * Math.cos(latRad) * (1 + term1 + term2) - 0.133; //Constant of 0.133
const term3 = (1/2) * Math.pow(omega, 2) * nu * Math.sin(latRad) * Math.cos(latRad);
const term4 = (1/24) * Math.pow(omega, 4) * nu * Math.sin(latRad) * Math.pow(Math.cos(latRad), 3) * (5 - t * t + 9 * (nu / rho) + 4 * Math.pow(nu / rho, 2));
const northing = N0 + k0 * (M + term3 + term4) - 1.006; // Constant of 1.006
return easting.toFixed(3)
}