protected function drawTool_drawEndHandler(event:DrawEvent):void { // reset after finished drawing a feature myDrawTool.deactivate(); drawbutton.selected= false; var polygon:Polygon = event.graphic.geometry as Polygon; if (GeometryUtil.polygonSelfIntersecting(polygon)) { // simplify the drawn polygon // Note: As of version 2.0, GeometryService input is geometries (instead of graphics). geometryService.simplify([ polygon ]); } else { //addPolygonToMap(polygon); projectPolygon(polygon); myDrawTool.deactivate(); } } private function geometryService_simplifyCompleteHandler(event:GeometryServiceEvent):void { // Note: GeometryService returns geometries instead of graphics as of Flex API 2.0 if (event.result) { var polygon:Polygon = (event.result as Array)[0]; // we only draw one area at a time projectPolygon(polygon); } } private function projectPolygon(polygon:Polygon):void { // project to 54034 (World_Cylindrical_Equal_Area) const projectParameters:ProjectParameters = new ProjectParameters; projectParameters.geometries = [ polygon ]; projectParameters.outSpatialReference = new SpatialReference(54034); geometryService.project(projectParameters, new AsyncResponder(project_resultHandler, project_faultHandler, polygon)); } private function project_resultHandler(result:Object, token:Object = null):void { if (result) { var polygon:Geometry = (result as Array)[0]; var areasAndLengthsParameters:AreasAndLengthsParameters = new AreasAndLengthsParameters(); areasAndLengthsParameters.areaUnit = GeometryService.UNIT_ACRES; areasAndLengthsParameters.polygons = [ polygon ]; geometryService.areasAndLengths(areasAndLengthsParameters, new AsyncResponder(areasAndLengths_resultHandler, areasAndLengths_faultHandler, token)); // project to 54034 (World_Cylindrical_Equal_Area) } } private function project_faultHandler(fault:Fault, token:Object = null):void { Alert.show(fault.faultString + "\n\n" + fault.faultDetail, "project Fault " + fault.faultCode); } private function areasAndLengths_resultHandler(result:AreasAndLengthsResult, token:Object = null):void { const area:String = myNumberFormatter.format(result.areas[0]); geometryService.labelPoints([ token ], new AsyncResponder(labelPoints_resultHandler, labelPoints_faultHandler, area + " acres")); } private function areasAndLengths_faultHandler(fault:Fault, token:Object = null):void { Alert.show(fault.faultString + "\n\n" + fault.faultDetail, "areasAndLengths Fault " + fault.faultCode); } private function labelPoints_resultHandler(result:Object, token:Object = null):void { for each (var geom:Geometry in result) { var g:Graphic = new Graphic(); g.geometry = geom; var tf:TextFormat = new TextFormat(null, 16, 0x41423A); g.symbol = new TextSymbol(String(token), null, 0xFFFFFF, 1, true, 0x41423A, true, 0xD8DACC, "middle", 0, 0, 0, tf); myGraphicsLayer.add(g); } } private function labelPoints_faultHandler(fault:Fault, token:Object = null):void { Alert.show(fault.faultString + "\n\n" + fault.faultDetail, "labelPoints Fault " + fault.faultCode); } private function myMap_mapMouseDownHandler(event:MapMouseEvent):void { event.currentTarget.addEventListener(MouseEvent.MOUSE_MOVE, map_mouseMoveHandler); event.currentTarget.addEventListener(MouseEvent.MOUSE_UP, map_mouseUpHandler); } private function map_mouseMoveHandler(event:MouseEvent):void { event.currentTarget.removeEventListener(MouseEvent.MOUSE_MOVE, map_mouseMoveHandler); event.currentTarget.removeEventListener(MouseEvent.MOUSE_UP, map_mouseUpHandler); } private var graphic:Graphic; private var lastEditGraphic:Graphic; private var lastActiveEditTypes:String; private function map_mouseUpHandler(event:MouseEvent):void { event.currentTarget.removeEventListener(MouseEvent.MOUSE_MOVE, map_mouseMoveHandler); event.currentTarget.removeEventListener(MouseEvent.MOUSE_UP, map_mouseUpHandler); if (event.target is Graphic) { graphic = Graphic(event.target); if (lastEditGraphic !== graphic) { lastEditGraphic = graphic; lastActiveEditTypes = "moveRotateScale"; // make sure move and edit vertices is the 1st mode } if (graphic.geometry is Polyline || graphic.geometry is Polygon) { if (lastActiveEditTypes == "moveEditVertices") { lastActiveEditTypes = "moveRotateScale"; myEditTool.activate(EditTool.MOVE | EditTool.SCALE | EditTool.ROTATE, [ graphic ]); } else { lastActiveEditTypes = "moveEditVertices"; myEditTool.activate(EditTool.MOVE | EditTool.EDIT_VERTICES, [ graphic ]); } } else if (graphic.geometry is Extent) { myEditTool.activate(EditTool.MOVE | EditTool.SCALE, [ graphic ]); } else if (graphic.graphicsLayer == myGraphicsLayer) { myEditTool.activate(EditTool.MOVE | EditTool.EDIT_VERTICES, [ graphic ]); } } else { myEditTool.deactivate(); lastActiveEditTypes = "moveRotateScale"; // make sure move and edit vertices is the 1st mode } }
Solved! Go to Solution.
/** * Adds event listeners to the current edit tool */ private function addEditToolEventListeners():void { editTool.addEventListener(EditEvent.GHOST_VERTEX_MOUSE_DOWN, handleHideMeasureLabel); editTool.addEventListener(EditEvent.CONTEXT_MENU_SELECT, handleHideMeasureLabel); editTool.addEventListener(EditEvent.VERTEX_MOVE_START, handleHideMeasureLabel); editTool.addEventListener(EditEvent.GRAPHICS_MOVE_START, handleHideMeasureLabel); editTool.addEventListener(EditEvent.GRAPHIC_ROTATE_START, handleHideMeasureLabel); editTool.addEventListener(EditEvent.GRAPHIC_SCALE_START, handleHideMeasureLabel); editTool.addEventListener(EditEvent.VERTEX_ADD, editTool_vertexAddDeleteHandler); editTool.addEventListener(EditEvent.VERTEX_DELETE, editTool_vertexAddDeleteHandler); editTool.addEventListener(EditEvent.VERTEX_MOVE_STOP, editTool_vertexMoveStopHandler); editTool.addEventListener(EditEvent.GRAPHICS_MOVE_STOP, editTool_graphicsMoveStopHandler); editTool.addEventListener(EditEvent.GRAPHIC_ROTATE_STOP, editTool_graphicRotateStopHandler); editTool.addEventListener(EditEvent.GRAPHIC_SCALE_STOP, editTool_graphicScaleStopHandler); } /** * Handle graphic move complete */ private function editTool_graphicsMoveStopHandler(event:EditEvent):void { handleEditEvent(event); } /** * Handle graphic editing */ private function handleEditEvent(event:EditEvent):void { var graphic:Graphic = event.graphic; if (!graphic && event.graphics) { graphic = event.graphics[0]; } if (map.wrapAround180) { normalizeGraphicGeometry(graphic); } else if (measurementLabelExists) { recalculate(graphic); } } /** * Adds event listeners to the current edit tool */ private function addEditToolEventListeners():void { editTool.addEventListener(EditEvent.GHOST_VERTEX_MOUSE_DOWN, handleHideMeasureLabel); editTool.addEventListener(EditEvent.CONTEXT_MENU_SELECT, handleHideMeasureLabel); editTool.addEventListener(EditEvent.VERTEX_MOVE_START, handleHideMeasureLabel); editTool.addEventListener(EditEvent.GRAPHICS_MOVE_START, handleHideMeasureLabel); editTool.addEventListener(EditEvent.GRAPHIC_ROTATE_START, handleHideMeasureLabel); editTool.addEventListener(EditEvent.GRAPHIC_SCALE_START, handleHideMeasureLabel); editTool.addEventListener(EditEvent.VERTEX_ADD, editTool_vertexAddDeleteHandler); editTool.addEventListener(EditEvent.VERTEX_DELETE, editTool_vertexAddDeleteHandler); editTool.addEventListener(EditEvent.VERTEX_MOVE_STOP, editTool_vertexMoveStopHandler); editTool.addEventListener(EditEvent.GRAPHICS_MOVE_STOP, editTool_graphicsMoveStopHandler); editTool.addEventListener(EditEvent.GRAPHIC_ROTATE_STOP, editTool_graphicRotateStopHandler); editTool.addEventListener(EditEvent.GRAPHIC_SCALE_STOP, editTool_graphicScaleStopHandler); } /** * Handle graphic move complete */ private function editTool_graphicsMoveStopHandler(event:EditEvent):void { handleEditEvent(event); } /** * Handle graphic editing */ private function handleEditEvent(event:EditEvent):void { var graphic:Graphic = event.graphic; if (!graphic && event.graphics) { graphic = event.graphics[0]; } if (map.wrapAround180) { normalizeGraphicGeometry(graphic); } else if (measurementLabelExists) { recalculate(graphic); } }
/**
* Update the graphic's measurement label and positioning
*/
private function recalculate(graphic:Graphic):void
{
var geom:Geometry = graphic.geometry;
measureGeometry(geom, graphic);
}
/**
* Depending on the geometry's spatial reference, calculate measurement or
* create a new geometry service project call
*/
private function measureGeometry(geom:Geometry, graphic:Graphic):void
{
var wkid:Number = geom.spatialReference.wkid;
if ((wkid == EPSG_GEOGRAPHIC) || (isWebMercator(wkid)))
{
calculateMeasurements(geom, graphic);
}
else
{
var geographicSpatialReference:SpatialReference = new SpatialReference(EPSG_GEOGRAPHIC);
const projectParameters:ProjectParameters = new ProjectParameters;
projectParameters.geometries = [ geom ];
projectParameters.outSpatialReference = geographicSpatialReference;
geometryService.project(projectParameters, new AsyncResponder(project_resultHandler, project_faultHandler, geom));
}
}
/**
* Determine if specified spatial reference is web mercator
*/
private function isWebMercator(wkid:Number):Boolean
{
return wkid == 102100 || wkid == 3857 || wkid == 102113;
}
/**
* Calculate geometry measurements depending on geometry type
*/
private function calculateMeasurements(geom:Geometry, graphic:Graphic):void
{
(graphic.attributes as GraphicPropertiesVO).measurementGeometry = geom;
switch (geom.type)
{
case Geometry.POLYLINE:
{
var polyline:Polyline = Polyline(geom);
calculatePolylineLengths(polyline, graphic);
break;
}
case Geometry.POLYGON:
{
var polygon:Polygon = Polygon(geom);
calculatePolygonAreasAndLengths(polygon, graphic);
break;
}
case Geometry.EXTENT:
{
var extent:Extent = Extent(geom);
calculatePolygonAreasAndLengths(extent.toPolygon(), graphic); //convert it to polygon for measurement
break;
}
case Geometry.MAPPOINT:
{
var mapPoint:MapPoint = MapPoint(geom);
calculateMapPointCoordinates(mapPoint, graphic);
}
}
}
/**
* Calculate polyline lengths
*/
private function calculatePolylineLengths(polyline:Polyline, graphic:Graphic):void
{
var polylineToMeasure:Polyline
var wkid:Number = polyline.spatialReference.wkid;
if (wkid == EPSG_GEOGRAPHIC)
{
polylineToMeasure = polyline;
}
else if (isWebMercator(wkid))
{
polylineToMeasure = WebMercatorUtil.webMercatorToGeographic(polyline) as Polyline;
}
var lengths:Array = GeometryUtil.geodesicLengths([ polylineToMeasure ], Units.METERS);
var length:Number = lengths[0] * distanceConversion;
var label:String = createLengthsLabel(length, distanceAbbr);
addDrawLabel(label, graphic);
}
/**
* Create lengths label
*/
private function createLengthsLabel(length:Number, lengthAbbrev:String):String
{
return lengthLabel + " " + numFormatter.format(length) + " " + lengthAbbrev;
}
/**
* Calculate map point coordinates
*/
private function calculateMapPointCoordinates(point:MapPoint, graphic:Graphic):void
{
var label:String = createPointMeasurementLabel(point);
addDrawLabel(label, graphic);
}
/**
* Formats the length measurement into a string to displayed on the map.
* <p>
* <b>Parameters</b><br/>
* <ul>
* <li><i>point [MapPoint]: </i>The map point that represents the location whose coordinates should be labelled.</li>
* </ul>
* </p>
*/
private function createPointMeasurementLabel(point:MapPoint):String
{
var wkid:Number = point.spatialReference.wkid;
if (wkid == EPSG_GEOGRAPHIC)
{
numFormatter.precision = 6;
return "Latitude: " + numFormatter.format(point.y) +
"\n" + "Longitude: " + numFormatter.format(point.x);
}
else
{
numFormatter.precision = 0;
return "X: " + numFormatter.format(point.x) +
"\n" + "Y: " + numFormatter.format(point.y);
}
}
/**
* Calculate Polygon areas and lengths
*/
private function calculatePolygonAreasAndLengths(polygon:Polygon, graphic:Graphic):void
{
var polygonToMeasure:Polygon;
var wkid:Number = polygon.spatialReference.wkid;
if (wkid == EPSG_GEOGRAPHIC)
{
polygonToMeasure = polygon;
}
else if (isWebMercator(wkid))
{
polygonToMeasure = WebMercatorUtil.webMercatorToGeographic(polygon) as Polygon;
}
var lengths:Array = GeometryUtil.geodesicLengths([ new Polyline(polygonToMeasure.rings)], Units.METERS);
var areas:Array = GeometryUtil.geodesicAreas([ polygonToMeasure ], Units.SQUARE_METERS);
var area:Number = areas[0] * areaConversion;
var length:Number = lengths[0] * distanceConversion;
var label:String = createAreasAndLengthsLabel(area, areaAbbr, length, distanceAbbr);
addDrawLabel(label, graphic);
}
/**
* Create area and lengths label
*/
private function createAreasAndLengthsLabel(area:Number, areaAbbrev:String, length:Number, lengthAbbrev:String):String
{
return areaLabel + " " + numFormatter.format(area) + " " + areaAbbrev +
"\n" + perimeterLabel + " " + numFormatter.format(length) + " " + lengthAbbrev;
}
/**
* Determine the ideal positioning of the measurement label
*/
private function getMeasureLabelPosition(geom:Geometry):MapPoint
{
var measurePt:MapPoint = null;
switch (geom.type)
{
case Geometry.POLYLINE:
{
var polyline:Polyline = geom as Polyline;
var polylineExtent:Extent;
if (polyline.paths.length == 1)
{
polylineExtent = polyline.extent;
}
else
{
// Multiple paths, hence show the measurement label at the center of first path
var tempPolyline:Polyline = new Polyline;
tempPolyline.paths = [ polyline.paths[0]];
polylineExtent = tempPolyline.extent;
}
measurePt = polylineExtent.center;
break;
}
case Geometry.POLYGON:
{
var polygon:Polygon = geom as Polygon;
var polygonExtent:Extent;
if (polygon.rings.length == 1)
{
polygonExtent = polygon.extent;
}
else
{
// Multiple rings, hence show the measurement label at the center of first ring
var tempPolygon:Polygon = new Polygon;
tempPolygon.rings = [ polygon.rings[0]];
polygonExtent = tempPolygon.extent;
}
measurePt = polygonExtent.center;
break;
}
case Geometry.EXTENT:
{
measurePt = geom.extent.center;
break;
}
case Geometry.MAPPOINT:
{
var screenPoint:Point = map.toScreen(geom as MapPoint);
screenPoint.x = screenPoint.x + 10;
screenPoint.y = screenPoint.y - 20;
measurePt = map.toMap(screenPoint);
}
}
return measurePt;
}
/**
* Create and place the measurement label
*/
private function addDrawLabel(label:String, graphic:Graphic):void
{
// create a text symbol
var txtSym:TextSymbol = new TextSymbol(label);
txtSym.yoffset = 8;
var txtFormat:TextFormat = new TextFormat("Arial", 12, 0x000000, true); // black label
txtSym.textFormat = txtFormat;
// remove the current graphic's measurement label
labelsLayer.remove(getMeasurementGraphic(graphic));
// create the new measurement graphic label
var gra:Graphic = new Graphic();
gra.name = graphic.id;
gra.geometry = getMeasureLabelPosition(graphic.geometry);
gra.symbol = txtSym;
gra.mouseEnabled = false;
gra.mouseChildren = false;
gra.filters = [ measurementBorderFilter ];
labelsLayer.add(gra);
// associate the measurement label text to the editing or previous graphic's attributes
(graphic.attributes as GraphicPropertiesVO).measurementLabel = label;
// update the graphic context menu with the ability to hide or show the measurement label
graphic_updateContextMenu(graphic);
}