Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Use conditional coloring on a plotly surface

Tags:

r

3d

plotly

I am using plotly via R for the first time and trying to create a surface from a grid and color it based on a calculation.

For example, I would like to use the surface from data(volcano), as in

library(plotly)
plot_ly(z = ~volcano) %>% add_surface()

enter image description here

But instead of color based on the z-value (altitude), let's just say I wanted to color based on distance from my house on the little mesa at (20,60) .

house_loc <- c(20,60,150) # (x,y,z) of my house
dist_to_house <- Vectorize(function(x,y,z){sqrt(sum( (c(x,y,z)-house_loc)^2 ))})

So far I have tried:

color_me <-function(x){
  colorRampPalette(c('tan','blue')
  )(24L)[findInterval(x,seq(0,1,length.out=25),
                      all.inside=TRUE)]
} 

library(dplyr)
library(reshape2)
volcano %>% 
     melt( varnames=c('y','x'),value.name='z' ) %>%
     mutate( d = dist_to_house(x, y, z) ,
             d_rel = d/max(d),
             d_color = color_me(d_rel) 
     ) -> df

plot_ly(df,
        type='scatter3d',
        mode='none', # no markers, just surface
        x=~x,
        y=~y,
        z=~z,
        surfaceaxis=2,
        surfacecolor=~d_color) # last argument seems not to work

Which just returns:

enter image description here

The desired result would color the landscape tan in the region of the house and gradually fade to blue in the regions far from the house.

Somewhat related question uses mesh3d code found elsewhere and doesn't explain how to calculate (i, j, k)

like image 240
C8H10N4O2 Avatar asked Oct 28 '25 10:10

C8H10N4O2


1 Answers

Your code virtually has everything you need, just use a surface plot and use your distance array as the color.

library(plotly)
library(dplyr)
library(reshape2)

house_loc <- c(20,60,150)
dist_to_house <- Vectorize(function(x,y,z){sqrt(sum( (c(x,y,z)-house_loc)^2 ))})

volcano %>% 
  melt( varnames=c('y','x'),value.name='z' ) %>%
  mutate( d = dist_to_house(x, y, z) ,
          d_rel = d/max(d)
  ) -> df

color <- df$d_rel
dim(color) <- dim(volcano)

plot_ly(df,
        type='surface',
        z=volcano,
        surfacecolor=color,
        colors=c('tan','blue'))

enter image description here

like image 67
Maximilian Peters Avatar answered Oct 30 '25 00:10

Maximilian Peters



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!