Friday, January 23, 2009
Thursday, January 22, 2009
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
Mapclass. In the constructor, I added a
LOADevent listener. The
LOADevent handler adds two
EXTENT_CHANGEevent 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
callLaterhandler 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.
Wednesday, January 21, 2009
In this post I'm demonstrating how to use Cocomo's data messaging to enable collaborative mapping. One or more map application can share their active extent and whiteboard using the mouse. Though the application is not very sophisticated, it demonstrates the extensibility of the flex api and the power of Cocomo. BTW, I highly recommend that you read Ryan's blog post on how to get started with Cocomo. Using the CocomoDevConsole, I created a
CollectionNodeand named it 'cocomoMap', and I added two non-persistant
Nodes. The application uses the node 'cocomoMapExtent' to publish and receive active map extents, and the node 'cocomoMapPoints' is used to publish and receive drawn polylines. One of the cool things that I like in Cocomo, is that you can register a class with the
MessageItemregistry to enable the publishing and receiving of message bodies in 'native' format. So, I registered the class
Extentin such a way that I can directly publish extents and polylines without having to come up with my own serializing/de-serialization scheme. Like usual, you can download the source code from here, and make sure to compile the application with the following switches '-keep-as3-metadata+=Inject -keep-as3-metadata+=Listen'. The later is a post for another day.
Saturday, January 17, 2009
I will be speaking at 360|Flex this year in Indianapolis. But this time, it was decided to let the community vote on subjects/speakers. So...I'm asking for your vote. The Title of the session is Yet Another Flex Mapping API - NOT! where we will demonstrate the Flex Mapping API For ArcGIS Server, where we will deconstruct live real-world mapping applications and algorithms such as dense clustering, auto labeling of features, collaborative editing, real-time asset tracking and client/server collaborative Geo-Processing. In addition, we will demonstrate how to create your own layer, geometry and symbol extensions for superior rendering performance taking advantage of the FP10 drawing API. Vote here and vote often.
Sunday, January 4, 2009
In this post, I will be demonstrating how to label map points using the flex API for AGS. This work is strongly based on Kevin Mote’s “Fast Point-Feature Label Placement For Dynamic Visualization”. In this application, I’m loading city data from a shapefile. The city attributes contain the city name and rank. Rank is a number between 1 and 7 where 1 indicates a very populated city and 7 indicates a much lesser populated city. Upon a map load event, the shapefile is read and the cities with a rank less or equal to 3 are selected then sorted in descending rank order. Each shapefile record is converted into a LabelGraphic and added to a list. A LabelGraphic is a subclass of Graphic and has a TextField as a child. A ExtentChange event listener is added to the map, in such a way that whenever the map extent changes, a LabelManager is created to manage the LabelGraphics in the visible extent. A LabelManager has a spatial index (a trellis per Mote’s) to quickly locate label candidates (more on this later) and has a list of Features in ascending priority. LabelGraphics should be added in incremental order of priority to the label manager. Each added LabelGraphic is wrapped with a Feature from which, four label candidates are derived. The label of a feature can reside in one of the four corners (candidate) around the feature; upper-right, lower-right, upper-left, lower-left. The later order is an “aesthetic” priority per Hartmann et al as discussed in Mote’s paper. Once all the LabelGraphics are added, the solve function is invoked. There, the “cost” of each feature is calculated in such a way that higher priority features are greatly weighted compare to lower priority features (Mote’s cost formula is applied here) In addition, in that step any feature candidate that is not fully visible on the map is removed. The features are in a stack and are popped one at the time, and for each feature candidate, we find all the overlapping candidates from the other features (the spatial index or the trellis comes very handy here :-) and we calculate the cost of that candidate based on the sum of the overlapping candidate. The candidate with the least cost sum is selected to label that feature and the TextField associated with the parent’s feature LabelGraphic is repositioned to “properly” label the feature upon the update of the display list. The other candidates in that feature are removed and the candidates from the other features that overlap the selected candidate are removed as feature label candidates. Now, something very important; the cost of the removed candidate is added to the feature in such a way that it makes is more costly to remove a candidate of a feature with fewer and fewer candidates. Due to this process of candidate elimination, lower priority features could not be labeled, but that is ok; that is why they are at a lower priority :-) There are differences between Mote’s “Trellis Strategy” and this implementation; In the Mote’s approach each feature is optimized for a uniformly sized labels where in this implementation each feature can be labeled with its own text format. In addition, the trellis is reconstructed on each extent change based on visible features, eliminating the cost adjustment based on distance. And finally, the trellis cell size is fixed and proportional to the map pixel width and height. You can see the application in action here, and like usual you can download the source code from here.