Tuesday, August 26, 2008

Heat Map + Papervision3D

Doug McCune (one of my all time Flex heroes) contributed heavily to SpatialKey, which looks and works great. Got to see it last week at 360|Flex in San Jose. I've been wanting to do something similar, but in 3D! Dabbled a bit with Papervision3D, but wanted to get into it, and that was the perfect opportunity. The idea that I had was to read a country shapefile, and thematically map all the cities in that country based on some attribute. And do all that on the client using Flex. I did a little bit of research, and here is a list of sites that "inspired" me:
And here is a snapshot of the result:


You can download the source code of the application from here. And you can see a sample demo here.

Sunday, August 10, 2008

Quantile Thematic Mapping

In a previous post, I showed how to bind the output of a query task to a graphic layer. The graphic layer had a default symbol that was used to render the graphic features. In the following example, I would like to symbolize each feature based on an attribute value. We could use the symbolFunction property of a graphic layer, however this function is called on each graphic feature and does not have a "grand picture" of the full set. This is the case of a quantile distribution, where the features are rank-ordered and equal number of features are placed in colored bucket. Here is the result:Each country is color coded based on a quantile distribution of its area property over a specified number of classes. Here is the code:

<?xml version="1.0" encoding="utf-8"?>
<mx:Application
xmlns:mx="http://www.adobe.com/2006/mxml"
xmlns:esri="http://www.esri.com/2008/ags"
xmlns:sample="com.esri.ags.sample.*"
layout="absolute"
>
<sample:QuantileAreaCalculator
numClasses="{numClasses.value as Number}"
graphicProvider="{queryTask.executeLastResult.features}"/>
<esri:QueryTask id="queryTask" url="http://tejas:8399/arcgis/rest/services/maps/world/MapServer/1">
<esri:Query id="query" returnGeometry="true" where="{where.text}">
<esri:outFields>
<mx:String>*</mx:String>
</esri:outFields>
</esri:Query>
</esri:QueryTask>
<mx:Panel width="100%" height="100%" title="Quantile Thematic Mapping">
<mx:HBox width="100%" height="100%" horizontalGap="0">
<esri:Map id="map">
<esri:ArcGISDynamicMapServiceLayer
url="http://tejas:8399/arcgis/rest/services/maps/world/MapServer"/>
<esri:GraphicsLayer id="graphicsLayer"
graphicProvider="{queryTask.executeLastResult.features}">
</esri:GraphicsLayer>
</esri:Map>
<mx:DataGrid dataProvider="{queryTask.executeLastResult.attributes}" width="100%" height="100%">
<mx:columns>
<mx:DataGridColumn headerText="Name" dataField="NAME"/>
<mx:DataGridColumn headerText="Area" dataField="AREA"/>
</mx:columns>
</mx:DataGrid>
</mx:HBox>
<mx:ControlBar>
<mx:TextInput id="where" text="FID < 10"/>
<mx:Button label="Query" click="queryTask.execute()"/>
<mx:ComboBox id="numClasses">
<mx:ArrayCollection>
<mx:Number>2</mx:Number>
<mx:Number>3</mx:Number>
<mx:Number>4</mx:Number>
<mx:Number>5</mx:Number>
</mx:ArrayCollection>
</mx:ComboBox>
</mx:ControlBar>
</mx:Panel>
</mx:Application>

I introduced the QuantileAreaCalculator Class that intercepts the query last result and performs a quantile distribution of the features. A graphic feature is assigned to a bucket, and is assigned the symbol associated with that bucket.
That last assignment forces the graphic to redraw itself. Thus the above result.
The QuantileAreaCalculator numClasses property is bound to the numClasses combo box value, where upon a value change, the distribution is recalculated and the layer is auto refreshed. Download the full source code from here.

Friday, August 8, 2008

3D Multinodal Routing Application

Was tasked to build a Flex based 3D multi-nodal routing application for ESRI's International User Conference. Check out it here. The application enables the user to select a starting and ending room, then an optimized route is calculated using an ArcGIS GeoProcess task. The returned features are rendered in 3D and symbolized based on the floor level and the transition type, such as escalator, stairs or elevator. The floor and room outlines are derived from embedded shapefiles. I used Papervision3D for the the 3D rendering. Though this was my first time dabbling with Papervision, the learning curve was easy and having access to the source code made it more approachable.

360|Flex

Just got approved to be there. Hope to connect with some of you guys !

Poor Man's Tracking

Short of using BlazeDS for asynchronous event notification, RSS is nice "standard" way to publish events. And since XML is a first class citizen in AS3, then parsing the feed is relatively easy. Yes, sure, I can use this syndication library, but it does not give me the control that I need over the feed items, specially over custom tags. One of these custom tags refer to GeoRSS, where you can add a geographical reference to the RSS entries. The geo tags can be of the form of points, lines or polygons. Here is a sample of a GeoRSS feed in JSP, where on every request a random lat/lon point value is generated. This can easily be extended to get the values from a database or a GPS source:

<%@ page contentType="text/xml" language="java" %>
<%
final double lat = -45.0 + 50.0 * Math.random();
final double lon = -45.0 + 50.0 * Math.random();
%>
<feed
xmlns="http://www.w3.org/2005/Atom"
xmlns:georss="http://www.georss.org/georss">
<title>Earthquakes</title>

<subtitle>International earthquake observation labs</subtitle>
<updated>2005-12-13T18:30:02Z</updated>
<author>
<name>Mansour Raad</name>
<email>mraad@esri.com</email>
</author>
<id>urn:uuid:60a76c80-d399-11d9-b93C-0003939e0af6</id>
<entry>
<title>M 3.2, Mona Passage</title>
<id>urn:uuid:1225c695-cfb8-4ebb-aaaa-80da344efa6a</id>
<updated>2005-08-17T07:02:32Z</updated>
<summary>We just had a big one.</summary>
<georss:point><%=lat%> <%=lon%></georss:point>
</entry>
</feed>

To read and render the entries on a map, I've extended the GraphicLayer class to create a GeoRSSLayer and it is used as follows:

<?xml version="1.0" encoding="utf-8"?>
<mx:Application
xmlns:mx="http://www.adobe.com/2006/mxml"
xmlns:esri="http://www.esri.com/2008/ags"
xmlns:georss="com.esri.ags.georss.*"
>
<mx:TraceTarget/>
<esri:Map>
<esri:ArcGISTiledMapServiceLayer
url="http://server.arcgisonline.com/ArcGIS/rest/services/ESRI_Imagery_World_2D/MapServer"/>
<georss:GeoRSSLayer
url="http://localhost:8080/georss.jsp"
delay="15000">
<georss:symbol>
<esri:SimpleMarkerSymbol style="circle" color="0x00FFFF" size="20"/>
</georss:symbol>
</georss:GeoRSSLayer>
</esri:Map>
</mx:Application>

The GeoRSS class has two additional attributes. The url attributes points to the georss feed location, and the delay attribute indicates the delay time in milliseconds to check for new feed entries. You can download the full source code from here. This is assuming that you are using the Flex API for ArcGIS :-)

Saturday, August 2, 2008

Callout Marker Symbol

Point locations in the new Flex API for AGS are rendered using a Symbol subclass. One of these classes is the InfoSymbol, where an info window (callout) will be displayed anchored at the point location. Developers can specify the content of the symbol as a DisplayObject sublcass. The InfoSymbol was inspired from the FIG: Callout Component.
Below is a sample. Click on it to see it in action, and you can download the source code from here.

Flex API For ArcGIS Server in action

This is one of my favorite usage of the API in pure MXML. I'm taking advantage of data binding to represent the output of a Query Task in graphical and textural format. In this application, I've created a QueryTask to a specific layer (countries) in an ArcGIS service (world). The QueryTask has a Query child specifying that the geomerty of the features should be returned, in addition to all the attribute fields. The application UI consists of a side by side map and data grid, and below those is a text field to define a "where" clause, and a button to execute the query. The map has two layers, a dynamic layer to show the world and a graphic layer to show the selected countries. When a user clicks the Query button, the Query "where" attribute is populated (via binding) with the textfield content and the QueryTask is executed. Upon a successful result, the graphic layer will be populated with new graphic objects and the data grid will contain new rows.

The binding "magic" is in the following two lines:

graphicProvider="{queryTask.executeLastResult.features}"

dataProvider="{queryTask.executeLastResult.attributes}"

where the graphic layer will be populated with the query task last result features, and the data grid will be populated with the query task last result attributes. Pretty cool, eh ? And the best part...no ActionScript :-)

<?xml version="1.0" encoding="utf-8"?>
<mx:Application
xmlns:mx="http://www.adobe.com/2006/mxml"
xmlns:esri="http://www.esri.com/2008/ags"
xmlns:sample="com.esri.ags.sample.*"
layout="absolute"
>
<esri:QueryTask id="queryTask" url="http://tejas:8399/arcgis/rest/services/maps/world/MapServer/1">
<esri:Query id="query" returnGeometry="true" where="{where.text}">
<esri:outFields>
<mx:String>*</mx:String>
</esri:outFields>
</esri:Query>
</esri:QueryTask>
<mx:Panel width="100%" height="100%">
<mx:HBox width="100%" height="100%" horizontalGap="0">
<esri:Map id="map">
<esri:ArcGISDynamicMapServiceLayer
url="http://tejas:8399/arcgis/rest/services/maps/world/MapServer"/>
<esri:GraphicsLayer id="graphicsLayer"
graphicProvider="{queryTask.executeLastResult.features}">
<esri:symbol>
<esri:SimpleFillSymbol color="0xFF0000"/>
</esri:symbol>
</esri:GraphicsLayer>
</esri:Map>
<mx:DataGrid width="100%" height="100%"
dataProvider="{queryTask.executeLastResult.attributes}">
<mx:columns>
<mx:DataGridColumn headerText="Name" dataField="NAME"/>
<mx:DataGridColumn headerText="FIPS" dataField="FIPS_CODE"/>
<mx:DataGridColumn headerText="Area" dataField="AREA"/>
</mx:columns>
</mx:DataGrid>
</mx:HBox>
<mx:ControlBar>
<mx:TextInput id="where" text="FID < 10"/>
<mx:Button label="Query" click="queryTask.execute()"/>
</mx:ControlBar>
</mx:Panel>
</mx:Application>

Flex API For ArcGIS Server

Ok gang, sorry for the long silence. We have been busy here @ ESRI with building the Flex API for ArcGIS Server. We will be announcing the public beta at the user conference this week and here is the link. Download it, try it out and give us some feedbacks.