ArcGIS.Server.9.2.DotNet自带例子分析(一、四)

目的:
1.距离测量功能
准备:
1.(一、三)的工程,具体见前篇。

开始:
1.新建名为Measure.ascx的用户控件,并且实现ICallbackEventHandler接口,具体代码如下:
 1namespace MappingApp
 2{
 3    public partial class Measure : System.Web.UI.UserControl, ICallbackEventHandler
 4    {
 5        protected void Page_Load(object sender, EventArgs e)
 6        {
 7
 8        }

 9
10        ICallbackEventHandler 成员
25    }

26}
2. 加入具体的线距离测量和面积测量功能代码,具体的代码和说明如下:
  1namespace MappingApp
  2{
  3    //地图单位
  4    public enum MapUnit
  5    {
  6        Resource_Default, Degrees, Feet, Meters //默认,度,码,米
  7    }

  8
  9    //测量单位
 10    public enum MeasureUnit
 11    {
 12        Feet, Kilometers, Meters, Miles //码,千米,米,英里
 13    }

 14
 15    //区域单位
 16    public enum AreaUnit
 17    {
 18        Acres, Sq_Feet, Sq_Kilometers, Sq_Meters, Sq_Miles //英亩,平方码,平方千米,平方米,平方英里
 19    }

 20
 21    public partial class Measure : System.Web.UI.UserControl, ICallbackEventHandler
 22    {
 23        MapResourceManager m_resourceManger;
 24        IMapFunctionality m_mapFunctionality;
 25        //页面
 26        private Page m_page;
 27        //客户端代码段
 28        public string m_callbackInvocation = "";
 29        //地图控件ID
 30        private string m_mapBuddyId = "Map1";
 31        //用户控件id
 32        public string m_id;
 33        //地图控件
 34        private Map m_map;
 35        //默认地图单位
 36        private MapUnit m_FallbackMapUnit = MapUnit.Degrees; 
 37        private MapUnit m_mapUnits;
 38        //
 39        private MapUnit m_startMapUnits = MapUnit.Degrees;
 40        //默认测量单位
 41        public MeasureUnit m_measureUnits = MeasureUnit.Miles;
 42        //默认区域单位
 43        public AreaUnit m_areaUnits = AreaUnit.Sq_Miles;
 44        //数字精确到4位
 45        private double m_numberDecimals = 4;
 46
 47        protected void Page_Load(object sender, EventArgs e)
 48        {
 49            //控件id
 50            m_id = this.ClientID;
 51            //页面
 52            m_page = this.Page;
 53            if (m_mapBuddyId == null || m_mapBuddyId.Length == 0)
 54            {
 55                m_mapBuddyId = "Map1";
 56            }

 57            //获取map控件
 58            m_map = m_page.FindControl(m_mapBuddyId) as Map;
 59            //获取MapResourceManager控件
 60            m_resourceManger = m_page.FindControl(m_map.MapResourceManager) as MapResourceManager;
 61            //通过GetCallbackEventReference生成客户端调用的javascript方法段
 62            m_callbackInvocation = m_page.ClientScript.GetCallbackEventReference(this"argument""processCallbackResult""context"true);
 63        }

 64
 65        //
 66        protected void Page_PreRender(object sender, EventArgs e)
 67        {
 68            GetMeasureResource();
 69        }

 70
 71        private void GetMeasureResource()
 72        {
 73            string primeResource = m_map.PrimaryMapResource;
 74            IEnumerable mapResources = m_resourceManger.GetResources();
 75            IEnumerator resEnum = mapResources.GetEnumerator();
 76           
 77            resEnum.MoveNext();
 78
 79            IGISResource resource;
 80            if (primeResource != null && primeResource.Length > 0)
 81            {
 82                resource = m_resourceManger.GetResource(primeResource);
 83            }

 84            else
 85            {
 86                resource = resEnum.Current as IGISResource;
 87            }

 88
 89            if (resource != null)
 90            {
 91                m_mapFunctionality = (IMapFunctionality)resource.CreateFunctionality(typeof(IMapFunctionality), "mapFunctionality");
 92            }

 93        }

 94
 95        ICallbackEventHandler 成员
163
164        //根据请求字符串进行不同的测量
165        public string ProcessMeasureRequest(NameValueCollection queryString)
166        {
167            if (m_mapFunctionality == null)
168            {
169                GetMeasureResource();
170            }

171            object o = Session["MeasureMapUnits"];
172            if (o != null)
173            {
174                m_mapUnits = (MapUnit)Enum.Parse(typeof(MapUnit), o.ToString());
175            }

176            else if (m_startMapUnits == MapUnit.Resource_Default)
177            {
178                //获取默认地图单位
179                m_mapUnits = GetResourceDefaultMapUnit();
180            }

181            else
182            {
183                m_mapUnits = m_startMapUnits;
184            }

185
186            //请求参数
187            string eventArg = queryString["EventArg"].ToLower();
188            string vectorAction = queryString["VectorAction"].ToLower();
189            string[] coordPairs, xys;
190            //坐标字符串
191            string coordString = queryString["coords"];
192            if (coordString == null && coordString.Length == 0)
193            {
194                coordString = "";
195            }

196            //坐标字符串分割
197            coordPairs = coordString.Split(char.Parse("|"));
198            //地图单位
199            string mapUnitString = queryString["MapUnits"];
200            if (mapUnitString != null && mapUnitString.Length > 0)
201            {
202                m_mapUnits = (MapUnit)Enum.Parse(typeof(MapUnit), mapUnitString);
203            }

204            Session["MeasureMapUnits"= m_mapUnits;
205            //测量单位
206            string measureUnitString = queryString["MeasureUnits"];
207            if (measureUnitString != null && measureUnitString.Length > 0)
208            {
209                m_measureUnits = (MeasureUnit)Enum.Parse(typeof(MeasureUnit), measureUnitString);
210            }

211            //区域单位
212            string areaUnitstring = queryString["AreaUnits"];
213            if (areaUnitstring != null && areaUnitstring.Length > 0)
214            {
215                m_areaUnits = (AreaUnit)Enum.Parse(typeof(AreaUnit), areaUnitstring);
216            }

217
218            //输出内容字符串
219            string response = "";
220            PointCollection points = new PointCollection();
221            PointCollection dPoints = new PointCollection();
222            ArrayList distances = new ArrayList();
223            double totalDistance = 0;
224            double segmentDistance = 0;
225            double area = 0;
226            double perimeter = 0;
227            double roundFactor = Math.Pow(10, m_numberDecimals);
228            double xD, yD, tempDist, tempDist2, tempArea, x1, x2, y1, y2;
229
230            //动作为添加点
231            if (vectorAction == "addpoint")
232            {
233                //坐标点大于1个时,就是保证是一条线
234                if (coordPairs != null && coordPairs.Length > 1)
235                {
236                    for (int i = 0; i < coordPairs.Length; i++)
237                    {
238                        xys = coordPairs[i].Split(char.Parse(":"));
239                        //像素坐标转换成地理坐标
240                        points.Add(Point.ToMapPoint(Convert.ToInt32(xys[0]), Convert.ToInt32(xys[1]), m_map.GetTransformationParams(ESRI.ArcGIS.ADF.Web.Geometry.TransformationDirection.ToMap)));
241
242                        if (i > 0)//第二个坐标点的时候
243                        {
244                            if (m_mapUnits == MapUnit.Degrees)//地图单位为度的时候
245                            {
246                                //计算与前一个点的距离,分段距离
247                                tempDist = DegreeToFeetDistance(points[i - 1].X, points[i - 1].Y, points[i].X, points[i].Y);
248                                //度转成码
249                                y1 = DegreeToFeetDistance(points[i].X, points[i].Y, points[i].X, 0);
250                                //度转成码
251                                x1 = DegreeToFeetDistance(points[i].X, points[i].Y, 0, points[i].Y);
252                                dPoints.Add(new Point(x1, y1));
253                                //单位换算
254                                segmentDistance = ConvertUnits(tempDist, MapUnit.Feet, m_measureUnits);
255                            }

256                            else//地图单位为米的时候
257                            {
258                                xD = Math.Abs(points[i].X - points[i - 1].X);
259                                yD = Math.Abs(points[i].Y - points[i - 1].Y);
260                                //计算2个坐标之间的距离
261                                tempDist = Math.Sqrt(Math.Pow(xD, 2+ Math.Pow(yD, 2));
262                                //单位换算
263                                segmentDistance = ConvertUnits(tempDist, m_mapUnits, m_measureUnits);
264
265                            }

266
267                            //把分段距离添加到distances
268                            distances.Add(segmentDistance);
269                            //计算总距离
270                            totalDistance += segmentDistance;
271                            //只显示4位小数
272                            segmentDistance = Math.Round(segmentDistance * roundFactor) / roundFactor;
273                            totalDistance = Math.Round(totalDistance * roundFactor) / roundFactor;
274                        }

275                        else//第一个坐标点的时候
276                        {
277                            if (m_mapUnits == MapUnit.Degrees)
278                            {
279                                //度转成码
280                                y1 = DegreeToFeetDistance(points[i].X, points[i].Y, points[i].X, 0);
281                                x1 = DegreeToFeetDistance(points[i].X, points[i].Y, 0, points[i].Y);
282                                dPoints.Add(new Point(x1, y1));
283                            }

284                        }

285                    }

286                }

287
288                //为多边形时
289                if (eventArg == "polygon")
290                {
291                    if (points.Count > 2)
292                    {
293                        if (m_mapUnits == MapUnit.Degrees)
294                        {
295                            //最后一段的距离计算
296                            tempDist = DegreeToFeetDistance(points[points.Count - 1].X, points[points.Count - 1].Y, points[0].X, points[0].Y);
297                            tempDist2 = ConvertUnits(tempDist, MapUnit.Feet, m_measureUnits);
298                            distances.Add(tempDist2);
299                            //加入第一点作为多边形的结束节点
300                            dPoints.Add(dPoints[0]);
301                        }

302                        else
303                        {
304                            //最后一段的距离计算
305                            xD = Math.Abs(points[points.Count - 1].X - points[0].X);
306                            yD = Math.Abs(points[points.Count - 1].Y - points[0].Y);
307                            tempDist = Math.Sqrt(Math.Pow(xD, 2+ Math.Pow(yD, 2));
308                            tempDist2 = ConvertUnits(tempDist, m_mapUnits, m_measureUnits);
309                            distances.Add(tempDist2);
310                        }

311                        //加入第一点作为多边形的结束节点
312                        points.Add(points[0]);
313                        //总长度+最后一段长度
314                        perimeter = totalDistance + tempDist2;
315                        //多边形面积计算
316                        tempArea = 0;
317                        MapUnit mUnits = m_mapUnits;
318                        for (int j = 0; j < points.Count - 1; j++)
319                        {
320                            if (m_mapUnits == MapUnit.Degrees)
321                            {
322                                x1 = Convert.ToDouble(dPoints[j].X);
323                                x2 = Convert.ToDouble(dPoints[j + 1].X);
324                                y1 = Convert.ToDouble(dPoints[j].Y);
325                                y2 = Convert.ToDouble(dPoints[j + 1].Y);
326                                mUnits = MapUnit.Feet;
327                            }

328                            else
329                            {
330                                x1 = Convert.ToDouble(points[j].X);
331                                x2 = Convert.ToDouble(points[j + 1].X);
332                                y1 = Convert.ToDouble(points[j].Y);
333                                y2 = Convert.ToDouble(points[j + 1].Y);
334                            }

335                            //tempArea += tempArea + (x1 + x2) * (y1 - y2);
336                            double xDiff = x2 - x1;
337                            double yDiff = y2 - y1;
338                            tempArea += x1 * yDiff - y1 * xDiff;
339                        }

340                        tempArea = Math.Abs(tempArea) / 2;
341                        //单位换算
342                        area = ConvertAreaUnits(tempArea, mUnits, m_areaUnits);
343                        //保留4位小数
344                        perimeter = Math.Round(perimeter * roundFactor) / roundFactor;
345                        area = Math.Round(area * roundFactor) / roundFactor;
346
347                        //输出显示内容html
348                        response = String.Format("<table cellspacing='0'  ><tr><td>Perimeter: </td><td align='right'>{0}</td><td>{1}</td></tr><tr><td>Area:</td><td  align='right'>{2}</td><td>{3}</td></tr></table>", perimeter, WriteMeasureUnitDropdown(), area, WriteAreaUnitDropdown());
349                    }

350                    else
351                    {
352                        //输出显示内容html,小于3个点时候
353                        response = String.Format("<table cellspacing='0' ><tr><td>Perimeter: </td><td align='right'> 0</td><td>{0}</td></tr><tr><td>Area:</td><td align='right'>0 </td><td>{1}</td></tr></table>", WriteMeasureUnitDropdown(), WriteAreaUnitDropdown());
354                    }

355                }

356                else
357                {
358                    //输出显示内容html,为线的时候
359                    response = String.Format("<table cellspacing='0' ><tr><td>Segment: </td><td align='right'>{0} </td><td>{1}</td></tr><tr><td>Total Length:</td><td align='right'>{2} </td><td>{3}</td></tr></table>", segmentDistance, m_measureUnits.ToString(), totalDistance, WriteMeasureUnitDropdown());
360                }

361
362            }

363            //动作为获取坐标
364            else if (vectorAction == "coordinates")
365            {
366                xys = coordPairs[0].Split(char.Parse(":"));
367                Point coordPoint = Point.ToMapPoint(Convert.ToInt32(xys[0]), Convert.ToInt32(xys[1]), m_map.GetTransformationParams(ESRI.ArcGIS.ADF.Web.Geometry.TransformationDirection.ToMap));
368
369                //输出坐标的html显示内容
370                response = String.Format("<table cellspacing='0' ><tr><td>X Coordinate:</td><td align='right'>{0}</td></tr><tr><td>Y Coordinate:</td><td align='right'>{1}</td></tr></table>", (Math.Round(coordPoint.X * roundFactor) / roundFactor).ToString(), (Math.Round(coordPoint.Y * roundFactor) / roundFactor).ToString());
371            }

372            //动作为结束画线
373            else if (vectorAction == "finish")
374            {
375                response = "Shape complete";
376            }

377
378            //把结果内容返回给客户端
379            return String.Format("measure:::{0}:::{1}:::{2}", m_id, vectorAction, response);
380        }

381
382        //输出测量单位选择下拉框
383        public string WriteMeasureUnitDropdown()
384        {
385            System.Text.StringBuilder sb = new System.Text.StringBuilder();
386            sb.Append("<select id=\"MeasureUnits2\" onchange=\"changeMeasureUnits()\" style=\"font: normal 7pt Verdana; width: 100px;\">");
387            Array mArray = Enum.GetValues(typeof(MeasureUnit));
388            foreach (MeasureUnit mu in mArray)
389            {
390                sb.AppendFormat("<option value=\"{0}\" {1}>{0}</option>", mu.ToString(), CheckFormMeasureUnits(mu.ToString()));
391
392            }

393            sb.Append("</select>");
394
395            return sb.ToString();
396        }

397
398        //检查默认选中项
399        public string CheckFormMeasureUnits(string unit)
400        {
401            string response = "";
402            if (unit == m_measureUnits.ToString())
403                response = "selected=\"selected\"";
404            return response;
405        }

406
407        //输出测量单位选择下拉框
408        public string WriteAreaUnitDropdown()
409        {
410            System.Text.StringBuilder sb = new System.Text.StringBuilder();
411            sb.Append("<select id=\"AreaUnits2\" onchange=\"changeAreaUnits()\" style=\"font: normal 7pt Verdana; width: 100px;\">");
412            Array aArray = Enum.GetValues(typeof(AreaUnit));
413            foreach (AreaUnit au in aArray)
414            {
415                sb.AppendFormat("<option value=\"{0}\" {1}>{0}</option>", au.ToString(), CheckFormAreaUnits(au.ToString()));
416
417            }

418            sb.Append("</select>");
419
420            return sb.ToString();
421        }

422
423        //检查默认选中项
424        public string CheckFormAreaUnits(string unit)
425        {
426            string response = "";
427            if (unit == m_areaUnits.ToString())
428                response = "selected=\"selected\"";
429            return response;
430        }

431
432        //面积单位换算
433        private double ConvertAreaUnits(double area, MapUnit baseUnits, AreaUnit toUnits)
434        {
435            double mArea = area;
436            if (baseUnits == MapUnit.Feet)
437            {
438                if (toUnits == AreaUnit.Acres)
439                    mArea = area * 0.000022956;
440                else if (toUnits == AreaUnit.Sq_Meters)
441                    mArea = area * 0.09290304;
442                else if (toUnits == AreaUnit.Sq_Miles)
443                    mArea = area * 0.00000003587;
444                else if (toUnits == AreaUnit.Sq_Kilometers)
445                    mArea = area * 0.09290304 / 1000000;
446            }

447            else if (baseUnits == MapUnit.Meters)
448            {
449                if (toUnits == AreaUnit.Acres)
450                    mArea = area * 0.0002471054;
451                else if (toUnits == AreaUnit.Sq_Miles)
452                    mArea = area * 0.0000003861003;
453                else if (toUnits == AreaUnit.Sq_Kilometers)
454                    mArea = area * 1.0e-6;
455                else if (toUnits == AreaUnit.Sq_Feet)
456                    mArea = area * 10.76391042;
457            }

458
459            return mArea;
460        }

461
462        //单位换算
463        public double ConvertUnits(double distance, MapUnit fromUnits, MeasureUnit toUnits)
464        {
465            double mDistance = distance;
466            if (fromUnits == MapUnit.Feet)
467            {
468                if (toUnits == MeasureUnit.Miles)
469                {
470                    mDistance = distance / 5280;
471                }

472                else if (toUnits == MeasureUnit.Meters)
473                {
474                    mDistance = distance * 0.304800609601;
475                }

476                else if (toUnits == MeasureUnit.Kilometers)
477                {
478                    mDistance = distance * 0.0003048;
479                }

480            }

481            else
482            {
483                if (toUnits == MeasureUnit.Miles)
484                {
485                    mDistance = distance * 0.0006213700922;
486                }

487                else if (toUnits == MeasureUnit.Feet)
488                {
489                    mDistance = distance * 3.280839895;
490                }

491                else if (toUnits == MeasureUnit.Kilometers)
492                {
493                    mDistance = distance / 1000;
494                }

495            }

496            return mDistance;
497        }

498
499        //度转成码距离
500        private double DegreeToFeetDistance(double x1, double y1, double x2, double y2)
501        {
502            double Lat1 = DegToRad(y1);
503            double Lat2 = DegToRad(y2);
504            double Lon1 = DegToRad(x1);
505            double Lon2 = DegToRad(x2);
506            double LonDist = Lon1 - Lon2;
507            double LatDist = Lat1 - Lat2;
508            double x = Math.Pow(Math.Sin(LatDist / 2), 2+ Math.Cos(Lat1) * Math.Cos(Lat2) * Math.Pow(Math.Sin(LonDist / 2), 2);
509            x = 2 * Math.Asin(Math.Min(1, Math.Sqrt(x)));
510            x = (3963 - 13 * Math.Sin((Lat1 + Lat2) / 2)) * x;
511            // in miles convert to feet and use that as base
512            return (x * 5280);
513        }

514
515        //度转成弧度
516        private double DegToRad(double degrees)
517        {
518            return Convert.ToDouble(degrees * Math.PI / 180);
519        }

520
521        private MapUnit GetResourceDefaultMapUnit()
522        {
523            MapUnit mUnit = MapUnit.Degrees;
524            try
525            {
526                //获取地图资源单位
527                Units mu = m_mapFunctionality.Units;
528                if (mu == Units.DecimalDegrees)
529                {
530                    mUnit = MapUnit.Degrees;
531                }
  
532                else if (mu == Units.Feet)
533                {
534                    mUnit = MapUnit.Feet;
535                }

536                else if (mu == Units.Meters)
537                {
538                    mUnit = MapUnit.Meters;
539                }

540                    
541            }

542            catch
543            {
544                //不能获取地图资源单位时用m_FallbackMapUnit定义的单位
545                mUnit = m_FallbackMapUnit;
546            }

547            return mUnit;
548
549        }

550
551        public string Id
552        {
553            get return m_id; }
554            set { m_id = value; }
555        }

556
557        private string ClientCallbackInvocation
558        {
559            get return m_callbackInvocation; }
560            set { m_callbackInvocation = value; }
561        }

562
563        private MapResourceManager MapResourceManager
564        {
565            get return m_resourceManger; }
566            set { m_resourceManger = value; }
567        }

568
569        /// <summary>
570        /// Id of Buddy MapControl
571        /// </summary>

572        public string MapBuddyId
573        {
574            get return m_mapBuddyId; }
575            set { m_mapBuddyId = value; }
576        }

577
578
579        /// <summary>
580        /// Unit used resource. Resource_Default will return value from resource, if available. Other values will force calculations to use that unit.
581        /// </summary>

582        public MapUnit MapUnits
583        {
584            get return m_startMapUnits; }
585            set { m_startMapUnits = value; }
586        }

587
588        /// <summary>
589        ///  Unit used in display of linear measurements.
590        /// </summary>

591        public MeasureUnit MeasureUnits
592        {
593            get return m_measureUnits; }
594            set { m_measureUnits = value; }
595        }

596
597        /// <summary>
598        ///  Area Units - Unit used in display of area measurements.
599        /// </summary>

600        public AreaUnit AreaUnits
601        {
602            get return m_areaUnits; }
603            set { m_areaUnits = value; }
604        }

605
606        // Number of Decimals - Number of decimal digits displayed in measurements.
607        public double NumberDecimals
608        {
609            get return m_numberDecimals; }
610            set { m_numberDecimals = value; }
611        }

612
613
614        public override bool Visible
615        {
616            get return base.Visible; }
617        }

618
619        public override bool EnableTheming
620        {
621            get
622            {
623                return base.EnableTheming;
624            }

625        }

626
627        public override bool EnableViewState
628        {
629            get
630            {
631                return base.EnableViewState;
632            }

633        }

634
635    }

636}

3.代码贴太多了编辑器死掉了一样了,郁闷换个新篇继续写了...
posted @ 2008-08-17 15:14  水的右边  阅读(3201)  评论(25编辑  收藏  举报