forked from tylermorganwall/rayshader
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
-Added plot_3d, a function to take hillshades/textures and visualize them with an elevation matrix in 3D. Includes water visualization and the ability to view the map as a solid object. -Added zscale argument to detect_water. -Changed default orientation to match the orientation of the matrix. -Changed detect_water and calculate_normals to not show a progress bar by default. -Changed ambient_shade to default to 1-45 degrees, instead of 0-45. -Changed write_png to stop when user doesn’t provide a filename. -Updated README
- Loading branch information
1 parent
aa61f1e
commit ba0dc1a
Showing
33 changed files
with
647 additions
and
88 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -5,7 +5,7 @@ Version: 0.4.0 | |
Date: 2018-06-30 | ||
Author: Tyler Morgan-Wall | ||
Maintainer: Tyler Morgan-Wall <[email protected]> | ||
Description: Uses ray tracing to produce global illumination maps of elevation matrices. | ||
Description: Uses a combination of raytracing, spherical UV mapping, Lambertian reflectance, and ambient occlusion to produce hillshades of elevation matrices. Includes water detection and layering, programmable color palette generation, several built-in textures, and 2D and 3D plotting options. | ||
License: GPL-3 | ||
Imports: doParallel, | ||
foreach, | ||
|
@@ -17,7 +17,8 @@ Imports: doParallel, | |
png, | ||
akima, | ||
magrittr, | ||
rgl | ||
rgl, | ||
imager | ||
LinkingTo: Rcpp, progress | ||
RoxygenNote: 6.0.1 | ||
URL: https://github.com/tylermorganwall/rayshader | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,47 @@ | ||
#'@title make_base | ||
#' | ||
#'@description Makes the base below the 3D elevation map. | ||
#' | ||
#'@param heightmap A two-dimensional matrix, where each entry in the matrix is the elevation at that point. All points are assumed to be evenly spaced. | ||
#'@param basedepth Default `0`. | ||
#'@param basecolor Default `grey20`. | ||
#'@param zscale Default `1`. The ratio between the x and y spacing (which are assumed to be equal) and the z axis. For example, if the elevation levels are in units | ||
#'of 1 meter and the grid values are separated by 10 meters, `zscale` would be 10. | ||
#'@keywords internal | ||
make_base = function(heightmap,basedepth=0,basecolor="grey20",zscale=1) { | ||
heightmap = heightmap[,ncol(heightmap):1]/zscale | ||
heightmap1 = heightmap[1,] | ||
heightmap2 = heightmap[,1] | ||
heightmap3 = heightmap[nrow(heightmap),] | ||
heightmap4 = heightmap[,ncol(heightmap)] | ||
heightlist1 = list() | ||
heightlist2 = list() | ||
heightlist3 = list() | ||
heightlist4 = list() | ||
heightlist5 = list() | ||
for(i in 1:(length(heightmap1)-1)) { | ||
heightlist1[[i]] = matrix(c(1,1,1, heightmap1[i],basedepth,basedepth, i,i,i+1),3,3) | ||
heightlist1[[i+length(heightmap1)]] = matrix(c(1,1,1, heightmap1[i],basedepth,heightmap1[i+1], i,i+1,i+1),3,3) | ||
} | ||
heightmat1 = do.call(rbind,heightlist1) | ||
for(i in 1:(length(heightmap2)-1)) { | ||
heightlist2[[i]] = matrix(c(i,i+1,i, heightmap2[i],basedepth,basedepth, 1,1,1),3,3) | ||
heightlist2[[i+length(heightmap2)]] = matrix(c(i,i+1,i+1, heightmap2[i],heightmap2[i+1],basedepth, 1,1,1),3,3) | ||
} | ||
heightmat2 = do.call(rbind,heightlist2) | ||
for(i in 1:(length(heightmap3)-1)) { | ||
heightlist3[[i]] = matrix(c(nrow(heightmap),nrow(heightmap),nrow(heightmap), heightmap3[i],basedepth,basedepth, i,i+1,i),3,3) | ||
heightlist3[[i+length(heightmap3)]] = matrix(c(nrow(heightmap),nrow(heightmap),nrow(heightmap), heightmap3[i],heightmap3[i+1],basedepth, i,i+1,i+1),3,3) | ||
} | ||
heightmat3 = do.call(rbind,heightlist3) | ||
for(i in 1:(length(heightmap4)-1)) { | ||
heightlist4[[i]] = matrix(c(i,i,i+1, heightmap4[i],basedepth,basedepth, ncol(heightmap),ncol(heightmap),ncol(heightmap)),3,3) | ||
heightlist4[[i+length(heightmap4)]] = matrix(c(i,i+1,i+1, heightmap4[i],basedepth,heightmap4[i+1], ncol(heightmap),ncol(heightmap),ncol(heightmap)),3,3) | ||
} | ||
heightmat4 = do.call(rbind,heightlist4) | ||
heightlist5[[1]] = matrix(c(0,nrow(heightmap),nrow(heightmap),basedepth,basedepth,basedepth,0,0,ncol(heightmap)),3,3) | ||
heightlist5[[2]] = matrix(c(0,0,nrow(heightmap),basedepth,basedepth,basedepth,ncol(heightmap),0,ncol(heightmap)),3,3) | ||
heightmat5 = do.call(rbind,heightlist5) | ||
fullsides = rbind(heightmat1,heightmat2,heightmat3,heightmat4,heightmat5) | ||
rgl::triangles3d(fullsides,lit=FALSE,color=basecolor,front="fill",back="culled") | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
#'@title make_lines | ||
#' | ||
#'@description Makes the lines in the corner of the base. | ||
#' | ||
#'@param heightmap A two-dimensional matrix, where each entry in the matrix is the elevation at that point. All points are assumed to be evenly spaced. | ||
#'@param basedepth Default `0`. | ||
#'@param linecolor Default `grey40`. | ||
#'@param zscale Default `1`. The ratio between the x and y spacing (which are assumed to be equal) and the z axis. For example, if the elevation levels are in units | ||
#'of 1 meter and the grid values are separated by 10 meters, `zscale` would be 10. | ||
#'@param alpha Default `1`. Transparency. | ||
#'@param linewidth Default `2`. Linewidth | ||
#'@keywords internal | ||
make_lines = function(heightmap,basedepth=0,linecolor="grey40",zscale=1,alpha=1,linewidth = 2) { | ||
heightmap = heightmap[,ncol(heightmap):1]/zscale | ||
heightval1 = heightmap[2,2] | ||
heightval2 = heightmap[nrow(heightmap)-1,2] | ||
heightval3 = heightmap[2,ncol(heightmap)-1] | ||
heightval4 = heightmap[nrow(heightmap)-1,ncol(heightmap)-1] | ||
heightlist = list() | ||
heightlist[[1]] = matrix(c(1,1,basedepth,heightval1,1,1),2,3) | ||
heightlist[[2]] = matrix(c(nrow(heightmap),nrow(heightmap),basedepth,heightval2,1,1),2,3) | ||
heightlist[[3]] = matrix(c(1,1,basedepth,heightval3,ncol(heightmap),ncol(heightmap)),2,3) | ||
heightlist[[4]] = matrix(c(nrow(heightmap),nrow(heightmap),basedepth,heightval4,ncol(heightmap),ncol(heightmap)),2,3) | ||
for(i in 1:4) { | ||
rgl::lines3d(heightlist[[i]],color=linecolor,lwd=linewidth,alpha=alpha) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
#'@title make_shadow | ||
#' | ||
#'@description Makes the base below the 3D elevation map. | ||
#' | ||
#'@param rows A two-dimensional matrix, where each entry in the matrix is the elevation at that point. All points are assumed to be evenly spaced. | ||
#'@param cols Default `0`. | ||
#'@param basedepth Default `grey20`. | ||
#'@param shadowwidth Default `50`. Shadow width. | ||
#'@import imager | ||
#'@keywords internal | ||
make_shadow = function(rows, cols, basedepth, shadowwidth) { | ||
basedepth = matrix(basedepth,nrow = rows+shadowwidth*2, ncol = cols+shadowwidth*2) | ||
imagemat = matrix(1,nrow = rows+shadowwidth*2, ncol = cols+shadowwidth*2) | ||
imagemat[shadowwidth:(rows-shadowwidth),shadowwidth:(cols-shadowwidth)] = 0 | ||
shadowarray = as.array(imager::isoblur(imager::as.cimg(imagemat),sigma=shadowwidth/2))[,,1,1] | ||
browser() | ||
tempmap = tempfile() | ||
write_png(shadowarray,tempmap) | ||
rgl.surface((-shadowwidth+1):(rows+shadowwidth),(-shadowwidth):(cols+shadowwidth-1),basedepth,texture=paste0(tempmap,".png"),lit=FALSE) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,52 @@ | ||
#'@title make_water | ||
#' | ||
#'@description Makes the base below the 3D elevation map. | ||
#' | ||
#'@param heightmap A two-dimensional matrix, where each entry in the matrix is the elevation at that point. All points are assumed to be evenly spaced. | ||
#'@param waterheight Default `0`. | ||
#'@param watercolor Default `blue`. | ||
#'@param zscale Default `1`. The ratio between the x and y spacing (which are assumed to be equal) and the z axis. For example, if the elevation levels are in units | ||
#'of 1 meter and the grid values are separated by 10 meters, `zscale` would be 10. | ||
#'@param wateralpha Default `0.5`. Water transparency. | ||
make_water = function(heightmap,waterheight=mean(heightmap),watercolor="lightblue",zscale=1,wateralpha=0.5) { | ||
heightmap = heightmap[,ncol(heightmap):1]/zscale | ||
heightmap1 = heightmap[1,] | ||
heightmap2 = heightmap[,1] | ||
heightmap3 = heightmap[nrow(heightmap),] | ||
heightmap4 = heightmap[,ncol(heightmap)] | ||
heightlist1 = list() | ||
heightlist2 = list() | ||
heightlist3 = list() | ||
heightlist4 = list() | ||
heightlist5 = list() | ||
for(i in 1:(length(heightmap1)-1)) { | ||
if(heightmap1[i] < waterheight) { | ||
heightlist1[[i]] = matrix(c(1,1,1, heightmap1[i],waterheight,waterheight, i,i,i+1),3,3)[c(1,3,2),] | ||
heightlist1[[i+length(heightmap1)]] = matrix(c(1,1,1, heightmap1[i],waterheight,heightmap1[i+1], i,i+1,i+1),3,3)[c(1,3,2),] | ||
} | ||
} | ||
heightmat1 = do.call(rbind,heightlist1) | ||
for(i in 1:(length(heightmap2)-1)) { | ||
if(heightmap2[i] < waterheight) { | ||
heightlist2[[i]] = matrix(c(i,i+1,i, heightmap2[i],waterheight,waterheight, 1,1,1),3,3)[c(1,3,2),] | ||
heightlist2[[i+length(heightmap2)]] = matrix(c(i,i+1,i+1, heightmap2[i],heightmap2[i+1],waterheight, 1,1,1),3,3)[c(1,3,2),] | ||
} | ||
} | ||
heightmat2 = do.call(rbind,heightlist2) | ||
for(i in 1:(length(heightmap3)-1)) { | ||
if(heightmap3[i] < waterheight) { | ||
heightlist3[[i]] = matrix(c(nrow(heightmap),nrow(heightmap),nrow(heightmap), heightmap3[i],waterheight,waterheight, i,i+1,i),3,3)[c(1,3,2),] | ||
heightlist3[[i+length(heightmap3)]] = matrix(c(nrow(heightmap),nrow(heightmap),nrow(heightmap), heightmap3[i],heightmap3[i+1],waterheight, i,i+1,i+1),3,3)[c(1,3,2),] | ||
} | ||
} | ||
heightmat3 = do.call(rbind,heightlist3) | ||
for(i in 1:(length(heightmap4)-1)) { | ||
if(heightmap4[i] < waterheight) { | ||
heightlist4[[i]] = matrix(c(i,i,i+1, heightmap4[i],waterheight,waterheight, ncol(heightmap),ncol(heightmap),ncol(heightmap)),3,3)[c(1,3,2),] | ||
heightlist4[[i+length(heightmap4)]] = matrix(c(i,i+1,i+1, heightmap4[i],waterheight,heightmap4[i+1], ncol(heightmap),ncol(heightmap),ncol(heightmap)),3,3)[c(1,3,2),] | ||
} | ||
} | ||
heightmat4 = do.call(rbind,heightlist4) | ||
fullsides = rbind(heightmat1,heightmat2,heightmat3,heightmat4) | ||
rgl::triangles3d(fullsides,lit=FALSE,color=watercolor,alpha=wateralpha,front="fill",back="culled") | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,76 @@ | ||
#'@title make_waterlines | ||
#' | ||
#'@description Makes the edge lines of | ||
#' | ||
#'@param heightmap A two-dimensional matrix, where each entry in the matrix is the elevation at that point. All points are assumed to be evenly spaced. | ||
#'@param waterdepth Default `0`. | ||
#'@param linecolor Default `grey40`. | ||
#'@param zscale Default `1`. The ratio between the x and y spacing (which are assumed to be equal) and the z axis. For example, if the elevation levels are in units | ||
#'of 1 meter and the grid values are separated by 10 meters, `zscale` would be 10. | ||
#'@param alpha Default `1`. Transparency of lines. | ||
#'@param lwd Default `2`. Water line width. | ||
#'@keywords internal | ||
make_waterlines = function(heightmap,waterdepth=0,linecolor="grey40",zscale=1,alpha=1,lwd=2) { | ||
heightmap = heightmap[,ncol(heightmap):1]/zscale | ||
heightval1 = heightmap[1,] | ||
heightval2 = heightmap[,1] | ||
heightval3 = heightmap[nrow(heightmap),] | ||
heightval4 = heightmap[,ncol(heightmap)] | ||
heightlist = list() | ||
counter = 1 | ||
drawing = FALSE | ||
startcoord = 1 | ||
for(i in 1:length(heightval1)) { | ||
if(heightval1[i] < waterdepth && !drawing) { | ||
startcoord = i | ||
drawing = TRUE | ||
} | ||
if((heightval1[i] > waterdepth || i == length(heightval1)) && drawing) { | ||
drawing = FALSE | ||
heightlist[[counter]] = matrix(c(1,1,waterdepth,waterdepth,startcoord,i),2,3) | ||
counter = counter + 1 | ||
} | ||
} | ||
drawing = FALSE | ||
startcoord = 1 | ||
for(i in 1:length(heightval2)) { | ||
if(heightval2[i] < waterdepth && !drawing) { | ||
startcoord = i | ||
drawing = TRUE | ||
} | ||
if((heightval2[i] > waterdepth || i == length(heightval2)) && drawing) { | ||
drawing = FALSE | ||
heightlist[[counter]] = matrix(c(startcoord,i,waterdepth,waterdepth,1,1),2,3) | ||
counter = counter + 1 | ||
} | ||
} | ||
drawing = FALSE | ||
startcoord = 1 | ||
for(i in 1:length(heightval3)) { | ||
if(heightval3[i] < waterdepth && !drawing) { | ||
startcoord = i | ||
drawing = TRUE | ||
} | ||
if((heightval3[i] > waterdepth || i == length(heightval3)) && drawing) { | ||
drawing = FALSE | ||
heightlist[[counter]] = matrix(c(nrow(heightmap),nrow(heightmap),waterdepth,waterdepth,startcoord,i),2,3) | ||
counter = counter + 1 | ||
} | ||
} | ||
drawing = FALSE | ||
startcoord = 1 | ||
for(i in 1:length(heightval4)) { | ||
if(heightval4[i] < waterdepth && !drawing) { | ||
startcoord = i | ||
drawing = TRUE | ||
} | ||
if((heightval4[i] > waterdepth || i == length(heightval4)) && drawing) { | ||
drawing = FALSE | ||
heightlist[[counter]] = matrix(c(startcoord,i,waterdepth,waterdepth,ncol(heightmap),ncol(heightmap)),2,3) | ||
counter = counter + 1 | ||
} | ||
} | ||
for(i in 1:length(heightlist)) { | ||
rgl::lines3d(heightlist[[i]],color=linecolor,lwd=lwd,alpha=alpha,depth_mask=FALSE) | ||
} | ||
} |
Oops, something went wrong.