Select to view content in your preferred language

Map Extent and Zoom Precision

2985
2
12-06-2013 02:56 PM
DinoMartin
New Contributor
Hi, I've been having some problems for some time with zooming in to the right extent. It seems like that there's an issue with the way extent is set into the map. There are instances where the extent are set properly i.e. the upper right corner (xmax, ymax) and the lower left corner (xmin, ymin) are close to what I expect if not exact. There are instances also that the extents are way off to the values I expect the map's extent should be.

I have created a fiddle to demonstrate this. Playing around with Extent's expand method, expanding by a factor of two (2) effectively zooms out the map twice but expanding by a factor of anything beyond two (2) but before three (3) still zooms out the map twice. Oddly, expanding by a factor of three (3) zooms out the map four times. What could be done to correct this so that the extents are properly set into the map? Thanks.
0 Kudos
2 Replies
JasonZou
Frequent Contributor
For a map with a cached map service as the basemap, its extent is determined by the size of the map container, the map center and the zoom level the map is set to. So when you try to set the map's extent like map.setExtent(aExtent), the map will not be zoomed in/out to an extent that exactly equals aExtent. What setExtent actually does, as I understand, is to get the center of aExtent, and calculate which zoom level aExtent is within, then kind of apply map.centerAndZoom. So what you can expect is that the map will center at the aExtent center, and cover aExtent.

If the above description makes sense to you, then you may understand why the zoomfactor does not do its work all the time. Zoomfactor is not the zoom level for the map, but to change the given extent to be larger or smaller. Its result will still be an extent.
0 Kudos
BenFousek
Deactivated User
The map on the client is a rectangle with dimensions in pixels. Most of the time as developers, and certainly for users, we think in terms of the coordinate system and its units, however in regard to displaying layers, graphics, info window, etc in the map, the api thinks in terms of pixels. So what we end with is a grid in pixels (integers) say 600 x 400 representing thousands, if not millions of map units, which are not integers. The values the api uses (10-11) in web mercator and as shown in your fiddle are less than a nanometer.

When the api creates a map, the spatial reference of the map is set by the first layer added to the map, unless otherwise specified. And if it's a tiled layer the map sets its levels of detail (LODS) based on the layer's LODS, unless otherwise specified. So when using the basemap option when creating the map, the map is set to web mercator and the standard web map LODS. When the map's LODS are set, the map will only use those specific LODS.

Here's 2 standard web mercator LODS:
{ level: 14, resolution: 9.55462853563415, scale: 36111.909643 },
{ level: 15, resolution: 4.77731426794937, scale: 18055.954822 }


With the map's LODS set, any action which changes the extent will use the LODS to the nearest available scale:
map.setScale(18000);
console.log(map.getScale()); //returns 18055.954822

map.setScale(27082);
console.log(map.getScale()); //returns 18055.954822

map.setScale(27084);
console.log(map.getScale()); //returns 36111.909643


For level 14 we have a scale, for which an inch measured on the screen, theoretically represents 36111.909643 inches on the ground, just like a paper map. The resolution represents the number of meters per pixel. Here we have 14 decimal places, which is important when representing the projected data in our pixel grid. If we have 2 point graphics of a feature layer, and the map scale is 36111.909643, unless the points are more that 9.55462853563415 meters apart in both x and y coordinates, they will have the same x,y screen point.

As you know using extent.expand() expands the extent by the factor provided.

The map.setExtent method takes an extent as it's first argument and a boolean as an optional second argument telling the api whether or not to fit the extent in the map. The fit option really only comes into play when the map's LODS are set. If the LODS are not set, the resulting map extent will fit the extent in x or y, whichever is larger in the extent in map units. When expanding the map's extent in this case, no matter what the expand factor is or the map's dimensions in pixels, the resulting map extent and the extent should be the same. Although I suspect you may find some small differences beyond 4 or 5 decimal places none the less.  When the LODS are set, as shown above, the map is confined to the nearest scale. This is where the fit option comes into play. If set to true, and the nearest scale doesn't fit the extent in either the x or y, the map goes to the next LOD.

In a web mercator map with standards LODS: if your map was square (400x400 pixels) and you expand by integers you should end up with a map extent which pretty closely matches the extent you set.
0 Kudos