Measure.cs
上传用户:huazai0421
上传日期:2008-05-30
资源大小:405k
文件大小:15k
源码类别:

SilverLight

开发平台:

C#

  1. using System;
  2. using System.Collections.Generic;
  3. using System.Windows;
  4. using System.Windows.Input;
  5. using System.Windows.Media;
  6. using ESRI.ArcGIS.Client;
  7. using ESRI.ArcGIS.Client.Geometry;
  8. using ESRI.ArcGIS.Client.Symbols;
  9. using ESRI.ArcGIS.Samples.Extensions;
  10. namespace ESRI.ArcGIS.Samples
  11. {
  12.     public class Measure
  13.     {
  14.         private bool isActivated;
  15.         int lineCount = 0;
  16.         int _graphicCount = 0;
  17.         double totalLength = 0;
  18.         double _segmentLength = 0;
  19.         double _tempTotalLength = 0;
  20.         MapPoint originPoint;
  21.         MapPoint endPoint;
  22.         ESRI.ArcGIS.Client.Geometry.PointCollection _points;
  23.         Point lastClick;
  24.         SimpleMarkerSymbol markerSymbol;
  25.         SimpleMarkerSymbol endSymbol;
  26.         bool _isMeasuring = false;
  27.         List<double> _lengths;
  28. public Measure()
  29. {
  30. //Set up defaults
  31. this.MapUnits = ScaleBarUnit.DecimalDegrees;
  32. this.NumberDecimals = 2;
  33. this.DistanceUnits = ScaleBarUnit.Kilometers;
  34. this.AreaUnits = AreaUnit.SqKm;
  35. this.Type = MeasureType.Distance;
  36. GraphicsLayer = new GraphicsLayer();
  37. LineSymbol = new SimpleLineSymbol()
  38. {
  39. Color = new SolidColorBrush(Color.FromArgb(255, 255, 0, 0)),
  40. Width = 2,
  41. Style = SimpleLineSymbol.LineStyle.Solid
  42. };
  43. FillSymbol = new SimpleFillSymbol()
  44. {
  45. Fill = new SolidColorBrush(Color.FromArgb(0x22, 255, 255, 255)),
  46. BorderBrush = new SolidColorBrush(Color.FromArgb(255, 255, 0, 0)),
  47. BorderThickness = 2
  48. };
  49. markerSymbol = new SimpleMarkerSymbol()
  50. {
  51. Color = new SolidColorBrush(Color.FromArgb(0x66, 255, 0, 0)),
  52. Size = 5,
  53. Style = SimpleMarkerSymbol.SimpleMarkerStyle.Circle
  54. };
  55. endSymbol = new SimpleMarkerSymbol()
  56. {
  57. Color = new SolidColorBrush(Color.FromArgb(0, 255, 255, 255)),
  58. Size = 5,
  59. Style = SimpleMarkerSymbol.SimpleMarkerStyle.Circle
  60. };
  61. _lengths = new List<double>();
  62. _points = new ESRI.ArcGIS.Client.Geometry.PointCollection();
  63. }
  64. #region Properties
  65. public ScaleBarUnit MapUnits { get; set; }
  66. public double NumberDecimals { get; set; }
  67. public Map Map { get; set; }
  68. private GraphicsLayer GraphicsLayer { get; set; }
  69. public MeasureType Type { get; set; }
  70. public double TotalLength { get; set; }
  71. public double TotalArea { get; set; }
  72. public AreaUnit AreaUnits { get; set; }
  73. public ScaleBarUnit DistanceUnits { get; set; }
  74. public FillSymbol FillSymbol { get; set; }
  75. public LineSymbol LineSymbol { get; set; }
  76.         public bool IsActivated
  77.         {
  78.             get { return isActivated; }
  79.             set
  80.             {
  81.                 if (isActivated != value)
  82.                 {
  83.                     isActivated = value;
  84.                     if (value)
  85.                     {
  86.                         Map.MouseMove += map_MouseMove;
  87. Map.MouseLeftButtonDown += map_MouseLeftButtonDown;
  88. Map.Layers.Add(GraphicsLayer);
  89. Map.Cursor = Cursors.Hand;
  90.                     }
  91.                     else
  92.                     {
  93. Map.Cursor = Cursors.Arrow;
  94. Map.MouseMove -= map_MouseMove;
  95. Map.MouseLeftButtonDown -= map_MouseLeftButtonDown;
  96. Map.Layers.Remove(GraphicsLayer);
  97.                         ResetValues();
  98.                     }
  99.                 }
  100.             }
  101. }
  102. #endregion
  103. public void ResetValues()
  104.         {
  105.             _isMeasuring = false;
  106.             originPoint = null;
  107.             endPoint = null;
  108.             lineCount = 0;
  109.             _points = new ESRI.ArcGIS.Client.Geometry.PointCollection();
  110.             _lengths = new List<double>();
  111.             totalLength = 0;
  112.             _tempTotalLength = 0;
  113.             _segmentLength = 0;
  114.         }
  115.         private void map_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
  116.         {
  117.             e.Handled = true;
  118.             Point pt = e.GetPosition(null);
  119.             if (Math.Abs(pt.X - lastClick.X) < 2 && Math.Abs(pt.Y - lastClick.Y) < 2)
  120.             {
  121.                 int lastone = GraphicsLayer.Graphics.Count - 1;
  122.                 GraphicsLayer.Graphics.RemoveAt(lastone);
  123.                 if (Type == MeasureType.Area)
  124.                 {
  125.                     ESRI.ArcGIS.Client.Geometry.Polygon poly1 = GraphicsLayer.Graphics[0].Geometry as ESRI.ArcGIS.Client.Geometry.Polygon;
  126.                     MapPoint firstpoint = poly1.Rings[0][0];
  127.                     poly1.Rings[0].Add(new MapPoint(firstpoint.X, firstpoint.Y));
  128.                     GraphicsLayer.Graphics[0].Geometry = poly1;
  129.                 }
  130.                 ResetValues();
  131.             }
  132.             else
  133.             {
  134.                 if (_points.Count == 0)
  135.                 {
  136.                     GraphicsLayer.Graphics.Clear();
  137.                     if (Type == MeasureType.Area)
  138.                     {
  139.                         Graphic areaGraphic = new Graphic()
  140.                         {
  141.                             Symbol = FillSymbol
  142.                         };
  143.                         GraphicsLayer.Graphics.Add(areaGraphic);
  144.                         Graphic areaTotalGraphic = new Graphic()
  145.                         {
  146.                             Symbol = new RotatingTextSymbol()
  147.                         };
  148.                         GraphicsLayer.Graphics.Add(areaTotalGraphic);
  149.                     }
  150.                 }
  151. originPoint = Map.ScreenToMap(e.GetPosition(Map));
  152. endPoint = Map.ScreenToMap(e.GetPosition(Map));
  153.                 ESRI.ArcGIS.Client.Geometry.Polyline line = new ESRI.ArcGIS.Client.Geometry.Polyline();
  154.                 ESRI.ArcGIS.Client.Geometry.PointCollection points = new ESRI.ArcGIS.Client.Geometry.PointCollection();
  155.                 points.Add(originPoint);
  156.                 points.Add(endPoint);
  157.                 line.Paths.Add(points);
  158.                 _points.Add(endPoint);
  159.                 if (_points.Count == 2)
  160.                     _points.Add(endPoint);
  161.                 lineCount++;
  162. if (Type == MeasureType.Area && _points.Count > 2)
  163.                 {
  164.                     ESRI.ArcGIS.Client.Geometry.Polygon poly = new ESRI.ArcGIS.Client.Geometry.Polygon();
  165.                     poly.Rings.Add(_points);
  166.                     GraphicsLayer.Graphics[0].Geometry = poly;
  167.                 }
  168. if (Type == MeasureType.Distance)
  169.                 {
  170.                     Graphic totalTextGraphic = new Graphic()
  171.                     {
  172.                         Geometry = originPoint,
  173.                         Symbol = new RotatingTextSymbol()
  174.                     };
  175.                     GraphicsLayer.Graphics.Add(totalTextGraphic);
  176.                 }
  177.                 Graphic marker = new Graphic()
  178.                 {
  179.                     Geometry = endPoint,
  180.                     Symbol = markerSymbol
  181.                 };
  182.                 GraphicsLayer.Graphics.Add(marker);
  183.                 Graphic lineGraphic = new Graphic()
  184.                 {
  185.                     Geometry = line,
  186.                     Symbol = LineSymbol
  187.                 };
  188.                 GraphicsLayer.Graphics.Add(lineGraphic);
  189.                 Graphic textGraphic = new Graphic()
  190.                 {
  191.                     Geometry = endPoint,
  192.                     Symbol = new RotatingTextSymbol()
  193.                 };
  194. textGraphic.SetZIndex(1);
  195.                 GraphicsLayer.Graphics.Add(textGraphic);
  196.                 totalLength += _segmentLength;
  197.                 _lengths.Add(_segmentLength);
  198.                 _segmentLength = 0;
  199.                 _isMeasuring = true;
  200.             }
  201.             lastClick = pt;
  202.         }
  203.         private void map_MouseMove(object sender, MouseEventArgs e)
  204.         {
  205.             Map.Cursor = Cursors.Hand; 
  206.             if (originPoint != null && _isMeasuring)
  207.             {
  208.                 _graphicCount = GraphicsLayer.Graphics.Count;
  209.                 int g = _graphicCount - 1;
  210. MapPoint p = Map.ScreenToMap(e.GetPosition(Map));
  211.                 MapPoint midpoint = new MapPoint((p.X + originPoint.X) / 2, (p.Y + originPoint.Y) / 2);
  212.                 ESRI.ArcGIS.Client.Geometry.PointCollection polypoints = new ESRI.ArcGIS.Client.Geometry.PointCollection();
  213.                 ESRI.ArcGIS.Client.Geometry.Polygon poly = new ESRI.ArcGIS.Client.Geometry.Polygon();
  214. if (Type == MeasureType.Area && _points.Count > 2)
  215.                 {
  216.                     Graphic graphic = GraphicsLayer.Graphics[0];
  217.                     poly = graphic.Geometry as ESRI.ArcGIS.Client.Geometry.Polygon;
  218.                     polypoints = poly.Rings[0];
  219.                     int lastPt = polypoints.Count - 1;
  220.                     polypoints[lastPt] = p;
  221.                 }
  222.                 GraphicsLayer.Graphics[g - 2].Geometry = midpoint;
  223.                 (GraphicsLayer.Graphics[g - 1].Geometry as ESRI.ArcGIS.Client.Geometry.Polyline).Paths[0][1] = p;
  224.                 GraphicsLayer.Graphics[g].Geometry = midpoint;
  225.                 double angle = Math.Atan2((p.X - originPoint.X), (p.Y - originPoint.Y)) / Math.PI * 180 - 90;
  226.                 if (angle > 90 || angle < -90) angle -= 180;
  227.                 RotatingTextSymbol symb = GraphicsLayer.Graphics[g].Symbol as RotatingTextSymbol;
  228.                 symb.Angle = angle;
  229.                 double dist = Geodesic.GetSphericalDistance(originPoint, p);
  230.                 double distRound = RoundToSignificantDigit(dist);
  231.                 symb.Text = Convert.ToString(RoundToSignificantDigit(ConvertDistance(dist,DistanceUnits)));
  232.                 GraphicsLayer.Graphics[g].Symbol = symb;
  233.                 _segmentLength = distRound;
  234.                 _tempTotalLength = totalLength + distRound;
  235.                 RotatingTextSymbol totSym;
  236. if (Type == MeasureType.Distance)
  237.                 {
  238.                     totSym = GraphicsLayer.Graphics[0].Symbol as RotatingTextSymbol;
  239.                     totSym.Text = string.Format("Length Total:n{0} {1}", RoundToSignificantDigit(ConvertDistance(_tempTotalLength, DistanceUnits)), DistanceUnits.ToString());
  240.                     GraphicsLayer.Graphics[0].Symbol = totSym;
  241.                 }
  242.                 else
  243.                 {
  244.                     totSym = GraphicsLayer.Graphics[1].Symbol as RotatingTextSymbol;
  245.                     if (polypoints != null && polypoints.Count > 2)
  246.                     {
  247.                         double lastLen = Geodesic.GetSphericalDistance(polypoints[0], polypoints[polypoints.Count - 1]);
  248.                         poly = GraphicsLayer.Graphics[0].Geometry as ESRI.ArcGIS.Client.Geometry.Polygon;
  249.                         MapPoint anchor = poly.Extent.GetCenter();
  250.                         ESRI.ArcGIS.Client.Geometry.PointCollection temppoints = new ESRI.ArcGIS.Client.Geometry.PointCollection();
  251.                         foreach (MapPoint point in poly.Rings[0])
  252.                         {
  253.                             temppoints.Add(point);
  254.                         }
  255.                         temppoints.Add(poly.Rings[0][0]);
  256.                         ESRI.ArcGIS.Client.Geometry.PointCollection pts = ToKmMapPoint(temppoints);
  257.                         double area = GetArea(pts);
  258.                         //double area = GetArea(ToKMMapPoint(polypoints));
  259.                         totSym.Text = string.Format("Area:n{0} {1}", RoundToSignificantDigit(area), AreaUnits.ToString());
  260.                         GraphicsLayer.Graphics[1].Geometry = anchor;
  261.                         GraphicsLayer.Graphics[1].Symbol = totSym;
  262.                     }
  263.                 }
  264.             }
  265.         }
  266.         private double RoundToSignificantDigit(double value)
  267.         {
  268.             double round = Math.Floor(-Math.Log(Map.Resolution * 111.1));
  269.             if (round > 0)
  270.             {
  271.                 round = Math.Pow(10, round);
  272.                 return Math.Round(value * round) / round;
  273.             }
  274.             else { return Math.Round(value); }
  275.         }
  276.         public double ConvertDistance(double distance, ScaleBarUnit toUnits)
  277.         {
  278.             double mDistance = distance;
  279.             if (toUnits == ScaleBarUnit.Miles)
  280.             {
  281.                 mDistance = distance / 1.60934;
  282.             }
  283.             else if (toUnits == ScaleBarUnit.Feet)
  284.             {
  285.                 mDistance = distance * 3000.280839895;
  286.             }
  287.             else if (toUnits == ScaleBarUnit.Meters)
  288.             {
  289.                 mDistance = distance * 1000;
  290.             }
  291.             return mDistance;
  292.         }
  293.         private double ConvertAreaUnits(double area, AreaUnit toUnits)
  294.         {
  295.             double mArea = area;
  296.             if (toUnits == AreaUnit.Acres)
  297.                 mArea = area * 247.1054;
  298.             else if (toUnits == AreaUnit.SqMi)
  299.                 mArea = area * 0.3861;
  300.             else if (toUnits == AreaUnit.SqM)
  301.                 mArea = area * 1000000;
  302.             else if (toUnits == AreaUnit.SqFt)
  303.                 mArea = area * 10763910.41671;
  304.             else if (toUnits == AreaUnit.Hect)
  305.                 mArea = area * 0.01;
  306.             return mArea;
  307.         }
  308.         private ESRI.ArcGIS.Client.Geometry.PointCollection ToKmMapPoint(ESRI.ArcGIS.Client.Geometry.PointCollection points)
  309.         {
  310.             ESRI.ArcGIS.Client.Geometry.PointCollection pts = new ESRI.ArcGIS.Client.Geometry.PointCollection();
  311.             MapPoint pt = points[0];
  312.             if (MapUnits == ScaleBarUnit.DecimalDegrees)
  313.             {
  314.                 foreach (MapPoint point in points)
  315.                 {
  316.                     double x = Geodesic.GetSphericalDistance(point, new MapPoint(pt.X, point.Y));
  317.                     double y = Geodesic.GetSphericalDistance(point, new MapPoint(point.X, pt.Y));
  318.                     pts.Add(new MapPoint(x, y));
  319.                 }
  320.                 return pts;
  321.             }
  322.             else
  323.                 return points;
  324.         }
  325.         private double GetArea(ESRI.ArcGIS.Client.Geometry.PointCollection points)
  326.         {
  327.             double tempArea = 0;
  328.             double xDiff, yDiff, x1, x2, y1, y2;
  329.             for (int i = 0; i < points.Count - 1; i++)
  330.             {
  331.                 x1 = points[i].X;
  332.                 x2 = points[i + 1].X;
  333.                 y1 = points[i].Y;
  334.                 y2 = points[i + 1].Y;
  335.                 xDiff = x2 - x1;
  336.                 yDiff = y2 - y1;
  337.                 //tempArea += x1 * yDiff - y1 * xDiff;
  338.                 tempArea += (x1 + x2) * (y1 - y2);
  339.             }
  340.             return Math.Abs(tempArea) / 2;
  341.         }
  342.     }
  343.     public enum AreaUnit : int
  344.     {
  345.         Undefined = -1,
  346.         SqMi = 1,
  347.         Acres = 2,
  348.         SqKm = 3,
  349.         SqFt = 4,
  350.         SqM = 5,
  351.         Hect = 6
  352.     }
  353.     public enum MeasureType : int
  354.     {
  355.         Distance = 1,
  356.         Area = 2
  357.     }
  358. }