[GIS] ArcGIS Javascript API – Return ‘normal’ map extents when panning around the world

arcgis-javascript-apijavascript

ArcGIS Javascript API maps allow the user to pan around the world, which is a great feature, however I am performing some processes that rely on map extents. I have discovered that despite the defined projection (wkid), extents are returned in meter coordinates with an origin of lat/lon 0,0 (off the coast of Africa). In order to get my extents in the projection I need, I use a Geometry service to project them, however when the user pans around the world, the coordinates do not reset, they just keep adding up, resulting in 'NaN' extents returned.

I saw this post, which would be one way to deal with this issue, however I would really like to keep the ability to pan around the world. Does anyone have any ideas on how to accomplish this?

Best Answer

"I have discovered that despite the defined projection (wkid), extents are returned in meter coordinates with an origin of lat/lon 0,0 (off the coast of Africa)."

With ArcGIS Javascript API, the first map service added sets coordinate system for the whole map. If you added one of ESRI's tiled map services for a basemap, it's probably one that was created using wkid 102100, which fits what you described. When you lay your map service on top of it, your services is reprojected to fit on top of this service. To fix this, you either need to create your own tiled map service basemap projected in the wkid you want, or use the geometry service to reproject points, as you have done.

"I use a Geometry service to project them, however when the user pans around the world, the coordinates do not reset, they just keep adding up, resulting in 'NaN' extents returned."

Here's a function you could use to fix the extent to something you can use for your geometry service:

function fixExtent(extent) {
    // hard-coded full extent of the world, using wkid 102100. 
    var full = new esri.geometry.Extent(-20037508.3427892430765884088807,-19971868.8804086,20037508.3427892430765884088807,19971868.8804086, new esri.SpatialReference({ wkid:102100 }));
    // calculate the extent size so that it fits within the normal extent
    var xwidth = full.xmax - full.xmin;

    var newXMin = extent.xmin;
    while (newXMin < full.xmin) {
        newXMin += xwidth;
    }
    while (newXMin > full.xmax) {
        newXMin -= xwidth;
    }

    var newXMax = extent.xmin;
    while (newXMax < full.xmin) {
        newXMax += xwidth;
    }
    while (newXMax > full.xmax) {
        newXMax -= xwidth;
    }

    // return a new geometry that is within the range of the full extent
    return new esri.geometry.Extent(newXMin, extent.ymin, newXMax, extent.ymax, extent.spatialReference);
}

I don't know how this will work if you compare an extent that crosses the dateline. Hope this helps.

Related Question