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

介绍

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的渲染结果就非常出色,可以用于数字地形渲染、动态制图等方向。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 213,558评论 6 492
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,002评论 3 387
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 159,036评论 0 349
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,024评论 1 285
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,144评论 6 385
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,255评论 1 292
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,295评论 3 412
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,068评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,478评论 1 305
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,789评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,965评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,649评论 4 336
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,267评论 3 318
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,982评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,223评论 1 267
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,800评论 2 365
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,847评论 2 351

推荐阅读更多精彩内容