ArcGIS水文分析

ArcGIS水文分析

rygdsddssd God

ArcGIS操作

老师给的教程与下文类似

【教程】ArcGIS水文分析提取河流及流域

不过老师的教程中没有河流链接这一步

最终做出的效果如下

编程操作

GridSame.txt和GridDiff.txt分别是我是否进行河流链接的最终结果。

不进行 河流连接 最后结果中grid_id全部 相同 ,为1,河段数 316

进行 河流连接 之后grid_id 不同 ,但是河段多了非常多, 47000+

数据结构

临时

下面这是读取文件使用的临时数据结构

文件中的结构:
OBJECTID,ARCID,grid_code,from_node,to_node,Shape_Length

因为Shape_Length是Double类型,

所以arcData存前面的数据,meters就是后面的Length

1
2
List<int[]> arcData = new ArrayList<>();
ArrayList<Double> meters = new ArrayList<Double>();

持久

以下是我用来存储数据的三个结构。

数据结构

List<int[]> Rivers_Nodes = new ArrayList<>();
List Rivers_Length = new ArrayList<>();
List<int[]> Rivers_Arcs = new ArrayList<>();

各个List<>依次对应,即Rivers_Nodes.get(i)对应Rivers_Length.get(i)和Rivers_Arcs.get(i);
他们分别是河流i的结点集,总长度,边集。
原始数据太少无法建立河流拓扑,就使用了简单的数据结构。

Tips

其实List<int[]>不是很方便,每次添加新元素进Nodes和Arcs的集合非常麻烦,应该整个嵌套List的,或者弄一个List数组

然后封装一下这个数组的添加删除修改操作,操作时需要检查数组大小和上限(数据结构乱入)

1
List<Integer> lis[]=new ArrayList[MaxSize+1];

懒得再改了

下面这段代码就是用来添加新边新点的,其实我应该封装一下的,不过不是什么重要玩意儿,懒得搞了

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
//添加边
int[] temp1 = new int[Rivers_Arcs.get(river_id).length+1];
//复制
for (int k = 0; k < Rivers_Arcs.get(river_id).length; k++) {
temp1[k]=Rivers_Arcs.get(river_id)[k];
}
temp1[temp1.length-1]=b[0];
Rivers_Arcs.set(river_id,temp1);
for (int j = i; j < RiversNodes.get(river_id).length; j++) {
if(RiversNodes.get(river_id)[j] == a[0]){
//这里说明a[0],a[1]都已存在
continue;
}
}
//这里说明a[1]存在,a[0]不存在,需要添加a[0]
int[] temp2 = new int[RiversNodes.get(river_id).length+1];
//复制
for (int k = 0; k < RiversNodes.get(river_id).length; k++) {
temp2[k]=RiversNodes.get(river_id)[k];
}
//添加
temp2[temp2.length-1]=a[0];
RiversNodes.set(river_id,temp2);
return;

ReadTxt

没有细化了,直接网上找的模板弄的

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
    public static void ReadTxt(List<int[]> arcs,ArrayList<Double> meters){
try {
String fileName = "src/GridSame.txt";
// String fileName = "src/GridDiff.txt";
File file = new File(fileName);
FileInputStream fis = null;
fis = new FileInputStream(file);
InputStreamReader isr = new InputStreamReader(fis);
BufferedReader br = new BufferedReader(isr);

String line;
line = br.readLine();
// if(line!=null){
// System.out.println(line);
// }
while((line = br.readLine()) != null){
String[] arc_S = line.split(",");
int[] arc = new int[5];
for (int i = 0; i < 5; i++) {
arc[i]=Integer.parseInt(arc_S[i]);
}
arcs.add(arc);
meters.add(Double.parseDouble(arc_S[5]));
}
br.close();
} catch (Exception e) {
e.printStackTrace();
}
}

addNodes

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
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
public static void addNodes(List<int[]> RiversNodes,List<int[]> Rivers_Arcs,List<Double> Rivers_Length,int[] arc,Double m){
int[] a = new int[2];
a[0]=arc[3];
a[1]=arc[4];
int[] b = new int[1];
b[0] = arc[1];

if(RiversNodes.isEmpty()){
RiversNodes.add(a);
// RiversNodes.set(0,a);
// Rivers_Length.set(0,m);
Rivers_Arcs.add(b);
Rivers_Length.add(m);
return;
}
for (int river_id = 0; river_id < RiversNodes.size(); river_id++) {
for (int i = 0; i < RiversNodes.get(river_id).length; i++) {
if(RiversNodes.get(river_id)[i] == a[0] ){
//若a[0]已存在,累加长度
Rivers_Length.set(river_id,Rivers_Length.get(river_id)+m);
//添加边
int[] temp1 = new int[Rivers_Arcs.get(river_id).length+1];
//复制
for (int k = 0; k < Rivers_Arcs.get(river_id).length; k++) {
temp1[k]=Rivers_Arcs.get(river_id)[k];
}
temp1[temp1.length-1]=b[0];
Rivers_Arcs.set(river_id,temp1);

for (int j = 0; j < Rivers_Arcs.get(river_id).length; j++) {
if(Rivers_Arcs.get(river_id)[j] == b[0]){
continue;
}
}

for (int j = i; j < RiversNodes.get(river_id).length; j++) {
if(RiversNodes.get(river_id)[j] == a[1]){
//这里说明a[0],a[1]都已存在
return;
}
}
//这里说明a[0]存在,a[1]不存在,需要添加a[1]
int[] temp2 = new int[RiversNodes.get(river_id).length+1];
//复制
for (int k = 0; k < RiversNodes.get(river_id).length; k++) {
temp2[k]=RiversNodes.get(river_id)[k];
}
//添加
temp2[temp2.length-1]=a[1];
RiversNodes.set(river_id,temp2);
return;
}

if(RiversNodes.get(river_id)[i] == a[1]){
//这里说明a[1]存在,累加长度
Rivers_Length.set(river_id,Rivers_Length.get(river_id)+m);

//添加边
int[] temp1 = new int[Rivers_Arcs.get(river_id).length+1];
//复制
for (int k = 0; k < Rivers_Arcs.get(river_id).length; k++) {
temp1[k]=Rivers_Arcs.get(river_id)[k];
}
temp1[temp1.length-1]=b[0];
Rivers_Arcs.set(river_id,temp1);
for (int j = i; j < RiversNodes.get(river_id).length; j++) {
if(RiversNodes.get(river_id)[j] == a[0]){
//这里说明a[0],a[1]都已存在
continue;
}
}
//这里说明a[1]存在,a[0]不存在,需要添加a[0]
int[] temp2 = new int[RiversNodes.get(river_id).length+1];
//复制
for (int k = 0; k < RiversNodes.get(river_id).length; k++) {
temp2[k]=RiversNodes.get(river_id)[k];
}
//添加
temp2[temp2.length-1]=a[0];
RiversNodes.set(river_id,temp2);
return;
}
}
}
//到这里说明a[0],a[1]都不存在,直接加上
RiversNodes.add(a);
Rivers_Length.add(m);
Rivers_Arcs.add(b);

}

printResult

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
public static void printResult(List<int[]> Rivers_Nodes,List<int[]> Rivers_Arcs,ArrayList<Double> meters) {
System.out.println("以下为整理好的河网");
System.out.println();
System.out.println("---------------------------------------------");
System.out.println("河流id");
System.out.println("结点id");
System.out.println("边id");
System.out.println("河流总长");
System.out.println("---------------------------------------------");
System.out.println();
System.out.println();
System.out.println("---------------------------------------------");
for (int k = 0; k < Rivers_Nodes.size(); k++) {
System.out.println("River_id:" + k);
System.out.print("Nodes:");
for (int j = 0; j < Rivers_Nodes.get(k).length; j++) {
System.out.print(Rivers_Nodes.get(k)[j] + " ");
}
System.out.println();
System.out.print("Arcs:");
for (int j = 0; j < Rivers_Arcs.get(k).length; j++) {
System.out.print(Rivers_Arcs.get(k)[j] + " ");
}
System.out.println();
System.out.println("Length:"+ meters.get(k));
System.out.println("---------------------------------------------");
}
}

Main

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
public static void main(String[] args) {
List<int[]> arcData = new ArrayList<>();
ArrayList<Double> meters = new ArrayList<Double>();
//OBJECTID(无意义),ARCID(无用),grid_code(无用),from_node,to_node,Shape_Length
ReadTxt(arcData,meters);
//控制台打印
// for (int i = 0; i < arcData.size(); i++) {
// for (int j = 0; j < arcData.get(i).length; j++) {
// System.out.print(arcData.get(i)[j]+" ");
// }
// System.out.println(meters.get(i));
// }
//ArcID==TO_NODE时说明为末端结点

//遍历arcData,在Rivers_Nodes中查询from_node和to_node,首次出现就说明属于一段新河流的,
// 将其from_node和to_node放到Rivers_nodes中,其Length加到对应的River_Length中
List<int[]> Rivers_Nodes = new ArrayList<>();
List<Double> Rivers_Length = new ArrayList<>();
List<int[]> Rivers_Arcs = new ArrayList<>();

for (int i = 0; i < arcData.size(); i++) {
addNodes(Rivers_Nodes,Rivers_Arcs,Rivers_Length,arcData.get(i),meters.get(i));
}

printResult(Rivers_Nodes,Rivers_Arcs,meters);

}

总结

最后结果是66条河流,明显不符合实际,仔细观察结果发现有些河段与其他河段“断联”了,没有完全连接。

思考

没有完全链接的原因猜测:

  • 水文处理没有处理汇(看到有说默认填洼和处理汇的 结果是一样的,基本可以排除)

  • 没有进行河网连接,不过进行河网链接之后反而输出的结果中河段多了非常多(河段47000+,最终河流12000-反而“断联”的情况更严重)不知道怎么回事,唉

    GPT的解释:

收获

  • 熟悉了ArcGIS水文分析相关步骤与知识

  • 简单练习了java语法

  • 标题: ArcGIS水文分析
  • 作者: rygdsddssd
  • 创建于 : 2023-04-26 01:20:40
  • 更新于 : 2023-04-30 17:09:19
  • 链接: http://rygdsddssd.github.io/2023/04/26/ArcGIS水文分析/
  • 版权声明: 本文章采用 CC BY-NC-SA 4.0 进行许可。
 评论