在城市影响范围的划分中,区域内地形、交通、人口密度等异质要素直接影响城市辐射传播的快慢和覆盖范围,理想化的匀质空间划分不能真实反应实际情形。这就要求必须有一种算法能同时兼顾到目标中心强度、几何形状以及空间差异性。
作者通过算法改进实现了非匀质空间下加权 Voronoi 图的生成,该算法兼顾了目标中心强度、几何形状以及空间差异性。在城市影响范围的划分中,可以将交通、地形等传导因素考虑在内。
图1 非匀质空间(路网+坡度)下,面状城市目标影响范围划分(本文加权Voronoi算法)
图2 匀质空间下(不考虑地形和路网),点状城市目标影响范围划分(传统加权Voronoi)
对比上两图,当研究区域山区较多,交通路网受地形影响分布不均匀,均质空间加权 V 图划分结果不能反映交通路网和地形特点,非匀质空间加权 V 图沿交通路网和地形分布,城市影响范围划分结果反映了交通路网和地形特点更贴近实际情况。
如有算法和软件需求请联系QQ406803725
软件核心模块界面如下
这里的“输入要素”为带权重的目标(城市),可以是点、线、面任意形状。
代码片段(c#版):
private void Scanfhole(int h, int w, int[,] Q, int[] NA)//扫描给定的领域
{
if (T[w, h].cWeight != max_min)
{
T[w, h].Distance = o_dis;//设置为初始值
//记录原父结点行列号
int w_father = (int)T[w, h].W_Father;
int h_father = (int)T[w, h].H_Father;
for (int n = 0; n < NA.Length; n++)
{
int x = w + Q[NA[n], 1];
int y = h + Q[NA[n], 0];
if ((T[x, y].O_num != max_min)&&((T[x, y].H_Father!=h)||(T[x, y].W_Father!=w))
{
double oneDistance = max_min;
switch (distanceMode)
{
case 1://棋盘距离
oneDistance = T[x, y].Distance + (Math.Sqrt(Math.Pow(x - w, 2) + Math.Pow(y - h, 2)) / T[x, y].Weight) * T[w, h].cWeight;
break;
case 2://欧氏距离
oneDistance = Math.Sqrt(Math.Pow(w - T[x, y].O_x, 2) + Math.Pow(h - T[x, y].O_y, 2)) / T[x, y].Weight; ;
break;
}
if (oneDistance < 0)
oneDistance = 0;
if (oneDistance < T[w, h].Distance || T[w, h].Distance == max_min)
{
T[w, h].Distance = oneDistance;
T[w, h].O_x = T[x, y].O_x;
T[w, h].O_y = T[x, y].O_y;
T[w, h].O_num = T[x, y].O_num;
T[w, h].Weight = T[x, y].Weight;
T[w, h].W_Father = x;
T[w, h].H_Father = y;
}
}
}
if (T[w, h].Distance != o_dis)//如果该结点被打通,才进行下一步操作
{
bool YN_Leaf = true;//判断是否到达叶子,看是否进行回溯迭代,排除击穿现象。
for (int n = 0; n < NA.Length; n++)
{
int x = w + Q[NA[n], 1];
int y = h + Q[NA[n], 0];
if ((T[x, y].H_Father == h) && (T[x, y].W_Father == w))//递归处理子结点,这种深度递归(深度优先遍历)
{
YN_Leaf = false;
Scanfhole(y, x, Q, NA);
}
}
//2022-05-31 对叶结点的父结点进行回溯,应对击穿现象,但对比变化不是很大
if (YN_Leaf && (!YN_FatherNode(h, w, h_father, w_father)) && (T[w, h].O_num != max_min))
{
Scanfhole(h_father, w_father, Q, NA);
}
}
}
}
代码片段(python版):
def scanfhole(i,j,q,na):
distance[i,j]=10000000
l=0
while l<len(na):
t=na[l]#邻域l
ti=i+q[t][0]#邻域行号
tj=j+q[t][1]#邻域列号
if x[ti,tj]!=10000000 and (r_father[ti,tj]!=i or c_father[ti,tj]!=j):#邻域已经有传递过来的目标,且不是子节点,才执行下列操作
#tempdistance=(pow((x[ti,tj]-i),2)+pow((y[ti,tj]-j),2))#不加权
#tempdistance=(pow((x[ti,tj]-i),2)+pow((y[ti,tj]-j),2))/m_weight[ti,tj]#加权,仅目标
tempdistance=distance[ti,tj]+math.sqrt(pow(q[t][0],2)+pow(q[t][1],2))/(m_weight[ti,tj])*0.5*(1/c_weight[ti,tj]+1/c_weight[i,j])#加权,目标+传递
if tempdistance<distance[i,j]:
x[i,j]=x[ti,tj]
y[i,j]=y[ti,tj]
r_father[i,j]=ti
c_father[i,j]=tj
distance[i,j]=tempdistance
m_weight[i,j]=m_weight[ti,tj]
table[i,j]=table[x[i,j],y[i,j]]
l+=1
l=0
while l<len(na):
t=na[l]#邻域l
ti=i+q[t][0]#邻域行号
tj=j+q[t][1]#邻域列号
if (r_father[ti,tj]==i and c_father[ti,tj]==j):#邻域是子节点,才执行下列操作
scanfhole(ti,tj,q,na)
l+=1
return 0