非匀质空间下加权 Voronoi 图的生成

        在城市影响范围的划分中,区域内地形、交通、人口密度等异质要素直接影响城市辐射传播的快慢和覆盖范围,理想化的匀质空间划分不能真实反应实际情形。这就要求必须有一种算法能同时兼顾到目标中心强度、几何形状以及空间差异性。

       作者通过算法改进实现了非匀质空间下加权 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

  • 0
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

海亲王

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值