DockWindow.cs
// Copyright 2011 ESRI // // All rights reserved under the copyright laws of the United States // and applicable international laws, treaties, and conventions. // // You may freely redistribute and use this sample code, with or // without modification, provided you include the original copyright // notice and use restrictions. // // See the use restrictions. // // Copyright 2010 ESRI // // All rights reserved under the copyright laws of the United States // and applicable international laws, treaties, and conventions. // // You may freely redistribute and use this sample code, with or // without modification, provided you include the original copyright // notice and use restrictions. // // See the use restrictions at <your ArcGIS Explorer install location>/DeveloperKit/userestrictions.txt. // using System; using System.Collections.Generic; using System.ComponentModel; using System.Drawing; using System.Data; using System.Linq; using System.Text; using System.Windows.Forms; using ESRI.ArcGISExplorer; using ESRI.ArcGISExplorer.Application; using ESRI.ArcGISExplorer.Mapping; using ESRI.ArcGISExplorer.Geometry; using ESRI.ArcGISExplorer.Data; using ESRI.ArcGISExplorer.Threading; namespace QueryDemographicsCS { public partial class DockWindow : ESRI.ArcGISExplorer.Application.DockWindow { private MapDisplay _mapDisp = ESRI.ArcGISExplorer.Application.Application.ActiveMapDisplay; public DockWindow() { InitializeComponent(); } private void txtLocation_DragDrop(object sender, DragEventArgs e) { //Make sure we have a treenode being dropped if (!e.Data.GetDataPresent(typeof(TreeNode))) return; //From the node, grab the text to display and then save the note for use later TreeNode node = ((TreeNode)e.Data.GetData(typeof(TreeNode))).Clone() as TreeNode; txtLocation.Text = node.Text; txtLocation.Tag = node.Tag; } private void txtLocation_DragOver(object sender, DragEventArgs e) { e.Effect = DragDropEffects.None; //make sure that we only allow point data from notes TreeNode node = ((TreeNode)e.Data.GetData(typeof(TreeNode))).Clone() as TreeNode; ESRI.ArcGISExplorer.Mapping.Note result = node.Tag as Note; if (result != null) { if (result.Graphic.Geometry.GetType() == typeof(ESRI.ArcGISExplorer.Geometry.Point)) { e.Effect = DragDropEffects.Move; return; } } return; } private void btnExecute_Click(object sender, EventArgs e) { //Make sure we have values in the location and distance boxes. if (txtDistance.Text == "" || txtLocation.Text == "") return; //Make sure the value in the distance box is numeric if (!IsNumeric(txtDistance.Text)) { MessageBox.Show("Distance value must be numeric!!", "Bad Value"); return; } //Make sure distance value is less than 10 miles if (System.Convert.ToDouble(txtDistance.Text) > 10) { MessageBox.Show("Distance value must be less than 10 miles!!", "Bad Value"); return; } //Get the point geometry out of the tag on the Location textbox ESRI.ArcGISExplorer.Geometry.Point queryPt = null; if (txtLocation.Tag.GetType() == typeof(Note)) { ESRI.ArcGISExplorer.Mapping.Note result = txtLocation.Tag as Note; queryPt = result.Graphic.Geometry as ESRI.ArcGISExplorer.Geometry.Point; } else { queryPt = txtLocation.Tag as ESRI.ArcGISExplorer.Geometry.Point; } if (queryPt == null) return; //Execute the query against the Demographics data QueryDemographics(queryPt, System.Convert.ToDouble(txtDistance.Text)); } private void QueryDemographics(ESRI.ArcGISExplorer.Geometry.Point queryPt, double dist) { //Open up ProgressHelper to show are progress. ProgressHelper help = new ProgressHelper("Query Progress", "Calculating Demographics in the area", "Forming query polygon ..."); help.Show(); List<ESRI.ArcGISExplorer.Geometry.Point> pts = new List<ESRI.ArcGISExplorer.Geometry.Point>(); pts.Add(GeometryOperations.Move(queryPt, dist, dist, Unit.Linear.MilesStatute) as ESRI.ArcGISExplorer.Geometry.Point); pts.Add(GeometryOperations.Move(queryPt, dist, (dist * -1), Unit.Linear.MilesStatute) as ESRI.ArcGISExplorer.Geometry.Point); pts.Add(GeometryOperations.Move(queryPt, (dist * -1), (dist * -1), Unit.Linear.MilesStatute) as ESRI.ArcGISExplorer.Geometry.Point); pts.Add(GeometryOperations.Move(queryPt, (dist * -1), dist, Unit.Linear.MilesStatute) as ESRI.ArcGISExplorer.Geometry.Point); Polygon searchPoly = new Polygon(pts, queryPt.CoordinateSystem); searchPoly.Close(); searchPoly = (Polygon)GeometryOperations.Project(searchPoly, CoordinateSystem.GeographicCoordinateSystems.NorthAmerica.NAD1983); help.UpdateMessage("Executing SOAP call to ArcGIS Online ..."); ////Make the connection to the server we will use for retrieving demographic information censusServer.ESRI_Census_USA_MapServer mapServer = new censusServer.ESRI_Census_USA_MapServer(); mapServer.Url = "http://sampleserver1.arcgisonline.com/ArcGIS/services/Demographics/ESRI_Census_USA/MapServer"; //Call the Census service to calculate the demographic information for the polygon. censusServer.SpatialFilter spf = new censusServer.SpatialFilter(); spf.FilterGeometry = SoapConverter.GeometryToSoap<Polygon,censusServer.PolygonN>(searchPoly); spf.SpatialRel = censusServer.esriSpatialRelEnum.esriSpatialRelIntersects; spf.SubFields = "AGE_UNDER5, AGE_5_17, AGE_18_21, AGE_22_29, AGE_30_39, AGE_40_49, AGE_50_64, AGE_65_UP, MALES, FEMALES"; string temp = mapServer.GetDefaultMapName(); censusServer.RecordSet recs = mapServer.QueryFeatureData("Layers", 1, spf); help.UpdateMessage("Summing results of query ..."); //Loop through the records that were returned and tally up the demographic data int males = 0; int females = 0; int age_u5 = 0; int age_5_17 = 0; int age_18_21 = 0; int age_22_29 = 0; int age_30_39 = 0; int age_40_49 = 0; int age_50_64 = 0; int age_65_up = 0; for (int j = 0; j < recs.Records.Length; j++) { censusServer.Record censusRec = recs.Records[j]; males += System.Convert.ToInt16(censusRec.Values[9]); females += System.Convert.ToInt16(censusRec.Values[10]); age_u5 += System.Convert.ToInt16(censusRec.Values[1]); age_5_17 += System.Convert.ToInt16(censusRec.Values[2]); age_18_21 += System.Convert.ToInt16(censusRec.Values[3]); age_22_29 += System.Convert.ToInt16(censusRec.Values[4]); age_30_39 += System.Convert.ToInt16(censusRec.Values[5]); age_40_49 += System.Convert.ToInt16(censusRec.Values[6]); age_50_64 += System.Convert.ToInt16(censusRec.Values[7]); age_65_up += System.Convert.ToInt16(censusRec.Values[8]); } int genderTotal = males + females; int ageTotal = age_u5 + age_5_17 + age_18_21 + age_22_29 + age_30_39 + age_40_49 + age_50_64 + age_65_up; double dMales = (System.Convert.ToDouble(males) / System.Convert.ToDouble(genderTotal)) * 100; double dFemales = (System.Convert.ToDouble(females) / System.Convert.ToDouble(genderTotal)) * 100; double dage_u5 = (System.Convert.ToDouble(age_u5) / System.Convert.ToDouble(ageTotal)) * 100; double dage_5_17 = (System.Convert.ToDouble(age_5_17) / System.Convert.ToDouble(ageTotal)) * 100; double dage_18_21 = (System.Convert.ToDouble(age_18_21) / System.Convert.ToDouble(ageTotal)) * 100; double dage_22_29 = (System.Convert.ToDouble(age_22_29) / System.Convert.ToDouble(ageTotal)) * 100; double dage_30_39 = (System.Convert.ToDouble(age_30_39) / System.Convert.ToDouble(ageTotal)) * 100; double dage_40_49 = (System.Convert.ToDouble(age_40_49) / System.Convert.ToDouble(ageTotal)) * 100; double dage_50_64 = (System.Convert.ToDouble(age_50_64) / System.Convert.ToDouble(ageTotal)) * 100; double dage_65_up = (System.Convert.ToDouble(age_65_up) / System.Convert.ToDouble(ageTotal)) * 100; help.UpdateMessage("Creating popup message ..."); //Figure out the percentage information for males and females, then generate the popup using //the Google chart api. string perc = "Males(" + dMales.ToString("###.#") + "%)|Females(" + dFemales.ToString("###.#") + "%)"; string popup = "<b><font size='4'>" + "Gender</font></b>" + "<br><img src=\"" + "http://chart.apis.google.com/chart?cht=p3&chd=t:" + dMales.ToString() + "," + dFemales.ToString() + "&chs=350x100&chl=" + perc + "\" />"; popup += "<br><br><b><font size='4'>" + "Age</font></b>" + "<br><img src=\"" + "http://chart.apis.google.com/chart?cht=p3&chd=t:" + dage_u5.ToString() + "," + dage_5_17.ToString(); popup += "," + dage_18_21.ToString() + "," + dage_22_29.ToString() + "," + dage_30_39.ToString() + "," + dage_40_49.ToString() + "," + dage_50_64 + "," + dage_65_up + "&chs=350x100&chl=Under 5|5 to 17|18 to 21|22 to 29|30 to 39|40 to 49|50 to 64|over 64" + "\" />"; //Add the polygon to the map as a note or graphic depending on the checkbox Graphic searchGraphic = new Graphic(searchPoly, Symbol.CreateFill(Color.Orange, Color.Black)); searchGraphic.Tag = "demographic query polygon"; if (chkResult.Checked) { Note newNote = new Note(txtDistance.Text + " mile demographic query", searchGraphic); newNote.Popup.Content = popup; _mapDisp.Map.ChildItems.Add(newNote); } else { RemovePreviousGraphic(); _mapDisp.Graphics.Add(searchGraphic); btnRemove.Enabled = true; } //Check extent and make sure we aren't zoomed in too far to show all of search shape Envelope env = GeometryOperations.Scale(searchPoly.GetEnvelope(),1.25) as Envelope; if (_mapDisp.Extent.Height < env.Height || _mapDisp.Extent.Width < env.Width) _mapDisp.ZoomTo(env); //Whether we are adding a graphic or a note, we can still show the popup information (it //just won't be stored for the graphic). ESRI.ArcGISExplorer.Application.Application.ActiveMapDisplay.HidePopups(true); Popup tempPopup = new Popup(ESRI.ArcGISExplorer.Application.Application.ActiveMapDisplay, popup, "Demographic information"); tempPopup.Activate(); help.Close(); return; } private void RemovePreviousGraphic() { if (_mapDisp.Graphics.Count == 0) return; //Loop through the graphics in the map and remove the first one found with the demographic query tag GraphicCollection graphs = _mapDisp.Graphics; foreach (Graphic graph in graphs) { if ((string)graph.Tag == "demographic query polygon") { _mapDisp.Graphics.Remove(graph); return; } } } // IsNumeric Function static bool IsNumeric(object Expression) { // Variable to collect the Return value of the TryParse method. bool isNum; // Define variable to collect out parameter of the TryParse method. If the conversion fails, the out parameter is zero. double retNum; // The TryParse method converts a string in a specified style and culture-specific format to its double-precision floating point number equivalent. // The TryParse method does not generate an exception if the conversion fails. If the conversion passes, True is returned. If it does not, False is returned. isNum = Double.TryParse(Convert.ToString(Expression), System.Globalization.NumberStyles.Any, System.Globalization.NumberFormatInfo.InvariantInfo, out retNum); return isNum; } private void btnRemove_Click(object sender, EventArgs e) { //Call the routine to search for a demographic query graphic RemovePreviousGraphic(); btnRemove.Enabled = false; } private void btnLocate_Click(object sender, EventArgs e) { //Capture a point from the map ESRI.ArcGISExplorer.Geometry.Point loc = _mapDisp.TrackPoint(); if (loc == null) return; //If we got a point, then add some text to the location box and the point as the tag txtLocation.Text = loc.Y.ToString("###.##") + " " + loc.X.ToString("###.##"); txtLocation.Tag = loc as object; } } }