Thursday, January 22, 2009

Constraining Map Extent

Though sometimes an ArcGIS map service extends the full world, an application that uses this map service will want to restrict the extent to a way smaller extent. In this post, I will be talking about how to achieve this. Check out the application in action. Note that when you pan the map, it "springs" back to the initial extent. And even after you zoom in, the spring is still in effect. So how did I do this is as follows: I created a sub class of the Map class. In the constructor, I added a LOAD event listener. The LOAD event handler adds two EXTENT_CHANGE event listeners, where one of them is at a lower priority to guarantee that it will called last. This low priority listener sole purpose is to get and save the map extent as the initial extent. In addition, the initial scale is computed and saved too. Now, upon an extent change, we check if the initial extent intersects the new extent. if it does, then we compute the horizontal and vertical overlap distance and we adjust the extent in such a way that there is not overlap. we get the "spring" effect for free (cool, eh?) by invoking a callLater. The callLater handler sets a "bounded" extent, thus the spring effect. Now one last thing, we have to make sure we do not zoom out beyond the initial extent. we accomplish this by overriding the extent setter function, where we convert the given extent to a scale value and we compare that to the initial scale. If it is smaller, we proceed by calling the super function, otherwise we just return. Hope you find this post useful. And like usual you can download the source code from here.

14 comments:

Greg said...

I think this app is broken... I cant get out of Africa! :)

ThunderHead said...

No - lol - that is the point of the app - it constrains the extent of the map and the scale :-)

ArcGuru said...

Brilliant piece. Spent months looking for similar!! I am kind of stuck with its use though. I'm using 9.2 vS2008 SP6. and a newbie to programming as a whole.

In my Default.aspx.cs I have

protected void Page_PreRender(object sender, EventArgs ea)
{

if (!Page.IsPostBack)
{

ESRI.ArcGIS.ADF.Web.Geometry.Envelope initextent = new

// minx, miny, maxx, maxy
ESRI.ArcGIS.ADF.Web.Geometry.Envelope(-45.0, -45.0, 45.0, 45.0);

Map1.Extent = initextent;

}

}


Could you help or give me some pointers on how I can incorporate this master piece in my web App? I would very grateful for any help.

Cheers, Don

Don said...

Nice name this has given me... but really not an ArcGuru. Just a learner! :)

Don

Greg said...

I was just joshin' ya bro! Nice work indeed!

DCAKen said...

Nice application...however, where is com.esri.ags.utils.ProjUtils coming from?

ThunderHead said...

ProjUtils is a function with esri_internal modifier - should be in the current swc and should be implicitly imported. If not in the current release - we are about to release 1.2 next week.

Lakshmanan said...

Nice sample. I am getting error in line if( extent.containsExtent( m_initialExtent ))

"Call to a possibly undefined method containsExtent through a reference with static type com.esri.ags.geometry:Extent."
I use 1.1 version and extent method doesnot have contiansExtent method. Is this V1.2 upgrade?

Lakshmanan said...

Yes. Contains Extent method available in V1.2 . I have updated the my swc. My mxml contains Map, which has many AGSdynamic, and tiled service layer. I have placed my map control inside Sample. But it throws error


sample:SampleMap
ESRI:Map
ESRI:ArcGISTiledMapServiceLayer
ESRI:ArcGISDynamicMapServiceLayer
/ESRI:Map
/sample:SampleMap

Another error:

TypeError: Error #1034: Type Coercion failed: cannot convert com.esri.ags::Map@38ed0a1 to com.esri.ags.layers.Layer.

ThunderHead said...

At what line this occurs in SampleMap ?

Abdul Mannan said...
This post has been removed by the author.
Abdul Mannan said...

Hi,
This is really excellent Post, almost million dollar!

I successfully able to run it however while running in Sample Flex viewer, The first display screen goes blank and then when i click on full extent then it display the extent that I set inside sample.as. From then onwards, neither its zoom in nor any effect.
I dont know what am I doing wrong here!
One change I noticed that the street map you are using has initial extent -xmin -ymin, +Xmax +Ymax. But mine is -xmin +ymin, -Xmax +Ymax.
Please advice. your comment is highly appreciated. Thanks

Robert said...

All,

I have modified this to work in flexviewer and the code and changes that need to be made to MapManager can be found here. http://forums.esri.com/Thread.asp?c=158&f=2421&t=295234&mc=0

Thanks for the great code Mansour.

ThunderHead said...

U R Welcome