Layers in Extent

1385
11
11-16-2011 02:00 PM
HeathClark
New Contributor III
Is there a way to get the layerIds of a Dynamic service that are only within a particular map.extent?
0 Kudos
11 Replies
derekswingley1
Frequent Contributor
I don't think there's a straightforward way to do this. What are you trying to do?
0 Kudos
HeathClark
New Contributor III
I have a service with almost 800 layers (group layers and data layers) and my identify queries are slow.  I was looking for a way to get a list of layers to put into the identify parameters layerIds setting to speed things up.

setting identify parameter mapExtent doesn't help either.

FYI - I know thats a large number of layers for one service, however, short answer - it's not going to change.
0 Kudos
JohnGrayson
Esri Regular Contributor
For this task, the only useful pieces of information about each layer are:


  1. Is the subLayer visible

  2. Is subLayer within scale range


var identifyLayerIds = dojo.filter(map.layerInfos, function(layerInfo){
  var mapScale = esri.geometry.getScale(map);
  var layer = map.getLayer(layerInfo.id);
  return (layer.visible && isWithinScaleRange(layerInfo,mapScale);
}).map(function(visibleLayerInfo){
  return visibleLayerInfo.id;
});

function isWithinScaleRange(layerInfo, mapScale){
  var isWithinScaleRange = true;
  if ((layerInfo.minScale === 0) && (layerInfo.maxScale !== 0)) {
      isWithinScaleRange = (mapScale > layerInfo.maxScale);
    } else {
      if ((layerInfo.maxScale === 0) && (layerInfo.minScale !== 0)) {
        isWithinScaleRange = (mapScale < layerInfo.minScale);
      } else {
        if ((layerInfo.maxScale !== 0) && (layerInfo.minScale !== 0)) {
          isWithinScaleRange = (mapScale < layerInfo.minScale) && (mapScale > layerInfo.maxScale);
        }
      }
    }
    return isWithinScaleRange;
}
0 Kudos
HeathClark
New Contributor III
Am I missing something?  If I set the IdentifyParameters.mapExtent wouldn't that limit the bounds of the identify task?  Do I also need to explicitly set height/width/dpi properties to limit the task to visible layers in the current extent?

identifyparameters.mapExtent descirption reads
The values for mapExtent, height, width, and dpi are used to determine the layers visible in the current extent. They are also used to calculate the search distance on the map based on the tolerance in screen pixels.


Does that mean layers within the service (specified in the identify.task.url) or layers (Dynamic, Tiled, or otherwise) on the map?
0 Kudos
derekswingley1
Frequent Contributor
Are you seeing any differences when you test?

It sounds like you already know that ~800 layers in a single map service is a bad idea. One of the main reasons it's bad is because it can kill performance. How long does your identify task take to run? Is this a public service?
0 Kudos
HeathClark
New Contributor III
Query time: 34 seconds the first time you run an Identify in a new session.  10-12 seconds thereafter, regardless of x,y clicked on the map.

Regardless of the pros/cons of the 800 layer service, I would still like some more details on what the identify.parameters.mapExtent setting is really doing.  By the description given it would sound like that process would limit or populate the layerIds to on those visible in the extent.
0 Kudos
derekswingley1
Frequent Contributor
To be honest, I'm not sure and I don't have a good answer for you.

Since the classes in the JS API are wrappers for the REST API, you might have better luck in that forum:  http://forums.arcgis.com/forums/11-ArcGIS-Server-REST-API

If you want to experiment/test more, you could work directly with the REST endpoint for your identify service and experiment with the various parameters to see if you speed up the response time. Here's an example on one of the sample servers:  http://sampleserver3.arcgisonline.com/ArcGIS/rest/services/BloomfieldHillsMichigan/Parcels/MapServer...
0 Kudos
HeathClark
New Contributor III
Code adjusted to work for me, just not the ESRI way.  I dropped the query time from average of 10seconds to less than 2 seconds.  I wrote code to dynamically populate the layerIds based on information stored in a database (populated thru the SOAP interface for a custom TOC tool).

What I learned, and will presume is correct unless others have input:
1- setting identify.parameters.mapExtent=map.extent DOES NOT limit the identify task to those sublayers within the current extent.
0 Kudos
derekswingley1
Frequent Contributor
What I learned, and will presume is correct unless others have input:
1- setting identify.parameters.mapExtent=map.extent DOES NOT limit the identify task to those sublayers within the current extent.


After discussing with a few other people, the purpose of providing an extent, height, width and dpi is so that the map service can determine the current map scale. Once the scale is known, the map service can exclude layers based on their scale dependency settings. The map service is not doing a spatial intersection based on the extent that's provided to exclude layers from the identify operation.

Glad you were able to come up with a solution to get your identify time down to something relatively reasonable. For future reference, when you have hundreds of layers you need to serve, the Esri recommendation is to use multiple map services with the number of layers in a map service to something smaller, say...less than 100. Preferably less than 50.
0 Kudos