疫情模拟——城市地点及路径设置

总体思路

疫情的模拟除了有人,我们还希望将“人”置于一个更加真实的环境中,使人在疫情中的行为更加“合理”。于是我们构建了若干个虚拟的“城市”,城市中有各种建筑,有道路。在保证我们需要的城市功能完整的情况下,为了降低城市的复杂度,我们在每个城市中设置了home(住宅)、market(菜场)、workplace(工作场所)、hospital(医院)、station(高铁站)、cross(路口)六种地标。这些地标在程序中都会被实例化为继承自place的子类对象,每个place对象中都存有这个对象的唯一标识符index、坐标position、到其他各个场所的路径集合,以及一些其他信息。
这部分的工作大体可以分为两个部分:1.城市的视效设计,2.各个“PlaceSystem”(为了方便代码的管理与调试,我们为每种地标构建了继承自“PlaceSystem”的子类系统)的初始化工作。

城市视效设计

在这里插入图片描述
这里的城市地图为我们的第一版设计,城市的布局参考了中心城市与其周边卫星城市的布局关系。这种布局能够使得每个简化版的城市之间联系更加紧密。在程序建模过程中,我们则并没有以中心城市与周边城市这种关系去定义这些城市。事实上,这种关系在这些虚拟的“微型”城市中会被弱化。城市中道路的设计我们参考了多种城市布局,包括网格状、环形放射状等。在绘制过程中,我们对其风格上进行了统一化处理,使其看上去更像一个整体。在城市的复杂度方面我们进行了多次尝试,综合考量了屏幕大小,视觉效果,人的运动等多方面因素之后,绘制了如上图所示的最终效果。

PlaceSystem的构建与初始化

对城市中的每种地标,我们都构建了一个继承自PlaceSystem的子类,以存放城市中每一个Place对象。因此,我们首先设想并讨论了各个“place”类的设计方案:

Place(父类)

父类Place包含四个属性:1.地点的类别——class;2.唯一标识地点的标识符——index;3.Place对象的坐标——pos;4.停留时间——staytime。
除此以外,人要在地图中沿着道路有目的地地运动起来,每一个place对象中还应该包括通往其他各类(除cross以外的类别)地点的路径。为了避免一些不太合理的“行为”,比如买完菜去上班,从医院去菜场等,我们将路径信息单独写在了每一个子类中:

Home(Place)

1.way_to_hospital:去往医院的路;
2.way_to_market:去往菜场的路;
3.way_to_station:去往车站的路;
4.way_to_work:去往工作的路;

Hospital(Place)

1.way_to_home:去往家的路;
2.way_to_work:去往工作的路;

3.intake:医院容纳量;
4.patientnum:已容纳人数

Work(Place)

1.way_to_hospital:去往医院的路;
2.way_to_market:去往菜场的路;
3.way_to_station:去往车站的路;
4.way_to_home:去往家的路;

Market(Place)

1.way_to_home:去往家的路;

Station(Place)

1.way_to_hospital:去往医院的路;
2.way_to_market:去往菜场的路;
3.way_to_home:去往家的路;
4.way_to_work:去往工作的路;

初始化

有了上述的想法之后,需要完成各个地点的初始化工作。初始化工作主要包括三部分:1.坐标信息以及标识符等基础信息的记录;2.各个地点路径的生成;3.数据记录与转存。

初始化——标识符、坐标信息

标识符、坐标信息的初始化我们通过ps标点实现,并将其记录到csv格式的文件中。
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

在csv文件中,我们还记录了与每一个地点直接相邻的地点标识,这一步的目的是为了初始化路径。

初始化——基于广度优先搜索初始化路径

路径初始化步骤在python中实现:
1.文件读取,构建各地点的邻接表:

def get_road(file_path):
    sheet = pd.read_excel(file_path)
    label_list = list(sheet["label"])
    label_class={}
    label_set=set(list(sheet["class"]))
    for sets in label_set:
        label_class[sets]=[]
    #print(label_class)
    place_info={}
    roads_tol = {}
    for i in range(len(label_list)):
        num_of_near = sheet.iloc[i, 4]
        roads_tol[label_list[i]] = list(sheet.iloc[i, 5:5 + num_of_near])
        classs=sheet.iloc[i,0]
        label_class[classs].append(sheet.iloc[i, 1])

        #place_info:
        place_info[label_list[i]]={}
        #index:
        place_info[label_list[i]]['index']=label_list[i]
        #position:
        position_str=sheet.iloc[i,3][1:-1].split(',')
        position=[float(pos) for pos in position_str]
        place_info[label_list[i]]['position']=position
        #class:
        place_info[label_list[i]]['class'] = classs



    #print(label_list,'\n',roads_tol,'\n',label_class,'\n',place_info)

    return label_list,roads_tol,label_class,place_info

2.构建广度优先搜索类,并定义最短路径生成函数:

class BFS_ROAD():
    def __init__(self, begin, label_list, roads_tol):
        self.begin = begin
        self.label_list = label_list
        self.roads_tol = roads_tol

    def init_dist(self):
        dist={}
        roads={}
        visted={}
        for label in self.label_list:
            dist[label]=10000
            roads[label]=[]
            visted[label]=False
        dist[self.begin]=1
        roads[self.begin]=[self.begin]

        return dist,roads,visted


    def bfs(self,target,roads_tol):
        #print(roads_tol)
        dist,roads,visted=self.init_dist()
        queue_save=[self.begin]
        while len(queue_save):
            place_out=queue_save[0]
            visted[place_out]=True
            queue_save=queue_save[1:]
            for near in roads_tol[place_out]:
                #print(near,visted)
                if not visted[near]:
                    if dist[near] > dist[place_out] + 1:
                        dist[near] = dist[place_out] + 1
                        roads_tmp=copy.deepcopy(roads[place_out])
                        roads_tmp.append(near)
                        roads[near] = roads_tmp
                    queue_save.append(near)

        #print(roads[target])
        return roads[target]

3.上述函数只是实现了最短路径的搜索,但在实际情况中,两个地点之间的路径一般不止一条,且单一的路径选择显得真实性不高。为了解决这一问题, 我们的做法是首先找到最短路径,随后随机删除最短路径中的某一段通路,在对删除后的路径进行广度优先搜索得到另一条通路。

def road_fromto(begin,end,inputfile):
    """

    :param begin: begin place
    :param end: end class
    :return:
    """
    label_list, roads_tol ,road_set,place_info= get_road(inputfile)
    road_ends=road_set[end]
    #print(road_ends)
    roada = BFS_ROAD(begin, label_list, roads_tol)
    roads_to_places=[]
    for road_end in road_ends:
        #print(roada.label_list)
        road1 = roada.bfs(road_end, roada.roads_tol)
        roadss = [road1]
        for i in range(len(road1) - 1):
            roads_tol_tmp = copy.deepcopy(roada.roads_tol)
            roads_tol_tmp[road1[i]].remove(road1[i + 1])
            road2 = roada.bfs(road_end, roads_tol_tmp)
            roadss.append(road2)
        new_road = []
        for road in roadss:
            if road not in new_road:
                new_road.append(road)
        for road in new_road:
            roads_to_places.append(road)
    return roads_to_places
初始化——基于json对数据进行转存

python生成的路径信息最终需要转存到p5.js的程序中。起初我们尝试了使用csv文件对地点的基础属性以及路径信息进行转存,但发现效率较低,且在读取多张表时信息的对应问题难以解决。
在这里插入图片描述
于是我们尝试使用了json格式的文件进行数据转存,使得问题得以很好地解决:
在这里插入图片描述
在python中保存json数据:

def write_json(inputfile,outputfile):
    label_list, roads_tol, road_set ,place_info= get_road(inputfile)

    for place in road_set["hm"]:
        place_info[place]['roads_otherplace']={}

        roads_work = road_fromto(place, "w", inputfile)
        roads_work=[road for road in roads_work if road!=[]]

        roads_station = road_fromto(place, "s", inputfile)
        roads_station = [road for road in roads_station if road != []]

        roads_hospital=road_fromto(place, "ho", inputfile)
        roads_hospital = [road for road in roads_hospital if road != []]

        roads_market=road_fromto(place,'m',inputfile)
        roads_market = [road for road in roads_market if road != []]

        place_info[place]['roads_otherplace']['work']=roads_work
        place_info[place]['roads_otherplace']['station'] = roads_station
        place_info[place]['roads_otherplace']['hospital'] = roads_hospital
        place_info[place]['roads_otherplace']['market'] = roads_market

    for place in road_set["ho"]:
        place_info[place]['roads_otherplace']={}

        roads_work = road_fromto(place, "w", inputfile)
        roads_work=[road for road in roads_work if road!=[]]

        roads_home = road_fromto(place, "hm", inputfile)
        roads_home = [road for road in roads_home if road != []]


        place_info[place]['roads_otherplace']['work']=roads_work
        place_info[place]['roads_otherplace']['home'] = roads_home

    for place in road_set["w"]:
        place_info[place]['roads_otherplace']={}

        roads_home = road_fromto(place, "hm", inputfile)
        roads_home=[road for road in roads_home if road!=[]]

        roads_station = road_fromto(place, "s", inputfile)
        roads_station = [road for road in roads_station if road != []]

        roads_hospital=road_fromto(place, "ho", inputfile)
        roads_hospital = [road for road in roads_hospital if road != []]

        roads_market=road_fromto(place,'m',inputfile)
        roads_market = [road for road in roads_market if road != []]

        place_info[place]['roads_otherplace']['home']=roads_home
        place_info[place]['roads_otherplace']['station'] = roads_station
        place_info[place]['roads_otherplace']['hospital'] = roads_hospital
        place_info[place]['roads_otherplace']['market'] = roads_market

    for place in road_set["s"]:
        place_info[place]['roads_otherplace']={}

        roads_home = road_fromto(place, "hm", inputfile)
        roads_home=[road for road in roads_home if road!=[]]

        roads_work = road_fromto(place, "w", inputfile)
        roads_work = [road for road in roads_work if road != []]

        roads_hospital=road_fromto(place, "ho", inputfile)
        roads_hospital = [road for road in roads_hospital if road != []]

        roads_market=road_fromto(place,'m',inputfile)
        roads_market = [road for road in roads_market if road != []]

        place_info[place]['roads_otherplace']['home']=roads_home
        place_info[place]['roads_otherplace']['work'] = roads_work
        place_info[place]['roads_otherplace']['hospital'] = roads_hospital
        place_info[place]['roads_otherplace']['market'] = roads_market

    for place in road_set["m"]:
        place_info[place]['roads_otherplace']={}

        roads_home = road_fromto(place, "hm", inputfile)
        roads_home=[road for road in roads_home if road!=[]]

        place_info[place]['roads_otherplace']['home']=roads_home

    print(place_info)
    place_info_str=json.dumps(place_info,indent=4)
    with open (outputfile,'w') as json_file:
        json_file.write(place_info_str)

在p5.js中读取并初始化类:

function preload(){
  city1_json=loadJSON("data/Place_info_json/city1_placeinfo.json")
  city2_json=loadJSON("data/Place_info_json/city2_placeinfo.json")
  city3_json=loadJSON("data/Place_info_json/city3_placeinfo.json")
  city4_json=loadJSON("data/Place_info_json/city4_placeinfo.json")
  city5_json=loadJSON("data/Place_info_json/city5_placeinfo.json")
  city6_json=loadJSON("data/Place_info_json/city6_placeinfo.json")

}

function System_data_pre(data_json){
  for (let key in data_json){
    if(data_json[key].class=='hm'){
      let place=[]
      //index:
      place.push(data_json[key].index)
      //position:
      place.push(createVector(data_json[key].position[0],data_json[key].position[0]))
      //ways:
      let way_tol=data_json[key].roads_otherplace
      let ways=[]
      let way_work=[]
      let way_station=[]
      let way_hospital=[]
      let way_market=[]

      for (let i in way_tol.work){
        way=way_tol.work[i]     
        let way_tmp=[]
        for (let j in way){
          let place_one=way[j]
          way_tmp.push(createVector(data_json[place_one].position[0],data_json[place_one].position[1]))
        }
        way_work.push(way_tmp)
        
      }
      ways.push(way_work)

      for (let i in way_tol.station){
        way=way_tol.station[i]     
        let way_tmp=[]
        for (let j in way){
          let place_one=way[j]
          way_tmp.push(createVector(data_json[place_one].position[0],data_json[place_one].position[1]))
        }
        way_station.push(way_tmp)
        
      }
      ways.push(way_station)

      for (let i in way_tol.hospital){
        way=way_tol.hospital[i]     
        let way_tmp=[]
        for (let j in way){
          let place_one=way[j]
          way_tmp.push(createVector(data_json[place_one].position[0],data_json[place_one].position[1]))
        }
        way_hospital.push(way_tmp)
        
      }
      ways.push(way_hospital)

      for (let i in way_tol.market){
        way=way_tol.market[i]     
        let way_tmp=[]
        for (let j in way){
          let place_one=way[j]
          way_tmp.push(createVector(data_json[place_one].position[0],data_json[place_one].position[1]))
        }
        way_market.push(way_tmp)
        
      }
      ways.push(way_market)
      place.push(ways)

      homes.push(place)
    }
    else if(data_json[key].class=='ho'){
      let place=[]
      //index:
      place.push(data_json[key].index)
      //position:
      place.push(createVector(data_json[key].position[0],data_json[key].position[0]))
      //ways:
      let way_tol=data_json[key].roads_otherplace
      let ways=[]
      let way_work=[]
      let way_home=[]

      for (let i in way_tol.work){
        way=way_tol.work[i]     
        let way_tmp=[]
        for (let j in way){
          let place_one=way[j]
          way_tmp.push(createVector(data_json[place_one].position[0],data_json[place_one].position[1]))
        }
        way_work.push(way_tmp)
        
      }
      ways.push(way_work)

      for (let i in way_tol.home){
        way=way_tol.home[i]     
        let way_tmp=[]
        for (let j in way){
          let place_one=way[j]
          way_tmp.push(createVector(data_json[place_one].position[0],data_json[place_one].position[1]))
        }
        way_home.push(way_tmp)
        
      }
      ways.push(way_home)
      place.push(ways)

      hospitals.push(place)
    }

    else if(data_json[key].class=='w'){
      let place=[]
      //index:
      place.push(data_json[key].index)
      //position:
      place.push(createVector(data_json[key].position[0],data_json[key].position[0]))
      //ways:
      let way_tol=data_json[key].roads_otherplace
      let ways=[]
      let way_home=[]
      let way_station=[]
      let way_hospital=[]
      let way_market=[]

      for (let i in way_tol.home){
        way=way_tol.home[i]     
        let way_tmp=[]
        for (let j in way){
          let place_one=way[j]
          way_tmp.push(createVector(data_json[place_one].position[0],data_json[place_one].position[1]))
        }
        way_home.push(way_tmp)
        
      }
      ways.push(way_home)

      for (let i in way_tol.station){
        way=way_tol.station[i]     
        let way_tmp=[]
        for (let j in way){
          let place_one=way[j]
          way_tmp.push(createVector(data_json[place_one].position[0],data_json[place_one].position[1]))
        }
        way_station.push(way_tmp)
        
      }
      ways.push(way_station)

      for (let i in way_tol.hospital){
        way=way_tol.hospital[i]     
        let way_tmp=[]
        for (let j in way){
          let place_one=way[j]
          way_tmp.push(createVector(data_json[place_one].position[0],data_json[place_one].position[1]))
        }
        way_hospital.push(way_tmp)
        
      }
      ways.push(way_hospital)

      for (let i in way_tol.market){
        way=way_tol.market[i]     
        let way_tmp=[]
        for (let j in way){
          let place_one=way[j]
          way_tmp.push(createVector(data_json[place_one].position[0],data_json[place_one].position[1]))
        }
        way_market.push(way_tmp)
        
      }
      ways.push(way_market)
      place.push(ways)

      works.push(place)
    }
    else if(data_json[key].class=='m'){
      let place=[]
      //index:
      place.push(data_json[key].index)
      //position:
      place.push(createVector(data_json[key].position[0],data_json[key].position[0]))
      //ways:
      let way_tol=data_json[key].roads_otherplace
      let ways=[]
      let way_home=[]

      for (let i in way_tol.home){
        way=way_tol.home[i]     
        let way_tmp=[]
        for (let j in way){
          let place_one=way[j]
          way_tmp.push(createVector(data_json[place_one].position[0],data_json[place_one].position[1]))
        }
        way_home.push(way_tmp)
        
      }
      ways.push(way_home)
      place.push(ways)

      markets.push(place)
    }
    else if(data_json[key].class=='s'){
      let place=[]
      //index:
      place.push(data_json[key].index)
      //position:
      place.push(createVector(data_json[key].position[0],data_json[key].position[0]))
      //ways:
      let way_tol=data_json[key].roads_otherplace
      let ways=[]
      let way_work=[]
      let way_home=[]
      let way_hospital=[]
      let way_market=[]

      for (let i in way_tol.work){
        way=way_tol.work[i]     
        let way_tmp=[]
        for (let j in way){
          let place_one=way[j]
          way_tmp.push(createVector(data_json[place_one].position[0],data_json[place_one].position[1]))
        }
        way_work.push(way_tmp)
        
      }
      ways.push(way_work)

      for (let i in way_tol.home){
        way=way_tol.home[i]     
        let way_tmp=[]
        for (let j in way){
          let place_one=way[j]
          way_tmp.push(createVector(data_json[place_one].position[0],data_json[place_one].position[1]))
        }
        way_home.push(way_tmp)
        
      }
      ways.push(way_home)

      for (let i in way_tol.hospital){
        way=way_tol.hospital[i]     
        let way_tmp=[]
        for (let j in way){
          let place_one=way[j]
          way_tmp.push(createVector(data_json[place_one].position[0],data_json[place_one].position[1]))
        }
        way_hospital.push(way_tmp)
        
      }
      ways.push(way_hospital)

      for (let i in way_tol.market){
        way=way_tol.market[i]     
        let way_tmp=[]
        for (let j in way){
          let place_one=way[j]
          way_tmp.push(createVector(data_json[place_one].position[0],data_json[place_one].position[1]))
        }
        way_market.push(way_tmp)
        
      }
      ways.push(way_market)
      place.push(ways)

      stations.push(place)
    }  
  }


}

function city_init(){
  let city1=new City("city1",["s1"],0.38)
  let city2=new City("city2",["s2"],0.67)
  let city3=new City("city3",["s3"],0.71)
  let city4=new City("city4",["s4"],0.89)
  let city5=new City("city5",["s5"],0.54)
  let city6=new City("city6",["s6","s7"],0.97)
  let citys=[city1,city2,city3,city4,city5,city6]
  return citys
}

function init_cityandwaytostation()
{
  //current_cities
  for(let i=0;i<6;i++){
    statSys.places[i].currentCity=citySys.citys[i]
  }
  statSys.places[6].currentCity=citySys.citys[5]

  //next_stations:
  statSys.places[0].connectstations=[statSys.places[1],statSys.places[3]]
  statSys.places[1].connectstations=[statSys.places[0],statSys.places[3],statSys.places[5],statSys.places[6]]
  statSys.places[2].connectstations=[statSys.places[3],statSys.places[4]]
  statSys.places[3].connectstations=[statSys.places[0],statSys.places[1],statSys.places[2]]
  statSys.places[4].connectstations=[statSys.places[2],statSys.places[5],statSys.places[6]]
  statSys.places[5].connectstations=[statSys.places[1],statSys.places[4],statSys.places[6]]
  statSys.places[6].connectstations=[statSys.places[1],statSys.places[4],statSys.places[5]]

  //way_to_stations:
  //s1:
  statSys.places[0].way_to_station=[[statSys.places[0].pos,createVector(4.29,8.34),createVector(4.64,8.64),createVector(7.53,8.20),statSys.places[1].pos],
[statSys.places[0].pos,createVector(5.70,4.75),statSys.places[3].pos]]
  
  statSys.places[1].way_to_station=[[statSys.places[1].pos,createVector(7.53,8.20),createVector(4.64,8.64),createVector(4.29,8.34),statSys.places[0].pos],
[statSys.places[1].pos,statSys.places[3].pos],
[statSys.places[1].pos,statSys.places[5].pos],
[statSys.places[1].pos,statSys.places[6].pos]]

  statSys.places[2].way_to_station=[[statSys.places[2].pos,createVector(8.61,2.66),statSys.places[3].pos],
[statSys.places[2].pos,createVector(11.12,3.85),statSys.places[4].pos]]

  statSys.places[3].way_to_station=[[statSys.places[3].pos,createVector(5.70,4.75),statSys.places[0].pos],
[statSys.places[3].pos,statSys.places[1].pos],
[statSys.places[3].pos,createVector(8.61,2.66),statSys.places[2].pos]]

  statSys.places[4].way_to_station=[[statSys.places[4].pos,createVector(11.12,3.85),statSys.places[2].pos],
[statSys.places[4].pos,createVector(14.35,4.85),statSys.places[5].pos],
[statSys.places[4].pos,statSys.places[6].pos]]

  statSys.places[5].way_to_station=[[statSys.places[5].pos,statSys.places[1].pos],
[statSys.places[5].pos,createVector(14.35,4.85),statSys.places[4].pos]
[statSys.places[5].pos,statSys.places[6].pos]]

  statSys.places[6].way_to_station=[[statSys.places[6].pos,statSys.places[1].pos],
[statSys.places[6].pos,statSys.places[4].pos],
[statSys.places[6].pos,statSys.places[5].pos]]
    


}

function initSystem_fromjson(){
  citys=city_init()

  citySys=new CitySystem(citys)

  homes=[]
  hospitals=[]
  works=[] 
  markets=[]
  stations=[] 

  System_data_pre(city1_json)
  System_data_pre(city2_json)
  System_data_pre(city3_json)
  System_data_pre(city4_json)
  System_data_pre(city5_json)
  System_data_pre(city6_json)

  homeSys=new HomeSystem(homes)
  hospSys=new HospitalSystem(hospitals)
  workSys=new WorkSystem(works)
  markSys=new MarketSystem(markets)
  statSys=new StationSystem(stations)

  init_cityandwaytostation()

  console.log(statSys)
  console.log(homeSys)
  console.log(hospSys)
  console.log(workSys)
  console.log(markSys)
  console.log(citySys)

}

function setup() {
  initSystem_fromjson()

  createCanvas(640, 320)
  colorMode(HSB, 360, 100, 100, 100)

}
  • 0
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值