ArcGIS Engine 空间关系之判断点在面内

做项目遇到的问题。寥寥几行代码轻松解决,记录一下。

几何对象之间的空间关系主要有包含相等在内部相交等。矢量数据的空间关系运算需要用到 IRelationalOperation 接口,通过该接口的不同方法判定两个几何对象之间的关系是否存在。关系运算符用于比较两个几何体,并返回一个布尔类型值来说明某种控件关系是否存在。

空间包含关系(Contains & Within)

空间包含(Contains)表示当前几何对象包含输入几何对象。在内部(Within)表示当前几何对象在输入几何对象的内部。Contains 和 Within 是相对的关系,即 Contains 的反面就是 Within。

交叉(Crosses)

交叉(Crosses)表示线和线或者线和面的边界之间有相交。

相离(Disjoint)

相离(Disjoint)表示两个几何对象之间没有任何公共部分。

重叠(Overlaps)

重叠(Overlaps)表示两个同一维度的几何对象具有公共部分,并且公共部分和输入集合对象具有相同的维度。

相等(Equals)

相等(Equals)表示两个几何对象具有相同的几何维度、顶点集合等。对于多边形和线几何类型,如果它们具有相等关系,则 SymmetricDifference 方法返回值为空。

相接(Touches)

相接(Touches)表示两个几何对象的边界相交。如果两个几何对象相接,那么它们的交集不为空,但是集合对象的内部交集为空。


IRelationalOperator的一些关系类型:
关系类型 描述
Contains 判断一个图形是否包含另外一个图形
Within 判断一个图形是否被另外一个图形所包含。
Crosses 判断两个图形是否在维数较少的那个图形的内部相交
Disjoint 判断两个图形间是否没有相同点
Equals 判断两个图形是否是同一个类型并且在平面上的点是否是相同的位置。如果返回值为真,则它们应该包含(Contains)另外一个图形同时也被另外一个图形所包含(Within)。
Overlaps 判断两个图形的交集是否和其中的一个图形拥有相同的维数,并且他们交集不能和其中任何一个图形相等。该方法只使用与两个Polyline 之间或者两个Polygon 之间。
Touches 判断两个图形的边界是否相交,如果两个图形的交集不为空,但两个图形内部的交集为空,则返回值为真。

本文主要实现了判断点在面内(空间包含关系)

AE 代码见 Github:PointInPolygon (AE 版本 10.1,VS 版本 2017)

若代码不能运行,请添加如下引用:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
using ESRI.ArcGIS.Carto;
using ESRI.ArcGIS.esriSystem;
using ESRI.ArcGIS.Geodatabase;
using ESRI.ArcGIS.Geoprocessing;
using ESRI.ArcGIS.AnalysisTools;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using ESRI.ArcGIS.Geoprocessor;
using ESRI.ArcGIS.Geometry;

我主要实现了 判断点在面内 的方法,核心代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
private void pointInPolygonButton_Click(object sender, EventArgs e)
{
// 获得点图层
int PointId = 1;
IFeatureLayer PointLayer = null;
for (int i = 0; i < axMapControl1.LayerCount; i++)
{
PointLayer = axMapControl1.get_Layer(i) as IFeatureLayer;
if (PointLayer is IFeatureLayer && PointLayer.FeatureClass.ShapeType == esriGeometryType.esriGeometryPoint)
{
PointId = i;
}
}
if (PointId == -1)
{
MessageBox.Show("找不到质点图层,请重新加载", "提示", MessageBoxButtons.OK, MessageBoxIcon.Error);
return;
}

// 获得面图层
int PolygonId = -1;
IFeatureLayer PolygonLayer = null;
for (int i = 0; i < axMapControl1.LayerCount; i++)
{
PolygonLayer = axMapControl1.get_Layer(i) as IFeatureLayer;
if (PolygonLayer is IFeatureLayer && PolygonLayer.FeatureClass.ShapeType == esriGeometryType.esriGeometryPolygon)
{
PolygonId = i;
}
}
if (PolygonId == -1)
{
MessageBox.Show("找不到边界图层,请重新加载", "提示", MessageBoxButtons.OK, MessageBoxIcon.Error);
return;
}

PointLayer = axMapControl1.get_Layer(PointId) as IFeatureLayer;
PolygonLayer = axMapControl1.get_Layer(PolygonId) as IFeatureLayer;

IFeatureCursor PointFeatureCursor = PointLayer.Search(null, true);
IFeature PointFeature = PointFeatureCursor.NextFeature();

IFeatureCursor PolygonFeatureCursor = PolygonLayer.Search(null, true);
IFeature PolygonFeature = PolygonFeatureCursor.NextFeature();

IRelationalOperator pRelationalOperator = PolygonFeature.Shape as IRelationalOperator;

if (pRelationalOperator.Contains(PointFeature.Shape))
{
MessageBox.Show("点在面内!", "恭喜你!", MessageBoxButtons.OK, MessageBoxIcon.Information);
return;
}
else
{
MessageBox.Show("点在面外!", "很遗憾!", MessageBoxButtons.OK, MessageBoxIcon.Error);
return;
}
}

运行结果: