美文网首页
利用rayrender动态可视化全球人口密度

利用rayrender动态可视化全球人口密度

作者: Cubics | 来源:发表于2021-10-12 19:36 被阅读0次

    介绍

    rayrender 是一个R语言编写的开源包,用于创建光线跟踪场景。这个包为用 C++ 构建的光线追踪器提供了一个整洁的 R API,以渲染由一组基元构建的场景。 rayrender 使用可管道化的迭代界面构建场景,并支持漫反射、金属、电介质(玻璃)、发光材料,以及程序和用户指定的图像纹理和 HDR 环境照明。 rayrender 包括通过 RcppThread 的多核支持(带有进度条)、通过 PCG RNG 的随机数生成以及通过 TinyObrjLoader 的 .obj 文件支持。

    官网链接
    Build and Raytrace 3D Scenes • rayrender

    数据源

    NASA社会数据应用中心的世界格网人口数据V4版本,2010年30km级别数据

    下载链接
    https://sedac.ciesin.columbia.edu/data/set/gpw-v4-basic-demographic-characteristics-rev11/data-download

    可视化过程

    1. 安装R语言环境

    2. 安装rayrender,rayshader,rgdal,magick等包

    3. 运行脚本

    4. 利用Python脚本拼接单独生成的PNG格式的图片为GIF格式的图片

    可视化脚本

     library(rayshader)
     library(rayrender)
     
     popdata = raster::raster("gpw_v4_basic_demographic_characteristics_rev11_atotpopbt_2010_dens_15_min.tif")
     
     population_mat = rayshader:::flipud(raster_to_matrix(popdata))
     
     above1 = population_mat > 1
     above5 = population_mat > 5
     above10 = population_mat > 10
     above50 = population_mat > 50
     above100 = population_mat > 100
     above500 = population_mat > 500
     above1000 = population_mat > 1000
     
     above1[is.na(above1)] = 0
     above5[is.na(above5)] = 0
     above10[is.na(above10)] = 0
     above50[is.na(above50)] = 0
     above100[is.na(above100)] = 0
     above500[is.na(above500)] = 0
     above1000[is.na(above1000)] = 0
     
     
     turbocols = viridis::turbo(7)
     wc = 0.4
     
     chart_items = 
      xy_rect(x=-1,y=-1.4,z=1,xwidth=wc,ywidth=0.2, 
      material=diffuse(color="grey30")) %>% 
      add_object(text3d(label = "0", x=-1,y=-1.4,z=1.01, text_height = 0.1, 
      material=diffuse(color="black"))) %>% 
      add_object(xy_rect(x=-0.6,y=-1.4,z=1,xwidth=wc,ywidth=0.2, 
      material=diffuse(color=turbocols[1]))) %>% 
      add_object(text3d(label = "1>", x=-0.6,y=-1.4,z=1.01, text_height = 0.1, 
      material=diffuse(color="black"))) %>% 
      add_object(xy_rect(x=-0.2,y=-1.4,z=1,xwidth=wc,ywidth=0.2, 
      material=diffuse(color=turbocols[2]))) %>% 
      add_object(text3d(label = "5>", x=-0.2,y=-1.4,z=1.01, text_height = 0.1, 
      material=diffuse(color="black"))) %>% 
      add_object(xy_rect(x=0.2,y=-1.4,z=1,xwidth=wc,ywidth=0.2, 
      material=diffuse(color=turbocols[3]))) %>% 
      add_object(text3d(label = "10>", x=0.2,y=-1.4,z=1.01, text_height = 0.1, 
      material=diffuse(color="black"))) %>% 
      add_object(xy_rect(x=0.6,y=-1.4,z=1,xwidth=wc,ywidth=0.2, 
      material=diffuse(color=turbocols[4]))) %>% 
      add_object(text3d(label = "50>", x=0.6,y=-1.4,z=1.01, text_height = 0.1, 
      material=diffuse(color="black"))) %>% 
      add_object(xy_rect(x=1.0,y=-1.4,z=1,xwidth=wc,ywidth=0.2, 
      material=diffuse(color=turbocols[5]))) %>% 
      add_object(text3d(label = "100>", x=1.0,y=-1.4,z=1.01, text_height = 0.1,
      material=diffuse(color="black"))) %>%
      add_object(xy_rect(x=1.4,y=-1.4,z=1,xwidth=wc,ywidth=0.2,
      material=diffuse(color=turbocols[6]))) %>%
      add_object(text3d(label = "500>", x=1.4,y=-1.4,z=1.01, text_height = 0.1,
      material=diffuse(color="black"))) %>%
      add_object(xy_rect(x=1.8,y=-1.4,z=1,xwidth=wc,ywidth=0.2,
      material=diffuse(color=turbocols[7]))) %>%
      add_object(text3d(label = "1000>", x=1.8,y=-1.4,z=1.01, text_height = 0.1,
      material=diffuse(color="black"))) %>%
      add_object(text3d(label = "People per 30km^2", x=-0.55,y=-1.2,z=1.01, text_height = 0.15,
      material=diffuse(color="white"))) %>%
      group_objects(group_translate = c(-0.4,0,0),group_scale=c(0.85,0.85,0.85))
     
     radm = 1.2
     for(i in 1:720) {
      chart_items %>% 
      add_object(group_objects(
      sphere(radius=0.99*radm,material=diffuse(color="grey20")) %>% 
      add_object(sphere(radius=1.0*radm,material= diffuse(color=turbocols[1],alpha_texture = above1))) %>% 
      add_object(sphere(radius=1.02*radm,material=diffuse(color=turbocols[2],alpha_texture = above5))) %>% 
      add_object(sphere(radius=1.03*radm,material=diffuse(color=turbocols[3],alpha_texture = above10))) %>% 
      add_object(sphere(radius=1.04*radm,material=diffuse(color=turbocols[4],alpha_texture = above50))) %>% 
      add_object(sphere(radius=1.05*radm,material=diffuse(color=turbocols[5],alpha_texture = above100))) %>% 
      add_object(sphere(radius=1.06*radm,material=diffuse(color=turbocols[6],alpha_texture = above500))) %>% 
      add_object(sphere(radius=1.07*radm,material=diffuse(color=turbocols[7],alpha_texture = above1000))),
      group_angle = c(0,-i/2,0))) %>% 
      add_object(sphere(y=10,z=5,radius=3,material=light(intensity = 20))) %>%
      add_object(sphere(y=0,z=20,radius=3,material=light(intensity = 20))) %>%
      render_scene(width=1000,height=1000,samples=128,rotate_env = 180,clamp_value = 10,
      aperture=0,
      filename=sprintf("worldpopfocus%i.png",i), lookat=c(0,-0.2,0))
     }
    

    单帧生成的结果图

    worldpopfocus1.png

    利用Python脚本拼接多张PNG图像

     import imageio
     
     def create_gif(image_list, gif_name):
      frames = []
      for image_name in image_list:
      frames.append(imageio.imread(image_name))
      imageio.mimsave(gif_name, frames, 'GIF', duration=0.1)
      return
     
     
     def main():
      image_list = ["rayrender\worldpopfocus" +
      str(x)+".png" for x in range(1, 200)]
      gif_name = 'rayrender\created_gif.gif'
      create_gif(image_list, gif_name)
     
     
     if __name__ == "__main__":
      main()
    

    动态可视化结果

    部分地区人口密度动态图.gif

    总结

    rayrender提供了非常方便简洁的调用方式,即可实现很强的光线渲染效果。在GIS领域,如何实现好的光线渲染效果是一个比较热门的研究方向,而rayrender的渲染结果就非常出色,可以用于数字地形渲染、动态制图等方向。

    相关文章

      网友评论

          本文标题:利用rayrender动态可视化全球人口密度

          本文链接:https://www.haomeiwen.com/subject/llrjoltx.html