1.
Introduction
Did you ever have a displacement of points
of 100m on your map, then you clearly run into problems with datum corrections.
This document explains how I tackle this issue , and how ArcGis 10.1 helps you.
Public geo databases as ‘Openstreet map’ , ‘Google maps’ or ‘Google Streetview’ are all based on the
spatial reference WGS84 and this is in most cases not the spatial reference of
the map. When trying to integrate this
information with a custom ArcGis JavaScript, you will need to project your data towards WGS 84 spatial reference
coordinates.
To project your data into WGS 84 spatial
reference, ESRI expose a project transformation service through the method
project of the geometry service of an
ArcGis server. As from ArcGis 10.1 and
JavaScript API 3.0 the project method has added a transformation parameter. The
list of all transformations can be found at the URL http://help.arcgis.com/en/webapi/javascript/arcgis/help/jshelp/dattrans.htm
In pre version 3.0, if a transformation is
required, a SOAP web service must be
used, however using this in JavaScript requires some extra data
processing, a JSON approach is more
practical.
Sometimes you will need using more than one
transformation in the case no direct transformation of projection to another
projection is available as outlined in the figure below.
2.
Transformation between WGS84
and WebMercator (102100/3857)
Because I could not find a transformation
in the list on the URL specified in the ‘Introduction’ I wrote two functions that handle this transformations in
both directions based on some C++ code I found. Doing so, I did not need an
async REST call to the ArcGIs Geometry service, speeding up the transformation.
The code for doing these transformations
are :
function
toGeographic(xMercator, yMercator) {
if (Math.abs(xMercator) < 180
&& Math.abs(yMercator) < 90)return null;
if ((Math.abs(xMercator) > 20037508.3427892) || (Math.abs(yMercator) > 20037508.3427892))
return null;
var x = xMercator;
var y = yMercator;
var w1 = x = x / 6378137.0;
var w2 = x * 57.295779513082323;
var w3 = Math.floor((x + 180.0) / 360.0);
x = w2 - (w3 * 360.0);
y = (1.5707963267948966 - (2.0 * Math.atan(Math.exp((-1.0 * y) / 6378137.0)))) * 57.295779513082323;
return {
x: x,
y: y
}
}
function toWebMercator(xlon,
ylat) {
if ((Math.abs(mercatorX_lon) > 180 ||
Math.abs(mercatorY_lat) > 90))return null;
var num = xlon * 0.017453292519943295;
var x = 6378137.0 * num;
var a = ylat * 0.017453292519943295;
var y = 3189068.5 * Math.Log((1.0 + Math.Sin(a)) / (1.0 - Math.Sin(a)));
return {
x: x,
y: y
}
}
3.
Other Project transformation
Creation of a generic function for doing projection transformation
requires as input either a wkid or wkt of the transformation that corresponds
to an item of the transformation list found at the URL specified earlier. In a real world application a transformation
happens between an input spatial reference (wkid) and an output spatial
reference (wkid).
I could not find a relation between the
transformation list wkid’s and the wkid’s
of spatial references.The only solution for this lack of automatic solution based on the two wkid’s was to add a parameter at the layer configuration specifying the transformation needed for the WGS 84 spatial references conversion. This solves all my issues for the transformation of country spatial references to WGS 84 spatial reference, making integration with Google Streetview possible and other WGS 84 related geographical data.
I also had a spatial reference problem in case WMS layers are used for doing spatial queries. A WMS query requires the same spatial reference as the WMS service expose. A solution is to add a parameter to the WMS configuration specifying the transformation needed for modifying the base layer spatial reference to the WMS spatial reference for the geometry involved.
The result of the project conversion consist of two cases, one that looks if it involves a Webmercator / WGS 84 transformation, and a second that will use the geometry service of the ArcGis server. The method requires version 3.0 of the ArcGis JavaScript API and ArcGis Server 10.1.
convertProjection: function (points, toSpacialReference, transformation,
callback) {
var wkidIn =
points[0].spatialReference.wkid;var wkidOut = toSpacialReference.wkid;
var result = null;
var resultPoints = new Array();
var point;
if ((wkidIn == '102100' || wkidIn == '3857') && wkidOut == '4326') {
for (var i = 0; i < points.length; i++) {
result = toGeographic(points[0].x, points[0].y);
point = new esri.geometry.Point([result.x, result.y], new esri.SpatialReference({ wkid: 4326 }));
resultPoints.push(point);
}
callback(resultPoints);
}
else if (wkidIn == '4326' && (wkidOut == '102100' || wkidIn == '3857')) {
for (var i = 0; i < points.length; i++) {
result = toWebMercator(points[0].x, points[0].y);
point = new esri.geometry.Point([result.x, result.y], new esri.SpatialReference({ wkid: 102100 }));
resultPoints.push(point);
}
callback(resultPoints);
}
else {
var params = new esri.tasks.ProjectParameters();
params.geometries = points;
params.outSR = toSpacialReference;
params.transformation = transformation;
params.transformationForward = false;
GisOperation.getGeometryService().project(params,
function (projectedPoints) {
callback(projectedPoints);
}, function errorprojected(err) {
logging.logMessage("E", "projection convertion failed -->" + err.message, "GisGeoProcessing");
callBack(null);
});
}
}
4.
Transformation in an
application
The above transformation worked well for me
having as spatial reference of Lambert 72 (31370) of the map, and using Google
Streetview to show the location selected. The transformation used was 1610.
I was having a really hard time trying to make my map have a specific spatial reference just for the sake of not having to use a service to project points. This helped and is a lot simpler for what I was trying to do.
ReplyDeleteThanks!
Hi, Great.. Tutorial is just awesome..It is really helpful for a newbie like me..
ReplyDeleteI am a regular follower of your blog. Really very informative post you shared here.
Kindly keep blogging. If anyone wants to become a Front end developer learn from Javascript Training in Chennai .
or Javascript Training in Chennai.
Nowadays JavaScript has tons of job opportunities on various vertical industry. ES6 Training in Chennai