Skip to content

Commit

Permalink
rayshader v0.37.0: render_buildings(), render_beveled_polygons(),…
Browse files Browse the repository at this point in the history
… bugfixes and improvements!

-Add support for beveled polygons and 3D buildings via the `raybevel` package
-Add support for
-Greatly speed up `render_contours()` and `render_path()`
-`render_camera()` Fix orientation when phi = 90
-`render_obj()` Add `lit` option and custom lighting arguments
-Center coordinate system at exactly 0/0
-`plot_3d()` Ensure everything is built from rgl triangle primitives
-`render_polygons()` add relative light angle option
-`add_overlay()` return original image if other is NULL
-`plot_3d()` Use LUV instead of LAB for darkened shadows
-`constant_shade()` Fix transpose
-Add shininess support to raymesh export
-Add `resolution_multiply` option to ease increasing the resolution of scalebar/line/polygon/point/label/compass overlays
-`generate_polygon_overlay()` ensure numeric extent is handled correctly
-`plot_3d()` Replace potential NA values (from NaNs) in normals
-`plot_gg()` Fix examples
-`render_snapshot()` Fix keep_user_par issue
-`render_tree()` Add lit option
-`plot_3d()` Fix baselines and waterlines
  • Loading branch information
tylermorganwall committed Jan 11, 2024
1 parent 81f95cf commit e69be2f
Show file tree
Hide file tree
Showing 67 changed files with 2,208 additions and 276 deletions.
7 changes: 5 additions & 2 deletions DESCRIPTION
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
Package: rayshader
Type: Package
Title: Create Maps and Visualize Data in 2D and 3D
Version: 0.36.1
Version: 0.37.0
Date: 2023-08-01
Author: Tyler Morgan-Wall
Maintainer: Tyler Morgan-Wall <tylermw@gmail.com>
Expand Down Expand Up @@ -43,7 +43,9 @@ Suggests:
lidR,
elevatr,
gridExtra,
testthat (>= 3.0.0)
testthat (>= 3.0.0),
osmdata,
raybevel
LinkingTo: Rcpp, progress, RcppArmadillo
RoxygenNote: 7.2.3
URL: https://www.rayshader.com,
Expand All @@ -52,5 +54,6 @@ BugReports: https://github.com/tylermorganwall/rayshader/issues
Remotes: tylermorganwall/rayimage,
tylermorganwall/rayrender,
tylermorganwall/rayvertex,
tylermorganwall/raybevel
dmurdoch/rgl
Config/testthat/edition: 3
3 changes: 3 additions & 0 deletions NAMESPACE
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,8 @@ export(plot_map)
export(raster_to_matrix)
export(ray_shade)
export(reduce_matrix_size)
export(render_beveled_polygons)
export(render_buildings)
export(render_camera)
export(render_clouds)
export(render_compass)
Expand All @@ -46,6 +48,7 @@ export(render_obj)
export(render_path)
export(render_points)
export(render_polygons)
export(render_raymesh)
export(render_resize_window)
export(render_scalebar)
export(render_snapshot)
Expand Down
8 changes: 7 additions & 1 deletion R/add_overlay.R
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@
#' add_shadow(ray_shade(montereybay,zscale=50)) %>%
#' plot_map()
#'}
add_overlay = function(hillshade, overlay, alphalayer = 1, alphacolor=NULL,
add_overlay = function(hillshade = NULL, overlay = NULL, alphalayer = 1, alphacolor=NULL,
alphamethod = "max", rescale_original = FALSE) {
if(any(alphalayer > 1 || alphalayer < 0)) {
stop("Argument `alphalayer` must not be less than 0 or more than 1")
Expand Down Expand Up @@ -76,6 +76,12 @@ add_overlay = function(hillshade, overlay, alphalayer = 1, alphacolor=NULL,
temp_over[alphalayer1] = 0
overlay[,,4] = temp_over
}
if(is.null(hillshade)) {
return(overlay)
}
if(is.null(overlay)) {
return(hillshade)
}
if(length(dim(hillshade)) == 2) {
rayimage::add_image_overlay(fliplr(t(hillshade)),overlay,alpha=alphalayer, rescale_original = rescale_original)
} else {
Expand Down
10 changes: 5 additions & 5 deletions R/colorspace_functions.R
Original file line number Diff line number Diff line change
Expand Up @@ -7,14 +7,14 @@
#'@keywords internal
#'@examples
#'#None
darken_color = function(col, darken = 0.5) {
darken_color = function(col, darken = 0.3) {
as.numeric(
grDevices::convertColor(
as.numeric(
grDevices::convertColor(
convert_color(col),
from = "sRGB", to = "Lab")
) * c(darken,1,1),
from = "Lab", to = "sRGB")
)
from = "sRGB", to = "Luv")
) * c(darken,1,1),
from = "Luv", to = "sRGB")
)
}
2 changes: 1 addition & 1 deletion R/constant_shade.R
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@
#' plot_map()
#'}
constant_shade = function(heightmap, color = "white", alpha = 1) {
return_array = array(alpha, dim = c(nrow(heightmap),ncol(heightmap),4))
return_array = array(alpha, dim = c(ncol(heightmap),nrow(heightmap),4))
const_col = convert_color(color)
return_array[,,1] = const_col[1]
return_array[,,2] = const_col[2]
Expand Down
66 changes: 27 additions & 39 deletions R/convert_rgl_to_raymesh.R
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ convert_rgl_to_raymesh = function(save_shadow = TRUE) {

vertex_info = get_ids_with_labels()
basic_load_mesh = function(row, texture_loc,
color = "white", alpha=1, obj = FALSE, specular = "white",
color = "white", alpha=1, obj = FALSE, specular = "white",shininess = 50,
lit = FALSE, quads = FALSE) {
id = as.character(vertex_info$id[row])

Expand Down Expand Up @@ -69,6 +69,19 @@ convert_rgl_to_raymesh = function(save_shadow = TRUE) {
tex_indices = NULL
}
}
#Get type
if(is.na(lit)) {
lit = FALSE
}
if(lit) {
if(shininess < 10) {
type_val = "diffuse"
} else {
type_val = "phong"
}
} else {
type_val = "color"
}

texture_loc = ifelse(!is.na(texture_loc), texture_loc, "")
return(rayvertex::construct_mesh(indices = indices,
Expand All @@ -79,13 +92,14 @@ convert_rgl_to_raymesh = function(save_shadow = TRUE) {
norm_indices = norm_indices,
material = rayvertex::material_list(texture_location = texture_loc,
diffuse = color,
type = ifelse(lit, "diffuse", "color"),
type = type_val,
shininess = shininess,
dissolve = alpha,
specular = specular)))
}
for(row in 1:nrow(vertex_info)) {
if(!is.na(vertex_info$lit[row])) {
lit_val = vertex_info$lit[row]
lit_val = unlist(vertex_info$lit[row])
} else {
lit_val = FALSE
}
Expand Down Expand Up @@ -126,45 +140,16 @@ convert_rgl_to_raymesh = function(save_shadow = TRUE) {
material = rayvertex::material_list(texture_location = texture_loc,
type = "color"))
} else if(vertex_info$tag[row] == "surface_tris") {
final_scene[[num_elems]] = basic_load_mesh(row, texture_loc = vertex_info$texture_file[[row]])
final_scene[[num_elems]] = basic_load_mesh(row,
texture_loc = vertex_info$texture_file[[row]])
} else if (vertex_info$tag[row] == "basebottom") {
indices = matrix(rgl::rgl.attrib(vertex_info$id[row], "indices"),
ncol = 3L, byrow = TRUE) - 1
vertices = rgl.attrib(vertex_info$id[row], "vertices")
textures = rgl.attrib(vertex_info$id[row], "texcoords")
dims = rgl::rgl.attrib(vertex_info$id[row], "dim")
vertices_y = vertices[,2]
nx = dims[1]
nz = dims[2]
indices = rep(0, 6 * (nz - 1) * (nx - 1))
counter = 0
na_counter = 0

for(i in seq_len(nz)[-nz]) {
for(j in seq_len(nx)[-nx]) {
if(!is.na(vertices_y[(i-1)*nx + j]) && !is.na(vertices_y[(i+1-1)*nx + j]) &&
!is.na(vertices_y[(i-1)*nx + j+1]) && !is.na(vertices_y[(i+1-1)*nx + j+1])) {
cindices = (i-1)*nx + c(j, j + nx, j + 1, j + nx, j + nx + 1, j + 1)
indices[(1:6 + 6*counter)] = cindices
counter = counter + 1
} else {
na_counter = na_counter + 2
}
}
}
indices = indices - 1
vertices_y[is.na(vertices_y)] = mean(vertices_y)

indices = matrix(indices, ncol=3, byrow=TRUE)
indices = indices[1:(nrow(indices)-na_counter),]
texture_loc = vertex_info$texture_file[[row]]
texture_loc = ifelse(!is.na(texture_loc), texture_loc, "")
final_scene[[num_elems]] = rayvertex::construct_mesh(indices = indices,
vertices = vertices,
texcoords = textures,
tex_indices = indices,
material = rayvertex::material_list(texture_location = texture_loc,
type = "color"))
final_scene[[num_elems]] = basic_load_mesh(row,
texture_loc = texture_loc,
lit = lit_val,
color = vertex_info$base_color[[row]])
} else if (vertex_info$tag[row] == "base") {
final_scene[[num_elems]] = basic_load_mesh(row,
lit = lit_val,
Expand Down Expand Up @@ -225,6 +210,7 @@ convert_rgl_to_raymesh = function(save_shadow = TRUE) {
} else if (vertex_info$tag[row] == "polygon3d") {
final_scene[[num_elems]] = basic_load_mesh(row, texture_loc = NA,
lit = lit_val,
shininess = vertex_info$shininess[[row]],
color = vertex_info$tricolor[[row]])
} else if(vertex_info$tag[row] == "shadow" && save_shadow) {
final_scene[[num_elems]] = basic_load_mesh(row,
Expand All @@ -245,12 +231,14 @@ convert_rgl_to_raymesh = function(save_shadow = TRUE) {
obj_ambient = vertex_info$obj_ambient[[row]]
obj_specular = vertex_info$obj_specular[[row]]
obj_emission = vertex_info$obj_emission[[row]]
shininess = vertex_info$shininess[[row]]
tmp_obj = rayvertex::change_material(tmp_obj,
diffuse = ifelse(is.na(obj_color), NULL, obj_color) ,
dissolve = ifelse(is.na(obj_alpha), NULL, obj_alpha),
ambient = ifelse(is.na(obj_ambient), NULL, obj_ambient),
specular = ifelse(is.na(obj_specular),NULL, obj_specular),
emission = ifelse(is.na(obj_emission),NULL, obj_emission))
emission = ifelse(is.na(obj_emission),NULL, obj_emission),
shininess = ifelse(is.na(shininess), 50, shininess))
final_scene[[num_elems]] = tmp_obj

}
Expand Down
11 changes: 9 additions & 2 deletions R/generate_compass_overlay.R
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,10 @@
#'RGB image array automatically.
#'@param width Default `NA`. Width of the resulting image array. Default the same dimensions as height map.
#'@param height Default `NA`. Width of the resulting image array. Default the same dimensions as height map.
#'@param resolution_multiply Default `1`. If passing in `heightmap` instead of width/height, amount to
#'increase the resolution of the overlay, which should make lines/polygons finer.
#'Should be combined with `add_overlay(rescale_original = TRUE)` to ensure those added details are captured
#'in the final map.
#'@param halo_color Default `NA`, no halo. If a color is specified, the compass will be surrounded by a halo
#'of this color.
#'@param halo_expand Default `1`. Number of pixels to expand the halo.
Expand Down Expand Up @@ -129,7 +133,7 @@
#'}
generate_compass_overlay = function(x=0.85, y=0.15,
size=0.075, text_size=1, bearing=0,
heightmap = NULL, width=NA, height=NA,
heightmap = NULL, width=NA, height=NA, resolution_multiply = 1,
color1 = "white", color2 = "black", text_color = "black",
border_color = "black", border_width = 1,
halo_color = NA, halo_expand = 1,
Expand All @@ -138,11 +142,14 @@ generate_compass_overlay = function(x=0.85, y=0.15,
loc[1] = x
loc[2] = y
if(is.na(height)) {
height = ncol(heightmap)
height = ncol(heightmap)
}
if(is.na(width)) {
width = nrow(heightmap)
}
height = height * resolution_multiply
width = width * resolution_multiply

# default colors are white and black
cols <- rep(c(color1,color2),8)
bearing = bearing*pi/180
Expand Down
17 changes: 12 additions & 5 deletions R/generate_contour_overlay.R
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,10 @@
#'this will automatically generate `nlevels` breaks between `levels[1]` and `levels[2]`.
#'@param width Default `NA`. Width of the resulting overlay. Default the same dimensions as heightmap.
#'@param height Default `NA`. Width of the resulting overlay. Default the same dimensions as heightmap.
#'@param resolution_multiply Default `1`. If passing in `heightmap` instead of width/height, amount to
#'increase the resolution of the overlay, which should make lines/polygons finer.
#'Should be combined with `add_overlay(rescale_original = TRUE)` to ensure those added details are captured
#'in the final map.
#'@param color Default `black`. Color.
#'@param linewidth Default `1`. Line width.
#'@return Semi-transparent overlay with contours.
Expand Down Expand Up @@ -73,7 +77,7 @@
#' plot_map()
#'}
generate_contour_overlay = function(heightmap, levels=NA, nlevels=NA,
zscale = 1, width=NA, height=NA,
zscale = 1, width=NA, height=NA, resolution_multiply = 1,
color = "black", linewidth = 1) {
if(!(length(find.package("sf", quiet = TRUE)) > 0)) {
stop("`sf` package required for generate_contour_overlay()")
Expand All @@ -100,12 +104,15 @@ generate_contour_overlay = function(heightmap, levels=NA, nlevels=NA,
levels=levels)
contours = isoband::iso_to_sfg(isolineval)
sf_contours = sf::st_sf(level = names(contours), geometry = sf::st_sfc(contours))
if(is.na(width)) {
width = ncol(heightmap)
}
if(is.na(height)) {
height = nrow(heightmap)
height = ncol(heightmap)
}
if(is.na(width)) {
width = nrow(heightmap)
}
height = height * resolution_multiply
width = width * resolution_multiply

tempoverlay = tempfile(fileext = ".png")
grDevices::png(filename = tempoverlay, width = width, height = height, units="px",bg = "transparent")
graphics::par(mar = c(0,0,0,0))
Expand Down
12 changes: 10 additions & 2 deletions R/generate_label_overlay.R
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,10 @@
#'overlay automatically.
#'@param width Default `NA`. Width of the resulting overlay. Default the same dimensions as height map.
#'@param height Default `NA`. Width of the resulting overlay. Default the same dimensions as height map.
#'@param resolution_multiply Default `1`. If passing in `heightmap` instead of width/height, amount to
#'increase the resolution of the overlay, which should make lines/polygons/text finer.
#'Should be combined with `add_overlay(rescale_original = TRUE)` to ensure those added details are captured
#'in the final map.
#'@param text_size Default `1`. Text size.
#'@param point_size Default `0`, no points. Point size.
#'@param color Default `black`. Color of the labels.
Expand Down Expand Up @@ -125,7 +129,8 @@
#' plot_map()
#'}
generate_label_overlay = function(labels, extent, x=NULL, y=NULL,
heightmap = NULL, width=NA, height=NA, text_size = 1,
heightmap = NULL, width=NA, height=NA, resolution_multiply = 1,
text_size = 1,
color = "black", font = 1, pch = 16,
point_size = 1, point_color = NA, offset = c(0,0),
data_label_column = NULL,
Expand Down Expand Up @@ -172,11 +177,14 @@ generate_label_overlay = function(labels, extent, x=NULL, y=NULL,

extent = get_extent(extent)
if(is.na(height)) {
height = ncol(heightmap)
height = ncol(heightmap)
}
if(is.na(width)) {
width = nrow(heightmap)
}
height = height * resolution_multiply
width = width * resolution_multiply

tempoverlay = tempfile(fileext = ".png")
grDevices::png(filename = tempoverlay, width = width, height = height, units="px",bg = "transparent")
graphics::par(mar = c(0,0,0,0))
Expand Down
14 changes: 11 additions & 3 deletions R/generate_line_overlay.R
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,10 @@
#'overlay automatically.
#'@param width Default `NA`. Width of the resulting overlay. Default the same dimensions as height map.
#'@param height Default `NA`. Width of the resulting overlay. Default the same dimensions as height map.
#'@param resolution_multiply Default `1`. If passing in `heightmap` instead of width/height, amount to
#'increase the resolution of the overlay, which should make lines/polygons/text finer.
#'Should be combined with `add_overlay(rescale_original = TRUE)` to ensure those added details are captured
#'in the final map.
#'@param color Default `black`. Color of the lines.
#'@param linewidth Default `1`. Line width.
#'@param lty Default `1`. Line type. `1` is solid, `2` is dashed, `3` is dotted,`4` is dot-dash,
Expand Down Expand Up @@ -56,7 +60,7 @@
#' plot_map()
#'}
generate_line_overlay = function(geometry, extent, heightmap = NULL,
width=NA, height=NA,
width=NA, height=NA, resolution_multiply = 1,
color = "black", linewidth = 1, lty = 1,
data_column_width = NULL, offset = c(0,0)) {
if(!(length(find.package("sf", quiet = TRUE)) > 0)) {
Expand All @@ -74,14 +78,18 @@ generate_line_overlay = function(geometry, extent, heightmap = NULL,
if(inherits(geometry,"sfg")) {
geometry = sf::st_sfc(geometry)
}
sf_lines_cropped = base::suppressMessages(base::suppressWarnings(sf::st_crop(geometry, extent)))
# sf_lines_cropped = base::suppressMessages(base::suppressWarnings(sf::st_crop(geometry, extent)))

sf_lines_cropped = geometry
if(is.na(height)) {
height = ncol(heightmap)
height = ncol(heightmap)
}
if(is.na(width)) {
width = nrow(heightmap)
}
height = height * resolution_multiply
width = width * resolution_multiply

if(!is.null(data_column_width)) {
if(data_column_width %in% colnames(sf_lines_cropped)) {
widthvals = sf_lines_cropped[[data_column_width]] / max(sf_lines_cropped[[data_column_width]],na.rm = TRUE) * linewidth
Expand Down
Loading

0 comments on commit e69be2f

Please sign in to comment.