• ArcMobile的CoordinateCollection在逆时针添加点时自动调整节点顺序的问题


      为了使用ArcMobile实现量测功能,LZ自定义了一个MapGraphicLayer用于绘图,代码如下:

    using System.Drawing;
    using ESRI.ArcGIS.Mobile;
    using ESRI.ArcGIS.Mobile.Geometries;
    
    namespace LandInspections
    {
        public class MeasureLayer : MapGraphicLayer
        {
            /// Defines a symbol class instance for displaying point
            private Symbol drawSymbol;
    
            /// Defines a CoordinateCollection instance to store custom features
            private CoordinateCollection coordinateCollection = new CoordinateCollection();
    
            /// Get or set coordinate collection stored in custom graphic layer 
            public CoordinateCollection Coordinates
            {
                get
                {
                    return coordinateCollection;
                }
                set
                {
                    coordinateCollection = value;
                }
            }
    
            /// Initializes a new instance of custom graphic layer
            public MeasureLayer()
                : base("MeasureLayer")
            {
                drawSymbol = new Symbol(
                    new PointPaintOperation(
                        Color.Green, 3, 0, Color.LightGreen, 100, 25, PointPaintStyle.Circle));
            }
    
            /// Draw method being called after adding to map
            protected override void Draw(Display display)
            {
                //return if display is null
                if (display == null)
                    return;
                //return if drawing is cancelled
                if (display.DrawingCanceled)
                    return;
                drawSymbol.DrawArea(display, coordinateCollection);
            }
    
            protected override void Dispose(bool disposing)
            {
                //Dispose symbol implementing IDisposible
                try
                {
                    if (disposing)
                    {
                        if (drawSymbol != null)
                            drawSymbol.Dispose();
                        drawSymbol = null;
    
                        coordinateCollection = null;
                    }
                }
                finally
                {
                    base.Dispose(disposing);
                }
            }
        }
    }

      在“量测”按钮所在的窗体代码中,添加如下代码:

    /// <summary>
    /// MapGraphicLayer的坐标点
    /// </summary>
    private CoordinateCollection coords = new CoordinateCollection();
    
    private BtnMeasure_Click(object sender, EventArgs e)
    {
        if (this.txtMeasure.Visible)//txtMeasure是用来显示量测结果的控件
        {
            this.txtMeasure.Visible = false;
            this.coords.Clear();
            this.map1.MapGraphicLayers.Remove(this.measureLayer);
            this._mapAction = MyMapAction.None;
        }
        else
        {
            this.txtMeasure.Text = "量测:
    长度:0.000 米
    面积:0.000 平方米";
            this.measureLayer = new MeasureLayer();
            this.measureLayer.Coordinates = this.coords;
            this.map1.MapGraphicLayers.Add(this.measureLayer);
            this._mapAction == MyMapAction.Measure;
            this.txtMeasure.Visible = true;
        }
    }
    
    private void map1_MouseUp(object sender, MapMouseEventArgs e)
    {
        if (this._mapAction == MyMapAction.Measure)
        {
            Coordinate coord = this.map1.ToMap(e.X, e.Y);
            this.coords.Add(coord);
            Polyline line = new Polyline(this.measureLayer.Coordinates);
            Polygon area = new Polygon(this.measureLayer.Coordinates);
            this.txtMeasure.Text = String.Format("量测:
    长度:{0} 米
    面积:{1} 平方米",
                line.GetLength().ToString("f3"), area.GetArea().ToString("f3"));
            this.map1.Refresh();
        }
    }

      运行后,发现顺时针点击屏幕的绘图结果正确,但是逆时针点击屏幕时绘图结果错误。

      检查后发现是因为ESRI.ArcGIS.Mobile.Geometries.CoordinateCollection类的Add方法对点集的顺序进行了自动调整,在this.coords.Add(coord)时点集的顺序已经被改变了。

      添加点1:CoordinateCollection中点集为[1]。

      添加点2:CoordinateCollection中点集为[1,2,1]。

      添加点3:CoordinateCollection中点集为[1,3,2,1]。

      添加点4:CoordinateCollection中点击为[1,4,2,3,1]。

      为解决这一问题,LZ在程序中定义一个List<Coordinate> coords,用来存储正确顺序的点集,在自定义的MapGraphicLayer中添加一个SetCoordinate方法,用来保证以顺时针方向添加节点到CoordinateCollection中。代码如下:

    public void SetCoordinate(System.Collections.Generic.List<Coordinate> coords)
    {
        if (coords == null || coords.Count < 1)
            return;
        if (this.coordinateCollection == null)
            this.coordinateCollection = new CoordinateCollection();
      this.coordinateCollection.Clear();
    //若为顺时针,则直接赋值 for (int i = 0; i < coords.Count; i++) { this.coordinateCollection.Add(new Coordinate(coords[i].X, coords[i].Y)); if (this.coordinateCollection.IsCounterClockwise == true) break; } //若为逆时针,则反向以顺时针方式将点集添加到CoordinateCollection中 if (this.coordinateCollection.IsCounterClockwise == true) { this.coordinateCollection.Clear(); this.coordinateCollection.Add(new Coordinate(coords[0].X, coords[0].Y)); for (int i = coords.Count - 1; i > 0; i--) { this.coordinateCollection.Add(new Coordinate(coords[i].X, coords[i].Y)); } } }

      相应的,“量测”功能所在窗体的代码也需要进行相应的修改,代码如下:

    /// <summary>
    /// MapGraphicLayer的坐标点
    /// </summary>
    private List<Coordinate> coords = new List<Coordinate>();
    
    private BtnMeasure_Click(object sender, EventArgs e)
    {
        if (this.txtMeasure.Visible)//txtMeasure是用来显示量测结果的控件
        {
            this.txtMeasure.Visible = false;
            this.coords.Clear();
            this.map1.MapGraphicLayers.Remove(this.measureLayer);
            this._mapAction = MyMapAction.None;
        }
        else
        {
            this.txtMeasure.Text = "量测:
    长度:0.000 米
    面积:0.000 平方米";
            this.measureLayer = new MeasureLayer();
            this.measureLayer.Coordinates.Clear();
    this.map1.MapGraphicLayers.Add(this.measureLayer); this._mapAction == MyMapAction.Measure; this.txtMeasure.Visible = true; } } private void map1_MouseUp(object sender, MapMouseEventArgs e) { if (this._mapAction == MyMapAction.Measure) { Coordinate coord = this.map1.ToMap(e.X, e.Y); this.coords.Add(coord);
    this.measureLayer.SetCoordinate(this.coords); Polyline line
    = new Polyline(this.measureLayer.Coordinates); Polygon area = new Polygon(this.measureLayer.Coordinates); this.txtMeasure.Text = String.Format("量测: 长度:{0} 米 面积:{1} 平方米", line.GetLength().ToString("f3"), area.GetArea().ToString("f3")); this.map1.Refresh(); } }

      经过测试,这种方式是可行的。之后大概是因为无聊,也可能是为了验证自己的想法,又分别测试了完全反向插入节点和完全正向插入节点的情况,结果出乎意料,竟然都是正确的???

      完全反向插入节点:即将[1,2,3,4]以[1,4,3,2]的顺序插入,无论节点顺序是顺时针还是逆时针。测试代码如下:

    public void SetCoordinate(System.Collections.Generic.List<Coordinate> coords)
    {
       if (coords == null || coords.Count < 1)
           return;
       if (this.coordinateCollection == null)
           this.coordinateCollection = new CoordinateCollection();
    this.coordinateCollection.Clear(); //反向插入节点 this.coordinateCollection.Add(new Coordinate(coords[0].X, coords[0].Y)); for (int i = coords.Count - 1; i > 0; i--) { this.coordinateCollection.Add(new Coordinate(coords[i].X, coords[i].Y)); } }

      完全正向插入节点:即将[1,2,3,4]以[1,2,3,4]的顺序插入,无论节点顺序是顺时针还是逆时针。测试代码如下:

    public void SetCoordinate(System.Collections.Generic.List<Coordinate> coords)
    {
        if (coords == null || coords.Count < 1)
            return;
        if (this.coordinateCollection == null)
            this.coordinateCollection = new CoordinateCollection();
        this.coordinateCollection.Clear();
        for (int i = 0; i < coords.Count; i++)
        {
            this.coordinateCollection.Add(new Coordinate(coords[i].X, coords[i].Y));
        }
    }

      最后的事实证明,只要每次绘图时,将所有的节点重新添加一次即可,于是LZ最终选择了完全正向插入节点的方式。

  • 相关阅读:
    jQuery中排除指定元素,同时选择剩下的所有元素
    Silverlight Telerik控件学习:弹出窗口RadWindow
    biztalk 2010 dev版安装小记
    Flex4中的ModuleLoader,Alert以及TitleWindow
    Silverlight Telerik控件学习:主题Theme切换
    用Flex模拟智能手机表单输入的自动放大功能
    "为帮助内容存储区指定的位置无效或者您无权访问该位置"解决方法
    Flex4中使用WCF
    Silverlight单元测试
    Silverlight:纠结的快捷键问题
  • 原文地址:https://www.cnblogs.com/hibernation/p/3314269.html
Copyright © 2020-2023  润新知