mansour raad & anthony jayaprakash - yet another mapping framework, not!

Post on 13-Jan-2015

839 Views

Category:

Technology

0 Downloads

Preview:

Click to see full reader

DESCRIPTION

In this session 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.

TRANSCRIPT

Yet AnotherMapping API - Not !

Mansour Raadmraad@esri.com

ArcGIS Services

• Map Tiles ESRI / Virtual Earth (token)

• Geocoding / Reverse

• Query / Identify

• Routing with Barriers and Time Windows

• Buffer / Projection

• GeoProcessing

You & ArcGIS

BlazePHP.Net

Local AGS

Map “Hello World”

1.<?xml version="1.0" encoding="utf-8"?>2.<mx:Application3. xmlns:mx="http://www.adobe.com/2006/mxml"4. xmlns:esri="http://www.esri.com/2008/ags"5. layout="absolute"6. >7. <esri:Map id="map">8. <esri:ArcGISTiledMapServiceLayer url=”http://host/rest/map”/> 9. </esri:Map> 10.</mx:Application>

Map “Hello World”

1.<?xml version="1.0" encoding="utf-8"?>2.<mx:Application3. xmlns:mx="http://www.adobe.com/2006/mxml"4. xmlns:esri="http://www.esri.com/2008/ags"5. layout="absolute"6. >7. <esri:Map id="map">8. <esri:ArcGISTiledMapServiceLayer url=”http://host/rest/map”/> 9. </esri:Map> 10.</mx:Application>

Map “Hello World”

1.<?xml version="1.0" encoding="utf-8"?>2.<mx:Application3. xmlns:mx="http://www.adobe.com/2006/mxml"4. xmlns:esri="http://www.esri.com/2008/ags"5. layout="absolute"6. >7. <esri:Map id="map" openHandCursorVisible="false" zoomSliderVisible="false">8. <esri:ArcGISTiledMapServiceLayer id="layer" url="{cb.selectedItem.url}"/> 9. </esri:Map>10. <mx:ComboBox id="cb" dataProvider="{[11. {label:'Imagery',url:'http://host/rest/Image'},12. {label:'Physical',url:'http://host/rest/Physical'}13. ]}"/> 14.</mx:Application>

1.<?xml version="1.0" encoding="utf-8"?>2.<mx:Application3. xmlns:mx="http://www.adobe.com/2006/mxml"4. xmlns:esri="http://www.esri.com/2008/ags"5. layout="absolute"6. >7. <esri:Map id="map" openHandCursorVisible="false" zoomSliderVisible="false">8. <esri:ArcGISTiledMapServiceLayer id="layer" url="{cb.selectedItem.url}"/> 9. </esri:Map>10. <mx:ComboBox id="cb" dataProvider="{[11. {label:'Imagery',url:'http://host/rest/Image'},12. {label:'Physical',url:'http://host/rest/Physical'}13. ]}"/> 14.</mx:Application>

1.<?xml version="1.0" encoding="utf-8"?>2.<mx:Application3. xmlns:mx="http://www.adobe.com/2006/mxml"4. xmlns:esri="http://www.esri.com/2008/ags"5. layout="absolute"6. >7. <esri:Map id="map" openHandCursorVisible="false" zoomSliderVisible="false">8. <esri:ArcGISTiledMapServiceLayer id="layer" url="{cb.selectedItem.url}"/> 9. </esri:Map>10. <mx:ComboBox id="cb" dataProvider="{[11. {label:'Imagery',url:'http://host/rest/Image'},12. {label:'Physical',url:'http://host/rest/Physical'}13. ]}"/> 14.</mx:Application>

GeoProcessingDriveTimes

1. <esri:Geoprocessor id="gp" url="<GeoProcessesorURL>" showBusyCursor="true"/>2. <esri:Map id="map" openHandCursorVisible="false" mapClick="mapClickHandler(event)">3. <esri:extent>4. <esri:Extent xmin="-95.41" ymin="38.86" xmax="-95.1" ymax="39.06">5. <esri:SpatialReference wkid="4326"/>6. </esri:Extent>7. </esri:extent>8. <esri:ArcGISTiledMapServiceLayer url="<MapServiceURL>"/>9. <esri:GraphicsLayer id="polygonLayer" graphicProvider="{gp.executeFirstFeatureSet.features}">10. <esri:renderer>11. <esri:UniqueValueRenderer attribute="ToBreak">12. <esri:UniqueValueInfo value="1">13. <esri:symbol>14. <esri:SimpleFillSymbol alpha="0.5" color="0xFF0000"/>15. </esri:symbol>16. </esri:UniqueValueInfo>17. <esri:UniqueValueInfo value="2">18. <esri:symbol>19. <esri:SimpleFillSymbol alpha="0.5" color="0x00FF00"/>20. </esri:symbol>21. </esri:UniqueValueInfo>22. <esri:UniqueValueInfo value="3">23. <esri:symbol>24. <esri:SimpleFillSymbol alpha="0.5" color="0x0000FF"/>25. </esri:symbol>26. </esri:UniqueValueInfo>27. </esri:UniqueValueRenderer>28. </esri:renderer>29. </esri:GraphicsLayer>30. <esri:GraphicsLayer id="pointLayer"/>31. </esri:Map>

1. <esri:Geoprocessor id="gp" url="<GeoProcessesorURL>" showBusyCursor="true"/>2. <esri:Map id="map" openHandCursorVisible="false" mapClick="mapClickHandler(event)">3. <esri:extent>4. <esri:Extent xmin="-95.41" ymin="38.86" xmax="-95.1" ymax="39.06">5. <esri:SpatialReference wkid="4326"/>6. </esri:Extent>7. </esri:extent>8. <esri:ArcGISTiledMapServiceLayer url="<MapServiceURL>"/>9. <esri:GraphicsLayer id="polygonLayer" graphicProvider="{gp.executeFirstFeatureSet.features}">10. <esri:renderer>11. <esri:UniqueValueRenderer attribute="ToBreak">12. <esri:UniqueValueInfo value="1">13. <esri:symbol>14. <esri:SimpleFillSymbol alpha="0.5" color="0xFF0000"/>15. </esri:symbol>16. </esri:UniqueValueInfo>17. <esri:UniqueValueInfo value="2">18. <esri:symbol>19. <esri:SimpleFillSymbol alpha="0.5" color="0x00FF00"/>20. </esri:symbol>21. </esri:UniqueValueInfo>22. <esri:UniqueValueInfo value="3">23. <esri:symbol>24. <esri:SimpleFillSymbol alpha="0.5" color="0x0000FF"/>25. </esri:symbol>26. </esri:UniqueValueInfo>27. </esri:UniqueValueRenderer>28. </esri:renderer>29. </esri:GraphicsLayer>30. <esri:GraphicsLayer id="pointLayer"/>31. </esri:Map>

1. <esri:Geoprocessor id="gp" url="<GeoProcessesorURL>" showBusyCursor="true"/>2. <esri:Map id="map" openHandCursorVisible="false" mapClick="mapClickHandler(event)">3. <esri:extent>4. <esri:Extent xmin="-95.41" ymin="38.86" xmax="-95.1" ymax="39.06">5. <esri:SpatialReference wkid="4326"/>6. </esri:Extent>7. </esri:extent>8. <esri:ArcGISTiledMapServiceLayer url="<MapServiceURL>"/>9. <esri:GraphicsLayer id="polygonLayer" graphicProvider="{gp.executeFirstFeatureSet.features}">10. <esri:renderer>11. <esri:UniqueValueRenderer attribute="ToBreak">12. <esri:UniqueValueInfo value="1">13. <esri:symbol>14. <esri:SimpleFillSymbol alpha="0.5" color="0xFF0000"/>15. </esri:symbol>16. </esri:UniqueValueInfo>17. <esri:UniqueValueInfo value="2">18. <esri:symbol>19. <esri:SimpleFillSymbol alpha="0.5" color="0x00FF00"/>20. </esri:symbol>21. </esri:UniqueValueInfo>22. <esri:UniqueValueInfo value="3">23. <esri:symbol>24. <esri:SimpleFillSymbol alpha="0.5" color="0x0000FF"/>25. </esri:symbol>26. </esri:UniqueValueInfo>27. </esri:UniqueValueRenderer>28. </esri:renderer>29. </esri:GraphicsLayer>30. <esri:GraphicsLayer id="pointLayer"/>31. </esri:Map>

1. <esri:Geoprocessor id="gp" url="<GeoProcessesorURL>" showBusyCursor="true"/>2. <esri:Map id="map" openHandCursorVisible="false" mapClick="mapClickHandler(event)">3. <esri:extent>4. <esri:Extent xmin="-95.41" ymin="38.86" xmax="-95.1" ymax="39.06">5. <esri:SpatialReference wkid="4326"/>6. </esri:Extent>7. </esri:extent>8. <esri:ArcGISTiledMapServiceLayer url="<MapServiceURL>"/>9. <esri:GraphicsLayer id="polygonLayer" graphicProvider="{gp.executeFirstFeatureSet.features}">10. <esri:renderer>11. <esri:UniqueValueRenderer attribute="ToBreak">12. <esri:UniqueValueInfo value="1">13. <esri:symbol>14. <esri:SimpleFillSymbol alpha="0.5" color="0xFF0000"/>15. </esri:symbol>16. </esri:UniqueValueInfo>17. <esri:UniqueValueInfo value="2">18. <esri:symbol>19. <esri:SimpleFillSymbol alpha="0.5" color="0x00FF00"/>20. </esri:symbol>21. </esri:UniqueValueInfo>22. <esri:UniqueValueInfo value="3">23. <esri:symbol>24. <esri:SimpleFillSymbol alpha="0.5" color="0x0000FF"/>25. </esri:symbol>26. </esri:UniqueValueInfo>27. </esri:UniqueValueRenderer>28. </esri:renderer>29. </esri:GraphicsLayer>30. <esri:GraphicsLayer id="pointLayer"/>31. </esri:Map>

1.<mx:Script>2. <![CDATA[3. import com.esri.ags.tasks.FeatureSet;4. import com.esri.ags.Graphic;5. import com.esri.ags.events.MapMouseEvent;

7. private function mapClickHandler(event:MapMouseEvent):void8. {9. const graphic:Graphic = new Graphic(event.mapPoint);10. pointLayer.clear();11. pointLayer.add(graphic);12. const featureSet:FeatureSet = new FeatureSet([graphic]);13. gp.execute({"Input_Location": featureSet, "Drive_Times": "1 2 3"});14. }15. ]]>16.</mx:Script>

1.<mx:Script>2. <![CDATA[3. import com.esri.ags.tasks.FeatureSet;4. import com.esri.ags.Graphic;5. import com.esri.ags.events.MapMouseEvent;

7. private function mapClickHandler(event:MapMouseEvent):void8. {9. const graphic:Graphic = new Graphic(event.mapPoint);10. pointLayer.clear();11. pointLayer.add(graphic);12. const featureSet:FeatureSet = new FeatureSet([graphic]);13. gp.execute({"Input_Location": featureSet, "Drive_Times": "1 2 3"});14. }15. ]]>16.</mx:Script>

DemoSample 1-2DriveTimes

Many Children Layers

Many Graphic Layers

GraphicLayer

GraphicLayer

• graphicProvider

• ArrayCollection

• renderer

• graphic with no symbol

Graphic

Graphic

• UIComponent

• Flex life cycle management

• geometry

• symbol

• attributes

Graphic/Geometry

Graphic/Geometry

• Geometry - base class

• MapPoint

• Polyline

• Polygon

Polyline/Polygon

Polyline/Polygon

• Multi Part Geometry

• Islands of Hawaii

Graphic/Symbol

Graphic/Symbol

• Symbol - base class

• Draws geometry of Graphic

• Uses Flash Drawing API

Graphic/Attributes

Graphic/Attributes

• Any Object !

• Attach any dynamic property to Graphic

Geometry/Symbol

Geometry/Symbol

• [Bindable] Properties

• Dispatch CHANGE event

DemoSample 3-7

LCDS

LCDS

• Remote Objects

• Messaging

• Data Services

Feature

Feature

• Serializable server side object

• Properties

• featureID:int;

• geometry:IGeometry;

• attributes:ASObject;

public class Feature implements Serializable{ private int m_featureId; private IGeometry m_geometry; private ASObject m_attributes;

public Feature() { }

public int getFeatureId() { return m_featureId; }

public void setFeatureId(final int featureId) { m_featureId = featureId; }

...

public class MapPoint implements IGeometry{ private double m_x; private double m_y; private SpatialReference m_spatialReference;

public MapPoint(){ }

public MapPoint(final double x, final double y){ m_x = x; m_y = y; }

public double getX(){ return m_x; }

public void setX(final double x){ m_x = x; }

...

DS Assembler

• fill

• createItem

• getItem

• updateItem

• deleteItem

private int m_featureId = 1;private Map<Integer, Feature> m_map = new ConcurrentHashMap<Integer, Feature>(17);

public Collection fill(final List fillParameters){ return m_map.values();}

public Object getItem(final Map map){ return m_map.get(map.get("featureId"));}

public void createItem(final Object newVersion){ final Feature Feature = (Feature) newVersion; Feature.setFeatureId(m_featureId++); m_map.put(Feature.getFeatureId(), Feature);}

public void updateItem(final Object newVersion, final Object prevVersion, final List changes){ final Feature Feature = (Feature) newVersion; m_map.put(Feature.getFeatureId(), Feature);}

public void deleteItem(final Object prevVersion){ final Feature Feature = (Feature) prevVersion; m_map.remove(Feature.getFeatureId());}

private int m_featureId = 1;private Map<Integer, Feature> m_map = new ConcurrentHashMap<Integer, Feature>(17);

public Collection fill(final List fillParameters){ return m_map.values();}

public Object getItem(final Map map){ return m_map.get(map.get("featureId"));}

public void createItem(final Object newVersion){ final Feature Feature = (Feature) newVersion; Feature.setFeatureId(m_featureId++); m_map.put(Feature.getFeatureId(), Feature);}

public void updateItem(final Object newVersion, final Object prevVersion, final List changes){ final Feature Feature = (Feature) newVersion; m_map.put(Feature.getFeatureId(), Feature);}

public void deleteItem(final Object prevVersion){ final Feature Feature = (Feature) prevVersion; m_map.remove(Feature.getFeatureId());}

private int m_featureId = 1;private Map<Integer, Feature> m_map = new ConcurrentHashMap<Integer, Feature>(17);

public Collection fill(final List fillParameters){ return m_map.values();}

public Object getItem(final Map map){ return m_map.get(map.get("featureId"));}

public void createItem(final Object newVersion){ final Feature Feature = (Feature) newVersion; Feature.setFeatureId(m_featureId++); m_map.put(Feature.getFeatureId(), Feature);}

public void updateItem(final Object newVersion, final Object prevVersion, final List changes){ final Feature Feature = (Feature) newVersion; m_map.put(Feature.getFeatureId(), Feature);}

public void deleteItem(final Object prevVersion){ final Feature Feature = (Feature) prevVersion; m_map.remove(Feature.getFeatureId());}

private int m_featureId = 1;private Map<Integer, Feature> m_map = new ConcurrentHashMap<Integer, Feature>(17);

public Collection fill(final List fillParameters){ return m_map.values();}

public Object getItem(final Map map){ return m_map.get(map.get("featureId"));}

public void createItem(final Object newVersion){ final Feature Feature = (Feature) newVersion; Feature.setFeatureId(m_featureId++); m_map.put(Feature.getFeatureId(), Feature);}

public void updateItem(final Object newVersion, final Object prevVersion, final List changes){ final Feature Feature = (Feature) newVersion; m_map.put(Feature.getFeatureId(), Feature);}

public void deleteItem(final Object prevVersion){ final Feature Feature = (Feature) prevVersion; m_map.remove(Feature.getFeatureId());}

private int m_featureId = 1;private Map<Integer, Feature> m_map = new ConcurrentHashMap<Integer, Feature>(17);

public Collection fill(final List fillParameters){ return m_map.values();}

public Object getItem(final Map map){ return m_map.get(map.get("featureId"));}

public void createItem(final Object newVersion){ final Feature Feature = (Feature) newVersion; Feature.setFeatureId(m_featureId++); m_map.put(Feature.getFeatureId(), Feature);}

public void updateItem(final Object newVersion, final Object prevVersion, final List changes){ final Feature Feature = (Feature) newVersion; m_map.put(Feature.getFeatureId(), Feature);}

public void deleteItem(final Object prevVersion){ final Feature Feature = (Feature) prevVersion; m_map.remove(Feature.getFeatureId());}

private int m_featureId = 1;private Map<Integer, Feature> m_map = new ConcurrentHashMap<Integer, Feature>(17);

public Collection fill(final List fillParameters){ return m_map.values();}

public Object getItem(final Map map){ return m_map.get(map.get("featureId"));}

public void createItem(final Object newVersion){ final Feature Feature = (Feature) newVersion; Feature.setFeatureId(m_featureId++); m_map.put(Feature.getFeatureId(), Feature);}

public void updateItem(final Object newVersion, final Object prevVersion, final List changes){ final Feature Feature = (Feature) newVersion; m_map.put(Feature.getFeatureId(), Feature);}

public void deleteItem(final Object prevVersion){ final Feature Feature = (Feature) prevVersion; m_map.remove(Feature.getFeatureId());}

data-management-config.xml

data-management-config.xml<destination id="feature"> <properties> <factory>spring</factory> <source>featureAssembler</source> <scope>application</scope> <use-transactions>false</use-transactions> <metadata> <identity property="featureId"/> </metadata> <network> <paging enabled="false" pageSize="10"/> </network> </properties></destination>

Back To The Client :-)

package com.esri.cats{ import com.esri.ags.SpatialReference; import com.esri.ags.geometry.MapPoint; import flash.net.registerClassAlias; import mx.core.IMXMLObject;

public class ClassAliasRegistry implements IMXMLObject { public function initialized(document:Object, id:String):void { registerClassAlias("com.esri.cats.MapPoint", MapPoint); registerClassAlias("com.esri.cats.SpatialReference", SpatialReference); } }}

package com.esri.cats{ import com.esri.ags.SpatialReference; import com.esri.ags.geometry.MapPoint; import flash.net.registerClassAlias; import mx.core.IMXMLObject;

public class ClassAliasRegistry implements IMXMLObject { public function initialized(document:Object, id:String):void { registerClassAlias("com.esri.cats.MapPoint", MapPoint); registerClassAlias("com.esri.cats.SpatialReference", SpatialReference); } }}

1.package com.esri.cats2.{3. import com.esri.ags.geometry.Geometry;

5. [Managed]6. [RemoteClass(alias="com.esri.cats.Feature")]7. public class Feature8. {9. public var featureId:int;10. public var geometry:Geometry;11. public var attributes:Object;12. 13. public function Feature()14. {15. }16. 17. } 18.}

1.package com.esri.cats2.{3. import com.esri.ags.geometry.Geometry;

5. [Managed]6. [RemoteClass(alias="com.esri.cats.Feature")]7. public class Feature8. {9. public var featureId:int;10. public var geometry:Geometry;11. public var attributes:Object;12. 13. public function Feature()14. {15. }16. 17. } 18.}

1.<cats:ClassAliasRegistry/>2.<mx:ArrayCollection id="features"3. collectionChange="collectionChangeHandler(event)"/>4.<mx:DataService id="ds" destination="feature"/>5.<esri:Map id="map" load="ds.fill(features)">6. <esri:GraphicsLayer id="graphicsLayer"/>7. <esri:GraphicsLayer id="pointLayer">8. <esri:symbol>9. <esri:SimpleMarkerSymbol color="0xFFFF00"/>10. </esri:symbol>11. </esri:GraphicsLayer>12.</esri:Map>

1.<cats:ClassAliasRegistry/>2.<mx:ArrayCollection id="features"3. collectionChange="collectionChangeHandler(event)"/>4.<mx:DataService id="ds" destination="feature"/>5.<esri:Map id="map" load="ds.fill(features)">6. <esri:GraphicsLayer id="graphicsLayer"/>7. <esri:GraphicsLayer id="pointLayer">8. <esri:symbol>9. <esri:SimpleMarkerSymbol color="0xFFFF00"/>10. </esri:symbol>11. </esri:GraphicsLayer>12.</esri:Map>

1.<cats:ClassAliasRegistry/>2.<mx:ArrayCollection id="features"3. collectionChange="collectionChangeHandler(event)"/>4.<mx:DataService id="ds" destination="feature"/>5.<esri:Map id="map" load="ds.fill(features)">6. <esri:GraphicsLayer id="graphicsLayer"/>7. <esri:GraphicsLayer id="pointLayer">8. <esri:symbol>9. <esri:SimpleMarkerSymbol color="0xFFFF00"/>10. </esri:symbol>11. </esri:GraphicsLayer>12.</esri:Map>

1.<cats:ClassAliasRegistry/>2.<mx:ArrayCollection id="features"3. collectionChange="collectionChangeHandler(event)"/>4.<mx:DataService id="ds" destination="feature"/>5.<esri:Map id="map" load="ds.fill(features)">6. <esri:GraphicsLayer id="graphicsLayer"/>7. <esri:GraphicsLayer id="pointLayer">8. <esri:symbol>9. <esri:SimpleMarkerSymbol color="0xFFFF00"/>10. </esri:symbol>11. </esri:GraphicsLayer>12.</esri:Map>

1.<cats:ClassAliasRegistry/>2.<mx:ArrayCollection id="features"3. collectionChange="collectionChangeHandler(event)"/>4.<mx:DataService id="ds" destination="feature"/>5.<esri:Map id="map" load="ds.fill(features)">6. <esri:GraphicsLayer id="graphicsLayer"/>7. <esri:GraphicsLayer id="pointLayer">8. <esri:symbol>9. <esri:SimpleMarkerSymbol color="0xFFFF00"/>10. </esri:symbol>11. </esri:GraphicsLayer>12.</esri:Map>

private function collectionChangeHandler(event:CollectionEvent):void{ switch (event.kind) { case CollectionEventKind.RESET: doReset(event); break; case CollectionEventKind.UPDATE: doUpdate(event); break; }}

private function doReset(event:CollectionEvent):void{ graphicsLayer.clear(); m_graphicsDict = new Dictionary(); for each (var feature:Feature in features) { var graphic:Graphic = new Graphic(feature.geometry, null, feature); graphic.buttonMode = true; graphic.addEventListener(MouseEvent.MOUSE_DOWN, mouseDownHandler); graphic.toolTip = String(feature.attributes.coords).replace(" ", "\n"); graphicsLayer.add(graphic); m_graphicsDict[feature.featureId] = graphic; }}

private function doReset(event:CollectionEvent):void{ graphicsLayer.clear(); m_graphicsDict = new Dictionary(); for each (var feature:Feature in features) { var graphic:Graphic = new Graphic(feature.geometry, null, feature); graphic.buttonMode = true; graphic.addEventListener(MouseEvent.MOUSE_DOWN, mouseDownHandler); graphic.toolTip = String(feature.attributes.coords).replace(" ", "\n"); graphicsLayer.add(graphic); m_graphicsDict[feature.featureId] = graphic; }}

private function doReset(event:CollectionEvent):void{ graphicsLayer.clear(); m_graphicsDict = new Dictionary(); for each (var feature:Feature in features) { var graphic:Graphic = new Graphic(feature.geometry, null, feature); graphic.buttonMode = true; graphic.addEventListener(MouseEvent.MOUSE_DOWN, mouseDownHandler); graphic.toolTip = String(feature.attributes.coords).replace(" ", "\n"); graphicsLayer.add(graphic); m_graphicsDict[feature.featureId] = graphic; }}

private function doUpdate(event:CollectionEvent):void{ for each (var propertyChangeEvent:PropertyChangeEvent in event.items) { var feature:Feature = propertyChangeEvent.target as Feature; if (propertyChangeEvent.property === "geometry") { var graphic:Graphic = m_graphicsDict[feature.featureId]; if (graphic) { graphic.geometry = feature.geometry; } } }}

private function doUpdate(event:CollectionEvent):void{ for each (var propertyChangeEvent:PropertyChangeEvent in event.items) { var feature:Feature = propertyChangeEvent.target as Feature; if (propertyChangeEvent.property === "geometry") { var graphic:Graphic = m_graphicsDict[feature.featureId]; if (graphic) { graphic.geometry = feature.geometry; } } }}

private function doUpdate(event:CollectionEvent):void{ for each (var propertyChangeEvent:PropertyChangeEvent in event.items) { var feature:Feature = propertyChangeEvent.target as Feature; if (propertyChangeEvent.property === "geometry") { var graphic:Graphic = m_graphicsDict[feature.featureId]; if (graphic) { graphic.geometry = feature.geometry; } } }}

1.private function mouseDownHandler(event:MouseEvent):void2.{3. const graphic:Graphic = event.target as Graphic;4. if (graphic)5. {6. m_feature = graphic.attributes as Feature;7. m_graphic.geometry = map.toMapFromStage(event.stageX, event.stageY);8. pointLayer.add(m_graphic);9. map.addEventListener(MouseEvent.MOUSE_MOVE, mouseMoveHandler);10. map.addEventListener(MouseEvent.MOUSE_UP, mouseUpHandler);11. }12.}

14.private function mouseMoveHandler(event:MouseEvent):void15.{16. m_graphic.geometry = map.toMapFromStage(event.stageX, event.stageY);17. event.updateAfterEvent();18.}

20.private function mouseUpHandler(event:MouseEvent):void21.{22. m_feature.geometry = m_graphic.geometry; // ALL DS FM is Here :-)23. m_feature = null;24. pointLayer.clear();25. map.removeEventListener(MouseEvent.MOUSE_MOVE, mouseMoveHandler);26. map.removeEventListener(MouseEvent.MOUSE_UP, mouseUpHandler);27.}

1.private function mouseDownHandler(event:MouseEvent):void2.{3. const graphic:Graphic = event.target as Graphic;4. if (graphic)5. {6. m_feature = graphic.attributes as Feature;7. m_graphic.geometry = map.toMapFromStage(event.stageX, event.stageY);8. pointLayer.add(m_graphic);9. map.addEventListener(MouseEvent.MOUSE_MOVE, mouseMoveHandler);10. map.addEventListener(MouseEvent.MOUSE_UP, mouseUpHandler);11. }12.}

14.private function mouseMoveHandler(event:MouseEvent):void15.{16. m_graphic.geometry = map.toMapFromStage(event.stageX, event.stageY);17. event.updateAfterEvent();18.}

20.private function mouseUpHandler(event:MouseEvent):void21.{22. m_feature.geometry = m_graphic.geometry; // ALL DS FM is Here :-)23. m_feature = null;24. pointLayer.clear();25. map.removeEventListener(MouseEvent.MOUSE_MOVE, mouseMoveHandler);26. map.removeEventListener(MouseEvent.MOUSE_UP, mouseUpHandler);27.}

1.private function mouseDownHandler(event:MouseEvent):void2.{3. const graphic:Graphic = event.target as Graphic;4. if (graphic)5. {6. m_feature = graphic.attributes as Feature;7. m_graphic.geometry = map.toMapFromStage(event.stageX, event.stageY);8. pointLayer.add(m_graphic);9. map.addEventListener(MouseEvent.MOUSE_MOVE, mouseMoveHandler);10. map.addEventListener(MouseEvent.MOUSE_UP, mouseUpHandler);11. }12.}

14.private function mouseMoveHandler(event:MouseEvent):void15.{16. m_graphic.geometry = map.toMapFromStage(event.stageX, event.stageY);17. event.updateAfterEvent();18.}

20.private function mouseUpHandler(event:MouseEvent):void21.{22. m_feature.geometry = m_graphic.geometry; // ALL DS FM is Here :-)23. m_feature = null;24. pointLayer.clear();25. map.removeEventListener(MouseEvent.MOUSE_MOVE, mouseMoveHandler);26. map.removeEventListener(MouseEvent.MOUSE_UP, mouseUpHandler);27.}

Demo CATS

“Lots” Features

Spatial Index

Spatial Index

• RTree

• QuadTree

• Grid / Trellis

• Simple

• Efficient (points)

• Good enough !

0,0

width,height

0,0

width,height

Xmin,Ymin

Xmax,Ymax

0,0

width,height

Xmin,Ymin

Xmax,Ymax

0,0

width,height

Xmin,Ymin

Xmax,Ymax

0 1 2 3

0

1

2

3

Cx

Cy

0 1 2 3

0

1

2

3

(0,0)

(1,3)

(3,2)

(3,2)

Cx

Cy

Cx & Cy > 0 int

Cx & Cy < 216

Dict[(cx<<16)|cy]

Cluster : Geometry

Cluster : Geometry

• Original X

• Original Y

• Cluster X

• Cluster Y

• count

ClusterSymbol : Symbol

ClusterSymbol : Symbol

• Draws a Cluster geometry instance

• Flash drawing API

• beginFill - based on cluster count

• drawRoundedRect - based on Cx,Cy

DemoDrawSymbol Code

Adaptive Clustering

Adaptive Clustering

• JIT

• “Smart” algorithm - all client side.

• React to map extent change

Given set of map points

Given set of map pointsAssign map point to cluster set

Given set of map pointsAssign map point to cluster setdo

Given set of map pointsAssign map point to cluster setdo spatial index clusters

Given set of map pointsAssign map point to cluster setdo spatial index clusters for each cluster Ci

Given set of map pointsAssign map point to cluster setdo spatial index clusters for each cluster Ci

find adjacent clusters Cj

Given set of map pointsAssign map point to cluster setdo spatial index clusters for each cluster Ci

find adjacent clusters Cj

if Cj is close enough to Ci

Given set of map pointsAssign map point to cluster setdo spatial index clusters for each cluster Ci

find adjacent clusters Cj

if Cj is close enough to Ci

assign Cj map points to Ci

Given set of map pointsAssign map point to cluster setdo spatial index clusters for each cluster Ci

find adjacent clusters Cj

if Cj is close enough to Ci

assign Cj map points to Ci

remove Cj from cluster set

Given set of map pointsAssign map point to cluster setdo spatial index clusters for each cluster Ci

find adjacent clusters Cj

if Cj is close enough to Ci

assign Cj map points to Ci

remove Cj from cluster set adjust Ci location

Given set of map pointsAssign map point to cluster setdo spatial index clusters for each cluster Ci

find adjacent clusters Cj

if Cj is close enough to Ci

assign Cj map points to Ci

remove Cj from cluster set adjust Ci locationrepeat while overlapping clusters exist

Adjusting Ci location

Adjusting Ci location

Ci

Wi

Adjusting Ci location

Ci

Wi

Cj

Wj

Adjusting Ci location

Ci

Wi

Cj

Wj

Adjusting Ci location

Wi+Wj

Ci=(Ci Wi+CjWj)/WiWj

DemoClusterApp

HeatMaps are Bitmaps !

1.<?xml version="1.0" encoding="utf-8"?>2.<view:PrepApplication3. xmlns:mx="http://www.adobe.com/2006/mxml"4. xmlns:esri="http://www.esri.com/2008/ags"5. xmlns:controller="com.esri.controller.*"6. xmlns:view="com.esri.view.*"7. layout="vertical"8. paddingLeft="0"9. paddingRight="0"10. paddingTop="0"11. paddingBottom="0"12. >13. <controller:LoadCommand/>14. <view:PrepSlider/>15. <view:PrepMap>16. <view:extent>17. <esri:Extent xmin="-143.141073" ymin="14.930875" xmax="-48.0570833" ymax="57.649769"/>18. </view:extent>19. <esri:ArcGISTiledMapServiceLayer20. url="http://server.arcgisonline.com/ArcGIS/rest/services/ESRI_Imagery_World_2D/MapServer"/>21. <view:PrepLayer/> 22. </view:PrepMap>23.</view:PrepApplication>

1.<?xml version="1.0" encoding="utf-8"?>2.<view:PrepApplication3. xmlns:mx="http://www.adobe.com/2006/mxml"4. xmlns:esri="http://www.esri.com/2008/ags"5. xmlns:controller="com.esri.controller.*"6. xmlns:view="com.esri.view.*"7. layout="vertical"8. paddingLeft="0"9. paddingRight="0"10. paddingTop="0"11. paddingBottom="0"12. >13. <controller:LoadCommand/>14. <view:PrepSlider/>15. <view:PrepMap>16. <view:extent>17. <esri:Extent xmin="-143.141073" ymin="14.930875" xmax="-48.0570833" ymax="57.649769"/>18. </view:extent>19. <esri:ArcGISTiledMapServiceLayer20. url="http://server.arcgisonline.com/ArcGIS/rest/services/ESRI_Imagery_World_2D/MapServer"/>21. <view:PrepLayer/> 22. </view:PrepMap>23.</view:PrepApplication>

PrepLayer : Layer

PrepLayer : Layer

• Subclass Layer

• Override updateLayer

• Invoked by updateDisplayList

• create bitmap - lock/unlock

• bitmap.fillRect each heat map point

• graphic.bitmapFill / drawRect

PrepLayer

PrepLayer

• Kept data in 2 arrays

• x = []

• y = []

• Easy to AMF

• toScreenX/Y built-in functions

DemoPrecipitationApp

Street Tracing

Street Tracing

• A*

• Create nodes and edges

• Define barriers

• Reverse geocoding

• Custom layer - faster rendering

A* / Path Finding

Streets

Streets

“Street” Graph

“Street” Graph

• Intersection - nodes

• Street Segment - edge

• Travel distance or time - cost

Nodes/Edges/Barriers

Nodes/Edges/Barriers

A

B

C

D

E

Nodes/Edges/Barriers

A

B

C

D

E

Nodes/Edges/Barriers

A

B

C

D

E

Street Info

Main St

Street Info

Main St

100

200

Street Info

Main St

100101

200199

ReverseGeocoding

ReverseGeocoding

Main StLeft 100-200Right 101-199

ReverseGeocoding

t

Main StLeft 100-200Right 101-199

ReverseGeocoding

t

Main StLeft 100-200Right 101-199

ReverseGeocoding

dt

Main StLeft 100-200Right 101-199

ReverseGeocoding

dt

Main StLeft 100-200Right 101-199

153 Main St

Distance Calculations

Distance Calculations

A

B

C

Distance Calculations

A

B

C

P

Distance Calculations

A

B

C

Pr

r=AC AB•

∣AB∣2

Distance Calculations

A

B

C

Pr

r=AC AB•

∣AB∣2

r≺0 beyond A ↤

Distance Calculations

A

B

C

Pr

r=AC AB•

∣AB∣2

r≺0 beyond A ↤r≻0 beyond B ↦

Distance Calculations

Ax Bx Cx

Ay By Cy

12

A=

A

B

C

Pr

r=AC AB•

∣AB∣2

r≺0 beyond A ↤r≻0 beyond B ↦

Distance Calculations

Ax Bx Cx

Ay By Cy

12

A=

A

B

C

height

Pr

r=AC AB•

∣AB∣2

r≺0 beyond A ↤r≻0 beyond B ↦

Distance Calculations

Ax Bx Cx

Ay By Cy

12

A=

A

B

C

base

height

Pr

r=AC AB•

∣AB∣2

r≺0 beyond A ↤r≻0 beyond B ↦

Distance Calculations

A=base×height

2

Ax Bx Cx

Ay By Cy

12

A=

A

B

C

base

height

Pr

r=AC AB•

∣AB∣2

r≺0 beyond A ↤r≻0 beyond B ↦

Distance Calculations

A=base×height

2

Ax Bx Cx

Ay By Cy

12

A=

A

B

C

base

height

Pr

r=AC AB•

∣AB∣2

r≺0 beyond A ↤r≻0 beyond B ↦

AP=rAB

1.override protected function updateLayer():void{2. const model:Model = Model.instance;3. graphics.clear();4. graphics.lineStyle(1, 0);5. model.streetGrid.search(map.extent, streetHandler);6.}

8.private function streetHandler(street:Street, data:Object = null):void{9. for each(var path:Array in street.shpPolyline.paths){10. var index:int = 0;11. var lastX:Number = toScreenX(path[index++]);12. var lastY:Number = toScreenY(path[index++]);13. graphics.moveTo(lastX, lastY);14. while(index < path.length){15. var currX:Number = toScreenX(path[index++]);16. var currY:Number = toScreenY(path[index++]);17. if( currX !== lastX || currY !== lastY){18. graphics.lineTo(currX, currY);19. lastX = currX;20. lastY = currY; 21. }22. }23. }24.}

1.override protected function updateLayer():void{2. const model:Model = Model.instance;3. graphics.clear();4. graphics.lineStyle(1, 0);5. model.streetGrid.search(map.extent, streetHandler);6.}

8.private function streetHandler(street:Street, data:Object = null):void{9. for each(var path:Array in street.shpPolyline.paths){10. var index:int = 0;11. var lastX:Number = toScreenX(path[index++]);12. var lastY:Number = toScreenY(path[index++]);13. graphics.moveTo(lastX, lastY);14. while(index < path.length){15. var currX:Number = toScreenX(path[index++]);16. var currY:Number = toScreenY(path[index++]);17. if( currX !== lastX || currY !== lastY){18. graphics.lineTo(currX, currY);19. lastX = currX;20. lastY = currY; 21. }22. }23. }24.}

1.override protected function updateLayer():void{2. const model:Model = Model.instance;3. graphics.clear();4. graphics.lineStyle(1, 0);5. model.streetGrid.search(map.extent, streetHandler);6.}

8.private function streetHandler(street:Street, data:Object = null):void{9. for each(var path:Array in street.shpPolyline.paths){10. var index:int = 0;11. var lastX:Number = toScreenX(path[index++]);12. var lastY:Number = toScreenY(path[index++]);13. graphics.moveTo(lastX, lastY);14. while(index < path.length){15. var currX:Number = toScreenX(path[index++]);16. var currY:Number = toScreenY(path[index++]);17. if( currX !== lastX || currY !== lastY){18. graphics.lineTo(currX, currY);19. lastX = currX;20. lastY = currY; 21. }22. }23. }24.}

1.override protected function updateLayer():void{2. const model:Model = Model.instance;3. graphics.clear();4. graphics.lineStyle(1, 0);5. model.streetGrid.search(map.extent, streetHandler);6.}

8.private function streetHandler(street:Street, data:Object = null):void{9. for each(var path:Array in street.shpPolyline.paths){10. var index:int = 0;11. var lastX:Number = toScreenX(path[index++]);12. var lastY:Number = toScreenY(path[index++]);13. graphics.moveTo(lastX, lastY);14. while(index < path.length){15. var currX:Number = toScreenX(path[index++]);16. var currY:Number = toScreenY(path[index++]);17. if( currX !== lastX || currY !== lastY){18. graphics.lineTo(currX, currY);19. lastX = currX;20. lastY = currY; 21. }22. }23. }24.}

1.override protected function updateLayer():void{2. const model:Model = Model.instance;3. graphics.clear();4. graphics.lineStyle(1, 0);5. model.streetGrid.search(map.extent, streetHandler);6.}

8.private function streetHandler(street:Street, data:Object = null):void{9. for each(var path:Array in street.shpPolyline.paths){10. var index:int = 0;11. var lastX:Number = toScreenX(path[index++]);12. var lastY:Number = toScreenY(path[index++]);13. graphics.moveTo(lastX, lastY);14. while(index < path.length){15. var currX:Number = toScreenX(path[index++]);16. var currY:Number = toScreenY(path[index++]);17. if( currX !== lastX || currY !== lastY){18. graphics.lineTo(currX, currY);19. lastX = currX;20. lastY = currY; 21. }22. }23. }24.}

1.override protected function updateLayer():void{2. const model:Model = Model.instance;3. graphics.clear();4. graphics.lineStyle(1, 0);5. model.streetGrid.search(map.extent, streetHandler);6.}

8.private function streetHandler(street:Street, data:Object = null):void{9. for each(var path:Array in street.shpPolyline.paths){10. var index:int = 0;11. var lastX:Number = toScreenX(path[index++]);12. var lastY:Number = toScreenY(path[index++]);13. graphics.moveTo(lastX, lastY);14. while(index < path.length){15. var currX:Number = toScreenX(path[index++]);16. var currY:Number = toScreenY(path[index++]);17. if( currX !== lastX || currY !== lastY){18. graphics.lineTo(currX, currY);19. lastX = currX;20. lastY = currY; 21. }22. }23. }24.}

DemoStreetTrace

When Will I Use This ?

top related