Open hongyuanjia opened 3 years ago
Hi there, great to hear that someone found the package and thanks a lot for the nice reproducible example. I'll take a look and patch a fix for this issue for you, hopefully later today.
Great! Actually, I am pretty excited about r3js. My package use rgl to provide 3D building geometry visualization. I am very interested in using r3js to achieve the same thing and add more interactive customized options, which is not so easy to do with rgl.
Sounds excellent! I hope it ends up being helpful, it's great to have some feedback on the things that still need fixing. I've pushed some changes that I hope fix this particular problem, let me know if not though. You might also want to check out the function shape3js()
which is designed to support more complex triangular meshes.
Thanks for the quick fix! Will try it out and update
@shwilks Appreicate the quick fix! I can successfully plot the geometry using triangle3js()
! Below is the test code:
vert <- data.frame(
id = rep(1:6, each = 6),
index = rep(1:6, 6),
x = c( 15, 15, 0, 0, 0, 15, 15, 15, 15, 15, 15, 15, 0, 0, 15, 15, 15, 0, 0,
0, 0, 0, 0, 0, 0, 15, 15, 15, 0, 0, 15, 15, 0, 0, 0, 15),
y = c(0, 0, 0, 0, 0, 0, 15, 15, 0, 0, 0, 15, 15, 15, 15, 15, 15, 15, 0, 0,
15, 15, 15, 0, 15, 15, 0, 0, 0, 15, 0, 15, 15, 15, 0, 0),
z = c(0, 5, 5, 5, 0, 0, 0, 5, 5, 5, 0, 0, 0, 5, 5, 5, 0, 0, 0, 5, 5, 5, 0, 0,
0, 0, 0, 0, 0, 0, 5, 5, 5, 5, 5, 5),
color_ext = c("#CCB266FF", "#CCB266FF", "#CCB266FF", "#CCB266FF",
"#CCB266FF", "#CCB266FF", "#CCB266FF", "#CCB266FF", "#CCB266FF",
"#CCB266FF", "#CCB266FF", "#CCB266FF", "#CCB266FF", "#CCB266FF",
"#CCB266FF", "#CCB266FF", "#CCB266FF", "#CCB266FF", "#CCB266FF",
"#CCB266FF", "#CCB266FF", "#CCB266FF", "#CCB266FF", "#CCB266FF",
"#808080FF", "#808080FF", "#808080FF", "#808080FF", "#808080FF",
"#808080FF", "#994C4CFF", "#994C4CFF", "#994C4CFF", "#994C4CFF",
"#994C4CFF", "#994C4CFF"),
color_int = c("#EBE2C5FF", "#EBE2C5FF", "#EBE2C5FF", "#EBE2C5FF",
"#EBE2C5FF", "#EBE2C5FF", "#EBE2C5FF", "#EBE2C5FF", "#EBE2C5FF",
"#EBE2C5FF", "#EBE2C5FF", "#EBE2C5FF", "#EBE2C5FF", "#EBE2C5FF",
"#EBE2C5FF", "#EBE2C5FF", "#EBE2C5FF", "#EBE2C5FF", "#EBE2C5FF",
"#EBE2C5FF", "#EBE2C5FF", "#EBE2C5FF", "#EBE2C5FF", "#EBE2C5FF",
"#BFBFBFFF", "#BFBFBFFF", "#BFBFBFFF", "#BFBFBFFF", "#BFBFBFFF",
"#BFBFBFFF", "#CA9595FF", "#CA9595FF", "#CA9595FF", "#CA9595FF",
"#CA9595FF", "#CA9595FF"),
alpha = c(1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1),
surface_type = c("Wall", "Wall", "Wall", "Wall", "Wall", "Wall", "Wall",
"Wall", "Wall", "Wall", "Wall", "Wall", "Wall", "Wall", "Wall", "Wall",
"Wall", "Wall", "Wall", "Wall", "Wall", "Wall", "Wall", "Wall", "Floor",
"Floor", "Floor", "Floor", "Floor", "Floor", "Roof", "Roof", "Roof",
"Roof", "Roof", "Roof")
)
# Initialise new plot
data3js <- plot3js.new()
# Set plot dimensions and aspect ratios
data3js <- plot3js.window(
data3js,
xlim = range(vert$x) * 1.1,
ylim = range(vert$y) * 1.1,
zlim = range(vert$z) * 1.1,
aspect = c(1,1,1)
)
# Add axes
data3js <- axis3js(data3js, side = "x")
data3js <- axis3js(data3js, side = "y")
data3js <- axis3js(data3js, side = "z")
# Add axes grids
data3js <- grid3js(data3js, col = "grey80")
data3js <- triangle3js(data3js,
vertices = as.matrix(vert[, c("x", "y", "z")]),
color = vert$color_ext,
shiness = 0
)
# Show the plot
r3js(data3js)
This is what I got using r3js:
What I want to achieve is:
You can see that even I pass the color for each surface, they are still all black. Besides that, below are my questions and I will really appreciate if you could give me some insights:
triangle3js()
and etc?doubleSide
being TRUE
, is it possible to set different colors for the inside and outside face separately?Sorry for the slow response, to address some of your questions:
data3js
object that the functions update has a component data3js$plot
that basically is a list of all the plot components, so modifying that list will remove the respective plot object. If you had an example use case we could think about a better way to implement that though.Thanks for your patience, it's great to have someone to work through this stuff with, sorry about the err somewhat developmental nature of the package! Here's the example code that goes some way towards what you're trying to achieve with the latest now updated version though
vert <- data.frame(
id = rep(1:6, each = 6),
index = rep(1:6, 6),
x = c( 15, 15, 0, 0, 0, 15, 15, 15, 15, 15, 15, 15, 0, 0, 15, 15, 15, 0, 0,
0, 0, 0, 0, 0, 0, 15, 15, 15, 0, 0, 15, 15, 0, 0, 0, 15),
y = c(0, 0, 0, 0, 0, 0, 15, 15, 0, 0, 0, 15, 15, 15, 15, 15, 15, 15, 0, 0,
15, 15, 15, 0, 15, 15, 0, 0, 0, 15, 0, 15, 15, 15, 0, 0),
z = c(0, 5, 5, 5, 0, 0, 0, 5, 5, 5, 0, 0, 0, 5, 5, 5, 0, 0, 0, 5, 5, 5, 0, 0,
0, 0, 0, 0, 0, 0, 5, 5, 5, 5, 5, 5),
color_ext = c("#CCB266FF", "#CCB266FF", "#CCB266FF", "#CCB266FF",
"#CCB266FF", "#CCB266FF", "#CCB266FF", "#CCB266FF", "#CCB266FF",
"#CCB266FF", "#CCB266FF", "#CCB266FF", "#CCB266FF", "#CCB266FF",
"#CCB266FF", "#CCB266FF", "#CCB266FF", "#CCB266FF", "#CCB266FF",
"#CCB266FF", "#CCB266FF", "#CCB266FF", "#CCB266FF", "#CCB266FF",
"#808080FF", "#808080FF", "#808080FF", "#808080FF", "#808080FF",
"#808080FF", "#994C4CFF", "#994C4CFF", "#994C4CFF", "#994C4CFF",
"#994C4CFF", "#994C4CFF"),
color_int = c("#EBE2C5FF", "#EBE2C5FF", "#EBE2C5FF", "#EBE2C5FF",
"#EBE2C5FF", "#EBE2C5FF", "#EBE2C5FF", "#EBE2C5FF", "#EBE2C5FF",
"#EBE2C5FF", "#EBE2C5FF", "#EBE2C5FF", "#EBE2C5FF", "#EBE2C5FF",
"#EBE2C5FF", "#EBE2C5FF", "#EBE2C5FF", "#EBE2C5FF", "#EBE2C5FF",
"#EBE2C5FF", "#EBE2C5FF", "#EBE2C5FF", "#EBE2C5FF", "#EBE2C5FF",
"#BFBFBFFF", "#BFBFBFFF", "#BFBFBFFF", "#BFBFBFFF", "#BFBFBFFF",
"#BFBFBFFF", "#CA9595FF", "#CA9595FF", "#CA9595FF", "#CA9595FF",
"#CA9595FF", "#CA9595FF"),
alpha = c(1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1),
surface_type = c("Wall", "Wall", "Wall", "Wall", "Wall", "Wall", "Wall",
"Wall", "Wall", "Wall", "Wall", "Wall", "Wall", "Wall", "Wall", "Wall",
"Wall", "Wall", "Wall", "Wall", "Wall", "Wall", "Wall", "Wall", "Floor",
"Floor", "Floor", "Floor", "Floor", "Floor", "Roof", "Roof", "Roof",
"Roof", "Roof", "Roof")
)
# Initialise new plot
data3js <- plot3js.new()
# Set plot dimensions and aspect ratios
data3js <- plot3js.window(
data3js,
xlim = range(vert$x) * 1.1,
ylim = range(vert$y) * 1.1,
zlim = range(vert$z) * 1.1,
aspect = c(1,1,1)
)
# Add axes
data3js <- axis3js(data3js, side = "x")
data3js <- axis3js(data3js, side = "y")
data3js <- axis3js(data3js, side = "z")
# Add axes grids
data3js <- grid3js(data3js, col = "grey80")
vertices <- as.matrix(vert[, c("x", "y", "z")])
# data3js <- shape3js(
# data3js,
# vertices = vertices,
# faces = matrix(seq_len(nrow(vert)*3), ncol = 3, byrow = TRUE),
# col = vert$color_ext
# )
data3js <- triangle3js(data3js,
vertices = vertices,
col = vert$color_ext)
# Add outlines to shape
lims <- apply(vertices, 2, range)
data3js <- lines3js(
data3js,
x = lims[c(1,2),1],
y = lims[c(2,2),2],
z = lims[c(2,2),3],
col = "black",
lwd = 2
)
data3js <- lines3js(
data3js,
x = lims[c(2,2),1],
y = lims[c(1,2),2],
z = lims[c(2,2),3],
col = "black",
lwd = 2
)
data3js <- lines3js(
data3js,
x = lims[c(2,2),1],
y = lims[c(2,2),2],
z = lims[c(1,2),3],
col = "black",
lwd = 2
)
# Add axis lines
data3js <- lines3js(
data3js,
x = c(0, 35),
y = c(0, 0),
z = c(0, 0),
col = "green",
lwd = 2
)
data3js <- lines3js(
data3js,
x = c(0, 0),
y = c(0, 35),
z = c(0, 0),
col = "blue",
lwd = 2
)
data3js <- lines3js(
data3js,
x = c(0, 0),
y = c(0, 0),
z = c(0, 15),
col = "red",
lwd = 2
)
data3js <- light3js(
data3js,
position = NULL
)
# Show the plot
r3js(data3js)
- You were specifying vertex colors correctly, it was just not implemented correctly, I've made some updates that make the example code for me (below) work now.
Great! Now I confirm that I can successfully plot the color of the surfaces. Thanks for the fix!
- Do you mean once you've added them how to then later remove them in your code? If so, good question, the data3js object that the functions update has a component data3js$plot that basically is a list of all the plot components, so modifying that list will remove the respective plot object. If you had an example use case we could think about a better way to implement that though.
Yes. I just found that when I exploring the functionalities of r3js, I have to reconstruct the data3js object from the very beginning (i.e., calling plot3js.new()
again) everytime when I want to use another geometry functions or vertices. Good to know that I can directly remove plot components by modifying the data3js$plot
. It would be handy to have some helper functions to do that, though.
In rgl, functions like rgl::rgl.triangles()
will return an integer unique identifier for the triangles. So I plot walls, roofs, floors separately, and use rgl::rgl.pop()
to remove them if I want. This works fine. But once they got removed, I have to plot them again if I want to show them again.
I see the lastID()
function which can also be used to track the last plotted components. But I did not find an equivalent for rgl::rgl.pop()
in r3js. However, I know Three.js should have much more customized options to let me dynamically toggle plotted components, programmatically. So there should be a more efficient way to do that in a Three.js way, right?
- This is a bit of an undocumented feature, if, as in the example below you specify your own light source with position = NULL, it replaces the default directional light with an ambient one. In future I'll better document this and add more options to control your type of light source.
Thanks for the trick. Setting position
to NULL
works perfectly for me.
- Hmm, I think no but you could probably achieve something equivalent by plotting the same shape with different colors and but different single sides visible, I'll have a think about that and an example.
That is the way I previously did using rgl package. I will try if it works in r3js.
This package looks quite promising to me. I will test it for more complex vertices to see the performance. Thanks again for all the efforts!
Thanks for this package!
I am exploring some functions of this package to see if I can reproduce the 3D geometry functionality implemented using rgl. Unfortunately, I could not get
triangle3js()
work:Only the axis showed up and no triangles were rendered.