怎么在gis加layer的属性_第1篇. GIS里的图形是咋画到界面上的?

本文介绍了如何使用C#手写一个简单的地理信息系统组件,包括空间对象如点、线、面的表示,以及利用图形理论进行绘制。通过创建图形实体类,实现了点的绘制和属性查询功能,涉及图形绘制、鼠标点选查询等核心概念。代码简洁,适合GIS爱好者和开发者学习底层逻辑。
摘要由CSDN通过智能技术生成

手写地理信息组件系列 第1篇空间对象的表示和简单绘制难度指数:★☆☆☆☆

各位看官老爷好!从此一篇起,我将会陆续更新“手写地理信息组件”系列。目的在于和广大GIS爱好者和从业者,讨论关于GIS底层的相关内容。力图用一种轻松的氛围,和最纯粹的代码形式表现GIS软件的底层逻辑。让地理信息从业者不再囿于商业软件的二次开发,更理性的看待商软。愿与诸共同进步,懂点儿底层,不做调包侠。

开发环境介绍

  • 实现语言:C#

  • 开发工具:VisualStudio,版本不限。

C#原生对窗口图形显示支持较好,虽然界面效果十分朴素,但是使用简单,开发难度小,对于图形开发,只要掌握图形理论知识就能很快上手。做到不纠结于具体语言,让GIS相关知识真正沉淀下来。

空间图形的构成

我们知道,不论是一维二维三维空间要素,都可以用点坐标来描述。线可以由两点表示,面可以由三个及以上的平面坐标点表示,空间体可以由四个及以上的空间坐标点表示。由此可见,空间实体可以由最基本的点来表示。

严格的讲,点实体(point)是一种抽象概念,不仅代指点状对象,而是可以被抽象为点的一切空间实体。如市区内的一座楼,楼上向下望的每个小脑袋,甚至这座楼所在的城市,都可以被抽象为一个点实体

1ba8846768c24a9bbe2a72e0659b95e3.png

不同于点实体的抽象概念,节点(vertex)是构成如线实体,面实体这样空间实体对象(feature)的实际单元。我们在地图上绘制一个三角形时,可以通过点取三个点坐标就能完成绘制,那么这三个点就可以称为这个面实体的三个节点。事实上,面图形实际存储的也就是这三个节点的有序坐标串。

b6d7319cc11aca31dadfd1165ee0a695.png

空间图形的代码表示

明确了空间图形的组成,下面就以C#代码实现一个简单的地图程序。
首先建立一个C#工程,选择windows窗体程序。命名为MiniGIS,新建类文件GISEntities,在内构建空间实体最基本的属性。

 1namespace MiniGIS
2{
3  //节点
4  class Vertex
5  {
6    double x;
7    double y;
8  }
9  //点实体
10  class Point
11  {
12    Vertex Location;
13  }
14  //线实体
15  class Line
16  {
17    List Vertexs;18  }19  //面实体20  class Polygon21  {22    List Vertexs;23  }24}

OK,空间实体的基本定义已经完成。下面来具体落实,图形怎么画的问题。

图形的绘制和查询

现以最基本的点绘制为例,实现图形和属性的绘制,鼠标点选图形的查询。

首先对实体类进行必要的属性和方法扩展,使其实现绘制方法。

 1class Vertex
2{
3  public double x;
4  public double y;
5
6  //扩展构造函数
7  public Vertex(double x, double y) 8  {
9    this.x = x;
10    this.y = y;
11  }
12
13  //扩展计算两点距离方法(点选查询时会用)
14  public double Distance(Vertex another)15  {
16    //勾股定理求两点距离
17    return Math.Sqrt(Math.Pow(x - another.x, 2) + Math.Pow(y - another.y, 2));
18  }
19}
20
21//点实体
22class Point
23{
24  private Vertex location;
25  private String attrbute;
26
27  public Point(Vertex vertex, String attr)28  {
29    this.location = vertex;
30    this.attrbute = attr;
31  }
32
33  /// 
34  /// 绘制图形
35  /// 
36  /// C#绘图类
37  public void DrawShape(System.Drawing.Graphics graphics)38  {
39    //画笔为实心红色画笔,绘制5*5像素的点
40    graphics.FillEllipse(new SolidBrush(Color.Red), new Rectangle((int)location.x, (int)location.y, 5, 5));
41  }
42  //绘制属性
43  public void DrawAttrbute(Graphics graphics)44  {
45    graphics.DrawString(attrbute, new Font("宋体", 20), new SolidBrush(Color.Blue), new PointF((int)location.x, (int)location.y));
46  }
47  //计算两点距离
48  public double Distance(Vertex another)49  {
50    return location.Distance(another);
51  }
52}

设计一个简单界面,主要由三个TextBox和一个Button组成,三个输入框textBox_X、textBox_Y、TextBox_Attr分别代表待显示点的x坐标,y坐标属性。

e86101ec134bd9b66eb83f622bc08a70.png

现在双击button按钮注册点击事件,在按钮点击事件代码块中书写上述内容的调用逻辑。

 1public partial class Form1 : Form
2{
3  //已输入点集合
4  List points = new List(); 5 6  public Form1() 7  { 8    InitializeComponent(); 9  }1011  private void button1_Click(object sender, EventArgs e)12  {13    //获取输入14    double x = Convert.ToDouble(textBox_X.Text);15    double y = Convert.ToDouble(textBox_Y.Text);16    String attr = textBox_Attr.Text;1718    //实例化节点19    Vertex vertex = new Vertex(x, y);2021    //实例化点实体22    Point p = new Point(vertex, attr);2324    //获取当前Form的Graphics(即窗口背景),并绘制25    Graphics graphics = this.CreateGraphics();26    p.DrawShape(graphics);27    p.DrawAttrbute(graphics);28    points.Add(p);29  }30}

现在启动项目,输入两组坐标13,45和55.6,80及其属性,现在可以查看效果

29e75a8da4a2d452fb29e56c0774c68d.png

当然,绘制和显示并不足以构成一个基本的地图应用,下面加入图形点选的属性查询。

属性查询的实现思路是获取鼠标坐标,匹配图上与之最近的坐标点,如果与最近坐标点的距离小于设定的阈值(Threshold),可以认为该点已被选取,相应地查找该点的Attrbute。
实现鼠标点选,需要事先注册窗体的MouseClick事件。

 1//距离容限值 10 像素
2const int ThresholdDistance = 10;
3
4private void Form1_MouseClick(object sender, MouseEventArgs e) 5{
6  Vertex vertex = new Vertex(e.X, e.Y);
7  double minDistance = Double.MaxValue;
8  Point nearest = null;
9
10  //筛选与鼠标点最近的坐标点
11  foreach (Point p in points)
12  {
13    double distance = p.Distance(vertex);
14    if (distance 15    {
16      nearest = p;
17      minDistance = distance;
18    }
19  }
20
21  //小于阈值,弹出属性
22  if (nearest != null && nearest.Distance(vertex) 23    MessageBox.Show(nearest.attrbute);
24}

下面运行看东西:

3f52cd6e2295972647378ed08f4bcc1b.png

点选查询已经实现。

OK,我们手写的第一个地图应用就完成了!功能非常纯粹,体积非常小巧(11k…)。虽然这个迷你GIS应用代码量少,逻辑也很简单,但是它暴露了节点(Vertex)这一重要,却在二次开发中并不常用的概念。
我们在产品或项目中更多的调用如Point,Polygon等Geometry层面的包装对象,因其方便的解析调用而更少的使用Vertex概念,因为其更靠近底层。

好了,这一篇的内容就是这些了。如果你自己有动手能力,可以自己手动做一下本篇这个“GIS小玩具”,或者尝试自己增加逻辑,甚至应用啊:),比如这个插入星星,查询星星什么的。。。

2d571a1b41eea59a70c4072209627ba7.gif

当然,点击添加星星后可以注掉一行代码,不显示名称,点选之后再显示。这里为了动图好看就加上了。把星空做背景确实好看些,不过若是使用也确实蛮弱智的。。

看好关注,下期见!


2635a9660afa06e608ff1e1bf7f98fb8.png

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值