为了使用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 = "量测:\r\n长度:0.000 米\r\n面积: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("量测:\r\n长度:{0} 米\r\n面积:{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 = "量测:\r\n长度:0.000 米\r\n面积: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("量测:\r\n长度:{0} 米\r\n面积:{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最终选择了完全正向插入节点的方式。

ArcMobile的CoordinateCollection在逆时针添加点时自动调整节点顺序的问题的更多相关文章

  1. Android Tips: 在给drawable中添加图片资源时,文件名必须全小写

    在给drawable中添加图片资源时,文件名必须全小写

  2. 使用mx:Repeater在删除和添加item时列表闪烁

    使用mx:Repeater在删除和添加item时列表闪烁 不可能在用户界面上闪闪的吧,recycleChildren属性可帮助我们 recycleChildren属性==缓存,设为true就可以了 本 ...

  3. servers中添加server时,看不到运行环境的选择。

    servers中添加server时,看不到运行环境的选择. 主要原因是tomcat目录中的配置文件格式不对.

  4. phpcmsv9如何实现添加栏目时不在首页内容区显示只在导航栏显示

    之前王晟璟一直使用PHPCMSV9系统建过自己的个人门户网站,同时也建立了一个其他类型的网站,感觉非常不错,我不得不说PHPCMSV9的功能非常齐全,非常强大. 但有一点时常让王晟璟感到很烦脑,那就是 ...

  5. 30.怎样在Swift中添加运行时属性?

    和OC一样,Swift中也可以添加运行时属性.下面将提供一个完整的例子,演示如何给按钮点击事件添加运行时属性. 1.示例 import UIKit var s_GofButtonTouchDownKe ...

  6. oracle添加数据时主键自动增长

    CREATE TABLE STUDENT( --创建学生表  ID NUMBER(10) PRIMARY KEY,   --主键ID  SNAME VARCHAR2(20), ); 此时给学生表添加数 ...

  7. mybatis添加记录时返回主键id

    参考:mybatis添加记录时返回主键id 场景 有些时候我们在添加记录成功后希望能直接获取到该记录的主键id值,而不需要再执行一次查询操作.在使用mybatis作为ORM组件时,可以很方便地达到这个 ...

  8. 使用mybatis注解@Options实现添加记录时返回主键值

    官网:http://www.mybatis.org/mybatis-3/index.html 在使用mybatis作为ORM框架时,我通常更喜欢使用注解而非xml配置文件的方式.业务场景:添加记录之后 ...

  9. cmd中mysql主键id自增,在添加信息时发生错误,再次成功添加时,id已经跳过错误的信息继续自增。

    id 自增,在往这个表里添加信息时 发生错误,再次添加 id数值已经跳过之前

随机推荐

  1. 计网Q1:多个方面比较电路交换、报文交换和分组交换的主要优缺点

    网上看到的带佬儿的帖子......膜过来<doge 原文链接: https://blog.csdn.net/njchenyi/article/details/1540657 电路交换: 由于电路 ...

  2. 一个div画同心圆

    二话不说上代码 background-image:radial-gradient(7px,#00A4FF 50%,#fff 75%,#00A4FF 94%); 7px是圆的半径 效果:

  3. 消息队列之kafka

    消息队列之activeMQ 消息队列之RabbitMQ 1.kafka介绍 kafka是由scala语言开发的一个多分区,多副本的并且居于zookeeper协调的分布式的发布-订阅消息系统.具有高吞吐 ...

  4. Python爬虫要学什么?写给小白的Python爬虫必备技能

    Python在爬虫方面用得比较多,所以你如果能掌握以下内容,找工作的时候就会顺利很多: 1.爬虫,不是抓取到数据就完事了,如果有数据抽取.清洗.消重等方面经验,也是加分项; 2.大部分的公司都要求爬虫 ...

  5. uni-app开发经验分享十五: uni-app 蓝牙打印功能

    最近在做uni-app项目时,遇到了需要蓝牙打印文件的功能需要制作,在网上找到了一个教程,这里分享给大家. 引入tsc.js 简单得引入到自己所需要得页面中去,本次我们只要到了标签模式,他同时还有账单 ...

  6. uni-app开发经验分享一: 多页面传值的三种解决方法

    开发了一年的uni-app,在这里总结一些uni-app开发中的问题,提供几个解决方法,分享给大家: 问题描述:一个主页面,需要联通一到两个子页面,子页面传值到主页面,主页面更新 问题难点: 首先我们 ...

  7. vue3.0 composition API

    一.Setup函数 1.创建时间:组件创建之前被调用,优先与created被调用,this指向的实例为window,created所指向的实例为proxy 2.this指向:不会指向组件实例 3.参数 ...

  8. Python格式化处理json数据的方式

    1.问题 在遇到json数据的过程中,我们经常需要获取json数据中某个值的操作,如果是用get方法去取比较繁琐,接下来介绍两种方式来取值. 2.jsonpath来格式化处理json数据 2.1介绍 ...

  9. jmeter三种阶梯式加压

    一.前言 在做性能测试的时候,在某些场景下需要逐渐加压,不总是停下来再修改线程再加压,且可以对比加压,找出服务的性能拐点. 二.三种逐渐加压方式 备注:普通的压测方式,并发的Samples是可预知的: ...

  10. IDEA SSM后端框架入门

    SSM框架 如果对SSM一无所知,推荐先去看这本书,可以在微信读书上看. 知识点 控制器返回对象时,对象需要有getter,setter方法,才能自动转化为json数据类型. 一个服务管理者对应多个业 ...